@bpmn-io/form-js-viewer 1.7.0-alpha.0 → 1.7.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.cjs CHANGED
@@ -1589,7 +1589,8 @@ function useCleanupMultiSelectValue(props) {
1589
1589
 
1590
1590
  function Description(props) {
1591
1591
  const {
1592
- description
1592
+ description,
1593
+ id
1593
1594
  } = props;
1594
1595
  const evaluatedDescription = useSingleLineTemplateEvaluation(description || '', {
1595
1596
  debug: true
@@ -1598,6 +1599,7 @@ function Description(props) {
1598
1599
  return null;
1599
1600
  }
1600
1601
  return jsxRuntime.jsx("div", {
1602
+ id: id,
1601
1603
  class: "fjs-form-field-description",
1602
1604
  children: evaluatedDescription
1603
1605
  });
@@ -1628,6 +1630,7 @@ function Errors(props) {
1628
1630
  function Label(props) {
1629
1631
  const {
1630
1632
  id,
1633
+ htmlFor,
1631
1634
  label,
1632
1635
  collapseOnEmpty = true,
1633
1636
  required = false
@@ -1636,12 +1639,14 @@ function Label(props) {
1636
1639
  debug: true
1637
1640
  });
1638
1641
  return jsxRuntime.jsxs("label", {
1639
- for: id,
1642
+ id: id,
1643
+ for: htmlFor,
1640
1644
  class: classNames('fjs-form-field-label', {
1641
1645
  'fjs-incollapsible-label': !collapseOnEmpty
1642
1646
  }, props['class']),
1643
1647
  children: [props.children, evaluatedLabel, required && jsxRuntime.jsx("span", {
1644
1648
  class: "fjs-asterix",
1649
+ "aria-hidden": true,
1645
1650
  children: "*"
1646
1651
  })]
1647
1652
  });
@@ -1652,7 +1657,6 @@ function Checkbox(props) {
1652
1657
  const {
1653
1658
  disabled,
1654
1659
  errors = [],
1655
- errorMessageId,
1656
1660
  domId,
1657
1661
  onBlur,
1658
1662
  onFocus,
@@ -1676,6 +1680,8 @@ function Checkbox(props) {
1676
1680
  value: target.checked
1677
1681
  });
1678
1682
  };
1683
+ const descriptionId = `${domId}-description`;
1684
+ const errorMessageId = `${domId}-error-message`;
1679
1685
  return jsxRuntime.jsxs("div", {
1680
1686
  class: classNames(formFieldClasses(type$f, {
1681
1687
  errors,
@@ -1685,7 +1691,7 @@ function Checkbox(props) {
1685
1691
  'fjs-checked': value
1686
1692
  }),
1687
1693
  children: [jsxRuntime.jsx(Label, {
1688
- id: domId,
1694
+ htmlFor: domId,
1689
1695
  label: label,
1690
1696
  required: required,
1691
1697
  children: jsxRuntime.jsx("input", {
@@ -1698,13 +1704,16 @@ function Checkbox(props) {
1698
1704
  onChange: onChange,
1699
1705
  onBlur: () => onBlur && onBlur(),
1700
1706
  onFocus: () => onFocus && onFocus(),
1701
- "aria-describedby": errorMessageId
1707
+ required: required,
1708
+ "aria-invalid": errors.length > 0,
1709
+ "aria-describedby": [descriptionId, errorMessageId].join(' ')
1702
1710
  })
1703
1711
  }), jsxRuntime.jsx(Description, {
1712
+ id: descriptionId,
1704
1713
  description: description
1705
1714
  }), jsxRuntime.jsx(Errors, {
1706
- errors: errors,
1707
- id: errorMessageId
1715
+ id: errorMessageId,
1716
+ errors: errors
1708
1717
  })]
1709
1718
  });
1710
1719
  }
@@ -1727,7 +1736,6 @@ function Checklist(props) {
1727
1736
  const {
1728
1737
  disabled,
1729
1738
  errors = [],
1730
- errorMessageId,
1731
1739
  domId,
1732
1740
  onBlur,
1733
1741
  onFocus,
@@ -1774,6 +1782,8 @@ function Checklist(props) {
1774
1782
  values,
1775
1783
  onChange: props.onChange
1776
1784
  });
1785
+ const descriptionId = `${domId}-description`;
1786
+ const errorMessageId = `${domId}-error-message`;
1777
1787
  return jsxRuntime.jsxs("div", {
1778
1788
  class: classNames(formFieldClasses(type$e, {
1779
1789
  errors,
@@ -1788,7 +1798,7 @@ function Checklist(props) {
1788
1798
  const itemDomId = `${domId}-${index}`;
1789
1799
  const isChecked = hasEqualValue(o.value, values);
1790
1800
  return jsxRuntime.jsx(Label, {
1791
- id: itemDomId,
1801
+ htmlFor: itemDomId,
1792
1802
  label: o.label,
1793
1803
  class: classNames({
1794
1804
  'fjs-checked': isChecked
@@ -1804,14 +1814,17 @@ function Checklist(props) {
1804
1814
  onClick: () => toggleCheckbox(o.value),
1805
1815
  onBlur: onCheckboxBlur,
1806
1816
  onFocus: onCheckboxFocus,
1807
- "aria-describedby": errorMessageId
1817
+ required: required,
1818
+ "aria-invalid": errors.length > 0,
1819
+ "aria-describedby": [descriptionId, errorMessageId].join(' ')
1808
1820
  })
1809
1821
  });
1810
1822
  }), jsxRuntime.jsx(Description, {
1823
+ id: descriptionId,
1811
1824
  description: description
1812
1825
  }), jsxRuntime.jsx(Errors, {
1813
- errors: errors,
1814
- id: errorMessageId
1826
+ id: errorMessageId,
1827
+ errors: errors
1815
1828
  })]
1816
1829
  });
1817
1830
  }
@@ -1851,6 +1864,10 @@ function FormField(props) {
1851
1864
  const {
1852
1865
  formId
1853
1866
  } = hooks.useContext(FormContext);
1867
+
1868
+ // track whether we should trigger initial validation on certain actions, e.g. field blur
1869
+ // disabled straight away, if viewerCommands are not available
1870
+ const [initialValidationTrigger, setInitialValidationTrigger] = hooks.useState(!!viewerCommands);
1854
1871
  const FormFieldComponent = formFields.get(field.type);
1855
1872
  if (!FormFieldComponent) {
1856
1873
  throw new Error(`cannot render field <${field.type}>`);
@@ -1864,26 +1881,48 @@ function FormField(props) {
1864
1881
 
1865
1882
  // add precedence: global readonly > form field disabled
1866
1883
  const disabled = !properties.readOnly && (properties.disabled || field.disabled || false);
1884
+
1885
+ // ensures the initial validation behavior can be re-triggered upon form reset
1886
+ hooks.useEffect(() => {
1887
+ if (!viewerCommands) {
1888
+ return;
1889
+ }
1890
+ const resetValidation = () => {
1891
+ setInitialValidationTrigger(true);
1892
+ };
1893
+ eventBus.on('import.done', resetValidation);
1894
+ eventBus.on('reset', resetValidation);
1895
+ return () => {
1896
+ eventBus.off('import.done', resetValidation);
1897
+ eventBus.off('reset', resetValidation);
1898
+ };
1899
+ }, [eventBus, viewerCommands]);
1900
+ hooks.useEffect(() => {
1901
+ if (initialValidationTrigger && initialValue) {
1902
+ setInitialValidationTrigger(false);
1903
+ viewerCommands.updateFieldValidation(field, initialValue, indexes);
1904
+ }
1905
+ }, [viewerCommands, field, initialValue, initialValidationTrigger, indexes]);
1867
1906
  const onBlur = hooks.useCallback(() => {
1868
- if (viewerCommands) {
1907
+ const value = minDash.get(data, valuePath);
1908
+ if (initialValidationTrigger) {
1909
+ setInitialValidationTrigger(false);
1869
1910
  viewerCommands.updateFieldValidation(field, value, indexes);
1870
1911
  }
1871
1912
  eventBus.fire('formField.blur', {
1872
1913
  formField: field
1873
1914
  });
1874
- }, [eventBus, viewerCommands, field, value, indexes]);
1915
+ }, [eventBus, field, indexes, viewerCommands, initialValidationTrigger, data, valuePath]);
1875
1916
  const onFocus = hooks.useCallback(() => {
1876
1917
  eventBus.fire('formField.focus', {
1877
1918
  formField: field
1878
1919
  });
1879
1920
  }, [eventBus, field]);
1880
- hooks.useEffect(() => {
1881
- if (viewerCommands && initialValue) {
1882
- viewerCommands.updateFieldValidation(field, initialValue, indexes);
1883
- }
1884
- }, [viewerCommands, field, initialValue, indexes]);
1885
1921
  const hidden = useCondition(field.conditional && field.conditional.hide || null);
1886
1922
  const onChangeIndexed = hooks.useCallback(update => {
1923
+ // any data change will trigger validation
1924
+ setInitialValidationTrigger(false);
1925
+
1887
1926
  // add indexes of the keyed field to the update, if any
1888
1927
  onChange(FormFieldComponent.config.keyed ? {
1889
1928
  ...update,
@@ -1897,7 +1936,6 @@ function FormField(props) {
1897
1936
  }
1898
1937
  const domId = `${prefixId(field.id, formId, indexes)}`;
1899
1938
  const fieldErrors = minDash.get(errors, [field.id, ...Object.values(indexes || {})]) || [];
1900
- const errorMessageId = errors.length === 0 ? undefined : `${domId}-error-message`;
1901
1939
  return jsxRuntime.jsx(Column, {
1902
1940
  field: field,
1903
1941
  class: gridColumnClasses(field),
@@ -1908,7 +1946,6 @@ function FormField(props) {
1908
1946
  ...props,
1909
1947
  disabled: disabled,
1910
1948
  errors: fieldErrors,
1911
- errorMessageId: errorMessageId,
1912
1949
  domId: domId,
1913
1950
  onChange: disabled || readonly ? noop$1 : onChangeIndexed,
1914
1951
  onBlur: disabled || readonly ? noop$1 : onBlur,
@@ -2311,7 +2348,7 @@ function Datepicker(props) {
2311
2348
  return jsxRuntime.jsxs("div", {
2312
2349
  class: "fjs-datetime-subsection",
2313
2350
  children: [jsxRuntime.jsx(Label, {
2314
- id: domId,
2351
+ htmlFor: domId,
2315
2352
  label: label,
2316
2353
  collapseOnEmpty: collapseLabelOnEmpty,
2317
2354
  required: required
@@ -2583,7 +2620,7 @@ function Timepicker(props) {
2583
2620
  return jsxRuntime.jsxs("div", {
2584
2621
  class: "fjs-datetime-subsection",
2585
2622
  children: [jsxRuntime.jsx(Label, {
2586
- id: domId,
2623
+ htmlFor: domId,
2587
2624
  label: label,
2588
2625
  collapseOnEmpty: collapseLabelOnEmpty,
2589
2626
  required: required
@@ -2770,6 +2807,7 @@ function Datetime(props) {
2770
2807
  });
2771
2808
  }, []);
2772
2809
  const errorMessageId = allErrors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
2810
+ const descriptionId = `${prefixId(id, formId)}-description`;
2773
2811
  const datePickerProps = {
2774
2812
  label: dateLabel,
2775
2813
  collapseLabelOnEmpty: !timeLabel,
@@ -2782,7 +2820,7 @@ function Datetime(props) {
2782
2820
  date: dateTime.date,
2783
2821
  readonly,
2784
2822
  setDate,
2785
- 'aria-describedby': errorMessageId
2823
+ 'aria-describedby': [descriptionId, errorMessageId].join(' ')
2786
2824
  };
2787
2825
  const timePickerProps = {
2788
2826
  label: timeLabel,
@@ -2797,7 +2835,7 @@ function Datetime(props) {
2797
2835
  timeInterval,
2798
2836
  time: dateTime.time,
2799
2837
  setTime,
2800
- 'aria-describedby': errorMessageId
2838
+ 'aria-describedby': [descriptionId, errorMessageId].join(' ')
2801
2839
  };
2802
2840
  return jsxRuntime.jsxs("div", {
2803
2841
  class: formFieldClasses(type$d, {
@@ -2816,6 +2854,7 @@ function Datetime(props) {
2816
2854
  ...timePickerProps
2817
2855
  })]
2818
2856
  }), jsxRuntime.jsx(Description, {
2857
+ id: descriptionId,
2819
2858
  description: description
2820
2859
  }), jsxRuntime.jsx(Errors, {
2821
2860
  errors: allErrors,
@@ -2919,7 +2958,7 @@ function IFrame(props) {
2919
2958
  readonly
2920
2959
  }),
2921
2960
  children: [jsxRuntime.jsx(Label, {
2922
- id: domId,
2961
+ htmlFor: domId,
2923
2962
  label: evaluatedLabel
2924
2963
  }), !evaluatedUrl && jsxRuntime.jsx(IFramePlaceholder, {
2925
2964
  text: "No content to show."
@@ -3465,7 +3504,6 @@ function Numberfield(props) {
3465
3504
  const {
3466
3505
  disabled,
3467
3506
  errors = [],
3468
- errorMessageId,
3469
3507
  domId,
3470
3508
  onBlur,
3471
3509
  onFocus,
@@ -3603,6 +3641,8 @@ function Numberfield(props) {
3603
3641
  e.preventDefault();
3604
3642
  }
3605
3643
  };
3644
+ const descriptionId = `${domId}-description`;
3645
+ const errorMessageId = `${domId}-error-message`;
3606
3646
  return jsxRuntime.jsxs("div", {
3607
3647
  class: formFieldClasses(type$a, {
3608
3648
  errors,
@@ -3610,7 +3650,7 @@ function Numberfield(props) {
3610
3650
  readonly
3611
3651
  }),
3612
3652
  children: [jsxRuntime.jsx(Label, {
3613
- id: domId,
3653
+ htmlFor: domId,
3614
3654
  label: label,
3615
3655
  required: required
3616
3656
  }), jsxRuntime.jsx(TemplatedInputAdorner, {
@@ -3644,7 +3684,9 @@ function Numberfield(props) {
3644
3684
  autoComplete: "off",
3645
3685
  step: incrementAmount,
3646
3686
  value: displayValue,
3647
- "aria-describedby": errorMessageId
3687
+ "aria-describedby": [descriptionId, errorMessageId].join(' '),
3688
+ required: required,
3689
+ "aria-invalid": errors.length > 0
3648
3690
  }), jsxRuntime.jsxs("div", {
3649
3691
  class: classNames('fjs-number-arrow-container', {
3650
3692
  'fjs-disabled': disabled,
@@ -3670,10 +3712,11 @@ function Numberfield(props) {
3670
3712
  })]
3671
3713
  })
3672
3714
  }), jsxRuntime.jsx(Description, {
3715
+ id: descriptionId,
3673
3716
  description: description
3674
3717
  }), jsxRuntime.jsx(Errors, {
3675
- errors: errors,
3676
- id: errorMessageId
3718
+ id: errorMessageId,
3719
+ errors: errors
3677
3720
  })]
3678
3721
  });
3679
3722
  }
@@ -3703,7 +3746,6 @@ function Radio(props) {
3703
3746
  const {
3704
3747
  disabled,
3705
3748
  errors = [],
3706
- errorMessageId,
3707
3749
  domId,
3708
3750
  onBlur,
3709
3751
  onFocus,
@@ -3749,6 +3791,8 @@ function Radio(props) {
3749
3791
  value,
3750
3792
  onChange: props.onChange
3751
3793
  });
3794
+ const descriptionId = `${domId}-description`;
3795
+ const errorMessageId = `${domId}-error-message`;
3752
3796
  return jsxRuntime.jsxs("div", {
3753
3797
  class: formFieldClasses(type$9, {
3754
3798
  errors,
@@ -3763,7 +3807,7 @@ function Radio(props) {
3763
3807
  const itemDomId = `${domId}-${index}`;
3764
3808
  const isChecked = isEqual(option.value, value);
3765
3809
  return jsxRuntime.jsx(Label, {
3766
- id: itemDomId,
3810
+ htmlFor: itemDomId,
3767
3811
  label: option.label,
3768
3812
  class: classNames({
3769
3813
  'fjs-checked': isChecked
@@ -3779,14 +3823,17 @@ function Radio(props) {
3779
3823
  onClick: () => onChange(option.value),
3780
3824
  onBlur: onRadioBlur,
3781
3825
  onFocus: onRadioFocus,
3782
- "aria-describedby": errorMessageId
3826
+ "aria-describedby": [descriptionId, errorMessageId].join(' '),
3827
+ required: required,
3828
+ "aria-invalid": errors.length > 0
3783
3829
  })
3784
3830
  }, index);
3785
3831
  }), jsxRuntime.jsx(Description, {
3832
+ id: descriptionId,
3786
3833
  description: description
3787
3834
  }), jsxRuntime.jsx(Errors, {
3788
- errors: errors,
3789
- id: errorMessageId
3835
+ id: errorMessageId,
3836
+ errors: errors
3790
3837
  })]
3791
3838
  });
3792
3839
  }
@@ -3851,7 +3898,7 @@ function SearchableSelect(props) {
3851
3898
 
3852
3899
  // whenever we change the underlying value, set the label to it
3853
3900
  hooks.useEffect(() => {
3854
- setFilter(label);
3901
+ setFilter(label || '');
3855
3902
  }, [label]);
3856
3903
  const filteredOptions = hooks.useMemo(() => {
3857
3904
  if (loadState !== LOAD_STATES.LOADED) {
@@ -3931,7 +3978,7 @@ function SearchableSelect(props) {
3931
3978
  }, [onFocus]);
3932
3979
  const onInputBlur = hooks.useCallback(() => {
3933
3980
  setIsDropdownExpanded(false);
3934
- setFilter(label);
3981
+ setFilter(label || '');
3935
3982
  onBlur && onBlur();
3936
3983
  }, [onBlur, label]);
3937
3984
  return jsxRuntime.jsxs(jsxRuntime.Fragment, {
@@ -4027,6 +4074,9 @@ function SimpleSelect(props) {
4027
4074
  }, [disabled, isDropdownExpanded, loadState, readonly, value]);
4028
4075
  const onMouseDown = hooks.useCallback(e => {
4029
4076
  const input = inputRef.current;
4077
+ if (disabled || !input) {
4078
+ return;
4079
+ }
4030
4080
  setIsDropdownExpanded(!isDropdownExpanded);
4031
4081
  if (isDropdownExpanded) {
4032
4082
  input.blur();
@@ -4034,7 +4084,7 @@ function SimpleSelect(props) {
4034
4084
  input.focus();
4035
4085
  }
4036
4086
  e.preventDefault();
4037
- }, [isDropdownExpanded]);
4087
+ }, [disabled, isDropdownExpanded]);
4038
4088
  const initialFocusIndex = hooks.useMemo(() => value && minDash.findIndex(options, o => o.value === value) || 0, [options, value]);
4039
4089
  const onInputFocus = hooks.useCallback(() => {
4040
4090
  if (!readonly) {
@@ -4106,7 +4156,6 @@ function Select(props) {
4106
4156
  const {
4107
4157
  disabled,
4108
4158
  errors = [],
4109
- errorMessageId,
4110
4159
  domId,
4111
4160
  onBlur,
4112
4161
  onFocus,
@@ -4124,6 +4173,8 @@ function Select(props) {
4124
4173
  const {
4125
4174
  required
4126
4175
  } = validate;
4176
+ const descriptionId = `${domId}-description`;
4177
+ const errorMessageId = `${domId}-error-message`;
4127
4178
  const selectProps = {
4128
4179
  domId,
4129
4180
  disabled,
@@ -4134,7 +4185,9 @@ function Select(props) {
4134
4185
  value,
4135
4186
  onChange,
4136
4187
  readonly,
4137
- 'aria-describedby': errorMessageId
4188
+ required,
4189
+ 'aria-invalid': errors.length > 0,
4190
+ 'aria-describedby': [descriptionId, errorMessageId].join(' ')
4138
4191
  };
4139
4192
  return jsxRuntime.jsxs("div", {
4140
4193
  class: formFieldClasses(type$8, {
@@ -4149,7 +4202,7 @@ function Select(props) {
4149
4202
  }
4150
4203
  },
4151
4204
  children: [jsxRuntime.jsx(Label, {
4152
- id: domId,
4205
+ htmlFor: domId,
4153
4206
  label: label,
4154
4207
  required: required
4155
4208
  }), searchable ? jsxRuntime.jsx(SearchableSelect, {
@@ -4157,10 +4210,11 @@ function Select(props) {
4157
4210
  }) : jsxRuntime.jsx(SimpleSelect, {
4158
4211
  ...selectProps
4159
4212
  }), jsxRuntime.jsx(Description, {
4213
+ id: descriptionId,
4160
4214
  description: description
4161
4215
  }), jsxRuntime.jsx(Errors, {
4162
- errors: errors,
4163
- id: errorMessageId
4216
+ id: errorMessageId,
4217
+ errors: errors
4164
4218
  })]
4165
4219
  });
4166
4220
  }
@@ -4293,7 +4347,6 @@ function Taglist(props) {
4293
4347
  const {
4294
4348
  disabled,
4295
4349
  errors = [],
4296
- errorMessageId,
4297
4350
  onFocus,
4298
4351
  domId,
4299
4352
  onBlur,
@@ -4429,6 +4482,8 @@ function Taglist(props) {
4429
4482
  inputRef.current.focus();
4430
4483
  };
4431
4484
  const shouldDisplayDropdown = hooks.useMemo(() => !disabled && loadState === LOAD_STATES.LOADED && isDropdownExpanded && !isEscapeClosed, [disabled, isDropdownExpanded, isEscapeClosed, loadState]);
4485
+ const descriptionId = `${domId}-description`;
4486
+ const errorMessageId = `${domId}-error-message`;
4432
4487
  return jsxRuntime.jsxs("div", {
4433
4488
  ref: focusScopeRef,
4434
4489
  class: formFieldClasses(type$5, {
@@ -4445,7 +4500,7 @@ function Taglist(props) {
4445
4500
  children: [jsxRuntime.jsx(Label, {
4446
4501
  label: label,
4447
4502
  required: required,
4448
- id: domId
4503
+ htmlFor: domId
4449
4504
  }), !disabled && !readonly && !!values.length && jsxRuntime.jsx(SkipLink, {
4450
4505
  className: "fjs-taglist-skip-link",
4451
4506
  label: "Skip to search",
@@ -4493,7 +4548,9 @@ function Taglist(props) {
4493
4548
  onMouseDown: () => setIsEscapeClose(false),
4494
4549
  onFocus: onInputFocus,
4495
4550
  onBlur: onInputBlur,
4496
- "aria-describedby": errorMessageId
4551
+ "aria-describedby": [descriptionId, errorMessageId].join(' '),
4552
+ required: required,
4553
+ "aria-invalid": errors.length > 0
4497
4554
  })]
4498
4555
  }), jsxRuntime.jsx("div", {
4499
4556
  class: "fjs-taglist-anchor",
@@ -4505,10 +4562,11 @@ function Taglist(props) {
4505
4562
  listenerElement: inputRef.current
4506
4563
  })
4507
4564
  }), jsxRuntime.jsx(Description, {
4565
+ id: descriptionId,
4508
4566
  description: description
4509
4567
  }), jsxRuntime.jsx(Errors, {
4510
- errors: errors,
4511
- id: errorMessageId
4568
+ id: errorMessageId,
4569
+ errors: errors
4512
4570
  })]
4513
4571
  });
4514
4572
  }
@@ -4825,7 +4883,6 @@ function Textfield(props) {
4825
4883
  const {
4826
4884
  disabled,
4827
4885
  errors = [],
4828
- errorMessageId,
4829
4886
  domId,
4830
4887
  onBlur,
4831
4888
  onFocus,
@@ -4861,6 +4918,8 @@ function Textfield(props) {
4861
4918
  const onInputFocus = () => {
4862
4919
  onFocus && onFocus();
4863
4920
  };
4921
+ const descriptionId = `${domId}-description`;
4922
+ const errorMessageId = `${domId}-error-message`;
4864
4923
  return jsxRuntime.jsxs("div", {
4865
4924
  class: formFieldClasses(type$2, {
4866
4925
  errors,
@@ -4868,7 +4927,7 @@ function Textfield(props) {
4868
4927
  readonly
4869
4928
  }),
4870
4929
  children: [jsxRuntime.jsx(Label, {
4871
- id: domId,
4930
+ htmlFor: domId,
4872
4931
  label: label,
4873
4932
  required: required
4874
4933
  }), jsxRuntime.jsx(TemplatedInputAdorner, {
@@ -4886,13 +4945,16 @@ function Textfield(props) {
4886
4945
  onFocus: onInputFocus,
4887
4946
  type: "text",
4888
4947
  value: value,
4889
- "aria-describedby": errorMessageId
4948
+ "aria-describedby": [descriptionId, errorMessageId].join(' '),
4949
+ required: required,
4950
+ "aria-invalid": errors.length > 0
4890
4951
  })
4891
4952
  }), jsxRuntime.jsx(Description, {
4953
+ id: descriptionId,
4892
4954
  description: description
4893
4955
  }), jsxRuntime.jsx(Errors, {
4894
- errors: errors,
4895
- id: errorMessageId
4956
+ id: errorMessageId,
4957
+ errors: errors
4896
4958
  })]
4897
4959
  });
4898
4960
  }
@@ -4925,7 +4987,6 @@ function Textarea(props) {
4925
4987
  const {
4926
4988
  disabled,
4927
4989
  errors = [],
4928
- errorMessageId,
4929
4990
  domId,
4930
4991
  onBlur,
4931
4992
  onFocus,
@@ -4942,7 +5003,7 @@ function Textarea(props) {
4942
5003
  required
4943
5004
  } = validate;
4944
5005
  const textareaRef = hooks.useRef();
4945
- const [onInputChange, flushOnChange] = useFlushDebounce(({
5006
+ const [onChange, flushOnChange] = useFlushDebounce(({
4946
5007
  target
4947
5008
  }) => {
4948
5009
  props.onChange({
@@ -4957,12 +5018,20 @@ function Textarea(props) {
4957
5018
  const onInputFocus = () => {
4958
5019
  onFocus && onFocus();
4959
5020
  };
5021
+ const onInputChange = event => {
5022
+ onChange({
5023
+ target: event.target
5024
+ });
5025
+ autoSizeTextarea(textareaRef.current);
5026
+ };
4960
5027
  hooks.useLayoutEffect(() => {
4961
5028
  autoSizeTextarea(textareaRef.current);
4962
5029
  }, [value]);
4963
5030
  hooks.useEffect(() => {
4964
5031
  autoSizeTextarea(textareaRef.current);
4965
5032
  }, []);
5033
+ const descriptionId = `${domId}-description`;
5034
+ const errorMessageId = `${domId}-error-message`;
4966
5035
  return jsxRuntime.jsxs("div", {
4967
5036
  class: formFieldClasses(type$1, {
4968
5037
  errors,
@@ -4970,7 +5039,7 @@ function Textarea(props) {
4970
5039
  readonly
4971
5040
  }),
4972
5041
  children: [jsxRuntime.jsx(Label, {
4973
- id: domId,
5042
+ htmlFor: domId,
4974
5043
  label: label,
4975
5044
  required: required
4976
5045
  }), jsxRuntime.jsx("textarea", {
@@ -4983,12 +5052,15 @@ function Textarea(props) {
4983
5052
  onFocus: onInputFocus,
4984
5053
  value: value,
4985
5054
  ref: textareaRef,
4986
- "aria-describedby": errorMessageId
5055
+ "aria-describedby": [descriptionId, errorMessageId].join(' '),
5056
+ required: required,
5057
+ "aria-invalid": errors.length > 0
4987
5058
  }), jsxRuntime.jsx(Description, {
5059
+ id: descriptionId,
4988
5060
  description: description
4989
5061
  }), jsxRuntime.jsx(Errors, {
4990
- errors: errors,
4991
- id: errorMessageId
5062
+ id: errorMessageId,
5063
+ errors: errors
4992
5064
  })]
4993
5065
  });
4994
5066
  }
@@ -5157,7 +5229,7 @@ function Table(props) {
5157
5229
  return jsxRuntime.jsxs("div", {
5158
5230
  class: formFieldClasses(type),
5159
5231
  children: [jsxRuntime.jsx(Label, {
5160
- id: prefixId(id),
5232
+ htmlFor: prefixId(id),
5161
5233
  label: label
5162
5234
  }), jsxRuntime.jsxs("div", {
5163
5235
  class: classNames('fjs-table-middle-container', {
@@ -5557,7 +5629,7 @@ class FormFields {
5557
5629
  }
5558
5630
 
5559
5631
  const EXPRESSION_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'conditional.hide', 'description', 'label', 'source', 'readonly', 'text', 'validate.min', 'validate.max', 'validate.minLength', 'validate.maxLength', 'valuesExpression', 'url', 'dataSource', 'columnsExpression'];
5560
- const TEMPLATE_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'description', 'label', 'source', 'text', 'url'];
5632
+ const TEMPLATE_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'description', 'label', 'source', 'text', 'content', 'url'];
5561
5633
 
5562
5634
  /**
5563
5635
  * @typedef { import('../types').Schema } Schema
@@ -6543,47 +6615,17 @@ class RepeatRenderManager {
6543
6615
  };
6544
6616
  const parentExpressionContextInfo = hooks.useContext(LocalExpressionContext);
6545
6617
  return jsxRuntime.jsx(jsxRuntime.Fragment, {
6546
- children: displayValues.map((value, index) => {
6547
- const elementProps = hooks.useMemo(() => ({
6548
- ...restProps,
6549
- indexes: {
6550
- ...(indexes || {}),
6551
- [repeaterField.id]: index
6552
- }
6553
- }), [index]);
6554
- const localExpressionContextInfo = hooks.useMemo(() => ({
6555
- data: parentExpressionContextInfo.data,
6556
- this: value,
6557
- parent: buildExpressionContext(parentExpressionContextInfo),
6558
- i: [...parentExpressionContextInfo.i, index + 1]
6559
- }), [index, value]);
6560
- return !showRemove ? jsxRuntime.jsx(LocalExpressionContext.Provider, {
6561
- value: localExpressionContextInfo,
6562
- children: jsxRuntime.jsx(RowsRenderer, {
6563
- ...elementProps
6564
- })
6565
- }) : jsxRuntime.jsxs("div", {
6566
- class: "fjs-repeat-row-container",
6567
- children: [jsxRuntime.jsx("div", {
6568
- class: "fjs-repeat-row-rows",
6569
- children: jsxRuntime.jsx(LocalExpressionContext.Provider, {
6570
- value: localExpressionContextInfo,
6571
- children: jsxRuntime.jsx(RowsRenderer, {
6572
- ...elementProps
6573
- })
6574
- })
6575
- }), jsxRuntime.jsx("button", {
6576
- class: "fjs-repeat-row-remove",
6577
- type: "button",
6578
- "aria-label": `Remove list item ${index + 1}`,
6579
- onClick: () => onDeleteItem(index),
6580
- children: jsxRuntime.jsx("div", {
6581
- class: "fjs-repeat-row-remove-icon-container",
6582
- children: jsxRuntime.jsx(DeleteSvg, {})
6583
- })
6584
- })]
6585
- });
6586
- })
6618
+ children: displayValues.map((value, index) => jsxRuntime.jsx(RepetitionScaffold, {
6619
+ index: index,
6620
+ value: value,
6621
+ parentExpressionContextInfo: parentExpressionContextInfo,
6622
+ repeaterField: repeaterField,
6623
+ RowsRenderer: RowsRenderer,
6624
+ indexes: indexes,
6625
+ onDeleteItem: onDeleteItem,
6626
+ showRemove: showRemove,
6627
+ ...restProps
6628
+ }, index))
6587
6629
  });
6588
6630
  }
6589
6631
  RepeatFooter(props) {
@@ -6675,6 +6717,73 @@ class RepeatRenderManager {
6675
6717
  return nonCollapsedItems ? nonCollapsedItems : DEFAULT_NON_COLLAPSED_ITEMS;
6676
6718
  }
6677
6719
  }
6720
+
6721
+ /**
6722
+ * Individual repetition of a repeated field and context scaffolding.
6723
+ *
6724
+ * @param {Object} props
6725
+ * @param {number} props.index
6726
+ * @param {Object} props.value
6727
+ * @param {Object} props.parentExpressionContextInfo
6728
+ * @param {Object} props.repeaterField
6729
+ * @param {Function} props.RowsRenderer
6730
+ * @param {Object} props.indexes
6731
+ * @param {Function} props.onDeleteItem
6732
+ * @param {boolean} props.showRemove
6733
+ */
6734
+
6735
+ const RepetitionScaffold = props => {
6736
+ const {
6737
+ index,
6738
+ value,
6739
+ parentExpressionContextInfo,
6740
+ repeaterField,
6741
+ RowsRenderer,
6742
+ indexes,
6743
+ onDeleteItem,
6744
+ showRemove,
6745
+ ...restProps
6746
+ } = props;
6747
+ const elementProps = hooks.useMemo(() => ({
6748
+ ...restProps,
6749
+ indexes: {
6750
+ ...(indexes || {}),
6751
+ [repeaterField.id]: index
6752
+ }
6753
+ }), [index, indexes, repeaterField.id, restProps]);
6754
+ const localExpressionContextInfo = hooks.useMemo(() => ({
6755
+ data: parentExpressionContextInfo.data,
6756
+ this: value,
6757
+ parent: buildExpressionContext(parentExpressionContextInfo),
6758
+ i: [...parentExpressionContextInfo.i, index + 1]
6759
+ }), [index, parentExpressionContextInfo, value]);
6760
+ return !showRemove ? jsxRuntime.jsx(LocalExpressionContext.Provider, {
6761
+ value: localExpressionContextInfo,
6762
+ children: jsxRuntime.jsx(RowsRenderer, {
6763
+ ...elementProps
6764
+ })
6765
+ }) : jsxRuntime.jsxs("div", {
6766
+ class: "fjs-repeat-row-container",
6767
+ children: [jsxRuntime.jsx("div", {
6768
+ class: "fjs-repeat-row-rows",
6769
+ children: jsxRuntime.jsx(LocalExpressionContext.Provider, {
6770
+ value: localExpressionContextInfo,
6771
+ children: jsxRuntime.jsx(RowsRenderer, {
6772
+ ...elementProps
6773
+ })
6774
+ })
6775
+ }), jsxRuntime.jsx("button", {
6776
+ class: "fjs-repeat-row-remove",
6777
+ type: "button",
6778
+ "aria-label": `Remove list item ${index + 1}`,
6779
+ onClick: () => onDeleteItem(index),
6780
+ children: jsxRuntime.jsx("div", {
6781
+ class: "fjs-repeat-row-remove-icon-container",
6782
+ children: jsxRuntime.jsx(DeleteSvg, {})
6783
+ })
6784
+ })]
6785
+ });
6786
+ };
6678
6787
  RepeatRenderManager.$inject = ['form', 'formFields', 'formFieldRegistry', 'pathRegistry'];
6679
6788
 
6680
6789
  const RepeatRenderModule = {
@@ -8112,10 +8221,10 @@ class Form {
8112
8221
  }
8113
8222
  }
8114
8223
  clear() {
8115
- // clear form services
8224
+ // clear diagram services (e.g. EventBus)
8116
8225
  this._emit('diagram.clear');
8117
8226
 
8118
- // clear diagram services (e.g. EventBus)
8227
+ // clear form services
8119
8228
  this._emit('form.clear');
8120
8229
  }
8121
8230