@ngx-formly/core 7.0.0 → 7.1.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.
Files changed (32) hide show
  1. package/README.md +12 -12
  2. package/esm2022/json-schema/formly-json-schema.service.mjs +102 -2
  3. package/esm2022/lib/components/formly.form.mjs +10 -4
  4. package/esm2022/lib/components/formly.template.mjs +11 -3
  5. package/esm2022/lib/core.config.mjs +35 -5
  6. package/esm2022/lib/core.mjs +3 -3
  7. package/esm2022/lib/core.module.mjs +9 -9
  8. package/esm2022/lib/extensions/field-expression/field-expression.mjs +6 -244
  9. package/esm2022/lib/extensions/field-expression/utils.mjs +453 -11
  10. package/esm2022/lib/extensions/field-expression-legacy/field-expression.mjs +249 -0
  11. package/esm2022/lib/extensions/field-expression-legacy/utils.mjs +20 -0
  12. package/esm2022/lib/utils.mjs +2 -1
  13. package/esm2022/preset/preset-substitution.extension.mjs +2 -2
  14. package/fesm2022/ngx-formly-core-json-schema.mjs +101 -1
  15. package/fesm2022/ngx-formly-core-json-schema.mjs.map +1 -1
  16. package/fesm2022/ngx-formly-core-preset.mjs +1 -1
  17. package/fesm2022/ngx-formly-core-preset.mjs.map +1 -1
  18. package/fesm2022/ngx-formly-core.mjs +532 -17
  19. package/fesm2022/ngx-formly-core.mjs.map +1 -1
  20. package/json-schema/formly-json-schema.service.d.ts +3 -0
  21. package/lib/components/formly.form.d.ts +3 -2
  22. package/lib/components/formly.template.d.ts +5 -1
  23. package/lib/core.config.d.ts +1 -0
  24. package/lib/core.d.ts +3 -3
  25. package/lib/core.module.d.ts +1 -1
  26. package/lib/extensions/field-expression/field-expression.d.ts +3 -12
  27. package/lib/extensions/field-expression/utils.d.ts +4 -2
  28. package/lib/extensions/field-expression-legacy/field-expression.d.ts +16 -0
  29. package/lib/extensions/field-expression-legacy/utils.d.ts +5 -0
  30. package/package.json +1 -1
  31. package/esm2022/lib/extensions/index.mjs +0 -2
  32. package/lib/extensions/index.d.ts +0 -1
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Type, TemplateRef, ComponentRef, ChangeDetectorRef, ɵNoopNgZone as _NoopNgZone, VERSION, Input, ViewChildren, Directive, ChangeDetectionStrategy, Component, Injectable, ViewContainerRef, ViewChild, Optional, InjectionToken, Inject, EventEmitter, ContentChildren, Output, NgModule } from '@angular/core';
2
+ import { Type, TemplateRef, ComponentRef, ChangeDetectorRef, ɵNoopNgZone as _NoopNgZone, VERSION, Input, ViewChildren, Directive, ChangeDetectionStrategy, Component, Injectable, ViewContainerRef, ViewChild, Optional, InjectionToken, inject, Inject, EventEmitter, ContentChildren, Output, NgModule } from '@angular/core';
3
3
  import { isObservable, Observable, Subject, of, merge } from 'rxjs';
4
4
  import * as i2 from '@angular/forms';
5
5
  import { AbstractControl, UntypedFormArray, UntypedFormGroup, FormControl, UntypedFormControl, Validators, NgControl } from '@angular/forms';
@@ -131,6 +131,7 @@ function isPromise(obj) {
131
131
  function clone(value) {
132
132
  if (!isObject(value) ||
133
133
  isObservable(value) ||
134
+ isPromise(value) ||
134
135
  value instanceof TemplateRef ||
135
136
  /* instanceof SafeHtmlImpl */ value.changingThisBreaksApplicationSecurity ||
136
137
  ['RegExp', 'FileList', 'File', 'Blob'].indexOf(value.constructor?.name) !== -1) {
@@ -317,7 +318,10 @@ function isSignalRequired() {
317
318
  return +VERSION.major > 18 || (+VERSION.major >= 18 && +VERSION.minor >= 1);
318
319
  }
319
320
 
320
- function evalStringExpression(expression, argNames) {
321
+ /**
322
+ * Legacy implementation
323
+ */
324
+ function evalStringExpressionLegacy(expression, argNames) {
321
325
  try {
322
326
  return Function(...argNames, `return ${expression};`);
323
327
  }
@@ -432,7 +436,7 @@ function clearControl(form) {
432
436
  }
433
437
  }
434
438
 
435
- class FieldExpressionExtension {
439
+ let FieldExpressionExtension$1 = class FieldExpressionExtension {
436
440
  onPopulate(field) {
437
441
  if (field._expressions) {
438
442
  return;
@@ -515,7 +519,7 @@ class FieldExpressionExtension {
515
519
  }
516
520
  expr = expr || (() => false);
517
521
  if (typeof expr === 'string') {
518
- expr = evalStringExpression(expr, ['model', 'formState', 'field']);
522
+ expr = this._evalStringExpression(expr, ['model', 'formState', 'field']);
519
523
  }
520
524
  let currentValue;
521
525
  return {
@@ -540,6 +544,9 @@ class FieldExpressionExtension {
540
544
  },
541
545
  };
542
546
  }
547
+ _evalStringExpression(expression, argNames) {
548
+ return evalStringExpressionLegacy(expression, argNames);
549
+ }
543
550
  checkExpressions(field, ignoreCache = false) {
544
551
  if (!field) {
545
552
  return false;
@@ -670,6 +677,471 @@ class FieldExpressionExtension {
670
677
  }
671
678
  return paths;
672
679
  }
680
+ };
681
+
682
+ // CSP-compliant expression parser for Formly expressions
683
+ // Supports: model.path, formState.path, field.path, comparisons, logical operators, and negation
684
+ // Tokenizer
685
+ var TokenType;
686
+ (function (TokenType) {
687
+ TokenType["IDENTIFIER"] = "IDENTIFIER";
688
+ TokenType["DOT"] = "DOT";
689
+ TokenType["BRACKET_OPEN"] = "BRACKET_OPEN";
690
+ TokenType["BRACKET_CLOSE"] = "BRACKET_CLOSE";
691
+ TokenType["STRING"] = "STRING";
692
+ TokenType["NUMBER"] = "NUMBER";
693
+ TokenType["BOOLEAN"] = "BOOLEAN";
694
+ TokenType["NULL"] = "NULL";
695
+ TokenType["UNDEFINED"] = "UNDEFINED";
696
+ TokenType["OPERATOR"] = "OPERATOR";
697
+ TokenType["LOGICAL"] = "LOGICAL";
698
+ TokenType["NOT"] = "NOT";
699
+ TokenType["ARITHMETIC"] = "ARITHMETIC";
700
+ TokenType["PAREN_OPEN"] = "PAREN_OPEN";
701
+ TokenType["PAREN_CLOSE"] = "PAREN_CLOSE";
702
+ TokenType["TERNARY_QUESTION"] = "TERNARY_QUESTION";
703
+ TokenType["TERNARY_COLON"] = "TERNARY_COLON";
704
+ TokenType["EOF"] = "EOF";
705
+ })(TokenType || (TokenType = {}));
706
+ class Tokenizer {
707
+ constructor(input) {
708
+ this.pos = 0;
709
+ this.input = input.trim();
710
+ }
711
+ tokenize() {
712
+ const tokens = [];
713
+ while (this.pos < this.input.length) {
714
+ this.skipWhitespace();
715
+ if (this.pos >= this.input.length)
716
+ break;
717
+ const char = this.input[this.pos];
718
+ // String literals
719
+ if (char === '"' || char === "'") {
720
+ tokens.push(this.readString());
721
+ }
722
+ // Numbers
723
+ else if (/\d/.test(char)) {
724
+ tokens.push(this.readNumber());
725
+ }
726
+ // Identifiers and keywords
727
+ else if (/[a-zA-Z_$]/.test(char)) {
728
+ tokens.push(this.readIdentifier());
729
+ }
730
+ // Operators and symbols
731
+ else if (char === '.') {
732
+ tokens.push({ type: TokenType.DOT, value: '.' });
733
+ this.pos++;
734
+ }
735
+ else if (char === '[') {
736
+ tokens.push({ type: TokenType.BRACKET_OPEN, value: '[' });
737
+ this.pos++;
738
+ }
739
+ else if (char === ']') {
740
+ tokens.push({ type: TokenType.BRACKET_CLOSE, value: ']' });
741
+ this.pos++;
742
+ }
743
+ else if (char === '(') {
744
+ tokens.push({ type: TokenType.PAREN_OPEN, value: '(' });
745
+ this.pos++;
746
+ }
747
+ else if (char === ')') {
748
+ tokens.push({ type: TokenType.PAREN_CLOSE, value: ')' });
749
+ this.pos++;
750
+ }
751
+ else if (char === '?') {
752
+ tokens.push({ type: TokenType.TERNARY_QUESTION, value: '?' });
753
+ this.pos++;
754
+ }
755
+ else if (char === ':') {
756
+ tokens.push({ type: TokenType.TERNARY_COLON, value: ':' });
757
+ this.pos++;
758
+ }
759
+ else if (char === '!') {
760
+ if (this.peek() === '=') {
761
+ if (this.input[this.pos + 2] === '=') {
762
+ tokens.push({ type: TokenType.OPERATOR, value: '!==' });
763
+ this.pos += 3;
764
+ }
765
+ else {
766
+ tokens.push({ type: TokenType.OPERATOR, value: '!=' });
767
+ this.pos += 2;
768
+ }
769
+ }
770
+ else {
771
+ tokens.push({ type: TokenType.NOT, value: '!' });
772
+ this.pos++;
773
+ }
774
+ }
775
+ else if (char === '=' || char === '<' || char === '>') {
776
+ tokens.push(this.readOperator());
777
+ }
778
+ else if (char === '+' || char === '*' || char === '/' || char === '%') {
779
+ tokens.push({ type: TokenType.ARITHMETIC, value: char });
780
+ this.pos++;
781
+ }
782
+ else if (char === '-') {
783
+ // Check if this is a negative number or subtraction
784
+ // It's a negative number if preceded by an operator, opening paren, or at the start
785
+ const lastToken = tokens[tokens.length - 1];
786
+ const isNegativeNumber = tokens.length === 0 ||
787
+ lastToken?.type === TokenType.OPERATOR ||
788
+ lastToken?.type === TokenType.LOGICAL ||
789
+ lastToken?.type === TokenType.ARITHMETIC ||
790
+ lastToken?.type === TokenType.PAREN_OPEN ||
791
+ lastToken?.type === TokenType.TERNARY_QUESTION ||
792
+ lastToken?.type === TokenType.TERNARY_COLON;
793
+ if (isNegativeNumber && this.peek() && /\d/.test(this.peek())) {
794
+ tokens.push(this.readNumber());
795
+ }
796
+ else {
797
+ tokens.push({ type: TokenType.ARITHMETIC, value: '-' });
798
+ this.pos++;
799
+ }
800
+ }
801
+ else if (char === '&' && this.peek() === '&') {
802
+ tokens.push({ type: TokenType.LOGICAL, value: '&&' });
803
+ this.pos += 2;
804
+ }
805
+ else if (char === '|' && this.peek() === '|') {
806
+ tokens.push({ type: TokenType.LOGICAL, value: '||' });
807
+ this.pos += 2;
808
+ }
809
+ else {
810
+ throw new Error(`Unexpected character: ${char} at position ${this.pos}`);
811
+ }
812
+ }
813
+ tokens.push({ type: TokenType.EOF, value: null });
814
+ return tokens;
815
+ }
816
+ skipWhitespace() {
817
+ while (this.pos < this.input.length && /\s/.test(this.input[this.pos])) {
818
+ this.pos++;
819
+ }
820
+ }
821
+ peek(offset = 1) {
822
+ return this.input[this.pos + offset] || '';
823
+ }
824
+ readString() {
825
+ const quote = this.input[this.pos];
826
+ this.pos++;
827
+ let value = '';
828
+ while (this.pos < this.input.length && this.input[this.pos] !== quote) {
829
+ if (this.input[this.pos] === '\\') {
830
+ this.pos++;
831
+ if (this.pos < this.input.length) {
832
+ const escaped = this.input[this.pos];
833
+ switch (escaped) {
834
+ case 'n':
835
+ value += '\n';
836
+ break;
837
+ case 't':
838
+ value += '\t';
839
+ break;
840
+ case 'r':
841
+ value += '\r';
842
+ break;
843
+ default:
844
+ value += escaped;
845
+ }
846
+ }
847
+ }
848
+ else {
849
+ value += this.input[this.pos];
850
+ }
851
+ this.pos++;
852
+ }
853
+ this.pos++; // skip closing quote
854
+ return { type: TokenType.STRING, value };
855
+ }
856
+ readNumber() {
857
+ let value = '';
858
+ // Handle negatives
859
+ if (this.input[this.pos] === '-') {
860
+ value += '-';
861
+ this.pos++;
862
+ }
863
+ let hasDecimal = false;
864
+ while (this.pos < this.input.length && /[\d.]/.test(this.input[this.pos])) {
865
+ if (this.input[this.pos] === '.') {
866
+ if (hasDecimal) {
867
+ throw new Error(`Invalid number format: multiple decimal points at position ${this.pos}`);
868
+ }
869
+ hasDecimal = true;
870
+ }
871
+ value += this.input[this.pos];
872
+ this.pos++;
873
+ }
874
+ const parsed = parseFloat(value);
875
+ if (isNaN(parsed)) {
876
+ throw new Error(`Invalid number format: ${value}`);
877
+ }
878
+ return { type: TokenType.NUMBER, value: parsed };
879
+ }
880
+ readIdentifier() {
881
+ let value = '';
882
+ while (this.pos < this.input.length && /[a-zA-Z0-9_$]/.test(this.input[this.pos])) {
883
+ value += this.input[this.pos];
884
+ this.pos++;
885
+ }
886
+ // Check for keywords
887
+ if (value === 'true' || value === 'false') {
888
+ return { type: TokenType.BOOLEAN, value: value === 'true' };
889
+ }
890
+ if (value === 'null') {
891
+ return { type: TokenType.NULL, value: null };
892
+ }
893
+ if (value === 'undefined') {
894
+ return { type: TokenType.UNDEFINED, value: undefined };
895
+ }
896
+ return { type: TokenType.IDENTIFIER, value };
897
+ }
898
+ readOperator() {
899
+ let op = this.input[this.pos];
900
+ this.pos++;
901
+ if (this.pos < this.input.length) {
902
+ const next = this.input[this.pos];
903
+ if ((op === '=' && next === '=') ||
904
+ (op === '!' && next === '=') ||
905
+ (op === '<' && next === '=') ||
906
+ (op === '>' && next === '=')) {
907
+ op += next;
908
+ this.pos++;
909
+ // Check for === or !==
910
+ if (this.pos < this.input.length && this.input[this.pos] === '=') {
911
+ op += '=';
912
+ this.pos++;
913
+ }
914
+ }
915
+ }
916
+ return { type: TokenType.OPERATOR, value: op };
917
+ }
918
+ }
919
+ // Parser and Evaluator
920
+ class ExpressionParser {
921
+ constructor(tokens) {
922
+ this.pos = 0;
923
+ this.tokens = tokens;
924
+ }
925
+ parse() {
926
+ const expr = this.parseTernary();
927
+ return (context) => expr(context);
928
+ }
929
+ parseTernary() {
930
+ const expr = this.parseLogicalOr();
931
+ if (this.current().type === TokenType.TERNARY_QUESTION) {
932
+ this.consume(TokenType.TERNARY_QUESTION);
933
+ const trueExpr = this.parseLogicalOr();
934
+ this.consume(TokenType.TERNARY_COLON);
935
+ const falseExpr = this.parseTernary();
936
+ return (context) => {
937
+ return expr(context) ? trueExpr(context) : falseExpr(context);
938
+ };
939
+ }
940
+ return expr;
941
+ }
942
+ parseLogicalOr() {
943
+ let left = this.parseLogicalAnd();
944
+ while (this.current().type === TokenType.LOGICAL && this.current().value === '||') {
945
+ this.consume(TokenType.LOGICAL);
946
+ const right = this.parseLogicalAnd();
947
+ const prevLeft = left;
948
+ left = (context) => prevLeft(context) || right(context);
949
+ }
950
+ return left;
951
+ }
952
+ parseLogicalAnd() {
953
+ let left = this.parseComparison();
954
+ while (this.current().type === TokenType.LOGICAL && this.current().value === '&&') {
955
+ this.consume(TokenType.LOGICAL);
956
+ const right = this.parseComparison();
957
+ const prevLeft = left;
958
+ left = (context) => prevLeft(context) && right(context);
959
+ }
960
+ return left;
961
+ }
962
+ parseComparison() {
963
+ const left = this.parseAdditive();
964
+ if (this.current().type === TokenType.OPERATOR) {
965
+ const op = this.consume(TokenType.OPERATOR).value;
966
+ const right = this.parseAdditive();
967
+ return (context) => {
968
+ const leftVal = left(context);
969
+ const rightVal = right(context);
970
+ switch (op) {
971
+ case '===':
972
+ return leftVal === rightVal;
973
+ case '!==':
974
+ return leftVal !== rightVal;
975
+ case '==':
976
+ return leftVal == rightVal;
977
+ case '!=':
978
+ return leftVal != rightVal;
979
+ case '<':
980
+ return leftVal < rightVal;
981
+ case '<=':
982
+ return leftVal <= rightVal;
983
+ case '>':
984
+ return leftVal > rightVal;
985
+ case '>=':
986
+ return leftVal >= rightVal;
987
+ default:
988
+ throw new Error(`Unknown operator: ${op}`);
989
+ }
990
+ };
991
+ }
992
+ return left;
993
+ }
994
+ parseAdditive() {
995
+ let left = this.parseMultiplicative();
996
+ while (this.current().type === TokenType.ARITHMETIC &&
997
+ (this.current().value === '+' || this.current().value === '-')) {
998
+ const op = this.consume(TokenType.ARITHMETIC).value;
999
+ const right = this.parseMultiplicative();
1000
+ const prevLeft = left;
1001
+ if (op === '+') {
1002
+ left = (context) => prevLeft(context) + right(context);
1003
+ }
1004
+ else {
1005
+ left = (context) => prevLeft(context) - right(context);
1006
+ }
1007
+ }
1008
+ return left;
1009
+ }
1010
+ parseMultiplicative() {
1011
+ let left = this.parseUnary();
1012
+ while (this.current().type === TokenType.ARITHMETIC &&
1013
+ (this.current().value === '*' || this.current().value === '/' || this.current().value === '%')) {
1014
+ const op = this.consume(TokenType.ARITHMETIC).value;
1015
+ const right = this.parseUnary();
1016
+ const prevLeft = left;
1017
+ if (op === '*') {
1018
+ left = (context) => prevLeft(context) * right(context);
1019
+ }
1020
+ else if (op === '/') {
1021
+ left = (context) => prevLeft(context) / right(context);
1022
+ }
1023
+ else {
1024
+ left = (context) => prevLeft(context) % right(context);
1025
+ }
1026
+ }
1027
+ return left;
1028
+ }
1029
+ parseUnary() {
1030
+ if (this.current().type === TokenType.NOT) {
1031
+ this.consume(TokenType.NOT);
1032
+ const expr = this.parseUnary();
1033
+ return (context) => !expr(context);
1034
+ }
1035
+ return this.parsePrimary();
1036
+ }
1037
+ parsePrimary() {
1038
+ const token = this.current();
1039
+ // Parentheses
1040
+ if (token.type === TokenType.PAREN_OPEN) {
1041
+ this.consume(TokenType.PAREN_OPEN);
1042
+ const expr = this.parseTernary();
1043
+ this.consume(TokenType.PAREN_CLOSE);
1044
+ return expr;
1045
+ }
1046
+ // Literals
1047
+ if (token.type === TokenType.STRING ||
1048
+ token.type === TokenType.NUMBER ||
1049
+ token.type === TokenType.BOOLEAN ||
1050
+ token.type === TokenType.NULL ||
1051
+ token.type === TokenType.UNDEFINED) {
1052
+ const value = token.value;
1053
+ this.pos++;
1054
+ return () => value;
1055
+ }
1056
+ // Property access (model.field, formState.prop, etc)
1057
+ if (token.type === TokenType.IDENTIFIER) {
1058
+ return this.parsePropertyAccess();
1059
+ }
1060
+ throw new Error(`Unexpected token: ${JSON.stringify(token)}`);
1061
+ }
1062
+ parsePropertyAccess() {
1063
+ const path = [];
1064
+ // Read first identifier
1065
+ path.push(this.consume(TokenType.IDENTIFIER).value);
1066
+ // Read rest of path (dots and brackets)
1067
+ while (this.current().type === TokenType.DOT || this.current().type === TokenType.BRACKET_OPEN) {
1068
+ if (this.current().type === TokenType.DOT) {
1069
+ this.consume(TokenType.DOT);
1070
+ path.push(this.consume(TokenType.IDENTIFIER).value);
1071
+ }
1072
+ else {
1073
+ this.consume(TokenType.BRACKET_OPEN);
1074
+ // bracket notation can contain expressions
1075
+ if (this.current().type === TokenType.STRING) {
1076
+ path.push(this.consume(TokenType.STRING).value);
1077
+ }
1078
+ else if (this.current().type === TokenType.NUMBER) {
1079
+ path.push(String(this.consume(TokenType.NUMBER).value));
1080
+ }
1081
+ else {
1082
+ // dynamic property access
1083
+ const expr = this.parseTernary();
1084
+ path.push(expr);
1085
+ }
1086
+ this.consume(TokenType.BRACKET_CLOSE);
1087
+ }
1088
+ }
1089
+ return (context) => {
1090
+ let value = context;
1091
+ for (const segment of path) {
1092
+ if (value === null || value === undefined) {
1093
+ return undefined;
1094
+ }
1095
+ if (typeof segment === 'function') {
1096
+ value = value[segment(context)];
1097
+ }
1098
+ else {
1099
+ value = value[segment];
1100
+ }
1101
+ }
1102
+ return value;
1103
+ };
1104
+ }
1105
+ current() {
1106
+ return this.tokens[this.pos];
1107
+ }
1108
+ consume(expectedType) {
1109
+ const token = this.current();
1110
+ if (token.type !== expectedType) {
1111
+ throw new Error(`Expected ${expectedType}, got ${token.type}`);
1112
+ }
1113
+ this.pos++;
1114
+ return token;
1115
+ }
1116
+ }
1117
+ /**
1118
+ * Uses CSP-safe implementation
1119
+ */
1120
+ function parseExpression(expression, argNames) {
1121
+ try {
1122
+ const tokenizer = new Tokenizer(expression);
1123
+ const tokens = tokenizer.tokenize();
1124
+ const parser = new ExpressionParser(tokens);
1125
+ const evaluator = parser.parse();
1126
+ // Return a function that maps the args to the context
1127
+ return (...args) => {
1128
+ const context = {};
1129
+ argNames.forEach((name, i) => {
1130
+ context[name] = args[i];
1131
+ });
1132
+ return evaluator(context);
1133
+ };
1134
+ }
1135
+ catch (error) {
1136
+ console.error('Expression parse error:', error);
1137
+ return undefined;
1138
+ }
1139
+ }
1140
+
1141
+ class FieldExpressionExtension extends FieldExpressionExtension$1 {
1142
+ _evalStringExpression(expression, argNames) {
1143
+ return parseExpression(expression, argNames);
1144
+ }
673
1145
  }
674
1146
 
675
1147
  class CoreExtension {
@@ -1405,15 +1877,23 @@ class FormlyTemplate {
1405
1877
  this.name = this.name || 'formly-group';
1406
1878
  }
1407
1879
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyTemplate, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
1408
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: FormlyTemplate, selector: "[formlyTemplate]", inputs: { name: ["formlyTemplate", "name"] }, usesOnChanges: true, ngImport: i0 }); }
1880
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: FormlyTemplate, isStandalone: true, selector: "[formlyTemplate]", inputs: { name: ["formlyTemplate", "name"] }, usesOnChanges: true, ngImport: i0 }); }
1409
1881
  }
1410
1882
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyTemplate, decorators: [{
1411
1883
  type: Directive,
1412
- args: [{ selector: '[formlyTemplate]' }]
1884
+ args: [{ selector: '[formlyTemplate]', standalone: true }]
1413
1885
  }], ctorParameters: () => [{ type: i0.TemplateRef }], propDecorators: { name: [{
1414
1886
  type: Input,
1415
1887
  args: ['formlyTemplate']
1416
1888
  }] } });
1889
+ class LegacyFormlyTemplate extends FormlyTemplate {
1890
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LegacyFormlyTemplate, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
1891
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: LegacyFormlyTemplate, selector: "[formlyTemplate]", usesInheritance: true, ngImport: i0 }); }
1892
+ }
1893
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LegacyFormlyTemplate, decorators: [{
1894
+ type: Directive,
1895
+ args: [{ selector: '[formlyTemplate]', standalone: false }]
1896
+ }] });
1417
1897
  // workarround for https://github.com/angular/angular/issues/43227#issuecomment-904173738
1418
1898
  class FormlyFieldTemplates {
1419
1899
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyFieldTemplates, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -1748,7 +2228,22 @@ function withDefaultConfig(config) {
1748
2228
  { name: 'core', extension: new CoreExtension(config), priority: -250 },
1749
2229
  { name: 'field-validation', extension: new FieldValidationExtension(config), priority: -200 },
1750
2230
  { name: 'field-form', extension: new FieldFormExtension(), priority: -150 },
1751
- { name: 'field-expression', extension: new FieldExpressionExtension(), priority: -100 },
2231
+ {
2232
+ name: 'field-expression',
2233
+ extension: new FieldExpressionExtension$1(),
2234
+ priority: -100,
2235
+ },
2236
+ ],
2237
+ };
2238
+ }
2239
+ function withFormlyFieldExpression() {
2240
+ return {
2241
+ extensions: [
2242
+ {
2243
+ name: 'field-expression',
2244
+ extension: new FieldExpressionExtension(),
2245
+ priority: -100,
2246
+ },
1752
2247
  ],
1753
2248
  };
1754
2249
  }
@@ -1759,7 +2254,21 @@ const provideFormlyCore = (configs = []) => {
1759
2254
  ];
1760
2255
  };
1761
2256
  const provideFormlyConfig = (configs = []) => {
1762
- return [{ provide: FORMLY_CONFIG, multi: true, useValue: configs }];
2257
+ return {
2258
+ provide: FORMLY_CONFIG,
2259
+ multi: true,
2260
+ useFactory: () => {
2261
+ const currentConfig = inject(FORMLY_CONFIG, {
2262
+ skipSelf: true,
2263
+ optional: true,
2264
+ });
2265
+ if (currentConfig) {
2266
+ currentConfig.push(configs);
2267
+ return currentConfig;
2268
+ }
2269
+ return configs;
2270
+ },
2271
+ };
1763
2272
  };
1764
2273
 
1765
2274
  class FormlyFormBuilder {
@@ -1991,8 +2500,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
1991
2500
  args: [FormlyTemplate]
1992
2501
  }] } });
1993
2502
  class LegacyFormlyForm extends FormlyForm {
2503
+ set templates(templates) {
2504
+ this.fieldTemplates.templates = templates;
2505
+ }
1994
2506
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LegacyFormlyForm, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1995
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LegacyFormlyForm, selector: "formly-form", providers: [FormlyFormBuilder, FormlyFieldTemplates], usesInheritance: true, ngImport: i0, template: '<formly-field [field]="field"></formly-field>', isInline: true, dependencies: [{ kind: "component", type: LegacyFormlyField, selector: "formly-field" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2507
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LegacyFormlyForm, selector: "formly-form", providers: [FormlyFormBuilder, FormlyFieldTemplates], queries: [{ propertyName: "templates", predicate: LegacyFormlyTemplate }], usesInheritance: true, ngImport: i0, template: '<formly-field [field]="field"></formly-field>', isInline: true, dependencies: [{ kind: "component", type: LegacyFormlyField, selector: "formly-field" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1996
2508
  }
1997
2509
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LegacyFormlyForm, decorators: [{
1998
2510
  type: Component,
@@ -2003,7 +2515,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
2003
2515
  changeDetection: ChangeDetectionStrategy.OnPush,
2004
2516
  standalone: false,
2005
2517
  }]
2006
- }] });
2518
+ }], propDecorators: { templates: [{
2519
+ type: ContentChildren,
2520
+ args: [LegacyFormlyTemplate]
2521
+ }] } });
2007
2522
 
2008
2523
  /**
2009
2524
  * Allow to link the `field` HTML attributes (`id`, `name` ...) and Event attributes (`focus`, `blur` ...) to an element in the DOM.
@@ -2379,7 +2894,7 @@ class FormlyModule {
2379
2894
  ngModule: FormlyModule,
2380
2895
  providers: [
2381
2896
  { provide: FORMLY_CONFIG, multi: true, useFactory: withDefaultConfig, deps: [FormlyConfig] },
2382
- { provide: FORMLY_CONFIG, useValue: config, multi: true },
2897
+ provideFormlyConfig(config),
2383
2898
  FormlyConfig,
2384
2899
  FormlyFormBuilder,
2385
2900
  ],
@@ -2390,19 +2905,19 @@ class FormlyModule {
2390
2905
  ngModule: FormlyModule,
2391
2906
  providers: [
2392
2907
  { provide: FORMLY_CONFIG, multi: true, useFactory: withDefaultConfig, deps: [FormlyConfig] },
2393
- { provide: FORMLY_CONFIG, useValue: config, multi: true },
2908
+ provideFormlyConfig(config),
2394
2909
  FormlyFormBuilder,
2395
2910
  ],
2396
2911
  };
2397
2912
  }
2398
2913
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormlyModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
2399
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: FormlyModule, declarations: [FormlyTemplate,
2914
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: FormlyModule, declarations: [LegacyFormlyTemplate,
2400
2915
  LegacyFormlyForm,
2401
2916
  LegacyFormlyField,
2402
2917
  LegacyFormlyAttributes,
2403
2918
  LegacyFormlyValidationMessage,
2404
2919
  FormlyGroup,
2405
- FormlyTemplateType], imports: [CommonModule], exports: [FormlyTemplate,
2920
+ FormlyTemplateType], imports: [CommonModule], exports: [LegacyFormlyTemplate,
2406
2921
  LegacyFormlyForm,
2407
2922
  LegacyFormlyField,
2408
2923
  LegacyFormlyAttributes,
@@ -2414,7 +2929,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
2414
2929
  type: NgModule,
2415
2930
  args: [{
2416
2931
  declarations: [
2417
- FormlyTemplate,
2932
+ LegacyFormlyTemplate,
2418
2933
  LegacyFormlyForm,
2419
2934
  LegacyFormlyField,
2420
2935
  LegacyFormlyAttributes,
@@ -2423,7 +2938,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
2423
2938
  FormlyTemplateType,
2424
2939
  ],
2425
2940
  exports: [
2426
- FormlyTemplate,
2941
+ LegacyFormlyTemplate,
2427
2942
  LegacyFormlyForm,
2428
2943
  LegacyFormlyField,
2429
2944
  LegacyFormlyAttributes,
@@ -2442,5 +2957,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
2442
2957
  * Generated bundle index. Do not edit.
2443
2958
  */
2444
2959
 
2445
- export { FORMLY_CONFIG, FieldArrayType, FieldType, FieldWrapper, FormlyAttributes, FormlyConfig, FormlyField, FormlyForm, FormlyFormBuilder, FormlyModule, FormlyValidationMessage, LegacyFormlyAttributes, LegacyFormlyField, LegacyFormlyForm, LegacyFormlyValidationMessage, provideFormlyConfig, provideFormlyCore, FormlyGroup as ɵFormlyGroup, FormlyTemplate as ɵFormlyTemplate, clone as ɵclone, defineHiddenProp as ɵdefineHiddenProp, getFieldValue as ɵgetFieldValue, hasKey as ɵhasKey, observe as ɵobserve, reverseDeepMerge as ɵreverseDeepMerge };
2960
+ export { FORMLY_CONFIG, FieldArrayType, FieldType, FieldWrapper, FormlyAttributes, FormlyConfig, FormlyField, FormlyForm, FormlyFormBuilder, FormlyModule, FormlyTemplate, FormlyValidationMessage, LegacyFormlyAttributes, LegacyFormlyField, LegacyFormlyForm, LegacyFormlyValidationMessage, provideFormlyConfig, provideFormlyCore, withFormlyFieldExpression, FormlyGroup as ɵFormlyGroup, LegacyFormlyTemplate as ɵFormlyTemplate, clone as ɵclone, defineHiddenProp as ɵdefineHiddenProp, getFieldValue as ɵgetFieldValue, hasKey as ɵhasKey, observe as ɵobserve, reverseDeepMerge as ɵreverseDeepMerge };
2446
2961
  //# sourceMappingURL=ngx-formly-core.mjs.map