@ng-forge/dynamic-forms 1.1.0-next.1 → 1.1.0-next.3

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 (29) hide show
  1. package/README.md +4 -1
  2. package/fesm2022/{ng-forge-dynamic-forms-array-field.component-CIheZh11.mjs → ng-forge-dynamic-forms-array-field.component-DCHrAcfd.mjs} +2 -2
  3. package/fesm2022/{ng-forge-dynamic-forms-array-field.component-CIheZh11.mjs.map → ng-forge-dynamic-forms-array-field.component-DCHrAcfd.mjs.map} +1 -1
  4. package/fesm2022/{ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-C9aVachF.mjs → ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-DWIWQjjZ.mjs} +2 -2
  5. package/fesm2022/{ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-C9aVachF.mjs.map → ng-forge-dynamic-forms-bootstrap-derivation-orchestrator-DWIWQjjZ.mjs.map} +1 -1
  6. package/fesm2022/{ng-forge-dynamic-forms-container-field.component-DNafCSO8.mjs → ng-forge-dynamic-forms-container-field.component-CSYhRBe6.mjs} +2 -2
  7. package/fesm2022/{ng-forge-dynamic-forms-container-field.component-DNafCSO8.mjs.map → ng-forge-dynamic-forms-container-field.component-CSYhRBe6.mjs.map} +1 -1
  8. package/fesm2022/{ng-forge-dynamic-forms-css-wrapper.component-BmHGlmES.mjs → ng-forge-dynamic-forms-css-wrapper.component-D_yRuLpu.mjs} +4 -3
  9. package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-D_yRuLpu.mjs.map +1 -0
  10. package/fesm2022/{ng-forge-dynamic-forms-group-field.component-CKVIw2K5.mjs → ng-forge-dynamic-forms-group-field.component-DqhHzVsN.mjs} +2 -2
  11. package/fesm2022/{ng-forge-dynamic-forms-group-field.component-CKVIw2K5.mjs.map → ng-forge-dynamic-forms-group-field.component-DqhHzVsN.mjs.map} +1 -1
  12. package/fesm2022/ng-forge-dynamic-forms-integration.mjs +17 -56
  13. package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -1
  14. package/fesm2022/ng-forge-dynamic-forms-internal.mjs +81 -59
  15. package/fesm2022/ng-forge-dynamic-forms-internal.mjs.map +1 -1
  16. package/fesm2022/{ng-forge-dynamic-forms-ng-forge-dynamic-forms-CBawLbtp.mjs → ng-forge-dynamic-forms-ng-forge-dynamic-forms-BYyZ_cuA.mjs} +56 -134
  17. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-BYyZ_cuA.mjs.map +1 -0
  18. package/fesm2022/{ng-forge-dynamic-forms-page-field.component-BRixkgyS.mjs → ng-forge-dynamic-forms-page-field.component-Vvk3fYZp.mjs} +2 -2
  19. package/fesm2022/{ng-forge-dynamic-forms-page-field.component-BRixkgyS.mjs.map → ng-forge-dynamic-forms-page-field.component-Vvk3fYZp.mjs.map} +1 -1
  20. package/fesm2022/ng-forge-dynamic-forms-testing.mjs +84 -0
  21. package/fesm2022/ng-forge-dynamic-forms-testing.mjs.map +1 -0
  22. package/fesm2022/ng-forge-dynamic-forms.mjs +1 -1
  23. package/package.json +5 -1
  24. package/types/ng-forge-dynamic-forms-integration.d.ts +6 -54
  25. package/types/ng-forge-dynamic-forms-internal.d.ts +41 -10
  26. package/types/ng-forge-dynamic-forms-testing.d.ts +58 -0
  27. package/types/ng-forge-dynamic-forms.d.ts +1 -1
  28. package/fesm2022/ng-forge-dynamic-forms-css-wrapper.component-BmHGlmES.mjs.map +0 -1
  29. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-CBawLbtp.mjs.map +0 -1
@@ -392,6 +392,15 @@ function hasCrossFieldWhenCondition(config, context) {
392
392
  }
393
393
  return isCrossFieldExpression(config.when, context);
394
394
  }
395
+ function requiresTreeValidation(config) {
396
+ if (isResourceBasedValidator(config)) {
397
+ return false;
398
+ }
399
+ if (config.type === 'custom') {
400
+ return isCrossFieldValidator(config);
401
+ }
402
+ return isCrossFieldBuiltInValidator(config);
403
+ }
395
404
  function isCrossFieldStateLogic(config, context) {
396
405
  return isCrossFieldExpression(config.condition, context);
397
406
  }
@@ -2185,6 +2194,18 @@ function validateNoNestedHttpConditions(expression) {
2185
2194
  }
2186
2195
  }
2187
2196
  }
2197
+ function containsInlineFunction(expression) {
2198
+ if (expression.type === 'and' || expression.type === 'or') {
2199
+ return expression.conditions.some(containsInlineFunction);
2200
+ }
2201
+ if (expression.type === 'custom') {
2202
+ return typeof expression.fn === 'function';
2203
+ }
2204
+ if (expression.type === 'async') {
2205
+ return typeof expression.asyncFn === 'function';
2206
+ }
2207
+ return false;
2208
+ }
2188
2209
  function createLogicFunction(expression) {
2189
2210
  if (expression?.type === 'async') {
2190
2211
  return createAsyncConditionLogicFunction(expression);
@@ -2198,16 +2219,21 @@ function createLogicFunction(expression) {
2198
2219
  const functionRegistry = inject(FunctionRegistryService);
2199
2220
  const fieldContextRegistry = inject(FieldContextRegistryService);
2200
2221
  const cacheService = inject(LogicFunctionCacheService);
2222
+ const cacheable = !expression || !containsInlineFunction(expression);
2201
2223
  const cacheKey = stableStringify(expression);
2224
+ if (cacheable) {
2202
2225
  const cached = cacheService.logicFunctionCache.get(cacheKey);
2203
- if (cached) {
2204
- return cached;
2226
+ if (cached) {
2227
+ return cached;
2228
+ }
2205
2229
  }
2206
2230
  const fn = (ctx) => {
2207
2231
  const evaluationContext = fieldContextRegistry.createReactiveEvaluationContext(ctx, functionRegistry.getCustomFunctions());
2208
2232
  return evaluateCondition(expression, evaluationContext);
2209
2233
  };
2234
+ if (cacheable) {
2210
2235
  cacheService.logicFunctionCache.set(cacheKey, fn);
2236
+ }
2211
2237
  return fn;
2212
2238
  }
2213
2239
  function createDebouncedLogicFunction(expression, debounceMs) {
@@ -2224,13 +2250,16 @@ function createDebouncedLogicFunction(expression, debounceMs) {
2224
2250
  const fieldContextRegistry = inject(FieldContextRegistryService);
2225
2251
  const injector = inject(Injector);
2226
2252
  const cacheService = inject(LogicFunctionCacheService);
2253
+ const cacheable = !expression || !containsInlineFunction(expression);
2227
2254
  const cacheKey = `${stableStringify(expression)}:${debounceMs}`;
2255
+ if (cacheable) {
2228
2256
  const cached = cacheService.debouncedLogicFunctionCache.get(cacheKey);
2229
- if (cached) {
2230
- return cached;
2257
+ if (cached) {
2258
+ return cached;
2259
+ }
2231
2260
  }
2232
2261
  const fn = (ctx) => {
2233
- const contextKey = safeReadPathKeys(ctx).join('.');
2262
+ const contextKey = safeReadPathKeys(ctx).join('.');
2234
2263
  let signalPair = cacheService.debouncedSignalStore.get(contextKey);
2235
2264
  if (!signalPair) {
2236
2265
  const immediateValue = signal(false, /* @ts-ignore */
@@ -2252,7 +2281,9 @@ function createDebouncedLogicFunction(expression, debounceMs) {
2252
2281
  });
2253
2282
  return debouncedValue() ?? false;
2254
2283
  };
2284
+ if (cacheable) {
2255
2285
  cacheService.debouncedLogicFunctionCache.set(cacheKey, fn);
2286
+ }
2256
2287
  return fn;
2257
2288
  }
2258
2289
 
@@ -2517,47 +2548,52 @@ function createDynamicValueFunction(expression) {
2517
2548
  return fn;
2518
2549
  }
2519
2550
 
2520
- function applyEmailValidator(path) {
2521
- email(path);
2551
+ function applyEmailValidator(path, when) {
2552
+ email(path, when ? { when: when } : undefined);
2522
2553
  }
2523
- function applyMinValidator(path, value, expression) {
2554
+ function applyMinValidator(path, value, expression, when) {
2555
+ const opts = when ? { when: when } : undefined;
2524
2556
  if (expression) {
2525
- min(path, createDynamicValueFunction(expression));
2557
+ min(path, createDynamicValueFunction(expression), opts);
2526
2558
  }
2527
2559
  else {
2528
- min(path, value);
2560
+ min(path, value, opts);
2529
2561
  }
2530
2562
  }
2531
- function applyMaxValidator(path, value, expression) {
2563
+ function applyMaxValidator(path, value, expression, when) {
2564
+ const opts = when ? { when: when } : undefined;
2532
2565
  if (expression) {
2533
- max(path, createDynamicValueFunction(expression));
2566
+ max(path, createDynamicValueFunction(expression), opts);
2534
2567
  }
2535
2568
  else {
2536
- max(path, value);
2569
+ max(path, value, opts);
2537
2570
  }
2538
2571
  }
2539
- function applyMinLengthValidator(path, value, expression) {
2572
+ function applyMinLengthValidator(path, value, expression, when) {
2573
+ const opts = when ? { when: when } : undefined;
2540
2574
  if (expression) {
2541
- minLength(path, createDynamicValueFunction(expression));
2575
+ minLength(path, createDynamicValueFunction(expression), opts);
2542
2576
  }
2543
2577
  else {
2544
- minLength(path, value);
2578
+ minLength(path, value, opts);
2545
2579
  }
2546
2580
  }
2547
- function applyMaxLengthValidator(path, value, expression) {
2581
+ function applyMaxLengthValidator(path, value, expression, when) {
2582
+ const opts = when ? { when: when } : undefined;
2548
2583
  if (expression) {
2549
- maxLength(path, createDynamicValueFunction(expression));
2584
+ maxLength(path, createDynamicValueFunction(expression), opts);
2550
2585
  }
2551
2586
  else {
2552
- maxLength(path, value);
2587
+ maxLength(path, value, opts);
2553
2588
  }
2554
2589
  }
2555
- function applyPatternValidator(path, value, expression) {
2590
+ function applyPatternValidator(path, value, expression, when) {
2591
+ const opts = when ? { when: when } : undefined;
2556
2592
  if (expression) {
2557
- pattern(path, createDynamicValueFunction(expression));
2593
+ pattern(path, createDynamicValueFunction(expression), opts);
2558
2594
  }
2559
2595
  else {
2560
- pattern(path, value);
2596
+ pattern(path, value, opts);
2561
2597
  }
2562
2598
  }
2563
2599
  function createConditionalLogic(when) {
@@ -2565,39 +2601,34 @@ function createConditionalLogic(when) {
2565
2601
  }
2566
2602
  function applyValidator(config, fieldPath) {
2567
2603
  const path = fieldPath;
2568
- if (!isResourceBasedValidator(config) && (isCrossFieldBuiltInValidator(config) || hasCrossFieldWhenCondition(config))) {
2604
+ if (requiresTreeValidation(config)) {
2569
2605
  return;
2570
2606
  }
2571
2607
  switch (config.type) {
2572
2608
  case 'required':
2573
- if (config.when) {
2574
- required(path, { when: createLogicFunction(config.when) });
2575
- }
2576
- else {
2577
- required(path);
2578
- }
2609
+ required(path, config.when ? { when: createConditionalLogic(config.when) } : undefined);
2579
2610
  break;
2580
2611
  case 'email':
2581
- applyEmailValidator(fieldPath);
2612
+ applyEmailValidator(fieldPath, createConditionalLogic(config.when));
2582
2613
  break;
2583
2614
  case 'min':
2584
2615
  if (typeof config.value === 'number') {
2585
- applyMinValidator(fieldPath, config.value, config.expression);
2616
+ applyMinValidator(fieldPath, config.value, config.expression, createConditionalLogic(config.when));
2586
2617
  }
2587
2618
  break;
2588
2619
  case 'max':
2589
2620
  if (typeof config.value === 'number') {
2590
- applyMaxValidator(fieldPath, config.value, config.expression);
2621
+ applyMaxValidator(fieldPath, config.value, config.expression, createConditionalLogic(config.when));
2591
2622
  }
2592
2623
  break;
2593
2624
  case 'minLength':
2594
2625
  if (typeof config.value === 'number') {
2595
- applyMinLengthValidator(fieldPath, config.value, config.expression);
2626
+ applyMinLengthValidator(fieldPath, config.value, config.expression, createConditionalLogic(config.when));
2596
2627
  }
2597
2628
  break;
2598
2629
  case 'maxLength':
2599
2630
  if (typeof config.value === 'number') {
2600
- applyMaxLengthValidator(fieldPath, config.value, config.expression);
2631
+ applyMaxLengthValidator(fieldPath, config.value, config.expression, createConditionalLogic(config.when));
2601
2632
  }
2602
2633
  break;
2603
2634
  case 'pattern':
@@ -2614,7 +2645,7 @@ function applyValidator(config, fieldPath) {
2614
2645
  else {
2615
2646
  regexPattern = config.value;
2616
2647
  }
2617
- applyPatternValidator(fieldPath, regexPattern, config.expression);
2648
+ applyPatternValidator(fieldPath, regexPattern, config.expression, createConditionalLogic(config.when));
2618
2649
  }
2619
2650
  break;
2620
2651
  case 'custom':
@@ -2629,9 +2660,6 @@ function applyValidator(config, fieldPath) {
2629
2660
  }
2630
2661
  }
2631
2662
  function applyCustomValidator(config, fieldPath) {
2632
- if (isCrossFieldValidator(config)) {
2633
- return;
2634
- }
2635
2663
  let validatorFn;
2636
2664
  if (config.expression) {
2637
2665
  validatorFn = createExpressionValidator(config);
@@ -3287,16 +3315,23 @@ function isDisplayOnlyField(field) {
3287
3315
  }
3288
3316
 
3289
3317
 
3318
+ function dynamicTextToObservable(value, injector) {
3319
+ if (value === undefined) {
3320
+ return of('');
3321
+ }
3322
+ if (isObservable(value)) {
3323
+ return value;
3324
+ }
3325
+ if (isSignal(value)) {
3326
+ return untracked(() => toObservable(value, { injector }));
3327
+ }
3328
+ return of(String(value));
3329
+ }
3330
+
3290
3331
  class DynamicTextPipe {
3291
3332
  injector = inject(Injector);
3292
3333
  transform(value) {
3293
- if (isObservable(value)) {
3294
- return value;
3295
- }
3296
- if (isSignal(value)) {
3297
- return toObservable(value, { injector: this.injector });
3298
- }
3299
- return of(value || '');
3334
+ return dynamicTextToObservable(value ?? undefined, this.injector);
3300
3335
  }
3301
3336
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: DynamicTextPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
3302
3337
  static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.1", ngImport: i0, type: DynamicTextPipe, isStandalone: true, name: "dynamicText" });
@@ -3326,19 +3361,6 @@ function applyMetaToElement(element, meta, previouslyApplied) {
3326
3361
  return newApplied;
3327
3362
  }
3328
3363
 
3329
- function dynamicTextToObservable(value, injector) {
3330
- if (value === undefined) {
3331
- return of('');
3332
- }
3333
- if (isObservable(value)) {
3334
- return value;
3335
- }
3336
- if (isSignal(value)) {
3337
- return toObservable(value, { injector });
3338
- }
3339
- return of(String(value));
3340
- }
3341
-
3342
3364
  const INITIALIZATION_TIMEOUT_MS = new InjectionToken('INITIALIZATION_TIMEOUT_MS', {
3343
3365
  providedIn: 'root',
3344
3366
  factory: () => 10_000,
@@ -3631,5 +3653,5 @@ function createWarningTracker() {
3631
3653
 
3632
3654
 
3633
3655
 
3634
- export { ADDON_ACTION_HANDLERS, ADDON_ACTION_REGISTRY, ADDON_TYPE_COMPONENT_CACHE, ADDON_TYPE_DEFINITIONS, ADDON_TYPE_REGISTRY, ARRAY_CONTEXT, AsyncConditionFunctionCacheService, ComponentInitializedEvent, DEFAULT_PROPS, DEFAULT_VALIDATION_MESSAGES, DEFAULT_WRAPPERS, DEPRECATION_WARNING_TRACKER, DF_FIELD_TEMPLATES, DfAddonSlot, DynamicFormError, DynamicFormLogger, DynamicTextPipe, DynamicValueFunctionCacheService, EMIT_FORM_VALUE_ON_EVENTS, EXTERNAL_DATA, EventBus, ExpressionParser, ExpressionParserError, FIELD_REGISTRY, FIELD_SIGNAL_CONTEXT, FORM_ID_PREFIX, FORM_OPTIONS, FieldContextRegistryService, FunctionRegistryService, GROUP_CONTEXT, HTTP_CONDITION_CACHE, HttpConditionCache, HttpConditionFunctionCacheService, INITIALIZATION_TIMEOUT_MS, LogicFunctionCacheService, NoopLogger, READONLY_FIELD_TREE_CACHE, RootFormRegistryService, TokenType, WRAPPER_AUTO_ASSOCIATIONS, WRAPPER_COMPONENT_CACHE, WRAPPER_REGISTRY, applyMetaToElement, applyValidator, applyValidators, arrayFieldMapper, assertNever, baseFieldMapper, buildBaseInputs, compareValues, containerFieldMapper, createAddonActionRegistry, createDebouncedLogicFunction, createDefaultDerivationLogConfig, createDynamicValueFunction, createFormFieldStateMap, createInitializationTracker, createLogicFunction, createWarningTracker, deepMergeDefaults, derivedFromDeferred, detectFormMode, dynamicTextToObservable, evaluateCondition, evaluateNonFieldDisabled, evaluateNonFieldHidden, extractExpressionDependencies, extractStringDependencies, getArrayLength, getChangedKeys, getFieldValueHandling, getNestedValue, groupFieldMapper, hasChildFields, hasCrossFieldWhenCondition, hasFormValue, hasNestedProperty, hasTargetProperty, injectAddonTypeRegistry, injectFieldSignalContext, injectFieldsSupportingAddons, injectNonFieldEvaluationContext, interpolateParams, isArrayField, isCheckedField, isContainerField, isCrossFieldBuiltInValidator, isCrossFieldExpression, isCrossFieldSchema, isCrossFieldStateLogic, isCrossFieldValidator, isDerivationLogicConfig, isDisplayOnlyField, isEqual, isFieldBoundContext, isFormStateCondition, isFunctionHttpValidator, isGenericContainerField, isGroupField, isHiddenField, isLeafField, isNonPagedForm, isPageField, isPagedForm, isResourceBasedValidator, isRowField, isSimplifiedArrayField, isStateLogicConfig, isValidNonPagedForm, isValidPagedForm, isValueBearingField, isValueField, isWrapperTypeDefinition, keyBy, mapValues, memoize, normalizeFieldsArray, omit, pageFieldMapper, readFieldStateInfo, resolveDynamicValue, resolveHttpRequest, resolveNextButtonDisabled, resolveNonFieldDisabled, resolveNonFieldHidden, resolveSubmitButtonDisabled, resolveTokens, rowFieldMapper, runPresetAction, setupInitializationTracking, shouldLog, textFieldMapper, toReadonlyFieldTree, toReadonlyFieldTreeCached, validatePageNesting, withPreviousValue, writeToFieldValue };
3656
+ export { ADDON_ACTION_HANDLERS, ADDON_ACTION_REGISTRY, ADDON_TYPE_COMPONENT_CACHE, ADDON_TYPE_DEFINITIONS, ADDON_TYPE_REGISTRY, ARRAY_CONTEXT, AsyncConditionFunctionCacheService, ComponentInitializedEvent, DEFAULT_PROPS, DEFAULT_VALIDATION_MESSAGES, DEFAULT_WRAPPERS, DEPRECATION_WARNING_TRACKER, DF_FIELD_TEMPLATES, DfAddonSlot, DynamicFormError, DynamicFormLogger, DynamicTextPipe, DynamicValueFunctionCacheService, EMIT_FORM_VALUE_ON_EVENTS, EXTERNAL_DATA, EventBus, ExpressionParser, ExpressionParserError, FIELD_REGISTRY, FIELD_SIGNAL_CONTEXT, FORM_ID_PREFIX, FORM_OPTIONS, FieldContextRegistryService, FunctionRegistryService, GROUP_CONTEXT, HTTP_CONDITION_CACHE, HttpConditionCache, HttpConditionFunctionCacheService, INITIALIZATION_TIMEOUT_MS, LogicFunctionCacheService, NoopLogger, READONLY_FIELD_TREE_CACHE, RootFormRegistryService, TokenType, WRAPPER_AUTO_ASSOCIATIONS, WRAPPER_COMPONENT_CACHE, WRAPPER_REGISTRY, applyMetaToElement, applyValidator, applyValidators, arrayFieldMapper, assertNever, baseFieldMapper, buildBaseInputs, buildClassName, compareValues, containerFieldMapper, createAddonActionRegistry, createDebouncedLogicFunction, createDefaultDerivationLogConfig, createDynamicValueFunction, createFormFieldStateMap, createInitializationTracker, createLogicFunction, createWarningTracker, deepMergeDefaults, derivedFromDeferred, detectFormMode, dynamicTextToObservable, evaluateCondition, evaluateNonFieldDisabled, evaluateNonFieldHidden, extractExpressionDependencies, extractStringDependencies, getArrayLength, getChangedKeys, getFieldValueHandling, getGridClassString, getNestedValue, groupFieldMapper, hasChildFields, hasCrossFieldWhenCondition, hasFormValue, hasNestedProperty, hasTargetProperty, injectAddonTypeRegistry, injectFieldSignalContext, injectFieldsSupportingAddons, injectNonFieldEvaluationContext, interpolateParams, isArrayField, isCheckedField, isContainerField, isCrossFieldBuiltInValidator, isCrossFieldExpression, isCrossFieldSchema, isCrossFieldStateLogic, isCrossFieldValidator, isDerivationLogicConfig, isDisplayOnlyField, isEqual, isFieldBoundContext, isFormStateCondition, isFunctionHttpValidator, isGenericContainerField, isGroupField, isHiddenField, isLeafField, isNonPagedForm, isPageField, isPagedForm, isResourceBasedValidator, isRowField, isSimplifiedArrayField, isStateLogicConfig, isValidNonPagedForm, isValidPagedForm, isValueBearingField, isValueField, isWrapperTypeDefinition, keyBy, mapValues, memoize, normalizeFieldsArray, omit, pageFieldMapper, readFieldStateInfo, requiresTreeValidation, resolveDynamicValue, resolveHttpRequest, resolveNextButtonDisabled, resolveNonFieldDisabled, resolveNonFieldHidden, resolveSubmitButtonDisabled, resolveTokens, rowFieldMapper, runPresetAction, setupInitializationTracking, shouldLog, textFieldMapper, toReadonlyFieldTree, toReadonlyFieldTreeCached, validatePageNesting, withPreviousValue, writeToFieldValue };
3635
3657
  //# sourceMappingURL=ng-forge-dynamic-forms-internal.mjs.map