@surveystudio/node-registery 1.0.2 → 1.2.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 +13 -1
- package/dist/builder.d.mts +269 -5
- package/dist/builder.mjs +152 -1
- package/dist/{coreTypes-D-1hYIe5.d.mts → coreTypes-CyFAym5A.d.mts} +1 -1
- package/dist/logic.d.mts +105 -39
- package/dist/logic.mjs +665 -1
- package/dist/runner.d.mts +40 -3
- package/dist/runner.mjs +21 -1
- package/dist/{types-BpvjaHAP.d.mts → types-4zXsOMLb.d.mts} +3 -3
- package/dist/types-BMnck1ag.d.mts +59 -0
- package/package.json +1 -1
- package/dist/types-D78Zx0gX.d.mts +0 -18
package/dist/logic.mjs
CHANGED
|
@@ -67,13 +67,677 @@ var plainTextLogic = {
|
|
|
67
67
|
]
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
+
// src/nodes/scale/manifest.ts
|
|
71
|
+
var defaultCondition = {
|
|
72
|
+
id: "root",
|
|
73
|
+
type: "group",
|
|
74
|
+
logicType: "AND",
|
|
75
|
+
children: []
|
|
76
|
+
};
|
|
77
|
+
var baseScaleData = {
|
|
78
|
+
label: "",
|
|
79
|
+
description: "",
|
|
80
|
+
condition: defaultCondition,
|
|
81
|
+
responseMode: "single",
|
|
82
|
+
items: []
|
|
83
|
+
};
|
|
84
|
+
var responseModeProperty = {
|
|
85
|
+
name: "responseMode",
|
|
86
|
+
label: "Response Mode",
|
|
87
|
+
type: "select",
|
|
88
|
+
defaultValue: "single",
|
|
89
|
+
options: [
|
|
90
|
+
{ label: "Single Question", value: "single" },
|
|
91
|
+
{ label: "Multiple Items", value: "multi" }
|
|
92
|
+
]
|
|
93
|
+
};
|
|
94
|
+
var commonProperties = [
|
|
95
|
+
responseModeProperty,
|
|
96
|
+
{ name: "label", label: "Question Label", type: "text" },
|
|
97
|
+
{ name: "description", label: "Description", type: "textarea" },
|
|
98
|
+
{
|
|
99
|
+
name: "condition",
|
|
100
|
+
label: "Logic Rule",
|
|
101
|
+
type: "condition",
|
|
102
|
+
defaultValue: defaultCondition
|
|
103
|
+
},
|
|
104
|
+
{ name: "items", label: "Items", type: "options", defaultValue: [] }
|
|
105
|
+
];
|
|
106
|
+
var ratingDefaultData = {
|
|
107
|
+
...baseScaleData,
|
|
108
|
+
label: "Rating",
|
|
109
|
+
maxRating: 5
|
|
110
|
+
};
|
|
111
|
+
var sliderDefaultData = {
|
|
112
|
+
...baseScaleData,
|
|
113
|
+
label: "Slider / Scale",
|
|
114
|
+
min: 0,
|
|
115
|
+
max: 10,
|
|
116
|
+
step: 1,
|
|
117
|
+
startValue: 5
|
|
118
|
+
};
|
|
119
|
+
var ratingManifest = {
|
|
120
|
+
type: "rating",
|
|
121
|
+
label: "Rating",
|
|
122
|
+
description: "Star rating scale",
|
|
123
|
+
category: "choice",
|
|
124
|
+
dataType: "number",
|
|
125
|
+
defaultData: ratingDefaultData,
|
|
126
|
+
properties: [
|
|
127
|
+
...commonProperties,
|
|
128
|
+
{ name: "maxRating", label: "Max Stars", type: "number", defaultValue: 5 }
|
|
129
|
+
]
|
|
130
|
+
};
|
|
131
|
+
var sliderManifest = {
|
|
132
|
+
type: "slider",
|
|
133
|
+
label: "Slider / Scale",
|
|
134
|
+
description: "Single or multi-item scale",
|
|
135
|
+
category: "choice",
|
|
136
|
+
dataType: "number",
|
|
137
|
+
defaultData: sliderDefaultData,
|
|
138
|
+
properties: [
|
|
139
|
+
...commonProperties,
|
|
140
|
+
{ name: "min", label: "Minimum", type: "number", defaultValue: 0 },
|
|
141
|
+
{ name: "max", label: "Maximum", type: "number", defaultValue: 10 },
|
|
142
|
+
{ name: "step", label: "Step", type: "number", defaultValue: 1, min: 0 },
|
|
143
|
+
{ name: "startValue", label: "Start Value", type: "number", defaultValue: 5 }
|
|
144
|
+
]
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// src/nodes/scale/logic.ts
|
|
148
|
+
var isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
149
|
+
var numberValue = (value) => {
|
|
150
|
+
const parsed = Number(value);
|
|
151
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
152
|
+
};
|
|
153
|
+
var positiveNumber = (value) => {
|
|
154
|
+
const parsed = Number(value);
|
|
155
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
|
|
156
|
+
};
|
|
157
|
+
var itemsFor = (nodeData) => Array.isArray(nodeData.items) ? nodeData.items : [];
|
|
158
|
+
var inferMode = (nodeData) => {
|
|
159
|
+
if (nodeData.responseMode === "single" || nodeData.responseMode === "multi") return nodeData.responseMode;
|
|
160
|
+
return itemsFor(nodeData).length > 0 ? "multi" : "single";
|
|
161
|
+
};
|
|
162
|
+
var itemKey = (item) => item.exportId || item.technicalId || item.value || item.id;
|
|
163
|
+
var itemLabel = (item, fallback) => item.label || fallback;
|
|
164
|
+
var firstItemKey = (nodeData) => {
|
|
165
|
+
const firstItem = itemsFor(nodeData)[0];
|
|
166
|
+
return firstItem ? itemKey(firstItem) : void 0;
|
|
167
|
+
};
|
|
168
|
+
var normalizeScaleValue = (rawValue, nodeData) => {
|
|
169
|
+
const mode = inferMode(nodeData);
|
|
170
|
+
if (mode === "multi") {
|
|
171
|
+
if (isRecord(rawValue)) {
|
|
172
|
+
return Object.fromEntries(Object.entries(rawValue).map(([key2, value]) => [key2, numberValue(value)]));
|
|
173
|
+
}
|
|
174
|
+
const key = firstItemKey(nodeData);
|
|
175
|
+
if (key) return { [key]: numberValue(rawValue) };
|
|
176
|
+
}
|
|
177
|
+
return numberValue(rawValue);
|
|
178
|
+
};
|
|
179
|
+
var validateFiniteScale = (value) => {
|
|
180
|
+
if (typeof value === "number") return Number.isFinite(value) ? { valid: true } : { valid: false, error: "Please enter a valid number" };
|
|
181
|
+
const invalidKey = Object.entries(value).find(([, itemValue]) => !Number.isFinite(itemValue))?.[0];
|
|
182
|
+
return invalidKey ? { valid: false, error: `${invalidKey}: Please enter a valid number` } : { valid: true };
|
|
183
|
+
};
|
|
184
|
+
var validateRatingValue = (value, nodeData) => {
|
|
185
|
+
const finiteResult = validateFiniteScale(value);
|
|
186
|
+
if (!finiteResult.valid) return finiteResult;
|
|
187
|
+
const maxRating = positiveNumber(nodeData.maxRating) || 5;
|
|
188
|
+
const values = typeof value === "number" ? [value] : Object.values(value);
|
|
189
|
+
const outOfRange = values.find((itemValue) => itemValue < 1 || itemValue > maxRating);
|
|
190
|
+
return typeof outOfRange === "number" ? { valid: false, error: `Rating must be between 1 and ${maxRating}` } : { valid: true };
|
|
191
|
+
};
|
|
192
|
+
var validateSliderValue = (value, nodeData) => {
|
|
193
|
+
const finiteResult = validateFiniteScale(value);
|
|
194
|
+
if (!finiteResult.valid) return finiteResult;
|
|
195
|
+
const min = numberValue(nodeData.min);
|
|
196
|
+
const max = Number.isFinite(Number(nodeData.max)) ? Number(nodeData.max) : 10;
|
|
197
|
+
const values = typeof value === "number" ? [value] : Object.values(value);
|
|
198
|
+
const outOfRange = values.find((itemValue) => itemValue < min || itemValue > max);
|
|
199
|
+
return typeof outOfRange === "number" ? { valid: false, error: `Value must be between ${min} and ${max}` } : { valid: true };
|
|
200
|
+
};
|
|
201
|
+
var extractScaleValue = (value, nodeData) => {
|
|
202
|
+
const mode = inferMode(nodeData);
|
|
203
|
+
if (mode === "multi" && isRecord(value)) {
|
|
204
|
+
const items = itemsFor(nodeData);
|
|
205
|
+
return Object.entries(value).map(([key, itemValue]) => {
|
|
206
|
+
const item = items.find((candidate) => itemKey(candidate) === key);
|
|
207
|
+
return {
|
|
208
|
+
columnKey: key,
|
|
209
|
+
columnLabel: item ? itemLabel(item, key) : key,
|
|
210
|
+
numberValue: itemValue,
|
|
211
|
+
textValue: String(itemValue)
|
|
212
|
+
};
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
const scalarValue = typeof value === "number" ? value : 0;
|
|
216
|
+
return [{ numberValue: scalarValue, textValue: String(scalarValue) }];
|
|
217
|
+
};
|
|
218
|
+
var ratingLogic = {
|
|
219
|
+
type: "rating",
|
|
220
|
+
dataType: "number",
|
|
221
|
+
defaultData: ratingDefaultData,
|
|
222
|
+
defaultValue: 0,
|
|
223
|
+
normalizeValue: normalizeScaleValue,
|
|
224
|
+
validate: validateRatingValue,
|
|
225
|
+
extractValue: extractScaleValue
|
|
226
|
+
};
|
|
227
|
+
var sliderLogic = {
|
|
228
|
+
type: "slider",
|
|
229
|
+
dataType: "number",
|
|
230
|
+
defaultData: sliderDefaultData,
|
|
231
|
+
defaultValue: 0,
|
|
232
|
+
normalizeValue: normalizeScaleValue,
|
|
233
|
+
validate: validateSliderValue,
|
|
234
|
+
extractValue: extractScaleValue
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// src/nodes/choice/manifest.ts
|
|
238
|
+
var defaultCondition2 = {
|
|
239
|
+
id: "root",
|
|
240
|
+
type: "group",
|
|
241
|
+
logicType: "AND",
|
|
242
|
+
children: []
|
|
243
|
+
};
|
|
244
|
+
var baseChoiceData = {
|
|
245
|
+
label: "",
|
|
246
|
+
description: "",
|
|
247
|
+
condition: defaultCondition2,
|
|
248
|
+
options: [],
|
|
249
|
+
randomizeOptions: false
|
|
250
|
+
};
|
|
251
|
+
var commonProperties2 = [
|
|
252
|
+
{ name: "label", label: "Question Label", type: "text" },
|
|
253
|
+
{ name: "description", label: "Description", type: "textarea" },
|
|
254
|
+
{
|
|
255
|
+
name: "condition",
|
|
256
|
+
label: "Logic Rule",
|
|
257
|
+
type: "condition",
|
|
258
|
+
defaultValue: defaultCondition2
|
|
259
|
+
},
|
|
260
|
+
{ name: "options", label: "Options", type: "options", defaultValue: [] },
|
|
261
|
+
{ name: "bulkOptions", label: "Bulk Add (one per line)", type: "textarea", placeholder: "Option A\nOption B\nOption C..." }
|
|
262
|
+
];
|
|
263
|
+
var singleChoiceDefaultData = {
|
|
264
|
+
...baseChoiceData,
|
|
265
|
+
label: "Single Choice",
|
|
266
|
+
allowOther: false,
|
|
267
|
+
otherLabel: "Other"
|
|
268
|
+
};
|
|
269
|
+
var dropdownDefaultData = {
|
|
270
|
+
...baseChoiceData,
|
|
271
|
+
label: "Dropdown",
|
|
272
|
+
searchable: true
|
|
273
|
+
};
|
|
274
|
+
var multipleChoiceDefaultData = {
|
|
275
|
+
...baseChoiceData,
|
|
276
|
+
label: "Multiple Choice",
|
|
277
|
+
minChoices: 0,
|
|
278
|
+
maxChoices: 0
|
|
279
|
+
};
|
|
280
|
+
var rankingDefaultData = {
|
|
281
|
+
...baseChoiceData,
|
|
282
|
+
label: "Ranking",
|
|
283
|
+
maxRank: 0,
|
|
284
|
+
displayMode: "drag"
|
|
285
|
+
};
|
|
286
|
+
var singleChoiceManifest = {
|
|
287
|
+
type: "singleChoice",
|
|
288
|
+
label: "Single Choice",
|
|
289
|
+
description: "Select one option",
|
|
290
|
+
category: "choice",
|
|
291
|
+
dataType: "option",
|
|
292
|
+
defaultData: singleChoiceDefaultData,
|
|
293
|
+
properties: [
|
|
294
|
+
...commonProperties2,
|
|
295
|
+
{ name: "allowOther", label: "Allow Other", type: "switch", defaultValue: false },
|
|
296
|
+
{ name: "otherLabel", label: "Other Label", type: "text", defaultValue: "Other" },
|
|
297
|
+
{ name: "randomizeOptions", label: "Randomize Options", type: "switch", defaultValue: false }
|
|
298
|
+
]
|
|
299
|
+
};
|
|
300
|
+
var dropdownManifest = {
|
|
301
|
+
type: "dropdown",
|
|
302
|
+
label: "Dropdown",
|
|
303
|
+
description: "Select from a dropdown menu",
|
|
304
|
+
category: "choice",
|
|
305
|
+
dataType: "option",
|
|
306
|
+
defaultData: dropdownDefaultData,
|
|
307
|
+
properties: [
|
|
308
|
+
...commonProperties2,
|
|
309
|
+
{ name: "searchable", label: "Searchable", type: "switch", defaultValue: true }
|
|
310
|
+
]
|
|
311
|
+
};
|
|
312
|
+
var multipleChoiceManifest = {
|
|
313
|
+
type: "multipleChoice",
|
|
314
|
+
label: "Multiple Choice",
|
|
315
|
+
description: "Select multiple options",
|
|
316
|
+
category: "choice",
|
|
317
|
+
dataType: "array",
|
|
318
|
+
defaultData: multipleChoiceDefaultData,
|
|
319
|
+
properties: [
|
|
320
|
+
...commonProperties2,
|
|
321
|
+
{ name: "minChoices", label: "Minimum Choices", type: "number", defaultValue: 0 },
|
|
322
|
+
{ name: "maxChoices", label: "Maximum Choices", type: "number", defaultValue: 0 },
|
|
323
|
+
{ name: "randomizeOptions", label: "Randomize Options", type: "switch", defaultValue: false }
|
|
324
|
+
]
|
|
325
|
+
};
|
|
326
|
+
var rankingManifest = {
|
|
327
|
+
type: "ranking",
|
|
328
|
+
label: "Ranking",
|
|
329
|
+
description: "Rank options in order",
|
|
330
|
+
category: "choice",
|
|
331
|
+
dataType: "array",
|
|
332
|
+
defaultData: rankingDefaultData,
|
|
333
|
+
properties: [
|
|
334
|
+
...commonProperties2,
|
|
335
|
+
{ name: "maxRank", label: "Maximum Rank", type: "number", defaultValue: 0 },
|
|
336
|
+
{
|
|
337
|
+
name: "displayMode",
|
|
338
|
+
label: "Display Mode",
|
|
339
|
+
type: "select",
|
|
340
|
+
defaultValue: "drag",
|
|
341
|
+
options: [
|
|
342
|
+
{ label: "Drag and Drop", value: "drag" },
|
|
343
|
+
{ label: "Dropdown Selection", value: "select" }
|
|
344
|
+
]
|
|
345
|
+
}
|
|
346
|
+
]
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
// src/nodes/choice/logic.ts
|
|
350
|
+
var normalizeChoiceValue = (value) => {
|
|
351
|
+
if (typeof value === "string") return value;
|
|
352
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
353
|
+
return "";
|
|
354
|
+
};
|
|
355
|
+
var normalizeChoiceArray = (value) => {
|
|
356
|
+
if (!Array.isArray(value)) return [];
|
|
357
|
+
return value.map(normalizeChoiceValue).filter(Boolean);
|
|
358
|
+
};
|
|
359
|
+
var positiveNumber2 = (value) => {
|
|
360
|
+
const parsed = Number(value);
|
|
361
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
|
|
362
|
+
};
|
|
363
|
+
var optionsFor = (nodeData) => Array.isArray(nodeData.options) ? nodeData.options : [];
|
|
364
|
+
var optionForValue = (nodeData, value) => optionsFor(nodeData).find((option) => option.value === value || option.id === value);
|
|
365
|
+
var optionLabel = (nodeData, value) => optionForValue(nodeData, value)?.label || value;
|
|
366
|
+
var optionUuid = (nodeData, value) => optionForValue(nodeData, value)?.value || value;
|
|
367
|
+
var validateOptionExists = (value, nodeData) => {
|
|
368
|
+
if (!value) return { valid: true };
|
|
369
|
+
if (optionsFor(nodeData).length === 0) return { valid: true };
|
|
370
|
+
return optionForValue(nodeData, value) ? { valid: true } : { valid: false, error: "Selected option is not available" };
|
|
371
|
+
};
|
|
372
|
+
var validateOptionArray = (value, nodeData) => {
|
|
373
|
+
if (optionsFor(nodeData).length === 0) return { valid: true };
|
|
374
|
+
const invalid = value.find((item) => !optionForValue(nodeData, item));
|
|
375
|
+
return invalid ? { valid: false, error: "Selected option is not available" } : { valid: true };
|
|
376
|
+
};
|
|
377
|
+
var extractSingleChoiceValue = (value, nodeData) => [
|
|
378
|
+
{
|
|
379
|
+
optionUuid: optionUuid(nodeData, value),
|
|
380
|
+
optionText: optionLabel(nodeData, value),
|
|
381
|
+
textValue: optionLabel(nodeData, value)
|
|
382
|
+
}
|
|
383
|
+
];
|
|
384
|
+
var singleChoiceLogic = {
|
|
385
|
+
type: "singleChoice",
|
|
386
|
+
dataType: "option",
|
|
387
|
+
defaultData: singleChoiceDefaultData,
|
|
388
|
+
defaultValue: "",
|
|
389
|
+
normalizeValue: normalizeChoiceValue,
|
|
390
|
+
validate: validateOptionExists,
|
|
391
|
+
extractValue: extractSingleChoiceValue
|
|
392
|
+
};
|
|
393
|
+
var dropdownLogic = {
|
|
394
|
+
type: "dropdown",
|
|
395
|
+
dataType: "option",
|
|
396
|
+
defaultData: dropdownDefaultData,
|
|
397
|
+
defaultValue: "",
|
|
398
|
+
normalizeValue: normalizeChoiceValue,
|
|
399
|
+
validate: validateOptionExists,
|
|
400
|
+
extractValue: extractSingleChoiceValue
|
|
401
|
+
};
|
|
402
|
+
var multipleChoiceLogic = {
|
|
403
|
+
type: "multipleChoice",
|
|
404
|
+
dataType: "array",
|
|
405
|
+
defaultData: multipleChoiceDefaultData,
|
|
406
|
+
defaultValue: [],
|
|
407
|
+
normalizeValue: normalizeChoiceArray,
|
|
408
|
+
validate: (value, nodeData) => {
|
|
409
|
+
const optionResult = validateOptionArray(value, nodeData);
|
|
410
|
+
if (!optionResult.valid) return optionResult;
|
|
411
|
+
const minChoices = positiveNumber2(nodeData.minChoices);
|
|
412
|
+
const maxChoices = positiveNumber2(nodeData.maxChoices);
|
|
413
|
+
if (minChoices && value.length < minChoices) return { valid: false, error: `Select at least ${minChoices} option(s)` };
|
|
414
|
+
if (maxChoices && value.length > maxChoices) return { valid: false, error: `Select at most ${maxChoices} option(s)` };
|
|
415
|
+
return { valid: true };
|
|
416
|
+
},
|
|
417
|
+
extractValue: (value, nodeData) => value.map((item) => ({
|
|
418
|
+
optionUuid: optionUuid(nodeData, item),
|
|
419
|
+
optionText: optionLabel(nodeData, item),
|
|
420
|
+
textValue: optionLabel(nodeData, item)
|
|
421
|
+
}))
|
|
422
|
+
};
|
|
423
|
+
var rankingLogic = {
|
|
424
|
+
type: "ranking",
|
|
425
|
+
dataType: "array",
|
|
426
|
+
defaultData: rankingDefaultData,
|
|
427
|
+
defaultValue: [],
|
|
428
|
+
normalizeValue: normalizeChoiceArray,
|
|
429
|
+
validate: (value, nodeData) => {
|
|
430
|
+
const optionResult = validateOptionArray(value, nodeData);
|
|
431
|
+
if (!optionResult.valid) return optionResult;
|
|
432
|
+
const maxRank = positiveNumber2(nodeData.maxRank);
|
|
433
|
+
if (maxRank && value.length > maxRank) return { valid: false, error: `Rank at most ${maxRank} option(s)` };
|
|
434
|
+
return { valid: true };
|
|
435
|
+
},
|
|
436
|
+
extractValue: (value, nodeData) => value.map((item, index) => {
|
|
437
|
+
const rank = index + 1;
|
|
438
|
+
const label = optionLabel(nodeData, item);
|
|
439
|
+
return {
|
|
440
|
+
optionUuid: optionUuid(nodeData, item),
|
|
441
|
+
optionText: label,
|
|
442
|
+
numberValue: rank,
|
|
443
|
+
textValue: `${rank}. ${label}`
|
|
444
|
+
};
|
|
445
|
+
})
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
// src/nodes/textLike/manifest.ts
|
|
449
|
+
var defaultCondition3 = {
|
|
450
|
+
id: "root",
|
|
451
|
+
type: "group",
|
|
452
|
+
logicType: "AND",
|
|
453
|
+
children: []
|
|
454
|
+
};
|
|
455
|
+
var baseTextData = {
|
|
456
|
+
label: "",
|
|
457
|
+
description: "",
|
|
458
|
+
condition: defaultCondition3,
|
|
459
|
+
minChars: 0,
|
|
460
|
+
maxChars: 0,
|
|
461
|
+
minWords: 0,
|
|
462
|
+
maxWords: 0
|
|
463
|
+
};
|
|
464
|
+
var commonProperties3 = [
|
|
465
|
+
{ name: "label", label: "Field Label", type: "text" },
|
|
466
|
+
{ name: "description", label: "Description", type: "textarea" },
|
|
467
|
+
{
|
|
468
|
+
name: "condition",
|
|
469
|
+
label: "Logic Rule",
|
|
470
|
+
type: "condition",
|
|
471
|
+
defaultValue: defaultCondition3
|
|
472
|
+
}
|
|
473
|
+
];
|
|
474
|
+
var textLimitProperties = [
|
|
475
|
+
{ name: "minChars", label: "Min Characters", type: "number", helperText: "Requires at least this many characters.", defaultValue: 0 },
|
|
476
|
+
{ name: "maxChars", label: "Max Characters", type: "number", helperText: "Limits total characters. 0 or empty for no limit.", defaultValue: 0 },
|
|
477
|
+
{ name: "minWords", label: "Min Words", type: "number", helperText: "Requires at least this many words.", defaultValue: 0 },
|
|
478
|
+
{ name: "maxWords", label: "Max Words", type: "number", helperText: "Limits total words. 0 or empty for no limit.", defaultValue: 0 }
|
|
479
|
+
];
|
|
480
|
+
var createBaseData = (label) => ({
|
|
481
|
+
...baseTextData,
|
|
482
|
+
label
|
|
483
|
+
});
|
|
484
|
+
var textInputDefaultData = {
|
|
485
|
+
...createBaseData("Text Answer"),
|
|
486
|
+
placeholder: "",
|
|
487
|
+
longAnswer: false
|
|
488
|
+
};
|
|
489
|
+
var emailInputDefaultData = createBaseData("Email");
|
|
490
|
+
var dateInputDefaultData = createBaseData("Date Picker");
|
|
491
|
+
var numberInputDefaultData = {
|
|
492
|
+
...createBaseData("Number")
|
|
493
|
+
};
|
|
494
|
+
var zipCodeInputDefaultData = {
|
|
495
|
+
...createBaseData("Accepted Zip Codes"),
|
|
496
|
+
allowedZips: ""
|
|
497
|
+
};
|
|
498
|
+
var multiInputDefaultData = {
|
|
499
|
+
...createBaseData("Multi-Input"),
|
|
500
|
+
fields: []
|
|
501
|
+
};
|
|
502
|
+
var textInputManifest = {
|
|
503
|
+
type: "textInput",
|
|
504
|
+
label: "Text Answer",
|
|
505
|
+
description: "Capture text responses",
|
|
506
|
+
category: "input",
|
|
507
|
+
dataType: "text",
|
|
508
|
+
defaultData: textInputDefaultData,
|
|
509
|
+
properties: [
|
|
510
|
+
...commonProperties3,
|
|
511
|
+
{ name: "placeholder", label: "Placeholder", type: "text", placeholder: "e.g., Type here...", defaultValue: "" },
|
|
512
|
+
{ name: "longAnswer", label: "Long Answer (Multi-line)", type: "switch", defaultValue: false },
|
|
513
|
+
...textLimitProperties
|
|
514
|
+
]
|
|
515
|
+
};
|
|
516
|
+
var numberInputManifest = {
|
|
517
|
+
type: "numberInput",
|
|
518
|
+
label: "Number",
|
|
519
|
+
description: "Input for numerical values",
|
|
520
|
+
category: "input",
|
|
521
|
+
dataType: "number",
|
|
522
|
+
defaultData: numberInputDefaultData,
|
|
523
|
+
properties: [
|
|
524
|
+
...commonProperties3,
|
|
525
|
+
{ name: "min", label: "Minimum Value", type: "number" },
|
|
526
|
+
{ name: "max", label: "Maximum Value", type: "number" }
|
|
527
|
+
]
|
|
528
|
+
};
|
|
529
|
+
var zipCodeInputManifest = {
|
|
530
|
+
type: "zipCodeInput",
|
|
531
|
+
label: "Accepted Zip Codes",
|
|
532
|
+
description: "Validate against a list of zip codes",
|
|
533
|
+
category: "input",
|
|
534
|
+
dataType: "text",
|
|
535
|
+
defaultData: zipCodeInputDefaultData,
|
|
536
|
+
properties: [
|
|
537
|
+
...commonProperties3,
|
|
538
|
+
{ name: "allowedZips", label: "Allowed Zip Codes", type: "fileTextarea", placeholder: "10001, 10002, 90210... (Leave empty to allow all)", helperText: "Validation: Only users entering these zip codes can proceed. Others will be blocked." }
|
|
539
|
+
]
|
|
540
|
+
};
|
|
541
|
+
var multiInputManifest = {
|
|
542
|
+
type: "multiInput",
|
|
543
|
+
label: "Multi-Input",
|
|
544
|
+
description: "Multiple fields in one screen",
|
|
545
|
+
category: "input",
|
|
546
|
+
dataType: "object",
|
|
547
|
+
defaultData: multiInputDefaultData,
|
|
548
|
+
properties: [
|
|
549
|
+
...commonProperties3,
|
|
550
|
+
{ name: "fields", label: "Input Fields", type: "options", defaultValue: [], helperText: "Value column represents input type (text, number, email)" },
|
|
551
|
+
...textLimitProperties
|
|
552
|
+
]
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
// src/nodes/textLike/logic.ts
|
|
556
|
+
var normalizeTextValue = (value) => {
|
|
557
|
+
if (typeof value === "string") return value;
|
|
558
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
559
|
+
return "";
|
|
560
|
+
};
|
|
561
|
+
var normalizeMultiInputValue = (value) => {
|
|
562
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
563
|
+
return Object.fromEntries(
|
|
564
|
+
Object.entries(value).map(([key, item]) => [key, normalizeTextValue(item)])
|
|
565
|
+
);
|
|
566
|
+
};
|
|
567
|
+
var numberLimit = (value) => {
|
|
568
|
+
const parsed = Number(value);
|
|
569
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
|
|
570
|
+
};
|
|
571
|
+
var countWords = (value) => value.trim().split(/\s+/).filter(Boolean).length;
|
|
572
|
+
var validateTextLimits = (value, nodeData) => {
|
|
573
|
+
const minChars = numberLimit(nodeData.minChars);
|
|
574
|
+
const maxChars = numberLimit(nodeData.maxChars);
|
|
575
|
+
const minWords = numberLimit(nodeData.minWords);
|
|
576
|
+
const maxWords = numberLimit(nodeData.maxWords);
|
|
577
|
+
if (minChars && value.length < minChars) {
|
|
578
|
+
return { valid: false, error: `Minimum character requirement not met (${value.length}/${minChars})` };
|
|
579
|
+
}
|
|
580
|
+
if (maxChars && value.length > maxChars) {
|
|
581
|
+
return { valid: false, error: `Character limit exceeded (${value.length}/${maxChars})` };
|
|
582
|
+
}
|
|
583
|
+
const wordCount = countWords(value);
|
|
584
|
+
if (minWords && wordCount < minWords) {
|
|
585
|
+
return { valid: false, error: `Minimum word requirement not met (${wordCount}/${minWords})` };
|
|
586
|
+
}
|
|
587
|
+
if (maxWords && wordCount > maxWords) {
|
|
588
|
+
return { valid: false, error: `Word limit exceeded (${wordCount}/${maxWords})` };
|
|
589
|
+
}
|
|
590
|
+
return { valid: true };
|
|
591
|
+
};
|
|
592
|
+
var extractTextValue = (value) => [
|
|
593
|
+
{
|
|
594
|
+
columnKey: "value",
|
|
595
|
+
columnLabel: "Value",
|
|
596
|
+
textValue: value
|
|
597
|
+
}
|
|
598
|
+
];
|
|
599
|
+
var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
600
|
+
var textInputLogic = {
|
|
601
|
+
type: "textInput",
|
|
602
|
+
dataType: "text",
|
|
603
|
+
defaultData: textInputDefaultData,
|
|
604
|
+
defaultValue: "",
|
|
605
|
+
normalizeValue: normalizeTextValue,
|
|
606
|
+
validate: validateTextLimits,
|
|
607
|
+
extractValue: extractTextValue
|
|
608
|
+
};
|
|
609
|
+
var emailInputLogic = {
|
|
610
|
+
type: "emailInput",
|
|
611
|
+
dataType: "text",
|
|
612
|
+
defaultData: emailInputDefaultData,
|
|
613
|
+
defaultValue: "",
|
|
614
|
+
normalizeValue: normalizeTextValue,
|
|
615
|
+
validate: (value, nodeData) => {
|
|
616
|
+
const limitResult = validateTextLimits(value, nodeData);
|
|
617
|
+
if (!limitResult.valid) return limitResult;
|
|
618
|
+
if (value.trim() && !emailRegex.test(value)) return { valid: false, error: "Please enter a valid email address" };
|
|
619
|
+
return { valid: true };
|
|
620
|
+
},
|
|
621
|
+
extractValue: extractTextValue
|
|
622
|
+
};
|
|
623
|
+
var dateInputLogic = {
|
|
624
|
+
type: "dateInput",
|
|
625
|
+
dataType: "text",
|
|
626
|
+
defaultData: dateInputDefaultData,
|
|
627
|
+
defaultValue: "",
|
|
628
|
+
normalizeValue: normalizeTextValue,
|
|
629
|
+
validate: validateTextLimits,
|
|
630
|
+
extractValue: extractTextValue
|
|
631
|
+
};
|
|
632
|
+
var numberInputLogic = {
|
|
633
|
+
type: "numberInput",
|
|
634
|
+
dataType: "number",
|
|
635
|
+
defaultData: numberInputDefaultData,
|
|
636
|
+
defaultValue: "",
|
|
637
|
+
normalizeValue: normalizeTextValue,
|
|
638
|
+
validate: (value, nodeData) => {
|
|
639
|
+
const limitResult = validateTextLimits(value, nodeData);
|
|
640
|
+
if (!limitResult.valid) return limitResult;
|
|
641
|
+
if (!value.trim()) return { valid: true };
|
|
642
|
+
const numberValue2 = Number(value);
|
|
643
|
+
if (Number.isNaN(numberValue2)) return { valid: false, error: "Please enter a valid number" };
|
|
644
|
+
if (typeof nodeData.min === "number" && numberValue2 < nodeData.min) {
|
|
645
|
+
return { valid: false, error: `Minimum value is ${nodeData.min}` };
|
|
646
|
+
}
|
|
647
|
+
if (typeof nodeData.max === "number" && numberValue2 > nodeData.max) {
|
|
648
|
+
return { valid: false, error: `Maximum value is ${nodeData.max}` };
|
|
649
|
+
}
|
|
650
|
+
return { valid: true };
|
|
651
|
+
},
|
|
652
|
+
extractValue: (value) => [
|
|
653
|
+
value.trim() ? {
|
|
654
|
+
columnKey: "value",
|
|
655
|
+
columnLabel: "Value",
|
|
656
|
+
textValue: value,
|
|
657
|
+
numberValue: Number(value)
|
|
658
|
+
} : {
|
|
659
|
+
columnKey: "value",
|
|
660
|
+
columnLabel: "Value",
|
|
661
|
+
textValue: value
|
|
662
|
+
}
|
|
663
|
+
]
|
|
664
|
+
};
|
|
665
|
+
var parseZipList = (value) => value.split(/[\s,]+/).map((item) => item.trim()).filter(Boolean);
|
|
666
|
+
var zipCodeInputLogic = {
|
|
667
|
+
type: "zipCodeInput",
|
|
668
|
+
dataType: "text",
|
|
669
|
+
defaultData: zipCodeInputDefaultData,
|
|
670
|
+
defaultValue: "",
|
|
671
|
+
normalizeValue: normalizeTextValue,
|
|
672
|
+
validate: (value, nodeData) => {
|
|
673
|
+
const limitResult = validateTextLimits(value, nodeData);
|
|
674
|
+
if (!limitResult.valid) return limitResult;
|
|
675
|
+
const allowedZips = parseZipList(String(nodeData.allowedZips || ""));
|
|
676
|
+
if (allowedZips.length > 0 && value.trim() && !allowedZips.includes(value.trim())) {
|
|
677
|
+
return { valid: false, error: "Zip code is not accepted" };
|
|
678
|
+
}
|
|
679
|
+
return { valid: true };
|
|
680
|
+
},
|
|
681
|
+
extractValue: extractTextValue
|
|
682
|
+
};
|
|
683
|
+
var multiInputLogic = {
|
|
684
|
+
type: "multiInput",
|
|
685
|
+
dataType: "object",
|
|
686
|
+
defaultData: multiInputDefaultData,
|
|
687
|
+
defaultValue: {},
|
|
688
|
+
normalizeValue: normalizeMultiInputValue,
|
|
689
|
+
validate: (value, nodeData) => {
|
|
690
|
+
for (const [fieldId, fieldValue] of Object.entries(value)) {
|
|
691
|
+
const limitResult = validateTextLimits(fieldValue, nodeData);
|
|
692
|
+
if (!limitResult.valid) return { valid: false, error: `${fieldId}: ${limitResult.error}` };
|
|
693
|
+
}
|
|
694
|
+
return { valid: true };
|
|
695
|
+
},
|
|
696
|
+
extractValue: (value, nodeData) => {
|
|
697
|
+
const fields = Array.isArray(nodeData.fields) ? nodeData.fields : [];
|
|
698
|
+
return Object.entries(value).map(([fieldId, fieldValue]) => {
|
|
699
|
+
const field = fields.find((item) => item.id === fieldId);
|
|
700
|
+
const label = field?.label || fieldId;
|
|
701
|
+
return {
|
|
702
|
+
columnKey: fieldId,
|
|
703
|
+
columnLabel: label,
|
|
704
|
+
textValue: fieldValue
|
|
705
|
+
};
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
};
|
|
709
|
+
|
|
70
710
|
// src/logic/index.ts
|
|
71
711
|
var logicRegistry = defineLogicRegistry({
|
|
712
|
+
textInput: textInputLogic,
|
|
713
|
+
numberInput: numberInputLogic,
|
|
714
|
+
emailInput: emailInputLogic,
|
|
715
|
+
dateInput: dateInputLogic,
|
|
716
|
+
multiInput: multiInputLogic,
|
|
717
|
+
zipCodeInput: zipCodeInputLogic,
|
|
718
|
+
singleChoice: singleChoiceLogic,
|
|
719
|
+
multipleChoice: multipleChoiceLogic,
|
|
720
|
+
dropdown: dropdownLogic,
|
|
721
|
+
ranking: rankingLogic,
|
|
722
|
+
rating: ratingLogic,
|
|
723
|
+
slider: sliderLogic,
|
|
72
724
|
plainText: plainTextLogic
|
|
73
725
|
});
|
|
74
726
|
export {
|
|
75
727
|
createInitialData,
|
|
728
|
+
dateInputLogic,
|
|
76
729
|
defineLogicRegistry,
|
|
730
|
+
dropdownLogic,
|
|
731
|
+
emailInputLogic,
|
|
77
732
|
logicRegistry,
|
|
78
|
-
|
|
733
|
+
multiInputLogic,
|
|
734
|
+
multipleChoiceLogic,
|
|
735
|
+
numberInputLogic,
|
|
736
|
+
plainTextLogic,
|
|
737
|
+
rankingLogic,
|
|
738
|
+
ratingLogic,
|
|
739
|
+
singleChoiceLogic,
|
|
740
|
+
sliderLogic,
|
|
741
|
+
textInputLogic,
|
|
742
|
+
zipCodeInputLogic
|
|
79
743
|
};
|