@jay-framework/wix-stores 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.
- package/README.md +184 -0
- package/dist/actions/get-categories.jay-action +8 -0
- package/dist/actions/get-product-by-slug.jay-action +10 -0
- package/dist/actions/search-products.jay-action +33 -0
- package/dist/contracts/category-list.jay-contract +50 -0
- package/dist/contracts/category-list.jay-contract.d.ts +40 -0
- package/dist/contracts/category-page.jay-contract +193 -0
- package/dist/contracts/category-page.jay-contract.d.ts +124 -0
- package/dist/contracts/media-gallery.jay-contract +22 -0
- package/dist/contracts/media-gallery.jay-contract.d.ts +53 -0
- package/dist/contracts/media.jay-contract +5 -0
- package/dist/contracts/media.jay-contract.d.ts +25 -0
- package/dist/contracts/product-card.jay-contract +182 -0
- package/dist/contracts/product-card.jay-contract.d.ts +120 -0
- package/dist/contracts/product-options.jay-contract +66 -0
- package/dist/contracts/product-options.jay-contract.d.ts +57 -0
- package/dist/contracts/product-page.jay-contract +151 -0
- package/dist/contracts/product-page.jay-contract.d.ts +218 -0
- package/dist/contracts/product-search.jay-contract +252 -0
- package/dist/contracts/product-search.jay-contract.d.ts +169 -0
- package/dist/index.client.js +649 -0
- package/dist/index.d.ts +943 -0
- package/dist/index.js +1140 -0
- package/package.json +66 -0
- package/plugin.yaml +34 -0
|
@@ -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,252 @@
|
|
|
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 with product counts
|
|
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: productCount
|
|
130
|
+
type: data
|
|
131
|
+
dataType: number
|
|
132
|
+
description: Number of products in this price range
|
|
133
|
+
|
|
134
|
+
- tag: isSelected
|
|
135
|
+
type: [data, interactive]
|
|
136
|
+
dataType: boolean
|
|
137
|
+
elementType: HTMLInputElement
|
|
138
|
+
description: Radio button for this range
|
|
139
|
+
|
|
140
|
+
# Category filter (slow for category list, fast+interactive for selection)
|
|
141
|
+
- tag: categoryFilter
|
|
142
|
+
type: sub-contract
|
|
143
|
+
description: Filter by category
|
|
144
|
+
tags:
|
|
145
|
+
- tag: categories
|
|
146
|
+
type: sub-contract
|
|
147
|
+
repeated: true
|
|
148
|
+
trackBy: categoryId
|
|
149
|
+
description: Available categories for filtering
|
|
150
|
+
tags:
|
|
151
|
+
- tag: categoryId
|
|
152
|
+
type: data
|
|
153
|
+
dataType: string
|
|
154
|
+
description: Category GUID
|
|
155
|
+
|
|
156
|
+
- tag: categoryName
|
|
157
|
+
type: data
|
|
158
|
+
dataType: string
|
|
159
|
+
description: Category name
|
|
160
|
+
|
|
161
|
+
- tag: categorySlug
|
|
162
|
+
type: data
|
|
163
|
+
dataType: string
|
|
164
|
+
description: Category slug for URL
|
|
165
|
+
|
|
166
|
+
- tag: isSelected
|
|
167
|
+
type: [data, interactive]
|
|
168
|
+
dataType: boolean
|
|
169
|
+
elementType: HTMLInputElement
|
|
170
|
+
description: Category checkbox
|
|
171
|
+
|
|
172
|
+
# Availability filter (fast+interactive)
|
|
173
|
+
- tag: inStockOnly
|
|
174
|
+
type: [data, interactive]
|
|
175
|
+
dataType: boolean
|
|
176
|
+
elementType: HTMLInputElement
|
|
177
|
+
description: Show only in-stock products checkbox
|
|
178
|
+
|
|
179
|
+
- tag: clearFilters
|
|
180
|
+
type: interactive
|
|
181
|
+
elementType: HTMLButtonElement
|
|
182
|
+
description: Clear all filters button
|
|
183
|
+
|
|
184
|
+
# Sorting (fast+interactive)
|
|
185
|
+
- tag: sortBy
|
|
186
|
+
type: sub-contract
|
|
187
|
+
phase: fast+interactive
|
|
188
|
+
description: Sort search results
|
|
189
|
+
tags:
|
|
190
|
+
- tag: currentSort
|
|
191
|
+
type: data
|
|
192
|
+
dataType: enum (relevance | priceAsc | priceDesc | newest | nameAsc | nameDesc)
|
|
193
|
+
description: Current sort option
|
|
194
|
+
|
|
195
|
+
- tag: sortDropdown
|
|
196
|
+
type: interactive
|
|
197
|
+
elementType: HTMLSelectElement
|
|
198
|
+
description: Dropdown to select sort option
|
|
199
|
+
|
|
200
|
+
# Load more (replaces pagination)
|
|
201
|
+
- tag: hasMore
|
|
202
|
+
type: variant
|
|
203
|
+
dataType: boolean
|
|
204
|
+
phase: fast+interactive
|
|
205
|
+
description: Whether there are more products to load
|
|
206
|
+
|
|
207
|
+
- tag: loadMoreButton
|
|
208
|
+
type: interactive
|
|
209
|
+
elementType: HTMLButtonElement
|
|
210
|
+
description: Button to load more products
|
|
211
|
+
|
|
212
|
+
- tag: loadedCount
|
|
213
|
+
type: data
|
|
214
|
+
dataType: number
|
|
215
|
+
phase: fast+interactive
|
|
216
|
+
description: Number of products currently loaded
|
|
217
|
+
|
|
218
|
+
- tag: totalCount
|
|
219
|
+
type: data
|
|
220
|
+
dataType: number
|
|
221
|
+
phase: fast+interactive
|
|
222
|
+
description: Total number of products matching search
|
|
223
|
+
|
|
224
|
+
# Search suggestions (fast+interactive)
|
|
225
|
+
- tag: hasSuggestions
|
|
226
|
+
type: variant
|
|
227
|
+
dataType: boolean
|
|
228
|
+
phase: fast+interactive
|
|
229
|
+
description: Whether search suggestions are available
|
|
230
|
+
|
|
231
|
+
- tag: suggestions
|
|
232
|
+
type: sub-contract
|
|
233
|
+
repeated: true
|
|
234
|
+
trackBy: suggestionId
|
|
235
|
+
phase: fast+interactive
|
|
236
|
+
description: Search term suggestions
|
|
237
|
+
tags:
|
|
238
|
+
- tag: suggestionId
|
|
239
|
+
type: data
|
|
240
|
+
dataType: string
|
|
241
|
+
description: Suggested id
|
|
242
|
+
|
|
243
|
+
- tag: suggestionText
|
|
244
|
+
type: data
|
|
245
|
+
dataType: string
|
|
246
|
+
description: Suggested search term
|
|
247
|
+
|
|
248
|
+
- tag: suggestionButton
|
|
249
|
+
type: interactive
|
|
250
|
+
elementType: HTMLButtonElement
|
|
251
|
+
description: Button to use this suggestion
|
|
252
|
+
|
|
@@ -0,0 +1,169 @@
|
|
|
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
|
+
productCount: number,
|
|
10
|
+
isSelected: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface PriceRangeOfFilterOfProductSearchViewState {
|
|
14
|
+
minPrice: number,
|
|
15
|
+
maxPrice: number,
|
|
16
|
+
minBound: number,
|
|
17
|
+
maxBound: number,
|
|
18
|
+
ranges: Array<RangeOfPriceRangeOfFilterOfProductSearchViewState>
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface CategoryOfCategoryFilterOfFilterOfProductSearchViewState {
|
|
22
|
+
categoryId: string,
|
|
23
|
+
categoryName: string,
|
|
24
|
+
categorySlug: string,
|
|
25
|
+
isSelected: boolean
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface CategoryFilterOfFilterOfProductSearchViewState {
|
|
29
|
+
categories: Array<CategoryOfCategoryFilterOfFilterOfProductSearchViewState>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface FilterOfProductSearchViewState {
|
|
33
|
+
priceRange: PriceRangeOfFilterOfProductSearchViewState,
|
|
34
|
+
categoryFilter: CategoryFilterOfFilterOfProductSearchViewState,
|
|
35
|
+
inStockOnly: boolean
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export enum CurrentSort {
|
|
39
|
+
relevance,
|
|
40
|
+
priceAsc,
|
|
41
|
+
priceDesc,
|
|
42
|
+
newest,
|
|
43
|
+
nameAsc,
|
|
44
|
+
nameDesc
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface SortByOfProductSearchViewState {
|
|
48
|
+
currentSort: CurrentSort
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface SuggestionOfProductSearchViewState {
|
|
52
|
+
suggestionId: string,
|
|
53
|
+
suggestionText: string
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ProductSearchViewState {
|
|
57
|
+
searchExpression: string,
|
|
58
|
+
searchFields: string,
|
|
59
|
+
fuzzySearch: boolean,
|
|
60
|
+
isSearching: boolean,
|
|
61
|
+
hasSearched: boolean,
|
|
62
|
+
searchResults: Array<ProductCardViewState>,
|
|
63
|
+
resultCount: number,
|
|
64
|
+
hasResults: boolean,
|
|
65
|
+
emptyStateMessage: string,
|
|
66
|
+
filters: FilterOfProductSearchViewState,
|
|
67
|
+
sortBy: SortByOfProductSearchViewState,
|
|
68
|
+
hasMore: boolean,
|
|
69
|
+
loadedCount: number,
|
|
70
|
+
totalCount: number,
|
|
71
|
+
hasSuggestions: boolean,
|
|
72
|
+
suggestions: Array<SuggestionOfProductSearchViewState>
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export type ProductSearchSlowViewState = Pick<ProductSearchViewState, 'searchFields' | 'fuzzySearch' | 'emptyStateMessage'> & {
|
|
76
|
+
filters: {
|
|
77
|
+
categoryFilter: {
|
|
78
|
+
categories: Array<Pick<ProductSearchViewState['filters']['categoryFilter']['categories'][number], 'categoryId' | 'categoryName' | 'categorySlug'>>;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export type ProductSearchFastViewState = Pick<ProductSearchViewState, 'searchExpression' | 'isSearching' | 'hasSearched' | 'resultCount' | 'hasResults' | 'hasMore' | 'loadedCount' | 'totalCount' | 'hasSuggestions'> & {
|
|
84
|
+
searchResults: Array<ProductSearchViewState['searchResults'][number]>;
|
|
85
|
+
filters: Pick<ProductSearchViewState['filters'], 'inStockOnly'> & {
|
|
86
|
+
priceRange: ProductSearchViewState['filters']['priceRange'];
|
|
87
|
+
categoryFilter: {
|
|
88
|
+
categories: Array<Pick<ProductSearchViewState['filters']['categoryFilter']['categories'][number], 'categoryId' | 'isSelected'>>;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
sortBy: ProductSearchViewState['sortBy'];
|
|
92
|
+
suggestions: Array<ProductSearchViewState['suggestions'][number]>;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export type ProductSearchInteractiveViewState = Pick<ProductSearchViewState, 'searchExpression' | 'isSearching' | 'hasSearched' | 'resultCount' | 'hasResults' | 'hasMore' | 'loadedCount' | 'totalCount' | 'hasSuggestions'> & {
|
|
96
|
+
searchResults: Array<ProductSearchViewState['searchResults'][number]>;
|
|
97
|
+
filters: Pick<ProductSearchViewState['filters'], 'inStockOnly'> & {
|
|
98
|
+
priceRange: ProductSearchViewState['filters']['priceRange'];
|
|
99
|
+
categoryFilter: {
|
|
100
|
+
categories: Array<Pick<ProductSearchViewState['filters']['categoryFilter']['categories'][number], 'categoryId' | 'isSelected'>>;
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
sortBy: ProductSearchViewState['sortBy'];
|
|
104
|
+
suggestions: Array<ProductSearchViewState['suggestions'][number]>;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
export interface ProductSearchRefs {
|
|
109
|
+
searchExpression: HTMLElementProxy<ProductSearchViewState, HTMLInputElement>,
|
|
110
|
+
searchButton: HTMLElementProxy<ProductSearchViewState, HTMLButtonElement>,
|
|
111
|
+
clearSearchButton: HTMLElementProxy<ProductSearchViewState, HTMLButtonElement>,
|
|
112
|
+
loadMoreButton: HTMLElementProxy<ProductSearchViewState, HTMLButtonElement>,
|
|
113
|
+
searchResults: ProductCardRepeatedRefs,
|
|
114
|
+
filters: {
|
|
115
|
+
inStockOnly: HTMLElementProxy<FilterOfProductSearchViewState, HTMLInputElement>,
|
|
116
|
+
clearFilters: HTMLElementProxy<FilterOfProductSearchViewState, HTMLButtonElement>,
|
|
117
|
+
priceRange: {
|
|
118
|
+
minPrice: HTMLElementProxy<PriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>,
|
|
119
|
+
maxPrice: HTMLElementProxy<PriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>,
|
|
120
|
+
ranges: {
|
|
121
|
+
isSelected: HTMLElementCollectionProxy<RangeOfPriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
categoryFilter: {
|
|
125
|
+
categories: {
|
|
126
|
+
isSelected: HTMLElementCollectionProxy<CategoryOfCategoryFilterOfFilterOfProductSearchViewState, HTMLInputElement>
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
sortBy: {
|
|
131
|
+
sortDropdown: HTMLElementProxy<SortByOfProductSearchViewState, HTMLSelectElement>
|
|
132
|
+
},
|
|
133
|
+
suggestions: {
|
|
134
|
+
suggestionButton: HTMLElementCollectionProxy<SuggestionOfProductSearchViewState, HTMLButtonElement>
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
export interface ProductSearchRepeatedRefs {
|
|
140
|
+
searchExpression: HTMLElementCollectionProxy<ProductSearchViewState, HTMLInputElement>,
|
|
141
|
+
searchButton: HTMLElementCollectionProxy<ProductSearchViewState, HTMLButtonElement>,
|
|
142
|
+
clearSearchButton: HTMLElementCollectionProxy<ProductSearchViewState, HTMLButtonElement>,
|
|
143
|
+
loadMoreButton: HTMLElementCollectionProxy<ProductSearchViewState, HTMLButtonElement>,
|
|
144
|
+
searchResults: ProductCardRepeatedRefs,
|
|
145
|
+
filters: {
|
|
146
|
+
inStockOnly: HTMLElementCollectionProxy<FilterOfProductSearchViewState, HTMLInputElement>,
|
|
147
|
+
clearFilters: HTMLElementCollectionProxy<FilterOfProductSearchViewState, HTMLButtonElement>,
|
|
148
|
+
priceRange: {
|
|
149
|
+
minPrice: HTMLElementCollectionProxy<PriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>,
|
|
150
|
+
maxPrice: HTMLElementCollectionProxy<PriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>,
|
|
151
|
+
ranges: {
|
|
152
|
+
isSelected: HTMLElementCollectionProxy<RangeOfPriceRangeOfFilterOfProductSearchViewState, HTMLInputElement>
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
categoryFilter: {
|
|
156
|
+
categories: {
|
|
157
|
+
isSelected: HTMLElementCollectionProxy<CategoryOfCategoryFilterOfFilterOfProductSearchViewState, HTMLInputElement>
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
sortBy: {
|
|
162
|
+
sortDropdown: HTMLElementCollectionProxy<SortByOfProductSearchViewState, HTMLSelectElement>
|
|
163
|
+
},
|
|
164
|
+
suggestions: {
|
|
165
|
+
suggestionButton: HTMLElementCollectionProxy<SuggestionOfProductSearchViewState, HTMLButtonElement>
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export type ProductSearchContract = JayContract<ProductSearchViewState, ProductSearchRefs, ProductSearchSlowViewState, ProductSearchFastViewState, ProductSearchInteractiveViewState>
|