@wix/headless-stores 0.0.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/astro/actions/package.json +4 -0
- package/cjs/dist/astro/actions/custom-checkout.d.ts +50 -0
- package/cjs/dist/astro/actions/custom-checkout.js +53 -0
- package/cjs/dist/astro/actions/index.d.ts +1 -0
- package/cjs/dist/astro/actions/index.js +1 -0
- package/cjs/dist/data-component-tags.d.ts +8 -0
- package/cjs/dist/data-component-tags.js +9 -0
- package/cjs/dist/enums/index.d.ts +2 -0
- package/cjs/dist/enums/index.js +2 -0
- package/cjs/dist/enums/social-platform-enums.d.ts +25 -0
- package/cjs/dist/enums/social-platform-enums.js +27 -0
- package/cjs/dist/enums/sort-enums.d.ts +17 -0
- package/cjs/dist/enums/sort-enums.js +18 -0
- package/cjs/dist/react/Category.d.ts +242 -0
- package/cjs/dist/react/Category.js +235 -0
- package/cjs/dist/react/CategoryList.d.ts +107 -0
- package/cjs/dist/react/CategoryList.js +91 -0
- package/cjs/dist/react/Choice.d.ts +211 -0
- package/cjs/dist/react/Choice.js +213 -0
- package/cjs/dist/react/Option.d.ts +242 -0
- package/cjs/dist/react/Option.js +346 -0
- package/cjs/dist/react/Product.d.ts +1065 -0
- package/cjs/dist/react/Product.js +1157 -0
- package/cjs/dist/react/ProductList.d.ts +400 -0
- package/cjs/dist/react/ProductList.js +368 -0
- package/cjs/dist/react/core/CategoryList.d.ts +194 -0
- package/cjs/dist/react/core/CategoryList.js +180 -0
- package/cjs/dist/react/core/Product.d.ts +225 -0
- package/cjs/dist/react/core/Product.js +190 -0
- package/cjs/dist/react/core/ProductList.d.ts +235 -0
- package/cjs/dist/react/core/ProductList.js +217 -0
- package/cjs/dist/react/core/ProductListFilters.d.ts +138 -0
- package/cjs/dist/react/core/ProductListFilters.js +242 -0
- package/cjs/dist/react/core/ProductListPagination.d.ts +49 -0
- package/cjs/dist/react/core/ProductListPagination.js +41 -0
- package/cjs/dist/react/core/ProductListSort.d.ts +19 -0
- package/cjs/dist/react/core/ProductListSort.js +52 -0
- package/cjs/dist/react/core/ProductModifiers.d.ts +416 -0
- package/cjs/dist/react/core/ProductModifiers.js +413 -0
- package/cjs/dist/react/core/ProductVariantSelector.d.ts +313 -0
- package/cjs/dist/react/core/ProductVariantSelector.js +291 -0
- package/cjs/dist/react/core/SelectedVariant.d.ts +230 -0
- package/cjs/dist/react/core/SelectedVariant.js +269 -0
- package/cjs/dist/react/index.d.ts +6 -0
- package/cjs/dist/react/index.js +6 -0
- package/cjs/dist/react/types.d.ts +8 -0
- package/cjs/dist/react/types.js +9 -0
- package/cjs/dist/server-actions/custom-checkout-action.d.ts +49 -0
- package/cjs/dist/server-actions/custom-checkout-action.js +64 -0
- package/cjs/dist/server-actions/index.d.ts +1 -0
- package/cjs/dist/server-actions/index.js +1 -0
- package/cjs/dist/services/buy-now-service.d.ts +346 -0
- package/cjs/dist/services/buy-now-service.js +197 -0
- package/cjs/dist/services/categories-list-service.d.ts +164 -0
- package/cjs/dist/services/categories-list-service.js +148 -0
- package/cjs/dist/services/index.d.ts +5 -0
- package/cjs/dist/services/index.js +5 -0
- package/cjs/dist/services/pay-now-service.d.ts +214 -0
- package/cjs/dist/services/pay-now-service.js +156 -0
- package/cjs/dist/services/product-modifiers-service.d.ts +34 -0
- package/cjs/dist/services/product-modifiers-service.js +107 -0
- package/cjs/dist/services/product-service.d.ts +177 -0
- package/cjs/dist/services/product-service.js +190 -0
- package/cjs/dist/services/products-list-search-service.d.ts +1 -0
- package/cjs/dist/services/products-list-search-service.js +1 -0
- package/cjs/dist/services/products-list-service.d.ts +429 -0
- package/cjs/dist/services/products-list-service.js +893 -0
- package/cjs/dist/services/selected-variant-service.d.ts +66 -0
- package/cjs/dist/services/selected-variant-service.js +527 -0
- package/cjs/dist/utils/index.d.ts +1 -0
- package/cjs/dist/utils/index.js +30 -0
- package/cjs/dist/utils/url-params.d.ts +73 -0
- package/cjs/dist/utils/url-params.js +114 -0
- package/cjs/package.json +3 -0
- package/dist/astro/actions/custom-checkout.d.ts +50 -0
- package/dist/astro/actions/custom-checkout.js +53 -0
- package/dist/astro/actions/index.d.ts +1 -0
- package/dist/astro/actions/index.js +1 -0
- package/dist/data-component-tags.d.ts +8 -0
- package/dist/data-component-tags.js +9 -0
- package/dist/enums/index.d.ts +2 -0
- package/dist/enums/index.js +2 -0
- package/dist/enums/social-platform-enums.d.ts +25 -0
- package/dist/enums/social-platform-enums.js +27 -0
- package/dist/enums/sort-enums.d.ts +17 -0
- package/dist/enums/sort-enums.js +18 -0
- package/dist/react/Category.d.ts +242 -0
- package/dist/react/Category.js +235 -0
- package/dist/react/CategoryList.d.ts +107 -0
- package/dist/react/CategoryList.js +91 -0
- package/dist/react/Choice.d.ts +211 -0
- package/dist/react/Choice.js +213 -0
- package/dist/react/Option.d.ts +242 -0
- package/dist/react/Option.js +346 -0
- package/dist/react/Product.d.ts +1065 -0
- package/dist/react/Product.js +1157 -0
- package/dist/react/ProductList.d.ts +400 -0
- package/dist/react/ProductList.js +368 -0
- package/dist/react/core/CategoryList.d.ts +194 -0
- package/dist/react/core/CategoryList.js +180 -0
- package/dist/react/core/Product.d.ts +225 -0
- package/dist/react/core/Product.js +190 -0
- package/dist/react/core/ProductList.d.ts +235 -0
- package/dist/react/core/ProductList.js +217 -0
- package/dist/react/core/ProductListFilters.d.ts +138 -0
- package/dist/react/core/ProductListFilters.js +242 -0
- package/dist/react/core/ProductListPagination.d.ts +49 -0
- package/dist/react/core/ProductListPagination.js +41 -0
- package/dist/react/core/ProductListSort.d.ts +19 -0
- package/dist/react/core/ProductListSort.js +52 -0
- package/dist/react/core/ProductModifiers.d.ts +416 -0
- package/dist/react/core/ProductModifiers.js +413 -0
- package/dist/react/core/ProductVariantSelector.d.ts +313 -0
- package/dist/react/core/ProductVariantSelector.js +291 -0
- package/dist/react/core/SelectedVariant.d.ts +230 -0
- package/dist/react/core/SelectedVariant.js +269 -0
- package/dist/react/index.d.ts +6 -0
- package/dist/react/index.js +6 -0
- package/dist/react/types.d.ts +8 -0
- package/dist/react/types.js +9 -0
- package/dist/server-actions/custom-checkout-action.d.ts +49 -0
- package/dist/server-actions/custom-checkout-action.js +64 -0
- package/dist/server-actions/index.d.ts +1 -0
- package/dist/server-actions/index.js +1 -0
- package/dist/services/buy-now-service.d.ts +346 -0
- package/dist/services/buy-now-service.js +197 -0
- package/dist/services/categories-list-service.d.ts +164 -0
- package/dist/services/categories-list-service.js +148 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.js +5 -0
- package/dist/services/pay-now-service.d.ts +214 -0
- package/dist/services/pay-now-service.js +156 -0
- package/dist/services/product-modifiers-service.d.ts +34 -0
- package/dist/services/product-modifiers-service.js +107 -0
- package/dist/services/product-service.d.ts +177 -0
- package/dist/services/product-service.js +190 -0
- package/dist/services/products-list-search-service.d.ts +0 -0
- package/dist/services/products-list-search-service.js +1 -0
- package/dist/services/products-list-service.d.ts +429 -0
- package/dist/services/products-list-service.js +893 -0
- package/dist/services/selected-variant-service.d.ts +66 -0
- package/dist/services/selected-variant-service.js +527 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +30 -0
- package/dist/utils/url-params.d.ts +73 -0
- package/dist/utils/url-params.js +114 -0
- package/package.json +89 -0
- package/react/package.json +4 -0
- package/server-actions/package.json +4 -0
- package/services/package.json +4 -0
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { useService, WixServices } from '@wix/services-manager-react';
|
|
4
|
+
import { ProductModifiersServiceDefinition, ProductModifiersService, } from '../../services/product-modifiers-service.js';
|
|
5
|
+
import { ModifierRenderType, } from '@wix/auto_sdk_stores_products-v-3';
|
|
6
|
+
import { createServicesMap } from '@wix/services-manager';
|
|
7
|
+
/**
|
|
8
|
+
* Root component that provides the ProductModifiers service context to its children.
|
|
9
|
+
* This component sets up the necessary services for managing product modifier functionality.
|
|
10
|
+
*
|
|
11
|
+
* @order 1
|
|
12
|
+
* @component
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* import { ProductModifiers } from '@wix/stores/components';
|
|
16
|
+
*
|
|
17
|
+
* function ProductCustomization() {
|
|
18
|
+
* return (
|
|
19
|
+
* <ProductModifiers.Root>
|
|
20
|
+
* <div>
|
|
21
|
+
* <ProductModifiers.Modifiers>
|
|
22
|
+
* {({ modifiers, hasModifiers, selectedModifiers, areAllRequiredModifiersFilled }) => (
|
|
23
|
+
* <div>
|
|
24
|
+
* {hasModifiers && (
|
|
25
|
+
* <div>
|
|
26
|
+
* <h3>Customize your product</h3>
|
|
27
|
+
* {modifiers.map(modifier => (
|
|
28
|
+
* <ProductModifiers.Modifier key={modifier.id} modifier={modifier}>
|
|
29
|
+
* {({ name, mandatory, hasChoices, choices, isFreeText }) => (
|
|
30
|
+
* <div className="modifier-field">
|
|
31
|
+
* <label>
|
|
32
|
+
* {name} {mandatory && <span className="required">*</span>}
|
|
33
|
+
* </label>
|
|
34
|
+
* {hasChoices && (
|
|
35
|
+
* <div className="choices">
|
|
36
|
+
* {choices.map(choice => (
|
|
37
|
+
* <ProductModifiers.Choice key={choice.id} modifier={modifier} choice={choice}>
|
|
38
|
+
* {({ value, isSelected, select }) => (
|
|
39
|
+
* <button
|
|
40
|
+
* onClick={select}
|
|
41
|
+
* className={isSelected ? 'selected' : ''}
|
|
42
|
+
* >
|
|
43
|
+
* {value}
|
|
44
|
+
* </button>
|
|
45
|
+
* )}
|
|
46
|
+
* </ProductModifiers.Choice>
|
|
47
|
+
* ))}
|
|
48
|
+
* </div>
|
|
49
|
+
* )}
|
|
50
|
+
* {isFreeText && (
|
|
51
|
+
* <ProductModifiers.FreeText modifier={modifier}>
|
|
52
|
+
* {({ value, onChange, placeholder, maxChars }) => (
|
|
53
|
+
* <input
|
|
54
|
+
* type="text"
|
|
55
|
+
* value={value}
|
|
56
|
+
* onChange={(e) => onChange(e.target.value)}
|
|
57
|
+
* placeholder={placeholder}
|
|
58
|
+
* maxLength={maxChars}
|
|
59
|
+
* />
|
|
60
|
+
* )}
|
|
61
|
+
* </ProductModifiers.FreeText>
|
|
62
|
+
* )}
|
|
63
|
+
* </div>
|
|
64
|
+
* )}
|
|
65
|
+
* </ProductModifiers.Modifier>
|
|
66
|
+
* ))}
|
|
67
|
+
* {!areAllRequiredModifiersFilled && (
|
|
68
|
+
* <div className="warning">Please fill all required options</div>
|
|
69
|
+
* )}
|
|
70
|
+
* </div>
|
|
71
|
+
* )}
|
|
72
|
+
* </div>
|
|
73
|
+
* )}
|
|
74
|
+
* </ProductModifiers.Modifiers>
|
|
75
|
+
* </div>
|
|
76
|
+
* </ProductModifiers.Root>
|
|
77
|
+
* );
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export function Root(props) {
|
|
82
|
+
return (_jsx(WixServices, { servicesMap: createServicesMap().addService(ProductModifiersServiceDefinition, ProductModifiersService, {}), children: props.children }));
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Custom hook to safely get the modifiers service
|
|
86
|
+
*/
|
|
87
|
+
function useModifiersService() {
|
|
88
|
+
try {
|
|
89
|
+
return useService(ProductModifiersServiceDefinition);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Headless component for all product modifiers
|
|
97
|
+
*
|
|
98
|
+
* @component
|
|
99
|
+
* @example
|
|
100
|
+
* ```tsx
|
|
101
|
+
* import { ProductModifiers } from '@wix/stores/components';
|
|
102
|
+
*
|
|
103
|
+
* function ModifiersSelector() {
|
|
104
|
+
* return (
|
|
105
|
+
* <ProductModifiers.Modifiers>
|
|
106
|
+
* {({ modifiers, hasModifiers, selectedModifiers, areAllRequiredModifiersFilled }) => (
|
|
107
|
+
* <div>
|
|
108
|
+
* {hasModifiers && (
|
|
109
|
+
* <div>
|
|
110
|
+
* <h3>Customize your product</h3>
|
|
111
|
+
* {modifiers.map(modifier => (
|
|
112
|
+
* <div key={modifier.id}>
|
|
113
|
+
* <label>{modifier.name}</label>
|
|
114
|
+
* {modifier.required && <span>*</span>}
|
|
115
|
+
* {modifier.choices?.map(choice => (
|
|
116
|
+
* <label key={choice.id}>
|
|
117
|
+
* <input
|
|
118
|
+
* type={modifier.multiple ? 'checkbox' : 'radio'}
|
|
119
|
+
* name={modifier.id}
|
|
120
|
+
* value={choice.id}
|
|
121
|
+
* checked={selectedModifiers[modifier.id] === choice.id}
|
|
122
|
+
* />
|
|
123
|
+
* {choice.description} (+{choice.priceChange?.price})
|
|
124
|
+
* </label>
|
|
125
|
+
* ))}
|
|
126
|
+
* </div>
|
|
127
|
+
* ))}
|
|
128
|
+
* {!areAllRequiredModifiersFilled && (
|
|
129
|
+
* <div className="warning">Please fill all required options</div>
|
|
130
|
+
* )}
|
|
131
|
+
* </div>
|
|
132
|
+
* )}
|
|
133
|
+
* </div>
|
|
134
|
+
* )}
|
|
135
|
+
* </ProductModifiers.Modifiers>
|
|
136
|
+
* );
|
|
137
|
+
* }
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export function Modifiers(props) {
|
|
141
|
+
const modifiersService = useModifiersService();
|
|
142
|
+
if (!modifiersService) {
|
|
143
|
+
return props.children({
|
|
144
|
+
modifiers: [],
|
|
145
|
+
hasModifiers: false,
|
|
146
|
+
selectedModifiers: {},
|
|
147
|
+
areAllRequiredModifiersFilled: true,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
const modifiers = modifiersService.modifiers.get();
|
|
151
|
+
const hasModifiers = modifiersService.hasModifiers.get();
|
|
152
|
+
const selectedModifiers = modifiersService.selectedModifiers.get();
|
|
153
|
+
const areAllRequiredModifiersFilled = modifiersService.areAllRequiredModifiersFilled();
|
|
154
|
+
return props.children({
|
|
155
|
+
modifiers,
|
|
156
|
+
hasModifiers,
|
|
157
|
+
selectedModifiers,
|
|
158
|
+
areAllRequiredModifiersFilled,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Headless component for a specific product modifier
|
|
163
|
+
*
|
|
164
|
+
* @component
|
|
165
|
+
* @example
|
|
166
|
+
* ```tsx
|
|
167
|
+
* import { ProductModifiers } from '@wix/stores/components';
|
|
168
|
+
*
|
|
169
|
+
* function ModifierField({ modifier }) {
|
|
170
|
+
* return (
|
|
171
|
+
* <ProductModifiers.Modifier modifier={modifier}>
|
|
172
|
+
* {({ name, mandatory, hasChoices, choices, selectedValue, isFreeText, placeholder, maxChars }) => (
|
|
173
|
+
* <div className="modifier-field">
|
|
174
|
+
* <label>
|
|
175
|
+
* {name} {mandatory && <span className="required">*</span>}
|
|
176
|
+
* </label>
|
|
177
|
+
* {hasChoices && (
|
|
178
|
+
* <div className="choices">
|
|
179
|
+
* {choices.map(choice => (
|
|
180
|
+
* <label key={choice.id}>
|
|
181
|
+
* <input
|
|
182
|
+
* type="radio"
|
|
183
|
+
* name={name}
|
|
184
|
+
* value={choice.name}
|
|
185
|
+
* checked={selectedValue?.choiceValue === choice.name}
|
|
186
|
+
* />
|
|
187
|
+
* {choice.description} (+{choice.priceChange?.price || '0'})
|
|
188
|
+
* </label>
|
|
189
|
+
* ))}
|
|
190
|
+
* </div>
|
|
191
|
+
* )}
|
|
192
|
+
* {isFreeText && (
|
|
193
|
+
* <input
|
|
194
|
+
* type="text"
|
|
195
|
+
* placeholder={placeholder}
|
|
196
|
+
* maxLength={maxChars}
|
|
197
|
+
* value={selectedValue?.freeTextValue || ''}
|
|
198
|
+
* />
|
|
199
|
+
* )}
|
|
200
|
+
* </div>
|
|
201
|
+
* )}
|
|
202
|
+
* </ProductModifiers.Modifier>
|
|
203
|
+
* );
|
|
204
|
+
* }
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
export function Modifier(props) {
|
|
208
|
+
const modifiersService = useModifiersService();
|
|
209
|
+
const { modifier } = props;
|
|
210
|
+
const name = modifier.name || '';
|
|
211
|
+
const type = modifier.modifierRenderType;
|
|
212
|
+
const mandatory = modifier.mandatory || false;
|
|
213
|
+
const choices = modifier.choicesSettings?.choices || [];
|
|
214
|
+
const hasChoices = choices.length > 0;
|
|
215
|
+
const isFreeText = type === ModifierRenderType.FREE_TEXT;
|
|
216
|
+
const freeTextSettings = modifier.freeTextSettings;
|
|
217
|
+
const maxChars = freeTextSettings?.maxLength;
|
|
218
|
+
const placeholder = freeTextSettings?.placeholder;
|
|
219
|
+
const selectedValue = modifiersService?.selectedModifiers.get()[name] || null;
|
|
220
|
+
return props.children({
|
|
221
|
+
name,
|
|
222
|
+
type,
|
|
223
|
+
mandatory,
|
|
224
|
+
choices,
|
|
225
|
+
selectedValue,
|
|
226
|
+
hasChoices,
|
|
227
|
+
isFreeText,
|
|
228
|
+
maxChars,
|
|
229
|
+
placeholder,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Headless component for individual modifier choice selection
|
|
234
|
+
*
|
|
235
|
+
* @component
|
|
236
|
+
* @example
|
|
237
|
+
* ```tsx
|
|
238
|
+
* import { ProductModifiers } from '@wix/stores/components';
|
|
239
|
+
*
|
|
240
|
+
* function ModifierChoiceButton({ modifier, choice }) {
|
|
241
|
+
* return (
|
|
242
|
+
* <ProductModifiers.Choice modifier={modifier} choice={choice}>
|
|
243
|
+
* {({ value, description, isSelected, select, colorCode }) => (
|
|
244
|
+
* <button
|
|
245
|
+
* onClick={select}
|
|
246
|
+
* className={`choice-button ${isSelected ? 'selected' : ''}`}
|
|
247
|
+
* style={colorCode ? { backgroundColor: colorCode } : {}}
|
|
248
|
+
* >
|
|
249
|
+
* {colorCode ? (
|
|
250
|
+
* <div className="color-swatch" title={value} />
|
|
251
|
+
* ) : (
|
|
252
|
+
* <span>{value}</span>
|
|
253
|
+
* )}
|
|
254
|
+
* {description && <span className="description">{description}</span>}
|
|
255
|
+
* </button>
|
|
256
|
+
* )}
|
|
257
|
+
* </ProductModifiers.Choice>
|
|
258
|
+
* );
|
|
259
|
+
* }
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
export function Choice(props) {
|
|
263
|
+
const modifiersService = useModifiersService();
|
|
264
|
+
const { modifier, choice } = props;
|
|
265
|
+
const modifierName = modifier.name || '';
|
|
266
|
+
const renderType = modifier.modifierRenderType;
|
|
267
|
+
// For TEXT_CHOICES, use choice.key; for SWATCH_CHOICES, use choice.name
|
|
268
|
+
const choiceValue = renderType === ModifierRenderType.TEXT_CHOICES
|
|
269
|
+
? choice.key || choice.name || ''
|
|
270
|
+
: choice.name || '';
|
|
271
|
+
const value = choice.name || ''; // Display name is always choice.name
|
|
272
|
+
const description = choice.description;
|
|
273
|
+
const colorCode = choice.colorCode;
|
|
274
|
+
const selectedValue = modifiersService?.getModifierValue(modifierName);
|
|
275
|
+
const isSelected = selectedValue?.choiceValue === choiceValue;
|
|
276
|
+
const select = () => {
|
|
277
|
+
modifiersService?.setModifierChoice(modifierName, choiceValue);
|
|
278
|
+
};
|
|
279
|
+
return props.children({
|
|
280
|
+
value,
|
|
281
|
+
description,
|
|
282
|
+
isSelected,
|
|
283
|
+
select,
|
|
284
|
+
modifierName,
|
|
285
|
+
choiceValue,
|
|
286
|
+
colorCode,
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Headless component for free text modifier input
|
|
291
|
+
*
|
|
292
|
+
* @component
|
|
293
|
+
* @example
|
|
294
|
+
* ```tsx
|
|
295
|
+
* import { ProductModifiers } from '@wix/stores/components';
|
|
296
|
+
*
|
|
297
|
+
* function FreeTextModifier({ modifier }) {
|
|
298
|
+
* return (
|
|
299
|
+
* <ProductModifiers.FreeText modifier={modifier}>
|
|
300
|
+
* {({ value, setText, mandatory, maxChars, placeholder, charCount, isOverLimit, modifierName }) => (
|
|
301
|
+
* <div className="free-text-modifier">
|
|
302
|
+
* <label>
|
|
303
|
+
* {modifierName} {mandatory && <span className="required">*</span>}
|
|
304
|
+
* </label>
|
|
305
|
+
* <textarea
|
|
306
|
+
* value={value}
|
|
307
|
+
* setText={(e) => setText(e.target.value)}
|
|
308
|
+
* placeholder={placeholder}
|
|
309
|
+
* maxLength={maxChars}
|
|
310
|
+
* className={isOverLimit ? 'over-limit' : ''}
|
|
311
|
+
* />
|
|
312
|
+
* {maxChars && (
|
|
313
|
+
* <div className={`char-count ${isOverLimit ? 'over-limit' : ''}`}>
|
|
314
|
+
* {charCount}/{maxChars}
|
|
315
|
+
* </div>
|
|
316
|
+
* )}
|
|
317
|
+
* </div>
|
|
318
|
+
* )}
|
|
319
|
+
* </ProductModifiers.FreeText>
|
|
320
|
+
* );
|
|
321
|
+
* }
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
export function FreeText(props) {
|
|
325
|
+
const modifiersService = useModifiersService();
|
|
326
|
+
const { modifier } = props;
|
|
327
|
+
const modifierName = modifier.name || '';
|
|
328
|
+
const mandatory = modifier.mandatory || false;
|
|
329
|
+
const freeTextSettings = modifier.freeTextSettings;
|
|
330
|
+
const maxChars = freeTextSettings?.maxLength;
|
|
331
|
+
const placeholder = freeTextSettings?.placeholder;
|
|
332
|
+
const selectedValue = modifiersService?.getModifierValue(modifierName);
|
|
333
|
+
const value = selectedValue?.freeTextValue || '';
|
|
334
|
+
const charCount = value.length;
|
|
335
|
+
const isOverLimit = maxChars ? charCount > maxChars : false;
|
|
336
|
+
const setText = (newValue) => {
|
|
337
|
+
if (maxChars && newValue.length > maxChars)
|
|
338
|
+
return;
|
|
339
|
+
modifiersService?.setModifierFreeText(modifierName, newValue);
|
|
340
|
+
};
|
|
341
|
+
return props.children({
|
|
342
|
+
value,
|
|
343
|
+
setText,
|
|
344
|
+
mandatory,
|
|
345
|
+
maxChars,
|
|
346
|
+
placeholder,
|
|
347
|
+
charCount,
|
|
348
|
+
isOverLimit,
|
|
349
|
+
modifierName,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Headless component for toggling free text modifier input
|
|
354
|
+
* Used for optional free text modifiers where a checkbox shows/hides the input
|
|
355
|
+
*
|
|
356
|
+
* @component
|
|
357
|
+
* @example
|
|
358
|
+
* ```tsx
|
|
359
|
+
* import { ProductModifiers } from '@wix/stores/components';
|
|
360
|
+
*
|
|
361
|
+
* function ToggleFreeTextModifier({ modifier }) {
|
|
362
|
+
* return (
|
|
363
|
+
* <ProductModifiers.ToggleFreeText modifier={modifier}>
|
|
364
|
+
* {({ isTextInputShown, toggle, mandatory, modifierName }) => (
|
|
365
|
+
* <div className="toggle-free-text">
|
|
366
|
+
* {!mandatory && (
|
|
367
|
+
* <label>
|
|
368
|
+
* <input
|
|
369
|
+
* type="checkbox"
|
|
370
|
+
* checked={isTextInputShown}
|
|
371
|
+
* onChange={toggle}
|
|
372
|
+
* />
|
|
373
|
+
* Add {modifierName}
|
|
374
|
+
* </label>
|
|
375
|
+
* )}
|
|
376
|
+
* {isTextInputShown && (
|
|
377
|
+
* <ProductModifiers.FreeText modifier={modifier}>
|
|
378
|
+
* {(props) => (
|
|
379
|
+
* <textarea
|
|
380
|
+
* value={props.value}
|
|
381
|
+
* onChange={(e) => props.onChange(e.target.value)}
|
|
382
|
+
* placeholder={props.placeholder}
|
|
383
|
+
* />
|
|
384
|
+
* )}
|
|
385
|
+
* </ProductModifiers.FreeText>
|
|
386
|
+
* )}
|
|
387
|
+
* </div>
|
|
388
|
+
* )}
|
|
389
|
+
* </ProductModifiers.ToggleFreeText>
|
|
390
|
+
* );
|
|
391
|
+
* }
|
|
392
|
+
* ```
|
|
393
|
+
*/
|
|
394
|
+
export function ToggleFreeText(props) {
|
|
395
|
+
const modifiersService = useModifiersService();
|
|
396
|
+
const { modifier } = props;
|
|
397
|
+
const modifierName = modifier.name || '';
|
|
398
|
+
const mandatory = modifier.mandatory || false;
|
|
399
|
+
const [isTextInputShown, setIsTextInputShown] = useState(mandatory);
|
|
400
|
+
const toggle = () => {
|
|
401
|
+
const newState = !isTextInputShown;
|
|
402
|
+
setIsTextInputShown(newState);
|
|
403
|
+
if (!newState) {
|
|
404
|
+
modifiersService?.clearModifier(modifierName);
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
return props.children({
|
|
408
|
+
isTextInputShown,
|
|
409
|
+
toggle,
|
|
410
|
+
mandatory,
|
|
411
|
+
modifierName,
|
|
412
|
+
});
|
|
413
|
+
}
|