@fogpipe/forma-core 0.11.2 → 0.12.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -35,12 +35,19 @@ __export(index_exports, {
35
35
  getFormattedValue: () => getFormattedValue,
36
36
  getOptionsVisibility: () => getOptionsVisibility,
37
37
  getPageVisibility: () => getPageVisibility,
38
+ getReadonly: () => getReadonly,
38
39
  getRequired: () => getRequired,
39
40
  getVisibility: () => getVisibility,
40
41
  getVisibleOptions: () => getVisibleOptions,
42
+ isAdornableField: () => isAdornableField,
43
+ isArrayField: () => isArrayField,
44
+ isDataField: () => isDataField,
45
+ isDisplayField: () => isDisplayField,
41
46
  isEnabled: () => isEnabled,
42
47
  isFieldVisible: () => isFieldVisible,
48
+ isReadonly: () => isReadonly,
43
49
  isRequired: () => isRequired,
50
+ isSelectionField: () => isSelectionField,
44
51
  isValidExpression: () => isValidExpression,
45
52
  isValidFormat: () => isValidFormat,
46
53
  parseDecimalFormat: () => parseDecimalFormat,
@@ -50,6 +57,32 @@ __export(index_exports, {
50
57
  });
51
58
  module.exports = __toCommonJS(index_exports);
52
59
 
60
+ // src/types.ts
61
+ var ADORNABLE_TYPES = /* @__PURE__ */ new Set([
62
+ "text",
63
+ "email",
64
+ "url",
65
+ "password",
66
+ "textarea",
67
+ "number",
68
+ "integer"
69
+ ]);
70
+ function isAdornableField(field) {
71
+ return ADORNABLE_TYPES.has(field.type);
72
+ }
73
+ function isDisplayField(field) {
74
+ return field.type === "display";
75
+ }
76
+ function isSelectionField(field) {
77
+ return field.type === "select" || field.type === "multiselect";
78
+ }
79
+ function isArrayField(field) {
80
+ return field.type === "array";
81
+ }
82
+ function isDataField(field) {
83
+ return field.type !== "display";
84
+ }
85
+
53
86
  // src/feel/index.ts
54
87
  var import_feelin = require("feelin");
55
88
  function buildFeelContext(ctx) {
@@ -406,7 +439,7 @@ function processArrayItemOptions(arrayPath, fieldDef, arrayData, baseContext, re
406
439
  itemIndex: i
407
440
  };
408
441
  for (const [itemFieldName, itemFieldDef] of Object.entries(fieldDef.itemFields)) {
409
- if (itemFieldDef.options && itemFieldDef.options.length > 0) {
442
+ if (isSelectionField(itemFieldDef) && itemFieldDef.options && itemFieldDef.options.length > 0) {
410
443
  const itemFieldPath = `${arrayPath}[${i}].${itemFieldName}`;
411
444
  result[itemFieldPath] = filterOptionsByContext(itemFieldDef.options, itemContext);
412
445
  }
@@ -438,7 +471,7 @@ function evaluateFieldVisibility(path, fieldDef, data, context, result) {
438
471
  if (!result[path]) {
439
472
  return;
440
473
  }
441
- if (fieldDef.itemFields) {
474
+ if (isArrayField(fieldDef) && fieldDef.itemFields) {
442
475
  const arrayData = data[path];
443
476
  if (Array.isArray(arrayData)) {
444
477
  evaluateArrayItemVisibility(path, fieldDef, arrayData, context, result);
@@ -511,10 +544,10 @@ function getOptionsVisibility(data, spec, options = {}) {
511
544
  for (const fieldPath of spec.fieldOrder) {
512
545
  const fieldDef = spec.fields[fieldPath];
513
546
  if (!fieldDef) continue;
514
- if (fieldDef.options && fieldDef.options.length > 0) {
547
+ if (isSelectionField(fieldDef) && fieldDef.options && fieldDef.options.length > 0) {
515
548
  result[fieldPath] = filterOptionsByContext(fieldDef.options, baseContext);
516
549
  }
517
- if (fieldDef.itemFields) {
550
+ if (isArrayField(fieldDef) && fieldDef.itemFields) {
518
551
  const arrayData = data[fieldPath];
519
552
  if (Array.isArray(arrayData)) {
520
553
  processArrayItemOptions(fieldPath, fieldDef, arrayData, baseContext, result);
@@ -552,7 +585,7 @@ function getRequired(data, spec, options = {}) {
552
585
  }
553
586
  }
554
587
  for (const [fieldPath, fieldDef] of Object.entries(spec.fields)) {
555
- if (fieldDef.itemFields) {
588
+ if (fieldDef.type === "array" && fieldDef.itemFields) {
556
589
  const arrayData = data[fieldPath];
557
590
  if (Array.isArray(arrayData)) {
558
591
  for (let i = 0; i < arrayData.length; i++) {
@@ -617,23 +650,10 @@ function getEnabled(data, spec, options = {}) {
617
650
  }
618
651
  }
619
652
  for (const [fieldPath, fieldDef] of Object.entries(spec.fields)) {
620
- if (fieldDef.itemFields) {
653
+ if (fieldDef.type === "array" && fieldDef.itemFields) {
621
654
  const arrayData = data[fieldPath];
622
655
  if (Array.isArray(arrayData)) {
623
- for (let i = 0; i < arrayData.length; i++) {
624
- const item = arrayData[i];
625
- const itemContext = {
626
- data,
627
- computed,
628
- referenceData: spec.referenceData,
629
- item,
630
- itemIndex: i
631
- };
632
- for (const [itemFieldName, itemFieldDef] of Object.entries(fieldDef.itemFields)) {
633
- const itemFieldPath = `${fieldPath}[${i}].${itemFieldName}`;
634
- result[itemFieldPath] = isFieldEnabled(itemFieldDef, itemContext);
635
- }
636
- }
656
+ evaluateArrayItemEnabled(fieldPath, fieldDef, arrayData, data, computed, spec, result);
637
657
  }
638
658
  }
639
659
  }
@@ -645,6 +665,23 @@ function isFieldEnabled(fieldDef, context) {
645
665
  }
646
666
  return true;
647
667
  }
668
+ function evaluateArrayItemEnabled(arrayPath, fieldDef, arrayData, data, computed, spec, result) {
669
+ if (!fieldDef.itemFields) return;
670
+ for (let i = 0; i < arrayData.length; i++) {
671
+ const item = arrayData[i];
672
+ const itemContext = {
673
+ data,
674
+ computed,
675
+ referenceData: spec.referenceData,
676
+ item,
677
+ itemIndex: i
678
+ };
679
+ for (const [itemFieldName, itemFieldDef] of Object.entries(fieldDef.itemFields)) {
680
+ const itemFieldPath = `${arrayPath}[${i}].${itemFieldName}`;
681
+ result[itemFieldPath] = isFieldEnabled(itemFieldDef, itemContext);
682
+ }
683
+ }
684
+ }
648
685
  function isEnabled(fieldPath, data, spec) {
649
686
  const fieldDef = spec.fields[fieldPath];
650
687
  if (!fieldDef) {
@@ -662,6 +699,71 @@ function isEnabled(fieldPath, data, spec) {
662
699
  return evaluateBoolean(fieldDef.enabledWhen, context);
663
700
  }
664
701
 
702
+ // src/engine/readonly.ts
703
+ function getReadonly(data, spec, options = {}) {
704
+ const computed = options.computed ?? calculate(data, spec);
705
+ const context = {
706
+ data,
707
+ computed,
708
+ referenceData: spec.referenceData
709
+ };
710
+ const result = {};
711
+ for (const fieldPath of spec.fieldOrder) {
712
+ const fieldDef = spec.fields[fieldPath];
713
+ if (fieldDef) {
714
+ result[fieldPath] = isFieldReadonly(fieldDef, context);
715
+ }
716
+ }
717
+ for (const [fieldPath, fieldDef] of Object.entries(spec.fields)) {
718
+ if (fieldDef.type === "array" && fieldDef.itemFields) {
719
+ const arrayData = data[fieldPath];
720
+ if (Array.isArray(arrayData)) {
721
+ evaluateArrayItemReadonly(fieldPath, fieldDef, arrayData, data, computed, spec, result);
722
+ }
723
+ }
724
+ }
725
+ return result;
726
+ }
727
+ function isFieldReadonly(fieldDef, context) {
728
+ if (fieldDef.readonlyWhen) {
729
+ return evaluateBoolean(fieldDef.readonlyWhen, context);
730
+ }
731
+ return false;
732
+ }
733
+ function evaluateArrayItemReadonly(arrayPath, fieldDef, arrayData, data, computed, spec, result) {
734
+ if (!fieldDef.itemFields) return;
735
+ for (let i = 0; i < arrayData.length; i++) {
736
+ const item = arrayData[i];
737
+ const itemContext = {
738
+ data,
739
+ computed,
740
+ referenceData: spec.referenceData,
741
+ item,
742
+ itemIndex: i
743
+ };
744
+ for (const [itemFieldName, itemFieldDef] of Object.entries(fieldDef.itemFields)) {
745
+ const itemFieldPath = `${arrayPath}[${i}].${itemFieldName}`;
746
+ result[itemFieldPath] = isFieldReadonly(itemFieldDef, itemContext);
747
+ }
748
+ }
749
+ }
750
+ function isReadonly(fieldPath, data, spec) {
751
+ const fieldDef = spec.fields[fieldPath];
752
+ if (!fieldDef) {
753
+ return false;
754
+ }
755
+ if (!fieldDef.readonlyWhen) {
756
+ return false;
757
+ }
758
+ const computed = calculate(data, spec);
759
+ const context = {
760
+ data,
761
+ computed,
762
+ referenceData: spec.referenceData
763
+ };
764
+ return evaluateBoolean(fieldDef.readonlyWhen, context);
765
+ }
766
+
665
767
  // src/engine/validate.ts
666
768
  function validate(data, spec, options = {}) {
667
769
  const { onlyVisible = true } = options;
@@ -674,6 +776,9 @@ function validate(data, spec, options = {}) {
674
776
  if (onlyVisible && visibility[fieldPath] === false) {
675
777
  continue;
676
778
  }
779
+ if (fieldDef.type === "display") {
780
+ continue;
781
+ }
677
782
  const schemaProperty = spec.schema.properties[fieldPath];
678
783
  const fieldErrors = validateField(
679
784
  fieldPath,
@@ -719,7 +824,7 @@ function validateField(path, value, fieldDef, schemaProperty, spec, data, comput
719
824
  const customErrors = validateCustomRules(path, fieldDef.validations, context);
720
825
  errors.push(...customErrors);
721
826
  }
722
- if (Array.isArray(value)) {
827
+ if (Array.isArray(value) && fieldDef.type === "array") {
723
828
  const arrayErrors = validateArray(
724
829
  path,
725
830
  value,
@@ -1107,12 +1212,19 @@ function validateSingleField(fieldPath, data, spec) {
1107
1212
  getFormattedValue,
1108
1213
  getOptionsVisibility,
1109
1214
  getPageVisibility,
1215
+ getReadonly,
1110
1216
  getRequired,
1111
1217
  getVisibility,
1112
1218
  getVisibleOptions,
1219
+ isAdornableField,
1220
+ isArrayField,
1221
+ isDataField,
1222
+ isDisplayField,
1113
1223
  isEnabled,
1114
1224
  isFieldVisible,
1225
+ isReadonly,
1115
1226
  isRequired,
1227
+ isSelectionField,
1116
1228
  isValidExpression,
1117
1229
  isValidFormat,
1118
1230
  parseDecimalFormat,