@plusscommunities/pluss-feature-builder-web-a 1.0.2-beta.5 → 1.0.2-beta.7
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/dist/index.cjs.js +827 -828
- package/package.json +1 -1
- package/src/actions/featureDefinitionsIndex.js +2 -3
- package/src/actions/formActions.js +148 -158
- package/src/actions/listingActions.js +1 -1
- package/src/actions/wizardActions.js +169 -184
- package/src/components/BaseFieldConfig.jsx +234 -234
- package/src/components/IconLoader.jsx +138 -138
- package/src/components/IconSelector.jsx +0 -1
- package/src/components/ListingEditor.jsx +0 -1
- package/src/components/SidebarLayout.jsx +4 -1
- package/src/components/index.js +0 -2
- package/src/components/listing/GalleryDisplay.jsx +0 -1
- package/src/components/listing/ListingGalleryInput.jsx +4 -1
- package/src/index.js +6 -6
- package/src/reducers/featureBuilderReducer.js +14 -25
- package/src/screens/FormLayoutStep.jsx +10 -13
- package/src/screens/FormOverviewStep.jsx +351 -358
- package/src/screens/ListingScreen.jsx +0 -1
- package/src/selectors/featureBuilderSelectors.js +49 -44
|
@@ -52,254 +52,254 @@ import styles from "./BaseFieldConfig.module.css";
|
|
|
52
52
|
* />
|
|
53
53
|
*/
|
|
54
54
|
export const BaseFieldConfig = (props) => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
55
|
+
const {
|
|
56
|
+
label,
|
|
57
|
+
placeholder,
|
|
58
|
+
allowCaption,
|
|
59
|
+
helpText,
|
|
60
|
+
isRequired,
|
|
61
|
+
minImages,
|
|
62
|
+
maxImages,
|
|
63
|
+
maxFileSize,
|
|
64
|
+
allowedTypes,
|
|
65
|
+
setLabel,
|
|
66
|
+
setPlaceholder,
|
|
67
|
+
setAllowCaption,
|
|
68
|
+
setHelpText,
|
|
69
|
+
toggleIsRequired,
|
|
70
|
+
toggleAllowCaption,
|
|
71
|
+
setMinImages,
|
|
72
|
+
setMaxImages,
|
|
73
|
+
setMaxFileSize,
|
|
74
|
+
setAllowedTypes,
|
|
75
|
+
stepErrors,
|
|
76
|
+
showWarnings,
|
|
77
|
+
id,
|
|
78
|
+
fieldType,
|
|
79
|
+
customLabel,
|
|
80
|
+
useAsSummary, // For description fields
|
|
81
|
+
setUseAsSummary, // For description fields
|
|
82
|
+
children, // For field-specific options
|
|
83
|
+
} = props;
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
// Determine if placeholder should be shown
|
|
86
|
+
const showPlaceholder =
|
|
87
|
+
fieldType !== "image" &&
|
|
88
|
+
fieldType !== "gallery" &&
|
|
89
|
+
fieldType !== "feature-image" &&
|
|
90
|
+
fieldType !== "file";
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
// Determine if caption option should be shown
|
|
93
|
+
const showCaptionOption = fieldType === "image";
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
// Determine if use as summary option should be shown
|
|
96
|
+
const showUseAsSummaryOption = fieldType === "description";
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
98
|
+
// Determine if required checkbox should be shown as disabled
|
|
99
|
+
const isRequiredFieldAlwaysRequired =
|
|
100
|
+
fieldType === "text" ||
|
|
101
|
+
fieldType === "feature-image" ||
|
|
102
|
+
fieldType === "title";
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
// Determine if required checkbox should be hidden entirely
|
|
105
|
+
const hideRequiredField = fieldType === "gallery";
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
107
|
+
return (
|
|
108
|
+
<div>
|
|
109
|
+
<div>
|
|
110
|
+
{/* Basic inputs - always visible */}
|
|
111
|
+
<TwoColumnInput
|
|
112
|
+
left={
|
|
113
|
+
<GenericInput
|
|
114
|
+
type="text"
|
|
115
|
+
placeholder="Type your label here (required)"
|
|
116
|
+
value={label}
|
|
117
|
+
label={customLabel || "Label"}
|
|
118
|
+
isRequired
|
|
119
|
+
onChange={(e) => setLabel && setLabel(e.target.value)}
|
|
120
|
+
showError={() => {
|
|
121
|
+
const hasWarning = showWarnings && stepErrors && stepErrors[id];
|
|
122
|
+
return hasWarning;
|
|
123
|
+
}}
|
|
124
|
+
errorMessage={
|
|
125
|
+
stepErrors && stepErrors[id]
|
|
126
|
+
? stepErrors[id]
|
|
127
|
+
: "Field label is required"
|
|
128
|
+
}
|
|
129
|
+
isValid={() => {
|
|
130
|
+
const isValid = !(stepErrors && stepErrors[id]);
|
|
131
|
+
return isValid;
|
|
132
|
+
}}
|
|
133
|
+
alwaysShowLabel
|
|
134
|
+
/>
|
|
135
|
+
}
|
|
136
|
+
right={
|
|
137
|
+
showPlaceholder && (
|
|
138
|
+
<GenericInput
|
|
139
|
+
type="text"
|
|
140
|
+
value={placeholder}
|
|
141
|
+
placeholder={"Add a placeholder (optional)"}
|
|
142
|
+
label={"Placeholder"}
|
|
143
|
+
onChange={(e) =>
|
|
144
|
+
setPlaceholder && setPlaceholder(e.target.value)
|
|
145
|
+
}
|
|
146
|
+
alwaysShowLabel
|
|
147
|
+
/>
|
|
148
|
+
)
|
|
149
|
+
}
|
|
150
|
+
/>
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
152
|
+
{/* Help Text - Always visible for better accessibility */}
|
|
153
|
+
{helpText !== undefined && (
|
|
154
|
+
<GenericInput
|
|
155
|
+
key={`helpText-${id || "unknown"}`}
|
|
156
|
+
type="text"
|
|
157
|
+
value={helpText || ""}
|
|
158
|
+
placeholder={"Add help text (optional)"}
|
|
159
|
+
label={"Help Text"}
|
|
160
|
+
onChange={(e) => {
|
|
161
|
+
if (setHelpText) {
|
|
162
|
+
setHelpText(e.target.value);
|
|
163
|
+
}
|
|
164
|
+
}}
|
|
165
|
+
className={styles.fieldSpacing}
|
|
166
|
+
alwaysShowLabel
|
|
167
|
+
/>
|
|
168
|
+
)}
|
|
169
169
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
170
|
+
{/* Required Field Setting - Hidden for gallery fields */}
|
|
171
|
+
{toggleIsRequired &&
|
|
172
|
+
!isRequiredFieldAlwaysRequired &&
|
|
173
|
+
!hideRequiredField && (
|
|
174
|
+
<CheckBox
|
|
175
|
+
label="Required field"
|
|
176
|
+
isActive={isRequired}
|
|
177
|
+
onChange={toggleIsRequired}
|
|
178
|
+
className={styles.fieldSpacing}
|
|
179
|
+
/>
|
|
180
|
+
)}
|
|
181
181
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
182
|
+
{/* Show disabled required checkbox for fields that are always required */}
|
|
183
|
+
{isRequiredFieldAlwaysRequired && !hideRequiredField && (
|
|
184
|
+
<CheckBox
|
|
185
|
+
label="Required field"
|
|
186
|
+
isActive={true}
|
|
187
|
+
onChange={() => {}}
|
|
188
|
+
disabled={true}
|
|
189
|
+
className={styles.fieldSpacing}
|
|
190
|
+
/>
|
|
191
|
+
)}
|
|
192
192
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
193
|
+
{/* Advanced options - always visible */}
|
|
194
|
+
{/* Use as Summary Option - Show for description fields */}
|
|
195
|
+
{showUseAsSummaryOption && (
|
|
196
|
+
<div className={styles.checkboxContainer}>
|
|
197
|
+
<CheckBox
|
|
198
|
+
label="Show as preview text"
|
|
199
|
+
isActive={useAsSummary}
|
|
200
|
+
onChange={() => setUseAsSummary(!useAsSummary)}
|
|
201
|
+
/>
|
|
202
|
+
<Text type="bodySmall" className={styles.helpText}>
|
|
203
|
+
Display this description as a short preview under the title in
|
|
204
|
+
listings. Only one description can be used as preview.
|
|
205
|
+
</Text>
|
|
206
|
+
</div>
|
|
207
|
+
)}
|
|
208
208
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
209
|
+
{/* Caption Option - Show for image fields */}
|
|
210
|
+
{showCaptionOption && (
|
|
211
|
+
<div className={styles.checkboxContainer}>
|
|
212
|
+
<CheckBox
|
|
213
|
+
label="Allow users to add caption to image"
|
|
214
|
+
isActive={allowCaption}
|
|
215
|
+
onChange={toggleAllowCaption || setAllowCaption}
|
|
216
|
+
/>
|
|
217
|
+
<Text type="bodySmall" className={styles.helpText}>
|
|
218
|
+
When checked, users uploading an image can add a short description
|
|
219
|
+
to explain what the image shows.
|
|
220
|
+
</Text>
|
|
221
|
+
</div>
|
|
222
|
+
)}
|
|
223
223
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
224
|
+
{/* Field-specific options */}
|
|
225
|
+
{fieldType === "gallery" && (
|
|
226
|
+
<>
|
|
227
|
+
{/* Minimum Images */}
|
|
228
|
+
{setMinImages && (
|
|
229
|
+
<GenericInput
|
|
230
|
+
type="number"
|
|
231
|
+
value={minImages || 1}
|
|
232
|
+
placeholder="1"
|
|
233
|
+
label="Minimum Images"
|
|
234
|
+
onChange={(e) => setMinImages(parseInt(e.target.value) || 1)}
|
|
235
|
+
className={styles.fieldSpacing}
|
|
236
|
+
alwaysShowLabel
|
|
237
|
+
/>
|
|
238
|
+
)}
|
|
239
239
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
240
|
+
{/* Maximum Images */}
|
|
241
|
+
{setMaxImages && (
|
|
242
|
+
<GenericInput
|
|
243
|
+
type="number"
|
|
244
|
+
value={maxImages || 10}
|
|
245
|
+
placeholder="10"
|
|
246
|
+
label="Maximum Images"
|
|
247
|
+
onChange={(e) => setMaxImages(parseInt(e.target.value) || 10)}
|
|
248
|
+
className={styles.fieldSpacing}
|
|
249
|
+
alwaysShowLabel
|
|
250
|
+
/>
|
|
251
|
+
)}
|
|
252
252
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
253
|
+
{/* Maximum File Size */}
|
|
254
|
+
{setMaxFileSize && (
|
|
255
|
+
<GenericInput
|
|
256
|
+
type="text"
|
|
257
|
+
value={maxFileSize || "5MB"}
|
|
258
|
+
placeholder="5MB"
|
|
259
|
+
label="Maximum File Size"
|
|
260
|
+
onChange={(e) => setMaxFileSize(e.target.value)}
|
|
261
|
+
className={styles.fieldSpacing}
|
|
262
|
+
alwaysShowLabel
|
|
263
|
+
/>
|
|
264
|
+
)}
|
|
265
265
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
266
|
+
{/* Allowed File Types */}
|
|
267
|
+
{setAllowedTypes && (
|
|
268
|
+
<div className={styles.fileTypesContainer}>
|
|
269
|
+
<Text type="formLabel" className={styles.formLabel}>
|
|
270
|
+
Allowed File Types
|
|
271
|
+
</Text>
|
|
272
|
+
<div className={styles.fileTypesList}>
|
|
273
|
+
{["image/jpeg", "image/png", "image/webp"].map((type) => (
|
|
274
|
+
<CheckBox
|
|
275
|
+
key={type}
|
|
276
|
+
label={type.replace("image/", "").toUpperCase()}
|
|
277
|
+
isActive={allowedTypes?.includes(type) || false}
|
|
278
|
+
onChange={() => {
|
|
279
|
+
const currentTypes = allowedTypes || [];
|
|
280
|
+
const newTypes = currentTypes.includes(type)
|
|
281
|
+
? currentTypes.filter((t) => t !== type)
|
|
282
|
+
: [...currentTypes, type];
|
|
283
|
+
setAllowedTypes(newTypes);
|
|
284
|
+
}}
|
|
285
|
+
className={styles.checkboxWithMargin}
|
|
286
|
+
/>
|
|
287
|
+
))}
|
|
288
|
+
</div>
|
|
289
|
+
</div>
|
|
290
|
+
)}
|
|
291
291
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
292
|
+
{/* Gallery Help Text */}
|
|
293
|
+
<Text
|
|
294
|
+
type="bodySmall"
|
|
295
|
+
className={`${styles.helpText} ${styles.fieldSpacing}`}
|
|
296
|
+
>
|
|
297
|
+
Gallery field for displaying multiple images.
|
|
298
|
+
</Text>
|
|
299
|
+
</>
|
|
300
|
+
)}
|
|
301
|
+
{children}
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
304
|
+
);
|
|
305
305
|
};
|