@bpmn-io/properties-panel 1.7.0 → 1.8.1

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.esm.js CHANGED
@@ -394,6 +394,10 @@ function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky)
394
394
  if (ref.current) {
395
395
  const scrollContainer = query(scrollContainerSelector);
396
396
  observer = new Observer(entries => {
397
+ // The ScrollContainer is unmounted, do not update sticky state
398
+ if (scrollContainer.scrollHeight === 0) {
399
+ return;
400
+ }
397
401
  entries.forEach(entry => {
398
402
  if (entry.intersectionRatio < 1) {
399
403
  setSticky(true);
@@ -640,7 +644,7 @@ function PropertiesPanel(props) {
640
644
  const [layout, setLayout] = useState(createLayout(layoutConfig));
641
645
 
642
646
  // react to external changes in the layout config
643
- useUpdateEffect(() => {
647
+ useUpdateLayoutEffect(() => {
644
648
  const newLayout = createLayout(layoutConfig);
645
649
  setLayout(newLayout);
646
650
  }, [layoutConfig]);
@@ -761,14 +765,14 @@ function createDescriptionContext(overrides = {}) {
761
765
  // hooks //////////////////
762
766
 
763
767
  /**
764
- * This hook behaves like useEffect, but does not trigger on the first render.
768
+ * This hook behaves like useLayoutEffect, but does not trigger on the first render.
765
769
  *
766
770
  * @param {Function} effect
767
771
  * @param {Array} deps
768
772
  */
769
- function useUpdateEffect(effect, deps) {
773
+ function useUpdateLayoutEffect(effect, deps) {
770
774
  const isMounted = useRef(false);
771
- useEffect(() => {
775
+ useLayoutEffect(() => {
772
776
  if (isMounted.current) {
773
777
  return effect();
774
778
  } else {
@@ -2741,6 +2745,7 @@ function TextArea(props) {
2741
2745
  * @param {Function} props.onBlur
2742
2746
  * @param {number} props.rows
2743
2747
  * @param {boolean} props.monospace
2748
+ * @param {Function} [props.validate]
2744
2749
  * @param {boolean} [props.disabled]
2745
2750
  */
2746
2751
  function TextAreaEntry(props) {
@@ -2755,12 +2760,38 @@ function TextAreaEntry(props) {
2755
2760
  rows,
2756
2761
  monospace,
2757
2762
  disabled,
2763
+ validate,
2758
2764
  onFocus,
2759
2765
  onBlur,
2760
2766
  autoResize
2761
2767
  } = props;
2762
- const value = getValue(element);
2763
- const error = useError(id);
2768
+ const [cachedInvalidValue, setCachedInvalidValue] = useState(null);
2769
+ const globalError = useError(id);
2770
+ const [localError, setLocalError] = useState(null);
2771
+ let value = getValue(element);
2772
+ const previousValue = usePrevious(value);
2773
+ useEffect(() => {
2774
+ if (isFunction(validate)) {
2775
+ const newValidationError = validate(value) || null;
2776
+ setLocalError(newValidationError);
2777
+ }
2778
+ }, [value]);
2779
+ const onInput = newValue => {
2780
+ let newValidationError = null;
2781
+ if (isFunction(validate)) {
2782
+ newValidationError = validate(newValue) || null;
2783
+ }
2784
+ if (newValidationError) {
2785
+ setCachedInvalidValue(newValue);
2786
+ } else {
2787
+ setValue(newValue);
2788
+ }
2789
+ setLocalError(newValidationError);
2790
+ };
2791
+ if (previousValue === value && localError) {
2792
+ value = cachedInvalidValue;
2793
+ }
2794
+ const error = globalError || localError;
2764
2795
  return jsxs("div", {
2765
2796
  class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
2766
2797
  "data-entry-id": id,
@@ -2768,7 +2799,7 @@ function TextAreaEntry(props) {
2768
2799
  id: id,
2769
2800
  label: label,
2770
2801
  value: value,
2771
- onInput: setValue,
2802
+ onInput: onInput,
2772
2803
  onFocus: onFocus,
2773
2804
  onBlur: onBlur,
2774
2805
  rows: rows,