@surveystudio/node-registery 1.1.0 → 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 +7 -1
- package/dist/builder.d.mts +4 -4
- package/dist/{coreTypes-YSpR0Oyh.d.mts → coreTypes-CyFAym5A.d.mts} +1 -1
- package/dist/logic.d.mts +88 -4
- package/dist/logic.mjs +402 -12
- package/dist/runner.d.mts +2 -2
- package/dist/{types-CgiAR_DF.d.mts → types-4zXsOMLb.d.mts} +1 -1
- package/dist/{types-CjF8-OZi.d.mts → types-BMnck1ag.d.mts} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Typed survey question node registry with separate entrypoints for pure logic, runner UI, and builder UI.
|
|
4
4
|
|
|
5
|
-
This package is currently in early migration. It exports
|
|
5
|
+
This package is currently in early migration. It exports migrated node logic for server runtimes and selected builder/runner UI adapters while the remaining SurveyChamp question nodes are being moved into the registry.
|
|
6
6
|
|
|
7
7
|
## Entrypoints
|
|
8
8
|
|
|
@@ -38,6 +38,12 @@ Migrated nodes:
|
|
|
38
38
|
- `dateInput`
|
|
39
39
|
- `multiInput`
|
|
40
40
|
- `zipCodeInput`
|
|
41
|
+
- `singleChoice` logic
|
|
42
|
+
- `multipleChoice` logic
|
|
43
|
+
- `dropdown` logic
|
|
44
|
+
- `ranking` logic
|
|
45
|
+
- `rating` logic
|
|
46
|
+
- `slider` logic
|
|
41
47
|
- `plainText`
|
|
42
48
|
|
|
43
49
|
The registry contract test intentionally fails until all planned question nodes are migrated.
|
package/dist/builder.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { B as BuilderRegistry, C as CompleteBuilderRegistry, N as NodeBuilder, a as NodeBuilderProps, b as NodeCanvasProps, Q as QuestionNodeDefinition, d as defineBuilderRegistry, c as defineQuestionNode } from './types-
|
|
2
|
-
import { J as JsonValue } from './coreTypes-
|
|
3
|
-
export { N as NodeManifest, P as PropertyField, a as PropertyFieldType, S as SelectOption } from './coreTypes-
|
|
4
|
-
import { P as PlainTextData, B as BaseTextData, M as MultiInputData, N as NumberInputData, T as TextInputData, Z as ZipCodeInputData } from './types-
|
|
1
|
+
export { B as BuilderRegistry, C as CompleteBuilderRegistry, N as NodeBuilder, a as NodeBuilderProps, b as NodeCanvasProps, Q as QuestionNodeDefinition, d as defineBuilderRegistry, c as defineQuestionNode } from './types-4zXsOMLb.mjs';
|
|
2
|
+
import { J as JsonValue } from './coreTypes-CyFAym5A.mjs';
|
|
3
|
+
export { N as NodeManifest, P as PropertyField, a as PropertyFieldType, S as SelectOption } from './coreTypes-CyFAym5A.mjs';
|
|
4
|
+
import { P as PlainTextData, B as BaseTextData, M as MultiInputData, N as NumberInputData, T as TextInputData, Z as ZipCodeInputData } from './types-BMnck1ag.mjs';
|
|
5
5
|
import 'react';
|
|
6
6
|
|
|
7
7
|
declare const plainTextBuilder: {
|
|
@@ -82,4 +82,4 @@ type RegistryKeySet = Readonly<Partial<Record<SurveyNodeType, unknown>>>;
|
|
|
82
82
|
declare function defineLogicRegistry<const TRegistry extends RegistryKeySet>(registry: TRegistry): TRegistry;
|
|
83
83
|
declare function createInitialData<TData extends NodeData>(manifest: NodeManifest<SurveyNodeType, TData>): TData;
|
|
84
84
|
|
|
85
|
-
export { type CompleteLogicRegistry as C, type DataType as D, type ExtractedValue as E, type JsonValue as J, type LogicRegistry as L, type NodeManifest as N, type PropertyField as P, type QuestionNodeType as Q, type SelectOption as S, type ValidationContext as V, type PropertyFieldType as a, type
|
|
85
|
+
export { type CompleteLogicRegistry as C, type DataType as D, type ExtractedValue as E, type JsonValue as J, type LogicRegistry as L, type NodeManifest as N, type PropertyField as P, type QuestionNodeType as Q, type SelectOption as S, type ValidationContext as V, type PropertyFieldType as a, type NodeData as b, type NodeLogic as c, type ExtractionContext as d, type NodeLogicContext as e, type ValidationResult as f, createInitialData as g, defineLogicRegistry as h, type SurveyNodeType as i, type NodeValue as j };
|
package/dist/logic.d.mts
CHANGED
|
@@ -1,9 +1,87 @@
|
|
|
1
|
-
import { P as PlainTextData, a as PlainTextValue, D as DateInputData, b as TextValue, E as EmailInputData, M as MultiInputData, c as MultiInputValue, N as NumberInputData, T as TextInputData, Z as ZipCodeInputData, B as BaseTextData } from './types-
|
|
2
|
-
import { b as NodeLogic } from './coreTypes-
|
|
3
|
-
export { C as CompleteLogicRegistry, D as DataType, E as ExtractedValue,
|
|
1
|
+
import { P as PlainTextData, a as PlainTextValue, D as DateInputData, b as TextValue, E as EmailInputData, M as MultiInputData, c as MultiInputValue, N as NumberInputData, T as TextInputData, Z as ZipCodeInputData, B as BaseTextData } from './types-BMnck1ag.mjs';
|
|
2
|
+
import { b as NodeData, J as JsonValue, c as NodeLogic } from './coreTypes-CyFAym5A.mjs';
|
|
3
|
+
export { C as CompleteLogicRegistry, D as DataType, E as ExtractedValue, d as ExtractionContext, L as LogicRegistry, e as NodeLogicContext, V as ValidationContext, f as ValidationResult, g as createInitialData, h as defineLogicRegistry } from './coreTypes-CyFAym5A.mjs';
|
|
4
|
+
|
|
5
|
+
type ConditionData$1 = {
|
|
6
|
+
id: string;
|
|
7
|
+
type: "group";
|
|
8
|
+
logicType: "AND" | "OR";
|
|
9
|
+
children: JsonValue[];
|
|
10
|
+
};
|
|
11
|
+
type ScaleItem = NodeData & {
|
|
12
|
+
id?: string;
|
|
13
|
+
exportId?: string;
|
|
14
|
+
technicalId?: string;
|
|
15
|
+
label?: string;
|
|
16
|
+
value?: string;
|
|
17
|
+
};
|
|
18
|
+
type ScaleResponseMode = "single" | "multi";
|
|
19
|
+
type BaseScaleData = NodeData & {
|
|
20
|
+
label: string;
|
|
21
|
+
description: string;
|
|
22
|
+
condition: ConditionData$1;
|
|
23
|
+
responseMode?: ScaleResponseMode;
|
|
24
|
+
items: ScaleItem[];
|
|
25
|
+
};
|
|
26
|
+
type RatingData = BaseScaleData & {
|
|
27
|
+
maxRating: number;
|
|
28
|
+
};
|
|
29
|
+
type SliderData = BaseScaleData & {
|
|
30
|
+
min: number;
|
|
31
|
+
max: number;
|
|
32
|
+
step: number;
|
|
33
|
+
startValue: number;
|
|
34
|
+
};
|
|
35
|
+
type ScaleValue = number | Record<string, number>;
|
|
36
|
+
|
|
37
|
+
type ConditionData = {
|
|
38
|
+
id: string;
|
|
39
|
+
type: "group";
|
|
40
|
+
logicType: "AND" | "OR";
|
|
41
|
+
children: JsonValue[];
|
|
42
|
+
};
|
|
43
|
+
type ChoiceOption = NodeData & {
|
|
44
|
+
id?: string;
|
|
45
|
+
label: string;
|
|
46
|
+
value: string;
|
|
47
|
+
imageUrl?: string;
|
|
48
|
+
};
|
|
49
|
+
type BaseChoiceData = NodeData & {
|
|
50
|
+
label: string;
|
|
51
|
+
description: string;
|
|
52
|
+
condition: ConditionData;
|
|
53
|
+
options: ChoiceOption[];
|
|
54
|
+
randomizeOptions?: boolean;
|
|
55
|
+
};
|
|
56
|
+
type SingleChoiceData = BaseChoiceData & {
|
|
57
|
+
allowOther?: boolean;
|
|
58
|
+
otherLabel?: string;
|
|
59
|
+
};
|
|
60
|
+
type DropdownData = BaseChoiceData & {
|
|
61
|
+
searchable?: boolean;
|
|
62
|
+
};
|
|
63
|
+
type MultipleChoiceData = BaseChoiceData & {
|
|
64
|
+
minChoices?: number;
|
|
65
|
+
maxChoices?: number;
|
|
66
|
+
};
|
|
67
|
+
type RankingData = BaseChoiceData & {
|
|
68
|
+
maxRank?: number;
|
|
69
|
+
displayMode?: "drag" | "select";
|
|
70
|
+
};
|
|
71
|
+
type SingleChoiceValue = string;
|
|
72
|
+
type MultipleChoiceValue = string[];
|
|
73
|
+
type RankingValue = string[];
|
|
4
74
|
|
|
5
75
|
declare const plainTextLogic: NodeLogic<"plainText", PlainTextData, PlainTextValue>;
|
|
6
76
|
|
|
77
|
+
declare const ratingLogic: NodeLogic<"rating", RatingData, ScaleValue>;
|
|
78
|
+
declare const sliderLogic: NodeLogic<"slider", SliderData, ScaleValue>;
|
|
79
|
+
|
|
80
|
+
declare const singleChoiceLogic: NodeLogic<"singleChoice", SingleChoiceData, SingleChoiceValue>;
|
|
81
|
+
declare const dropdownLogic: NodeLogic<"dropdown", DropdownData, SingleChoiceValue>;
|
|
82
|
+
declare const multipleChoiceLogic: NodeLogic<"multipleChoice", MultipleChoiceData, MultipleChoiceValue>;
|
|
83
|
+
declare const rankingLogic: NodeLogic<"ranking", RankingData, RankingValue>;
|
|
84
|
+
|
|
7
85
|
declare const textInputLogic: NodeLogic<"textInput", TextInputData, TextValue>;
|
|
8
86
|
declare const emailInputLogic: NodeLogic<"emailInput", EmailInputData, TextValue>;
|
|
9
87
|
declare const dateInputLogic: NodeLogic<"dateInput", DateInputData, TextValue>;
|
|
@@ -18,7 +96,13 @@ declare const logicRegistry: {
|
|
|
18
96
|
readonly dateInput: NodeLogic<"dateInput", BaseTextData, string>;
|
|
19
97
|
readonly multiInput: NodeLogic<"multiInput", MultiInputData, MultiInputValue>;
|
|
20
98
|
readonly zipCodeInput: NodeLogic<"zipCodeInput", ZipCodeInputData, string>;
|
|
99
|
+
readonly singleChoice: NodeLogic<"singleChoice", SingleChoiceData, string>;
|
|
100
|
+
readonly multipleChoice: NodeLogic<"multipleChoice", MultipleChoiceData, MultipleChoiceValue>;
|
|
101
|
+
readonly dropdown: NodeLogic<"dropdown", DropdownData, string>;
|
|
102
|
+
readonly ranking: NodeLogic<"ranking", RankingData, RankingValue>;
|
|
103
|
+
readonly rating: NodeLogic<"rating", RatingData, ScaleValue>;
|
|
104
|
+
readonly slider: NodeLogic<"slider", SliderData, ScaleValue>;
|
|
21
105
|
readonly plainText: NodeLogic<"plainText", PlainTextData, PlainTextValue>;
|
|
22
106
|
};
|
|
23
107
|
|
|
24
|
-
export { NodeLogic, dateInputLogic, emailInputLogic, logicRegistry, multiInputLogic, numberInputLogic, plainTextLogic, textInputLogic, zipCodeInputLogic };
|
|
108
|
+
export { NodeLogic, dateInputLogic, dropdownLogic, emailInputLogic, logicRegistry, multiInputLogic, multipleChoiceLogic, numberInputLogic, plainTextLogic, rankingLogic, ratingLogic, singleChoiceLogic, sliderLogic, textInputLogic, zipCodeInputLogic };
|
package/dist/logic.mjs
CHANGED
|
@@ -67,30 +67,408 @@ var plainTextLogic = {
|
|
|
67
67
|
]
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
// src/nodes/
|
|
70
|
+
// src/nodes/scale/manifest.ts
|
|
71
71
|
var defaultCondition = {
|
|
72
72
|
id: "root",
|
|
73
73
|
type: "group",
|
|
74
74
|
logicType: "AND",
|
|
75
75
|
children: []
|
|
76
76
|
};
|
|
77
|
-
var
|
|
77
|
+
var baseScaleData = {
|
|
78
78
|
label: "",
|
|
79
79
|
description: "",
|
|
80
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,
|
|
81
459
|
minChars: 0,
|
|
82
460
|
maxChars: 0,
|
|
83
461
|
minWords: 0,
|
|
84
462
|
maxWords: 0
|
|
85
463
|
};
|
|
86
|
-
var
|
|
464
|
+
var commonProperties3 = [
|
|
87
465
|
{ name: "label", label: "Field Label", type: "text" },
|
|
88
466
|
{ name: "description", label: "Description", type: "textarea" },
|
|
89
467
|
{
|
|
90
468
|
name: "condition",
|
|
91
469
|
label: "Logic Rule",
|
|
92
470
|
type: "condition",
|
|
93
|
-
defaultValue:
|
|
471
|
+
defaultValue: defaultCondition3
|
|
94
472
|
}
|
|
95
473
|
];
|
|
96
474
|
var textLimitProperties = [
|
|
@@ -129,7 +507,7 @@ var textInputManifest = {
|
|
|
129
507
|
dataType: "text",
|
|
130
508
|
defaultData: textInputDefaultData,
|
|
131
509
|
properties: [
|
|
132
|
-
...
|
|
510
|
+
...commonProperties3,
|
|
133
511
|
{ name: "placeholder", label: "Placeholder", type: "text", placeholder: "e.g., Type here...", defaultValue: "" },
|
|
134
512
|
{ name: "longAnswer", label: "Long Answer (Multi-line)", type: "switch", defaultValue: false },
|
|
135
513
|
...textLimitProperties
|
|
@@ -143,7 +521,7 @@ var numberInputManifest = {
|
|
|
143
521
|
dataType: "number",
|
|
144
522
|
defaultData: numberInputDefaultData,
|
|
145
523
|
properties: [
|
|
146
|
-
...
|
|
524
|
+
...commonProperties3,
|
|
147
525
|
{ name: "min", label: "Minimum Value", type: "number" },
|
|
148
526
|
{ name: "max", label: "Maximum Value", type: "number" }
|
|
149
527
|
]
|
|
@@ -156,7 +534,7 @@ var zipCodeInputManifest = {
|
|
|
156
534
|
dataType: "text",
|
|
157
535
|
defaultData: zipCodeInputDefaultData,
|
|
158
536
|
properties: [
|
|
159
|
-
...
|
|
537
|
+
...commonProperties3,
|
|
160
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." }
|
|
161
539
|
]
|
|
162
540
|
};
|
|
@@ -168,7 +546,7 @@ var multiInputManifest = {
|
|
|
168
546
|
dataType: "object",
|
|
169
547
|
defaultData: multiInputDefaultData,
|
|
170
548
|
properties: [
|
|
171
|
-
...
|
|
549
|
+
...commonProperties3,
|
|
172
550
|
{ name: "fields", label: "Input Fields", type: "options", defaultValue: [], helperText: "Value column represents input type (text, number, email)" },
|
|
173
551
|
...textLimitProperties
|
|
174
552
|
]
|
|
@@ -261,12 +639,12 @@ var numberInputLogic = {
|
|
|
261
639
|
const limitResult = validateTextLimits(value, nodeData);
|
|
262
640
|
if (!limitResult.valid) return limitResult;
|
|
263
641
|
if (!value.trim()) return { valid: true };
|
|
264
|
-
const
|
|
265
|
-
if (Number.isNaN(
|
|
266
|
-
if (typeof nodeData.min === "number" &&
|
|
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) {
|
|
267
645
|
return { valid: false, error: `Minimum value is ${nodeData.min}` };
|
|
268
646
|
}
|
|
269
|
-
if (typeof nodeData.max === "number" &&
|
|
647
|
+
if (typeof nodeData.max === "number" && numberValue2 > nodeData.max) {
|
|
270
648
|
return { valid: false, error: `Maximum value is ${nodeData.max}` };
|
|
271
649
|
}
|
|
272
650
|
return { valid: true };
|
|
@@ -337,17 +715,29 @@ var logicRegistry = defineLogicRegistry({
|
|
|
337
715
|
dateInput: dateInputLogic,
|
|
338
716
|
multiInput: multiInputLogic,
|
|
339
717
|
zipCodeInput: zipCodeInputLogic,
|
|
718
|
+
singleChoice: singleChoiceLogic,
|
|
719
|
+
multipleChoice: multipleChoiceLogic,
|
|
720
|
+
dropdown: dropdownLogic,
|
|
721
|
+
ranking: rankingLogic,
|
|
722
|
+
rating: ratingLogic,
|
|
723
|
+
slider: sliderLogic,
|
|
340
724
|
plainText: plainTextLogic
|
|
341
725
|
});
|
|
342
726
|
export {
|
|
343
727
|
createInitialData,
|
|
344
728
|
dateInputLogic,
|
|
345
729
|
defineLogicRegistry,
|
|
730
|
+
dropdownLogic,
|
|
346
731
|
emailInputLogic,
|
|
347
732
|
logicRegistry,
|
|
348
733
|
multiInputLogic,
|
|
734
|
+
multipleChoiceLogic,
|
|
349
735
|
numberInputLogic,
|
|
350
736
|
plainTextLogic,
|
|
737
|
+
rankingLogic,
|
|
738
|
+
ratingLogic,
|
|
739
|
+
singleChoiceLogic,
|
|
740
|
+
sliderLogic,
|
|
351
741
|
textInputLogic,
|
|
352
742
|
zipCodeInputLogic
|
|
353
743
|
};
|
package/dist/runner.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { e as CompleteRunnerRegistry, f as NodeRunner, g as NodeRunnerProps, Q as QuestionNodeDefinition, R as RunnerRegistry, c as defineQuestionNode, h as defineRunnerRegistry } from './types-
|
|
1
|
+
export { e as CompleteRunnerRegistry, f as NodeRunner, g as NodeRunnerProps, Q as QuestionNodeDefinition, R as RunnerRegistry, c as defineQuestionNode, h as defineRunnerRegistry } from './types-4zXsOMLb.mjs';
|
|
2
2
|
import 'react';
|
|
3
|
-
import './coreTypes-
|
|
3
|
+
import './coreTypes-CyFAym5A.mjs';
|
|
4
4
|
|
|
5
5
|
declare const plainTextRunner: {
|
|
6
6
|
type: "plainText";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode, ComponentType } from 'react';
|
|
2
|
-
import { i as SurveyNodeType,
|
|
2
|
+
import { i as SurveyNodeType, b as NodeData, Q as QuestionNodeType, j as NodeValue, N as NodeManifest, c as NodeLogic } from './coreTypes-CyFAym5A.mjs';
|
|
3
3
|
|
|
4
4
|
interface NodeRunnerProps<TData extends NodeData = NodeData, TValue extends NodeValue = NodeValue> {
|
|
5
5
|
readonly data: Readonly<TData>;
|
package/package.json
CHANGED