@bpmn-io/properties-panel 0.15.0 → 0.16.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.
package/dist/index.js CHANGED
@@ -174,6 +174,10 @@ const DescriptionContext = preact.createContext({
174
174
  getDescriptionForId: () => {}
175
175
  });
176
176
 
177
+ const ErrorsContext = preact.createContext({
178
+ errors: {}
179
+ });
180
+
177
181
  /**
178
182
  * @typedef {Function} <propertiesPanel.showEntry> callback
179
183
  *
@@ -222,29 +226,48 @@ function useDescriptionContext(id, element) {
222
226
  return getDescriptionForId(id, element);
223
227
  }
224
228
 
225
- const DEFAULT_PRIORITY = 1000;
229
+ function useError(id) {
230
+ const {
231
+ errors
232
+ } = hooks.useContext(ErrorsContext);
233
+ return errors[id];
234
+ }
235
+
226
236
  /**
227
- * Subscribe to an event.
237
+ * Subscribe to an event immediately. Update subscription after inputs changed.
228
238
  *
229
239
  * @param {string} event
230
240
  * @param {Function} callback
231
- * @param {number} [priority]
232
- *
233
- * @returns {import('preact').Ref}
234
241
  */
235
242
 
236
- function useEvent(event, callback, priority = DEFAULT_PRIORITY) {
237
- const {
238
- eventBus
239
- } = hooks.useContext(EventContext);
243
+ function useEvent(event, callback, eventBus) {
244
+ const eventContext = hooks.useContext(EventContext);
245
+
246
+ if (!eventBus) {
247
+ ({
248
+ eventBus
249
+ } = eventContext);
250
+ }
251
+
252
+ const didMount = hooks.useRef(false); // (1) subscribe immediately
253
+
254
+ if (eventBus && !didMount.current) {
255
+ eventBus.on(event, callback);
256
+ } // (2) update subscription after inputs changed
257
+
258
+
240
259
  hooks.useEffect(() => {
241
- if (!eventBus) {
242
- return;
260
+ if (eventBus && didMount.current) {
261
+ eventBus.on(event, callback);
243
262
  }
244
263
 
245
- eventBus.on(event, priority, callback);
246
- return () => eventBus.off(event, callback);
247
- }, [callback, event, eventBus, priority]);
264
+ didMount.current = true;
265
+ return () => {
266
+ if (eventBus) {
267
+ eventBus.off(event, callback);
268
+ }
269
+ };
270
+ }, [callback, event, eventBus]);
248
271
  }
249
272
 
250
273
  const HIGH_PRIORITY = 10000;
@@ -390,30 +413,28 @@ function usePrevious(value) {
390
413
  /**
391
414
  * Subscribe to `propertiesPanel.showEntry`.
392
415
  *
393
- * @param {Function} show
416
+ * @param {string} id
394
417
  *
395
418
  * @returns {import('preact').Ref}
396
419
  */
397
420
 
398
- function useShowEntryEvent(show) {
421
+ function useShowEntryEvent(id) {
399
422
  const {
400
423
  onShow
401
424
  } = hooks.useContext(LayoutContext);
402
425
  const ref = hooks.useRef();
403
- const [focus, setFocus] = hooks.useState(false);
426
+ const focus = hooks.useRef(false);
404
427
  const onShowEntry = hooks.useCallback(event => {
405
- if (show(event)) {
406
- if (minDash.isFunction(onShow)) {
407
- onShow();
408
- }
428
+ if (event.id === id) {
429
+ onShow();
409
430
 
410
- if (event.focus && !focus) {
411
- setFocus(true);
431
+ if (!focus.current) {
432
+ focus.current = true;
412
433
  }
413
434
  }
414
- }, [show]);
435
+ }, [id]);
415
436
  hooks.useEffect(() => {
416
- if (focus && ref.current) {
437
+ if (focus.current && ref.current) {
417
438
  if (minDash.isFunction(ref.current.focus)) {
418
439
  ref.current.focus();
419
440
  }
@@ -422,45 +443,13 @@ function useShowEntryEvent(show) {
422
443
  ref.current.select();
423
444
  }
424
445
 
425
- setFocus(false);
446
+ focus.current = false;
426
447
  }
427
- }, [focus]);
448
+ });
428
449
  useEvent('propertiesPanel.showEntry', onShowEntry);
429
450
  return ref;
430
451
  }
431
452
 
432
- /**
433
- * Subscribe to `propertiesPanel.showError`. On `propertiesPanel.showError` set
434
- * temporary error. Fire `propertiesPanel.showEntry` for temporary error to be
435
- * visible. Unset error on `propertiesPanel.updated`.
436
- *
437
- * @param {Function} show
438
- *
439
- * @returns {import('preact').Ref}
440
- */
441
-
442
- function useShowErrorEvent(show) {
443
- const {
444
- eventBus
445
- } = hooks.useContext(EventContext);
446
- const [temporaryError, setTemporaryError] = hooks.useState(null);
447
- const onPropertiesPanelUpdated = hooks.useCallback(() => setTemporaryError(null), []);
448
- useEvent('propertiesPanel.updated', onPropertiesPanelUpdated);
449
- const onShowError = hooks.useCallback(event => {
450
- setTemporaryError(null);
451
-
452
- if (show(event)) {
453
- if (eventBus) {
454
- eventBus.fire('propertiesPanel.showEntry', event);
455
- }
456
-
457
- setTemporaryError(event.message);
458
- }
459
- }, [show]);
460
- useEvent('propertiesPanel.showError', onShowError);
461
- return temporaryError;
462
- }
463
-
464
453
  /**
465
454
  * @callback setSticky
466
455
  * @param {boolean} value
@@ -629,7 +618,7 @@ const DEFAULT_LAYOUT = {
629
618
  open: true
630
619
  };
631
620
  const DEFAULT_DESCRIPTION = {};
632
- const bufferedEvents = ['propertiesPanel.showEntry', 'propertiesPanel.showError'];
621
+ const bufferedEvents = ['propertiesPanel.showEntry', 'propertiesPanel.setErrors'];
633
622
  /**
634
623
  * @typedef { {
635
624
  * component: import('preact').Component,
@@ -750,6 +739,16 @@ function PropertiesPanel(props) {
750
739
  getDescriptionForId
751
740
  };
752
741
  useEventBuffer(bufferedEvents, eventBus);
742
+ const [errors, setErrors] = hooks.useState({});
743
+
744
+ const onSetErrors = ({
745
+ errors
746
+ }) => setErrors(errors);
747
+
748
+ useEvent('propertiesPanel.setErrors', onSetErrors, eventBus);
749
+ const errorsContext = {
750
+ errors
751
+ };
753
752
  const eventContext = {
754
753
  eventBus
755
754
  };
@@ -770,30 +769,33 @@ function PropertiesPanel(props) {
770
769
 
771
770
  return jsxRuntime.jsx(LayoutContext.Provider, {
772
771
  value: propertiesPanelContext,
773
- children: jsxRuntime.jsx(DescriptionContext.Provider, {
774
- value: descriptionContext,
775
- children: jsxRuntime.jsx(LayoutContext.Provider, {
776
- value: layoutContext,
777
- children: jsxRuntime.jsx(EventContext.Provider, {
778
- value: eventContext,
779
- children: jsxRuntime.jsxs("div", {
780
- class: classnames__default["default"]('bio-properties-panel', layout.open ? 'open' : ''),
781
- children: [jsxRuntime.jsx(Header, {
782
- element: element,
783
- headerProvider: headerProvider
784
- }), jsxRuntime.jsx("div", {
785
- class: "bio-properties-panel-scroll-container",
786
- children: groups.map(group => {
787
- const {
788
- component: Component = Group,
789
- id
790
- } = group;
791
- return preact.createElement(Component, { ...group,
792
- key: id,
793
- element: element
794
- });
795
- })
796
- })]
772
+ children: jsxRuntime.jsx(ErrorsContext.Provider, {
773
+ value: errorsContext,
774
+ children: jsxRuntime.jsx(DescriptionContext.Provider, {
775
+ value: descriptionContext,
776
+ children: jsxRuntime.jsx(LayoutContext.Provider, {
777
+ value: layoutContext,
778
+ children: jsxRuntime.jsx(EventContext.Provider, {
779
+ value: eventContext,
780
+ children: jsxRuntime.jsxs("div", {
781
+ class: classnames__default["default"]('bio-properties-panel', layout.open ? 'open' : ''),
782
+ children: [jsxRuntime.jsx(Header, {
783
+ element: element,
784
+ headerProvider: headerProvider
785
+ }), jsxRuntime.jsx("div", {
786
+ class: "bio-properties-panel-scroll-container",
787
+ children: groups.map(group => {
788
+ const {
789
+ component: Component = Group,
790
+ id
791
+ } = group;
792
+ return preact.createElement(Component, { ...group,
793
+ key: id,
794
+ element: element
795
+ });
796
+ })
797
+ })]
798
+ })
797
799
  })
798
800
  })
799
801
  })
@@ -1020,7 +1022,7 @@ function ListItem(props) {
1020
1022
  });
1021
1023
  }
1022
1024
 
1023
- const noop$3 = () => {};
1025
+ const noop = () => {};
1024
1026
  /**
1025
1027
  * @param {import('../PropertiesPanel').ListGroupDefinition} props
1026
1028
  */
@@ -1125,7 +1127,7 @@ function ListGroup(props) {
1125
1127
  ref: groupRef,
1126
1128
  children: [jsxRuntime.jsxs("div", {
1127
1129
  class: classnames__default["default"]('bio-properties-panel-group-header', hasItems ? '' : 'empty', hasItems && open ? 'open' : '', sticky && open ? 'sticky' : ''),
1128
- onClick: hasItems ? toggleOpen : noop$3,
1130
+ onClick: hasItems ? toggleOpen : noop,
1129
1131
  children: [jsxRuntime.jsx("div", {
1130
1132
  title: label,
1131
1133
  class: "bio-properties-panel-group-header-title",
@@ -1213,16 +1215,13 @@ function Description(props) {
1213
1215
  }
1214
1216
  }
1215
1217
 
1216
- const noop$2 = () => {};
1217
-
1218
1218
  function Checkbox(props) {
1219
1219
  const {
1220
1220
  id,
1221
1221
  label,
1222
1222
  onChange,
1223
1223
  disabled,
1224
- value = false,
1225
- show = noop$2
1224
+ value = false
1226
1225
  } = props;
1227
1226
  const [localValue, setLocalValue] = hooks.useState(value);
1228
1227
 
@@ -1244,7 +1243,7 @@ function Checkbox(props) {
1244
1243
 
1245
1244
  setLocalValue(value);
1246
1245
  }, [value]);
1247
- const ref = useShowEntryEvent(show);
1246
+ const ref = useShowEntryEvent(id);
1248
1247
  return jsxRuntime.jsxs("div", {
1249
1248
  class: "bio-properties-panel-checkbox",
1250
1249
  children: [jsxRuntime.jsx("input", {
@@ -1283,11 +1282,10 @@ function CheckboxEntry(props) {
1283
1282
  label,
1284
1283
  getValue,
1285
1284
  setValue,
1286
- disabled,
1287
- show = noop$2
1285
+ disabled
1288
1286
  } = props;
1289
1287
  const value = getValue(element);
1290
- const error = useShowErrorEvent(show);
1288
+ const error = useError(id);
1291
1289
  return jsxRuntime.jsxs("div", {
1292
1290
  class: "bio-properties-panel-entry bio-properties-panel-checkbox-entry",
1293
1291
  "data-entry-id": id,
@@ -1296,7 +1294,6 @@ function CheckboxEntry(props) {
1296
1294
  id: id,
1297
1295
  label: label,
1298
1296
  onChange: setValue,
1299
- show: show,
1300
1297
  value: value
1301
1298
  }), error && jsxRuntime.jsx("div", {
1302
1299
  class: "bio-properties-panel-error",
@@ -1623,25 +1620,6 @@ function prefixId$5(id) {
1623
1620
  return `bio-properties-panel-${id}`;
1624
1621
  }
1625
1622
 
1626
- const noop$1 = () => {};
1627
- /**
1628
- * @typedef { { value: string, label: string, disabled: boolean } } Option
1629
- */
1630
-
1631
- /**
1632
- * Provides basic select input.
1633
- *
1634
- * @param {object} props
1635
- * @param {string} props.id
1636
- * @param {string[]} props.path
1637
- * @param {string} props.label
1638
- * @param {Function} props.onChange
1639
- * @param {Array<Option>} [props.options]
1640
- * @param {string} props.value
1641
- * @param {boolean} [props.disabled]
1642
- */
1643
-
1644
-
1645
1623
  function Select(props) {
1646
1624
  const {
1647
1625
  id,
@@ -1649,10 +1627,9 @@ function Select(props) {
1649
1627
  onChange,
1650
1628
  options = [],
1651
1629
  value,
1652
- disabled,
1653
- show = noop$1
1630
+ disabled
1654
1631
  } = props;
1655
- const ref = useShowEntryEvent(show);
1632
+ const ref = useShowEntryEvent(id);
1656
1633
  const [localValue, setLocalValue] = hooks.useState(value);
1657
1634
 
1658
1635
  const handleChangeCallback = ({
@@ -1719,12 +1696,11 @@ function SelectEntry(props) {
1719
1696
  getValue,
1720
1697
  setValue,
1721
1698
  getOptions,
1722
- disabled,
1723
- show = noop$1
1699
+ disabled
1724
1700
  } = props;
1725
1701
  const value = getValue(element);
1726
1702
  const options = getOptions(element);
1727
- const error = useShowErrorEvent(show);
1703
+ const error = useError(id);
1728
1704
  return jsxRuntime.jsxs("div", {
1729
1705
  class: classnames__default["default"]('bio-properties-panel-entry', error ? 'has-error' : ''),
1730
1706
  "data-entry-id": id,
@@ -1734,8 +1710,7 @@ function SelectEntry(props) {
1734
1710
  value: value,
1735
1711
  onChange: setValue,
1736
1712
  options: options,
1737
- disabled: disabled,
1738
- show: show
1713
+ disabled: disabled
1739
1714
  }), error && jsxRuntime.jsx("div", {
1740
1715
  class: "bio-properties-panel-error",
1741
1716
  children: error
@@ -1838,6 +1813,7 @@ function TextArea(props) {
1838
1813
  monospace
1839
1814
  } = props;
1840
1815
  const [localValue, setLocalValue] = hooks.useState(value);
1816
+ const ref = useShowEntryEvent(id);
1841
1817
  const handleInputCallback = hooks.useMemo(() => {
1842
1818
  return debounce(({
1843
1819
  target
@@ -1866,6 +1842,7 @@ function TextArea(props) {
1866
1842
  label: label
1867
1843
  })]
1868
1844
  }), jsxRuntime.jsx("textarea", {
1845
+ ref: ref,
1869
1846
  id: prefixId$2(id),
1870
1847
  name: id,
1871
1848
  spellCheck: "false",
@@ -1909,6 +1886,7 @@ function TextAreaEntry(props) {
1909
1886
  disabled
1910
1887
  } = props;
1911
1888
  const value = getValue(element);
1889
+ const error = useError(id);
1912
1890
  return jsxRuntime.jsxs("div", {
1913
1891
  class: "bio-properties-panel-entry",
1914
1892
  "data-entry-id": id,
@@ -1922,6 +1900,9 @@ function TextAreaEntry(props) {
1922
1900
  monospace: monospace,
1923
1901
  feel: feel,
1924
1902
  disabled: disabled
1903
+ }), error && jsxRuntime.jsx("div", {
1904
+ class: "bio-properties-panel-error",
1905
+ children: error
1925
1906
  }), jsxRuntime.jsx(Description, {
1926
1907
  forId: id,
1927
1908
  element: element,
@@ -1937,8 +1918,6 @@ function prefixId$2(id) {
1937
1918
  return `bio-properties-panel-${id}`;
1938
1919
  }
1939
1920
 
1940
- const noop = () => {};
1941
-
1942
1921
  function Textfield(props) {
1943
1922
  const {
1944
1923
  debounce,
@@ -1947,11 +1926,10 @@ function Textfield(props) {
1947
1926
  label,
1948
1927
  onInput,
1949
1928
  feel = false,
1950
- value = '',
1951
- show = noop
1929
+ value = ''
1952
1930
  } = props;
1953
1931
  const [localValue, setLocalValue] = hooks.useState(value || '');
1954
- const ref = useShowEntryEvent(show);
1932
+ const ref = useShowEntryEvent(id);
1955
1933
  const handleInputCallback = hooks.useMemo(() => {
1956
1934
  return debounce(({
1957
1935
  target
@@ -2020,17 +1998,17 @@ function TextfieldEntry(props) {
2020
1998
  label,
2021
1999
  getValue,
2022
2000
  setValue,
2023
- validate,
2024
- show = noop
2001
+ validate
2025
2002
  } = props;
2026
2003
  const [cachedInvalidValue, setCachedInvalidValue] = hooks.useState(null);
2027
- const [validationError, setValidationError] = hooks.useState(null);
2004
+ const globalError = useError(id);
2005
+ const [localError, setLocalError] = hooks.useState(null);
2028
2006
  let value = getValue(element);
2029
2007
  const previousValue = usePrevious(value);
2030
2008
  hooks.useEffect(() => {
2031
2009
  if (minDash.isFunction(validate)) {
2032
2010
  const newValidationError = validate(value) || null;
2033
- setValidationError(newValidationError);
2011
+ setLocalError(newValidationError);
2034
2012
  }
2035
2013
  }, [value]);
2036
2014
 
@@ -2047,15 +2025,14 @@ function TextfieldEntry(props) {
2047
2025
  setValue(newValue);
2048
2026
  }
2049
2027
 
2050
- setValidationError(newValidationError);
2028
+ setLocalError(newValidationError);
2051
2029
  };
2052
2030
 
2053
- if (previousValue === value && validationError) {
2031
+ if (previousValue === value && localError) {
2054
2032
  value = cachedInvalidValue;
2055
2033
  }
2056
2034
 
2057
- const temporaryError = useShowErrorEvent(show);
2058
- const error = temporaryError || validationError;
2035
+ const error = globalError || localError;
2059
2036
  return jsxRuntime.jsxs("div", {
2060
2037
  class: classnames__default["default"]('bio-properties-panel-entry', error ? 'has-error' : ''),
2061
2038
  "data-entry-id": id,
@@ -2066,7 +2043,6 @@ function TextfieldEntry(props) {
2066
2043
  id: id,
2067
2044
  label: label,
2068
2045
  onInput: onInput,
2069
- show: show,
2070
2046
  value: value
2071
2047
  }), error && jsxRuntime.jsx("div", {
2072
2048
  class: "bio-properties-panel-error",
@@ -2212,6 +2188,7 @@ exports.DeleteIcon = DeleteIcon;
2212
2188
  exports.DescriptionContext = DescriptionContext;
2213
2189
  exports.DescriptionEntry = Description;
2214
2190
  exports.DropdownButton = DropdownButton;
2191
+ exports.ErrorsContext = ErrorsContext;
2215
2192
  exports.EventContext = EventContext;
2216
2193
  exports.ExternalLinkIcon = ExternalLinkIcon;
2217
2194
  exports.FeelOptionalIcon = FeelOptionalIcon;
@@ -2240,12 +2217,12 @@ exports.isTextAreaEntryEdited = isEdited$2;
2240
2217
  exports.isTextFieldEntryEdited = isEdited$1;
2241
2218
  exports.isToggleSwitchEntryEdited = isEdited;
2242
2219
  exports.useDescriptionContext = useDescriptionContext;
2220
+ exports.useError = useError;
2243
2221
  exports.useEvent = useEvent;
2244
2222
  exports.useEventBuffer = useEventBuffer;
2245
2223
  exports.useKeyFactory = useKeyFactory;
2246
2224
  exports.useLayoutState = useLayoutState;
2247
2225
  exports.usePrevious = usePrevious;
2248
2226
  exports.useShowEntryEvent = useShowEntryEvent;
2249
- exports.useShowErrorEvent = useShowErrorEvent;
2250
2227
  exports.useStickyIntersectionObserver = useStickyIntersectionObserver;
2251
2228
  //# sourceMappingURL=index.js.map