@bpmn-io/form-js-viewer 1.3.0-alpha.0 → 1.3.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.
@@ -458,13 +458,20 @@
458
458
  min-height: var(--form-field-height);
459
459
  }
460
460
 
461
-
462
461
  .fjs-container .fjs-datepicker,
463
- .fjs-container .fjs-timepicker,
464
- .fjs-container .fjs-datetime-subsection {
462
+ .fjs-container .fjs-timepicker {
465
463
  width: 100%;
466
464
  }
467
465
 
466
+ .fjs-container .fjs-datetime-subsection {
467
+ min-width: 0;
468
+ flex: 1;
469
+ }
470
+
471
+ .fjs-container .fjs-datetime-separator {
472
+ width: 10px;
473
+ }
474
+
468
475
  .fjs-container .fjs-timepicker-anchor {
469
476
  height: 100%;
470
477
  display: flex;
@@ -474,10 +481,6 @@
474
481
  color: var(--color-icon-base);
475
482
  }
476
483
 
477
- .fjs-container .fjs-datetime-separator {
478
- width: 10px;
479
- }
480
-
481
484
  .fjs-container .fjs-input-group {
482
485
  display: flex;
483
486
  width: 100%;
@@ -547,11 +550,6 @@
547
550
  border-radius: 3px;
548
551
  }
549
552
 
550
- .fjs-container .fjs-vertical-group {
551
- display: flex;
552
- width: 100%;
553
- }
554
-
555
553
  .fjs-container .flatpickr-wrapper {
556
554
  width: 100%;
557
555
  height: 100%;
@@ -599,6 +597,10 @@
599
597
  color: var(--cds-text-inverse, var(--color-text));
600
598
  }
601
599
 
600
+ .fjs-container .fjs-form-field-number.fjs-readonly .fjs-number-arrow-container {
601
+ display: none;
602
+ }
603
+
602
604
  .fjs-container .fjs-radio {
603
605
  display: flex;
604
606
  flex-direction: column;
@@ -443,11 +443,19 @@
443
443
  }
444
444
 
445
445
  .fjs-container .fjs-datepicker,
446
- .fjs-container .fjs-timepicker,
447
- .fjs-container .fjs-datetime-subsection {
446
+ .fjs-container .fjs-timepicker {
448
447
  width: 100%;
449
448
  }
450
449
 
450
+ .fjs-container .fjs-datetime-subsection {
451
+ min-width: 0;
452
+ flex: 1;
453
+ }
454
+
455
+ .fjs-container .fjs-datetime-separator {
456
+ width: 10px;
457
+ }
458
+
451
459
  .fjs-container .fjs-timepicker-anchor {
452
460
  height: 100%;
453
461
  display: flex;
@@ -457,10 +465,6 @@
457
465
  color: var(--color-icon-base);
458
466
  }
459
467
 
460
- .fjs-container .fjs-datetime-separator {
461
- width: 10px;
462
- }
463
-
464
468
  .fjs-container .fjs-input-group {
465
469
  display: flex;
466
470
  width: 100%;
@@ -529,11 +533,6 @@
529
533
  border-radius: 3px;
530
534
  }
531
535
 
532
- .fjs-container .fjs-vertical-group {
533
- display: flex;
534
- width: 100%;
535
- }
536
-
537
536
  .fjs-container .flatpickr-wrapper {
538
537
  width: 100%;
539
538
  height: 100%;
@@ -581,6 +580,10 @@
581
580
  color: var(--cds-text-inverse, var(--color-text));
582
581
  }
583
582
 
583
+ .fjs-container .fjs-form-field-number.fjs-readonly .fjs-number-arrow-container {
584
+ display: none;
585
+ }
586
+
584
587
  .fjs-container .fjs-radio {
585
588
  display: flex;
586
589
  flex-direction: column;
package/dist/index.cjs CHANGED
@@ -639,9 +639,14 @@ class ConditionChecker {
639
639
  *
640
640
  * @param {Object<string, any>} properties
641
641
  * @param {Object<string, any>} data
642
+ * @param {Object} [options]
643
+ * @param {Function} [options.getFilterPath]
642
644
  */
643
- applyConditions(properties, data = {}) {
645
+ applyConditions(properties, data = {}, options = {}) {
644
646
  const newProperties = clone(properties);
647
+ const {
648
+ getFilterPath = field => this._pathRegistry.getValuePath(field)
649
+ } = options;
645
650
  const form = this._formFieldRegistry.getAll().find(field => field.type === 'default');
646
651
  if (!form) {
647
652
  throw new Error('form field registry has no form');
@@ -658,8 +663,7 @@ class ConditionChecker {
658
663
 
659
664
  // only clear the leaf nodes, as groups may both point to the same path
660
665
  if (context.isHidden && isClosed) {
661
- const valuePath = this._pathRegistry.getValuePath(field);
662
- this._clearObjectValueRecursively(valuePath, newProperties);
666
+ this._clearObjectValueRecursively(getFilterPath(field), newProperties);
663
667
  }
664
668
  });
665
669
  return newProperties;
@@ -2724,6 +2728,37 @@ function useReadonly(formField, properties = {}) {
2724
2728
  return readonly || false;
2725
2729
  }
2726
2730
 
2731
+ function usePrevious(value, defaultValue, dependencies) {
2732
+ const ref = hooks.useRef(defaultValue);
2733
+ hooks.useEffect(() => ref.current = value, dependencies);
2734
+ return ref.current;
2735
+ }
2736
+
2737
+ /**
2738
+ * A custom hook to manage state changes with deep comparison.
2739
+ *
2740
+ * @param {any} value - The current value to manage.
2741
+ * @param {any} defaultValue - The initial default value for the state.
2742
+ * @returns {any} - Returns the current state.
2743
+ */
2744
+ function useDeepCompareState(value, defaultValue) {
2745
+ const [state, setState] = hooks.useState(defaultValue);
2746
+ const previous = usePrevious(value, defaultValue, [value]);
2747
+ const changed = !compare(previous, value);
2748
+ hooks.useEffect(() => {
2749
+ if (changed) {
2750
+ setState(value);
2751
+ }
2752
+ }, [changed, value]);
2753
+ return state;
2754
+ }
2755
+
2756
+ // helpers //////////////////////////
2757
+
2758
+ function compare(a, b) {
2759
+ return JSON.stringify(a) === JSON.stringify(b);
2760
+ }
2761
+
2727
2762
  /**
2728
2763
  * Template a string reactively based on form data. If the string is not a template, it is returned as is.
2729
2764
  * Memoised to minimize re-renders
@@ -2993,11 +3028,8 @@ function useValuesAsync (field) {
2993
3028
  state: LOAD_STATES.LOADING
2994
3029
  });
2995
3030
  const initialData = useService('form')._getState().initialData;
2996
- const evaluatedValues = hooks.useMemo(() => {
2997
- if (valuesExpression) {
2998
- return useExpressionEvaluation(valuesExpression);
2999
- }
3000
- }, [valuesExpression]);
3031
+ const expressionEvaluation = useExpressionEvaluation(valuesExpression);
3032
+ const evaluatedValues = useDeepCompareState(expressionEvaluation || [], []);
3001
3033
  hooks.useEffect(() => {
3002
3034
  let values = [];
3003
3035
 
@@ -3013,8 +3045,10 @@ function useValuesAsync (field) {
3013
3045
  values = Array.isArray(staticValues) ? staticValues : [];
3014
3046
 
3015
3047
  // expression
3016
- } else if (evaluatedValues && Array.isArray(evaluatedValues)) {
3017
- values = evaluatedValues;
3048
+ } else if (valuesExpression) {
3049
+ if (evaluatedValues && Array.isArray(evaluatedValues)) {
3050
+ values = evaluatedValues;
3051
+ }
3018
3052
  } else {
3019
3053
  setValuesGetter(buildErrorState('No values source defined in the form definition'));
3020
3054
  return;
@@ -3023,7 +3057,7 @@ function useValuesAsync (field) {
3023
3057
  // normalize data to support primitives and partially defined objects
3024
3058
  values = normalizeValuesData(values);
3025
3059
  setValuesGetter(buildLoadedState(values));
3026
- }, [valuesKey, staticValues, initialData]);
3060
+ }, [valuesKey, staticValues, initialData, valuesExpression, evaluatedValues]);
3027
3061
  return valuesGetter;
3028
3062
  }
3029
3063
  const buildErrorState = error => ({
@@ -3042,7 +3076,6 @@ const ENTER_KEYDOWN_EVENT = new KeyboardEvent('keydown', {
3042
3076
  key: 'Enter',
3043
3077
  charCode: 13,
3044
3078
  keyCode: 13,
3045
- view: window,
3046
3079
  bubbles: true
3047
3080
  });
3048
3081
  function focusRelevantFlatpickerDay(flatpickrInstance) {
@@ -3808,7 +3841,8 @@ function DropdownList(props) {
3808
3841
  hooks.useEffect(() => {
3809
3842
  const individualEntries = dropdownContainer.current.children;
3810
3843
  if (individualEntries.length && !mouseControl) {
3811
- individualEntries[focusedValueIndex].scrollIntoView({
3844
+ const focusedEntry = individualEntries[focusedValueIndex];
3845
+ focusedEntry && focusedEntry.scrollIntoView({
3812
3846
  block: 'nearest',
3813
3847
  inline: 'nearest'
3814
3848
  });
@@ -6371,10 +6405,9 @@ class Form {
6371
6405
  }
6372
6406
  const data = this._getSubmitData();
6373
6407
  const errors = this.validate();
6374
- const filteredErrors = this._applyConditions(errors, data);
6375
6408
  const result = {
6376
6409
  data,
6377
- errors: filteredErrors
6410
+ errors
6378
6411
  };
6379
6412
  this._emit('submit', result);
6380
6413
  return result;
@@ -6397,6 +6430,7 @@ class Form {
6397
6430
  const {
6398
6431
  data
6399
6432
  } = this._getState();
6433
+ const getErrorPath = field => [field.id];
6400
6434
  const errors = formFieldRegistry.getAll().reduce((errors, field) => {
6401
6435
  const {
6402
6436
  disabled
@@ -6406,12 +6440,15 @@ class Form {
6406
6440
  }
6407
6441
  const value = minDash.get(data, pathRegistry.getValuePath(field));
6408
6442
  const fieldErrors = validator.validateField(field, value);
6409
- return minDash.set(errors, [field.id], fieldErrors.length ? fieldErrors : undefined);
6443
+ return minDash.set(errors, getErrorPath(field), fieldErrors.length ? fieldErrors : undefined);
6410
6444
  }, /** @type {Errors} */{});
6445
+ const filteredErrors = this._applyConditions(errors, data, {
6446
+ getFilterPath: getErrorPath
6447
+ });
6411
6448
  this._setState({
6412
- errors
6449
+ errors: filteredErrors
6413
6450
  });
6414
- return errors;
6451
+ return filteredErrors;
6415
6452
  }
6416
6453
 
6417
6454
  /**
@@ -6590,9 +6627,9 @@ class Form {
6590
6627
  /**
6591
6628
  * @internal
6592
6629
  */
6593
- _applyConditions(toFilter, data) {
6630
+ _applyConditions(toFilter, data, options = {}) {
6594
6631
  const conditionChecker = this.get('conditionChecker');
6595
- return conditionChecker.applyConditions(toFilter, data);
6632
+ return conditionChecker.applyConditions(toFilter, data, options);
6596
6633
  }
6597
6634
 
6598
6635
  /**
@@ -6676,6 +6713,7 @@ exports.FieldFactory = FieldFactory;
6676
6713
  exports.Form = Form;
6677
6714
  exports.FormComponent = FormComponent;
6678
6715
  exports.FormContext = FormContext$1;
6716
+ exports.FormField = FormField;
6679
6717
  exports.FormFieldRegistry = FormFieldRegistry;
6680
6718
  exports.FormFields = FormFields;
6681
6719
  exports.FormLayouter = FormLayouter;