@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.
@@ -0,0 +1,53 @@
1
+ import {HTMLElementCollectionProxy, JayContract} from "@jay-framework/runtime";
2
+ import {MediaViewState, MediaRefs, MediaRepeatedRefs} from "./media.jay-contract";
3
+
4
+ export enum Selected {
5
+ selected,
6
+ notSelected
7
+ }
8
+
9
+ export interface AvailableMediaOfMediaGalleryViewState {
10
+ mediaId: string,
11
+ media: MediaViewState,
12
+ selected: Selected
13
+ }
14
+
15
+ export interface MediaGalleryViewState {
16
+ selectedMedia: MediaViewState,
17
+ availableMedia: Array<AvailableMediaOfMediaGalleryViewState>
18
+ }
19
+
20
+ export type MediaGallerySlowViewState = {
21
+ selectedMedia: MediaGalleryViewState['selectedMedia'];
22
+ availableMedia: Array<Pick<MediaGalleryViewState['availableMedia'][number], 'mediaId'> & {
23
+ media: MediaGalleryViewState['availableMedia'][number]['media'];
24
+ }>;
25
+ };
26
+
27
+ export type MediaGalleryFastViewState = {
28
+ availableMedia: Array<Pick<MediaGalleryViewState['availableMedia'][number], 'mediaId' | 'selected'>>;
29
+ };
30
+
31
+ export type MediaGalleryInteractiveViewState = {
32
+ availableMedia: Array<Pick<MediaGalleryViewState['availableMedia'][number], 'mediaId' | 'selected'>>;
33
+ };
34
+
35
+
36
+ export interface MediaGalleryRefs {
37
+ selectedMedia: MediaRefs,
38
+ availableMedia: {
39
+ selected: HTMLElementCollectionProxy<AvailableMediaOfMediaGalleryViewState, HTMLImageElement | HTMLDivElement>,
40
+ media: MediaRefs
41
+ }
42
+ }
43
+
44
+
45
+ export interface MediaGalleryRepeatedRefs {
46
+ selectedMedia: MediaRepeatedRefs,
47
+ availableMedia: {
48
+ selected: HTMLElementCollectionProxy<AvailableMediaOfMediaGalleryViewState, HTMLImageElement | HTMLDivElement>,
49
+ media: MediaRepeatedRefs
50
+ }
51
+ }
52
+
53
+ export type MediaGalleryContract = JayContract<MediaGalleryViewState, MediaGalleryRefs, MediaGallerySlowViewState, MediaGalleryFastViewState, MediaGalleryInteractiveViewState>
@@ -0,0 +1,5 @@
1
+ name: media
2
+ tags:
3
+ - {tag: url, type: data, dataType: string, description: Media Url}
4
+ - {tag: mediaType, type: variant, dataType: "enum (IMAGE | VIDEO)", description: Media type}
5
+ - {tag: thumbnail_50x50, type: data, dataType: string, description: Media Thumbnail Url }
@@ -0,0 +1,25 @@
1
+ import {JayContract} from "@jay-framework/runtime";
2
+
3
+
4
+ export enum MediaType {
5
+ IMAGE,
6
+ VIDEO
7
+ }
8
+
9
+ export interface MediaViewState {
10
+ url: string,
11
+ mediaType: MediaType,
12
+ thumbnail_50x50: string
13
+ }
14
+
15
+ export type MediaSlowViewState = Pick<MediaViewState, 'url' | 'mediaType' | 'thumbnail_50x50'>;
16
+
17
+ export type MediaFastViewState = {};
18
+
19
+ export type MediaInteractiveViewState = {};
20
+
21
+ export interface MediaRefs {}
22
+
23
+ export interface MediaRepeatedRefs {}
24
+
25
+ export type MediaContract = JayContract<MediaViewState, MediaRefs, MediaSlowViewState, MediaFastViewState, MediaInteractiveViewState>
@@ -0,0 +1,182 @@
1
+ name: product-card
2
+ tags:
3
+ # Product basic info (from Wix Stores Product API)
4
+ - tag: _id
5
+ type: data
6
+ dataType: string
7
+ description: Product GUID
8
+
9
+ - tag: name
10
+ type: data
11
+ dataType: string
12
+ required: true
13
+ description: Product name
14
+
15
+ - tag: slug
16
+ type: data
17
+ dataType: string
18
+ description: Product slug for URL
19
+
20
+ - tag: productUrl
21
+ type: data
22
+ dataType: string
23
+ description: Full URL path to product page (e.g., /products/my-product or /products/polgat/my-product)
24
+
25
+ - tag: categoryPrefix
26
+ type: data
27
+ dataType: string
28
+ description: Category prefix name for the product (e.g., the display name of the root category). Empty when no prefix is configured.
29
+
30
+ - tag: productLink
31
+ type: interactive
32
+ elementType: HTMLAnchorElement
33
+ description: Link to product page
34
+
35
+ # Media (from Wix Stores Product API)
36
+ - tag: mainMedia
37
+ type: sub-contract
38
+ description: Main product media
39
+ tags:
40
+ - tag: url
41
+ type: data
42
+ dataType: string
43
+ description: Media URL
44
+
45
+ - tag: altText
46
+ type: data
47
+ dataType: string
48
+ description: Media alt text
49
+
50
+ - tag: mediaType
51
+ type: data
52
+ dataType: enum (IMAGE | VIDEO)
53
+ description: Media type
54
+
55
+ - tag: thumbnail
56
+ type: sub-contract
57
+ description: Thumbnail image optimized for listings
58
+ tags:
59
+ - tag: url
60
+ type: data
61
+ dataType: string
62
+ description: Thumbnail URL
63
+
64
+ - tag: altText
65
+ type: data
66
+ dataType: string
67
+ description: Thumbnail alt text
68
+
69
+ - tag: width
70
+ type: data
71
+ dataType: number
72
+ description: Thumbnail width in pixels
73
+
74
+ - tag: height
75
+ type: data
76
+ dataType: number
77
+ description: Thumbnail height in pixels
78
+
79
+ # Price information
80
+ - tag: price
81
+ type: data
82
+ dataType: string
83
+ phase: fast+interactive
84
+ description: The product or variant price
85
+
86
+ - tag: strikethroughPrice
87
+ type: data
88
+ dataType: string
89
+ phase: fast+interactive
90
+ description: A Strikethrough product price for sales
91
+
92
+ - tag: hasDiscount
93
+ type: variant
94
+ dataType: boolean
95
+ description: Whether product has a discount (compareAtPrice > actualPrice)
96
+
97
+ # Inventory (from Wix Stores Product API)
98
+ - tag: inventory
99
+ type: sub-contract
100
+ description: Product inventory information
101
+ tags:
102
+ - tag: availabilityStatus
103
+ type: variant
104
+ dataType: enum (IN_STOCK | OUT_OF_STOCK | PARTIALLY_OUT_OF_STOCK)
105
+ description: Current availability status
106
+
107
+ - tag: preorderStatus
108
+ type: data
109
+ dataType: enum (ENABLED | DISABLED | PARTIALLY_ENABLED)
110
+ description: Current preorder status
111
+
112
+ # Product ribbon (from Wix Stores Product API)
113
+ - tag: ribbon
114
+ type: sub-contract
115
+ description: Product ribbon/badge
116
+ tags:
117
+ - tag: _id
118
+ type: data
119
+ dataType: string
120
+ description: Ribbon GUID
121
+
122
+ - tag: name
123
+ type: data
124
+ dataType: string
125
+ description: Ribbon text (e.g., "New", "Sale", "Best Seller")
126
+
127
+ - tag: hasRibbon
128
+ type: variant
129
+ dataType: boolean
130
+ description: Whether product has a ribbon/badge
131
+
132
+ # Brand (from Wix Stores Product API)
133
+ - tag: brand
134
+ type: sub-contract
135
+ description: Product brand
136
+ tags:
137
+ - tag: _id
138
+ type: data
139
+ dataType: string
140
+ description: Brand GUID
141
+
142
+ - tag: name
143
+ type: data
144
+ dataType: string
145
+ description: Brand name
146
+
147
+ # Additional product metadata
148
+ - tag: productType
149
+ type: data
150
+ dataType: enum (PHYSICAL | DIGITAL)
151
+ description: Product type
152
+
153
+ # Quick actions
154
+ - tag: addToCartButton
155
+ type: interactive
156
+ elementType: HTMLButtonElement
157
+ description: Quick add to cart button (for SIMPLE products with no options)
158
+
159
+ - tag: isAddingToCart
160
+ type: variant
161
+ dataType: boolean
162
+ phase: fast+interactive
163
+ description: Whether add to cart is in progress
164
+
165
+ # Quick-add behavior
166
+ - tag: quickAddType
167
+ type: variant
168
+ dataType: enum (SIMPLE | SINGLE_OPTION | NEEDS_CONFIGURATION)
169
+ description: |
170
+ SIMPLE = no options, show Add to Cart button
171
+ SINGLE_OPTION = one option, show choices on hover (click = add to cart)
172
+ NEEDS_CONFIGURATION = multiple options or modifiers, link to product page
173
+
174
+ - tag: quickOption
175
+ type: sub-contract
176
+ description: Primary option for quick selection (only when quickAddType = SINGLE_OPTION)
177
+ link: ./product-options
178
+
179
+ - tag: viewOptionsButton
180
+ type: interactive
181
+ elementType: HTMLButtonElement
182
+ description: Button to navigate to product page (when quickAddType = NEEDS_CONFIGURATION)
@@ -0,0 +1,120 @@
1
+ import {HTMLElementCollectionProxy, HTMLElementProxy, JayContract} from "@jay-framework/runtime";
2
+ import {ProductOptionsViewState, ProductOptionsRefs, ProductOptionsRepeatedRefs} from "./product-options.jay-contract";
3
+
4
+ export enum MediaType {
5
+ IMAGE,
6
+ VIDEO
7
+ }
8
+
9
+ export interface MainMediaOfProductCardViewState {
10
+ url: string,
11
+ altText: string,
12
+ mediaType: MediaType
13
+ }
14
+
15
+ export interface ThumbnailOfProductCardViewState {
16
+ url: string,
17
+ altText: string,
18
+ width: number,
19
+ height: number
20
+ }
21
+
22
+ export enum AvailabilityStatus {
23
+ IN_STOCK,
24
+ OUT_OF_STOCK,
25
+ PARTIALLY_OUT_OF_STOCK
26
+ }
27
+
28
+ export enum PreorderStatus {
29
+ ENABLED,
30
+ DISABLED,
31
+ PARTIALLY_ENABLED
32
+ }
33
+
34
+ export interface InventoryOfProductCardViewState {
35
+ availabilityStatus: AvailabilityStatus,
36
+ preorderStatus: PreorderStatus
37
+ }
38
+
39
+ export interface RibbonOfProductCardViewState {
40
+ _id: string,
41
+ name: string
42
+ }
43
+
44
+ export interface BrandOfProductCardViewState {
45
+ _id: string,
46
+ name: string
47
+ }
48
+
49
+ export enum ProductType {
50
+ PHYSICAL,
51
+ DIGITAL
52
+ }
53
+
54
+ export enum QuickAddType {
55
+ SIMPLE,
56
+ SINGLE_OPTION,
57
+ NEEDS_CONFIGURATION
58
+ }
59
+
60
+ export interface ProductCardViewState {
61
+ _id: string,
62
+ name: string,
63
+ slug: string,
64
+ productUrl: string,
65
+ categoryPrefix: string,
66
+ mainMedia: MainMediaOfProductCardViewState,
67
+ thumbnail: ThumbnailOfProductCardViewState,
68
+ price: string,
69
+ strikethroughPrice: string,
70
+ hasDiscount: boolean,
71
+ inventory: InventoryOfProductCardViewState,
72
+ ribbon: RibbonOfProductCardViewState,
73
+ hasRibbon: boolean,
74
+ brand: BrandOfProductCardViewState,
75
+ productType: ProductType,
76
+ isAddingToCart: boolean,
77
+ quickAddType: QuickAddType,
78
+ quickOption: ProductOptionsViewState
79
+ }
80
+
81
+ export type ProductCardSlowViewState = Pick<ProductCardViewState, '_id' | 'name' | 'slug' | 'productUrl' | 'categoryPrefix' | 'hasDiscount' | 'hasRibbon' | 'productType' | 'quickAddType'> & {
82
+ mainMedia: ProductCardViewState['mainMedia'];
83
+ thumbnail: ProductCardViewState['thumbnail'];
84
+ inventory: ProductCardViewState['inventory'];
85
+ ribbon: ProductCardViewState['ribbon'];
86
+ brand: ProductCardViewState['brand'];
87
+ quickOption: Pick<ProductCardViewState['quickOption'], '_id' | 'name' | 'optionRenderType'> & {
88
+ choices: Array<Pick<ProductCardViewState['quickOption']['choices'][number], 'choiceId' | 'name' | 'choiceType' | 'colorCode' | 'variantId'>>;
89
+ };
90
+ };
91
+
92
+ export type ProductCardFastViewState = Pick<ProductCardViewState, 'price' | 'strikethroughPrice' | 'isAddingToCart'> & {
93
+ quickOption: {
94
+ choices: Array<Pick<ProductCardViewState['quickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
95
+ };
96
+ };
97
+
98
+ export type ProductCardInteractiveViewState = Pick<ProductCardViewState, 'price' | 'strikethroughPrice' | 'isAddingToCart'> & {
99
+ quickOption: {
100
+ choices: Array<Pick<ProductCardViewState['quickOption']['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
101
+ };
102
+ };
103
+
104
+
105
+ export interface ProductCardRefs {
106
+ productLink: HTMLElementProxy<ProductCardViewState, HTMLAnchorElement>,
107
+ addToCartButton: HTMLElementProxy<ProductCardViewState, HTMLButtonElement>,
108
+ viewOptionsButton: HTMLElementProxy<ProductCardViewState, HTMLButtonElement>,
109
+ quickOption: ProductOptionsRefs
110
+ }
111
+
112
+
113
+ export interface ProductCardRepeatedRefs {
114
+ productLink: HTMLElementCollectionProxy<ProductCardViewState, HTMLAnchorElement>,
115
+ addToCartButton: HTMLElementCollectionProxy<ProductCardViewState, HTMLButtonElement>,
116
+ viewOptionsButton: HTMLElementCollectionProxy<ProductCardViewState, HTMLButtonElement>,
117
+ quickOption: ProductOptionsRepeatedRefs
118
+ }
119
+
120
+ export type ProductCardContract = JayContract<ProductCardViewState, ProductCardRefs, ProductCardSlowViewState, ProductCardFastViewState, ProductCardInteractiveViewState>
@@ -0,0 +1,66 @@
1
+ name: product-options
2
+ description: Shared product option structure for quick selection and full product page
3
+
4
+ tags:
5
+ - tag: _id
6
+ type: data
7
+ dataType: string
8
+ description: Option GUID
9
+
10
+ - tag: name
11
+ type: data
12
+ dataType: string
13
+ description: "Option name (e.g., \"Size\", \"Color\")"
14
+
15
+ - tag: optionRenderType
16
+ type: variant
17
+ dataType: enum (TEXT_CHOICES | COLOR_SWATCH_CHOICES)
18
+ description: How the option should be rendered
19
+
20
+ - tag: choices
21
+ type: sub-contract
22
+ repeated: true
23
+ trackBy: choiceId
24
+ description: Available choices for this option
25
+ tags:
26
+ - tag: choiceId
27
+ type: data
28
+ dataType: string
29
+ description: Choice GUID
30
+
31
+ - tag: name
32
+ type: data
33
+ dataType: string
34
+ description: "Choice display name (e.g., \"XL\", \"Red\")"
35
+
36
+ - tag: choiceType
37
+ type: variant
38
+ dataType: enum (CHOICE_TEXT | ONE_COLOR)
39
+ description: Type of choice (text or color swatch)
40
+
41
+ - tag: colorCode
42
+ type: data
43
+ dataType: string
44
+ description: Color code in HEX format (for color swatches)
45
+
46
+ - tag: inStock
47
+ type: variant
48
+ dataType: boolean
49
+ phase: fast+interactive
50
+ description: Whether this choice has available stock
51
+
52
+ - tag: variantId
53
+ type: data
54
+ dataType: string
55
+ description: The variant ID to use when adding to cart (for single-option products)
56
+
57
+ - tag: isSelected
58
+ type: variant
59
+ dataType: boolean
60
+ phase: fast+interactive
61
+ description: Whether this choice is currently selected
62
+
63
+ - tag: choiceButton
64
+ type: interactive
65
+ elementType: HTMLButtonElement
66
+ description: Button to select this choice (click adds to cart for quick-add)
@@ -0,0 +1,57 @@
1
+ import {HTMLElementCollectionProxy, JayContract} from "@jay-framework/runtime";
2
+
3
+
4
+ export enum OptionRenderType {
5
+ TEXT_CHOICES,
6
+ COLOR_SWATCH_CHOICES
7
+ }
8
+
9
+ export enum ChoiceType {
10
+ CHOICE_TEXT,
11
+ ONE_COLOR
12
+ }
13
+
14
+ export interface ChoiceOfProductOptionsViewState {
15
+ choiceId: string,
16
+ name: string,
17
+ choiceType: ChoiceType,
18
+ colorCode: string,
19
+ inStock: boolean,
20
+ variantId: string,
21
+ isSelected: boolean
22
+ }
23
+
24
+ export interface ProductOptionsViewState {
25
+ _id: string,
26
+ name: string,
27
+ optionRenderType: OptionRenderType,
28
+ choices: Array<ChoiceOfProductOptionsViewState>
29
+ }
30
+
31
+ export type ProductOptionsSlowViewState = Pick<ProductOptionsViewState, '_id' | 'name' | 'optionRenderType'> & {
32
+ choices: Array<Pick<ProductOptionsViewState['choices'][number], 'choiceId' | 'name' | 'choiceType' | 'colorCode' | 'variantId'>>;
33
+ };
34
+
35
+ export type ProductOptionsFastViewState = {
36
+ choices: Array<Pick<ProductOptionsViewState['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
37
+ };
38
+
39
+ export type ProductOptionsInteractiveViewState = {
40
+ choices: Array<Pick<ProductOptionsViewState['choices'][number], 'choiceId' | 'inStock' | 'isSelected'>>;
41
+ };
42
+
43
+
44
+ export interface ProductOptionsRefs {
45
+ choices: {
46
+ choiceButton: HTMLElementCollectionProxy<ChoiceOfProductOptionsViewState, HTMLButtonElement>
47
+ }
48
+ }
49
+
50
+
51
+ export interface ProductOptionsRepeatedRefs {
52
+ choices: {
53
+ choiceButton: HTMLElementCollectionProxy<ChoiceOfProductOptionsViewState, HTMLButtonElement>
54
+ }
55
+ }
56
+
57
+ export type ProductOptionsContract = JayContract<ProductOptionsViewState, ProductOptionsRefs, ProductOptionsSlowViewState, ProductOptionsFastViewState, ProductOptionsInteractiveViewState>
@@ -0,0 +1,151 @@
1
+ name: product-page
2
+ tags:
3
+ - {tag: _id, type: data, dataType: string, description: Product GUID}
4
+ - {tag: productName, type: data, dataType: string, required: true, description: Product name}
5
+
6
+ - tag: mediaGallery
7
+ type: sub-contract
8
+ phase: fast+interactive
9
+ link: ./media-gallery
10
+
11
+ - {tag: description, type: data, dataType: string, description: Product description}
12
+ - {tag: brand, type: data, dataType: string, description: Brand name}
13
+ - {tag: ribbon, type: data, dataType: string, description: "Ribbon text (e.g., \"New\", \"Sale\")"}
14
+ - {tag: productType, type: variant, dataType: "enum (PHYSICAL | DIGITAL)", description: Product type }
15
+
16
+ - {tag: sku, type: data, dataType: string, phase: fast+interactive, description: Product SKU, or chosen variant SKU}
17
+ - {tag: price, type: data, dataType: string, phase: fast+interactive, description: The product or variant price}
18
+ - {tag: strikethroughPrice, type: data, dataType: string, phase: fast+interactive, description: A Strikethrough product price for sales}
19
+ - {tag: pricePerUnit, type: data, dataType: string, phase: fast+interactive, description: formatted price per unit, if used}
20
+ - {tag: stockStatus, type: variant, dataType: "enum (OUT_OF_STOCK | IN_STOCK)", phase: fast+interactive, description: indicator if the product or current variant are in stock }
21
+
22
+ - tag: quantity
23
+ type: sub-contract
24
+ description: Quantity selection controls
25
+ tags:
26
+ - {tag: decrementButton, type: interactive, elementType: HTMLButtonElement, description: Button to decrease quantity}
27
+ - {tag: incrementButton, type: interactive, elementType: HTMLButtonElement, description: Button to increase quantity}
28
+ - {tag: quantity, type: [data, interactive], dataType: number, elementType: HTMLInputElement, description: Selected Quantity and Direct quantity input field}
29
+
30
+ # Call to action
31
+ - {tag: addToCartButton, type: interactive, elementType: HTMLButtonElement, required: true, description: Add product to cart button}
32
+ - {tag: buyNowButton, type: interactive, elementType: HTMLButtonElement, required: true, description: Buy now button}
33
+ - {tag: actionsEnabled, type: variant, dataType: boolean, phase: fast+interactive, description: should the add to cart and buy now buttons be enabled}
34
+
35
+ - tag: options
36
+ type: sub-contract
37
+ repeated: true
38
+ trackBy: _id
39
+ description: Product customization options that generate variants
40
+ tags:
41
+ - {tag: _id, type: data, dataType: string, description: "Option GUID (customization ID)"}
42
+ - {tag: name, type: data, dataType: string, description: "Option name (e.g., \"Color\", \"Size\")"}
43
+ - {tag: optionRenderType, type: variant, dataType: "enum (TEXT_CHOICES | COLOR_SWATCH_CHOICES)", description: How the option should be rendered}
44
+ - {tag: textChoice, type: interactive, elementType: HTMLSelectElement, description: dropdown for text choice}
45
+ - {tag: textChoiceSelection, type: data, dataType: string, phase: fast+interactive, description: the selected text option}
46
+
47
+ - tag: choices
48
+ type: sub-contract
49
+ repeated: true
50
+ trackBy: choiceId
51
+ description: Available choices for this option
52
+ tags:
53
+ - {tag: choiceId, type: data, dataType: string, description: Choice GUID}
54
+ - {tag: choiceType, type: variant, dataType: "enum (CHOICE_TEXT | ONE_COLOR)", description: Type of choice}
55
+ - {tag: name, type: data, dataType: string, description: "Choice name (e.g., \"Red\", \"Large\")"}
56
+ - {tag: colorCode, type: data, dataType: string, description: Color code in HEX format (for color choices)}
57
+ - {tag: inStock, type: data, dataType: boolean, description: Whether at least one variant with this choice is in stock}
58
+ - {tag: isSelected, type: variant, dataType: boolean, phase: fast+interactive, description: Whether this choice is currently selected (UI state)}
59
+ - {tag: choiceButton, type: interactive, elementType: HTMLButtonElement, description: Button to select this choice}
60
+
61
+ # Additional info sections (from Wix Stores API)
62
+ - tag: infoSections
63
+ type: sub-contract
64
+ repeated: true
65
+ trackBy: _id
66
+ description: Additional product information sections
67
+ tags:
68
+ - {tag: _id, type: data, dataType: string, description: Info section GUID}
69
+ - {tag: title, type: data, dataType: string, description: Info section title}
70
+ - {tag: plainDescription, type: data, dataType: string, description: Info section description in HTML}
71
+
72
+ - tag: modifiers
73
+ type: sub-contract
74
+ repeated: true
75
+ trackBy: _id
76
+ description: Product customization options that do not generate variants
77
+ tags:
78
+ - {tag: _id, type: data, dataType: string, description: "modifier id"}
79
+ - {tag: name, type: data, dataType: string, description: "modifier name (e.g., \"Color\", \"Size\")"}
80
+ - {tag: modifierType, type: variant, dataType: "enum (TEXT_CHOICES | COLOR_SWATCH_CHOICES | FREE_TEXT)", description: What type of modifier to use?}
81
+ - {tag: textModifier, type: interactive, elementType: HTMLSelectElement, description: dropdown for text modifier}
82
+ - {tag: textModifierSelection, type: data, dataType: string, phase: fast+interactive, description: the selected text modifier}
83
+ - {tag: textInput, type: interactive, elementType: HTMLInputElement | HTMLAreaElement, description: text input for free text}
84
+ - {tag: textInputLength, type: data, dataType: number, description: the limit on the length of free text}
85
+ - {tag: textInputRequired, type: data, dataType: boolean, description: Is the free text input required?}
86
+
87
+ - tag: choices
88
+ type: sub-contract
89
+ repeated: true
90
+ trackBy: choiceId
91
+ description: Available choices for this Modifier
92
+ tags:
93
+ - {tag: choiceId, type: data, dataType: string, description: Choice GUID}
94
+ - {tag: choiceType, type: variant, dataType: "enum (CHOICE_TEXT | ONE_COLOR)", description: Type of choice}
95
+ - {tag: name, type: data, dataType: string, description: "Choice name (e.g., \"Red\", \"Large\")"}
96
+ - {tag: colorCode, type: data, dataType: string, description: Color code in HEX format (for color choices)}
97
+ - {tag: isSelected, type: variant, dataType: boolean, phase: fast+interactive, description: Whether this choice is currently selected (UI state)}
98
+ - {tag: choiceButton, type: interactive, elementType: HTMLButtonElement, description: Button to select this choice}
99
+
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. }