@bpmn-io/form-js-viewer 1.5.0 → 1.6.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.
Files changed (43) hide show
  1. package/dist/assets/form-js-base.css +220 -16
  2. package/dist/assets/form-js.css +219 -16
  3. package/dist/index.cjs +1822 -606
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.es.js +1812 -603
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/types/Form.d.ts +15 -4
  8. package/dist/types/core/FieldFactory.d.ts +2 -0
  9. package/dist/types/core/FormFieldRegistry.d.ts +1 -0
  10. package/dist/types/core/PathRegistry.d.ts +7 -3
  11. package/dist/types/features/{expression-language → expressionLanguage}/ConditionChecker.d.ts +8 -4
  12. package/dist/types/features/index.d.ts +4 -2
  13. package/dist/types/features/repeatRender/RepeatRenderManager.d.ts +21 -0
  14. package/dist/types/features/repeatRender/index.d.ts +7 -0
  15. package/dist/types/features/viewerCommands/ViewerCommands.d.ts +1 -1
  16. package/dist/types/index.d.ts +1 -1
  17. package/dist/types/render/components/Label.d.ts +21 -1
  18. package/dist/types/render/components/Util.d.ts +1 -1
  19. package/dist/types/render/components/form-fields/DynamicList.d.ts +18 -0
  20. package/dist/types/render/components/form-fields/Table.d.ts +71 -0
  21. package/dist/types/render/components/form-fields/parts/ChildrenRenderer.d.ts +1 -0
  22. package/dist/types/render/components/index.d.ts +3 -1
  23. package/dist/types/render/context/FormRenderContext.d.ts +4 -3
  24. package/dist/types/render/context/LocalExpressionContext.d.ts +7 -0
  25. package/dist/types/render/context/index.d.ts +1 -0
  26. package/dist/types/render/hooks/index.d.ts +1 -0
  27. package/dist/types/render/hooks/useExpressionEvaluation.d.ts +3 -3
  28. package/dist/types/render/hooks/useFilteredFormData.d.ts +1 -0
  29. package/dist/types/render/hooks/useScrollIntoView.d.ts +18 -0
  30. package/dist/types/render/hooks/useTemplateEvaluation.d.ts +1 -1
  31. package/dist/types/util/constants/OptionsSourceConstants.d.ts +19 -0
  32. package/dist/types/util/constants/index.d.ts +1 -1
  33. package/dist/types/util/getSchemaVariables.d.ts +39 -0
  34. package/dist/types/util/index.d.ts +3 -52
  35. package/dist/types/util/simple.d.ts +20 -0
  36. package/dist/types/util/structure.d.ts +1 -0
  37. package/package.json +4 -4
  38. package/dist/types/render/components/form-fields/parts/Grid.d.ts +0 -1
  39. package/dist/types/util/constants/ValuesSourceConstants.d.ts +0 -19
  40. /package/dist/types/features/{expression-language → expressionLanguage}/FeelExpressionLanguage.d.ts +0 -0
  41. /package/dist/types/features/{expression-language → expressionLanguage}/FeelersTemplating.d.ts +0 -0
  42. /package/dist/types/features/{expression-language → expressionLanguage}/index.d.ts +0 -0
  43. /package/dist/types/features/{expression-language → expressionLanguage}/variableExtractionHelpers.d.ts +0 -0
package/dist/index.es.js CHANGED
@@ -1,17 +1,17 @@
1
1
  import Ids from 'ids';
2
- import { isString, get, isNumber, set, findIndex, isArray, isObject, isNil, values, uniqueBy, isFunction, bind, assign, groupBy, flatten, isUndefined } from 'min-dash';
2
+ import { isString, get, some, isNumber, set, findIndex, isArray, isObject, isNil, isDefined, values, uniqueBy, isFunction, bind, assign, groupBy, flatten, isUndefined } from 'min-dash';
3
3
  import Big from 'big.js';
4
- import { parseExpression, parseUnaryTests, evaluate, unaryTest } from 'feelin';
5
- import { evaluate as evaluate$1, parser, buildSimpleTree } from 'feelers';
6
4
  import classNames from 'classnames';
7
- import { jsx, jsxs, Fragment as Fragment$1 } from 'preact/jsx-runtime';
5
+ import { jsx, jsxs, Fragment } from 'preact/jsx-runtime';
8
6
  import { useContext, useMemo, useEffect, useRef, useState, useCallback, useLayoutEffect } from 'preact/hooks';
9
- import { createContext, createElement, Fragment, render } from 'preact';
7
+ import { createContext, createElement, Fragment as Fragment$1, render } from 'preact';
8
+ import flatpickr from 'flatpickr';
10
9
  import * as React from 'preact/compat';
11
10
  import { createPortal } from 'preact/compat';
12
- import flatpickr from 'flatpickr';
13
11
  import Markup from 'preact-markup';
14
12
  import { Injector } from 'didi';
13
+ import { parseExpression, parseUnaryTests, evaluate, unaryTest } from 'feelin';
14
+ import { evaluate as evaluate$1, parser, buildSimpleTree } from 'feelers';
15
15
  import showdown from 'showdown';
16
16
 
17
17
  const getFlavouredFeelVariableNames = (feelString, feelFlavour = 'expression', options = {}) => {
@@ -393,6 +393,92 @@ class FeelersTemplating {
393
393
  }
394
394
  FeelersTemplating.$inject = [];
395
395
 
396
+ // config ///////////////////
397
+
398
+ const MINUTES_IN_DAY = 60 * 24;
399
+ const DATETIME_SUBTYPES = {
400
+ DATE: 'date',
401
+ TIME: 'time',
402
+ DATETIME: 'datetime'
403
+ };
404
+ const TIME_SERIALISING_FORMATS = {
405
+ UTC_OFFSET: 'utc_offset',
406
+ UTC_NORMALIZED: 'utc_normalized',
407
+ NO_TIMEZONE: 'no_timezone'
408
+ };
409
+ const DATETIME_SUBTYPES_LABELS = {
410
+ [DATETIME_SUBTYPES.DATE]: 'Date',
411
+ [DATETIME_SUBTYPES.TIME]: 'Time',
412
+ [DATETIME_SUBTYPES.DATETIME]: 'Date & Time'
413
+ };
414
+ const TIME_SERIALISINGFORMAT_LABELS = {
415
+ [TIME_SERIALISING_FORMATS.UTC_OFFSET]: 'UTC offset',
416
+ [TIME_SERIALISING_FORMATS.UTC_NORMALIZED]: 'UTC normalized',
417
+ [TIME_SERIALISING_FORMATS.NO_TIMEZONE]: 'No timezone'
418
+ };
419
+ const DATETIME_SUBTYPE_PATH = ['subtype'];
420
+ const DATE_LABEL_PATH = ['dateLabel'];
421
+ const DATE_DISALLOW_PAST_PATH = ['disallowPassedDates'];
422
+ const TIME_LABEL_PATH = ['timeLabel'];
423
+ const TIME_USE24H_PATH = ['use24h'];
424
+ const TIME_INTERVAL_PATH = ['timeInterval'];
425
+ const TIME_SERIALISING_FORMAT_PATH = ['timeSerializingFormat'];
426
+
427
+ // config ///////////////////
428
+
429
+ const OPTIONS_SOURCES = {
430
+ STATIC: 'static',
431
+ INPUT: 'input',
432
+ EXPRESSION: 'expression'
433
+ };
434
+ const OPTIONS_SOURCE_DEFAULT = OPTIONS_SOURCES.STATIC;
435
+ const OPTIONS_SOURCES_LABELS = {
436
+ [OPTIONS_SOURCES.STATIC]: 'Static',
437
+ [OPTIONS_SOURCES.INPUT]: 'Input data',
438
+ [OPTIONS_SOURCES.EXPRESSION]: 'Expression'
439
+ };
440
+ const OPTIONS_SOURCES_PATHS = {
441
+ [OPTIONS_SOURCES.STATIC]: ['values'],
442
+ [OPTIONS_SOURCES.INPUT]: ['valuesKey'],
443
+ [OPTIONS_SOURCES.EXPRESSION]: ['valuesExpression']
444
+ };
445
+ const OPTIONS_SOURCES_DEFAULTS = {
446
+ [OPTIONS_SOURCES.STATIC]: [{
447
+ label: 'Value',
448
+ value: 'value'
449
+ }],
450
+ [OPTIONS_SOURCES.INPUT]: '',
451
+ [OPTIONS_SOURCES.EXPRESSION]: '='
452
+ };
453
+
454
+ // helpers ///////////////////
455
+
456
+ function getOptionsSource(field) {
457
+ for (const source of Object.values(OPTIONS_SOURCES)) {
458
+ if (get(field, OPTIONS_SOURCES_PATHS[source]) !== undefined) {
459
+ return source;
460
+ }
461
+ }
462
+ return OPTIONS_SOURCE_DEFAULT;
463
+ }
464
+
465
+ function createInjector(bootstrapModules) {
466
+ const injector = new Injector(bootstrapModules);
467
+ injector.init();
468
+ return injector;
469
+ }
470
+
471
+ /**
472
+ * @param {string?} prefix
473
+ *
474
+ * @returns Element
475
+ */
476
+ function createFormContainer(prefix = 'fjs') {
477
+ const container = document.createElement('div');
478
+ container.classList.add(`${prefix}-container`);
479
+ return container;
480
+ }
481
+
396
482
  function formFieldClasses(type, {
397
483
  errors = [],
398
484
  disabled = false,
@@ -418,14 +504,19 @@ function gridColumnClasses(formField) {
418
504
  // always fall back to top-down on smallest screens
419
505
  'cds--col-sm-16', 'cds--col-md-16');
420
506
  }
421
- function prefixId(id, formId) {
507
+ function prefixId(id, formId, indexes) {
508
+ let result = 'fjs-form';
422
509
  if (formId) {
423
- return `fjs-form-${formId}-${id}`;
510
+ result += `-${formId}`;
424
511
  }
425
- return `fjs-form-${id}`;
512
+ result += `-${id}`;
513
+ Object.values(indexes || {}).forEach(index => {
514
+ result += `_${index}`;
515
+ });
516
+ return result;
426
517
  }
427
518
 
428
- const type$e = 'button';
519
+ const type$f = 'button';
429
520
  function Button(props) {
430
521
  const {
431
522
  disabled,
@@ -437,7 +528,7 @@ function Button(props) {
437
528
  action = 'submit'
438
529
  } = field;
439
530
  return jsx("div", {
440
- class: formFieldClasses(type$e),
531
+ class: formFieldClasses(type$f),
441
532
  children: jsx("button", {
442
533
  class: "fjs-button",
443
534
  type: action,
@@ -449,7 +540,7 @@ function Button(props) {
449
540
  });
450
541
  }
451
542
  Button.config = {
452
- type: type$e,
543
+ type: type$f,
453
544
  keyed: false,
454
545
  label: 'Button',
455
546
  group: 'action',
@@ -460,27 +551,30 @@ Button.config = {
460
551
  };
461
552
 
462
553
  const FormRenderContext = createContext({
463
- EmptyRoot: props => {
554
+ Empty: props => {
464
555
  return null;
465
556
  },
466
- Empty: props => {
557
+ Hidden: props => {
467
558
  return null;
468
559
  },
469
560
  Children: props => {
470
561
  return jsx("div", {
471
562
  class: props.class,
563
+ style: props.style,
472
564
  children: props.children
473
565
  });
474
566
  },
475
567
  Element: props => {
476
568
  return jsx("div", {
477
569
  class: props.class,
570
+ style: props.style,
478
571
  children: props.children
479
572
  });
480
573
  },
481
574
  Row: props => {
482
575
  return jsx("div", {
483
576
  class: props.class,
577
+ style: props.style,
484
578
  children: props.children
485
579
  });
486
580
  },
@@ -490,16 +584,24 @@ const FormRenderContext = createContext({
490
584
  }
491
585
  return jsx("div", {
492
586
  class: props.class,
587
+ style: props.style,
493
588
  children: props.children
494
589
  });
495
590
  },
496
- hoveredId: [],
497
- setHoveredId: newValue => {
498
- console.log(`setHoveredId not defined, called with '${newValue}'`);
591
+ hoverInfo: {
592
+ cleanup: () => {}
499
593
  }
500
594
  });
501
595
  var FormRenderContext$1 = FormRenderContext;
502
596
 
597
+ const LocalExpressionContext = createContext({
598
+ data: null,
599
+ this: null,
600
+ parent: null,
601
+ i: null
602
+ });
603
+ var LocalExpressionContext$1 = LocalExpressionContext;
604
+
503
605
  /**
504
606
  * @param {string} type
505
607
  * @param {boolean} [strict]
@@ -520,24 +622,77 @@ function useService(type, strict) {
520
622
  return getService(type, strict);
521
623
  }
522
624
 
625
+ function isRequired(field) {
626
+ return field.required;
627
+ }
628
+ function pathParse(path) {
629
+ if (!path) {
630
+ return [];
631
+ }
632
+ return path.split('.').map(key => {
633
+ return isNaN(parseInt(key)) ? key : parseInt(key);
634
+ });
635
+ }
636
+ function pathsEqual(a, b) {
637
+ return a && b && a.length === b.length && a.every((value, index) => value === b[index]);
638
+ }
639
+ const indices = {};
640
+ function generateIndexForType(type) {
641
+ if (type in indices) {
642
+ indices[type]++;
643
+ } else {
644
+ indices[type] = 1;
645
+ }
646
+ return indices[type];
647
+ }
648
+ function generateIdForType(type) {
649
+ return `${type}${generateIndexForType(type)}`;
650
+ }
651
+
523
652
  /**
524
- * Returns the conditionally filtered data of a form reactively.
525
- * Memoised to minimize re-renders
653
+ * @template T
654
+ * @param {T} data
655
+ * @param {(this: any, key: string, value: any) => any} [replacer]
656
+ * @return {T}
657
+ */
658
+ function clone(data, replacer) {
659
+ return JSON.parse(JSON.stringify(data, replacer));
660
+ }
661
+
662
+ /**
663
+ * Transform a LocalExpressionContext object into a usable FEEL context.
526
664
  *
665
+ * @param {Object} context - The LocalExpressionContext object.
666
+ * @returns {Object} The usable FEEL context.
527
667
  */
528
- function useFilteredFormData() {
668
+
669
+ function buildExpressionContext(context) {
529
670
  const {
530
- initialData,
531
- data
532
- } = useService('form')._getState();
533
- const conditionChecker = useService('conditionChecker', false);
534
- return useMemo(() => {
535
- const newData = conditionChecker ? conditionChecker.applyConditions(data, data) : data;
536
- return {
537
- ...initialData,
538
- ...newData
539
- };
540
- }, [conditionChecker, data, initialData]);
671
+ data,
672
+ ...specialContextKeys
673
+ } = context;
674
+ return {
675
+ ...specialContextKeys,
676
+ ...data,
677
+ ..._wrapObjectKeysWithUnderscores(specialContextKeys)
678
+ };
679
+ }
680
+ function runRecursively(formField, fn) {
681
+ const components = formField.components || [];
682
+ components.forEach((component, index) => {
683
+ runRecursively(component, fn);
684
+ });
685
+ fn(formField);
686
+ }
687
+
688
+ // helpers //////////////////////
689
+
690
+ function _wrapObjectKeysWithUnderscores(obj) {
691
+ const newObj = {};
692
+ for (const [key, value] of Object.entries(obj)) {
693
+ newObj[`_${key}_`] = value;
694
+ }
695
+ return newObj;
541
696
  }
542
697
 
543
698
  /**
@@ -549,29 +704,125 @@ function useFilteredFormData() {
549
704
  */
550
705
  function useCondition(condition) {
551
706
  const conditionChecker = useService('conditionChecker', false);
552
- const filteredData = useFilteredFormData();
707
+ const expressionContextInfo = useContext(LocalExpressionContext$1);
553
708
  return useMemo(() => {
554
- return conditionChecker ? conditionChecker.check(condition, filteredData) : null;
555
- }, [conditionChecker, condition, filteredData]);
709
+ return conditionChecker ? conditionChecker.check(condition, buildExpressionContext(expressionContextInfo)) : null;
710
+ }, [conditionChecker, condition, expressionContextInfo]);
711
+ }
712
+
713
+ /**
714
+ * Custom hook to scroll an element into view only when it is not visible within the viewport.
715
+ *
716
+ * @param {Object} targetRef - A ref pointing to the DOM element to scroll into view.
717
+ * @param {Array} deps - An array of dependencies that trigger the effect.
718
+ * @param {Array} flagRefs - An array of refs that are used as flags to control when to scroll.
719
+ * @param {Object} [scrollOptions={}] - Options defining the behavior of the scrolling.
720
+ * @param {String} [scrollOptions.align='center'] - The alignment of the element within the viewport.
721
+ * @param {String} [scrollOptions.behavior='auto'] - The scrolling behavior.
722
+ * @param {Number} [scrollOptions.offset=0] - An offset that is added to the scroll position.
723
+ * @param {Boolean} [scrollOptions.scrollIfVisible=false] - Whether to scroll even if the element is visible.
724
+ */
725
+ function useScrollIntoView(targetRef, deps, scrollOptions = null, flagRefs = []) {
726
+ useEffect(() => {
727
+ // return early if flags are not raised, or component is not mounted
728
+ if (some(flagRefs, ref => !ref.current) || !targetRef.current) {
729
+ return;
730
+ }
731
+ for (let i = 0; i < flagRefs.length; i++) {
732
+ flagRefs[i].current = false;
733
+ }
734
+ const itemToBeScrolled = targetRef.current;
735
+ const scrollContainer = _getNearestScrollableAncestor(itemToBeScrolled);
736
+ if (!scrollContainer) {
737
+ return;
738
+ }
739
+ const itemRect = itemToBeScrolled.getBoundingClientRect();
740
+ const containerRect = scrollContainer.getBoundingClientRect();
741
+
742
+ // should scroll if visible or scrollIfVisible option is set
743
+ const shouldScroll = scrollOptions.scrollIfVisible || !(itemRect.top >= containerRect.top && itemRect.bottom <= containerRect.bottom);
744
+ if (!shouldScroll) {
745
+ return;
746
+ }
747
+ const {
748
+ align = 'center',
749
+ offset = 0,
750
+ behavior = 'auto'
751
+ } = scrollOptions;
752
+ const topOffset = _getTopOffset(itemToBeScrolled, scrollContainer, {
753
+ align,
754
+ offset
755
+ });
756
+ scrollContainer.scroll({
757
+ top: topOffset,
758
+ behavior
759
+ });
760
+
761
+ // eslint-disable-next-line react-hooks/exhaustive-deps
762
+ }, deps);
763
+ }
764
+
765
+ // helper //////////////////////
766
+
767
+ function _getNearestScrollableAncestor(el) {
768
+ while (el) {
769
+ if (el.scrollHeight > el.clientHeight) {
770
+ return el;
771
+ }
772
+ el = el.parentElement;
773
+ }
774
+ }
775
+ function _getTopOffset(item, scrollContainer, options) {
776
+ const itemRect = item.getBoundingClientRect();
777
+ const containerRect = scrollContainer.getBoundingClientRect();
778
+ if (options.align === 'top') {
779
+ return itemRect.top - containerRect.top + scrollContainer.scrollTop - options.offset;
780
+ } else if (options.align === 'bottom') {
781
+ return itemRect.bottom - containerRect.top - scrollContainer.clientHeight + scrollContainer.scrollTop + options.offset;
782
+ } else if (options.align === 'center') {
783
+ return itemRect.top - containerRect.top - scrollContainer.clientHeight / 2 + scrollContainer.scrollTop + itemRect.height / 2 + options.offset;
784
+ }
785
+ return 0;
556
786
  }
557
787
 
558
788
  /**
559
789
  * Evaluate a string reactively based on the expressionLanguage and form data.
560
790
  * If the string is not an expression, it is returned as is.
561
- * Memoised to minimize re-renders.
562
- *
563
- * @param {string} value
791
+ * The function is memoized to minimize re-renders.
564
792
  *
793
+ * @param {string} value - The string to evaluate.
794
+ * @returns {any} - Evaluated value or the original value if not an expression.
565
795
  */
566
796
  function useExpressionEvaluation(value) {
567
- const formData = useFilteredFormData();
568
797
  const expressionLanguage = useService('expressionLanguage');
798
+ const expressionContextInfo = useContext(LocalExpressionContext$1);
569
799
  return useMemo(() => {
570
800
  if (expressionLanguage && expressionLanguage.isExpression(value)) {
571
- return expressionLanguage.evaluate(value, formData);
801
+ return expressionLanguage.evaluate(value, buildExpressionContext(expressionContextInfo));
572
802
  }
573
803
  return value;
574
- }, [expressionLanguage, formData, value]);
804
+ }, [expressionLanguage, expressionContextInfo, value]);
805
+ }
806
+
807
+ /**
808
+ * Returns the conditionally filtered data of a form reactively.
809
+ * Memoised to minimize re-renders
810
+ *
811
+ * Warning: costly operation, use with care
812
+ */
813
+ function useFilteredFormData() {
814
+ const {
815
+ initialData,
816
+ data
817
+ } = useService('form')._getState();
818
+ const conditionChecker = useService('conditionChecker', false);
819
+ return useMemo(() => {
820
+ const newData = conditionChecker ? conditionChecker.applyConditions(data, data) : data;
821
+ return {
822
+ ...initialData,
823
+ ...newData
824
+ };
825
+ }, [conditionChecker, data, initialData]);
575
826
  }
576
827
 
577
828
  function useKeyDownAction(targetKey, action, listenerElement = window) {
@@ -604,7 +855,7 @@ function useKeyDownAction(targetKey, action, listenerElement = window) {
604
855
  function useReadonly(formField, properties = {}) {
605
856
  const expressionLanguage = useService('expressionLanguage');
606
857
  const conditionChecker = useService('conditionChecker', false);
607
- const filteredData = useFilteredFormData();
858
+ const expressionContextInfo = useContext(LocalExpressionContext$1);
608
859
  const {
609
860
  readonly
610
861
  } = formField;
@@ -612,7 +863,7 @@ function useReadonly(formField, properties = {}) {
612
863
  return true;
613
864
  }
614
865
  if (expressionLanguage && expressionLanguage.isExpression(readonly)) {
615
- return conditionChecker ? conditionChecker.check(readonly, filteredData) : false;
866
+ return conditionChecker ? conditionChecker.check(readonly, buildExpressionContext(expressionContextInfo)) : false;
616
867
  }
617
868
  return readonly || false;
618
869
  }
@@ -659,15 +910,15 @@ function compare(a, b) {
659
910
  * @param {Function} [options.buildDebugString]
660
911
  *
661
912
  */
662
- function useTemplateEvaluation(value, options) {
663
- const filteredData = useFilteredFormData();
913
+ function useTemplateEvaluation(value, options = {}) {
664
914
  const templating = useService('templating');
915
+ const expressionContextInfo = useContext(LocalExpressionContext$1);
665
916
  return useMemo(() => {
666
917
  if (templating && templating.isTemplate(value)) {
667
- return templating.evaluate(value, filteredData, options);
918
+ return templating.evaluate(value, buildExpressionContext(expressionContextInfo), options);
668
919
  }
669
920
  return value;
670
- }, [filteredData, templating, value, options]);
921
+ }, [templating, value, expressionContextInfo, options]);
671
922
  }
672
923
 
673
924
  /**
@@ -747,11 +998,13 @@ function Label(props) {
747
998
  });
748
999
  }
749
1000
 
750
- const type$d = 'checkbox';
1001
+ const type$e = 'checkbox';
751
1002
  function Checkbox(props) {
752
1003
  const {
753
1004
  disabled,
754
1005
  errors = [],
1006
+ errorMessageId,
1007
+ domId,
755
1008
  onBlur,
756
1009
  onFocus,
757
1010
  field,
@@ -760,7 +1013,6 @@ function Checkbox(props) {
760
1013
  } = props;
761
1014
  const {
762
1015
  description,
763
- id,
764
1016
  label,
765
1017
  validate = {}
766
1018
  } = field;
@@ -775,12 +1027,8 @@ function Checkbox(props) {
775
1027
  value: target.checked
776
1028
  });
777
1029
  };
778
- const {
779
- formId
780
- } = useContext(FormContext$1);
781
- const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
782
1030
  return jsxs("div", {
783
- class: classNames(formFieldClasses(type$d, {
1031
+ class: classNames(formFieldClasses(type$e, {
784
1032
  errors,
785
1033
  disabled,
786
1034
  readonly
@@ -788,7 +1036,7 @@ function Checkbox(props) {
788
1036
  'fjs-checked': value
789
1037
  }),
790
1038
  children: [jsx(Label, {
791
- id: prefixId(id, formId),
1039
+ id: domId,
792
1040
  label: label,
793
1041
  required: required,
794
1042
  children: jsx("input", {
@@ -796,7 +1044,7 @@ function Checkbox(props) {
796
1044
  class: "fjs-input",
797
1045
  disabled: disabled,
798
1046
  readOnly: readonly,
799
- id: prefixId(id, formId),
1047
+ id: domId,
800
1048
  type: "checkbox",
801
1049
  onChange: onChange,
802
1050
  onBlur: () => onBlur && onBlur(),
@@ -812,7 +1060,7 @@ function Checkbox(props) {
812
1060
  });
813
1061
  }
814
1062
  Checkbox.config = {
815
- type: type$d,
1063
+ type: type$e,
816
1064
  keyed: true,
817
1065
  label: 'Checkbox',
818
1066
  group: 'selection',
@@ -986,37 +1234,6 @@ function useCleanupMultiSelectValues (props) {
986
1234
  }, [field, options, onChange, JSON.stringify(values), loadState]);
987
1235
  }
988
1236
 
989
- // config ///////////////////
990
-
991
- const MINUTES_IN_DAY = 60 * 24;
992
- const DATETIME_SUBTYPES = {
993
- DATE: 'date',
994
- TIME: 'time',
995
- DATETIME: 'datetime'
996
- };
997
- const TIME_SERIALISING_FORMATS = {
998
- UTC_OFFSET: 'utc_offset',
999
- UTC_NORMALIZED: 'utc_normalized',
1000
- NO_TIMEZONE: 'no_timezone'
1001
- };
1002
- const DATETIME_SUBTYPES_LABELS = {
1003
- [DATETIME_SUBTYPES.DATE]: 'Date',
1004
- [DATETIME_SUBTYPES.TIME]: 'Time',
1005
- [DATETIME_SUBTYPES.DATETIME]: 'Date & Time'
1006
- };
1007
- const TIME_SERIALISINGFORMAT_LABELS = {
1008
- [TIME_SERIALISING_FORMATS.UTC_OFFSET]: 'UTC offset',
1009
- [TIME_SERIALISING_FORMATS.UTC_NORMALIZED]: 'UTC normalized',
1010
- [TIME_SERIALISING_FORMATS.NO_TIMEZONE]: 'No timezone'
1011
- };
1012
- const DATETIME_SUBTYPE_PATH = ['subtype'];
1013
- const DATE_LABEL_PATH = ['dateLabel'];
1014
- const DATE_DISALLOW_PAST_PATH = ['disallowPassedDates'];
1015
- const TIME_LABEL_PATH = ['timeLabel'];
1016
- const TIME_USE24H_PATH = ['use24h'];
1017
- const TIME_INTERVAL_PATH = ['timeInterval'];
1018
- const TIME_SERIALISING_FORMAT_PATH = ['timeSerializingFormat'];
1019
-
1020
1237
  const ENTER_KEYDOWN_EVENT = new KeyboardEvent('keydown', {
1021
1238
  code: 'Enter',
1022
1239
  key: 'Enter',
@@ -1223,11 +1440,13 @@ function sanitizeMultiSelectValue(options) {
1223
1440
  }
1224
1441
  }
1225
1442
 
1226
- const type$c = 'checklist';
1443
+ const type$d = 'checklist';
1227
1444
  function Checklist(props) {
1228
1445
  const {
1229
1446
  disabled,
1230
1447
  errors = [],
1448
+ errorMessageId,
1449
+ domId,
1231
1450
  onBlur,
1232
1451
  onFocus,
1233
1452
  field,
@@ -1236,7 +1455,6 @@ function Checklist(props) {
1236
1455
  } = props;
1237
1456
  const {
1238
1457
  description,
1239
- id,
1240
1458
  label,
1241
1459
  validate = {}
1242
1460
  } = field;
@@ -1279,12 +1497,8 @@ function Checklist(props) {
1279
1497
  values,
1280
1498
  onChange: props.onChange
1281
1499
  });
1282
- const {
1283
- formId
1284
- } = useContext(FormContext$1);
1285
- const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
1286
1500
  return jsxs("div", {
1287
- class: classNames(formFieldClasses(type$c, {
1501
+ class: classNames(formFieldClasses(type$d, {
1288
1502
  errors,
1289
1503
  disabled,
1290
1504
  readonly
@@ -1293,27 +1507,28 @@ function Checklist(props) {
1293
1507
  children: [jsx(Label, {
1294
1508
  label: label,
1295
1509
  required: required
1296
- }), loadState == LOAD_STATES.LOADED && options.map((v, index) => {
1510
+ }), loadState == LOAD_STATES.LOADED && options.map((o, index) => {
1511
+ const itemDomId = `${domId}-${index}`;
1297
1512
  return jsx(Label, {
1298
- id: prefixId(`${id}-${index}`, formId),
1299
- label: v.label,
1513
+ id: itemDomId,
1514
+ label: o.label,
1300
1515
  class: classNames({
1301
- 'fjs-checked': values.includes(v.value)
1516
+ 'fjs-checked': values.includes(o.value)
1302
1517
  }),
1303
1518
  required: false,
1304
1519
  children: jsx("input", {
1305
- checked: values.includes(v.value),
1520
+ checked: values.includes(o.value),
1306
1521
  class: "fjs-input",
1307
1522
  disabled: disabled,
1308
1523
  readOnly: readonly,
1309
- id: prefixId(`${id}-${index}`, formId),
1524
+ id: itemDomId,
1310
1525
  type: "checkbox",
1311
- onClick: () => toggleCheckbox(v.value),
1526
+ onClick: () => toggleCheckbox(o.value),
1312
1527
  onBlur: onCheckboxBlur,
1313
1528
  onFocus: onCheckboxFocus,
1314
1529
  "aria-describedby": errorMessageId
1315
1530
  })
1316
- }, `${id}-${index}`);
1531
+ });
1317
1532
  }), jsx(Description, {
1318
1533
  description: description
1319
1534
  }), jsx(Errors, {
@@ -1323,7 +1538,7 @@ function Checklist(props) {
1323
1538
  });
1324
1539
  }
1325
1540
  Checklist.config = {
1326
- type: type$c,
1541
+ type: type$d,
1327
1542
  keyed: true,
1328
1543
  label: 'Checkbox group',
1329
1544
  group: 'selection',
@@ -1336,6 +1551,7 @@ const noop$1 = () => false;
1336
1551
  function FormField(props) {
1337
1552
  const {
1338
1553
  field,
1554
+ indexes,
1339
1555
  onChange
1340
1556
  } = props;
1341
1557
  const formFields = useService('formFields'),
@@ -1351,14 +1567,19 @@ function FormField(props) {
1351
1567
  } = form._getState();
1352
1568
  const {
1353
1569
  Element,
1354
- Empty,
1570
+ Hidden,
1355
1571
  Column
1356
1572
  } = useContext(FormRenderContext$1);
1573
+ const {
1574
+ formId
1575
+ } = useContext(FormContext$1);
1357
1576
  const FormFieldComponent = formFields.get(field.type);
1358
1577
  if (!FormFieldComponent) {
1359
1578
  throw new Error(`cannot render field <${field.type}>`);
1360
1579
  }
1361
- const valuePath = useMemo(() => pathRegistry.getValuePath(field), [field, pathRegistry]);
1580
+ const valuePath = useMemo(() => pathRegistry.getValuePath(field, {
1581
+ indexes
1582
+ }), [field, indexes, pathRegistry]);
1362
1583
  const initialValue = useMemo(() => get(initialData, valuePath), [initialData, valuePath]);
1363
1584
  const readonly = useReadonly(field, properties);
1364
1585
  const value = get(data, valuePath);
@@ -1367,12 +1588,12 @@ function FormField(props) {
1367
1588
  const disabled = !properties.readOnly && (properties.disabled || field.disabled || false);
1368
1589
  const onBlur = useCallback(() => {
1369
1590
  if (viewerCommands) {
1370
- viewerCommands.updateFieldValidation(field, value);
1591
+ viewerCommands.updateFieldValidation(field, value, indexes);
1371
1592
  }
1372
1593
  eventBus.fire('formField.blur', {
1373
1594
  formField: field
1374
1595
  });
1375
- }, [eventBus, viewerCommands, field, value]);
1596
+ }, [eventBus, viewerCommands, field, value, indexes]);
1376
1597
  const onFocus = useCallback(() => {
1377
1598
  eventBus.fire('formField.focus', {
1378
1599
  formField: field
@@ -1380,13 +1601,25 @@ function FormField(props) {
1380
1601
  }, [eventBus, field]);
1381
1602
  useEffect(() => {
1382
1603
  if (viewerCommands && initialValue) {
1383
- viewerCommands.updateFieldValidation(field, initialValue);
1604
+ viewerCommands.updateFieldValidation(field, initialValue, indexes);
1384
1605
  }
1385
- }, [viewerCommands, field, initialValue]);
1606
+ }, [viewerCommands, field, initialValue, JSON.stringify(indexes)]);
1386
1607
  const hidden = useCondition(field.conditional && field.conditional.hide || null);
1608
+ const onChangeIndexed = useCallback(update => {
1609
+ // add indexes of the keyed field to the update, if any
1610
+ onChange(FormFieldComponent.config.keyed ? {
1611
+ ...update,
1612
+ indexes
1613
+ } : update);
1614
+ }, [onChange, FormFieldComponent.config.keyed, indexes]);
1387
1615
  if (hidden) {
1388
- return jsx(Empty, {});
1616
+ return jsx(Hidden, {
1617
+ field: field
1618
+ });
1389
1619
  }
1620
+ const domId = `${prefixId(field.id, formId, indexes)}`;
1621
+ const fieldErrors = get(errors, [field.id, ...Object.values(indexes || {})]) || [];
1622
+ const errorMessageId = errors.length === 0 ? undefined : `${domId}-error-message`;
1390
1623
  return jsx(Column, {
1391
1624
  field: field,
1392
1625
  class: gridColumnClasses(field),
@@ -1396,8 +1629,10 @@ function FormField(props) {
1396
1629
  children: jsx(FormFieldComponent, {
1397
1630
  ...props,
1398
1631
  disabled: disabled,
1399
- errors: errors[field.id],
1400
- onChange: disabled || readonly ? noop$1 : onChange,
1632
+ errors: fieldErrors,
1633
+ errorMessageId: errorMessageId,
1634
+ domId: domId,
1635
+ onChange: disabled || readonly ? noop$1 : onChangeIndexed,
1401
1636
  onBlur: disabled || readonly ? noop$1 : onBlur,
1402
1637
  onFocus: disabled || readonly ? noop$1 : onFocus,
1403
1638
  readonly: readonly,
@@ -1407,60 +1642,147 @@ function FormField(props) {
1407
1642
  });
1408
1643
  }
1409
1644
 
1410
- function Grid(props) {
1645
+ function ChildrenRenderer(props) {
1411
1646
  const {
1412
- Children,
1413
- Row
1647
+ Children
1414
1648
  } = useContext(FormRenderContext$1);
1415
1649
  const {
1416
1650
  field,
1417
1651
  Empty
1418
1652
  } = props;
1419
1653
  const {
1420
- id,
1421
- components = []
1654
+ id
1422
1655
  } = field;
1423
- const formLayouter = useService('formLayouter');
1424
- const formFieldRegistry = useService('formFieldRegistry');
1425
- const rows = formLayouter.getRows(id);
1426
- return jsxs(Children, {
1427
- class: "fjs-vertical-layout fjs-children cds--grid cds--grid--condensed",
1428
- field: field,
1429
- children: [rows.map(row => {
1430
- const {
1431
- components = []
1432
- } = row;
1433
- if (!components.length) {
1656
+ const repeatRenderManager = useService('repeatRenderManager', false);
1657
+ const isRepeating = repeatRenderManager && repeatRenderManager.isFieldRepeating(id);
1658
+ const Repeater = repeatRenderManager.Repeater;
1659
+ const RepeatFooter = repeatRenderManager.RepeatFooter;
1660
+ return isRepeating ? jsx(RepeatChildrenRenderer, {
1661
+ ...props,
1662
+ ChildrenRoot: Children,
1663
+ Empty,
1664
+ Repeater,
1665
+ RepeatFooter,
1666
+ repeatRenderManager
1667
+ }) : jsx(SimpleChildrenRenderer, {
1668
+ ...props,
1669
+ ChildrenRoot: Children,
1670
+ Empty
1671
+ });
1672
+ }
1673
+ function SimpleChildrenRenderer(props) {
1674
+ const {
1675
+ ChildrenRoot,
1676
+ Empty,
1677
+ field
1678
+ } = props;
1679
+ const {
1680
+ components = []
1681
+ } = field;
1682
+ const isEmpty = !components.length;
1683
+ return jsxs(ChildrenRoot, {
1684
+ class: "fjs-vertical-layout fjs-children cds--grid cds--grid--condensed",
1685
+ field: field,
1686
+ children: [jsx(RowsRenderer, {
1687
+ ...props
1688
+ }), isEmpty ? jsx(Empty, {
1689
+ field: field
1690
+ }) : null]
1691
+ });
1692
+ }
1693
+ function RepeatChildrenRenderer(props) {
1694
+ const {
1695
+ ChildrenRoot,
1696
+ repeatRenderManager,
1697
+ Empty,
1698
+ field,
1699
+ ...restProps
1700
+ } = props;
1701
+ const {
1702
+ components = []
1703
+ } = field;
1704
+ const useSharedState = useState({
1705
+ isCollapsed: true
1706
+ });
1707
+ const Repeater = repeatRenderManager.Repeater;
1708
+ const RepeatFooter = repeatRenderManager.RepeatFooter;
1709
+ return jsxs(Fragment, {
1710
+ children: [jsxs(ChildrenRoot, {
1711
+ class: "fjs-vertical-layout fjs-children cds--grid cds--grid--condensed",
1712
+ field: field,
1713
+ children: [Repeater ? jsx(Repeater, {
1714
+ ...restProps,
1715
+ useSharedState,
1716
+ field,
1717
+ RowsRenderer
1718
+ }) : jsx(RowsRenderer, {
1719
+ ...restProps,
1720
+ field
1721
+ }), !components.length ? jsx(Empty, {
1722
+ field: field
1723
+ }) : null]
1724
+ }), RepeatFooter ? jsx(RepeatFooter, {
1725
+ ...restProps,
1726
+ useSharedState,
1727
+ field
1728
+ }) : null]
1729
+ });
1730
+ }
1731
+ function RowsRenderer(props) {
1732
+ const {
1733
+ field,
1734
+ indexes
1735
+ } = props;
1736
+ const {
1737
+ id: parentId,
1738
+ verticalAlignment = 'start'
1739
+ } = field;
1740
+ const formLayouter = useService('formLayouter');
1741
+ const formFieldRegistry = useService('formFieldRegistry');
1742
+ const rows = formLayouter.getRows(parentId);
1743
+ const {
1744
+ Row
1745
+ } = useContext(FormRenderContext$1);
1746
+ return jsxs(Fragment, {
1747
+ children: [" ", rows.map(row => {
1748
+ const {
1749
+ components = []
1750
+ } = row;
1751
+ if (!components.length) {
1434
1752
  return null;
1435
1753
  }
1436
1754
  return jsx(Row, {
1437
1755
  row: row,
1438
1756
  class: "fjs-layout-row cds--row",
1439
- children: components.map(id => {
1440
- const childField = formFieldRegistry.get(id);
1757
+ style: {
1758
+ alignItems: verticalAlignment
1759
+ },
1760
+ children: components.map(childId => {
1761
+ const childField = formFieldRegistry.get(childId);
1441
1762
  if (!childField) {
1442
1763
  return null;
1443
1764
  }
1444
1765
  return createElement(FormField, {
1445
1766
  ...props,
1446
- key: childField.id,
1447
- field: childField
1767
+ key: childId,
1768
+ field: childField,
1769
+ indexes: indexes
1448
1770
  });
1449
1771
  })
1450
1772
  });
1451
- }), components.length ? null : jsx(Empty, {})]
1773
+ }), " "]
1452
1774
  });
1453
1775
  }
1454
1776
 
1455
1777
  function FormComponent$1(props) {
1456
1778
  const {
1457
- EmptyRoot
1779
+ Empty
1458
1780
  } = useContext(FormRenderContext$1);
1459
1781
  const fullProps = {
1460
1782
  ...props,
1461
- Empty: EmptyRoot
1783
+ Empty
1462
1784
  };
1463
- return jsx(Grid, {
1785
+ return jsx(ChildrenRenderer, {
1464
1786
  ...fullProps
1465
1787
  });
1466
1788
  }
@@ -1475,24 +1797,6 @@ FormComponent$1.config = {
1475
1797
  })
1476
1798
  };
1477
1799
 
1478
- var _path$k;
1479
- function _extends$m() { _extends$m = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$m.apply(this, arguments); }
1480
- var SvgCalendar = function SvgCalendar(props) {
1481
- return /*#__PURE__*/React.createElement("svg", _extends$m({
1482
- xmlns: "http://www.w3.org/2000/svg",
1483
- width: 14,
1484
- height: 15,
1485
- fill: "none",
1486
- viewBox: "0 0 28 30"
1487
- }, props), _path$k || (_path$k = /*#__PURE__*/React.createElement("path", {
1488
- fill: "currentColor",
1489
- fillRule: "evenodd",
1490
- d: "M19 2H9V0H7v2H2a2 2 0 0 0-2 2v24a2 2 0 0 0 2 2h24a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-5V0h-2v2ZM7 7V4H2v5h24V4h-5v3h-2V4H9v3H7Zm-5 4v17h24V11H2Z",
1491
- clipRule: "evenodd"
1492
- })));
1493
- };
1494
- var CalendarIcon = SvgCalendar;
1495
-
1496
1800
  /**
1497
1801
  * Returns date format for the provided locale.
1498
1802
  * If the locale is not provided, uses the browser's locale.
@@ -1561,6 +1865,24 @@ function flatpickerizeDateFormat(dateFormat) {
1561
1865
  return dateFormat;
1562
1866
  }
1563
1867
 
1868
+ var _path$u;
1869
+ function _extends$w() { _extends$w = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$w.apply(this, arguments); }
1870
+ var SvgCalendar = function SvgCalendar(props) {
1871
+ return /*#__PURE__*/React.createElement("svg", _extends$w({
1872
+ xmlns: "http://www.w3.org/2000/svg",
1873
+ width: 14,
1874
+ height: 15,
1875
+ fill: "none",
1876
+ viewBox: "0 0 28 30"
1877
+ }, props), _path$u || (_path$u = /*#__PURE__*/React.createElement("path", {
1878
+ fill: "currentColor",
1879
+ fillRule: "evenodd",
1880
+ d: "M19 2H9V0H7v2H2a2 2 0 0 0-2 2v24a2 2 0 0 0 2 2h24a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2h-5V0h-2v2ZM7 7V4H2v5h24V4h-5v3h-2V4H9v3H7Zm-5 4v17h24V11H2Z",
1881
+ clipRule: "evenodd"
1882
+ })));
1883
+ };
1884
+ var CalendarIcon = SvgCalendar;
1885
+
1564
1886
  function InputAdorner(props) {
1565
1887
  const {
1566
1888
  pre,
@@ -1601,12 +1923,11 @@ function InputAdorner(props) {
1601
1923
 
1602
1924
  function Datepicker(props) {
1603
1925
  const {
1604
- id,
1605
1926
  label,
1927
+ domId,
1606
1928
  collapseLabelOnEmpty,
1607
1929
  onDateTimeBlur,
1608
1930
  onDateTimeFocus,
1609
- formId,
1610
1931
  required,
1611
1932
  disabled,
1612
1933
  disallowPassedDates,
@@ -1706,11 +2027,10 @@ function Datepicker(props) {
1706
2027
  }
1707
2028
  onDateTimeBlur(e);
1708
2029
  }, [isInputDirty, onDateTimeBlur]);
1709
- const fullId = `${prefixId(id, formId)}--date`;
1710
2030
  return jsxs("div", {
1711
2031
  class: "fjs-datetime-subsection",
1712
2032
  children: [jsx(Label, {
1713
- id: fullId,
2033
+ id: domId,
1714
2034
  label: label,
1715
2035
  collapseOnEmpty: collapseLabelOnEmpty,
1716
2036
  required: required
@@ -1728,7 +2048,7 @@ function Datepicker(props) {
1728
2048
  children: jsx("input", {
1729
2049
  ref: dateInputRef,
1730
2050
  type: "text",
1731
- id: fullId,
2051
+ id: domId,
1732
2052
  class: "fjs-input",
1733
2053
  disabled: disabled,
1734
2054
  readOnly: readonly,
@@ -1747,19 +2067,19 @@ function Datepicker(props) {
1747
2067
  });
1748
2068
  }
1749
2069
 
1750
- var _path$j, _path2$4;
1751
- function _extends$l() { _extends$l = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$l.apply(this, arguments); }
2070
+ var _path$t, _path2$5;
2071
+ function _extends$v() { _extends$v = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$v.apply(this, arguments); }
1752
2072
  var SvgClock = function SvgClock(props) {
1753
- return /*#__PURE__*/React.createElement("svg", _extends$l({
2073
+ return /*#__PURE__*/React.createElement("svg", _extends$v({
1754
2074
  xmlns: "http://www.w3.org/2000/svg",
1755
2075
  width: 16,
1756
2076
  height: 16,
1757
2077
  fill: "none",
1758
2078
  viewBox: "0 0 28 29"
1759
- }, props), _path$j || (_path$j = /*#__PURE__*/React.createElement("path", {
2079
+ }, props), _path$t || (_path$t = /*#__PURE__*/React.createElement("path", {
1760
2080
  fill: "currentColor",
1761
2081
  d: "M13 14.41 18.59 20 20 18.59l-5-5.01V5h-2v9.41Z"
1762
- })), _path2$4 || (_path2$4 = /*#__PURE__*/React.createElement("path", {
2082
+ })), _path2$5 || (_path2$5 = /*#__PURE__*/React.createElement("path", {
1763
2083
  fill: "currentColor",
1764
2084
  fillRule: "evenodd",
1765
2085
  d: "M6.222 25.64A14 14 0 1 0 21.778 2.36 14 14 0 0 0 6.222 25.64ZM7.333 4.023a12 12 0 1 1 13.334 19.955A12 12 0 0 1 7.333 4.022Z",
@@ -1866,12 +2186,11 @@ function DropdownList(props) {
1866
2186
 
1867
2187
  function Timepicker(props) {
1868
2188
  const {
1869
- id,
1870
2189
  label,
1871
2190
  collapseLabelOnEmpty,
1872
2191
  onDateTimeBlur,
1873
2192
  onDateTimeFocus,
1874
- formId,
2193
+ domId,
1875
2194
  required,
1876
2195
  disabled,
1877
2196
  readonly,
@@ -1980,11 +2299,10 @@ function Timepicker(props) {
1980
2299
  setDropdownIsOpen(false);
1981
2300
  propagateRawToMinute(value);
1982
2301
  };
1983
- const fullId = `${prefixId(id, formId)}--time`;
1984
2302
  return jsxs("div", {
1985
2303
  class: "fjs-datetime-subsection",
1986
2304
  children: [jsx(Label, {
1987
- id: fullId,
2305
+ id: domId,
1988
2306
  label: label,
1989
2307
  collapseOnEmpty: collapseLabelOnEmpty,
1990
2308
  required: required
@@ -1998,7 +2316,7 @@ function Timepicker(props) {
1998
2316
  children: [jsx("input", {
1999
2317
  ref: timeInputRef,
2000
2318
  type: "text",
2001
- id: fullId,
2319
+ id: domId,
2002
2320
  class: "fjs-input",
2003
2321
  value: rawValue,
2004
2322
  disabled: disabled,
@@ -2030,11 +2348,12 @@ function Timepicker(props) {
2030
2348
  });
2031
2349
  }
2032
2350
 
2033
- const type$b = 'datetime';
2351
+ const type$c = 'datetime';
2034
2352
  function Datetime(props) {
2035
2353
  const {
2036
2354
  disabled,
2037
2355
  errors = [],
2356
+ domId,
2038
2357
  onBlur,
2039
2358
  onFocus,
2040
2359
  field,
@@ -2171,12 +2490,11 @@ function Datetime(props) {
2171
2490
  }, []);
2172
2491
  const errorMessageId = allErrors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
2173
2492
  const datePickerProps = {
2174
- id,
2175
2493
  label: dateLabel,
2176
2494
  collapseLabelOnEmpty: !timeLabel,
2177
2495
  onDateTimeBlur,
2178
2496
  onDateTimeFocus,
2179
- formId,
2497
+ domId: `${domId}-date`,
2180
2498
  required,
2181
2499
  disabled,
2182
2500
  disallowPassedDates,
@@ -2186,12 +2504,11 @@ function Datetime(props) {
2186
2504
  'aria-describedby': errorMessageId
2187
2505
  };
2188
2506
  const timePickerProps = {
2189
- id,
2190
2507
  label: timeLabel,
2191
2508
  collapseLabelOnEmpty: !dateLabel,
2192
2509
  onDateTimeBlur,
2193
2510
  onDateTimeFocus,
2194
- formId,
2511
+ domId: `${domId}-time`,
2195
2512
  required,
2196
2513
  disabled,
2197
2514
  readonly,
@@ -2202,7 +2519,7 @@ function Datetime(props) {
2202
2519
  'aria-describedby': errorMessageId
2203
2520
  };
2204
2521
  return jsxs("div", {
2205
- class: formFieldClasses(type$b, {
2522
+ class: formFieldClasses(type$c, {
2206
2523
  errors: allErrors,
2207
2524
  disabled,
2208
2525
  readonly
@@ -2226,7 +2543,7 @@ function Datetime(props) {
2226
2543
  });
2227
2544
  }
2228
2545
  Datetime.config = {
2229
- type: type$b,
2546
+ type: type$c,
2230
2547
  keyed: true,
2231
2548
  label: 'Date time',
2232
2549
  group: 'basic-input',
@@ -2322,7 +2639,7 @@ function PoweredBy(props) {
2322
2639
  setOpen(open);
2323
2640
  };
2324
2641
  }
2325
- return jsxs(Fragment, {
2642
+ return jsxs(Fragment$1, {
2326
2643
  children: [createPortal(jsx(Lightbox, {
2327
2644
  open: open,
2328
2645
  onBackdropClick: toggleOpen(false)
@@ -2355,32 +2672,39 @@ function FormComponent(props) {
2355
2672
  event.preventDefault();
2356
2673
  onReset();
2357
2674
  };
2675
+ const filteredFormData = useFilteredFormData();
2676
+ const localExpressionContext = useMemo(() => ({
2677
+ data: filteredFormData,
2678
+ parent: null,
2679
+ this: filteredFormData,
2680
+ i: []
2681
+ }), [filteredFormData]);
2358
2682
  return jsxs("form", {
2359
2683
  class: "fjs-form",
2360
2684
  onSubmit: handleSubmit,
2361
2685
  onReset: handleReset,
2362
2686
  "aria-label": ariaLabel,
2363
2687
  noValidate: true,
2364
- children: [jsx(FormField, {
2365
- field: schema,
2366
- onChange: onChange
2688
+ children: [jsx(LocalExpressionContext$1.Provider, {
2689
+ value: localExpressionContext,
2690
+ children: jsx(FormField, {
2691
+ field: schema,
2692
+ onChange: onChange
2693
+ })
2367
2694
  }), jsx(PoweredBy, {})]
2368
2695
  });
2369
2696
  }
2370
2697
 
2371
2698
  function Group(props) {
2372
2699
  const {
2373
- field
2700
+ field,
2701
+ domId
2374
2702
  } = props;
2375
2703
  const {
2376
2704
  label,
2377
- id,
2378
2705
  type,
2379
2706
  showOutline
2380
2707
  } = field;
2381
- const {
2382
- formId
2383
- } = useContext(FormContext$1);
2384
2708
  const {
2385
2709
  Empty
2386
2710
  } = useContext(FormRenderContext$1);
@@ -2389,15 +2713,15 @@ function Group(props) {
2389
2713
  Empty
2390
2714
  };
2391
2715
  return jsxs("div", {
2392
- className: classNames(formFieldClasses(type), {
2716
+ className: classNames(formFieldClasses(type), 'fjs-form-field-grouplike', {
2393
2717
  'fjs-outlined': showOutline
2394
2718
  }),
2395
2719
  role: "group",
2396
- "aria-labelledby": prefixId(id, formId),
2720
+ "aria-labelledby": domId,
2397
2721
  children: [jsx(Label, {
2398
- id: prefixId(id, formId),
2722
+ id: domId,
2399
2723
  label: label
2400
- }), jsx(Grid, {
2724
+ }), jsx(ChildrenRenderer, {
2401
2725
  ...fullProps
2402
2726
  })]
2403
2727
  });
@@ -2554,7 +2878,7 @@ function isValidAttribute(lcTag, lcName, value) {
2554
2878
  return true;
2555
2879
  }
2556
2880
 
2557
- const type$a = 'iframe';
2881
+ const type$b = 'iframe';
2558
2882
  const DEFAULT_HEIGHT = 300;
2559
2883
  function IFrame(props) {
2560
2884
  const {
@@ -2579,7 +2903,7 @@ function IFrame(props) {
2579
2903
  formId
2580
2904
  } = useContext(FormContext$1);
2581
2905
  return jsxs("div", {
2582
- class: formFieldClasses(type$a, {
2906
+ class: formFieldClasses(type$b, {
2583
2907
  disabled,
2584
2908
  readonly
2585
2909
  }),
@@ -2613,7 +2937,7 @@ function IFramePlaceholder(props) {
2613
2937
  });
2614
2938
  }
2615
2939
  IFrame.config = {
2616
- type: type$a,
2940
+ type: type$b,
2617
2941
  keyed: false,
2618
2942
  label: 'iFrame',
2619
2943
  group: 'container',
@@ -2622,9 +2946,9 @@ IFrame.config = {
2622
2946
  })
2623
2947
  };
2624
2948
 
2625
- function _extends$k() { _extends$k = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$k.apply(this, arguments); }
2949
+ function _extends$u() { _extends$u = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$u.apply(this, arguments); }
2626
2950
  var SvgImagePlaceholder = function SvgImagePlaceholder(props) {
2627
- return /*#__PURE__*/React.createElement("svg", _extends$k({
2951
+ return /*#__PURE__*/React.createElement("svg", _extends$u({
2628
2952
  xmlns: "http://www.w3.org/2000/svg",
2629
2953
  xmlSpace: "preserve",
2630
2954
  width: 64,
@@ -2663,7 +2987,7 @@ var SvgImagePlaceholder = function SvgImagePlaceholder(props) {
2663
2987
  };
2664
2988
  var ImagePlaceholder = SvgImagePlaceholder;
2665
2989
 
2666
- const type$9 = 'image';
2990
+ const type$a = 'image';
2667
2991
  function Image(props) {
2668
2992
  const {
2669
2993
  field
@@ -2684,7 +3008,7 @@ function Image(props) {
2684
3008
  formId
2685
3009
  } = useContext(FormContext$1);
2686
3010
  return jsx("div", {
2687
- class: formFieldClasses(type$9),
3011
+ class: formFieldClasses(type$a),
2688
3012
  children: jsxs("div", {
2689
3013
  class: "fjs-image-container",
2690
3014
  children: [safeSource && jsx("img", {
@@ -2702,7 +3026,7 @@ function Image(props) {
2702
3026
  });
2703
3027
  }
2704
3028
  Image.config = {
2705
- type: type$9,
3029
+ type: type$a,
2706
3030
  keyed: false,
2707
3031
  label: 'Image view',
2708
3032
  group: 'presentation',
@@ -2729,14 +3053,14 @@ function TemplatedInputAdorner(props) {
2729
3053
  });
2730
3054
  }
2731
3055
 
2732
- var _path$i;
2733
- function _extends$j() { _extends$j = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$j.apply(this, arguments); }
3056
+ var _path$s;
3057
+ function _extends$t() { _extends$t = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$t.apply(this, arguments); }
2734
3058
  var SvgAngelDown = function SvgAngelDown(props) {
2735
- return /*#__PURE__*/React.createElement("svg", _extends$j({
3059
+ return /*#__PURE__*/React.createElement("svg", _extends$t({
2736
3060
  xmlns: "http://www.w3.org/2000/svg",
2737
3061
  width: 8,
2738
3062
  height: 8
2739
- }, props), _path$i || (_path$i = /*#__PURE__*/React.createElement("path", {
3063
+ }, props), _path$s || (_path$s = /*#__PURE__*/React.createElement("path", {
2740
3064
  fill: "currentColor",
2741
3065
  fillRule: "evenodd",
2742
3066
  stroke: "currentColor",
@@ -2747,14 +3071,14 @@ var SvgAngelDown = function SvgAngelDown(props) {
2747
3071
  };
2748
3072
  var AngelDownIcon = SvgAngelDown;
2749
3073
 
2750
- var _path$h;
2751
- function _extends$i() { _extends$i = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$i.apply(this, arguments); }
3074
+ var _path$r;
3075
+ function _extends$s() { _extends$s = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$s.apply(this, arguments); }
2752
3076
  var SvgAngelUp = function SvgAngelUp(props) {
2753
- return /*#__PURE__*/React.createElement("svg", _extends$i({
3077
+ return /*#__PURE__*/React.createElement("svg", _extends$s({
2754
3078
  xmlns: "http://www.w3.org/2000/svg",
2755
3079
  width: 8,
2756
3080
  height: 8
2757
- }, props), _path$h || (_path$h = /*#__PURE__*/React.createElement("path", {
3081
+ }, props), _path$r || (_path$r = /*#__PURE__*/React.createElement("path", {
2758
3082
  fill: "currentColor",
2759
3083
  fillRule: "evenodd",
2760
3084
  stroke: "currentColor",
@@ -2790,11 +3114,13 @@ function isNullEquivalentValue(value) {
2790
3114
  return value === undefined || value === null || value === '';
2791
3115
  }
2792
3116
 
2793
- const type$8 = 'number';
3117
+ const type$9 = 'number';
2794
3118
  function Numberfield(props) {
2795
3119
  const {
2796
3120
  disabled,
2797
3121
  errors = [],
3122
+ errorMessageId,
3123
+ domId,
2798
3124
  onBlur,
2799
3125
  onFocus,
2800
3126
  field,
@@ -2804,7 +3130,6 @@ function Numberfield(props) {
2804
3130
  } = props;
2805
3131
  const {
2806
3132
  description,
2807
- id,
2808
3133
  label,
2809
3134
  appearance = {},
2810
3135
  validate = {},
@@ -2924,18 +3249,14 @@ function Numberfield(props) {
2924
3249
  e.preventDefault();
2925
3250
  }
2926
3251
  };
2927
- const {
2928
- formId
2929
- } = useContext(FormContext$1);
2930
- const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
2931
3252
  return jsxs("div", {
2932
- class: formFieldClasses(type$8, {
3253
+ class: formFieldClasses(type$9, {
2933
3254
  errors,
2934
3255
  disabled,
2935
3256
  readonly
2936
3257
  }),
2937
3258
  children: [jsx(Label, {
2938
- id: prefixId(id, formId),
3259
+ id: domId,
2939
3260
  label: label,
2940
3261
  required: required
2941
3262
  }), jsx(TemplatedInputAdorner, {
@@ -2955,7 +3276,7 @@ function Numberfield(props) {
2955
3276
  class: "fjs-input",
2956
3277
  disabled: disabled,
2957
3278
  readOnly: readonly,
2958
- id: prefixId(id, formId),
3279
+ id: domId,
2959
3280
  onKeyDown: onKeyDown,
2960
3281
  onKeyPress: onKeyPress,
2961
3282
  onBlur: () => onBlur && onBlur(),
@@ -3002,7 +3323,7 @@ function Numberfield(props) {
3002
3323
  });
3003
3324
  }
3004
3325
  Numberfield.config = {
3005
- type: type$8,
3326
+ type: type$9,
3006
3327
  keyed: true,
3007
3328
  label: 'Number',
3008
3329
  group: 'basic-input',
@@ -3046,11 +3367,13 @@ function useCleanupSingleSelectValue (props) {
3046
3367
  }, [field, options, onChange, value, loadState]);
3047
3368
  }
3048
3369
 
3049
- const type$7 = 'radio';
3370
+ const type$8 = 'radio';
3050
3371
  function Radio(props) {
3051
3372
  const {
3052
3373
  disabled,
3053
3374
  errors = [],
3375
+ errorMessageId,
3376
+ domId,
3054
3377
  onBlur,
3055
3378
  onFocus,
3056
3379
  field,
@@ -3059,7 +3382,6 @@ function Radio(props) {
3059
3382
  } = props;
3060
3383
  const {
3061
3384
  description,
3062
- id,
3063
3385
  label,
3064
3386
  validate = {}
3065
3387
  } = field;
@@ -3096,12 +3418,8 @@ function Radio(props) {
3096
3418
  value,
3097
3419
  onChange: props.onChange
3098
3420
  });
3099
- const {
3100
- formId
3101
- } = useContext(FormContext$1);
3102
- const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3103
3421
  return jsxs("div", {
3104
- class: formFieldClasses(type$7, {
3422
+ class: formFieldClasses(type$8, {
3105
3423
  errors,
3106
3424
  disabled,
3107
3425
  readonly
@@ -3111,8 +3429,9 @@ function Radio(props) {
3111
3429
  label: label,
3112
3430
  required: required
3113
3431
  }), loadState == LOAD_STATES.LOADED && options.map((option, index) => {
3432
+ const itemDomId = `${domId}-${index}`;
3114
3433
  return jsx(Label, {
3115
- id: prefixId(`${id}-${index}`, formId),
3434
+ id: itemDomId,
3116
3435
  label: option.label,
3117
3436
  class: classNames({
3118
3437
  'fjs-checked': option.value === value
@@ -3123,14 +3442,14 @@ function Radio(props) {
3123
3442
  class: "fjs-input",
3124
3443
  disabled: disabled,
3125
3444
  readOnly: readonly,
3126
- id: prefixId(`${id}-${index}`, formId),
3445
+ id: itemDomId,
3127
3446
  type: "radio",
3128
3447
  onClick: () => onChange(option.value),
3129
3448
  onBlur: onRadioBlur,
3130
3449
  onFocus: onRadioFocus,
3131
3450
  "aria-describedby": errorMessageId
3132
3451
  })
3133
- }, `${id}-${index}`);
3452
+ }, index);
3134
3453
  }), jsx(Description, {
3135
3454
  description: description
3136
3455
  }), jsx(Errors, {
@@ -3140,7 +3459,7 @@ function Radio(props) {
3140
3459
  });
3141
3460
  }
3142
3461
  Radio.config = {
3143
- type: type$7,
3462
+ type: type$8,
3144
3463
  keyed: true,
3145
3464
  label: 'Radio group',
3146
3465
  group: 'selection',
@@ -3149,14 +3468,14 @@ Radio.config = {
3149
3468
  create: createEmptyOptions
3150
3469
  };
3151
3470
 
3152
- var _path$g;
3153
- function _extends$h() { _extends$h = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$h.apply(this, arguments); }
3471
+ var _path$q;
3472
+ function _extends$r() { _extends$r = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$r.apply(this, arguments); }
3154
3473
  var SvgXMark = function SvgXMark(props) {
3155
- return /*#__PURE__*/React.createElement("svg", _extends$h({
3474
+ return /*#__PURE__*/React.createElement("svg", _extends$r({
3156
3475
  xmlns: "http://www.w3.org/2000/svg",
3157
3476
  width: 8,
3158
3477
  height: 8
3159
- }, props), _path$g || (_path$g = /*#__PURE__*/React.createElement("path", {
3478
+ }, props), _path$q || (_path$q = /*#__PURE__*/React.createElement("path", {
3160
3479
  fill: "currentColor",
3161
3480
  fillRule: "evenodd",
3162
3481
  stroke: "currentColor",
@@ -3169,7 +3488,7 @@ var XMarkIcon = SvgXMark;
3169
3488
 
3170
3489
  function SearchableSelect(props) {
3171
3490
  const {
3172
- id,
3491
+ domId,
3173
3492
  disabled,
3174
3493
  errors,
3175
3494
  onBlur,
@@ -3178,9 +3497,6 @@ function SearchableSelect(props) {
3178
3497
  readonly,
3179
3498
  value
3180
3499
  } = props;
3181
- const {
3182
- formId
3183
- } = useContext(FormContext$1);
3184
3500
  const [filter, setFilter] = useState('');
3185
3501
  const [isDropdownExpanded, setIsDropdownExpanded] = useState(false);
3186
3502
  const [shouldApplyFilter, setShouldApplyFilter] = useState(true);
@@ -3287,9 +3603,8 @@ function SearchableSelect(props) {
3287
3603
  setFilter(valueLabel);
3288
3604
  onBlur && onBlur();
3289
3605
  }, [onBlur, valueLabel]);
3290
- return jsxs(Fragment$1, {
3606
+ return jsxs(Fragment, {
3291
3607
  children: [jsxs("div", {
3292
- id: prefixId(`${id}`, formId),
3293
3608
  class: classNames('fjs-input-group', {
3294
3609
  'disabled': disabled,
3295
3610
  'readonly': readonly
@@ -3301,7 +3616,7 @@ function SearchableSelect(props) {
3301
3616
  readOnly: readonly,
3302
3617
  class: "fjs-input",
3303
3618
  ref: searchbarRef,
3304
- id: prefixId(`${id}-search`, formId),
3619
+ id: domId,
3305
3620
  onChange: onInputChange,
3306
3621
  type: "text",
3307
3622
  value: filter,
@@ -3341,7 +3656,7 @@ function SearchableSelect(props) {
3341
3656
 
3342
3657
  function SimpleSelect(props) {
3343
3658
  const {
3344
- id,
3659
+ domId,
3345
3660
  disabled,
3346
3661
  errors,
3347
3662
  onBlur,
@@ -3350,9 +3665,6 @@ function SimpleSelect(props) {
3350
3665
  readonly,
3351
3666
  value
3352
3667
  } = props;
3353
- const {
3354
- formId
3355
- } = useContext(FormContext$1);
3356
3668
  const [isDropdownExpanded, setIsDropdownExpanded] = useState(false);
3357
3669
  const selectRef = useRef();
3358
3670
  const inputRef = useRef();
@@ -3409,10 +3721,9 @@ function SimpleSelect(props) {
3409
3721
  onBlur && onBlur();
3410
3722
  }
3411
3723
  }, [onBlur, readonly]);
3412
- return jsxs(Fragment$1, {
3724
+ return jsxs(Fragment, {
3413
3725
  children: [jsxs("div", {
3414
3726
  ref: selectRef,
3415
- id: prefixId(`${id}`, formId),
3416
3727
  class: classNames('fjs-input-group', {
3417
3728
  disabled,
3418
3729
  readonly
@@ -3426,11 +3737,11 @@ function SimpleSelect(props) {
3426
3737
  class: classNames('fjs-select-display', {
3427
3738
  'fjs-select-placeholder': !value
3428
3739
  }),
3429
- id: prefixId(`${id}-display`, formId),
3740
+ id: `${domId}-display`,
3430
3741
  children: valueLabel || 'Select'
3431
3742
  }), !disabled && jsx("input", {
3432
3743
  ref: inputRef,
3433
- id: prefixId(`${id}-search`, formId),
3744
+ id: domId,
3434
3745
  class: "fjs-select-hidden-input",
3435
3746
  value: valueLabel,
3436
3747
  onFocus: onInputFocus,
@@ -3463,11 +3774,13 @@ function SimpleSelect(props) {
3463
3774
  });
3464
3775
  }
3465
3776
 
3466
- const type$6 = 'select';
3777
+ const type$7 = 'select';
3467
3778
  function Select(props) {
3468
3779
  const {
3469
3780
  disabled,
3470
3781
  errors = [],
3782
+ errorMessageId,
3783
+ domId,
3471
3784
  onBlur,
3472
3785
  onFocus,
3473
3786
  field,
@@ -3477,7 +3790,6 @@ function Select(props) {
3477
3790
  } = props;
3478
3791
  const {
3479
3792
  description,
3480
- id,
3481
3793
  label,
3482
3794
  searchable = false,
3483
3795
  validate = {}
@@ -3485,12 +3797,8 @@ function Select(props) {
3485
3797
  const {
3486
3798
  required
3487
3799
  } = validate;
3488
- const {
3489
- formId
3490
- } = useContext(FormContext$1);
3491
- const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3492
- const selectProps = useMemo(() => ({
3493
- id,
3800
+ const selectProps = {
3801
+ domId,
3494
3802
  disabled,
3495
3803
  errors,
3496
3804
  onBlur,
@@ -3500,9 +3808,9 @@ function Select(props) {
3500
3808
  onChange,
3501
3809
  readonly,
3502
3810
  'aria-describedby': errorMessageId
3503
- }), [disabled, errors, field, id, value, onChange, onBlur, onFocus, readonly, errorMessageId]);
3811
+ };
3504
3812
  return jsxs("div", {
3505
- class: formFieldClasses(type$6, {
3813
+ class: formFieldClasses(type$7, {
3506
3814
  errors,
3507
3815
  disabled,
3508
3816
  readonly
@@ -3514,7 +3822,7 @@ function Select(props) {
3514
3822
  }
3515
3823
  },
3516
3824
  children: [jsx(Label, {
3517
- id: prefixId(`${id}-search`, formId),
3825
+ id: domId,
3518
3826
  label: label,
3519
3827
  required: required
3520
3828
  }), searchable ? jsx(SearchableSelect, {
@@ -3530,7 +3838,7 @@ function Select(props) {
3530
3838
  });
3531
3839
  }
3532
3840
  Select.config = {
3533
- type: type$6,
3841
+ type: type$7,
3534
3842
  keyed: true,
3535
3843
  label: 'Select',
3536
3844
  group: 'selection',
@@ -3539,15 +3847,15 @@ Select.config = {
3539
3847
  create: createEmptyOptions
3540
3848
  };
3541
3849
 
3542
- const type$5 = 'separator';
3850
+ const type$6 = 'separator';
3543
3851
  function Separator() {
3544
3852
  return jsx("div", {
3545
- class: formFieldClasses(type$5),
3853
+ class: formFieldClasses(type$6),
3546
3854
  children: jsx("hr", {})
3547
3855
  });
3548
3856
  }
3549
3857
  Separator.config = {
3550
- type: type$5,
3858
+ type: type$6,
3551
3859
  keyed: false,
3552
3860
  label: 'Separator',
3553
3861
  group: 'presentation',
@@ -3556,7 +3864,7 @@ Separator.config = {
3556
3864
  })
3557
3865
  };
3558
3866
 
3559
- const type$4 = 'spacer';
3867
+ const type$5 = 'spacer';
3560
3868
  function Spacer(props) {
3561
3869
  const {
3562
3870
  field
@@ -3565,14 +3873,14 @@ function Spacer(props) {
3565
3873
  height = 60
3566
3874
  } = field;
3567
3875
  return jsx("div", {
3568
- class: formFieldClasses(type$4),
3876
+ class: formFieldClasses(type$5),
3569
3877
  style: {
3570
3878
  height: height
3571
3879
  }
3572
3880
  });
3573
3881
  }
3574
3882
  Spacer.config = {
3575
- type: type$4,
3883
+ type: type$5,
3576
3884
  keyed: false,
3577
3885
  label: 'Spacer',
3578
3886
  group: 'presentation',
@@ -3582,6 +3890,56 @@ Spacer.config = {
3582
3890
  })
3583
3891
  };
3584
3892
 
3893
+ function DynamicList(props) {
3894
+ const {
3895
+ field,
3896
+ domId,
3897
+ readonly
3898
+ } = props;
3899
+ const {
3900
+ label,
3901
+ type,
3902
+ showOutline
3903
+ } = field;
3904
+ const {
3905
+ Empty
3906
+ } = useContext(FormRenderContext$1);
3907
+ const fullProps = {
3908
+ ...props,
3909
+ Empty
3910
+ };
3911
+ return jsxs("div", {
3912
+ className: classNames(formFieldClasses(type, {
3913
+ readonly
3914
+ }), 'fjs-form-field-grouplike', {
3915
+ 'fjs-outlined': showOutline
3916
+ }),
3917
+ role: "group",
3918
+ "aria-labelledby": domId,
3919
+ children: [jsx(Label, {
3920
+ id: domId,
3921
+ label: label
3922
+ }), jsx(ChildrenRenderer, {
3923
+ ...fullProps
3924
+ })]
3925
+ });
3926
+ }
3927
+ DynamicList.config = {
3928
+ type: 'dynamiclist',
3929
+ pathed: true,
3930
+ repeatable: true,
3931
+ label: 'Dynamic list',
3932
+ group: 'container',
3933
+ create: (options = {}) => ({
3934
+ components: [],
3935
+ showOutline: true,
3936
+ isRepeating: true,
3937
+ allowAddRemove: true,
3938
+ defaultRepetitions: 1,
3939
+ ...options
3940
+ })
3941
+ };
3942
+
3585
3943
  function SkipLink(props) {
3586
3944
  const {
3587
3945
  className,
@@ -3603,12 +3961,14 @@ function SkipLink(props) {
3603
3961
  });
3604
3962
  }
3605
3963
 
3606
- const type$3 = 'taglist';
3964
+ const type$4 = 'taglist';
3607
3965
  function Taglist(props) {
3608
3966
  const {
3609
3967
  disabled,
3610
3968
  errors = [],
3969
+ errorMessageId,
3611
3970
  onFocus,
3971
+ domId,
3612
3972
  onBlur,
3613
3973
  field,
3614
3974
  readonly,
@@ -3616,17 +3976,12 @@ function Taglist(props) {
3616
3976
  } = props;
3617
3977
  const {
3618
3978
  description,
3619
- id,
3620
3979
  label,
3621
3980
  validate = {}
3622
3981
  } = field;
3623
3982
  const {
3624
3983
  required
3625
3984
  } = validate;
3626
- const {
3627
- formId
3628
- } = useContext(FormContext$1);
3629
- const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3630
3985
  const [filter, setFilter] = useState('');
3631
3986
  const [isDropdownExpanded, setIsDropdownExpanded] = useState(false);
3632
3987
  const [isEscapeClosed, setIsEscapeClose] = useState(false);
@@ -3749,7 +4104,7 @@ function Taglist(props) {
3749
4104
  const shouldDisplayDropdown = useMemo(() => !disabled && loadState === LOAD_STATES.LOADED && isDropdownExpanded && !isEscapeClosed, [disabled, isDropdownExpanded, isEscapeClosed, loadState]);
3750
4105
  return jsxs("div", {
3751
4106
  ref: focusScopeRef,
3752
- class: formFieldClasses(type$3, {
4107
+ class: formFieldClasses(type$4, {
3753
4108
  errors,
3754
4109
  disabled,
3755
4110
  readonly
@@ -3763,7 +4118,7 @@ function Taglist(props) {
3763
4118
  children: [jsx(Label, {
3764
4119
  label: label,
3765
4120
  required: required,
3766
- id: prefixId(`${id}-search`, formId)
4121
+ id: domId
3767
4122
  }), !disabled && !readonly && !!values.length && jsx(SkipLink, {
3768
4123
  className: "fjs-taglist-skip-link",
3769
4124
  label: "Skip to search",
@@ -3801,7 +4156,7 @@ function Taglist(props) {
3801
4156
  readOnly: readonly,
3802
4157
  class: "fjs-taglist-input",
3803
4158
  ref: inputRef,
3804
- id: prefixId(`${id}-search`, formId),
4159
+ id: domId,
3805
4160
  onChange: onInputChange,
3806
4161
  type: "text",
3807
4162
  value: filter,
@@ -3831,7 +4186,7 @@ function Taglist(props) {
3831
4186
  });
3832
4187
  }
3833
4188
  Taglist.config = {
3834
- type: type$3,
4189
+ type: type$4,
3835
4190
  keyed: true,
3836
4191
  label: 'Tag list',
3837
4192
  group: 'selection',
@@ -3840,7 +4195,7 @@ Taglist.config = {
3840
4195
  create: createEmptyOptions
3841
4196
  };
3842
4197
 
3843
- const type$2 = 'text';
4198
+ const type$3 = 'text';
3844
4199
  function Text(props) {
3845
4200
  const form = useService('form');
3846
4201
  const {
@@ -3867,7 +4222,7 @@ function Text(props) {
3867
4222
  const html = markdownRenderer.render(markdown);
3868
4223
  return sanitizeHTML(html);
3869
4224
  }, [markdownRenderer, markdown]);
3870
- const OverridenTargetLink = useMemo(() => BuildOverridenTargetLink(textLinkTarget), [textLinkTarget]);
4225
+ const OverriddenTargetLink = useMemo(() => BuildOverriddenTargetLink(textLinkTarget), [textLinkTarget]);
3871
4226
  const componentOverrides = useMemo(() => {
3872
4227
  if (disableLinks) {
3873
4228
  return {
@@ -3876,13 +4231,13 @@ function Text(props) {
3876
4231
  }
3877
4232
  if (textLinkTarget) {
3878
4233
  return {
3879
- 'a': OverridenTargetLink
4234
+ 'a': OverriddenTargetLink
3880
4235
  };
3881
4236
  }
3882
4237
  return {};
3883
- }, [disableLinks, OverridenTargetLink, textLinkTarget]);
4238
+ }, [disableLinks, OverriddenTargetLink, textLinkTarget]);
3884
4239
  return jsx("div", {
3885
- class: formFieldClasses(type$2),
4240
+ class: formFieldClasses(type$3),
3886
4241
  children: jsx(Markup, {
3887
4242
  markup: safeHtml,
3888
4243
  components: componentOverrides,
@@ -3891,7 +4246,7 @@ function Text(props) {
3891
4246
  });
3892
4247
  }
3893
4248
  Text.config = {
3894
- type: type$2,
4249
+ type: type$3,
3895
4250
  keyed: false,
3896
4251
  label: 'Text view',
3897
4252
  group: 'presentation',
@@ -3900,7 +4255,7 @@ Text.config = {
3900
4255
  ...options
3901
4256
  })
3902
4257
  };
3903
- function BuildOverridenTargetLink(target) {
4258
+ function BuildOverriddenTargetLink(target) {
3904
4259
  return function ({
3905
4260
  children,
3906
4261
  ...rest
@@ -3924,11 +4279,13 @@ function DisabledLink({
3924
4279
  });
3925
4280
  }
3926
4281
 
3927
- const type$1 = 'textfield';
4282
+ const type$2 = 'textfield';
3928
4283
  function Textfield(props) {
3929
4284
  const {
3930
4285
  disabled,
3931
4286
  errors = [],
4287
+ errorMessageId,
4288
+ domId,
3932
4289
  onBlur,
3933
4290
  onFocus,
3934
4291
  field,
@@ -3937,7 +4294,6 @@ function Textfield(props) {
3937
4294
  } = props;
3938
4295
  const {
3939
4296
  description,
3940
- id,
3941
4297
  label,
3942
4298
  appearance = {},
3943
4299
  validate = {}
@@ -3957,18 +4313,14 @@ function Textfield(props) {
3957
4313
  value: target.value
3958
4314
  });
3959
4315
  };
3960
- const {
3961
- formId
3962
- } = useContext(FormContext$1);
3963
- const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
3964
4316
  return jsxs("div", {
3965
- class: formFieldClasses(type$1, {
4317
+ class: formFieldClasses(type$2, {
3966
4318
  errors,
3967
4319
  disabled,
3968
4320
  readonly
3969
4321
  }),
3970
4322
  children: [jsx(Label, {
3971
- id: prefixId(id, formId),
4323
+ id: domId,
3972
4324
  label: label,
3973
4325
  required: required
3974
4326
  }), jsx(TemplatedInputAdorner, {
@@ -3980,7 +4332,7 @@ function Textfield(props) {
3980
4332
  class: "fjs-input",
3981
4333
  disabled: disabled,
3982
4334
  readOnly: readonly,
3983
- id: prefixId(id, formId),
4335
+ id: domId,
3984
4336
  onInput: onChange,
3985
4337
  onBlur: () => onBlur && onBlur(),
3986
4338
  onFocus: () => onFocus && onFocus(),
@@ -3997,7 +4349,7 @@ function Textfield(props) {
3997
4349
  });
3998
4350
  }
3999
4351
  Textfield.config = {
4000
- type: type$1,
4352
+ type: type$2,
4001
4353
  keyed: true,
4002
4354
  label: 'Text field',
4003
4355
  group: 'basic-input',
@@ -4020,11 +4372,13 @@ Textfield.config = {
4020
4372
  })
4021
4373
  };
4022
4374
 
4023
- const type = 'textarea';
4375
+ const type$1 = 'textarea';
4024
4376
  function Textarea(props) {
4025
4377
  const {
4026
4378
  disabled,
4027
4379
  errors = [],
4380
+ errorMessageId,
4381
+ domId,
4028
4382
  onBlur,
4029
4383
  onFocus,
4030
4384
  field,
@@ -4033,7 +4387,6 @@ function Textarea(props) {
4033
4387
  } = props;
4034
4388
  const {
4035
4389
  description,
4036
- id,
4037
4390
  label,
4038
4391
  validate = {}
4039
4392
  } = field;
@@ -4055,25 +4408,21 @@ function Textarea(props) {
4055
4408
  useEffect(() => {
4056
4409
  autoSizeTextarea(textareaRef.current);
4057
4410
  }, []);
4058
- const {
4059
- formId
4060
- } = useContext(FormContext$1);
4061
- const errorMessageId = errors.length === 0 ? undefined : `${prefixId(id, formId)}-error-message`;
4062
4411
  return jsxs("div", {
4063
- class: formFieldClasses(type, {
4412
+ class: formFieldClasses(type$1, {
4064
4413
  errors,
4065
4414
  disabled,
4066
4415
  readonly
4067
4416
  }),
4068
4417
  children: [jsx(Label, {
4069
- id: prefixId(id, formId),
4418
+ id: domId,
4070
4419
  label: label,
4071
4420
  required: required
4072
4421
  }), jsx("textarea", {
4073
4422
  class: "fjs-textarea",
4074
4423
  disabled: disabled,
4075
4424
  readonly: readonly,
4076
- id: prefixId(id, formId),
4425
+ id: domId,
4077
4426
  onInput: onInput,
4078
4427
  onBlur: () => onBlur && onBlur(),
4079
4428
  onFocus: () => onFocus && onFocus(),
@@ -4089,7 +4438,7 @@ function Textarea(props) {
4089
4438
  });
4090
4439
  }
4091
4440
  Textarea.config = {
4092
- type,
4441
+ type: type$1,
4093
4442
  keyed: true,
4094
4443
  label: 'Text area',
4095
4444
  group: 'basic-input',
@@ -4120,45 +4469,400 @@ const autoSizeTextarea = textarea => {
4120
4469
  textarea.style.overflow = calculatedHeight > maxHeight ? 'visible' : 'hidden';
4121
4470
  };
4122
4471
 
4123
- var _path$f;
4124
- function _extends$g() { _extends$g = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$g.apply(this, arguments); }
4125
- var SvgButton = function SvgButton(props) {
4126
- return /*#__PURE__*/React.createElement("svg", _extends$g({
4472
+ var _path$p;
4473
+ function _extends$q() { _extends$q = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$q.apply(this, arguments); }
4474
+ var SvgArrowDown = function SvgArrowDown(props) {
4475
+ return /*#__PURE__*/React.createElement("svg", _extends$q({
4127
4476
  xmlns: "http://www.w3.org/2000/svg",
4128
- width: 54,
4129
- height: 54,
4130
- fill: "currentcolor"
4131
- }, props), _path$f || (_path$f = /*#__PURE__*/React.createElement("path", {
4132
- fillRule: "evenodd",
4133
- d: "M45 17a3 3 0 0 1 3 3v14a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V20a3 3 0 0 1 3-3h36zm-9 8.889H18v2.222h18v-2.222z"
4477
+ viewBox: "0 0 32 32"
4478
+ }, props), _path$p || (_path$p = /*#__PURE__*/React.createElement("path", {
4479
+ fill: "currentcolor",
4480
+ d: "M24.59 16.59 17 24.17V4h-2v20.17l-7.59-7.58L6 18l10 10 10-10-1.41-1.41z"
4134
4481
  })));
4135
4482
  };
4136
- var ButtonIcon = SvgButton;
4483
+ var ArrowDownIcon = SvgArrowDown;
4137
4484
 
4138
- var _path$e;
4139
- function _extends$f() { _extends$f = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$f.apply(this, arguments); }
4140
- var SvgCheckbox = function SvgCheckbox(props) {
4141
- return /*#__PURE__*/React.createElement("svg", _extends$f({
4485
+ var _path$o;
4486
+ function _extends$p() { _extends$p = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$p.apply(this, arguments); }
4487
+ var SvgArrowUp = function SvgArrowUp(props) {
4488
+ return /*#__PURE__*/React.createElement("svg", _extends$p({
4142
4489
  xmlns: "http://www.w3.org/2000/svg",
4143
- width: 54,
4144
- height: 54,
4145
- fill: "currentcolor"
4146
- }, props), _path$e || (_path$e = /*#__PURE__*/React.createElement("path", {
4147
- d: "M34 18H20a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V20a2 2 0 0 0-2-2zm-9 14-5-5 1.41-1.41L25 29.17l7.59-7.59L34 23l-9 9z"
4490
+ viewBox: "0 0 32 32"
4491
+ }, props), _path$o || (_path$o = /*#__PURE__*/React.createElement("path", {
4492
+ fill: "currentcolor",
4493
+ d: "M16 4 6 14l1.41 1.41L15 7.83V28h2V7.83l7.59 7.58L26 14 16 4z"
4148
4494
  })));
4149
4495
  };
4150
- var CheckboxIcon = SvgCheckbox;
4496
+ var ArrowUpIcon = SvgArrowUp;
4151
4497
 
4152
- var _path$d;
4153
- function _extends$e() { _extends$e = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$e.apply(this, arguments); }
4154
- var SvgChecklist = function SvgChecklist(props) {
4155
- return /*#__PURE__*/React.createElement("svg", _extends$e({
4498
+ var _path$n;
4499
+ function _extends$o() { _extends$o = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$o.apply(this, arguments); }
4500
+ var SvgCaretLeft = function SvgCaretLeft(props) {
4501
+ return /*#__PURE__*/React.createElement("svg", _extends$o({
4156
4502
  xmlns: "http://www.w3.org/2000/svg",
4157
- width: 54,
4158
- height: 54,
4159
- fill: "none"
4160
- }, props), _path$d || (_path$d = /*#__PURE__*/React.createElement("path", {
4161
- fill: "currentColor",
4503
+ xmlSpace: "preserve",
4504
+ viewBox: "0 0 32 32"
4505
+ }, props), _path$n || (_path$n = /*#__PURE__*/React.createElement("path", {
4506
+ fill: "currentcolor",
4507
+ d: "m20 24-10-8 10-8z"
4508
+ })));
4509
+ };
4510
+ var CaretLeftIcon = SvgCaretLeft;
4511
+
4512
+ var _path$m;
4513
+ function _extends$n() { _extends$n = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$n.apply(this, arguments); }
4514
+ var SvgCaretRight = function SvgCaretRight(props) {
4515
+ return /*#__PURE__*/React.createElement("svg", _extends$n({
4516
+ xmlns: "http://www.w3.org/2000/svg",
4517
+ xmlSpace: "preserve",
4518
+ viewBox: "0 0 32 32"
4519
+ }, props), _path$m || (_path$m = /*#__PURE__*/React.createElement("path", {
4520
+ fill: "currentcolor",
4521
+ d: "m12 8 10 8-10 8z"
4522
+ })));
4523
+ };
4524
+ var CaretRightIcon = SvgCaretRight;
4525
+
4526
+ const type = 'table';
4527
+
4528
+ /**
4529
+ * @typedef {('asc'|'desc')} Direction
4530
+ *
4531
+ * @typedef Sorting
4532
+ * @property {string} key
4533
+ * @property {Direction} direction
4534
+ *
4535
+ * @typedef Column
4536
+ * @property {string} label
4537
+ * @property {string} key
4538
+ *
4539
+ * @typedef Props
4540
+ * @property {Object} field
4541
+ * @property {string} field.id
4542
+ * @property {Array<Column>} [field.columns]
4543
+ * @property {string} [field.columnsExpression]
4544
+ * @property {string} [field.label]
4545
+ * @property {number} [field.rowCount]
4546
+ * @property {string} [field.dataSource]
4547
+ *
4548
+ * @param {Props} props
4549
+ * @returns {import("preact").JSX.Element}
4550
+ */
4551
+ function Table(props) {
4552
+ const {
4553
+ field
4554
+ } = props;
4555
+ const {
4556
+ columns = [],
4557
+ columnsExpression,
4558
+ dataSource = '',
4559
+ rowCount,
4560
+ id,
4561
+ label
4562
+ } = field;
4563
+
4564
+ /** @type {[(null|Sorting), import("preact/hooks").StateUpdater<null|Sorting>]} */
4565
+ const [sortBy, setSortBy] = useState(null);
4566
+ const evaluatedColumns = useEvaluatedColumns(columnsExpression || '', columns);
4567
+ const columnKeys = evaluatedColumns.map(({
4568
+ key
4569
+ }) => key);
4570
+ const evaluatedDataSource = useExpressionEvaluation(dataSource);
4571
+ const data = Array.isArray(evaluatedDataSource) ? evaluatedDataSource : [];
4572
+ const sortedData = sortBy === null ? data : sortByColumn(data, sortBy.key, sortBy.direction);
4573
+
4574
+ /** @type {unknown[][]} */
4575
+ const chunkedData = isNumber(rowCount) ? chunk(sortedData, rowCount) : [sortedData];
4576
+ const [currentPage, setCurrentPage] = useState(0);
4577
+ const currentChunk = chunkedData[currentPage] || [];
4578
+ useEffect(() => {
4579
+ setCurrentPage(0);
4580
+ }, [rowCount, sortBy]);
4581
+
4582
+ /** @param {string} key */
4583
+ function toggleSortBy(key) {
4584
+ setSortBy(current => {
4585
+ if (current === null || current.key !== key) {
4586
+ return {
4587
+ key,
4588
+ direction: 'asc'
4589
+ };
4590
+ }
4591
+ if (current.direction === 'desc') {
4592
+ return null;
4593
+ }
4594
+ return {
4595
+ key,
4596
+ direction: 'desc'
4597
+ };
4598
+ });
4599
+ }
4600
+ return jsxs("div", {
4601
+ class: formFieldClasses(type),
4602
+ children: [jsx(Label, {
4603
+ id: prefixId(id),
4604
+ label: label
4605
+ }), jsxs("div", {
4606
+ class: classNames('fjs-table-middle-container', {
4607
+ 'fjs-table-empty': evaluatedColumns.length === 0
4608
+ }),
4609
+ children: [evaluatedColumns.length === 0 ? 'Nothing to show.' : jsx("div", {
4610
+ class: "fjs-table-inner-container",
4611
+ children: jsxs("table", {
4612
+ class: "fjs-table",
4613
+ id: prefixId(id),
4614
+ children: [jsx("thead", {
4615
+ class: "fjs-table-head",
4616
+ children: jsx("tr", {
4617
+ class: "fjs-table-tr",
4618
+ children: evaluatedColumns.map(({
4619
+ key,
4620
+ label
4621
+ }) => {
4622
+ const displayLabel = label || key;
4623
+ return jsx("th", {
4624
+ tabIndex: 0,
4625
+ class: "fjs-table-th",
4626
+ onClick: () => {
4627
+ toggleSortBy(key);
4628
+ },
4629
+ onKeyDown: event => {
4630
+ if (['Enter', 'Space'].includes(event.code)) {
4631
+ toggleSortBy(key);
4632
+ }
4633
+ },
4634
+ "aria-label": getHeaderAriaLabel(sortBy, key, displayLabel),
4635
+ children: jsxs("span", {
4636
+ class: "fjs-table-th-label",
4637
+ children: [displayLabel, sortBy !== null && sortBy.key === key ? jsx(Fragment, {
4638
+ children: sortBy.direction === 'asc' ? jsx(ArrowUpIcon, {
4639
+ class: "fjs-table-sort-icon-asc"
4640
+ }) : jsx(ArrowDownIcon, {
4641
+ class: "fjs-table-sort-icon-desc"
4642
+ })
4643
+ }) : null]
4644
+ })
4645
+ }, key);
4646
+ })
4647
+ })
4648
+ }), currentChunk.length === 0 ? jsx("tbody", {
4649
+ class: "fjs-table-body",
4650
+ children: jsx("tr", {
4651
+ class: "fjs-table-tr",
4652
+ children: jsx("td", {
4653
+ class: "fjs-table-td",
4654
+ colSpan: evaluatedColumns.length,
4655
+ children: "Nothing to show."
4656
+ })
4657
+ })
4658
+ }) : jsx("tbody", {
4659
+ class: "fjs-table-body",
4660
+ children: currentChunk.map((row, index) => jsx("tr", {
4661
+ class: "fjs-table-tr",
4662
+ children: columnKeys.map(key => jsx("td", {
4663
+ class: "fjs-table-td",
4664
+ children: row[key]
4665
+ }, key))
4666
+ }, index))
4667
+ })]
4668
+ })
4669
+ }), isNumber(rowCount) && chunkedData.length > 1 && evaluatedColumns.length > 0 ? jsxs("nav", {
4670
+ class: "fjs-table-nav",
4671
+ children: [jsxs("span", {
4672
+ class: "fjs-table-nav-label",
4673
+ children: [currentPage + 1, " of ", chunkedData.length]
4674
+ }), jsx("button", {
4675
+ type: "button",
4676
+ class: "fjs-table-nav-button",
4677
+ onClick: () => {
4678
+ setCurrentPage(page => Math.max(page - 1, 0));
4679
+ },
4680
+ disabled: currentPage === 0,
4681
+ "aria-label": "Previous page",
4682
+ children: jsx(CaretLeftIcon, {})
4683
+ }), jsx("button", {
4684
+ type: "button",
4685
+ class: "fjs-table-nav-button",
4686
+ onClick: () => {
4687
+ setCurrentPage(page => Math.min(page + 1, chunkedData.length - 1));
4688
+ },
4689
+ disabled: currentPage >= chunkedData.length - 1,
4690
+ "aria-label": "Next page",
4691
+ children: jsx(CaretRightIcon, {})
4692
+ })]
4693
+ }) : null]
4694
+ })]
4695
+ });
4696
+ }
4697
+ Table.config = {
4698
+ type,
4699
+ keyed: false,
4700
+ label: 'Table',
4701
+ group: 'presentation',
4702
+ create: (options = {}) => {
4703
+ const {
4704
+ id,
4705
+ columnsExpression,
4706
+ columns,
4707
+ rowCount,
4708
+ ...remainingOptions
4709
+ } = options;
4710
+ if (isDefined(id) && isNumber(rowCount)) {
4711
+ remainingOptions['rowCount'] = rowCount;
4712
+ }
4713
+ if (isString(columnsExpression)) {
4714
+ return {
4715
+ ...remainingOptions,
4716
+ id,
4717
+ columnsExpression
4718
+ };
4719
+ }
4720
+ if (Array.isArray(columns) && columns.every(isColumn)) {
4721
+ return {
4722
+ ...remainingOptions,
4723
+ id,
4724
+ columns
4725
+ };
4726
+ }
4727
+ return {
4728
+ ...remainingOptions,
4729
+ rowCount: 10,
4730
+ columns: [{
4731
+ label: 'ID',
4732
+ key: 'id'
4733
+ }, {
4734
+ label: 'Name',
4735
+ key: 'name'
4736
+ }, {
4737
+ label: 'Date',
4738
+ key: 'date'
4739
+ }]
4740
+ };
4741
+ },
4742
+ initialDemoData: [{
4743
+ id: 1,
4744
+ name: 'John Doe',
4745
+ date: '31.01.2023'
4746
+ }, {
4747
+ id: 2,
4748
+ name: 'Erika Muller',
4749
+ date: '20.02.2023'
4750
+ }, {
4751
+ id: 3,
4752
+ name: 'Dominic Leaf',
4753
+ date: '11.03.2023'
4754
+ }]
4755
+ };
4756
+
4757
+ // helpers /////////////////////////////
4758
+
4759
+ /**
4760
+ * @param {string|void} columnsExpression
4761
+ * @param {Column[]} fallbackColumns
4762
+ * @returns {Column[]}
4763
+ */
4764
+ function useEvaluatedColumns(columnsExpression, fallbackColumns) {
4765
+ /** @type {Column[]|null} */
4766
+ const evaluation = useExpressionEvaluation(columnsExpression || '');
4767
+ return Array.isArray(evaluation) && evaluation.every(isColumn) ? evaluation : fallbackColumns;
4768
+ }
4769
+
4770
+ /**
4771
+ * @param {any} column
4772
+ * @returns {column is Column}
4773
+ */
4774
+ function isColumn(column) {
4775
+ return isObject(column) && isString(column['label']) && isString(column['key']);
4776
+ }
4777
+
4778
+ /**
4779
+ * @param {Array} array
4780
+ * @param {number} size
4781
+ * @returns {Array}
4782
+ */
4783
+ function chunk(array, size) {
4784
+ return array.reduce((chunks, item, index) => {
4785
+ if (index % size === 0) {
4786
+ chunks.push([item]);
4787
+ } else {
4788
+ chunks[chunks.length - 1].push(item);
4789
+ }
4790
+ return chunks;
4791
+ }, []);
4792
+ }
4793
+
4794
+ /**
4795
+ * @param {unknown[]} array
4796
+ * @param {string} key
4797
+ * @param {Direction} direction
4798
+ * @returns {unknown[]}
4799
+ */
4800
+ function sortByColumn(array, key, direction) {
4801
+ return [...array].sort((a, b) => {
4802
+ if (!isObject(a) || !isObject(b)) {
4803
+ return 0;
4804
+ }
4805
+ if (direction === 'asc') {
4806
+ return a[key] > b[key] ? 1 : -1;
4807
+ }
4808
+ return a[key] < b[key] ? 1 : -1;
4809
+ });
4810
+ }
4811
+
4812
+ /**
4813
+ * @param {null|Sorting} sortBy
4814
+ * @param {string} key
4815
+ * @param {string} label
4816
+ */
4817
+ function getHeaderAriaLabel(sortBy, key, label) {
4818
+ if (sortBy === null || sortBy.key !== key) {
4819
+ return `Click to sort by ${label} descending`;
4820
+ }
4821
+ if (sortBy.direction === 'asc') {
4822
+ return 'Click to remove sorting';
4823
+ }
4824
+ return `Click to sort by ${label} ascending`;
4825
+ }
4826
+
4827
+ var _path$l;
4828
+ function _extends$m() { _extends$m = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$m.apply(this, arguments); }
4829
+ var SvgButton = function SvgButton(props) {
4830
+ return /*#__PURE__*/React.createElement("svg", _extends$m({
4831
+ xmlns: "http://www.w3.org/2000/svg",
4832
+ width: 54,
4833
+ height: 54,
4834
+ fill: "currentcolor"
4835
+ }, props), _path$l || (_path$l = /*#__PURE__*/React.createElement("path", {
4836
+ fillRule: "evenodd",
4837
+ d: "M45 17a3 3 0 0 1 3 3v14a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V20a3 3 0 0 1 3-3h36zm-9 8.889H18v2.222h18v-2.222z"
4838
+ })));
4839
+ };
4840
+ var ButtonIcon = SvgButton;
4841
+
4842
+ var _path$k;
4843
+ function _extends$l() { _extends$l = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$l.apply(this, arguments); }
4844
+ var SvgCheckbox = function SvgCheckbox(props) {
4845
+ return /*#__PURE__*/React.createElement("svg", _extends$l({
4846
+ xmlns: "http://www.w3.org/2000/svg",
4847
+ width: 54,
4848
+ height: 54,
4849
+ fill: "currentcolor"
4850
+ }, props), _path$k || (_path$k = /*#__PURE__*/React.createElement("path", {
4851
+ d: "M34 18H20a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V20a2 2 0 0 0-2-2zm-9 14-5-5 1.41-1.41L25 29.17l7.59-7.59L34 23l-9 9z"
4852
+ })));
4853
+ };
4854
+ var CheckboxIcon = SvgCheckbox;
4855
+
4856
+ var _path$j;
4857
+ function _extends$k() { _extends$k = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$k.apply(this, arguments); }
4858
+ var SvgChecklist = function SvgChecklist(props) {
4859
+ return /*#__PURE__*/React.createElement("svg", _extends$k({
4860
+ xmlns: "http://www.w3.org/2000/svg",
4861
+ width: 54,
4862
+ height: 54,
4863
+ fill: "none"
4864
+ }, props), _path$j || (_path$j = /*#__PURE__*/React.createElement("path", {
4865
+ fill: "currentColor",
4162
4866
  fillRule: "evenodd",
4163
4867
  d: "M14.35 24.75H19v4.65h-4.65v-4.65Zm-1.414-1.414a2 2 0 0 1 1.414-.586H19a2 2 0 0 1 2 2v4.65a2 2 0 0 1-2 2h-4.65a2 2 0 0 1-2-2v-4.65a2 2 0 0 1 .586-1.414ZM14.35 37.05H19v4.65h-4.65v-4.65Zm-1.414-1.414a2 2 0 0 1 1.414-.586H19a2 2 0 0 1 2 2v4.65a2 2 0 0 1-2 2h-4.65a2 2 0 0 1-2-2v-4.65a2 2 0 0 1 .586-1.414ZM14.35 12.45H19v4.65h-4.65v-4.65Zm-1.414-1.414a2 2 0 0 1 1.414-.586H19a2 2 0 0 1 2 2v4.65a2 2 0 0 1-2 2h-4.65a2 2 0 0 1-2-2v-4.65a2 2 0 0 1 .586-1.414Zm12.007 14.977a1 1 0 0 0-.293.707v.65a1 1 0 0 0 1 1h15a1 1 0 0 0 1-1v-.65a1 1 0 0 0-1-1h-15a1 1 0 0 0-.707.293Zm0 12.3a1 1 0 0 0-.293.707v.65a1 1 0 0 0 1 1h15a1 1 0 0 0 1-1v-.65a1 1 0 0 0-1-1h-15a1 1 0 0 0-.707.293Zm0-24.6a1 1 0 0 0-.293.707v.65a1 1 0 0 0 1 1h15a1 1 0 0 0 1-1v-.65a1 1 0 0 0-1-1h-15a1 1 0 0 0-.707.293Z",
4164
4868
  clipRule: "evenodd"
@@ -4166,18 +4870,18 @@ var SvgChecklist = function SvgChecklist(props) {
4166
4870
  };
4167
4871
  var ChecklistIcon = SvgChecklist;
4168
4872
 
4169
- var _path$c, _path2$3, _path3;
4170
- function _extends$d() { _extends$d = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$d.apply(this, arguments); }
4873
+ var _path$i, _path2$4, _path3;
4874
+ function _extends$j() { _extends$j = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$j.apply(this, arguments); }
4171
4875
  var SvgDatetime = function SvgDatetime(props) {
4172
- return /*#__PURE__*/React.createElement("svg", _extends$d({
4876
+ return /*#__PURE__*/React.createElement("svg", _extends$j({
4173
4877
  xmlns: "http://www.w3.org/2000/svg",
4174
4878
  width: 54,
4175
4879
  height: 54,
4176
4880
  fill: "currentcolor"
4177
- }, props), _path$c || (_path$c = /*#__PURE__*/React.createElement("path", {
4881
+ }, props), _path$i || (_path$i = /*#__PURE__*/React.createElement("path", {
4178
4882
  fillRule: "evenodd",
4179
4883
  d: "M37.908 13.418h-5.004v-2.354h-1.766v2.354H21.13v-2.354h-1.766v2.354H14.36a2.07 2.07 0 0 0-2.06 2.06v23.549a2.07 2.07 0 0 0 2.06 2.06h6.77v-1.766h-6.358a.707.707 0 0 1-.706-.706V15.89c0-.39.316-.707.706-.707h4.592v2.355h1.766v-2.355h10.008v2.355h1.766v-2.355h4.592a.71.71 0 0 1 .707.707v6.358h1.765v-6.77c0-1.133-.927-2.06-2.06-2.06z"
4180
- })), _path2$3 || (_path2$3 = /*#__PURE__*/React.createElement("path", {
4884
+ })), _path2$4 || (_path2$4 = /*#__PURE__*/React.createElement("path", {
4181
4885
  d: "m35.13 37.603 1.237-1.237-3.468-3.475v-5.926h-1.754v6.654l3.984 3.984Z"
4182
4886
  })), _path3 || (_path3 = /*#__PURE__*/React.createElement("path", {
4183
4887
  fillRule: "evenodd",
@@ -4186,27 +4890,27 @@ var SvgDatetime = function SvgDatetime(props) {
4186
4890
  };
4187
4891
  var DatetimeIcon = SvgDatetime;
4188
4892
 
4189
- var _path$b, _path2$2;
4190
- function _extends$c() { _extends$c = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$c.apply(this, arguments); }
4893
+ var _path$h, _path2$3;
4894
+ function _extends$i() { _extends$i = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$i.apply(this, arguments); }
4191
4895
  var SvgTaglist = function SvgTaglist(props) {
4192
- return /*#__PURE__*/React.createElement("svg", _extends$c({
4896
+ return /*#__PURE__*/React.createElement("svg", _extends$i({
4193
4897
  xmlns: "http://www.w3.org/2000/svg",
4194
4898
  width: 54,
4195
4899
  height: 54,
4196
4900
  fill: "currentcolor"
4197
- }, props), _path$b || (_path$b = /*#__PURE__*/React.createElement("path", {
4901
+ }, props), _path$h || (_path$h = /*#__PURE__*/React.createElement("path", {
4198
4902
  fillRule: "evenodd",
4199
4903
  d: "M45 16a3 3 0 0 1 3 3v16a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V19a3 3 0 0 1 3-3h36Zm0 2H9a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h36a1 1 0 0 0 1-1V19a1 1 0 0 0-1-1Z"
4200
- })), _path2$2 || (_path2$2 = /*#__PURE__*/React.createElement("path", {
4904
+ })), _path2$3 || (_path2$3 = /*#__PURE__*/React.createElement("path", {
4201
4905
  d: "M11 22a1 1 0 0 1 1-1h19a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1H12a1 1 0 0 1-1-1V22Z"
4202
4906
  })));
4203
4907
  };
4204
4908
  var TaglistIcon = SvgTaglist;
4205
4909
 
4206
4910
  var _rect, _rect2, _rect3;
4207
- function _extends$b() { _extends$b = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$b.apply(this, arguments); }
4911
+ function _extends$h() { _extends$h = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$h.apply(this, arguments); }
4208
4912
  var SvgForm = function SvgForm(props) {
4209
- return /*#__PURE__*/React.createElement("svg", _extends$b({
4913
+ return /*#__PURE__*/React.createElement("svg", _extends$h({
4210
4914
  xmlns: "http://www.w3.org/2000/svg",
4211
4915
  width: 54,
4212
4916
  height: 54
@@ -4232,151 +4936,168 @@ var SvgForm = function SvgForm(props) {
4232
4936
  };
4233
4937
  var FormIcon = SvgForm;
4234
4938
 
4235
- var _path$a;
4236
- function _extends$a() { _extends$a = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$a.apply(this, arguments); }
4939
+ var _path$g;
4940
+ function _extends$g() { _extends$g = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$g.apply(this, arguments); }
4237
4941
  var SvgGroup = function SvgGroup(props) {
4238
- return /*#__PURE__*/React.createElement("svg", _extends$a({
4942
+ return /*#__PURE__*/React.createElement("svg", _extends$g({
4239
4943
  xmlns: "http://www.w3.org/2000/svg",
4240
4944
  width: 54,
4241
4945
  height: 54,
4242
4946
  fill: "currentcolor"
4243
- }, props), _path$a || (_path$a = /*#__PURE__*/React.createElement("path", {
4947
+ }, props), _path$g || (_path$g = /*#__PURE__*/React.createElement("path", {
4244
4948
  fillRule: "evenodd",
4245
4949
  d: "M8 33v5a1 1 0 0 0 1 1h4v2H9a3 3 0 0 1-3-3v-5h2Zm18 6v2H15v-2h11Zm13 0v2H28v-2h11Zm9-6v5a3 3 0 0 1-3 3h-4v-2h4a1 1 0 0 0 .993-.883L46 38v-5h2ZM8 22v9H6v-9h2Zm40 0v9h-2v-9h2Zm-35-9v2H9a1 1 0 0 0-.993.883L8 16v4H6v-4a3 3 0 0 1 3-3h4Zm32 0a3 3 0 0 1 3 3v4h-2v-4a1 1 0 0 0-.883-.993L45 15h-4v-2h4Zm-6 0v2H28v-2h11Zm-13 0v2H15v-2h11Z"
4246
4950
  })));
4247
4951
  };
4248
4952
  var GroupIcon = SvgGroup;
4249
4953
 
4250
- var _path$9;
4251
- function _extends$9() { _extends$9 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$9.apply(this, arguments); }
4954
+ var _path$f;
4955
+ function _extends$f() { _extends$f = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$f.apply(this, arguments); }
4252
4956
  var SvgNumber = function SvgNumber(props) {
4253
- return /*#__PURE__*/React.createElement("svg", _extends$9({
4957
+ return /*#__PURE__*/React.createElement("svg", _extends$f({
4254
4958
  xmlns: "http://www.w3.org/2000/svg",
4255
4959
  width: 54,
4256
4960
  height: 54,
4257
4961
  fill: "currentcolor"
4258
- }, props), _path$9 || (_path$9 = /*#__PURE__*/React.createElement("path", {
4962
+ }, props), _path$f || (_path$f = /*#__PURE__*/React.createElement("path", {
4259
4963
  fillRule: "evenodd",
4260
4964
  d: "M45 16a3 3 0 0 1 3 3v16a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V19a3 3 0 0 1 3-3h36zm0 2H9a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h36a1 1 0 0 0 1-1V19a1 1 0 0 0-1-1zM35 28.444h7l-3.5 4-3.5-4zM35 26h7l-3.5-4-3.5 4z"
4261
4965
  })));
4262
4966
  };
4263
4967
  var NumberIcon = SvgNumber;
4264
4968
 
4265
- var _path$8;
4266
- function _extends$8() { _extends$8 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$8.apply(this, arguments); }
4969
+ var _path$e;
4970
+ function _extends$e() { _extends$e = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$e.apply(this, arguments); }
4267
4971
  var SvgRadio = function SvgRadio(props) {
4268
- return /*#__PURE__*/React.createElement("svg", _extends$8({
4972
+ return /*#__PURE__*/React.createElement("svg", _extends$e({
4269
4973
  xmlns: "http://www.w3.org/2000/svg",
4270
4974
  width: 54,
4271
4975
  height: 54,
4272
4976
  fill: "currentcolor"
4273
- }, props), _path$8 || (_path$8 = /*#__PURE__*/React.createElement("path", {
4977
+ }, props), _path$e || (_path$e = /*#__PURE__*/React.createElement("path", {
4274
4978
  d: "M27 22c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10zm0 18a8 8 0 1 1 0-16 8 8 0 1 1 0 16z"
4275
4979
  })));
4276
4980
  };
4277
4981
  var RadioIcon = SvgRadio;
4278
4982
 
4279
- var _path$7;
4280
- function _extends$7() { _extends$7 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$7.apply(this, arguments); }
4983
+ var _path$d;
4984
+ function _extends$d() { _extends$d = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$d.apply(this, arguments); }
4281
4985
  var SvgSelect = function SvgSelect(props) {
4282
- return /*#__PURE__*/React.createElement("svg", _extends$7({
4986
+ return /*#__PURE__*/React.createElement("svg", _extends$d({
4283
4987
  xmlns: "http://www.w3.org/2000/svg",
4284
4988
  width: 54,
4285
4989
  height: 54,
4286
4990
  fill: "currentcolor"
4287
- }, props), _path$7 || (_path$7 = /*#__PURE__*/React.createElement("path", {
4991
+ }, props), _path$d || (_path$d = /*#__PURE__*/React.createElement("path", {
4288
4992
  fillRule: "evenodd",
4289
4993
  d: "M45 16a3 3 0 0 1 3 3v16a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V19a3 3 0 0 1 3-3h36zm0 2H9a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h36a1 1 0 0 0 1-1V19a1 1 0 0 0-1-1zm-12 7h9l-4.5 6-4.5-6z"
4290
4994
  })));
4291
4995
  };
4292
4996
  var SelectIcon = SvgSelect;
4293
4997
 
4294
- var _path$6;
4295
- function _extends$6() { _extends$6 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$6.apply(this, arguments); }
4998
+ var _path$c;
4999
+ function _extends$c() { _extends$c = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$c.apply(this, arguments); }
4296
5000
  var SvgSeparator = function SvgSeparator(props) {
4297
- return /*#__PURE__*/React.createElement("svg", _extends$6({
5001
+ return /*#__PURE__*/React.createElement("svg", _extends$c({
4298
5002
  xmlns: "http://www.w3.org/2000/svg",
4299
5003
  width: 54,
4300
5004
  height: 54,
4301
5005
  fill: "none"
4302
- }, props), _path$6 || (_path$6 = /*#__PURE__*/React.createElement("path", {
5006
+ }, props), _path$c || (_path$c = /*#__PURE__*/React.createElement("path", {
4303
5007
  fill: "currentColor",
4304
5008
  d: "M26.293 16.293a1 1 0 0 1 1.414 0l4 4a1 1 0 0 1-1.414 1.414L27 18.414l-3.293 3.293a1 1 0 0 1-1.414-1.414l4-4ZM9 26h36v2H9v-2Zm13.293 7.707 4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0-1.414-1.414L27 35.586l-3.293-3.293a1 1 0 0 0-1.414 1.414Z"
4305
5009
  })));
4306
5010
  };
4307
5011
  var SeparatorIcon = SvgSeparator;
4308
5012
 
4309
- var _path$5;
4310
- function _extends$5() { _extends$5 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$5.apply(this, arguments); }
5013
+ var _path$b;
5014
+ function _extends$b() { _extends$b = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$b.apply(this, arguments); }
4311
5015
  var SvgSpacer = function SvgSpacer(props) {
4312
- return /*#__PURE__*/React.createElement("svg", _extends$5({
5016
+ return /*#__PURE__*/React.createElement("svg", _extends$b({
4313
5017
  xmlns: "http://www.w3.org/2000/svg",
4314
5018
  width: 54,
4315
5019
  height: 54,
4316
5020
  fill: "none"
4317
- }, props), _path$5 || (_path$5 = /*#__PURE__*/React.createElement("path", {
5021
+ }, props), _path$b || (_path$b = /*#__PURE__*/React.createElement("path", {
4318
5022
  fill: "currentColor",
4319
5023
  d: "M9 15v2h36v-2H9Zm0 22v2h36v-2H9Zm17.293-17.707a1 1 0 0 1 1.414 0l4 4a1 1 0 0 1-1.414 1.414L27 21.414l-3.293 3.293a1 1 0 0 1-1.414-1.414l4-4Zm-4 11.414 4 4a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0-1.414-1.414L27 32.586l-3.293-3.293a1 1 0 0 0-1.414 1.414Z"
4320
5024
  })));
4321
5025
  };
4322
5026
  var SpacerIcon = SvgSpacer;
4323
5027
 
4324
- var _path$4;
4325
- function _extends$4() { _extends$4 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$4.apply(this, arguments); }
5028
+ var _path$a;
5029
+ function _extends$a() { _extends$a = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$a.apply(this, arguments); }
5030
+ var SvgDynamicList = function SvgDynamicList(props) {
5031
+ return /*#__PURE__*/React.createElement("svg", _extends$a({
5032
+ xmlns: "http://www.w3.org/2000/svg",
5033
+ width: 54,
5034
+ height: 54,
5035
+ fill: "none"
5036
+ }, props), _path$a || (_path$a = /*#__PURE__*/React.createElement("path", {
5037
+ fill: "currentColor",
5038
+ fillRule: "evenodd",
5039
+ d: "M2.7 43.296v1.254c0 .746.604 1.35 1.35 1.35h1.275v-1.795c.049.14.075.29.075.445v-1.254h-.075V43.2H4.05c.177 0 .347.034.502.096H2.7Zm2.7-2.507v-2.507H2.7v2.507h2.7Zm0-5.014v-2.507H2.7v2.507h2.7Zm0-5.014v-2.507H2.7v2.507h2.7Zm0-5.015V23.24H2.7v2.507h2.7Zm0-5.014v-2.507H2.7v2.507h2.7Zm0-5.014V13.21H2.7v2.507h2.7Zm-2.7-5.014h1.852a1.346 1.346 0 0 1-.502.096h1.275v-.096H5.4V9.45c0 .156-.026.306-.075.445V8.1H4.05A1.35 1.35 0 0 0 2.7 9.45v1.254Zm5.175.096h2.55V8.1h-2.55v2.7Zm5.1 0h2.55V8.1h-2.55v2.7Zm5.1 0h2.55V8.1h-2.55v2.7Zm5.1 0h2.55V8.1h-2.55v2.7Zm5.1 0h2.55V8.1h-2.55v2.7Zm5.1 0h2.55V8.1h-2.55v2.7Zm5.1 0h2.55V8.1h-2.55v2.7Zm5.1 0h2.55V8.1h-2.55v2.7Zm5.1-2.7v1.795a1.348 1.348 0 0 1-.075-.445v1.254h.075v.096h1.275c-.177 0-.347-.034-.502-.096H51.3V9.45a1.35 1.35 0 0 0-1.35-1.35h-1.275Zm-.075 5.11v2.508h2.7V13.21h-2.7Zm0 5.015v2.507h2.7v-2.507h-2.7Zm0 5.014v2.507h2.7V23.24h-2.7Zm0 5.015v2.507h2.7v-2.507h-2.7Zm0 5.014v2.507h2.7v-2.507h-2.7Zm0 5.014v2.507h2.7v-2.507h-2.7Zm2.7 5.014h-1.852c.155-.062.325-.096.502-.096h-1.275v.096H48.6v1.254c0-.156.026-.305.075-.445V45.9h1.275a1.35 1.35 0 0 0 1.35-1.35v-1.254Zm-5.175-.096h-2.55v2.7h2.55v-2.7Zm-5.1 0h-2.55v2.7h2.55v-2.7Zm-5.1 0h-2.55v2.7h2.55v-2.7Zm-5.1 0h-2.55v2.7h2.55v-2.7Zm-5.1 0h-2.55v2.7h2.55v-2.7Zm-5.1 0h-2.55v2.7h2.55v-2.7Zm-5.1 0h-2.55v2.7h2.55v-2.7Zm-5.1 0h-2.55v2.7h2.55v-2.7ZM16.2 17.55a4.05 4.05 0 0 1 4.05 4.05v1.35A4.05 4.05 0 0 1 16.2 27h-1.35a4.05 4.05 0 0 1-4.05-4.05V21.6a4.05 4.05 0 0 1 4.05-4.05h1.35Zm0 2.7h-1.35a1.35 1.35 0 0 0-1.35 1.35v1.35c0 .746.604 1.35 1.35 1.35h1.35a1.35 1.35 0 0 0 1.35-1.35V21.6a1.35 1.35 0 0 0-1.35-1.35Zm27 1.35a4.05 4.05 0 0 0-4.05-4.05H29.7a4.05 4.05 0 0 0-4.05 4.05v1.35A4.05 4.05 0 0 0 29.7 27h9.45a4.05 4.05 0 0 0 4.05-4.05V21.6Zm-13.5-1.35h9.45c.746 0 1.35.604 1.35 1.35v1.35a1.35 1.35 0 0 1-1.35 1.35H29.7a1.35 1.35 0 0 1-1.35-1.35V21.6c0-.746.604-1.35 1.35-1.35ZM43.2 37.8a4.05 4.05 0 0 0-4.05-4.05H29.7a4.05 4.05 0 0 0-4.05 4.05v1.35h2.7V37.8c0-.746.604-1.35 1.35-1.35h9.45c.746 0 1.35.604 1.35 1.35v1.35h2.7V37.8Zm-27-4.05a4.05 4.05 0 0 1 4.05 4.05v1.35h-2.7V37.8a1.35 1.35 0 0 0-1.35-1.35h-1.35a1.35 1.35 0 0 0-1.35 1.35v1.35h-2.7V37.8a4.05 4.05 0 0 1 4.05-4.05h1.35Z",
5040
+ clipRule: "evenodd"
5041
+ })));
5042
+ };
5043
+ var DynamicListIcon = SvgDynamicList;
5044
+
5045
+ var _path$9;
5046
+ function _extends$9() { _extends$9 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$9.apply(this, arguments); }
4326
5047
  var SvgText = function SvgText(props) {
4327
- return /*#__PURE__*/React.createElement("svg", _extends$4({
5048
+ return /*#__PURE__*/React.createElement("svg", _extends$9({
4328
5049
  xmlns: "http://www.w3.org/2000/svg",
4329
5050
  width: 54,
4330
5051
  height: 54,
4331
5052
  fill: "currentcolor"
4332
- }, props), _path$4 || (_path$4 = /*#__PURE__*/React.createElement("path", {
5053
+ }, props), _path$9 || (_path$9 = /*#__PURE__*/React.createElement("path", {
4333
5054
  d: "M20.58 33.77h-3l-1.18-3.08H11l-1.1 3.08H7l5.27-13.54h2.89zm-5-5.36-1.86-5-1.83 5zM22 20.23h5.41a15.47 15.47 0 0 1 2.4.14 3.42 3.42 0 0 1 1.41.55 3.47 3.47 0 0 1 1 1.14 3 3 0 0 1 .42 1.58 3.26 3.26 0 0 1-1.91 2.94 3.63 3.63 0 0 1 1.91 1.22 3.28 3.28 0 0 1 .66 2 4 4 0 0 1-.43 1.8 3.63 3.63 0 0 1-1.09 1.4 3.89 3.89 0 0 1-1.83.65q-.69.07-3.3.09H22zm2.73 2.25v3.13h3.8a1.79 1.79 0 0 0 1.1-.49 1.41 1.41 0 0 0 .41-1 1.49 1.49 0 0 0-.35-1 1.54 1.54 0 0 0-1-.48c-.27 0-1.05-.05-2.34-.05zm0 5.39v3.62h2.57a11.52 11.52 0 0 0 1.88-.09 1.65 1.65 0 0 0 1-.54 1.6 1.6 0 0 0 .38-1.14 1.75 1.75 0 0 0-.29-1 1.69 1.69 0 0 0-.86-.62 9.28 9.28 0 0 0-2.41-.23zm19.62.92 2.65.84a5.94 5.94 0 0 1-2 3.29A5.74 5.74 0 0 1 41.38 34a5.87 5.87 0 0 1-4.44-1.84 7.09 7.09 0 0 1-1.73-5A7.43 7.43 0 0 1 37 21.87 6 6 0 0 1 41.54 20a5.64 5.64 0 0 1 4 1.47A5.33 5.33 0 0 1 47 24l-2.7.65a2.8 2.8 0 0 0-2.86-2.27A3.09 3.09 0 0 0 39 23.42a5.31 5.31 0 0 0-.93 3.5 5.62 5.62 0 0 0 .93 3.65 3 3 0 0 0 2.4 1.09 2.72 2.72 0 0 0 1.82-.66 4 4 0 0 0 1.13-2.21z"
4334
5055
  })));
4335
5056
  };
4336
5057
  var TextIcon = SvgText;
4337
5058
 
4338
- var _path$3;
4339
- function _extends$3() { _extends$3 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$3.apply(this, arguments); }
5059
+ var _path$8;
5060
+ function _extends$8() { _extends$8 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$8.apply(this, arguments); }
4340
5061
  var SvgTextfield = function SvgTextfield(props) {
4341
- return /*#__PURE__*/React.createElement("svg", _extends$3({
5062
+ return /*#__PURE__*/React.createElement("svg", _extends$8({
4342
5063
  xmlns: "http://www.w3.org/2000/svg",
4343
5064
  width: 54,
4344
5065
  height: 54,
4345
5066
  fill: "currentcolor"
4346
- }, props), _path$3 || (_path$3 = /*#__PURE__*/React.createElement("path", {
5067
+ }, props), _path$8 || (_path$8 = /*#__PURE__*/React.createElement("path", {
4347
5068
  fillRule: "evenodd",
4348
5069
  d: "M45 16a3 3 0 0 1 3 3v16a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V19a3 3 0 0 1 3-3h36zm0 2H9a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h36a1 1 0 0 0 1-1V19a1 1 0 0 0-1-1zm-32 4v10h-2V22h2z"
4349
5070
  })));
4350
5071
  };
4351
5072
  var TextfieldIcon = SvgTextfield;
4352
5073
 
4353
- var _path$2;
4354
- function _extends$2() { _extends$2 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$2.apply(this, arguments); }
5074
+ var _path$7;
5075
+ function _extends$7() { _extends$7 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$7.apply(this, arguments); }
4355
5076
  var SvgTextarea = function SvgTextarea(props) {
4356
- return /*#__PURE__*/React.createElement("svg", _extends$2({
5077
+ return /*#__PURE__*/React.createElement("svg", _extends$7({
4357
5078
  xmlns: "http://www.w3.org/2000/svg",
4358
5079
  width: 54,
4359
5080
  height: 54,
4360
5081
  fill: "currentcolor"
4361
- }, props), _path$2 || (_path$2 = /*#__PURE__*/React.createElement("path", {
5082
+ }, props), _path$7 || (_path$7 = /*#__PURE__*/React.createElement("path", {
4362
5083
  fillRule: "evenodd",
4363
5084
  d: "M45 13a3 3 0 0 1 3 3v22a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V16a3 3 0 0 1 3-3h36zm0 2H9a1 1 0 0 0-1 1v22a1 1 0 0 0 1 1h36a1 1 0 0 0 1-1V16a1 1 0 0 0-1-1zm-1.136 15.5.849.849-6.364 6.364-.849-.849 6.364-6.364zm.264 3.5.849.849-2.828 2.828-.849-.849L44.128 34zM13 19v10h-2V19h2z"
4364
5085
  })));
4365
5086
  };
4366
5087
  var TextareaIcon = SvgTextarea;
4367
5088
 
4368
- var _path$1, _path2$1;
4369
- function _extends$1() { _extends$1 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$1.apply(this, arguments); }
5089
+ var _path$6, _path2$2;
5090
+ function _extends$6() { _extends$6 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$6.apply(this, arguments); }
4370
5091
  var SvgIFrame = function SvgIFrame(props) {
4371
- return /*#__PURE__*/React.createElement("svg", _extends$1({
5092
+ return /*#__PURE__*/React.createElement("svg", _extends$6({
4372
5093
  xmlns: "http://www.w3.org/2000/svg",
4373
5094
  width: 54,
4374
5095
  height: 54,
4375
5096
  fill: "none"
4376
- }, props), _path$1 || (_path$1 = /*#__PURE__*/React.createElement("path", {
5097
+ }, props), _path$6 || (_path$6 = /*#__PURE__*/React.createElement("path", {
4377
5098
  fill: "currentcolor",
4378
5099
  d: "M34.467 37.3 41 31l-6.533-6.3-1.32 1.273L38.36 31l-5.213 5.027 1.32 1.273ZM19.533 24.7 13 31l6.533 6.3 1.32-1.273L15.64 31l5.214-5.027-1.32-1.273Zm4.127 14.832 1.805.468 4.875-17.532L28.535 22 23.66 39.532Z"
4379
- })), _path2$1 || (_path2$1 = /*#__PURE__*/React.createElement("path", {
5100
+ })), _path2$2 || (_path2$2 = /*#__PURE__*/React.createElement("path", {
4380
5101
  fill: "currentcolor",
4381
5102
  fillRule: "evenodd",
4382
5103
  d: "M46 9a3 3 0 0 1 3 3v30a3 3 0 0 1-3 3H8a3 3 0 0 1-3-3V12a3 3 0 0 1 3-3h38Zm0 2H8a1 1 0 0 0-1 1v4h40v-4a1 1 0 0 0-1-1ZM7 42V18h40v24a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1Z",
@@ -4385,19 +5106,19 @@ var SvgIFrame = function SvgIFrame(props) {
4385
5106
  };
4386
5107
  var IFrameIcon = SvgIFrame;
4387
5108
 
4388
- var _path, _path2;
4389
- function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
5109
+ var _path$5, _path2$1;
5110
+ function _extends$5() { _extends$5 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$5.apply(this, arguments); }
4390
5111
  var SvgImage = function SvgImage(props) {
4391
- return /*#__PURE__*/React.createElement("svg", _extends({
5112
+ return /*#__PURE__*/React.createElement("svg", _extends$5({
4392
5113
  xmlns: "http://www.w3.org/2000/svg",
4393
5114
  width: 54,
4394
5115
  height: 54,
4395
5116
  fill: "currentcolor"
4396
- }, props), _path || (_path = /*#__PURE__*/React.createElement("path", {
5117
+ }, props), _path$5 || (_path$5 = /*#__PURE__*/React.createElement("path", {
4397
5118
  fillRule: "evenodd",
4398
5119
  d: "M34.636 21.91A3.818 3.818 0 1 1 27 21.908a3.818 3.818 0 0 1 7.636 0Zm-2 0A1.818 1.818 0 1 1 29 21.908a1.818 1.818 0 0 1 3.636 0Z",
4399
5120
  clipRule: "evenodd"
4400
- })), _path2 || (_path2 = /*#__PURE__*/React.createElement("path", {
5121
+ })), _path2$1 || (_path2$1 = /*#__PURE__*/React.createElement("path", {
4401
5122
  fillRule: "evenodd",
4402
5123
  d: "M15 13a2 2 0 0 0-2 2v24a2 2 0 0 0 2 2h24a2 2 0 0 0 2-2V15a2 2 0 0 0-2-2H15Zm24 2H15v12.45l4.71-4.709a1.91 1.91 0 0 1 2.702 0l6.695 6.695 2.656-1.77a1.91 1.91 0 0 1 2.411.239L39 32.73V15ZM15 39v-8.754a.975.975 0 0 0 .168-.135l5.893-5.893 6.684 6.685a1.911 1.911 0 0 0 2.41.238l2.657-1.77 6.02 6.02c.052.051.108.097.168.135V39H15Z",
4403
5124
  clipRule: "evenodd"
@@ -4405,6 +5126,22 @@ var SvgImage = function SvgImage(props) {
4405
5126
  };
4406
5127
  var ImageIcon = SvgImage;
4407
5128
 
5129
+ var _path$4;
5130
+ function _extends$4() { _extends$4 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$4.apply(this, arguments); }
5131
+ var SvgTable = function SvgTable(props) {
5132
+ return /*#__PURE__*/React.createElement("svg", _extends$4({
5133
+ xmlns: "http://www.w3.org/2000/svg",
5134
+ fill: "none",
5135
+ viewBox: "0 0 54 54"
5136
+ }, props), _path$4 || (_path$4 = /*#__PURE__*/React.createElement("path", {
5137
+ fill: "currentcolor",
5138
+ fillRule: "evenodd",
5139
+ d: "M42.545 12.273A2.455 2.455 0 0 1 45 14.727v24.546a2.455 2.455 0 0 1-2.455 2.454h-31.09A2.455 2.455 0 0 1 9 39.273V14.727a2.455 2.455 0 0 1 2.455-2.454zM27.818 40.09h14.727a.818.818 0 0 0 .819-.818v-4.91H27.818Zm-1.636-5.727v5.727H11.455a.818.818 0 0 1-.819-.818v-4.91zm1.636-1.637h15.546V27H27.818ZM26.182 27v5.727H10.636V27zm1.636-1.636h15.546v-5.728H27.818Zm-1.636-5.728v5.728H10.636v-5.728z",
5140
+ clipRule: "evenodd"
5141
+ })));
5142
+ };
5143
+ var TableIcon = SvgTable;
5144
+
4408
5145
  const iconsByType = type => {
4409
5146
  return {
4410
5147
  button: ButtonIcon,
@@ -4420,124 +5157,35 @@ const iconsByType = type => {
4420
5157
  select: SelectIcon,
4421
5158
  separator: SeparatorIcon,
4422
5159
  spacer: SpacerIcon,
5160
+ dynamiclist: DynamicListIcon,
4423
5161
  taglist: TaglistIcon,
4424
5162
  text: TextIcon,
4425
5163
  textfield: TextfieldIcon,
4426
5164
  textarea: TextareaIcon,
5165
+ table: TableIcon,
4427
5166
  default: FormIcon
4428
5167
  }[type];
4429
5168
  };
4430
5169
 
4431
- const formFields = [Button, Checkbox, Checklist, FormComponent$1, Group, IFrame, Image, Numberfield, Datetime, Radio, Select, Spacer, Separator, Taglist, Text, Textfield, Textarea];
5170
+ const formFields = [Button, Checkbox, Checklist, FormComponent$1, Group, IFrame, DynamicList, Image, Numberfield, Datetime, Radio, Select, Spacer, Separator, DynamicList, Taglist, Text, Textfield, Textarea, Table];
4432
5171
 
4433
5172
  class FormFields {
4434
5173
  constructor() {
4435
5174
  this._formFields = {};
4436
5175
  formFields.forEach(formField => {
4437
- this.register(formField.config.type, formField);
4438
- });
4439
- }
4440
- register(type, formField) {
4441
- this._formFields[type] = formField;
4442
- }
4443
- get(type) {
4444
- return this._formFields[type];
4445
- }
4446
- }
4447
-
4448
- // config ///////////////////
4449
-
4450
- const VALUES_SOURCES = {
4451
- STATIC: 'static',
4452
- INPUT: 'input',
4453
- EXPRESSION: 'expression'
4454
- };
4455
- const VALUES_SOURCE_DEFAULT = VALUES_SOURCES.STATIC;
4456
- const VALUES_SOURCES_LABELS = {
4457
- [VALUES_SOURCES.STATIC]: 'Static',
4458
- [VALUES_SOURCES.INPUT]: 'Input data',
4459
- [VALUES_SOURCES.EXPRESSION]: 'Expression'
4460
- };
4461
- const VALUES_SOURCES_PATHS = {
4462
- [VALUES_SOURCES.STATIC]: ['values'],
4463
- [VALUES_SOURCES.INPUT]: ['valuesKey'],
4464
- [VALUES_SOURCES.EXPRESSION]: ['valuesExpression']
4465
- };
4466
- const VALUES_SOURCES_DEFAULTS = {
4467
- [VALUES_SOURCES.STATIC]: [{
4468
- label: 'Value',
4469
- value: 'value'
4470
- }],
4471
- [VALUES_SOURCES.INPUT]: '',
4472
- [VALUES_SOURCES.EXPRESSION]: '='
4473
- };
4474
-
4475
- // helpers ///////////////////
4476
-
4477
- function getValuesSource(field) {
4478
- for (const source of Object.values(VALUES_SOURCES)) {
4479
- if (get(field, VALUES_SOURCES_PATHS[source]) !== undefined) {
4480
- return source;
4481
- }
4482
- }
4483
- return VALUES_SOURCE_DEFAULT;
4484
- }
4485
-
4486
- function createInjector(bootstrapModules) {
4487
- const injector = new Injector(bootstrapModules);
4488
- injector.init();
4489
- return injector;
4490
- }
4491
-
4492
- /**
4493
- * @param {string?} prefix
4494
- *
4495
- * @returns Element
4496
- */
4497
- function createFormContainer(prefix = 'fjs') {
4498
- const container = document.createElement('div');
4499
- container.classList.add(`${prefix}-container`);
4500
- return container;
4501
- }
4502
-
4503
- 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'];
4504
- const TEMPLATE_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'description', 'label', 'source', 'text', 'url'];
4505
- function isRequired(field) {
4506
- return field.required;
4507
- }
4508
- function pathParse(path) {
4509
- if (!path) {
4510
- return [];
4511
- }
4512
- return path.split('.').map(key => {
4513
- return isNaN(parseInt(key)) ? key : parseInt(key);
4514
- });
4515
- }
4516
- function pathsEqual(a, b) {
4517
- return a && b && a.length === b.length && a.every((value, index) => value === b[index]);
4518
- }
4519
- const indices = {};
4520
- function generateIndexForType(type) {
4521
- if (type in indices) {
4522
- indices[type]++;
4523
- } else {
4524
- indices[type] = 1;
5176
+ this.register(formField.config.type, formField);
5177
+ });
5178
+ }
5179
+ register(type, formField) {
5180
+ this._formFields[type] = formField;
5181
+ }
5182
+ get(type) {
5183
+ return this._formFields[type];
4525
5184
  }
4526
- return indices[type];
4527
- }
4528
- function generateIdForType(type) {
4529
- return `${type}${generateIndexForType(type)}`;
4530
5185
  }
4531
5186
 
4532
- /**
4533
- * @template T
4534
- * @param {T} data
4535
- * @param {(this: any, key: string, value: any) => any} [replacer]
4536
- * @return {T}
4537
- */
4538
- function clone(data, replacer) {
4539
- return JSON.parse(JSON.stringify(data, replacer));
4540
- }
5187
+ 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'];
5188
+ const TEMPLATE_PROPERTIES = ['alt', 'appearance.prefixAdorner', 'appearance.suffixAdorner', 'description', 'label', 'source', 'text', 'url'];
4541
5189
 
4542
5190
  /**
4543
5191
  * @typedef { import('../types').Schema } Schema
@@ -4644,13 +5292,24 @@ function getSchemaVariables(schema, options = {}) {
4644
5292
  // remove duplicates
4645
5293
  return Array.from(new Set(variables));
4646
5294
  }
4647
- function runRecursively(formField, fn) {
4648
- const components = formField.components || [];
4649
- components.forEach((component, index) => {
4650
- runRecursively(component, fn);
4651
- });
4652
- fn(formField);
4653
- }
5295
+
5296
+ /**
5297
+ * Get the ancestry list of a form field.
5298
+ *
5299
+ * @param {string} formFieldId
5300
+ * @param {import('../core/FormFieldRegistry').default} formFieldRegistry
5301
+ *
5302
+ * @return {Array<string>} ancestry list
5303
+ */
5304
+ const getAncestryList = (formFieldId, formFieldRegistry) => {
5305
+ const ids = [];
5306
+ let currentFormField = formFieldRegistry.get(formFieldId);
5307
+ while (currentFormField) {
5308
+ ids.push(currentFormField.id);
5309
+ currentFormField = formFieldRegistry.get(currentFormField._parent);
5310
+ }
5311
+ return ids;
5312
+ };
4654
5313
 
4655
5314
  /**
4656
5315
  * @typedef {object} Condition
@@ -4667,36 +5326,102 @@ class ConditionChecker {
4667
5326
  /**
4668
5327
  * For given data, remove properties based on condition.
4669
5328
  *
4670
- * @param {Object<string, any>} properties
4671
5329
  * @param {Object<string, any>} data
5330
+ * @param {Object<string, any>} contextData
4672
5331
  * @param {Object} [options]
4673
5332
  * @param {Function} [options.getFilterPath]
5333
+ * @param {boolean} [options.leafNodeDeletionOnly]
4674
5334
  */
4675
- applyConditions(properties, data = {}, options = {}) {
4676
- const newProperties = clone(properties);
5335
+ applyConditions(data, contextData = {}, options = {}) {
5336
+ const workingData = clone(data);
4677
5337
  const {
4678
- getFilterPath = field => this._pathRegistry.getValuePath(field)
5338
+ getFilterPath = (field, indexes) => this._pathRegistry.getValuePath(field, {
5339
+ indexes
5340
+ }),
5341
+ leafNodeDeletionOnly = false
4679
5342
  } = options;
4680
- const form = this._formFieldRegistry.getAll().find(field => field.type === 'default');
5343
+ const _applyConditionsWithinScope = (rootField, scopeContext, startHidden = false) => {
5344
+ const {
5345
+ indexes = {},
5346
+ expressionIndexes = [],
5347
+ scopeData = contextData,
5348
+ parentScopeData = null
5349
+ } = scopeContext;
5350
+ this._pathRegistry.executeRecursivelyOnFields(rootField, ({
5351
+ field,
5352
+ isClosed,
5353
+ isRepeatable,
5354
+ context
5355
+ }) => {
5356
+ const {
5357
+ conditional,
5358
+ components,
5359
+ id
5360
+ } = field;
5361
+
5362
+ // build the expression context in the right format
5363
+ const localExpressionContext = buildExpressionContext({
5364
+ this: scopeData,
5365
+ data: contextData,
5366
+ i: expressionIndexes,
5367
+ parent: parentScopeData
5368
+ });
5369
+ context.isHidden = startHidden || context.isHidden || conditional && this._checkHideCondition(conditional, localExpressionContext);
5370
+
5371
+ // if a field is repeatable and visible, we need to implement custom recursion on its children
5372
+ if (isRepeatable && (!context.isHidden || leafNodeDeletionOnly)) {
5373
+ // prevent the regular recursion behavior of executeRecursivelyOnFields
5374
+ context.preventRecursion = true;
5375
+ const repeaterValuePath = this._pathRegistry.getValuePath(field, {
5376
+ indexes
5377
+ });
5378
+ const repeaterValue = get(contextData, repeaterValuePath);
5379
+
5380
+ // quit early if there are no children or data associated with the repeater
5381
+ if (!Array.isArray(repeaterValue) || !repeaterValue.length || !Array.isArray(components) || !components.length) {
5382
+ return;
5383
+ }
5384
+ for (let i = 0; i < repeaterValue.length; i++) {
5385
+ // create a new scope context for each index
5386
+ const newScopeContext = {
5387
+ indexes: {
5388
+ ...indexes,
5389
+ [id]: i
5390
+ },
5391
+ expressionIndexes: [...expressionIndexes, i + 1],
5392
+ scopeData: repeaterValue[i],
5393
+ parentScopeData: scopeData
5394
+ };
5395
+
5396
+ // for each child component, apply conditions within the new repetition scope
5397
+ components.forEach(component => {
5398
+ _applyConditionsWithinScope(component, newScopeContext, context.isHidden);
5399
+ });
5400
+ }
5401
+ }
5402
+
5403
+ // if we have a hidden repeatable field, and the data structure allows, we clear it directly at the root and stop recursion
5404
+ if (context.isHidden && !leafNodeDeletionOnly && isRepeatable) {
5405
+ context.preventRecursion = true;
5406
+ this._cleanlyClearDataAtPath(getFilterPath(field, indexes), workingData);
5407
+ }
5408
+
5409
+ // for simple leaf fields, we always clear
5410
+ if (context.isHidden && isClosed) {
5411
+ this._cleanlyClearDataAtPath(getFilterPath(field, indexes), workingData);
5412
+ }
5413
+ });
5414
+ };
5415
+
5416
+ // apply conditions starting with the root of the form
5417
+ const form = this._formFieldRegistry.getForm();
4681
5418
  if (!form) {
4682
5419
  throw new Error('form field registry has no form');
4683
5420
  }
4684
- this._pathRegistry.executeRecursivelyOnFields(form, ({
4685
- field,
4686
- isClosed,
4687
- context
4688
- }) => {
4689
- const {
4690
- conditional: condition
4691
- } = field;
4692
- context.isHidden = context.isHidden || condition && this._checkHideCondition(condition, data);
4693
-
4694
- // only clear the leaf nodes, as groups may both point to the same path
4695
- if (context.isHidden && isClosed) {
4696
- this._clearObjectValueRecursively(getFilterPath(field), newProperties);
4697
- }
5421
+ _applyConditionsWithinScope(form, {
5422
+ scopeData: contextData
4698
5423
  });
4699
- return newProperties;
5424
+ return workingData;
4700
5425
  }
4701
5426
 
4702
5427
  /**
@@ -4740,16 +5465,22 @@ class ConditionChecker {
4740
5465
  const result = this.check(condition.hide, data);
4741
5466
  return result === true;
4742
5467
  }
4743
- _clearObjectValueRecursively(valuePath, obj) {
5468
+ _cleanlyClearDataAtPath(valuePath, obj) {
4744
5469
  const workingValuePath = [...valuePath];
4745
5470
  let recurse = false;
4746
5471
  do {
4747
5472
  set(obj, workingValuePath, undefined);
4748
5473
  workingValuePath.pop();
4749
5474
  const parentObject = get(obj, workingValuePath);
4750
- recurse = isObject(parentObject) && !values(parentObject).length && !!workingValuePath.length;
5475
+ recurse = !!workingValuePath.length && (this._isEmptyObject(parentObject) || this._isEmptyArray(parentObject));
4751
5476
  } while (recurse);
4752
5477
  }
5478
+ _isEmptyObject(parentObject) {
5479
+ return isObject(parentObject) && !values(parentObject).length;
5480
+ }
5481
+ _isEmptyArray(parentObject) {
5482
+ return Array.isArray(parentObject) && (!parentObject.length || parentObject.every(item => item === undefined));
5483
+ }
4753
5484
  }
4754
5485
  ConditionChecker.$inject = ['formFieldRegistry', 'pathRegistry', 'eventBus'];
4755
5486
 
@@ -5264,14 +5995,15 @@ class UpdateFieldValidationHandler {
5264
5995
  execute(context) {
5265
5996
  const {
5266
5997
  field,
5267
- value
5998
+ value,
5999
+ indexes
5268
6000
  } = context;
5269
6001
  const {
5270
6002
  errors
5271
6003
  } = this._form._getState();
5272
6004
  context.oldErrors = clone(errors);
5273
6005
  const fieldErrors = this._validator.validateField(field, value);
5274
- const updatedErrors = set(errors, [field.id], fieldErrors.length ? fieldErrors : undefined);
6006
+ const updatedErrors = set(errors, [field.id, ...Object.values(indexes || {})], fieldErrors.length ? fieldErrors : undefined);
5275
6007
  this._form._setState({
5276
6008
  errors: updatedErrors
5277
6009
  });
@@ -5301,10 +6033,11 @@ class ViewerCommands {
5301
6033
  'formField.validation.update': UpdateFieldValidationHandler
5302
6034
  };
5303
6035
  }
5304
- updateFieldValidation(field, value) {
6036
+ updateFieldValidation(field, value, indexes) {
5305
6037
  const context = {
5306
6038
  field,
5307
- value
6039
+ value,
6040
+ indexes
5308
6041
  };
5309
6042
  this._commandStack.execute('formField.validation.update', context);
5310
6043
  }
@@ -5317,6 +6050,266 @@ var ViewerCommandsModule = {
5317
6050
  viewerCommands: ['type', ViewerCommands]
5318
6051
  };
5319
6052
 
6053
+ var _path$3;
6054
+ function _extends$3() { _extends$3 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$3.apply(this, arguments); }
6055
+ var SvgExpand = function SvgExpand(props) {
6056
+ return /*#__PURE__*/React.createElement("svg", _extends$3({
6057
+ xmlns: "http://www.w3.org/2000/svg",
6058
+ width: 16,
6059
+ height: 16,
6060
+ fill: "none"
6061
+ }, props), _path$3 || (_path$3 = /*#__PURE__*/React.createElement("path", {
6062
+ fill: "currentColor",
6063
+ d: "M2 9h5.5v3.086l-1.293-1.293-.707.707L8 14l2.5-2.5-.707-.707L8.5 12.086V9H14V8H2v1Zm11-7H3a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1Zm0 3H3V3h10v2Z"
6064
+ })));
6065
+ };
6066
+ var ExpandSvg = SvgExpand;
6067
+
6068
+ var _path$2;
6069
+ function _extends$2() { _extends$2 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$2.apply(this, arguments); }
6070
+ var SvgCollapse = function SvgCollapse(props) {
6071
+ return /*#__PURE__*/React.createElement("svg", _extends$2({
6072
+ xmlns: "http://www.w3.org/2000/svg",
6073
+ width: 16,
6074
+ height: 16,
6075
+ fill: "none"
6076
+ }, props), _path$2 || (_path$2 = /*#__PURE__*/React.createElement("path", {
6077
+ fill: "currentColor",
6078
+ d: "M13 10H3a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1Zm0 3H3v-2h10v2ZM8.5 3.914l1.293 1.293.707-.707L8 2 5.5 4.5l.707.707L7.5 3.914V7H2v1h12V7H8.5V3.914Z"
6079
+ })));
6080
+ };
6081
+ var CollapseSvg = SvgCollapse;
6082
+
6083
+ var _path$1, _path2;
6084
+ function _extends$1() { _extends$1 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$1.apply(this, arguments); }
6085
+ var SvgAdd = function SvgAdd(props) {
6086
+ return /*#__PURE__*/React.createElement("svg", _extends$1({
6087
+ xmlns: "http://www.w3.org/2000/svg",
6088
+ width: 16,
6089
+ height: 16,
6090
+ fill: "none"
6091
+ }, props), _path$1 || (_path$1 = /*#__PURE__*/React.createElement("path", {
6092
+ fill: "currentColor",
6093
+ d: "M8 2c3.3 0 6 2.7 6 6s-2.7 6-6 6-6-2.7-6-6 2.7-6 6-6Zm0-1C4.15 1 1 4.15 1 8s3.15 7 7 7 7-3.15 7-7-3.15-7-7-7Z"
6094
+ })), _path2 || (_path2 = /*#__PURE__*/React.createElement("path", {
6095
+ fill: "currentColor",
6096
+ d: "M12 7.5H8.5V4h-1v3.5H4v1h3.5V12h1V8.5H12v-1Z"
6097
+ })));
6098
+ };
6099
+ var AddSvg = SvgAdd;
6100
+
6101
+ var _path;
6102
+ function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
6103
+ var SvgDelete = function SvgDelete(props) {
6104
+ return /*#__PURE__*/React.createElement("svg", _extends({
6105
+ xmlns: "http://www.w3.org/2000/svg",
6106
+ width: 16,
6107
+ height: 16,
6108
+ fill: "none"
6109
+ }, props), _path || (_path = /*#__PURE__*/React.createElement("path", {
6110
+ fill: "currentColor",
6111
+ d: "m12 4.7-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8 12 4.7Z"
6112
+ })));
6113
+ };
6114
+ var DeleteSvg = SvgDelete;
6115
+
6116
+ // disable react hook rules as the linter is confusing the functional components within a class as class components
6117
+ class RepeatRenderManager {
6118
+ constructor(form, formFields, formFieldRegistry, pathRegistry) {
6119
+ this._form = form;
6120
+ this._formFields = formFields;
6121
+ this._formFieldRegistry = formFieldRegistry;
6122
+ this._pathRegistry = pathRegistry;
6123
+ this.Repeater = this.Repeater.bind(this);
6124
+ this.RepeatFooter = this.RepeatFooter.bind(this);
6125
+ }
6126
+
6127
+ /**
6128
+ * Checks whether a field is currently repeating its children.
6129
+ *
6130
+ * @param {string} id - The id of the field to check
6131
+ * @returns {boolean} - True if repeatable, false otherwise
6132
+ */
6133
+ isFieldRepeating(id) {
6134
+ if (!id) {
6135
+ return false;
6136
+ }
6137
+ const formField = this._formFieldRegistry.get(id);
6138
+ const formFieldDefinition = this._formFields.get(formField.type);
6139
+ return formFieldDefinition.config.repeatable && formField.isRepeating;
6140
+ }
6141
+ Repeater(props) {
6142
+ const {
6143
+ RowsRenderer,
6144
+ indexes,
6145
+ useSharedState,
6146
+ ...restProps
6147
+ } = props;
6148
+ const [sharedRepeatState] = useSharedState;
6149
+ const {
6150
+ data
6151
+ } = this._form._getState();
6152
+ const repeaterField = props.field;
6153
+ const dataPath = this._pathRegistry.getValuePath(repeaterField, {
6154
+ indexes
6155
+ });
6156
+ const values = get(data, dataPath) || [];
6157
+ const nonCollapsedItems = this._getNonCollapsedItems(repeaterField);
6158
+ const collapseEnabled = !repeaterField.disableCollapse && values.length > nonCollapsedItems;
6159
+ const isCollapsed = collapseEnabled && sharedRepeatState.isCollapsed;
6160
+ const hasChildren = repeaterField.components && repeaterField.components.length > 0;
6161
+ const showRemove = repeaterField.allowAddRemove && hasChildren;
6162
+ const displayValues = isCollapsed ? values.slice(0, nonCollapsedItems) : values;
6163
+ const onDeleteItem = index => {
6164
+ const updatedValues = values.slice();
6165
+ updatedValues.splice(index, 1);
6166
+ props.onChange({
6167
+ field: repeaterField,
6168
+ value: updatedValues,
6169
+ indexes
6170
+ });
6171
+ };
6172
+ const parentExpressionContextInfo = useContext(LocalExpressionContext$1);
6173
+ return jsx(Fragment, {
6174
+ children: displayValues.map((value, index) => {
6175
+ const elementProps = {
6176
+ ...restProps,
6177
+ indexes: {
6178
+ ...(indexes || {}),
6179
+ [repeaterField.id]: index
6180
+ }
6181
+ };
6182
+ const localExpressionContextInfo = useMemo(() => ({
6183
+ data: parentExpressionContextInfo.data,
6184
+ this: value,
6185
+ parent: buildExpressionContext(parentExpressionContextInfo),
6186
+ i: [...parentExpressionContextInfo.i, index + 1]
6187
+ }), [index, value]);
6188
+ return !showRemove ? jsx(LocalExpressionContext$1.Provider, {
6189
+ value: localExpressionContextInfo,
6190
+ children: jsx(RowsRenderer, {
6191
+ ...elementProps
6192
+ })
6193
+ }) : jsxs("div", {
6194
+ class: "fjs-repeat-row-container",
6195
+ children: [jsx("div", {
6196
+ class: "fjs-repeat-row-rows",
6197
+ children: jsx(LocalExpressionContext$1.Provider, {
6198
+ value: localExpressionContextInfo,
6199
+ children: jsx(RowsRenderer, {
6200
+ ...elementProps
6201
+ })
6202
+ })
6203
+ }), jsx("button", {
6204
+ class: "fjs-repeat-row-remove",
6205
+ type: "button",
6206
+ "aria-label": `Remove list item ${index + 1}`,
6207
+ onClick: () => onDeleteItem(index),
6208
+ children: jsx("div", {
6209
+ class: "fjs-repeat-row-remove-icon-container",
6210
+ children: jsx(DeleteSvg, {})
6211
+ })
6212
+ })]
6213
+ });
6214
+ })
6215
+ });
6216
+ }
6217
+ RepeatFooter(props) {
6218
+ const addButtonRef = useRef(null);
6219
+ const {
6220
+ useSharedState,
6221
+ indexes,
6222
+ field: repeaterField,
6223
+ readonly,
6224
+ disabled
6225
+ } = props;
6226
+ const [sharedRepeatState, setSharedRepeatState] = useSharedState;
6227
+ const {
6228
+ data
6229
+ } = this._form._getState();
6230
+ const dataPath = this._pathRegistry.getValuePath(repeaterField, {
6231
+ indexes
6232
+ });
6233
+ const values = get(data, dataPath) || [];
6234
+ const nonCollapsedItems = this._getNonCollapsedItems(repeaterField);
6235
+ const collapseEnabled = !repeaterField.disableCollapse && values.length > nonCollapsedItems;
6236
+ const isCollapsed = collapseEnabled && sharedRepeatState.isCollapsed;
6237
+ const hasChildren = repeaterField.components && repeaterField.components.length > 0;
6238
+ const showAdd = repeaterField.allowAddRemove && hasChildren;
6239
+ const toggle = () => {
6240
+ setSharedRepeatState(state => ({
6241
+ ...state,
6242
+ isCollapsed: !isCollapsed
6243
+ }));
6244
+ };
6245
+ const shouldScroll = useRef(false);
6246
+ const onAddItem = () => {
6247
+ const updatedValues = values.slice();
6248
+ const newItem = this._form._getInitializedFieldData(this._form._getState().data, {
6249
+ container: repeaterField,
6250
+ indexes: {
6251
+ ...indexes,
6252
+ [repeaterField.id]: updatedValues.length
6253
+ }
6254
+ });
6255
+ updatedValues.push(newItem);
6256
+ shouldScroll.current = true;
6257
+ props.onChange({
6258
+ field: repeaterField,
6259
+ value: updatedValues,
6260
+ indexes
6261
+ });
6262
+ setSharedRepeatState(state => ({
6263
+ ...state,
6264
+ isCollapsed: false
6265
+ }));
6266
+ };
6267
+ useScrollIntoView(addButtonRef, [values.length], {
6268
+ align: 'bottom',
6269
+ behavior: 'auto',
6270
+ offset: 20
6271
+ }, [shouldScroll]);
6272
+ return jsxs("div", {
6273
+ className: classNames('fjs-repeat-render-footer', {
6274
+ 'fjs-remove-allowed': repeaterField.allowAddRemove
6275
+ }),
6276
+ children: [showAdd ? jsx("button", {
6277
+ readOnly: readonly,
6278
+ disabled: disabled || readonly,
6279
+ class: "fjs-repeat-render-add",
6280
+ type: "button",
6281
+ ref: addButtonRef,
6282
+ onClick: onAddItem,
6283
+ children: jsxs(Fragment, {
6284
+ children: [jsx(AddSvg, {}), " ", 'Add new']
6285
+ })
6286
+ }) : null, collapseEnabled ? jsx("button", {
6287
+ class: "fjs-repeat-render-collapse",
6288
+ type: "button",
6289
+ onClick: toggle,
6290
+ children: isCollapsed ? jsxs(Fragment, {
6291
+ children: [jsx(ExpandSvg, {}), " ", `Expand all (${values.length})`]
6292
+ }) : jsxs(Fragment, {
6293
+ children: [jsx(CollapseSvg, {}), " ", 'Collapse']
6294
+ })
6295
+ }) : null]
6296
+ });
6297
+ }
6298
+ _getNonCollapsedItems(field) {
6299
+ const DEFAULT_NON_COLLAPSED_ITEMS = 5;
6300
+ const {
6301
+ nonCollapsedItems
6302
+ } = field;
6303
+ return nonCollapsedItems ? nonCollapsedItems : DEFAULT_NON_COLLAPSED_ITEMS;
6304
+ }
6305
+ }
6306
+ RepeatRenderManager.$inject = ['form', 'formFields', 'formFieldRegistry', 'pathRegistry'];
6307
+
6308
+ var RepeatRenderModule = {
6309
+ __init__: ['repeatRenderManager'],
6310
+ repeatRenderManager: ['type', RepeatRenderManager]
6311
+ };
6312
+
5320
6313
  var FN_REF = '__fn';
5321
6314
  var DEFAULT_PRIORITY = 1000;
5322
6315
  var slice = Array.prototype.slice;
@@ -5717,7 +6710,7 @@ EventBus.prototype._invokeListener = function (event, args, listener) {
5717
6710
  * * after: [ 1500, 1500, (new=1300), 1000, 1000, (new=1000) ]
5718
6711
  *
5719
6712
  * @param {string} event
5720
- * @param {EventBusListener} listener
6713
+ * @param {EventBusListener} newListener
5721
6714
  */
5722
6715
  EventBus.prototype._addListener = function (event, newListener) {
5723
6716
  var listener = this._getListeners(event),
@@ -6065,10 +7058,17 @@ class FieldFactory {
6065
7058
 
6066
7059
  const parent = _parent && this._formFieldRegistry.get(_parent);
6067
7060
  const parentPath = parent && this._pathRegistry.getValuePath(parent) || [];
6068
- if (config.keyed && key && !this._pathRegistry.canClaimPath([...parentPath, ...key.split('.')], true)) {
7061
+ const knownAncestorIds = getAncestryList(_parent, this._formFieldRegistry);
7062
+ if (config.keyed && key && !this._pathRegistry.canClaimPath([...parentPath, ...key.split('.')], {
7063
+ isClosed: true,
7064
+ knownAncestorIds
7065
+ })) {
6069
7066
  throw new Error(`binding path '${[...parentPath, key].join('.')}' is already claimed`);
6070
7067
  }
6071
- if (config.pathed && path && !this._pathRegistry.canClaimPath([...parentPath, ...path.split('.')], false)) {
7068
+ if (config.pathed && path && !this._pathRegistry.canClaimPath([...parentPath, ...path.split('.')], {
7069
+ isRepeatable: config.repeatable,
7070
+ knownAncestorIds
7071
+ })) {
6072
7072
  throw new Error(`binding path '${[...parentPath, ...path.split('.')].join('.')}' is already claimed`);
6073
7073
  }
6074
7074
  const labelAttrs = applyDefaults && config.label ? {
@@ -6081,9 +7081,23 @@ class FieldFactory {
6081
7081
  this._ensureId(field);
6082
7082
  if (config.keyed) {
6083
7083
  this._ensureKey(field);
7084
+ this._pathRegistry.claimPath(this._pathRegistry.getValuePath(field), {
7085
+ isClosed: true,
7086
+ claimerId: field.id,
7087
+ knownAncestorIds: getAncestryList(_parent, this._formFieldRegistry)
7088
+ });
6084
7089
  }
6085
- if (config.pathed && path) {
6086
- this._pathRegistry.claimPath(this._pathRegistry.getValuePath(field), false);
7090
+ if (config.pathed) {
7091
+ if (config.repeatable) {
7092
+ this._enforceDefaultPath(field);
7093
+ }
7094
+ if (field.path) {
7095
+ this._pathRegistry.claimPath(this._pathRegistry.getValuePath(field), {
7096
+ isRepeatable: config.repeatable,
7097
+ claimerId: field.id,
7098
+ knownAncestorIds: getAncestryList(_parent, this._formFieldRegistry)
7099
+ });
7100
+ }
6087
7101
  }
6088
7102
  return field;
6089
7103
  }
@@ -6100,16 +7114,23 @@ class FieldFactory {
6100
7114
  }
6101
7115
  _ensureKey(field) {
6102
7116
  if (!field.key) {
6103
- let random;
6104
- const parent = this._formFieldRegistry.get(field._parent);
6105
-
6106
- // ensure key uniqueness at level
6107
- do {
6108
- random = Math.random().toString(36).substring(7);
6109
- } while (parent && parent.components.some(child => child.key === random));
6110
- field.key = `${field.type}_${random}`;
7117
+ field.key = this._getUniqueKeyPath(field);
7118
+ }
7119
+ }
7120
+ _enforceDefaultPath(field) {
7121
+ if (!field.path) {
7122
+ field.path = this._getUniqueKeyPath(field);
6111
7123
  }
6112
- this._pathRegistry.claimPath(this._pathRegistry.getValuePath(field), true);
7124
+ }
7125
+ _getUniqueKeyPath(field) {
7126
+ let random;
7127
+ const parent = this._formFieldRegistry.get(field._parent);
7128
+
7129
+ // ensure key uniqueness at level
7130
+ do {
7131
+ random = Math.random().toString(36).substring(7);
7132
+ } while (parent && parent.components.some(child => child.key === random));
7133
+ return `${field.type}_${random}`;
6113
7134
  }
6114
7135
  }
6115
7136
  FieldFactory.$inject = ['formFieldRegistry', 'pathRegistry', 'formFields'];
@@ -6146,34 +7167,61 @@ FieldFactory.$inject = ['formFieldRegistry', 'pathRegistry', 'formFields'];
6146
7167
  * ]
6147
7168
  */
6148
7169
  class PathRegistry {
6149
- constructor(formFieldRegistry, formFields) {
7170
+ constructor(formFieldRegistry, formFields, injector) {
6150
7171
  this._formFieldRegistry = formFieldRegistry;
6151
7172
  this._formFields = formFields;
7173
+ this._injector = injector;
6152
7174
  this._dataPaths = [];
6153
7175
  }
6154
- canClaimPath(path, closed = false) {
7176
+ canClaimPath(path, options = {}) {
7177
+ const {
7178
+ isClosed = false,
7179
+ isRepeatable = false,
7180
+ skipAncestryCheck = false,
7181
+ claimerId = null,
7182
+ knownAncestorIds = []
7183
+ } = options;
6155
7184
  let node = {
6156
7185
  children: this._dataPaths
6157
7186
  };
7187
+
7188
+ // (1) if we reach a leaf node, we cannot claim it, if we reach an open node, we can
7189
+ // if we reach a repeatable node, we need to ensure that the claimer is (or will be) an ancestor of the repeater
6158
7190
  for (const segment of path) {
6159
7191
  node = _getNextSegment(node, segment);
6160
-
6161
- // if no node at that path, we can claim it no matter what
6162
7192
  if (!node) {
6163
7193
  return true;
6164
7194
  }
6165
-
6166
- // if we reach a leaf node, definitely not claimable
7195
+ if (node.isRepeatable && !skipAncestryCheck) {
7196
+ if (!(claimerId || knownAncestorIds.length)) {
7197
+ throw new Error('cannot claim a path that contains a repeater without specifying a claimerId or knownAncestorIds');
7198
+ }
7199
+ const isValidRepeatClaim = knownAncestorIds.includes(node.repeaterId) || claimerId && getAncestryList(claimerId, this._formFieldRegistry).includes(node.repeaterId);
7200
+ if (!isValidRepeatClaim) {
7201
+ return false;
7202
+ }
7203
+ }
6167
7204
  if (node.children === null) {
6168
7205
  return false;
6169
7206
  }
6170
7207
  }
6171
7208
 
6172
- // if after all segments we reach a node with children, we can claim it only openly
6173
- return !closed;
7209
+ // (2) if the path lands in the middle of the tree, we can only claim an open, non-repeatable path
7210
+ return !(isClosed || isRepeatable);
6174
7211
  }
6175
- claimPath(path, closed = false) {
6176
- if (!this.canClaimPath(path, closed)) {
7212
+ claimPath(path, options = {}) {
7213
+ const {
7214
+ isClosed = false,
7215
+ isRepeatable = false,
7216
+ claimerId = null,
7217
+ knownAncestorIds = []
7218
+ } = options;
7219
+ if (!this.canClaimPath(path, {
7220
+ isClosed,
7221
+ isRepeatable,
7222
+ claimerId,
7223
+ knownAncestorIds
7224
+ })) {
6177
7225
  throw new Error(`cannot claim path '${path.join('.')}'`);
6178
7226
  }
6179
7227
  let node = {
@@ -6193,9 +7241,15 @@ class PathRegistry {
6193
7241
  }
6194
7242
  node = child;
6195
7243
  }
6196
- if (closed) {
7244
+ if (isClosed) {
6197
7245
  node.children = null;
6198
7246
  }
7247
+
7248
+ // add some additional info when we make a repeatable path claim
7249
+ if (isRepeatable) {
7250
+ node.isRepeatable = true;
7251
+ node.repeaterId = claimerId;
7252
+ }
6199
7253
  }
6200
7254
  unclaimPath(path) {
6201
7255
  // verification Pass
@@ -6244,6 +7298,7 @@ class PathRegistry {
6244
7298
  const callResult = fn({
6245
7299
  field,
6246
7300
  isClosed: true,
7301
+ isRepeatable: false,
6247
7302
  context
6248
7303
  });
6249
7304
  return result && callResult;
@@ -6251,16 +7306,22 @@ class PathRegistry {
6251
7306
  const callResult = fn({
6252
7307
  field,
6253
7308
  isClosed: false,
7309
+ isRepeatable: formFieldConfig.repeatable,
6254
7310
  context
6255
7311
  });
6256
7312
  result = result && callResult;
6257
7313
  }
6258
- if (field.components) {
7314
+
7315
+ // stop executing if false is specifically returned or if preventing recursion
7316
+ if (result === false || context.preventRecursion) {
7317
+ return result;
7318
+ }
7319
+ if (Array.isArray(field.components)) {
6259
7320
  for (const child of field.components) {
6260
7321
  const callResult = this.executeRecursivelyOnFields(child, fn, clone(context));
6261
7322
  result = result && callResult;
6262
7323
 
6263
- // only stop executing if false is specifically returned, not if undefined
7324
+ // stop executing if false is specifically returned
6264
7325
  if (result === false) {
6265
7326
  return result;
6266
7327
  }
@@ -6275,6 +7336,7 @@ class PathRegistry {
6275
7336
  * @param {Object} field - The field object with properties: `key`, `path`, `id`, and optionally `_parent`.
6276
7337
  * @param {Object} [options={}] - Configuration options.
6277
7338
  * @param {Object} [options.replacements={}] - A map of field IDs to alternative path arrays.
7339
+ * @param {Object} [options.indexes=null] - A map of parent IDs to the index of the field within said parent, leave null to get an unindexed path.
6278
7340
  * @param {Object} [options.cutoffNode] - The ID of the parent field at which to stop generating the path.
6279
7341
  *
6280
7342
  * @returns {(Array<string>|undefined)} An array of strings representing the binding path, or undefined if not determinable.
@@ -6282,11 +7344,14 @@ class PathRegistry {
6282
7344
  getValuePath(field, options = {}) {
6283
7345
  const {
6284
7346
  replacements = {},
7347
+ indexes = null,
6285
7348
  cutoffNode = null
6286
7349
  } = options;
6287
7350
  let localValuePath = [];
6288
7351
  const hasReplacement = Object.prototype.hasOwnProperty.call(replacements, field.id);
6289
7352
  const formFieldConfig = this._formFields.get(field.type).config;
7353
+
7354
+ // uses path overrides instead of true path to calculate a potential value path
6290
7355
  if (hasReplacement) {
6291
7356
  const replacement = replacements[field.id];
6292
7357
  if (replacement === null || replacement === undefined || replacement === '') {
@@ -6303,6 +7368,13 @@ class PathRegistry {
6303
7368
  } else if (formFieldConfig.pathed && field.path) {
6304
7369
  localValuePath = field.path.split('.');
6305
7370
  }
7371
+
7372
+ // add potential indexes of repeated fields
7373
+ if (indexes) {
7374
+ localValuePath = this._addIndexes(localValuePath, field, indexes);
7375
+ }
7376
+
7377
+ // if parent exists and isn't cutoff node, add parent's value path
6306
7378
  if (field._parent && field._parent !== cutoffNode) {
6307
7379
  const parent = this._formFieldRegistry.get(field._parent);
6308
7380
  return [...(this.getValuePath(parent, options) || []), ...localValuePath];
@@ -6312,6 +7384,13 @@ class PathRegistry {
6312
7384
  clear() {
6313
7385
  this._dataPaths = [];
6314
7386
  }
7387
+ _addIndexes(localValuePath, field, indexes) {
7388
+ const repeatRenderManager = this._injector.get('repeatRenderManager', false);
7389
+ if (repeatRenderManager && repeatRenderManager.isFieldRepeating(field._parent)) {
7390
+ return [indexes[field._parent], ...localValuePath];
7391
+ }
7392
+ return localValuePath;
7393
+ }
6315
7394
  }
6316
7395
  const _getNextSegment = (node, segment) => {
6317
7396
  if (isArray(node.children)) {
@@ -6319,7 +7398,7 @@ const _getNextSegment = (node, segment) => {
6319
7398
  }
6320
7399
  return null;
6321
7400
  };
6322
- PathRegistry.$inject = ['formFieldRegistry', 'formFields'];
7401
+ PathRegistry.$inject = ['formFieldRegistry', 'formFields', 'injector'];
6323
7402
 
6324
7403
  /**
6325
7404
  * @typedef { { id: String, components: Array<String> } } FormRow
@@ -6411,7 +7490,7 @@ class FormLayouter {
6411
7490
  type,
6412
7491
  components
6413
7492
  } = formField;
6414
- if (type !== 'default' && type !== 'group' || !components) {
7493
+ if (!['default', 'group', 'dynamiclist'].includes(type) || !components) {
6415
7494
  return;
6416
7495
  }
6417
7496
 
@@ -6503,6 +7582,9 @@ class FormFieldRegistry {
6503
7582
  getAll() {
6504
7583
  return Object.values(this._formFields);
6505
7584
  }
7585
+ getForm() {
7586
+ return this.getAll().find(formField => formField.type === 'default');
7587
+ }
6506
7588
  forEach(callback) {
6507
7589
  this.getAll().forEach(formField => callback(formField));
6508
7590
  }
@@ -6694,7 +7776,7 @@ class Form {
6694
7776
  schema: importedSchema,
6695
7777
  warnings
6696
7778
  } = this.get('importer').importSchema(schema);
6697
- const initializedData = this._initializeFieldData(clone(data));
7779
+ const initializedData = this._getInitializedFieldData(clone(data));
6698
7780
  this._setState({
6699
7781
  data: initializedData,
6700
7782
  errors: {},
@@ -6750,26 +7832,68 @@ class Form {
6750
7832
  * @returns {Errors}
6751
7833
  */
6752
7834
  validate() {
6753
- const formFieldRegistry = this.get('formFieldRegistry'),
7835
+ const formFields = this.get('formFields'),
7836
+ formFieldRegistry = this.get('formFieldRegistry'),
6754
7837
  pathRegistry = this.get('pathRegistry'),
6755
7838
  validator = this.get('validator');
6756
7839
  const {
6757
7840
  data
6758
7841
  } = this._getState();
6759
- const getErrorPath = field => [field.id];
6760
- const errors = formFieldRegistry.getAll().reduce((errors, field) => {
7842
+ const getErrorPath = (field, indexes) => [field.id, ...Object.values(indexes || {})];
7843
+ function validateFieldRecursively(errors, field, indexes) {
6761
7844
  const {
6762
- disabled
7845
+ disabled,
7846
+ type,
7847
+ isRepeating
6763
7848
  } = field;
7849
+ const {
7850
+ config: fieldConfig
7851
+ } = formFields.get(type);
7852
+
7853
+ // (1) Skip disabled fields
6764
7854
  if (disabled) {
6765
- return errors;
7855
+ return;
7856
+ }
7857
+
7858
+ // (2) Validate the field
7859
+ const valuePath = pathRegistry.getValuePath(field, {
7860
+ indexes
7861
+ });
7862
+ const valueData = get(data, valuePath);
7863
+ const fieldErrors = validator.validateField(field, valueData);
7864
+ if (fieldErrors.length) {
7865
+ set(errors, getErrorPath(field, indexes), fieldErrors);
7866
+ }
7867
+
7868
+ // (3) Process parents
7869
+ if (!Array.isArray(field.components)) {
7870
+ return;
7871
+ }
7872
+
7873
+ // (4a) Recurse repeatable parents both across the indexes of repetition and the children
7874
+ if (fieldConfig.repeatable && isRepeating) {
7875
+ if (!Array.isArray(valueData)) {
7876
+ return;
7877
+ }
7878
+ valueData.forEach((_, index) => {
7879
+ field.components.forEach(component => {
7880
+ validateFieldRecursively(errors, component, {
7881
+ ...indexes,
7882
+ [field.id]: index
7883
+ });
7884
+ });
7885
+ });
7886
+ return;
6766
7887
  }
6767
- const value = get(data, pathRegistry.getValuePath(field));
6768
- const fieldErrors = validator.validateField(field, value);
6769
- return set(errors, getErrorPath(field), fieldErrors.length ? fieldErrors : undefined);
6770
- }, /** @type {Errors} */{});
6771
- const filteredErrors = this._applyConditions(errors, data, {
6772
- getFilterPath: getErrorPath
7888
+
7889
+ // (4b) Recurse non-repeatable parents only across the children
7890
+ field.components.forEach(component => validateFieldRecursively(errors, component, indexes));
7891
+ }
7892
+ const workingErrors = {};
7893
+ validateFieldRecursively(workingErrors, formFieldRegistry.getForm());
7894
+ const filteredErrors = this._applyConditions(workingErrors, data, {
7895
+ getFilterPath: getErrorPath,
7896
+ leafNodeDeletionOnly: true
6773
7897
  });
6774
7898
  this._setState({
6775
7899
  errors: filteredErrors
@@ -6867,11 +7991,12 @@ class Form {
6867
7991
  /**
6868
7992
  * @internal
6869
7993
  *
6870
- * @param { { add?: boolean, field: any, remove?: number, value?: any } } update
7994
+ * @param { { add?: boolean, field: any, indexes: object, remove?: number, value?: any } } update
6871
7995
  */
6872
7996
  _update(update) {
6873
7997
  const {
6874
7998
  field,
7999
+ indexes,
6875
8000
  value
6876
8001
  } = update;
6877
8002
  const {
@@ -6881,8 +8006,11 @@ class Form {
6881
8006
  const validator = this.get('validator'),
6882
8007
  pathRegistry = this.get('pathRegistry');
6883
8008
  const fieldErrors = validator.validateField(field, value);
6884
- set(data, pathRegistry.getValuePath(field), value);
6885
- set(errors, [field.id], fieldErrors.length ? fieldErrors : undefined);
8009
+ const valuePath = pathRegistry.getValuePath(field, {
8010
+ indexes
8011
+ });
8012
+ set(data, valuePath, value);
8013
+ set(errors, [field.id, ...Object.values(indexes || {})], fieldErrors.length ? fieldErrors : undefined);
6886
8014
  this._setState({
6887
8015
  data: clone(data),
6888
8016
  errors: clone(errors)
@@ -6911,7 +8039,7 @@ class Form {
6911
8039
  * @internal
6912
8040
  */
6913
8041
  _getModules() {
6914
- return [ExpressionLanguageModule, MarkdownModule, ViewerCommandsModule];
8042
+ return [ExpressionLanguageModule, MarkdownModule, ViewerCommandsModule, RepeatRenderModule];
6915
8043
  }
6916
8044
 
6917
8045
  /**
@@ -6925,29 +8053,58 @@ class Form {
6925
8053
  * @internal
6926
8054
  */
6927
8055
  _getSubmitData() {
6928
- const formFieldRegistry = this.get('formFieldRegistry'),
6929
- pathRegistry = this.get('pathRegistry'),
6930
- formFields = this.get('formFields');
8056
+ const formFieldRegistry = this.get('formFieldRegistry');
8057
+ const formFields = this.get('formFields');
8058
+ const pathRegistry = this.get('pathRegistry');
6931
8059
  const formData = this._getState().data;
6932
- const submitData = formFieldRegistry.getAll().reduce((previous, field) => {
8060
+ function collectSubmitDataRecursively(submitData, formField, indexes) {
6933
8061
  const {
6934
8062
  disabled,
6935
8063
  type
6936
- } = field;
8064
+ } = formField;
6937
8065
  const {
6938
8066
  config: fieldConfig
6939
8067
  } = formFields.get(type);
6940
8068
 
6941
- // do not submit disabled form fields or routing fields
6942
- if (disabled || !fieldConfig.keyed) {
6943
- return previous;
8069
+ // (1) Process keyed fields
8070
+ if (!disabled && fieldConfig.keyed) {
8071
+ const valuePath = pathRegistry.getValuePath(formField, {
8072
+ indexes
8073
+ });
8074
+ const value = get(formData, valuePath);
8075
+ set(submitData, valuePath, value);
8076
+ }
8077
+
8078
+ // (2) Process parents
8079
+ if (!Array.isArray(formField.components)) {
8080
+ return;
8081
+ }
8082
+
8083
+ // (3a) Recurse repeatable parents both across the indexes of repetition and the children
8084
+ if (fieldConfig.repeatable && formField.isRepeating) {
8085
+ const valueData = get(formData, pathRegistry.getValuePath(formField, {
8086
+ indexes
8087
+ }));
8088
+ if (!Array.isArray(valueData)) {
8089
+ return;
8090
+ }
8091
+ valueData.forEach((_, index) => {
8092
+ formField.components.forEach(component => {
8093
+ collectSubmitDataRecursively(submitData, component, {
8094
+ ...indexes,
8095
+ [formField.id]: index
8096
+ });
8097
+ });
8098
+ });
8099
+ return;
6944
8100
  }
6945
- const valuePath = pathRegistry.getValuePath(field);
6946
- const value = get(formData, valuePath);
6947
- return set(previous, valuePath, value);
6948
- }, {});
6949
- const filteredSubmitData = this._applyConditions(submitData, formData);
6950
- return filteredSubmitData;
8101
+
8102
+ // (3b) Recurse non-repeatable parents only across the children
8103
+ formField.components.forEach(component => collectSubmitDataRecursively(submitData, component, indexes));
8104
+ }
8105
+ const workingSubmitData = {};
8106
+ collectSubmitDataRecursively(workingSubmitData, formFieldRegistry.getForm(), {});
8107
+ return this._applyConditions(workingSubmitData, formData);
6951
8108
  }
6952
8109
 
6953
8110
  /**
@@ -6961,26 +8118,27 @@ class Form {
6961
8118
  /**
6962
8119
  * @internal
6963
8120
  */
6964
- _initializeFieldData(data) {
6965
- const formFieldRegistry = this.get('formFieldRegistry'),
6966
- formFields = this.get('formFields'),
6967
- pathRegistry = this.get('pathRegistry');
6968
- return formFieldRegistry.getAll().reduce((initializedData, formField) => {
8121
+ _getInitializedFieldData(data, options = {}) {
8122
+ const formFieldRegistry = this.get('formFieldRegistry');
8123
+ const formFields = this.get('formFields');
8124
+ const pathRegistry = this.get('pathRegistry');
8125
+ function initializeFieldDataRecursively(initializedData, formField, indexes) {
6969
8126
  const {
6970
8127
  defaultValue,
6971
- type
8128
+ type,
8129
+ isRepeating
6972
8130
  } = formField;
8131
+ const {
8132
+ config: fieldConfig
8133
+ } = formFields.get(type);
8134
+ const valuePath = pathRegistry.getValuePath(formField, {
8135
+ indexes
8136
+ });
8137
+ let valueData = get(data, valuePath);
6973
8138
 
6974
- // try to get value from data
6975
- // if unavailable - try to get default value from form field
6976
- // if unavailable - get empty value from form field
6977
-
6978
- const valuePath = pathRegistry.getValuePath(formField);
6979
- if (valuePath) {
6980
- const {
6981
- config: fieldConfig
6982
- } = formFields.get(type);
6983
- let valueData = get(data, valuePath);
8139
+ // (1) Process keyed fields
8140
+ if (fieldConfig.keyed) {
8141
+ // (a) Retrieve and sanitize data from input
6984
8142
  if (!isUndefined(valueData) && fieldConfig.sanitizeValue) {
6985
8143
  valueData = fieldConfig.sanitizeValue({
6986
8144
  formField,
@@ -6988,15 +8146,66 @@ class Form {
6988
8146
  value: valueData
6989
8147
  });
6990
8148
  }
8149
+
8150
+ // (b) Initialize field value in output data
6991
8151
  const initializedFieldValue = !isUndefined(valueData) ? valueData : !isUndefined(defaultValue) ? defaultValue : fieldConfig.emptyValue;
6992
- return set(initializedData, valuePath, initializedFieldValue);
8152
+ set(initializedData, valuePath, initializedFieldValue);
8153
+ }
8154
+
8155
+ // (2) Process parents
8156
+ if (!Array.isArray(formField.components)) {
8157
+ return;
8158
+ }
8159
+ if (fieldConfig.repeatable && isRepeating) {
8160
+ // (a) Sanitize repeatable parents data if it is not an array
8161
+ if (!valueData || !Array.isArray(valueData)) {
8162
+ valueData = new Array(isUndefined(formField.defaultRepetitions) ? 1 : formField.defaultRepetitions).fill().map(_ => ({})) || [];
8163
+ }
8164
+
8165
+ // (b) Ensure all elements of the array are objects
8166
+ valueData = valueData.map(val => isObject(val) ? val : {});
8167
+
8168
+ // (c) Initialize field value in output data
8169
+ set(initializedData, valuePath, valueData);
8170
+
8171
+ // (d) If indexed ahead of time, recurse repeatable simply across the children
8172
+ if (!isUndefined(indexes[formField.id])) {
8173
+ formField.components.forEach(component => initializeFieldDataRecursively(initializedData, component, {
8174
+ ...indexes
8175
+ }));
8176
+ return;
8177
+ }
8178
+
8179
+ // (e1) Recurse repeatable parents both across the indexes of repetition and the children
8180
+ valueData.forEach((_, index) => {
8181
+ formField.components.forEach(component => initializeFieldDataRecursively(initializedData, component, {
8182
+ ...indexes,
8183
+ [formField.id]: index
8184
+ }));
8185
+ });
8186
+ return;
6993
8187
  }
6994
- return initializedData;
6995
- }, data);
8188
+
8189
+ // (e2) Recurse non-repeatable parents only across the children
8190
+ formField.components.forEach(component => initializeFieldDataRecursively(initializedData, component, indexes));
8191
+ }
8192
+
8193
+ // allows definition of a specific subfield to generate the data for
8194
+ const container = options.container || formFieldRegistry.getForm();
8195
+ const indexes = options.indexes || {};
8196
+ const basePath = pathRegistry.getValuePath(container, {
8197
+ indexes
8198
+ }) || [];
8199
+
8200
+ // if indexing ahead of time, we must add this index to the data path at the end
8201
+ const path = !isUndefined(indexes[container.id]) ? [...basePath, indexes[container.id]] : basePath;
8202
+ const workingData = clone(data);
8203
+ initializeFieldDataRecursively(workingData, container, indexes);
8204
+ return get(workingData, path, {});
6996
8205
  }
6997
8206
  }
6998
8207
 
6999
- const schemaVersion = 13;
8208
+ const schemaVersion = 14;
7000
8209
 
7001
8210
  /**
7002
8211
  * @typedef { import('./types').CreateFormOptions } CreateFormOptions
@@ -7021,5 +8230,5 @@ function createForm(options) {
7021
8230
  });
7022
8231
  }
7023
8232
 
7024
- export { Button, Checkbox, Checklist, ConditionChecker, DATETIME_SUBTYPES, DATETIME_SUBTYPES_LABELS, DATETIME_SUBTYPE_PATH, DATE_DISALLOW_PAST_PATH, DATE_LABEL_PATH, Datetime, FormComponent$1 as Default, Description, Errors, ExpressionLanguageModule, FeelExpressionLanguage, FeelersTemplating, FieldFactory, Form, FormComponent, FormContext$1 as FormContext, FormField, FormFieldRegistry, FormFields, FormLayouter, FormRenderContext$1 as FormRenderContext, Group, IFrame, Image, Importer, Label, MINUTES_IN_DAY, MarkdownModule, MarkdownRenderer, Numberfield, PathRegistry, Radio, Select, Separator, Spacer, TIME_INTERVAL_PATH, TIME_LABEL_PATH, TIME_SERIALISINGFORMAT_LABELS, TIME_SERIALISING_FORMATS, TIME_SERIALISING_FORMAT_PATH, TIME_USE24H_PATH, Taglist, Text, Textarea, Textfield, VALUES_SOURCES, VALUES_SOURCES_DEFAULTS, VALUES_SOURCES_LABELS, VALUES_SOURCES_PATHS, VALUES_SOURCE_DEFAULT, ViewerCommands, ViewerCommandsModule, clone, createForm, createFormContainer, createInjector, formFields, generateIdForType, generateIndexForType, getSchemaVariables, getValuesSource, iconsByType, isRequired, pathParse, pathsEqual, runRecursively, sanitizeHTML, sanitizeIFrameSource, sanitizeImageSource, schemaVersion, useExpressionEvaluation, useSingleLineTemplateEvaluation, useTemplateEvaluation };
8233
+ export { Button, Checkbox, Checklist, ConditionChecker, DATETIME_SUBTYPES, DATETIME_SUBTYPES_LABELS, DATETIME_SUBTYPE_PATH, DATE_DISALLOW_PAST_PATH, DATE_LABEL_PATH, Datetime, FormComponent$1 as Default, Description, DynamicList, Errors, ExpressionLanguageModule, FeelExpressionLanguage, FeelersTemplating, FieldFactory, Form, FormComponent, FormContext$1 as FormContext, FormField, FormFieldRegistry, FormFields, FormLayouter, FormRenderContext$1 as FormRenderContext, Group, IFrame, Image, Importer, Label, LocalExpressionContext$1 as LocalExpressionContext, MINUTES_IN_DAY, MarkdownModule, MarkdownRenderer, Numberfield, OPTIONS_SOURCES, OPTIONS_SOURCES_DEFAULTS, OPTIONS_SOURCES_LABELS, OPTIONS_SOURCES_PATHS, OPTIONS_SOURCE_DEFAULT, PathRegistry, Radio, RepeatRenderManager, RepeatRenderModule, Select, Separator, Spacer, TIME_INTERVAL_PATH, TIME_LABEL_PATH, TIME_SERIALISINGFORMAT_LABELS, TIME_SERIALISING_FORMATS, TIME_SERIALISING_FORMAT_PATH, TIME_USE24H_PATH, Table, Taglist, Text, Textarea, Textfield, ViewerCommands, ViewerCommandsModule, buildExpressionContext, clone, createForm, createFormContainer, createInjector, formFields, generateIdForType, generateIndexForType, getAncestryList, getOptionsSource, getSchemaVariables, iconsByType, isRequired, pathParse, pathsEqual, runRecursively, sanitizeHTML, sanitizeIFrameSource, sanitizeImageSource, schemaVersion, useExpressionEvaluation, useSingleLineTemplateEvaluation, useTemplateEvaluation };
7025
8234
  //# sourceMappingURL=index.es.js.map