@formality-ui/core 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/dist/index.js ADDED
@@ -0,0 +1,1105 @@
1
+ import jsep from 'jsep';
2
+
3
+ // src/expression/evaluate.ts
4
+
5
+ // src/expression/context.ts
6
+ var QUALIFIED_PREFIXES = [
7
+ "fields",
8
+ "record",
9
+ "errors",
10
+ "defaultValues",
11
+ "touchedFields",
12
+ "dirtyFields",
13
+ "props"
14
+ ];
15
+ var KEYWORDS = [
16
+ "true",
17
+ "false",
18
+ "null",
19
+ "undefined",
20
+ "typeof",
21
+ "instanceof",
22
+ "new",
23
+ "this",
24
+ "if",
25
+ "else",
26
+ "return"
27
+ ];
28
+ var FIELD_STATE_PROPERTIES = /* @__PURE__ */ new Set([
29
+ "value",
30
+ "isTouched",
31
+ "isDirty",
32
+ "isValidating",
33
+ "error",
34
+ "invalid"
35
+ ]);
36
+ var FIELD_PROXY_MARKER = /* @__PURE__ */ Symbol.for("formality.fieldProxy");
37
+ var FIELD_PROXY_VALUE = /* @__PURE__ */ Symbol.for("formality.fieldProxyValue");
38
+ function createFieldStateProxy(fieldState) {
39
+ const proxy = new Proxy(fieldState, {
40
+ get(target, prop) {
41
+ if (prop === FIELD_PROXY_MARKER) {
42
+ return true;
43
+ }
44
+ if (prop === FIELD_PROXY_VALUE) {
45
+ return target.value;
46
+ }
47
+ if (prop === Symbol.toPrimitive) {
48
+ return (_hint) => target.value;
49
+ }
50
+ if (typeof prop === "string" && FIELD_STATE_PROPERTIES.has(prop)) {
51
+ return target[prop];
52
+ }
53
+ const value = target.value;
54
+ if (value !== null && value !== void 0 && typeof value === "object") {
55
+ return value[prop];
56
+ }
57
+ return void 0;
58
+ }
59
+ });
60
+ return proxy;
61
+ }
62
+ function isFieldProxy(value) {
63
+ return value !== null && typeof value === "object" && value[FIELD_PROXY_MARKER] === true;
64
+ }
65
+ function unwrapFieldProxy(value) {
66
+ if (isFieldProxy(value)) {
67
+ return value[FIELD_PROXY_VALUE];
68
+ }
69
+ return value;
70
+ }
71
+ function buildFormContext(fields, record, errors, defaultValues, touchedFields, dirtyFields) {
72
+ const context = {};
73
+ context.fields = fields;
74
+ context.record = record ?? {};
75
+ context.errors = errors ?? {};
76
+ context.defaultValues = defaultValues ?? {};
77
+ context.touchedFields = touchedFields ?? {};
78
+ context.dirtyFields = dirtyFields ?? {};
79
+ for (const [fieldName, fieldState] of Object.entries(fields)) {
80
+ if (!(fieldName in context)) {
81
+ context[fieldName] = createFieldStateProxy(fieldState);
82
+ }
83
+ }
84
+ return context;
85
+ }
86
+ function buildFieldContext(formState, fieldName, additionalProps) {
87
+ const context = buildFormContext(
88
+ formState.fields,
89
+ formState.record,
90
+ formState.errors,
91
+ formState.defaultValues,
92
+ formState.touchedFields,
93
+ formState.dirtyFields
94
+ );
95
+ context.props = {
96
+ name: fieldName,
97
+ ...additionalProps
98
+ };
99
+ return context;
100
+ }
101
+ function buildEvaluationContext(fieldValues, record, props, fieldStates) {
102
+ const context = {};
103
+ const fields = {};
104
+ for (const [name, value] of Object.entries(fieldValues)) {
105
+ if (fieldStates && fieldStates[name]) {
106
+ fields[name] = fieldStates[name];
107
+ } else {
108
+ fields[name] = { value };
109
+ }
110
+ }
111
+ context.fields = fields;
112
+ context.record = record ?? {};
113
+ context.props = props ?? {};
114
+ for (const [fieldName] of Object.entries(fieldValues)) {
115
+ if (!(fieldName in context)) {
116
+ context[fieldName] = createFieldStateProxy(fields[fieldName]);
117
+ }
118
+ }
119
+ return context;
120
+ }
121
+
122
+ // src/expression/evaluate.ts
123
+ function getProperty(obj, key) {
124
+ if (obj === null || obj === void 0) {
125
+ return void 0;
126
+ }
127
+ if (typeof obj === "object") {
128
+ return obj[key];
129
+ }
130
+ return void 0;
131
+ }
132
+ function evaluateNode(node, context) {
133
+ switch (node.type) {
134
+ case "Literal":
135
+ return node.value;
136
+ case "Identifier":
137
+ return context[node.name];
138
+ case "MemberExpression": {
139
+ const memberNode = node;
140
+ const object = evaluateNode(memberNode.object, context);
141
+ if (memberNode.computed) {
142
+ const property = evaluateNode(memberNode.property, context);
143
+ return getProperty(object, String(property));
144
+ } else {
145
+ return getProperty(object, memberNode.property.name);
146
+ }
147
+ }
148
+ case "BinaryExpression": {
149
+ const binaryNode = node;
150
+ switch (binaryNode.operator) {
151
+ case "&&": {
152
+ const left2 = evaluateNode(binaryNode.left, context);
153
+ const leftValue2 = unwrapFieldProxy(left2);
154
+ return leftValue2 ? evaluateNode(binaryNode.right, context) : leftValue2;
155
+ }
156
+ case "||": {
157
+ const left2 = evaluateNode(binaryNode.left, context);
158
+ const leftValue2 = unwrapFieldProxy(left2);
159
+ return leftValue2 ? leftValue2 : evaluateNode(binaryNode.right, context);
160
+ }
161
+ case "??": {
162
+ const left2 = evaluateNode(binaryNode.left, context);
163
+ const leftValue2 = unwrapFieldProxy(left2);
164
+ return leftValue2 !== null && leftValue2 !== void 0 ? leftValue2 : evaluateNode(binaryNode.right, context);
165
+ }
166
+ }
167
+ const left = evaluateNode(binaryNode.left, context);
168
+ const right = evaluateNode(binaryNode.right, context);
169
+ const leftValue = unwrapFieldProxy(left);
170
+ const rightValue = unwrapFieldProxy(right);
171
+ switch (binaryNode.operator) {
172
+ case "+":
173
+ return leftValue + rightValue;
174
+ case "-":
175
+ return leftValue - rightValue;
176
+ case "*":
177
+ return leftValue * rightValue;
178
+ case "/":
179
+ return leftValue / rightValue;
180
+ case "%":
181
+ return leftValue % rightValue;
182
+ case "===":
183
+ return leftValue === rightValue;
184
+ case "!==":
185
+ return leftValue !== rightValue;
186
+ case "==":
187
+ return leftValue == rightValue;
188
+ case "!=":
189
+ return leftValue != rightValue;
190
+ case "<":
191
+ return leftValue < rightValue;
192
+ case ">":
193
+ return leftValue > rightValue;
194
+ case "<=":
195
+ return leftValue <= rightValue;
196
+ case ">=":
197
+ return leftValue >= rightValue;
198
+ default:
199
+ throw new Error(`Unknown binary operator: ${binaryNode.operator}`);
200
+ }
201
+ }
202
+ case "LogicalExpression": {
203
+ const logicalNode = node;
204
+ const left = evaluateNode(logicalNode.left, context);
205
+ const leftValue = unwrapFieldProxy(left);
206
+ switch (logicalNode.operator) {
207
+ case "&&":
208
+ return leftValue ? evaluateNode(logicalNode.right, context) : leftValue;
209
+ case "||":
210
+ return leftValue ? leftValue : evaluateNode(logicalNode.right, context);
211
+ case "??":
212
+ return leftValue !== null && leftValue !== void 0 ? leftValue : evaluateNode(logicalNode.right, context);
213
+ default:
214
+ throw new Error(`Unknown logical operator: ${logicalNode.operator}`);
215
+ }
216
+ }
217
+ case "UnaryExpression": {
218
+ const unaryNode = node;
219
+ const argument = evaluateNode(unaryNode.argument, context);
220
+ const argValue = unwrapFieldProxy(argument);
221
+ switch (unaryNode.operator) {
222
+ case "!":
223
+ return !argValue;
224
+ case "-":
225
+ return -argValue;
226
+ case "+":
227
+ return +argValue;
228
+ case "typeof":
229
+ return typeof argValue;
230
+ default:
231
+ throw new Error(`Unknown unary operator: ${unaryNode.operator}`);
232
+ }
233
+ }
234
+ case "ConditionalExpression": {
235
+ const condNode = node;
236
+ const test = evaluateNode(condNode.test, context);
237
+ const testValue = unwrapFieldProxy(test);
238
+ return testValue ? evaluateNode(condNode.consequent, context) : evaluateNode(condNode.alternate, context);
239
+ }
240
+ case "ArrayExpression": {
241
+ const arrayNode = node;
242
+ return arrayNode.elements.map(
243
+ (element) => element ? evaluateNode(element, context) : void 0
244
+ );
245
+ }
246
+ case "CallExpression": {
247
+ throw new Error("Function calls are not allowed in expressions");
248
+ }
249
+ case "Compound": {
250
+ const compoundNode = node;
251
+ let result;
252
+ for (const bodyNode of compoundNode.body) {
253
+ result = evaluateNode(bodyNode, context);
254
+ }
255
+ return result;
256
+ }
257
+ default:
258
+ throw new Error(`Unknown node type: ${node.type}`);
259
+ }
260
+ }
261
+ var astCache = /* @__PURE__ */ new Map();
262
+ function parseExpression(expr) {
263
+ const cached = astCache.get(expr);
264
+ if (cached) {
265
+ return cached;
266
+ }
267
+ const ast = jsep(expr);
268
+ astCache.set(expr, ast);
269
+ return ast;
270
+ }
271
+ function evaluate(expr, context) {
272
+ try {
273
+ const ast = parseExpression(expr);
274
+ const result = evaluateNode(ast, context);
275
+ const unwrapped = unwrapFieldProxy(result);
276
+ return unwrapped;
277
+ } catch (error) {
278
+ if (process.env.NODE_ENV !== "production") {
279
+ console.warn(`Expression evaluation error for "${expr}":`, error);
280
+ }
281
+ return void 0;
282
+ }
283
+ }
284
+ function evaluateDescriptor(descriptor, context) {
285
+ if (typeof descriptor === "string") {
286
+ return evaluate(descriptor, context);
287
+ }
288
+ if (typeof descriptor === "function") {
289
+ return descriptor;
290
+ }
291
+ if (Array.isArray(descriptor)) {
292
+ return descriptor.map((item) => evaluateDescriptor(item, context));
293
+ }
294
+ if (descriptor !== null && typeof descriptor === "object") {
295
+ const result = {};
296
+ for (const [key, value] of Object.entries(descriptor)) {
297
+ result[key] = evaluateDescriptor(value, context);
298
+ }
299
+ return result;
300
+ }
301
+ return descriptor;
302
+ }
303
+ function clearExpressionCache() {
304
+ astCache.clear();
305
+ }
306
+
307
+ // src/expression/infer.ts
308
+ var IDENTIFIER_REGEX = /\b([a-zA-Z_$][a-zA-Z0-9_$]*)\b/g;
309
+ var KEYWORD_SET = new Set(KEYWORDS);
310
+ var QUALIFIED_PREFIX_SET = new Set(QUALIFIED_PREFIXES);
311
+ function inferFieldsFromExpression(expr) {
312
+ const fields = [];
313
+ let match;
314
+ IDENTIFIER_REGEX.lastIndex = 0;
315
+ while ((match = IDENTIFIER_REGEX.exec(expr)) !== null) {
316
+ const identifier = match[1];
317
+ if (KEYWORD_SET.has(identifier)) {
318
+ continue;
319
+ }
320
+ const beforeMatch = expr.slice(0, match.index);
321
+ const lastNonWhitespace = beforeMatch.trimEnd().slice(-1);
322
+ if (lastNonWhitespace === ".") {
323
+ continue;
324
+ }
325
+ const afterMatch = expr.slice(match.index + identifier.length);
326
+ if (afterMatch.startsWith(".") && QUALIFIED_PREFIX_SET.has(identifier)) {
327
+ continue;
328
+ }
329
+ fields.push(identifier);
330
+ }
331
+ return [...new Set(fields)];
332
+ }
333
+ function inferFieldsFromDescriptor(descriptor) {
334
+ if (typeof descriptor === "string") {
335
+ return inferFieldsFromExpression(descriptor);
336
+ }
337
+ if (typeof descriptor === "function") {
338
+ return [];
339
+ }
340
+ if (Array.isArray(descriptor)) {
341
+ const allFields = [];
342
+ for (const item of descriptor) {
343
+ allFields.push(...inferFieldsFromDescriptor(item));
344
+ }
345
+ return [...new Set(allFields)];
346
+ }
347
+ if (descriptor !== null && typeof descriptor === "object") {
348
+ const allFields = [];
349
+ for (const value of Object.values(descriptor)) {
350
+ allFields.push(...inferFieldsFromDescriptor(value));
351
+ }
352
+ return [...new Set(allFields)];
353
+ }
354
+ return [];
355
+ }
356
+
357
+ // src/conditions/evaluate.ts
358
+ function evaluateConditionMatch(condition, context, fieldValues) {
359
+ let triggerValue;
360
+ if (condition.when !== void 0) {
361
+ triggerValue = fieldValues[condition.when];
362
+ } else if (condition.selectWhen !== void 0) {
363
+ if (typeof condition.selectWhen === "string") {
364
+ triggerValue = evaluate(condition.selectWhen, context);
365
+ } else if (typeof condition.selectWhen === "function") {
366
+ return false;
367
+ } else {
368
+ triggerValue = evaluateDescriptor(condition.selectWhen, context);
369
+ }
370
+ } else {
371
+ return false;
372
+ }
373
+ if (condition.is !== void 0) {
374
+ return triggerValue === condition.is;
375
+ }
376
+ if (condition.truthy !== void 0) {
377
+ const isTruthy = Boolean(triggerValue);
378
+ return condition.truthy ? isTruthy : !isTruthy;
379
+ }
380
+ return Boolean(triggerValue);
381
+ }
382
+ function evaluateConditions(input) {
383
+ const { conditions, fieldValues, fieldStates, record, props } = input;
384
+ const context = buildEvaluationContext(fieldValues, record, props, fieldStates);
385
+ let disabled;
386
+ let visible;
387
+ let setValue;
388
+ let hasDisabledCondition = false;
389
+ let hasVisibleCondition = false;
390
+ let hasSetCondition = false;
391
+ for (const condition of conditions) {
392
+ const isMatched = evaluateConditionMatch(condition, context, fieldValues);
393
+ if (!isMatched) {
394
+ continue;
395
+ }
396
+ if (condition.disabled !== void 0) {
397
+ hasDisabledCondition = true;
398
+ disabled = (disabled ?? false) || condition.disabled;
399
+ }
400
+ if (condition.visible !== void 0) {
401
+ hasVisibleCondition = true;
402
+ visible = visible === void 0 ? condition.visible : visible && condition.visible;
403
+ }
404
+ if (condition.set !== void 0) {
405
+ hasSetCondition = true;
406
+ setValue = condition.set;
407
+ } else if (condition.selectSet !== void 0) {
408
+ hasSetCondition = true;
409
+ if (typeof condition.selectSet === "string") {
410
+ setValue = unwrapFieldProxy(evaluate(condition.selectSet, context));
411
+ } else if (typeof condition.selectSet === "function") {
412
+ setValue = condition.selectSet;
413
+ } else {
414
+ setValue = unwrapFieldProxy(evaluateDescriptor(condition.selectSet, context));
415
+ }
416
+ }
417
+ }
418
+ return {
419
+ disabled: hasDisabledCondition ? disabled : void 0,
420
+ visible: hasVisibleCondition ? visible : void 0,
421
+ setValue: hasSetCondition ? setValue : void 0,
422
+ hasDisabledCondition,
423
+ hasVisibleCondition,
424
+ hasSetCondition
425
+ };
426
+ }
427
+ function conditionMatches(condition, fieldValues, record, props) {
428
+ const context = buildEvaluationContext(fieldValues, record, props);
429
+ return evaluateConditionMatch(condition, context, fieldValues);
430
+ }
431
+ function mergeConditionResults(results) {
432
+ let disabled;
433
+ let visible;
434
+ let setValue;
435
+ let hasDisabledCondition = false;
436
+ let hasVisibleCondition = false;
437
+ let hasSetCondition = false;
438
+ for (const result of results) {
439
+ if (result.hasDisabledCondition) {
440
+ hasDisabledCondition = true;
441
+ disabled = (disabled ?? false) || (result.disabled ?? false);
442
+ }
443
+ if (result.hasVisibleCondition) {
444
+ hasVisibleCondition = true;
445
+ visible = visible === void 0 ? result.visible : visible && (result.visible ?? true);
446
+ }
447
+ if (result.hasSetCondition) {
448
+ hasSetCondition = true;
449
+ setValue = result.setValue;
450
+ }
451
+ }
452
+ return {
453
+ disabled: hasDisabledCondition ? disabled : void 0,
454
+ visible: hasVisibleCondition ? visible : void 0,
455
+ setValue: hasSetCondition ? setValue : void 0,
456
+ hasDisabledCondition,
457
+ hasVisibleCondition,
458
+ hasSetCondition
459
+ };
460
+ }
461
+ function inferFieldsFromConditions(conditions) {
462
+ const fields = [];
463
+ for (const condition of conditions) {
464
+ if (condition.when !== void 0) {
465
+ fields.push(condition.when);
466
+ }
467
+ if (condition.selectWhen !== void 0) {
468
+ fields.push(...inferFieldsFromDescriptor(condition.selectWhen));
469
+ }
470
+ if (condition.selectSet !== void 0) {
471
+ fields.push(...inferFieldsFromDescriptor(condition.selectSet));
472
+ }
473
+ if (condition.subscribesTo !== void 0) {
474
+ fields.push(...condition.subscribesTo);
475
+ }
476
+ }
477
+ return [...new Set(fields)];
478
+ }
479
+
480
+ // src/validation/validate.ts
481
+ function runSingleValidator(validator, value, formValues) {
482
+ try {
483
+ return validator(value, formValues);
484
+ } catch (error) {
485
+ return {
486
+ type: "validation_error",
487
+ message: error instanceof Error ? error.message : "Validation error"
488
+ };
489
+ }
490
+ }
491
+ function resolveNamedValidator(name, validators) {
492
+ const validator = validators[name];
493
+ if (typeof validator === "function") {
494
+ return validator;
495
+ }
496
+ return void 0;
497
+ }
498
+ async function runValidator(spec, value, formValues, namedValidators) {
499
+ if (Array.isArray(spec)) {
500
+ for (const item of spec) {
501
+ const result = await runValidator(item, value, formValues, namedValidators);
502
+ if (!isValid(result)) {
503
+ return result;
504
+ }
505
+ }
506
+ return true;
507
+ }
508
+ if (typeof spec === "string") {
509
+ if (!namedValidators) {
510
+ console.warn(`Named validator "${spec}" requested but no validators provided`);
511
+ return true;
512
+ }
513
+ const validator = resolveNamedValidator(spec, namedValidators);
514
+ if (!validator) {
515
+ console.warn(`Validator "${spec}" not found in validators config`);
516
+ return true;
517
+ }
518
+ const result = runSingleValidator(validator, value, formValues);
519
+ return Promise.resolve(result);
520
+ }
521
+ if (typeof spec === "function") {
522
+ const result = runSingleValidator(spec, value, formValues);
523
+ return Promise.resolve(result);
524
+ }
525
+ return true;
526
+ }
527
+ function runValidatorSync(spec, value, formValues, namedValidators) {
528
+ if (Array.isArray(spec)) {
529
+ for (const item of spec) {
530
+ const result = runValidatorSync(item, value, formValues, namedValidators);
531
+ if (!isValid(result)) {
532
+ return result;
533
+ }
534
+ }
535
+ return true;
536
+ }
537
+ if (typeof spec === "string") {
538
+ if (!namedValidators) {
539
+ return true;
540
+ }
541
+ const validator = resolveNamedValidator(spec, namedValidators);
542
+ if (!validator) {
543
+ return true;
544
+ }
545
+ const result = validator(value, formValues);
546
+ return result;
547
+ }
548
+ if (typeof spec === "function") {
549
+ const result = spec(value, formValues);
550
+ return result;
551
+ }
552
+ return true;
553
+ }
554
+ function isValid(result) {
555
+ if (result === true || result === void 0) {
556
+ return true;
557
+ }
558
+ return false;
559
+ }
560
+ function composeValidators(validators, namedValidators) {
561
+ return async (value, formValues) => {
562
+ for (const spec of validators) {
563
+ const result = await runValidator(spec, value, formValues, namedValidators);
564
+ if (!isValid(result)) {
565
+ return result;
566
+ }
567
+ }
568
+ return true;
569
+ };
570
+ }
571
+ function required() {
572
+ return (value) => {
573
+ if (value === void 0 || value === null || value === "") {
574
+ return { type: "required", message: "This field is required" };
575
+ }
576
+ if (Array.isArray(value) && value.length === 0) {
577
+ return { type: "required", message: "This field is required" };
578
+ }
579
+ return true;
580
+ };
581
+ }
582
+ function minLength(length) {
583
+ return (value) => {
584
+ if (typeof value !== "string") {
585
+ return true;
586
+ }
587
+ if (value.length < length) {
588
+ return {
589
+ type: "minLength",
590
+ message: `Must be at least ${length} characters`
591
+ };
592
+ }
593
+ return true;
594
+ };
595
+ }
596
+ function maxLength(length) {
597
+ return (value) => {
598
+ if (typeof value !== "string") {
599
+ return true;
600
+ }
601
+ if (value.length > length) {
602
+ return {
603
+ type: "maxLength",
604
+ message: `Must be at most ${length} characters`
605
+ };
606
+ }
607
+ return true;
608
+ };
609
+ }
610
+ function pattern(pattern2, message) {
611
+ return (value) => {
612
+ if (typeof value !== "string") {
613
+ return true;
614
+ }
615
+ if (!pattern2.test(value)) {
616
+ return {
617
+ type: "pattern",
618
+ message: message ?? "Invalid format"
619
+ };
620
+ }
621
+ return true;
622
+ };
623
+ }
624
+
625
+ // src/validation/messages.ts
626
+ function resolveErrorMessage(result, errorMessages) {
627
+ if (result === true || result === void 0) {
628
+ return void 0;
629
+ }
630
+ if (typeof result === "string") {
631
+ return result;
632
+ }
633
+ if (result === false) {
634
+ return errorMessages?.["invalid"] ?? "Invalid value";
635
+ }
636
+ if (typeof result === "object" && result !== null) {
637
+ if (result.message) {
638
+ return result.message;
639
+ }
640
+ if (result.type && errorMessages?.[result.type]) {
641
+ return errorMessages[result.type];
642
+ }
643
+ if (result.type) {
644
+ return formatTypeAsMessage(result.type);
645
+ }
646
+ return "Invalid value";
647
+ }
648
+ return "Invalid value";
649
+ }
650
+ function formatTypeAsMessage(type) {
651
+ const words = type.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/_/g, " ").toLowerCase();
652
+ return words.charAt(0).toUpperCase() + words.slice(1);
653
+ }
654
+ function createErrorMessages(overrides) {
655
+ const defaults = {
656
+ required: "This field is required",
657
+ invalid: "Invalid value",
658
+ minLength: "Too short",
659
+ maxLength: "Too long",
660
+ pattern: "Invalid format",
661
+ min: "Value is too small",
662
+ max: "Value is too large",
663
+ email: "Invalid email address",
664
+ url: "Invalid URL",
665
+ number: "Must be a number",
666
+ integer: "Must be a whole number",
667
+ positive: "Must be positive",
668
+ negative: "Must be negative",
669
+ date: "Invalid date",
670
+ phone: "Invalid phone number",
671
+ unique: "Must be unique",
672
+ match: "Fields do not match",
673
+ validate: "Validation failed"
674
+ };
675
+ return {
676
+ ...defaults,
677
+ ...overrides
678
+ };
679
+ }
680
+ function getErrorType(result) {
681
+ if (result === true || result === void 0) {
682
+ return void 0;
683
+ }
684
+ if (result === false) {
685
+ return "invalid";
686
+ }
687
+ if (typeof result === "string") {
688
+ return "validate";
689
+ }
690
+ if (typeof result === "object" && result !== null) {
691
+ return result.type || "validate";
692
+ }
693
+ return "validate";
694
+ }
695
+ function createValidationError(type, message, errorMessages) {
696
+ const resolvedMessage = message ?? errorMessages?.[type] ?? formatTypeAsMessage(type);
697
+ return {
698
+ type,
699
+ message: resolvedMessage
700
+ };
701
+ }
702
+
703
+ // src/transform/pipeline.ts
704
+ function parse(value, parserSpec, namedParsers) {
705
+ if (parserSpec === void 0) {
706
+ return value;
707
+ }
708
+ if (typeof parserSpec === "string") {
709
+ const parser = namedParsers?.[parserSpec];
710
+ if (!parser) {
711
+ if (process.env.NODE_ENV !== "production") {
712
+ console.warn(`Parser "${parserSpec}" not found in parsers config`);
713
+ }
714
+ return value;
715
+ }
716
+ try {
717
+ return parser(value);
718
+ } catch (error) {
719
+ if (process.env.NODE_ENV !== "production") {
720
+ console.warn(`Parser "${parserSpec}" threw error:`, error);
721
+ }
722
+ return value;
723
+ }
724
+ }
725
+ if (typeof parserSpec === "function") {
726
+ try {
727
+ return parserSpec(value);
728
+ } catch (error) {
729
+ if (process.env.NODE_ENV !== "production") {
730
+ console.warn("Inline parser threw error:", error);
731
+ }
732
+ return value;
733
+ }
734
+ }
735
+ return value;
736
+ }
737
+ function format(value, formatterSpec, namedFormatters) {
738
+ if (formatterSpec === void 0) {
739
+ return value;
740
+ }
741
+ if (typeof formatterSpec === "string") {
742
+ const formatter = namedFormatters?.[formatterSpec];
743
+ if (!formatter) {
744
+ if (process.env.NODE_ENV !== "production") {
745
+ console.warn(`Formatter "${formatterSpec}" not found in formatters config`);
746
+ }
747
+ return value;
748
+ }
749
+ try {
750
+ return formatter(value);
751
+ } catch (error) {
752
+ if (process.env.NODE_ENV !== "production") {
753
+ console.warn(`Formatter "${formatterSpec}" threw error:`, error);
754
+ }
755
+ return value;
756
+ }
757
+ }
758
+ if (typeof formatterSpec === "function") {
759
+ try {
760
+ return formatterSpec(value);
761
+ } catch (error) {
762
+ if (process.env.NODE_ENV !== "production") {
763
+ console.warn("Inline formatter threw error:", error);
764
+ }
765
+ return value;
766
+ }
767
+ }
768
+ return value;
769
+ }
770
+ function extractValueField(value, valueField) {
771
+ if (!valueField) {
772
+ return value;
773
+ }
774
+ if (value === null || value === void 0) {
775
+ return value;
776
+ }
777
+ if (typeof value !== "object") {
778
+ return value;
779
+ }
780
+ return value[valueField];
781
+ }
782
+ function transformFieldName(fieldName, getSubmitField) {
783
+ if (!getSubmitField) {
784
+ return fieldName;
785
+ }
786
+ return getSubmitField(fieldName);
787
+ }
788
+ function createFloatParser(fallback = 0) {
789
+ return (value) => {
790
+ const parsed = parseFloat(String(value));
791
+ return isNaN(parsed) ? fallback : parsed;
792
+ };
793
+ }
794
+ function createFloatFormatter(precision = 2) {
795
+ return (value) => {
796
+ if (typeof value !== "number" || isNaN(value)) {
797
+ return "";
798
+ }
799
+ return value.toFixed(precision);
800
+ };
801
+ }
802
+ function createIntParser(fallback = 0) {
803
+ return (value) => {
804
+ const parsed = parseInt(String(value), 10);
805
+ return isNaN(parsed) ? fallback : parsed;
806
+ };
807
+ }
808
+ function createTrimParser() {
809
+ return (value) => {
810
+ if (typeof value !== "string") {
811
+ return value;
812
+ }
813
+ return value.trim();
814
+ };
815
+ }
816
+ function createDefaultParsers() {
817
+ return {
818
+ float: createFloatParser(),
819
+ int: createIntParser(),
820
+ integer: createIntParser(),
821
+ trim: createTrimParser(),
822
+ string: (value) => String(value ?? "")
823
+ };
824
+ }
825
+ function createDefaultFormatters() {
826
+ return {
827
+ float: createFloatFormatter(2),
828
+ float2: createFloatFormatter(2),
829
+ float3: createFloatFormatter(3),
830
+ float4: createFloatFormatter(4),
831
+ percent: createFloatFormatter(2),
832
+ percent3: createFloatFormatter(3),
833
+ integer: (value) => {
834
+ if (typeof value !== "number" || isNaN(value)) {
835
+ return "";
836
+ }
837
+ return Math.round(value).toString();
838
+ },
839
+ string: (value) => String(value ?? "")
840
+ };
841
+ }
842
+
843
+ // src/config/merge.ts
844
+ function deepMerge(base, override) {
845
+ if (!override) {
846
+ return base;
847
+ }
848
+ const result = { ...base };
849
+ for (const key in override) {
850
+ const baseValue = base[key];
851
+ const overrideValue = override[key];
852
+ if (overrideValue === void 0) {
853
+ continue;
854
+ }
855
+ if (typeof baseValue === "object" && baseValue !== null && typeof overrideValue === "object" && overrideValue !== null && !Array.isArray(baseValue) && !Array.isArray(overrideValue)) {
856
+ result[key] = deepMerge(
857
+ baseValue,
858
+ overrideValue
859
+ );
860
+ } else {
861
+ result[key] = overrideValue;
862
+ }
863
+ }
864
+ return result;
865
+ }
866
+ function mergeInputConfigs(providerInputs, formInputs) {
867
+ if (!formInputs) {
868
+ return providerInputs;
869
+ }
870
+ if (typeof formInputs === "function") {
871
+ const transformed = formInputs(providerInputs);
872
+ return mergeInputConfigs(providerInputs, transformed);
873
+ }
874
+ const result = { ...providerInputs };
875
+ for (const [type, overrides] of Object.entries(formInputs)) {
876
+ if (result[type]) {
877
+ result[type] = deepMerge(result[type], overrides);
878
+ } else {
879
+ result[type] = overrides;
880
+ }
881
+ }
882
+ return result;
883
+ }
884
+ function resolveInputConfig(type, inputs, defaultType = "textField") {
885
+ return inputs[type] ?? inputs[defaultType];
886
+ }
887
+ function resolveFieldType(componentType, fieldConfig, defaultType = "textField") {
888
+ return componentType ?? fieldConfig?.type ?? defaultType;
889
+ }
890
+ function mergeStaticProps(...layers) {
891
+ const result = {};
892
+ for (const layer of layers) {
893
+ if (layer) {
894
+ Object.assign(result, layer);
895
+ }
896
+ }
897
+ return result;
898
+ }
899
+ function mergeFieldProps(options) {
900
+ const {
901
+ providerDefaultFieldProps,
902
+ providerSelectDefaultFieldProps,
903
+ formDefaultFieldProps,
904
+ formSelectDefaultFieldProps,
905
+ inputProps,
906
+ fieldConfigProps,
907
+ selectProps,
908
+ componentProps,
909
+ coreProps
910
+ } = options;
911
+ return mergeStaticProps(
912
+ providerDefaultFieldProps,
913
+ providerSelectDefaultFieldProps,
914
+ formDefaultFieldProps,
915
+ formSelectDefaultFieldProps,
916
+ inputProps,
917
+ fieldConfigProps,
918
+ selectProps,
919
+ componentProps,
920
+ coreProps
921
+ // Core props always win (name, value, onChange, etc.)
922
+ );
923
+ }
924
+ function createConfigContext(providerConfig, formConfig) {
925
+ const mergedInputs = mergeInputConfigs(
926
+ providerConfig.inputs,
927
+ formConfig?.inputs
928
+ );
929
+ return {
930
+ inputs: mergedInputs,
931
+ formatters: providerConfig.formatters ?? {},
932
+ parsers: providerConfig.parsers ?? {},
933
+ validators: providerConfig.validators ?? {},
934
+ errorMessages: providerConfig.errorMessages ?? {},
935
+ defaultFieldProps: mergeStaticProps(
936
+ providerConfig.defaultFieldProps,
937
+ formConfig?.defaultFieldProps
938
+ ),
939
+ selectDefaultFieldProps: formConfig?.selectDefaultFieldProps ?? providerConfig.selectDefaultFieldProps
940
+ };
941
+ }
942
+
943
+ // src/config/defaults.ts
944
+ function resolveInitialValue(fieldName, fieldConfig, inputConfig, record, defaultValues) {
945
+ if (defaultValues && fieldName in defaultValues) {
946
+ return defaultValues[fieldName];
947
+ }
948
+ const recordKey = fieldConfig?.recordKey ?? fieldName;
949
+ if (record && recordKey in record) {
950
+ return record[recordKey];
951
+ }
952
+ if (inputConfig?.defaultValue !== void 0) {
953
+ return inputConfig.defaultValue;
954
+ }
955
+ return void 0;
956
+ }
957
+ function resolveAllInitialValues(fieldConfigs, inputs, record, defaultValues) {
958
+ const result = {};
959
+ for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
960
+ const type = fieldConfig.type ?? "textField";
961
+ const inputConfig = inputs[type];
962
+ const value = resolveInitialValue(
963
+ fieldName,
964
+ fieldConfig,
965
+ inputConfig,
966
+ record,
967
+ defaultValues
968
+ );
969
+ if (value !== void 0) {
970
+ result[fieldName] = value;
971
+ }
972
+ }
973
+ if (defaultValues) {
974
+ for (const [fieldName, value] of Object.entries(defaultValues)) {
975
+ if (!(fieldName in result)) {
976
+ result[fieldName] = value;
977
+ }
978
+ }
979
+ }
980
+ return result;
981
+ }
982
+ function isEmptyValue(value) {
983
+ if (value === void 0 || value === null) {
984
+ return true;
985
+ }
986
+ if (value === "") {
987
+ return true;
988
+ }
989
+ if (Array.isArray(value) && value.length === 0) {
990
+ return true;
991
+ }
992
+ return false;
993
+ }
994
+ function getInputDefaultValue(inputConfig, typeName) {
995
+ if (inputConfig?.defaultValue !== void 0) {
996
+ return inputConfig.defaultValue;
997
+ }
998
+ if (typeName) {
999
+ switch (typeName) {
1000
+ case "switch":
1001
+ case "checkbox":
1002
+ return false;
1003
+ case "number":
1004
+ case "decimal":
1005
+ case "integer":
1006
+ return 0;
1007
+ case "select":
1008
+ case "autocomplete":
1009
+ return null;
1010
+ case "multiSelect":
1011
+ case "checkboxGroup":
1012
+ return [];
1013
+ case "textField":
1014
+ case "text":
1015
+ case "textarea":
1016
+ case "email":
1017
+ case "password":
1018
+ default:
1019
+ return "";
1020
+ }
1021
+ }
1022
+ return "";
1023
+ }
1024
+ function mergeRecordWithDefaults(record, defaults) {
1025
+ const result = {};
1026
+ if (defaults) {
1027
+ Object.assign(result, defaults);
1028
+ }
1029
+ if (record) {
1030
+ for (const [key, value] of Object.entries(record)) {
1031
+ result[key] = value;
1032
+ }
1033
+ }
1034
+ return result;
1035
+ }
1036
+
1037
+ // src/labels/resolve.ts
1038
+ function humanizeLabel(fieldName) {
1039
+ if (!fieldName) {
1040
+ return "";
1041
+ }
1042
+ if (/[^a-zA-Z0-9]/.test(fieldName)) {
1043
+ return fieldName.charAt(0).toUpperCase() + fieldName.slice(1);
1044
+ }
1045
+ const words = fieldName.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").split(" ");
1046
+ return words.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
1047
+ }
1048
+ function resolveLabel(fieldName, fieldConfig, evaluatedSelectProps, componentProps) {
1049
+ if (componentProps?.label !== void 0) {
1050
+ return String(componentProps.label);
1051
+ }
1052
+ if (fieldConfig?.props?.label !== void 0) {
1053
+ return String(fieldConfig.props.label);
1054
+ }
1055
+ if (evaluatedSelectProps?.label !== void 0) {
1056
+ return String(evaluatedSelectProps.label);
1057
+ }
1058
+ if (fieldConfig?.label !== void 0) {
1059
+ return fieldConfig.label;
1060
+ }
1061
+ if (fieldConfig?.title !== void 0) {
1062
+ return fieldConfig.title;
1063
+ }
1064
+ return humanizeLabel(fieldName);
1065
+ }
1066
+ function resolveFormTitle(formTitle, evaluatedSelectTitle) {
1067
+ if (evaluatedSelectTitle !== void 0 && evaluatedSelectTitle !== null) {
1068
+ return String(evaluatedSelectTitle);
1069
+ }
1070
+ return formTitle;
1071
+ }
1072
+ function isAutoGeneratedLabel(fieldName, label) {
1073
+ return humanizeLabel(fieldName) === label;
1074
+ }
1075
+ function createLabelWithUnit(baseLabel, unit) {
1076
+ return `${baseLabel} (${unit})`;
1077
+ }
1078
+ function parseLabelWithUnit(label) {
1079
+ const match = label.match(/^(.+)\s*\(([^)]+)\)$/);
1080
+ if (match) {
1081
+ return {
1082
+ base: match[1].trim(),
1083
+ unit: match[2]
1084
+ };
1085
+ }
1086
+ return { base: label };
1087
+ }
1088
+ function sortFieldsByOrder(fieldNames, fieldConfigs) {
1089
+ return [...fieldNames].sort((a, b) => {
1090
+ const orderA = fieldConfigs[a]?.order ?? Infinity;
1091
+ const orderB = fieldConfigs[b]?.order ?? Infinity;
1092
+ return orderA - orderB;
1093
+ });
1094
+ }
1095
+ function getUnusedFields(allFields, declaredFields) {
1096
+ return allFields.filter((name) => !declaredFields.has(name));
1097
+ }
1098
+ function getOrderedUnusedFields(allFields, declaredFields, fieldConfigs) {
1099
+ const unused = getUnusedFields(allFields, declaredFields);
1100
+ return sortFieldsByOrder(unused, fieldConfigs);
1101
+ }
1102
+
1103
+ export { FIELD_PROXY_MARKER, FIELD_PROXY_VALUE, KEYWORDS, QUALIFIED_PREFIXES, buildEvaluationContext, buildFieldContext, buildFormContext, clearExpressionCache, composeValidators, conditionMatches, createConfigContext, createDefaultFormatters, createDefaultParsers, createErrorMessages, createFieldStateProxy, createFloatFormatter, createFloatParser, createIntParser, createLabelWithUnit, createTrimParser, createValidationError, deepMerge, evaluate, evaluateConditions, evaluateDescriptor, extractValueField, format, formatTypeAsMessage, getErrorType, getInputDefaultValue, getOrderedUnusedFields, getUnusedFields, humanizeLabel, inferFieldsFromConditions, inferFieldsFromDescriptor, inferFieldsFromExpression, isAutoGeneratedLabel, isEmptyValue, isFieldProxy, isValid, maxLength, mergeConditionResults, mergeFieldProps, mergeInputConfigs, mergeRecordWithDefaults, mergeStaticProps, minLength, parse, parseLabelWithUnit, pattern, required, resolveAllInitialValues, resolveErrorMessage, resolveFieldType, resolveFormTitle, resolveInitialValue, resolveInputConfig, resolveLabel, runValidator, runValidatorSync, sortFieldsByOrder, transformFieldName, unwrapFieldProxy };
1104
+ //# sourceMappingURL=index.js.map
1105
+ //# sourceMappingURL=index.js.map