@jay-framework/wix-stores-v1 0.15.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.
@@ -0,0 +1,218 @@
1
+ import {HTMLElementCollectionProxy, HTMLElementProxy, JayContract} from "@jay-framework/runtime";
2
+ import {MediaGalleryViewState, MediaGalleryRefs, MediaGalleryRepeatedRefs} from "./media-gallery.jay-contract";
3
+
4
+ export enum ProductType {
5
+ PHYSICAL,
6
+ DIGITAL
7
+ }
8
+
9
+ export enum StockStatus {
10
+ OUT_OF_STOCK,
11
+ IN_STOCK
12
+ }
13
+
14
+ export interface QuantityOfProductPageViewState {
15
+ quantity: number
16
+ }
17
+
18
+ export enum OptionRenderType {
19
+ TEXT_CHOICES,
20
+ COLOR_SWATCH_CHOICES
21
+ }
22
+
23
+ export enum ChoiceType {
24
+ CHOICE_TEXT,
25
+ ONE_COLOR
26
+ }
27
+
28
+ export interface ChoiceOfOptionOfProductPageViewState {
29
+ choiceId: string,
30
+ choiceType: ChoiceType,
31
+ name: string,
32
+ colorCode: string,
33
+ inStock: boolean,
34
+ isSelected: boolean
35
+ }
36
+
37
+ export interface OptionOfProductPageViewState {
38
+ _id: string,
39
+ name: string,
40
+ optionRenderType: OptionRenderType,
41
+ textChoiceSelection: string,
42
+ choices: Array<ChoiceOfOptionOfProductPageViewState>
43
+ }
44
+
45
+ export interface InfoSectionOfProductPageViewState {
46
+ _id: string,
47
+ title: string,
48
+ plainDescription: string
49
+ }
50
+
51
+ export enum ModifierType {
52
+ TEXT_CHOICES,
53
+ COLOR_SWATCH_CHOICES,
54
+ FREE_TEXT
55
+ }
56
+
57
+ export enum ChoiceType {
58
+ CHOICE_TEXT,
59
+ ONE_COLOR
60
+ }
61
+
62
+ export interface ChoiceOfModifierOfProductPageViewState {
63
+ choiceId: string,
64
+ choiceType: ChoiceType,
65
+ name: string,
66
+ colorCode: string,
67
+ isSelected: boolean
68
+ }
69
+
70
+ export interface ModifierOfProductPageViewState {
71
+ _id: string,
72
+ name: string,
73
+ modifierType: ModifierType,
74
+ textModifierSelection: string,
75
+ textInputLength: number,
76
+ textInputRequired: boolean,
77
+ choices: Array<ChoiceOfModifierOfProductPageViewState>
78
+ }
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
+ export interface ProductPageViewState {
115
+ _id: string,
116
+ productName: string,
117
+ mediaGallery: MediaGalleryViewState,
118
+ description: string,
119
+ brand: string,
120
+ ribbon: string,
121
+ productType: ProductType,
122
+ sku: string,
123
+ price: string,
124
+ strikethroughPrice: string,
125
+ pricePerUnit: string,
126
+ stockStatus: StockStatus,
127
+ quantity: QuantityOfProductPageViewState,
128
+ actionsEnabled: boolean,
129
+ options: Array<OptionOfProductPageViewState>,
130
+ infoSections: Array<InfoSectionOfProductPageViewState>,
131
+ modifiers: Array<ModifierOfProductPageViewState>,
132
+ seoData: SeoDatumOfProductPageViewState
133
+ }
134
+
135
+ export type ProductPageSlowViewState = Pick<ProductPageViewState, '_id' | 'productName' | 'description' | 'brand' | 'ribbon' | 'productType'> & {
136
+ options: Array<Pick<ProductPageViewState['options'][number], '_id' | 'name' | 'optionRenderType'> & {
137
+ choices: Array<Pick<ProductPageViewState['options'][number]['choices'][number], 'choiceId' | 'choiceType' | 'name' | 'colorCode' | 'inStock'>>;
138
+ }>;
139
+ infoSections: Array<ProductPageViewState['infoSections'][number]>;
140
+ modifiers: Array<Pick<ProductPageViewState['modifiers'][number], '_id' | 'name' | 'modifierType' | 'textInputLength' | 'textInputRequired'> & {
141
+ choices: Array<Pick<ProductPageViewState['modifiers'][number]['choices'][number], 'choiceId' | 'choiceType' | 'name' | 'colorCode'>>;
142
+ }>;
143
+ seoData: ProductPageViewState['seoData'];
144
+ };
145
+
146
+ export type ProductPageFastViewState = Pick<ProductPageViewState, 'sku' | 'price' | 'strikethroughPrice' | 'pricePerUnit' | 'stockStatus' | 'actionsEnabled'> & {
147
+ mediaGallery: ProductPageViewState['mediaGallery'];
148
+ quantity: ProductPageViewState['quantity'];
149
+ options: Array<Pick<ProductPageViewState['options'][number], '_id' | 'textChoiceSelection'> & {
150
+ choices: Array<Pick<ProductPageViewState['options'][number]['choices'][number], 'choiceId' | 'isSelected'>>;
151
+ }>;
152
+ modifiers: Array<Pick<ProductPageViewState['modifiers'][number], '_id' | 'textModifierSelection'> & {
153
+ choices: Array<Pick<ProductPageViewState['modifiers'][number]['choices'][number], 'choiceId' | 'isSelected'>>;
154
+ }>;
155
+ };
156
+
157
+ export type ProductPageInteractiveViewState = Pick<ProductPageViewState, 'sku' | 'price' | 'strikethroughPrice' | 'pricePerUnit' | 'stockStatus' | 'actionsEnabled'> & {
158
+ mediaGallery: ProductPageViewState['mediaGallery'];
159
+ quantity: ProductPageViewState['quantity'];
160
+ options: Array<Pick<ProductPageViewState['options'][number], '_id' | 'textChoiceSelection'> & {
161
+ choices: Array<Pick<ProductPageViewState['options'][number]['choices'][number], 'choiceId' | 'isSelected'>>;
162
+ }>;
163
+ modifiers: Array<Pick<ProductPageViewState['modifiers'][number], '_id' | 'textModifierSelection'> & {
164
+ choices: Array<Pick<ProductPageViewState['modifiers'][number]['choices'][number], 'choiceId' | 'isSelected'>>;
165
+ }>;
166
+ };
167
+
168
+
169
+ export interface ProductPageRefs {
170
+ addToCartButton: HTMLElementProxy<ProductPageViewState, HTMLButtonElement>,
171
+ buyNowButton: HTMLElementProxy<ProductPageViewState, HTMLButtonElement>,
172
+ mediaGallery: MediaGalleryRefs,
173
+ quantity: {
174
+ decrementButton: HTMLElementProxy<QuantityOfProductPageViewState, HTMLButtonElement>,
175
+ incrementButton: HTMLElementProxy<QuantityOfProductPageViewState, HTMLButtonElement>,
176
+ quantity: HTMLElementProxy<QuantityOfProductPageViewState, HTMLInputElement>
177
+ },
178
+ options: {
179
+ textChoice: HTMLElementCollectionProxy<OptionOfProductPageViewState, HTMLSelectElement>,
180
+ choices: {
181
+ choiceButton: HTMLElementCollectionProxy<ChoiceOfOptionOfProductPageViewState, HTMLButtonElement>
182
+ }
183
+ },
184
+ modifiers: {
185
+ textModifier: HTMLElementCollectionProxy<ModifierOfProductPageViewState, HTMLSelectElement>,
186
+ textInput: HTMLElementCollectionProxy<ModifierOfProductPageViewState, HTMLInputElement | HTMLAreaElement>,
187
+ choices: {
188
+ choiceButton: HTMLElementCollectionProxy<ChoiceOfModifierOfProductPageViewState, HTMLButtonElement>
189
+ }
190
+ }
191
+ }
192
+
193
+
194
+ export interface ProductPageRepeatedRefs {
195
+ addToCartButton: HTMLElementCollectionProxy<ProductPageViewState, HTMLButtonElement>,
196
+ buyNowButton: HTMLElementCollectionProxy<ProductPageViewState, HTMLButtonElement>,
197
+ mediaGallery: MediaGalleryRepeatedRefs,
198
+ quantity: {
199
+ decrementButton: HTMLElementCollectionProxy<QuantityOfProductPageViewState, HTMLButtonElement>,
200
+ incrementButton: HTMLElementCollectionProxy<QuantityOfProductPageViewState, HTMLButtonElement>,
201
+ quantity: HTMLElementCollectionProxy<QuantityOfProductPageViewState, HTMLInputElement>
202
+ },
203
+ options: {
204
+ textChoice: HTMLElementCollectionProxy<OptionOfProductPageViewState, HTMLSelectElement>,
205
+ choices: {
206
+ choiceButton: HTMLElementCollectionProxy<ChoiceOfOptionOfProductPageViewState, HTMLButtonElement>
207
+ }
208
+ },
209
+ modifiers: {
210
+ textModifier: HTMLElementCollectionProxy<ModifierOfProductPageViewState, HTMLSelectElement>,
211
+ textInput: HTMLElementCollectionProxy<ModifierOfProductPageViewState, HTMLInputElement | HTMLAreaElement>,
212
+ choices: {
213
+ choiceButton: HTMLElementCollectionProxy<ChoiceOfModifierOfProductPageViewState, HTMLButtonElement>
214
+ }
215
+ }
216
+ }
217
+
218
+ export type ProductPageContract = JayContract<ProductPageViewState, ProductPageRefs, ProductPageSlowViewState, ProductPageFastViewState, ProductPageInteractiveViewState>
@@ -0,0 +1,240 @@
1
+ name: product-search
2
+ tags:
3
+ # Search input (matches Wix searchProducts search.search parameter)
4
+ - tag: searchExpression
5
+ type: [data, interactive]
6
+ dataType: string
7
+ elementType: HTMLInputElement
8
+ description: Search term or expression
9
+
10
+ - tag: searchFields
11
+ type: data
12
+ dataType: string
13
+ description: Comma-separated list of fields to search in (name, description, sku, etc.)
14
+
15
+ - tag: fuzzySearch
16
+ type: data
17
+ dataType: boolean
18
+ description: Whether to enable fuzzy search for typos and declensions
19
+
20
+ - tag: searchButton
21
+ type: interactive
22
+ elementType: HTMLButtonElement
23
+ description: Search submit button
24
+
25
+ - tag: clearSearchButton
26
+ type: interactive
27
+ elementType: HTMLButtonElement
28
+ description: Clear search input button
29
+
30
+ # Search state (fast+interactive for dynamic updates)
31
+ - tag: isSearching
32
+ type: variant
33
+ dataType: boolean
34
+ phase: fast+interactive
35
+ description: Whether search is in progress
36
+
37
+ - tag: hasSearched
38
+ type: variant
39
+ dataType: boolean
40
+ phase: fast+interactive
41
+ description: Whether a search has been performed
42
+
43
+ # Search results (fast+interactive for dynamic loading)
44
+ - tag: searchResults
45
+ type: sub-contract
46
+ repeated: true
47
+ trackBy: _id
48
+ phase: fast+interactive
49
+ description: Product search results (loaded dynamically)
50
+ link: ./product-card
51
+
52
+ - tag: resultCount
53
+ type: data
54
+ dataType: number
55
+ phase: fast+interactive
56
+ description: Total number of search results
57
+
58
+ - tag: hasResults
59
+ type: variant
60
+ dataType: boolean
61
+ phase: fast+interactive
62
+ description: Whether search returned any results
63
+
64
+ # Empty state message
65
+ - tag: emptyStateMessage
66
+ type: data
67
+ dataType: string
68
+ description: Message to show when no results found
69
+
70
+ # Search filters
71
+ - tag: filters
72
+ type: sub-contract
73
+ description: Search result filters
74
+ tags:
75
+ # Price range filter (fast+interactive)
76
+ - tag: priceRange
77
+ type: sub-contract
78
+ phase: fast+interactive
79
+ description: Price range filter
80
+ tags:
81
+ - tag: minPrice
82
+ type: [data, interactive]
83
+ dataType: number
84
+ elementType: HTMLInputElement
85
+ description: Current minimum price filter (works with number input or range slider)
86
+
87
+ - tag: maxPrice
88
+ type: [data, interactive]
89
+ dataType: number
90
+ elementType: HTMLInputElement
91
+ description: Current maximum price filter (works with number input or range slider)
92
+
93
+ - tag: minBound
94
+ type: data
95
+ dataType: number
96
+ description: Absolute minimum price from product catalog (for slider min attribute)
97
+
98
+ - tag: maxBound
99
+ type: data
100
+ dataType: number
101
+ description: Absolute maximum price from product catalog (for slider max attribute)
102
+
103
+ - tag: ranges
104
+ type: sub-contract
105
+ repeated: true
106
+ trackBy: rangeId
107
+ description: Predefined price range options (computed from min/max bounds)
108
+ tags:
109
+ - tag: rangeId
110
+ type: data
111
+ dataType: string
112
+ description: Unique range identifier
113
+
114
+ - tag: label
115
+ type: data
116
+ dataType: string
117
+ description: Display label (e.g., "$0 - $100")
118
+
119
+ - tag: minValue
120
+ type: data
121
+ dataType: number
122
+ description: Range minimum (null for "Show all")
123
+
124
+ - tag: maxValue
125
+ type: data
126
+ dataType: number
127
+ description: Range maximum (null for open-ended like "$400+")
128
+
129
+ - tag: isSelected
130
+ type: [data, interactive]
131
+ dataType: boolean
132
+ elementType: HTMLInputElement
133
+ description: Radio button for this range
134
+
135
+ # Category filter (slow for category list, fast+interactive for selection)
136
+ - tag: categoryFilter
137
+ type: sub-contract
138
+ description: Filter by category
139
+ tags:
140
+ - tag: categories
141
+ type: sub-contract
142
+ repeated: true
143
+ trackBy: categoryId
144
+ description: Available categories for filtering
145
+ tags:
146
+ - tag: categoryId
147
+ type: data
148
+ dataType: string
149
+ description: Category GUID
150
+
151
+ - tag: categoryName
152
+ type: data
153
+ dataType: string
154
+ description: Category name
155
+
156
+ - tag: categorySlug
157
+ type: data
158
+ dataType: string
159
+ description: Category slug for URL
160
+
161
+ - tag: isSelected
162
+ type: [data, interactive]
163
+ dataType: boolean
164
+ elementType: HTMLInputElement
165
+ description: Category checkbox
166
+
167
+ - tag: clearFilters
168
+ type: interactive
169
+ elementType: HTMLButtonElement
170
+ description: Clear all filters button
171
+
172
+ # Sorting (fast+interactive)
173
+ - tag: sortBy
174
+ type: sub-contract
175
+ phase: fast+interactive
176
+ description: Sort search results
177
+ tags:
178
+ - tag: currentSort
179
+ type: data
180
+ dataType: enum (relevance | priceAsc | priceDesc | newest | nameAsc | nameDesc)
181
+ description: Current sort option
182
+
183
+ - tag: sortDropdown
184
+ type: interactive
185
+ elementType: HTMLSelectElement
186
+ description: Dropdown to select sort option
187
+
188
+ # Load more (replaces pagination)
189
+ - tag: hasMore
190
+ type: variant
191
+ dataType: boolean
192
+ phase: fast+interactive
193
+ description: Whether there are more products to load
194
+
195
+ - tag: loadMoreButton
196
+ type: interactive
197
+ elementType: HTMLButtonElement
198
+ description: Button to load more products
199
+
200
+ - tag: loadedCount
201
+ type: data
202
+ dataType: number
203
+ phase: fast+interactive
204
+ description: Number of products currently loaded
205
+
206
+ - tag: totalCount
207
+ type: data
208
+ dataType: number
209
+ phase: fast+interactive
210
+ description: Total number of products matching search
211
+
212
+ # Search suggestions (fast+interactive)
213
+ - tag: hasSuggestions
214
+ type: variant
215
+ dataType: boolean
216
+ phase: fast+interactive
217
+ description: Whether search suggestions are available
218
+
219
+ - tag: suggestions
220
+ type: sub-contract
221
+ repeated: true
222
+ trackBy: suggestionId
223
+ phase: fast+interactive
224
+ description: Search term suggestions
225
+ tags:
226
+ - tag: suggestionId
227
+ type: data
228
+ dataType: string
229
+ description: Suggested id
230
+
231
+ - tag: suggestionText
232
+ type: data
233
+ dataType: string
234
+ description: Suggested search term
235
+
236
+ - tag: suggestionButton
237
+ type: interactive
238
+ elementType: HTMLButtonElement
239
+ description: Button to use this suggestion
240
+
@@ -0,0 +1,165 @@
1
+ import {HTMLElementCollectionProxy, HTMLElementProxy, JayContract} from "@jay-framework/runtime";
2
+ import {ProductCardViewState, ProductCardRefs, ProductCardRepeatedRefs} from "./product-card.jay-contract";
3
+
4
+ export interface RangeOfPriceRangeOfFilterOfProductSearchViewState {
5
+ rangeId: string,
6
+ label: string,
7
+ minValue: number,
8
+ maxValue: number,
9
+ isSelected: boolean
10
+ }
11
+
12
+ export interface PriceRangeOfFilterOfProductSearchViewState {
13
+ minPrice: number,
14
+ maxPrice: number,
15
+ minBound: number,
16
+ maxBound: number,
17
+ ranges: Array<RangeOfPriceRangeOfFilterOfProductSearchViewState>
18
+ }
19
+
20
+ export interface CategoryOfCategoryFilterOfFilterOfProductSearchViewState {
21
+ categoryId: string,
22
+ categoryName: string,
23
+ categorySlug: string,
24
+ isSelected: boolean
25
+ }
26
+
27
+ export interface CategoryFilterOfFilterOfProductSearchViewState {
28
+ categories: Array<CategoryOfCategoryFilterOfFilterOfProductSearchViewState>
29
+ }
30
+
31
+ export interface FilterOfProductSearchViewState {
32
+ priceRange: PriceRangeOfFilterOfProductSearchViewState,
33
+ categoryFilter: CategoryFilterOfFilterOfProductSearchViewState
34
+ }
35
+
36
+ export enum CurrentSort {
37
+ relevance,
38
+ priceAsc,
39
+ priceDesc,
40
+ newest,
41
+ nameAsc,
42
+ nameDesc
43
+ }
44
+
45
+ export interface SortByOfProductSearchViewState {
46
+ currentSort: CurrentSort
47
+ }
48
+
49
+ export interface SuggestionOfProductSearchViewState {
50
+ suggestionId: string,
51
+ suggestionText: string
52
+ }
53
+
54
+ export interface ProductSearchViewState {
55
+ searchExpression: string,
56
+ searchFields: string,
57
+ fuzzySearch: boolean,
58
+ isSearching: boolean,
59
+ hasSearched: boolean,
60
+ searchResults: Array<ProductCardViewState>,
61
+ resultCount: number,
62
+ hasResults: boolean,
63
+ emptyStateMessage: string,
64
+ filters: FilterOfProductSearchViewState,
65
+ sortBy: SortByOfProductSearchViewState,
66
+ hasMore: boolean,
67
+ loadedCount: number,
68
+ totalCount: number,
69
+ hasSuggestions: boolean,
70
+ suggestions: Array<SuggestionOfProductSearchViewState>
71
+ }
72
+
73
+ export type ProductSearchSlowViewState = Pick<ProductSearchViewState, 'searchFields' | 'fuzzySearch' | 'emptyStateMessage'> & {
74
+ filters: {
75
+ categoryFilter: {
76
+ categories: Array<Pick<ProductSearchViewState['filters']['categoryFilter']['categories'][number], 'categoryId' | 'categoryName' | 'categorySlug'>>;
77
+ };
78
+ };
79
+ };
80
+
81
+ export type ProductSearchFastViewState = Pick<ProductSearchViewState, 'searchExpression' | 'isSearching' | 'hasSearched' | 'resultCount' | 'hasResults' | 'hasMore' | 'loadedCount' | 'totalCount' | 'hasSuggestions'> & {
82
+ searchResults: Array<ProductSearchViewState['searchResults'][number]>;
83
+ filters: {
84
+ priceRange: ProductSearchViewState['filters']['priceRange'];
85
+ categoryFilter: {
86
+ categories: Array<Pick<ProductSearchViewState['filters']['categoryFilter']['categories'][number], 'categoryId' | 'isSelected'>>;
87
+ };
88
+ };
89
+ sortBy: ProductSearchViewState['sortBy'];
90
+ suggestions: Array<ProductSearchViewState['suggestions'][number]>;
91
+ };
92
+
93
+ export type ProductSearchInteractiveViewState = Pick<ProductSearchViewState, 'searchExpression' | 'isSearching' | 'hasSearched' | 'resultCount' | 'hasResults' | 'hasMore' | 'loadedCount' | 'totalCount' | 'hasSuggestions'> & {
94
+ searchResults: Array<ProductSearchViewState['searchResults'][number]>;
95
+ filters: {
96
+ priceRange: ProductSearchViewState['filters']['priceRange'];
97
+ categoryFilter: {
98
+ categories: Array<Pick<ProductSearchViewState['filters']['categoryFilter']['categories'][number], 'categoryId' | 'isSelected'>>;
99
+ };
100
+ };
101
+ sortBy: ProductSearchViewState['sortBy'];
102
+ suggestions: Array<ProductSearchViewState['suggestions'][number]>;
103
+ };
104
+
105
+
106
+ export interface ProductSearchRefs {
107
+ searchExpression: HTMLElementProxy<ProductSearchViewState, HTMLInputElement>,
108
+ searchButton: HTMLElementProxy<ProductSearchViewState, HTMLButtonElement>,
109
+ clearSearchButton: HTMLElementProxy<ProductSearchViewState, HTMLButtonElement>,
110
+ loadMoreButton: HTMLElementProxy<ProductSearchViewState, HTMLButtonElement>,
111
+ searchResults: ProductCardRepeatedRefs,
112
+ filters: {
113
+ clearFilters: HTMLElementProxy<FilterOfProductSearchViewState, HTMLButtonElement>,
114
+ priceRange: {
115
+ minPrice: HTMLElementProxy<PriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>,
116
+ maxPrice: HTMLElementProxy<PriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>,
117
+ ranges: {
118
+ isSelected: HTMLElementCollectionProxy<RangeOfPriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>
119
+ }
120
+ },
121
+ categoryFilter: {
122
+ categories: {
123
+ isSelected: HTMLElementCollectionProxy<CategoryOfCategoryFilterOfFilterOfProductSearchViewState, HTMLInputElement>
124
+ }
125
+ }
126
+ },
127
+ sortBy: {
128
+ sortDropdown: HTMLElementProxy<SortByOfProductSearchViewState, HTMLSelectElement>
129
+ },
130
+ suggestions: {
131
+ suggestionButton: HTMLElementCollectionProxy<SuggestionOfProductSearchViewState, HTMLButtonElement>
132
+ }
133
+ }
134
+
135
+
136
+ export interface ProductSearchRepeatedRefs {
137
+ searchExpression: HTMLElementCollectionProxy<ProductSearchViewState, HTMLInputElement>,
138
+ searchButton: HTMLElementCollectionProxy<ProductSearchViewState, HTMLButtonElement>,
139
+ clearSearchButton: HTMLElementCollectionProxy<ProductSearchViewState, HTMLButtonElement>,
140
+ loadMoreButton: HTMLElementCollectionProxy<ProductSearchViewState, HTMLButtonElement>,
141
+ searchResults: ProductCardRepeatedRefs,
142
+ filters: {
143
+ clearFilters: HTMLElementCollectionProxy<FilterOfProductSearchViewState, HTMLButtonElement>,
144
+ priceRange: {
145
+ minPrice: HTMLElementCollectionProxy<PriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>,
146
+ maxPrice: HTMLElementCollectionProxy<PriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>,
147
+ ranges: {
148
+ isSelected: HTMLElementCollectionProxy<RangeOfPriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>
149
+ }
150
+ },
151
+ categoryFilter: {
152
+ categories: {
153
+ isSelected: HTMLElementCollectionProxy<CategoryOfCategoryFilterOfFilterOfProductSearchViewState, HTMLInputElement>
154
+ }
155
+ }
156
+ },
157
+ sortBy: {
158
+ sortDropdown: HTMLElementCollectionProxy<SortByOfProductSearchViewState, HTMLSelectElement>
159
+ },
160
+ suggestions: {
161
+ suggestionButton: HTMLElementCollectionProxy<SuggestionOfProductSearchViewState, HTMLButtonElement>
162
+ }
163
+ }
164
+
165
+ export type ProductSearchContract = JayContract<ProductSearchViewState, ProductSearchRefs, ProductSearchSlowViewState, ProductSearchFastViewState, ProductSearchInteractiveViewState>