@bpmn-io/form-js-viewer 0.10.0-alpha.3 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/LICENSE +22 -22
  2. package/README.md +165 -164
  3. package/dist/assets/flatpickr/light.css +809 -0
  4. package/dist/assets/form-js.css +611 -498
  5. package/dist/index.cjs +1493 -369
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.es.js +1475 -372
  8. package/dist/index.es.js.map +1 -1
  9. package/dist/types/Form.d.ts +144 -144
  10. package/dist/types/core/ConditionChecker.d.ts +57 -57
  11. package/dist/types/core/EventBus.d.ts +1 -1
  12. package/dist/types/core/FormFieldRegistry.d.ts +17 -17
  13. package/dist/types/core/Validator.d.ts +7 -7
  14. package/dist/types/core/index.d.ts +18 -18
  15. package/dist/types/import/Importer.d.ts +43 -43
  16. package/dist/types/import/index.d.ts +5 -5
  17. package/dist/types/index.d.ts +18 -18
  18. package/dist/types/render/FormFields.d.ts +5 -5
  19. package/dist/types/render/Renderer.d.ts +23 -23
  20. package/dist/types/render/components/Description.d.ts +1 -1
  21. package/dist/types/render/components/Errors.d.ts +1 -1
  22. package/dist/types/render/components/FormComponent.d.ts +1 -1
  23. package/dist/types/render/components/FormField.d.ts +1 -1
  24. package/dist/types/render/components/Label.d.ts +1 -1
  25. package/dist/types/render/components/PoweredBy.d.ts +1 -1
  26. package/dist/types/render/components/Sanitizer.d.ts +8 -8
  27. package/dist/types/render/components/Util.d.ts +17 -19
  28. package/dist/types/render/components/form-fields/Button.d.ts +11 -11
  29. package/dist/types/render/components/form-fields/Checkbox.d.ts +13 -13
  30. package/dist/types/render/components/form-fields/Checklist.d.ts +12 -12
  31. package/dist/types/render/components/form-fields/Datetime.d.ts +11 -0
  32. package/dist/types/render/components/form-fields/Default.d.ts +9 -9
  33. package/dist/types/render/components/form-fields/Image.d.ts +8 -8
  34. package/dist/types/render/components/form-fields/Number.d.ts +14 -14
  35. package/dist/types/render/components/form-fields/Radio.d.ts +12 -12
  36. package/dist/types/render/components/form-fields/Select.d.ts +12 -12
  37. package/dist/types/render/components/form-fields/Taglist.d.ts +12 -12
  38. package/dist/types/render/components/form-fields/Text.d.ts +10 -10
  39. package/dist/types/render/components/form-fields/Textarea.d.ts +13 -13
  40. package/dist/types/render/components/form-fields/Textfield.d.ts +13 -13
  41. package/dist/types/render/components/form-fields/parts/Datepicker.d.ts +1 -0
  42. package/dist/types/render/components/form-fields/parts/DropdownList.d.ts +1 -1
  43. package/dist/types/render/components/form-fields/parts/InputAdorner.d.ts +1 -0
  44. package/dist/types/render/components/form-fields/parts/Timepicker.d.ts +1 -0
  45. package/dist/types/render/components/icons/index.d.ts +16 -0
  46. package/dist/types/render/components/index.d.ts +17 -15
  47. package/dist/types/render/components/util/dateTimeUtil.d.ts +12 -0
  48. package/dist/types/render/components/util/numberFieldUtil.d.ts +4 -4
  49. package/dist/types/render/components/util/sanitizerUtil.d.ts +3 -0
  50. package/dist/types/render/context/FormContext.d.ts +12 -12
  51. package/dist/types/render/context/FormRenderContext.d.ts +6 -6
  52. package/dist/types/render/context/index.d.ts +2 -2
  53. package/dist/types/render/hooks/useCondition.d.ts +9 -9
  54. package/dist/types/render/hooks/useEvaluation.d.ts +6 -6
  55. package/dist/types/render/hooks/useExpressionValue.d.ts +5 -5
  56. package/dist/types/render/hooks/useKeyDownAction.d.ts +1 -1
  57. package/dist/types/render/hooks/useService.d.ts +1 -1
  58. package/dist/types/render/hooks/useValuesAsync.d.ts +28 -28
  59. package/dist/types/render/index.d.ts +11 -11
  60. package/dist/types/src/types.d.ts +35 -35
  61. package/dist/types/util/constants/DatetimeConstants.d.ts +24 -0
  62. package/dist/types/util/constants/ValuesSourceConstants.d.ts +15 -0
  63. package/dist/types/util/constants/index.d.ts +2 -0
  64. package/dist/types/util/feel.d.ts +15 -14
  65. package/dist/types/util/form.d.ts +6 -6
  66. package/dist/types/util/index.d.ts +25 -24
  67. package/dist/types/util/injector.d.ts +2 -2
  68. package/package.json +4 -2
package/dist/index.es.js CHANGED
@@ -1,19 +1,20 @@
1
1
  import Ids from 'ids';
2
- import { isString, isArray, isFunction, isNumber, bind, assign, isNil, get, isUndefined, isObject, set } from 'min-dash';
2
+ import { isString, isArray, isFunction, isNumber, bind, assign, isNil, get, isUndefined, set, isObject } from 'min-dash';
3
3
  import { unaryTest, evaluate, parseUnaryTests, parseExpressions } from 'feelin';
4
4
  import Big from 'big.js';
5
5
  import snarkdown from '@bpmn-io/snarkdown';
6
6
  import classNames from 'classnames';
7
7
  import { jsx, jsxs } from 'preact/jsx-runtime';
8
- import { useContext, useState, useEffect, useRef, useMemo, useCallback } from 'preact/hooks';
8
+ import { useContext, useState, useEffect, useRef, useCallback, useMemo } from 'preact/hooks';
9
9
  import { createContext, createElement, Fragment, render } from 'preact';
10
10
  import React, { createPortal } from 'preact/compat';
11
+ import flatpickr from 'flatpickr';
11
12
  import Markup from 'preact-markup';
12
13
  import { Injector } from 'didi';
13
14
 
14
- /**
15
- * @typedef {object} Condition
16
- * @property {string} [hide]
15
+ /**
16
+ * @typedef {object} Condition
17
+ * @property {string} [hide]
17
18
  */
18
19
 
19
20
  class ConditionChecker {
@@ -22,11 +23,11 @@ class ConditionChecker {
22
23
  this._eventBus = eventBus;
23
24
  }
24
25
 
25
- /**
26
- * For given data, remove properties based on condition.
27
- *
28
- * @param {Object<string, any>} properties
29
- * @param {Object<string, any>} data
26
+ /**
27
+ * For given data, remove properties based on condition.
28
+ *
29
+ * @param {Object<string, any>} properties
30
+ * @param {Object<string, any>} data
30
31
  */
31
32
  applyConditions(properties, data = {}) {
32
33
  const conditions = this._getConditions();
@@ -45,13 +46,13 @@ class ConditionChecker {
45
46
  return newProperties;
46
47
  }
47
48
 
48
- /**
49
- * Check if given condition is met. Returns null for invalid/missing conditions.
50
- *
51
- * @param {string} condition
52
- * @param {import('../types').Data} [data]
53
- *
54
- * @returns {boolean|null}
49
+ /**
50
+ * Check if given condition is met. Returns null for invalid/missing conditions.
51
+ *
52
+ * @param {string} condition
53
+ * @param {import('../types').Data} [data]
54
+ *
55
+ * @returns {boolean|null}
55
56
  */
56
57
  check(condition, data = {}) {
57
58
  if (!condition) {
@@ -72,12 +73,12 @@ class ConditionChecker {
72
73
  }
73
74
  }
74
75
 
75
- /**
76
- * Check if hide condition is met.
77
- *
78
- * @param {Condition} condition
79
- * @param {Object<string, any>} data
80
- * @returns {boolean}
76
+ /**
77
+ * Check if hide condition is met.
78
+ *
79
+ * @param {Condition} condition
80
+ * @param {Object<string, any>} data
81
+ * @returns {boolean}
81
82
  */
82
83
  _checkHideCondition(condition, data) {
83
84
  if (!condition.hide) {
@@ -87,13 +88,13 @@ class ConditionChecker {
87
88
  return result === true;
88
89
  }
89
90
 
90
- /**
91
- * Evaluate an expression.
92
- *
93
- * @param {string} expression
94
- * @param {import('../types').Data} [data]
95
- *
96
- * @returns {any}
91
+ /**
92
+ * Evaluate an expression.
93
+ *
94
+ * @param {string} expression
95
+ * @param {import('../types').Data} [data]
96
+ *
97
+ * @returns {any}
97
98
  */
98
99
  evaluate(expression, data = {}) {
99
100
  if (!expression) {
@@ -702,11 +703,11 @@ class FormFieldRegistry {
702
703
  }
703
704
  FormFieldRegistry.$inject = ['eventBus'];
704
705
 
705
- /**
706
- * Retrieve variable names from given FEEL unary test.
707
- *
708
- * @param {string} unaryTest
709
- * @returns {string[]}
706
+ /**
707
+ * Retrieve variable names from given FEEL unary test.
708
+ *
709
+ * @param {string} unaryTest
710
+ * @returns {string[]}
710
711
  */
711
712
  function getVariableNames(unaryTest) {
712
713
  const tree = parseUnaryTests(unaryTest);
@@ -721,11 +722,11 @@ function getVariableNames(unaryTest) {
721
722
  return Array.from(variables);
722
723
  }
723
724
 
724
- /**
725
- * Retrieve variable names from given FEEL expression.
726
- *
727
- * @param {string} expression
728
- * @returns {string[]}
725
+ /**
726
+ * Retrieve variable names from given FEEL expression.
727
+ *
728
+ * @param {string} expression
729
+ * @returns {string[]}
729
730
  */
730
731
  function getExpressionVariableNames(expression) {
731
732
  const tree = parseExpressions(expression);
@@ -739,6 +740,71 @@ function getExpressionVariableNames(expression) {
739
740
  } while (cursor.next());
740
741
  return Array.from(variables);
741
742
  }
743
+ function isExpression$2(value) {
744
+ return isString(value) && value.startsWith('=');
745
+ }
746
+
747
+ // config ///////////////////
748
+
749
+ const MINUTES_IN_DAY = 60 * 24;
750
+ const DATETIME_SUBTYPES = {
751
+ DATE: 'date',
752
+ TIME: 'time',
753
+ DATETIME: 'datetime'
754
+ };
755
+ const TIME_SERIALISING_FORMATS = {
756
+ UTC_OFFSET: 'utc_offset',
757
+ UTC_NORMALIZED: 'utc_normalized',
758
+ NO_TIMEZONE: 'no_timezone'
759
+ };
760
+ const DATETIME_SUBTYPES_LABELS = {
761
+ [DATETIME_SUBTYPES.DATE]: 'Date',
762
+ [DATETIME_SUBTYPES.TIME]: 'Time',
763
+ [DATETIME_SUBTYPES.DATETIME]: 'Date & Time'
764
+ };
765
+ const TIME_SERIALISINGFORMAT_LABELS = {
766
+ [TIME_SERIALISING_FORMATS.UTC_OFFSET]: 'UTC offset',
767
+ [TIME_SERIALISING_FORMATS.UTC_NORMALIZED]: 'UTC normalized',
768
+ [TIME_SERIALISING_FORMATS.NO_TIMEZONE]: 'No timezone'
769
+ };
770
+ const DATETIME_SUBTYPE_PATH = ['subtype'];
771
+ const DATE_LABEL_PATH = ['dateLabel'];
772
+ const DATE_DISALLOW_PAST_PATH = ['disallowPassedDates'];
773
+ const TIME_LABEL_PATH = ['timeLabel'];
774
+ const TIME_USE24H_PATH = ['use24h'];
775
+ const TIME_INTERVAL_PATH = ['timeInterval'];
776
+ const TIME_SERIALISING_FORMAT_PATH = ['timeSerializingFormat'];
777
+
778
+ // config ///////////////////
779
+
780
+ const VALUES_SOURCES = {
781
+ STATIC: 'static',
782
+ INPUT: 'input'
783
+ };
784
+ const VALUES_SOURCE_DEFAULT = VALUES_SOURCES.STATIC;
785
+ const VALUES_SOURCES_LABELS = {
786
+ [VALUES_SOURCES.STATIC]: 'Static',
787
+ [VALUES_SOURCES.INPUT]: 'Input data'
788
+ };
789
+ const VALUES_SOURCES_PATHS = {
790
+ [VALUES_SOURCES.STATIC]: ['values'],
791
+ [VALUES_SOURCES.INPUT]: ['valuesKey']
792
+ };
793
+ const VALUES_SOURCES_DEFAULTS = {
794
+ [VALUES_SOURCES.STATIC]: [],
795
+ [VALUES_SOURCES.INPUT]: ''
796
+ };
797
+
798
+ // helpers ///////////////////
799
+
800
+ function getValuesSource(field) {
801
+ for (const source of Object.values(VALUES_SOURCES)) {
802
+ if (get(field, VALUES_SOURCES_PATHS[source]) !== undefined) {
803
+ return source;
804
+ }
805
+ }
806
+ return VALUES_SOURCE_DEFAULT;
807
+ }
742
808
 
743
809
  function createInjector(bootstrapModules) {
744
810
  const injector = new Injector(bootstrapModules);
@@ -746,10 +812,10 @@ function createInjector(bootstrapModules) {
746
812
  return injector;
747
813
  }
748
814
 
749
- /**
750
- * @param {string?} prefix
751
- *
752
- * @returns Element
815
+ /**
816
+ * @param {string?} prefix
817
+ *
818
+ * @returns Element
753
819
  */
754
820
  function createFormContainer(prefix = 'fjs') {
755
821
  const container = document.createElement('div');
@@ -757,7 +823,7 @@ function createFormContainer(prefix = 'fjs') {
757
823
  return container;
758
824
  }
759
825
 
760
- const EXPRESSION_PROPERTIES = ['alt', 'source'];
826
+ const EXPRESSION_PROPERTIES = ['alt', 'source', 'text'];
761
827
  function findErrors(errors, path) {
762
828
  return errors[pathStringify(path)];
763
829
  }
@@ -794,22 +860,22 @@ function generateIdForType(type) {
794
860
  return `${type}${generateIndexForType(type)}`;
795
861
  }
796
862
 
797
- /**
798
- * @template T
799
- * @param {T} data
800
- * @param {(this: any, key: string, value: any) => any} [replacer]
801
- * @return {T}
863
+ /**
864
+ * @template T
865
+ * @param {T} data
866
+ * @param {(this: any, key: string, value: any) => any} [replacer]
867
+ * @return {T}
802
868
  */
803
869
  function clone(data, replacer) {
804
870
  return JSON.parse(JSON.stringify(data, replacer));
805
871
  }
806
872
 
807
- /**
808
- * Parse the schema for input variables a form might make use of
809
- *
810
- * @param {any} schema
811
- *
812
- * @return {string[]}
873
+ /**
874
+ * Parse the schema for input variables a form might make use of
875
+ *
876
+ * @param {any} schema
877
+ *
878
+ * @return {string[]}
813
879
  */
814
880
  function getSchemaVariables(schema) {
815
881
  if (!schema.components) {
@@ -822,7 +888,7 @@ function getSchemaVariables(schema) {
822
888
  type,
823
889
  conditional
824
890
  } = component;
825
- if (['text', 'button'].includes(type)) {
891
+ if (['button'].includes(type)) {
826
892
  return variables;
827
893
  }
828
894
  if (key) {
@@ -858,25 +924,25 @@ function isExpression$1(value) {
858
924
  }
859
925
 
860
926
  class Importer {
861
- /**
862
- * @constructor
863
- * @param { import('../core').FormFieldRegistry } formFieldRegistry
864
- * @param { import('../render/FormFields').default } formFields
927
+ /**
928
+ * @constructor
929
+ * @param { import('../core').FormFieldRegistry } formFieldRegistry
930
+ * @param { import('../render/FormFields').default } formFields
865
931
  */
866
932
  constructor(formFieldRegistry, formFields) {
867
933
  this._formFieldRegistry = formFieldRegistry;
868
934
  this._formFields = formFields;
869
935
  }
870
936
 
871
- /**
872
- * Import schema adding `id`, `_parent` and `_path`
873
- * information to each field and adding it to the
874
- * form field registry.
875
- *
876
- * @param {any} schema
877
- * @param {any} [data]
878
- *
879
- * @return { { warnings: Array<any>, schema: any, data: any } }
937
+ /**
938
+ * Import schema adding `id`, `_parent` and `_path`
939
+ * information to each field and adding it to the
940
+ * form field registry.
941
+ *
942
+ * @param {any} schema
943
+ * @param {any} [data]
944
+ *
945
+ * @return { { warnings: Array<any>, schema: any, data: any } }
880
946
  */
881
947
  importSchema(schema, data = {}) {
882
948
  // TODO: Add warnings - https://github.com/bpmn-io/form-js/issues/289
@@ -895,11 +961,11 @@ class Importer {
895
961
  }
896
962
  }
897
963
 
898
- /**
899
- * @param {any} formField
900
- * @param {string} [parentId]
901
- *
902
- * @return {any} importedField
964
+ /**
965
+ * @param {any} formField
966
+ * @param {string} [parentId]
967
+ *
968
+ * @return {any} importedField
903
969
  */
904
970
  importFormField(formField, parentId) {
905
971
  const {
@@ -950,10 +1016,10 @@ class Importer {
950
1016
  });
951
1017
  }
952
1018
 
953
- /**
954
- * @param {Object} data
955
- *
956
- * @return {Object} initializedData
1019
+ /**
1020
+ * @param {Object} data
1021
+ *
1022
+ * @return {Object} initializedData
957
1023
  */
958
1024
  initializeFieldValues(data) {
959
1025
  return this._formFieldRegistry.getAll().reduce((initializedData, formField) => {
@@ -995,7 +1061,7 @@ var importModule = {
995
1061
 
996
1062
  const NODE_TYPE_TEXT = 3,
997
1063
  NODE_TYPE_ELEMENT = 1;
998
- const ALLOWED_NODES = ['h1', 'h2', 'h3', 'h4', 'h5', 'span', 'em', 'a', 'p', 'div', 'ul', 'ol', 'li', 'hr', 'blockquote', 'img', 'pre', 'code', 'br', 'strong'];
1064
+ const ALLOWED_NODES = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span', 'em', 'a', 'p', 'div', 'ul', 'ol', 'li', 'hr', 'blockquote', 'img', 'pre', 'code', 'br', 'strong'];
999
1065
  const ALLOWED_ATTRIBUTES = ['align', 'alt', 'class', 'href', 'id', 'name', 'rel', 'target', 'src'];
1000
1066
  const ALLOWED_URI_PATTERN = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i; // eslint-disable-line no-useless-escape
1001
1067
  const ALLOWED_IMAGE_SRC_PATTERN = /^(https?|data):.*/i; // eslint-disable-line no-useless-escape
@@ -1003,11 +1069,11 @@ const ATTR_WHITESPACE_PATTERN = /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u
1003
1069
 
1004
1070
  const FORM_ELEMENT = document.createElement('form');
1005
1071
 
1006
- /**
1007
- * Sanitize a HTML string and return the cleaned, safe version.
1008
- *
1009
- * @param {string} html
1010
- * @return {string}
1072
+ /**
1073
+ * Sanitize a HTML string and return the cleaned, safe version.
1074
+ *
1075
+ * @param {string} html
1076
+ * @return {string}
1011
1077
  */
1012
1078
  function sanitizeHTML(html) {
1013
1079
  const doc = new DOMParser().parseFromString(`<!DOCTYPE html>\n<html><body><div>${html}`, 'text/html');
@@ -1027,15 +1093,15 @@ function sanitizeImageSource(src) {
1027
1093
  return valid ? src : '';
1028
1094
  }
1029
1095
 
1030
- /**
1031
- * Recursively sanitize a HTML node, potentially
1032
- * removing it, its children or attributes.
1033
- *
1034
- * Inspired by https://github.com/developit/snarkdown/issues/70
1035
- * and https://github.com/cure53/DOMPurify. Simplified
1036
- * for our use-case.
1037
- *
1038
- * @param {Element} node
1096
+ /**
1097
+ * Recursively sanitize a HTML node, potentially
1098
+ * removing it, its children or attributes.
1099
+ *
1100
+ * Inspired by https://github.com/developit/snarkdown/issues/70
1101
+ * and https://github.com/cure53/DOMPurify. Simplified
1102
+ * for our use-case.
1103
+ *
1104
+ * @param {Element} node
1039
1105
  */
1040
1106
  function sanitizeNode(node) {
1041
1107
  // allow text nodes
@@ -1079,13 +1145,13 @@ function sanitizeNode(node) {
1079
1145
  }
1080
1146
  }
1081
1147
 
1082
- /**
1083
- * Validates attributes for validity.
1084
- *
1085
- * @param {string} lcTag
1086
- * @param {string} lcName
1087
- * @param {string} value
1088
- * @return {boolean}
1148
+ /**
1149
+ * Validates attributes for validity.
1150
+ *
1151
+ * @param {string} lcTag
1152
+ * @param {string} lcName
1153
+ * @param {string} value
1154
+ * @return {boolean}
1089
1155
  */
1090
1156
  function isValidAttribute(lcTag, lcName, value) {
1091
1157
  // disallow most attributes based on whitelist
@@ -1127,7 +1193,7 @@ function prefixId(id, formId) {
1127
1193
  return `fjs-form-${id}`;
1128
1194
  }
1129
1195
  function markdownToHTML(markdown) {
1130
- const htmls = markdown.split(/(?:\r?\n){2,}/).map(line => /^((\d+.)|[><\s#-*])/.test(line) ? snarkdown(line) : `<p>${snarkdown(line)}</p>`);
1196
+ const htmls = markdown.toString().split(/(?:\r?\n){2,}/).map(line => /^((\d+.)|[><\s#-*])/.test(line) ? snarkdown(line) : `<p>${snarkdown(line)}</p>`);
1131
1197
  return htmls.join('\n\n');
1132
1198
  }
1133
1199
 
@@ -1137,58 +1203,20 @@ function safeMarkdown(markdown) {
1137
1203
  return sanitizeHTML(html);
1138
1204
  }
1139
1205
 
1140
- /**
1141
- * Sanitizes an image source to ensure we only allow for data URI and links
1142
- * that start with http(s).
1143
- *
1144
- * Note: Most browsers anyway do not support script execution in <img> elements.
1145
- *
1146
- * @param {string} src
1147
- * @returns {string}
1206
+ /**
1207
+ * Sanitizes an image source to ensure we only allow for data URI and links
1208
+ * that start with http(s).
1209
+ *
1210
+ * Note: Most browsers anyway do not support script execution in <img> elements.
1211
+ *
1212
+ * @param {string} src
1213
+ * @returns {string}
1148
1214
  */
1149
1215
  function safeImageSource(src) {
1150
1216
  return sanitizeImageSource(src);
1151
1217
  }
1152
- function sanitizeSingleSelectValue(options) {
1153
- const {
1154
- formField,
1155
- data,
1156
- value
1157
- } = options;
1158
- const {
1159
- valuesKey,
1160
- values
1161
- } = formField;
1162
- try {
1163
- const validValues = (valuesKey ? get(data, [valuesKey]) : values).map(v => v.value) || [];
1164
- return validValues.includes(value) ? value : null;
1165
- } catch (error) {
1166
- // use default value in case of formatting error
1167
- // TODO(@Skaiir): log a warning when this happens - https://github.com/bpmn-io/form-js/issues/289
1168
- return null;
1169
- }
1170
- }
1171
- function sanitizeMultiSelectValue(options) {
1172
- const {
1173
- formField,
1174
- data,
1175
- value
1176
- } = options;
1177
- const {
1178
- valuesKey,
1179
- values
1180
- } = formField;
1181
- try {
1182
- const validValues = (valuesKey ? get(data, [valuesKey]) : values).map(v => v.value) || [];
1183
- return value.filter(v => validValues.includes(v));
1184
- } catch (error) {
1185
- // use default value in case of formatting error
1186
- // TODO(@Skaiir): log a warning when this happens - https://github.com/bpmn-io/form-js/issues/289
1187
- return [];
1188
- }
1189
- }
1190
1218
 
1191
- const type$a = 'button';
1219
+ const type$b = 'button';
1192
1220
  function Button(props) {
1193
1221
  const {
1194
1222
  disabled,
@@ -1198,7 +1226,7 @@ function Button(props) {
1198
1226
  action = 'submit'
1199
1227
  } = field;
1200
1228
  return jsx("div", {
1201
- class: formFieldClasses(type$a),
1229
+ class: formFieldClasses(type$b),
1202
1230
  children: jsx("button", {
1203
1231
  class: "fjs-button",
1204
1232
  type: action,
@@ -1213,7 +1241,7 @@ Button.create = function (options = {}) {
1213
1241
  ...options
1214
1242
  };
1215
1243
  };
1216
- Button.type = type$a;
1244
+ Button.type = type$b;
1217
1245
  Button.label = 'Button';
1218
1246
  Button.keyed = true;
1219
1247
 
@@ -1229,11 +1257,11 @@ const FormRenderContext = createContext({
1229
1257
  }
1230
1258
  });
1231
1259
 
1232
- /**
1233
- * @param {string} type
1234
- * @param {boolean} [strict]
1235
- *
1236
- * @returns {any}
1260
+ /**
1261
+ * @param {string} type
1262
+ * @param {boolean} [strict]
1263
+ *
1264
+ * @returns {any}
1237
1265
  */
1238
1266
  function getService(type, strict) {}
1239
1267
  const FormContext = createContext({
@@ -1277,11 +1305,14 @@ function Label(props) {
1277
1305
  const {
1278
1306
  id,
1279
1307
  label,
1308
+ collapseOnEmpty = true,
1280
1309
  required = false
1281
1310
  } = props;
1282
1311
  return jsxs("label", {
1283
1312
  for: id,
1284
- class: classNames('fjs-form-field-label', props['class']),
1313
+ class: classNames('fjs-form-field-label', {
1314
+ 'fjs-incollapsible-label': !collapseOnEmpty
1315
+ }, props['class']),
1285
1316
  children: [props.children, label || '', required && jsx("span", {
1286
1317
  class: "fjs-asterix",
1287
1318
  children: "*"
@@ -1289,7 +1320,7 @@ function Label(props) {
1289
1320
  });
1290
1321
  }
1291
1322
 
1292
- const type$9 = 'checkbox';
1323
+ const type$a = 'checkbox';
1293
1324
  function Checkbox(props) {
1294
1325
  const {
1295
1326
  disabled,
@@ -1314,7 +1345,7 @@ function Checkbox(props) {
1314
1345
  formId
1315
1346
  } = useContext(FormContext);
1316
1347
  return jsxs("div", {
1317
- class: classNames(formFieldClasses(type$9, {
1348
+ class: classNames(formFieldClasses(type$a, {
1318
1349
  errors,
1319
1350
  disabled
1320
1351
  }), {
@@ -1344,7 +1375,7 @@ Checkbox.create = function (options = {}) {
1344
1375
  ...options
1345
1376
  };
1346
1377
  };
1347
- Checkbox.type = type$9;
1378
+ Checkbox.type = type$a;
1348
1379
  Checkbox.label = 'Checkbox';
1349
1380
  Checkbox.keyed = true;
1350
1381
  Checkbox.emptyValue = false;
@@ -1359,8 +1390,8 @@ function useService (type, strict) {
1359
1390
  return getService(type, strict);
1360
1391
  }
1361
1392
 
1362
- /**
1363
- * @enum { String }
1393
+ /**
1394
+ * @enum { String }
1364
1395
  */
1365
1396
  const LOAD_STATES = {
1366
1397
  LOADING: 'loading',
@@ -1368,17 +1399,17 @@ const LOAD_STATES = {
1368
1399
  ERROR: 'error'
1369
1400
  };
1370
1401
 
1371
- /**
1372
- * @typedef {Object} ValuesGetter
1373
- * @property {Object[]} values - The values data
1374
- * @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
1402
+ /**
1403
+ * @typedef {Object} ValuesGetter
1404
+ * @property {Object[]} values - The values data
1405
+ * @property {(LOAD_STATES)} state - The values data's loading state, to use for conditional rendering
1375
1406
  */
1376
1407
 
1377
- /**
1378
- * A hook to load values for single and multiselect components.
1379
- *
1380
- * @param {Object} field - The form field to handle values for
1381
- * @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
1408
+ /**
1409
+ * A hook to load values for single and multiselect components.
1410
+ *
1411
+ * @param {Object} field - The form field to handle values for
1412
+ * @return {ValuesGetter} valuesGetter - A values getter object providing loading state and values
1382
1413
  */
1383
1414
  function useValuesAsync (field) {
1384
1415
  const {
@@ -1419,7 +1450,222 @@ const buildLoadedState = values => ({
1419
1450
  state: LOAD_STATES.LOADED
1420
1451
  });
1421
1452
 
1422
- const type$8 = 'checklist';
1453
+ const ENTER_KEYDOWN_EVENT = new KeyboardEvent('keydown', {
1454
+ code: 'Enter',
1455
+ key: 'Enter',
1456
+ charCode: 13,
1457
+ keyCode: 13,
1458
+ view: window,
1459
+ bubbles: true
1460
+ });
1461
+ function focusRelevantFlatpickerDay(flatpickrInstance) {
1462
+ if (!flatpickrInstance) return;
1463
+ !flatpickrInstance.isOpen && flatpickrInstance.open();
1464
+ const container = flatpickrInstance.calendarContainer;
1465
+ const dayToFocus = container.querySelector('.flatpickr-day.selected') || container.querySelector('.flatpickr-day.today') || container.querySelector('.flatpickr-day');
1466
+ dayToFocus && dayToFocus.focus();
1467
+ }
1468
+ function formatTime(use24h, minutes) {
1469
+ if (minutes === null) return null;
1470
+ const wrappedMinutes = minutes % (24 * 60);
1471
+ const minute = minutes % 60;
1472
+ let hour = Math.floor(wrappedMinutes / 60);
1473
+ if (use24h) {
1474
+ return _getZeroPaddedString(hour) + ':' + _getZeroPaddedString(minute);
1475
+ }
1476
+ hour = hour % 12 || 12;
1477
+ const isPM = wrappedMinutes >= 12 * 60;
1478
+ return _getZeroPaddedString(hour) + ':' + _getZeroPaddedString(minute) + ' ' + (isPM ? 'PM' : 'AM');
1479
+ }
1480
+ function parseInputTime(stringTime) {
1481
+ let workingString = stringTime.toLowerCase();
1482
+ const is12h = workingString.includes('am') || workingString.includes('pm');
1483
+ if (is12h) {
1484
+ const isPM = workingString.includes('pm');
1485
+ const digits = workingString.match(/\d+/g);
1486
+ const displayHour = parseInt(digits?.[0]);
1487
+ const minute = parseInt(digits?.[1]) || 0;
1488
+ const isValidDisplayHour = isNumber(displayHour) && displayHour >= 1 && displayHour <= 12;
1489
+ const isValidMinute = minute >= 0 && minute <= 59;
1490
+ if (!isValidDisplayHour || !isValidMinute) return null;
1491
+ const hour = displayHour % 12 + (isPM ? 12 : 0);
1492
+ return hour * 60 + minute;
1493
+ } else {
1494
+ const digits = workingString.match(/\d+/g);
1495
+ const hour = parseInt(digits?.[0]);
1496
+ const minute = parseInt(digits?.[1]);
1497
+ const isValidHour = isNumber(hour) && hour >= 0 && hour <= 23;
1498
+ const isValidMinute = isNumber(minute) && minute >= 0 && minute <= 59;
1499
+ if (!isValidHour || !isValidMinute) return null;
1500
+ return hour * 60 + minute;
1501
+ }
1502
+ }
1503
+ function serializeTime(minutes, offset, timeSerializingFormat) {
1504
+ if (timeSerializingFormat === TIME_SERIALISING_FORMATS.UTC_NORMALIZED) {
1505
+ const normalizedMinutes = (minutes + offset + MINUTES_IN_DAY) % MINUTES_IN_DAY;
1506
+ return _getZeroPaddedString(Math.floor(normalizedMinutes / 60)) + ':' + _getZeroPaddedString(normalizedMinutes % 60) + 'Z';
1507
+ }
1508
+ const baseTime = _getZeroPaddedString(Math.floor(minutes / 60)) + ':' + _getZeroPaddedString(minutes % 60);
1509
+ const addUTCOffset = timeSerializingFormat === TIME_SERIALISING_FORMATS.UTC_OFFSET;
1510
+ return baseTime + (addUTCOffset ? formatTimezoneOffset(offset) : '');
1511
+ }
1512
+ function parseIsoTime(isoTimeString) {
1513
+ if (!isoTimeString) return null;
1514
+ const parseBasicMinutes = timeString => {
1515
+ const timeSegments = timeString.split(':');
1516
+ const hour = parseInt(timeSegments[0]);
1517
+ const minute = timeSegments.length > 1 ? parseInt(timeSegments[1]) : 0;
1518
+ if (isNaN(hour) || hour < 0 || hour > 24 || isNaN(minute) || minute < 0 || minute > 60) return null;
1519
+ return hour * 60 + minute;
1520
+ };
1521
+ const localOffset = new Date().getTimezoneOffset();
1522
+
1523
+ // Parse normalized time
1524
+ if (isoTimeString.includes('Z')) {
1525
+ isoTimeString = isoTimeString.replace('Z', '');
1526
+ const minutes = parseBasicMinutes(isoTimeString);
1527
+ if (minutes === null) return null;
1528
+ return (minutes - localOffset + MINUTES_IN_DAY) % MINUTES_IN_DAY;
1529
+ }
1530
+
1531
+ // Parse offset positive time
1532
+ else if (isoTimeString.includes('+')) {
1533
+ const [timeString, offsetString] = isoTimeString.split('+');
1534
+ const minutes = parseBasicMinutes(timeString);
1535
+ let inboundOffset = parseBasicMinutes(offsetString);
1536
+ if (minutes === null || inboundOffset === null) return null;
1537
+
1538
+ // The offset is flipped for consistency with javascript
1539
+ inboundOffset = -inboundOffset;
1540
+ return (minutes + inboundOffset - localOffset + MINUTES_IN_DAY) % MINUTES_IN_DAY;
1541
+ }
1542
+
1543
+ // Parse offset negative time
1544
+ else if (isoTimeString.includes('-')) {
1545
+ const [timeString, offsetString] = isoTimeString.split('-');
1546
+ const minutes = parseBasicMinutes(timeString);
1547
+ let inboundOffset = parseBasicMinutes(offsetString);
1548
+ if (minutes === null || inboundOffset === null) return null;
1549
+ return (minutes + inboundOffset - localOffset + MINUTES_IN_DAY) % MINUTES_IN_DAY;
1550
+ }
1551
+
1552
+ // Default to local parsing
1553
+ else {
1554
+ return parseBasicMinutes(isoTimeString);
1555
+ }
1556
+ }
1557
+ function serializeDate(date) {
1558
+ var d = new Date(date),
1559
+ month = '' + (d.getMonth() + 1),
1560
+ day = '' + d.getDate(),
1561
+ year = d.getFullYear();
1562
+ if (month.length < 2) month = '0' + month;
1563
+ if (day.length < 2) day = '0' + day;
1564
+ return [year, month, day].join('-');
1565
+ }
1566
+
1567
+ // this method is used to make the `new Date(value)` parsing behavior stricter
1568
+ function isDateTimeInputInformationSufficient(value) {
1569
+ if (!value || typeof value !== 'string') return false;
1570
+ const segments = value.split('T');
1571
+ if (segments.length != 2) return false;
1572
+ const dateNumbers = segments[0].split('-');
1573
+ if (dateNumbers.length != 3) return false;
1574
+ return true;
1575
+ }
1576
+
1577
+ // this method checks if the date isn't a datetime, or a partial date
1578
+ function isDateInputInformationMatching(value) {
1579
+ if (!value || typeof value !== 'string') return false;
1580
+ if (value.includes('T')) return false;
1581
+ const dateNumbers = value.split('-');
1582
+ if (dateNumbers.length != 3) return false;
1583
+ return true;
1584
+ }
1585
+ function serializeDateTime(date, time, timeSerializingFormat) {
1586
+ const workingDate = new Date();
1587
+ workingDate.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
1588
+ workingDate.setHours(Math.floor(time / 60), time % 60, 0, 0);
1589
+ if (timeSerializingFormat === TIME_SERIALISING_FORMATS.UTC_NORMALIZED) {
1590
+ const timezoneOffsetMinutes = workingDate.getTimezoneOffset();
1591
+ const dayOffset = time + timezoneOffsetMinutes < 0 ? -1 : time + timezoneOffsetMinutes > MINUTES_IN_DAY ? 1 : 0;
1592
+
1593
+ // Apply the date rollover pre-emptively
1594
+ workingDate.setHours(workingDate.getHours() + dayOffset * 24);
1595
+ }
1596
+ return serializeDate(workingDate) + 'T' + serializeTime(time, workingDate.getTimezoneOffset(), timeSerializingFormat);
1597
+ }
1598
+ function formatTimezoneOffset(minutes) {
1599
+ return _getSignedPaddedHours(minutes) + ':' + _getZeroPaddedString(Math.abs(minutes % 60));
1600
+ }
1601
+ function isInvalidDateString(value) {
1602
+ return isNaN(new Date(Date.parse(value)).getTime());
1603
+ }
1604
+ function _getSignedPaddedHours(minutes) {
1605
+ if (minutes > 0) {
1606
+ return '-' + _getZeroPaddedString(Math.floor(minutes / 60));
1607
+ } else {
1608
+ return '+' + _getZeroPaddedString(Math.floor((0 - minutes) / 60));
1609
+ }
1610
+ }
1611
+ function _getZeroPaddedString(time) {
1612
+ return time.toString().padStart(2, '0');
1613
+ }
1614
+
1615
+ function sanitizeDateTimePickerValue(options) {
1616
+ const {
1617
+ formField,
1618
+ value
1619
+ } = options;
1620
+ const {
1621
+ subtype
1622
+ } = formField;
1623
+ if (typeof value !== 'string') return null;
1624
+ if (subtype === DATETIME_SUBTYPES.DATE && (isInvalidDateString(value) || !isDateInputInformationMatching(value))) return null;
1625
+ if (subtype === DATETIME_SUBTYPES.TIME && parseIsoTime(value) === null) return null;
1626
+ if (subtype === DATETIME_SUBTYPES.DATETIME && (isInvalidDateString(value) || !isDateTimeInputInformationSufficient(value))) return null;
1627
+ return value;
1628
+ }
1629
+ function sanitizeSingleSelectValue(options) {
1630
+ const {
1631
+ formField,
1632
+ data,
1633
+ value
1634
+ } = options;
1635
+ const {
1636
+ valuesKey,
1637
+ values
1638
+ } = formField;
1639
+ try {
1640
+ const validValues = (valuesKey ? get(data, [valuesKey]) : values).map(v => v.value) || [];
1641
+ return validValues.includes(value) ? value : null;
1642
+ } catch (error) {
1643
+ // use default value in case of formatting error
1644
+ // TODO(@Skaiir): log a warning when this happens - https://github.com/bpmn-io/form-js/issues/289
1645
+ return null;
1646
+ }
1647
+ }
1648
+ function sanitizeMultiSelectValue(options) {
1649
+ const {
1650
+ formField,
1651
+ data,
1652
+ value
1653
+ } = options;
1654
+ const {
1655
+ valuesKey,
1656
+ values
1657
+ } = formField;
1658
+ try {
1659
+ const validValues = (valuesKey ? get(data, [valuesKey]) : values).map(v => v.value) || [];
1660
+ return value.filter(v => validValues.includes(v));
1661
+ } catch (error) {
1662
+ // use default value in case of formatting error
1663
+ // TODO(@Skaiir): log a warning when this happens - https://github.com/bpmn-io/form-js/issues/289
1664
+ return [];
1665
+ }
1666
+ }
1667
+
1668
+ const type$9 = 'checklist';
1423
1669
  function Checklist(props) {
1424
1670
  const {
1425
1671
  disabled,
@@ -1452,7 +1698,7 @@ function Checklist(props) {
1452
1698
  formId
1453
1699
  } = useContext(FormContext);
1454
1700
  return jsxs("div", {
1455
- class: classNames(formFieldClasses(type$8, {
1701
+ class: classNames(formFieldClasses(type$9, {
1456
1702
  errors,
1457
1703
  disabled
1458
1704
  })),
@@ -1492,26 +1738,33 @@ Checklist.create = function (options = {}) {
1492
1738
  ...options
1493
1739
  };
1494
1740
  };
1495
- Checklist.type = type$8;
1741
+ Checklist.type = type$9;
1496
1742
  Checklist.label = 'Checklist';
1497
1743
  Checklist.keyed = true;
1498
1744
  Checklist.emptyValue = [];
1499
1745
  Checklist.sanitizeValue = sanitizeMultiSelectValue;
1500
1746
 
1501
- /**
1502
- * Check if condition is met with given variables.
1503
- *
1504
- * @param {string | undefined} condition
1505
- * @param {import('../../types').Data} data
1506
- *
1507
- * @returns {boolean} true if condition is met or no condition or condition checker exists
1747
+ /**
1748
+ * Check if condition is met with given variables.
1749
+ *
1750
+ * @param {string | undefined} condition
1751
+ * @param {import('../../types').Data} data
1752
+ *
1753
+ * @returns {boolean} true if condition is met or no condition or condition checker exists
1508
1754
  */
1509
1755
  function useCondition(condition, data) {
1756
+ const initialData = useService('form')._getState().initialData;
1510
1757
  const conditionChecker = useService('conditionChecker', false);
1511
1758
  if (!conditionChecker) {
1512
1759
  return null;
1513
1760
  }
1514
- return conditionChecker.check(condition, data);
1761
+
1762
+ // make sure we do not use data from hidden fields
1763
+ const filteredData = {
1764
+ ...initialData,
1765
+ ...conditionChecker.applyConditions(data, data)
1766
+ };
1767
+ return conditionChecker.check(condition, filteredData);
1515
1768
  }
1516
1769
 
1517
1770
  const noop$1 = () => false;
@@ -1593,32 +1846,688 @@ Default.create = function (options = {}) {
1593
1846
  Default.type = 'default';
1594
1847
  Default.keyed = false;
1595
1848
 
1596
- /**
1597
- * This file must not be changed or exchanged.
1598
- *
1599
- * @see http://bpmn.io/license for more information.
1600
- */
1601
- function Logo() {
1602
- return jsxs("svg", {
1603
- xmlns: "http://www.w3.org/2000/svg",
1604
- viewBox: "0 0 14.02 5.57",
1605
- width: "53",
1606
- height: "21",
1607
- style: "vertical-align:middle",
1608
- children: [jsx("path", {
1609
- fill: "currentColor",
1610
- d: "M1.88.92v.14c0 .41-.13.68-.4.8.33.14.46.44.46.86v.33c0 .61-.33.95-.95.95H0V0h.95c.65 0 .93.3.93.92zM.63.57v1.06h.24c.24 0 .38-.1.38-.43V.98c0-.28-.1-.4-.32-.4zm0 1.63v1.22h.36c.2 0 .32-.1.32-.39v-.35c0-.37-.12-.48-.4-.48H.63zM4.18.99v.52c0 .64-.31.98-.94.98h-.3V4h-.62V0h.92c.63 0 .94.35.94.99zM2.94.57v1.35h.3c.2 0 .3-.09.3-.37v-.6c0-.29-.1-.38-.3-.38h-.3zm2.89 2.27L6.25 0h.88v4h-.6V1.12L6.1 3.99h-.6l-.46-2.82v2.82h-.55V0h.87zM8.14 1.1V4h-.56V0h.79L9 2.4V0h.56v4h-.64zm2.49 2.29v.6h-.6v-.6zM12.12 1c0-.63.33-1 .95-1 .61 0 .95.37.95 1v2.04c0 .64-.34 1-.95 1-.62 0-.95-.37-.95-1zm.62 2.08c0 .28.13.39.33.39s.32-.1.32-.4V.98c0-.29-.12-.4-.32-.4s-.33.11-.33.4z"
1611
- }), jsx("path", {
1612
- fill: "currentColor",
1613
- d: "M0 4.53h14.02v1.04H0zM11.08 0h.63v.62h-.63zm.63 4V1h-.63v2.98z"
1849
+ 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); }
1850
+ var CalendarIcon = (({
1851
+ styles = {},
1852
+ ...props
1853
+ }) => /*#__PURE__*/React.createElement("svg", _extends$h({
1854
+ width: "14",
1855
+ height: "15",
1856
+ viewBox: "0 0 28 30",
1857
+ fill: "none",
1858
+ xmlns: "http://www.w3.org/2000/svg"
1859
+ }, props), /*#__PURE__*/React.createElement("path", {
1860
+ fillRule: "evenodd",
1861
+ clipRule: "evenodd",
1862
+ d: "M19 2H9V0H7v2H2a2 2 0 00-2 2v24a2 2 0 002 2h24a2 2 0 002-2V4a2 2 0 00-2-2h-5V0h-2v2zM7 7V4H2v5h24V4h-5v3h-2V4H9v3H7zm-5 4v17h24V11H2z",
1863
+ fill: "#000"
1864
+ })));
1865
+
1866
+ function InputAdorner(props) {
1867
+ const {
1868
+ pre = null,
1869
+ post = null,
1870
+ rootRef,
1871
+ inputRef,
1872
+ children,
1873
+ disabled,
1874
+ hasErrors
1875
+ } = props;
1876
+ const onAdornmentClick = () => inputRef?.current?.focus();
1877
+ return jsxs("div", {
1878
+ class: classNames('fjs-input-group', {
1879
+ 'disabled': disabled
1880
+ }, {
1881
+ 'hasErrors': hasErrors
1882
+ }),
1883
+ ref: rootRef,
1884
+ children: [pre !== null && jsxs("span", {
1885
+ class: "fjs-input-adornment border-right border-radius-left",
1886
+ onClick: onAdornmentClick,
1887
+ children: [" ", pre, " "]
1888
+ }), children, post !== null && jsxs("span", {
1889
+ class: "fjs-input-adornment border-left border-radius-right",
1890
+ onClick: onAdornmentClick,
1891
+ children: [" ", post, " "]
1614
1892
  })]
1615
1893
  });
1616
1894
  }
1617
- function Lightbox(props) {
1895
+
1896
+ function Datepicker(props) {
1618
1897
  const {
1619
- open
1620
- } = props;
1621
- if (!open) {
1898
+ id,
1899
+ label,
1900
+ collapseLabelOnEmpty,
1901
+ formId,
1902
+ required,
1903
+ disabled,
1904
+ disallowPassedDates,
1905
+ date,
1906
+ setDate
1907
+ } = props;
1908
+ const dateInputRef = useRef();
1909
+ const focusScopeRef = useRef();
1910
+ const [flatpickrInstance, setFlatpickrInstance] = useState(null);
1911
+ const [isInputDirty, setIsInputDirty] = useState(false);
1912
+ const [forceFocusCalendar, setForceFocusCalendar] = useState(false);
1913
+
1914
+ // shorts the date value back to the source
1915
+ useEffect(() => {
1916
+ if (!flatpickrInstance || !flatpickrInstance.config) return;
1917
+ flatpickrInstance.setDate(date, true);
1918
+ setIsInputDirty(false);
1919
+ }, [flatpickrInstance, date.toString()]);
1920
+ useEffect(() => {
1921
+ if (!forceFocusCalendar) return;
1922
+ focusRelevantFlatpickerDay(flatpickrInstance);
1923
+ setForceFocusCalendar(false);
1924
+ }, [flatpickrInstance, forceFocusCalendar]);
1925
+
1926
+ // setup flatpickr instance
1927
+ useEffect(() => {
1928
+ if (disabled) {
1929
+ setFlatpickrInstance(null);
1930
+ return;
1931
+ }
1932
+ let config = {
1933
+ allowInput: true,
1934
+ dateFormat: 'm/d/Y',
1935
+ static: true,
1936
+ clickOpens: false,
1937
+ errorHandler: () => {/* do nothing, we expect the values to sometimes be erronous and we don't want warnings polluting the console */}
1938
+ };
1939
+ if (disallowPassedDates) {
1940
+ config = {
1941
+ ...config,
1942
+ minDate: 'today'
1943
+ };
1944
+ }
1945
+ const instance = flatpickr(dateInputRef.current, config);
1946
+ setFlatpickrInstance(instance);
1947
+ const onCalendarFocusOut = e => {
1948
+ if (!instance.calendarContainer.contains(e.relatedTarget) && e.relatedTarget != dateInputRef.current) {
1949
+ instance.close();
1950
+ }
1951
+ };
1952
+
1953
+ // remove dirty tag to have mouse day selection prioritize input blur
1954
+ const onCalendarMouseDown = e => {
1955
+ if (e.target.classList.contains('flatpickr-day')) {
1956
+ setIsInputDirty(false);
1957
+ }
1958
+ };
1959
+
1960
+ // when the dropdown of the datepickr opens, we register a few event handlers to re-implement some of the
1961
+ // flatpicker logic that was lost when setting allowInput to true
1962
+ instance.config.onOpen = [() => instance.calendarContainer.addEventListener('focusout', onCalendarFocusOut), () => instance.calendarContainer.addEventListener('mousedown', onCalendarMouseDown)];
1963
+ instance.config.onClose = [() => instance.calendarContainer.removeEventListener('focusout', onCalendarFocusOut), () => instance.calendarContainer.removeEventListener('mousedown', onCalendarMouseDown)];
1964
+ }, [disabled, disallowPassedDates]);
1965
+
1966
+ // onChange is updated dynamically, so not to re-render the flatpicker every time it changes
1967
+ useEffect(() => {
1968
+ if (!flatpickrInstance || !flatpickrInstance.config) return;
1969
+ flatpickrInstance.config.onChange = [date => setDate(new Date(date)), () => setIsInputDirty(false)];
1970
+ }, [flatpickrInstance, setDate]);
1971
+ const onInputKeyDown = useCallback(e => {
1972
+ if (!flatpickrInstance) return;
1973
+ if (e.code === 'Escape') {
1974
+ flatpickrInstance.close();
1975
+ }
1976
+ if (e.code === 'ArrowDown') {
1977
+ if (isInputDirty) {
1978
+ // trigger an enter keypress to submit the new input, then focus calendar day on the next render cycle
1979
+ dateInputRef.current.dispatchEvent(ENTER_KEYDOWN_EVENT);
1980
+ setIsInputDirty(false);
1981
+ setForceFocusCalendar(true);
1982
+ } else {
1983
+ // focus calendar day immediately
1984
+ focusRelevantFlatpickerDay(flatpickrInstance);
1985
+ }
1986
+ e.preventDefault();
1987
+ }
1988
+ if (e.code === 'Enter') {
1989
+ setIsInputDirty(false);
1990
+ }
1991
+ }, [flatpickrInstance, isInputDirty]);
1992
+ const onInputFocus = useCallback(e => {
1993
+ if (!flatpickrInstance || focusScopeRef.current.contains(e.relatedTarget)) return;
1994
+ flatpickrInstance.open();
1995
+ }, [flatpickrInstance]);
1996
+
1997
+ // simulate an enter press on blur to make sure the date value is submitted in all scenarios
1998
+ const onInputBlur = useCallback(e => {
1999
+ if (!isInputDirty || e.relatedTarget && e.relatedTarget.classList.contains('flatpickr-day')) return;
2000
+ dateInputRef.current.dispatchEvent(ENTER_KEYDOWN_EVENT);
2001
+ setIsInputDirty(false);
2002
+ }, [isInputDirty]);
2003
+ const fullId = `${prefixId(id, formId)}--date`;
2004
+ return jsxs("div", {
2005
+ class: "fjs-datetime-subsection",
2006
+ children: [jsx(Label, {
2007
+ id: fullId,
2008
+ label: label,
2009
+ collapseOnEmpty: collapseLabelOnEmpty,
2010
+ required: required
2011
+ }), jsx(InputAdorner, {
2012
+ pre: jsx(CalendarIcon, {}),
2013
+ disabled: disabled,
2014
+ rootRef: focusScopeRef,
2015
+ inputRef: dateInputRef,
2016
+ children: jsx("div", {
2017
+ class: "fjs-datepicker",
2018
+ style: {
2019
+ width: '100%'
2020
+ },
2021
+ children: jsx("input", {
2022
+ ref: dateInputRef,
2023
+ type: "text",
2024
+ id: fullId,
2025
+ class: 'fjs-input',
2026
+ disabled: disabled,
2027
+ placeholder: "mm/dd/yyyy",
2028
+ autoComplete: "false",
2029
+ onFocus: onInputFocus,
2030
+ onKeyDown: onInputKeyDown,
2031
+ onMouseDown: e => !flatpickrInstance.isOpen && flatpickrInstance.open(),
2032
+ onBlur: onInputBlur,
2033
+ onInput: e => setIsInputDirty(true),
2034
+ "data-input": true
2035
+ })
2036
+ })
2037
+ })]
2038
+ });
2039
+ }
2040
+
2041
+ 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); }
2042
+ var ClockIcon = (({
2043
+ styles = {},
2044
+ ...props
2045
+ }) => /*#__PURE__*/React.createElement("svg", _extends$g({
2046
+ width: "16",
2047
+ height: "16",
2048
+ viewBox: "0 0 28 29",
2049
+ fill: "none",
2050
+ xmlns: "http://www.w3.org/2000/svg"
2051
+ }, props), /*#__PURE__*/React.createElement("path", {
2052
+ d: "M13 14.41L18.59 20 20 18.59l-5-5.01V5h-2v9.41z",
2053
+ fill: "#000"
2054
+ }), /*#__PURE__*/React.createElement("path", {
2055
+ fillRule: "evenodd",
2056
+ clipRule: "evenodd",
2057
+ d: "M6.222 25.64A14 14 0 1021.778 2.36 14 14 0 006.222 25.64zM7.333 4.023a12 12 0 1113.334 19.955A12 12 0 017.333 4.022z",
2058
+ fill: "#000"
2059
+ })));
2060
+
2061
+ function useKeyDownAction(targetKey, action, listenerElement = window) {
2062
+ function downHandler({
2063
+ key
2064
+ }) {
2065
+ if (key === targetKey) {
2066
+ action();
2067
+ }
2068
+ }
2069
+ useEffect(() => {
2070
+ listenerElement.addEventListener('keydown', downHandler);
2071
+ return () => {
2072
+ listenerElement.removeEventListener('keydown', downHandler);
2073
+ };
2074
+ });
2075
+ }
2076
+
2077
+ const DEFAULT_LABEL_GETTER = value => value;
2078
+ const NOOP = () => {};
2079
+ function DropdownList(props) {
2080
+ const {
2081
+ keyEventsListener = window,
2082
+ values = [],
2083
+ getLabel = DEFAULT_LABEL_GETTER,
2084
+ onValueSelected = NOOP,
2085
+ height = 235,
2086
+ emptyListMessage = 'No results',
2087
+ initialFocusIndex = 0
2088
+ } = props;
2089
+ const [mouseControl, setMouseControl] = useState(false);
2090
+ const [focusedValueIndex, setFocusedValueIndex] = useState(initialFocusIndex);
2091
+ const [smoothScrolling, setSmoothScrolling] = useState(false);
2092
+ const dropdownContainer = useRef();
2093
+ const mouseScreenPos = useRef();
2094
+ const focusedItem = useMemo(() => values.length ? values[focusedValueIndex] : null, [focusedValueIndex, values]);
2095
+ const changeFocusedValueIndex = useCallback(delta => {
2096
+ setFocusedValueIndex(x => Math.min(Math.max(0, x + delta), values.length - 1));
2097
+ }, [values.length]);
2098
+ useEffect(() => {
2099
+ if (focusedValueIndex === 0) return;
2100
+ if (!focusedValueIndex || !values.length) {
2101
+ setFocusedValueIndex(0);
2102
+ } else if (focusedValueIndex >= values.length) {
2103
+ setFocusedValueIndex(values.length - 1);
2104
+ }
2105
+ }, [focusedValueIndex, values.length]);
2106
+ useKeyDownAction('ArrowUp', () => {
2107
+ if (values.length) {
2108
+ changeFocusedValueIndex(-1);
2109
+ setMouseControl(false);
2110
+ }
2111
+ }, keyEventsListener);
2112
+ useKeyDownAction('ArrowDown', () => {
2113
+ if (values.length) {
2114
+ changeFocusedValueIndex(1);
2115
+ setMouseControl(false);
2116
+ }
2117
+ }, keyEventsListener);
2118
+ useKeyDownAction('Enter', () => {
2119
+ if (focusedItem) {
2120
+ onValueSelected(focusedItem);
2121
+ }
2122
+ }, keyEventsListener);
2123
+ useEffect(() => {
2124
+ const individualEntries = dropdownContainer.current.children;
2125
+ if (individualEntries.length && !mouseControl) {
2126
+ individualEntries[focusedValueIndex].scrollIntoView({
2127
+ block: 'nearest',
2128
+ inline: 'nearest'
2129
+ });
2130
+ }
2131
+ }, [focusedValueIndex, mouseControl]);
2132
+ useEffect(() => {
2133
+ setSmoothScrolling(true);
2134
+ }, []);
2135
+ const onMouseMovedInKeyboardMode = (event, valueIndex) => {
2136
+ const userMovedCursor = !mouseScreenPos.current || mouseScreenPos.current.x !== event.screenX && mouseScreenPos.current.y !== event.screenY;
2137
+ if (userMovedCursor) {
2138
+ mouseScreenPos.current = {
2139
+ x: event.screenX,
2140
+ y: event.screenY
2141
+ };
2142
+ setMouseControl(true);
2143
+ setFocusedValueIndex(valueIndex);
2144
+ }
2145
+ };
2146
+ return jsxs("div", {
2147
+ ref: dropdownContainer,
2148
+ tabIndex: -1,
2149
+ class: "fjs-dropdownlist",
2150
+ style: {
2151
+ maxHeight: height,
2152
+ scrollBehavior: smoothScrolling ? 'smooth' : 'auto'
2153
+ },
2154
+ children: [values.length > 0 && values.map((v, i) => {
2155
+ return jsx("div", {
2156
+ class: classNames('fjs-dropdownlist-item', {
2157
+ 'focused': focusedValueIndex === i
2158
+ }),
2159
+ onMouseMove: mouseControl ? undefined : e => onMouseMovedInKeyboardMode(e, i),
2160
+ onMouseEnter: mouseControl ? () => setFocusedValueIndex(i) : undefined,
2161
+ onMouseDown: e => {
2162
+ e.preventDefault();
2163
+ onValueSelected(v);
2164
+ },
2165
+ children: getLabel(v)
2166
+ });
2167
+ }), !values.length && jsx("div", {
2168
+ class: "fjs-dropdownlist-empty",
2169
+ children: emptyListMessage
2170
+ })]
2171
+ });
2172
+ }
2173
+
2174
+ function Timepicker(props) {
2175
+ const {
2176
+ id,
2177
+ label,
2178
+ collapseLabelOnEmpty,
2179
+ formId,
2180
+ required,
2181
+ disabled,
2182
+ use24h = false,
2183
+ timeInterval,
2184
+ time,
2185
+ setTime
2186
+ } = props;
2187
+ const timeInputRef = useRef();
2188
+ const [dropdownIsOpen, setDropdownIsOpen] = useState(false);
2189
+ const useDropdown = useMemo(() => timeInterval !== 1, [timeInterval]);
2190
+ const [rawValue, setRawValue] = useState('');
2191
+
2192
+ // populates values from source
2193
+ useEffect(() => {
2194
+ if (time === null) {
2195
+ setRawValue('');
2196
+ return;
2197
+ }
2198
+ const intervalAdjustedTime = time - time % timeInterval;
2199
+ setRawValue(formatTime(use24h, intervalAdjustedTime));
2200
+ if (intervalAdjustedTime != time) {
2201
+ setTime(intervalAdjustedTime);
2202
+ }
2203
+ }, [time, setTime, use24h, timeInterval]);
2204
+ const propagateRawToMinute = useCallback(newRawValue => {
2205
+ const localRawValue = newRawValue || rawValue;
2206
+
2207
+ // If no raw value exists, set the minute to null
2208
+ if (!localRawValue) {
2209
+ setTime(null);
2210
+ return;
2211
+ }
2212
+ const minutes = parseInputTime(localRawValue);
2213
+
2214
+ // If raw string couldn't be parsed, clean everything up
2215
+ if (!isNumber(minutes)) {
2216
+ setRawValue('');
2217
+ setTime(null);
2218
+ return;
2219
+ }
2220
+
2221
+ // Enforce the minutes to match the timeInterval
2222
+ const correctedMinutes = minutes - minutes % timeInterval;
2223
+
2224
+ // Enforce the raw text to be formatted properly
2225
+ setRawValue(formatTime(use24h, correctedMinutes));
2226
+ setTime(correctedMinutes);
2227
+ }, [rawValue, timeInterval, use24h, setTime]);
2228
+ const timeOptions = useMemo(() => {
2229
+ const minutesInDay = 24 * 60;
2230
+ const intervalCount = Math.floor(minutesInDay / timeInterval);
2231
+ return [...Array(intervalCount).keys()].map(intervalIndex => formatTime(use24h, intervalIndex * timeInterval));
2232
+ }, [timeInterval, use24h]);
2233
+ const initialFocusIndex = useMemo(() => {
2234
+ // if there are no options, there will not be any focusing
2235
+ if (!timeOptions || !timeInterval) return null;
2236
+
2237
+ // if there is a set minute value, we focus it in the dropdown
2238
+ if (time) return time / timeInterval;
2239
+ const cacheTime = parseInputTime(rawValue);
2240
+
2241
+ // if there is a valid value in the input cache, we try and focus close to it
2242
+ if (cacheTime) {
2243
+ const flooredCacheTime = cacheTime - cacheTime % timeInterval;
2244
+ return flooredCacheTime / timeInterval;
2245
+ }
2246
+
2247
+ // If there is no set value, simply focus the middle of the dropdown (12:00)
2248
+ return Math.floor(timeOptions.length / 2);
2249
+ }, [rawValue, time, timeInterval, timeOptions]);
2250
+ const onInputKeyDown = e => {
2251
+ switch (e.key) {
2252
+ case 'ArrowUp':
2253
+ e.preventDefault();
2254
+ break;
2255
+ case 'ArrowDown':
2256
+ useDropdown && setDropdownIsOpen(true);
2257
+ e.preventDefault();
2258
+ break;
2259
+ case 'Escape':
2260
+ useDropdown && setDropdownIsOpen(false);
2261
+ break;
2262
+ case 'Enter':
2263
+ !dropdownIsOpen && propagateRawToMinute();
2264
+ break;
2265
+ }
2266
+ };
2267
+ const onInputBlur = e => {
2268
+ setDropdownIsOpen(false);
2269
+ propagateRawToMinute();
2270
+ };
2271
+ const onDropdownValueSelected = value => {
2272
+ setDropdownIsOpen(false);
2273
+ propagateRawToMinute(value);
2274
+ };
2275
+ const fullId = `${prefixId(id, formId)}--time`;
2276
+ return jsxs("div", {
2277
+ class: "fjs-datetime-subsection",
2278
+ children: [jsx(Label, {
2279
+ id: fullId,
2280
+ label: label,
2281
+ collapseOnEmpty: collapseLabelOnEmpty,
2282
+ required: required
2283
+ }), jsx(InputAdorner, {
2284
+ pre: jsx(ClockIcon, {}),
2285
+ inputRef: timeInputRef,
2286
+ disabled: disabled,
2287
+ children: jsxs("div", {
2288
+ class: "fjs-timepicker fjs-timepicker-anchor",
2289
+ children: [jsx("input", {
2290
+ ref: timeInputRef,
2291
+ type: "text",
2292
+ id: fullId,
2293
+ class: "fjs-input",
2294
+ value: rawValue,
2295
+ disabled: disabled,
2296
+ placeholder: use24h ? 'hh:mm' : 'hh:mm ?m',
2297
+ autoComplete: "false",
2298
+ onFocus: () => useDropdown && setDropdownIsOpen(true),
2299
+ onClick: () => useDropdown && setDropdownIsOpen(true)
2300
+
2301
+ // @ts-ignore
2302
+ ,
2303
+ onInput: e => {
2304
+ setRawValue(e.target.value);
2305
+ useDropdown && setDropdownIsOpen(false);
2306
+ },
2307
+ onBlur: onInputBlur,
2308
+ onKeyDown: onInputKeyDown,
2309
+ "data-input": true
2310
+ }), dropdownIsOpen && jsx(DropdownList, {
2311
+ values: timeOptions,
2312
+ height: 150,
2313
+ onValueSelected: onDropdownValueSelected,
2314
+ listenerElement: timeInputRef.current,
2315
+ initialFocusIndex: initialFocusIndex
2316
+ })]
2317
+ })
2318
+ })]
2319
+ });
2320
+ }
2321
+
2322
+ const type$8 = 'datetime';
2323
+ function Datetime(props) {
2324
+ const {
2325
+ disabled,
2326
+ errors = [],
2327
+ field,
2328
+ onChange,
2329
+ value = ''
2330
+ } = props;
2331
+ const {
2332
+ description,
2333
+ id,
2334
+ dateLabel,
2335
+ timeLabel,
2336
+ validate = {},
2337
+ subtype,
2338
+ use24h,
2339
+ disallowPassedDates,
2340
+ timeInterval,
2341
+ timeSerializingFormat
2342
+ } = field;
2343
+ const {
2344
+ required
2345
+ } = validate;
2346
+ const {
2347
+ formId
2348
+ } = useContext(FormContext);
2349
+ const getNullDateTime = () => ({
2350
+ date: new Date(Date.parse(null)),
2351
+ time: null
2352
+ });
2353
+ const [dateTime, setDateTime] = useState(getNullDateTime());
2354
+ const [dateTimeUpdateRequest, setDateTimeUpdateRequest] = useState(null);
2355
+ const isValidDate = date => date && !isNaN(date.getTime());
2356
+ const isValidTime = time => !isNaN(parseInt(time));
2357
+ const useDatePicker = useMemo(() => subtype === DATETIME_SUBTYPES.DATE || subtype === DATETIME_SUBTYPES.DATETIME, [subtype]);
2358
+ const useTimePicker = useMemo(() => subtype === DATETIME_SUBTYPES.TIME || subtype === DATETIME_SUBTYPES.DATETIME, [subtype]);
2359
+ useEffect(() => {
2360
+ let {
2361
+ date,
2362
+ time
2363
+ } = getNullDateTime();
2364
+ if (!disabled) {
2365
+ switch (subtype) {
2366
+ case DATETIME_SUBTYPES.DATE:
2367
+ {
2368
+ date = new Date(Date.parse(value));
2369
+ break;
2370
+ }
2371
+ case DATETIME_SUBTYPES.TIME:
2372
+ {
2373
+ time = parseIsoTime(value);
2374
+ break;
2375
+ }
2376
+ case DATETIME_SUBTYPES.DATETIME:
2377
+ {
2378
+ date = new Date(Date.parse(value));
2379
+ time = isValidDate(date) ? 60 * date.getHours() + date.getMinutes() : null;
2380
+ break;
2381
+ }
2382
+ }
2383
+ }
2384
+ setDateTime({
2385
+ date,
2386
+ time
2387
+ });
2388
+ }, [subtype, value, disabled]);
2389
+ const computeAndSetState = useCallback(({
2390
+ date,
2391
+ time
2392
+ }) => {
2393
+ let newDateTimeValue = null;
2394
+ if (subtype === DATETIME_SUBTYPES.DATE && isValidDate(date)) {
2395
+ newDateTimeValue = serializeDate(date);
2396
+ } else if (subtype === DATETIME_SUBTYPES.TIME && isValidTime(time)) {
2397
+ newDateTimeValue = serializeTime(time, new Date().getTimezoneOffset(), timeSerializingFormat);
2398
+ } else if (subtype === DATETIME_SUBTYPES.DATETIME && isValidDate(date) && isValidTime(time)) {
2399
+ newDateTimeValue = serializeDateTime(date, time, timeSerializingFormat);
2400
+ }
2401
+ onChange({
2402
+ value: newDateTimeValue,
2403
+ field
2404
+ });
2405
+ }, [field, onChange, subtype, timeSerializingFormat]);
2406
+ useEffect(() => {
2407
+ if (dateTimeUpdateRequest) {
2408
+ if (dateTimeUpdateRequest.refreshOnly) {
2409
+ computeAndSetState(dateTime);
2410
+ } else {
2411
+ const newDateTime = {
2412
+ ...dateTime,
2413
+ ...dateTimeUpdateRequest
2414
+ };
2415
+ setDateTime(newDateTime);
2416
+ computeAndSetState(newDateTime);
2417
+ }
2418
+ setDateTimeUpdateRequest(null);
2419
+ }
2420
+ }, [computeAndSetState, dateTime, dateTimeUpdateRequest]);
2421
+ useEffect(() => {
2422
+ setDateTimeUpdateRequest({
2423
+ refreshOnly: true
2424
+ });
2425
+ }, [timeSerializingFormat]);
2426
+ const allErrors = useMemo(() => {
2427
+ if (required || subtype !== DATETIME_SUBTYPES.DATETIME) return errors;
2428
+ const isOnlyOneFieldSet = isValidDate(dateTime.date) && !isValidTime(dateTime.time) || !isValidDate(dateTime.date) && isValidTime(dateTime.time);
2429
+ return isOnlyOneFieldSet ? ['Date and time must both be entered.', ...errors] : errors;
2430
+ }, [required, subtype, dateTime, errors]);
2431
+ const setDate = useCallback(date => {
2432
+ setDateTimeUpdateRequest(prev => prev ? {
2433
+ ...prev,
2434
+ date
2435
+ } : {
2436
+ date
2437
+ });
2438
+ }, []);
2439
+ const setTime = useCallback(time => {
2440
+ setDateTimeUpdateRequest(prev => prev ? {
2441
+ ...prev,
2442
+ time
2443
+ } : {
2444
+ time
2445
+ });
2446
+ }, []);
2447
+ const datePickerProps = {
2448
+ id,
2449
+ label: dateLabel,
2450
+ collapseLabelOnEmpty: !timeLabel,
2451
+ formId,
2452
+ required,
2453
+ disabled,
2454
+ disallowPassedDates,
2455
+ date: dateTime.date,
2456
+ setDate
2457
+ };
2458
+ const timePickerProps = {
2459
+ id,
2460
+ label: timeLabel,
2461
+ collapseLabelOnEmpty: !dateLabel,
2462
+ formId,
2463
+ required,
2464
+ disabled,
2465
+ use24h,
2466
+ timeInterval,
2467
+ time: dateTime.time,
2468
+ setTime
2469
+ };
2470
+ return jsxs("div", {
2471
+ class: formFieldClasses(type$8, {
2472
+ errors: allErrors,
2473
+ disabled
2474
+ }),
2475
+ children: [jsxs("div", {
2476
+ class: classNames('fjs-vertical-group'),
2477
+ children: [useDatePicker && jsx(Datepicker, {
2478
+ ...datePickerProps
2479
+ }), useTimePicker && useDatePicker && jsx("div", {
2480
+ class: "fjs-datetime-separator"
2481
+ }), useTimePicker && jsx(Timepicker, {
2482
+ ...timePickerProps
2483
+ })]
2484
+ }), jsx(Description, {
2485
+ description: description
2486
+ }), jsx(Errors, {
2487
+ errors: allErrors
2488
+ })]
2489
+ });
2490
+ }
2491
+ Datetime.create = function (options = {}) {
2492
+ const newOptions = {};
2493
+ set(newOptions, DATETIME_SUBTYPE_PATH, DATETIME_SUBTYPES.DATE);
2494
+ set(newOptions, DATE_LABEL_PATH, 'Date');
2495
+ return {
2496
+ ...newOptions,
2497
+ ...options
2498
+ };
2499
+ };
2500
+ Datetime.type = type$8;
2501
+ Datetime.keyed = true;
2502
+ Datetime.emptyValue = null;
2503
+ Datetime.sanitizeValue = sanitizeDateTimePickerValue;
2504
+
2505
+ /**
2506
+ * This file must not be changed or exchanged.
2507
+ *
2508
+ * @see http://bpmn.io/license for more information.
2509
+ */
2510
+ function Logo() {
2511
+ return jsxs("svg", {
2512
+ xmlns: "http://www.w3.org/2000/svg",
2513
+ viewBox: "0 0 14.02 5.57",
2514
+ width: "53",
2515
+ height: "21",
2516
+ style: "vertical-align:middle",
2517
+ children: [jsx("path", {
2518
+ fill: "currentColor",
2519
+ d: "M1.88.92v.14c0 .41-.13.68-.4.8.33.14.46.44.46.86v.33c0 .61-.33.95-.95.95H0V0h.95c.65 0 .93.3.93.92zM.63.57v1.06h.24c.24 0 .38-.1.38-.43V.98c0-.28-.1-.4-.32-.4zm0 1.63v1.22h.36c.2 0 .32-.1.32-.39v-.35c0-.37-.12-.48-.4-.48H.63zM4.18.99v.52c0 .64-.31.98-.94.98h-.3V4h-.62V0h.92c.63 0 .94.35.94.99zM2.94.57v1.35h.3c.2 0 .3-.09.3-.37v-.6c0-.29-.1-.38-.3-.38h-.3zm2.89 2.27L6.25 0h.88v4h-.6V1.12L6.1 3.99h-.6l-.46-2.82v2.82h-.55V0h.87zM8.14 1.1V4h-.56V0h.79L9 2.4V0h.56v4h-.64zm2.49 2.29v.6h-.6v-.6zM12.12 1c0-.63.33-1 .95-1 .61 0 .95.37.95 1v2.04c0 .64-.34 1-.95 1-.62 0-.95-.37-.95-1zm.62 2.08c0 .28.13.39.33.39s.32-.1.32-.4V.98c0-.29-.12-.4-.32-.4s-.33.11-.33.4z"
2520
+ }), jsx("path", {
2521
+ fill: "currentColor",
2522
+ d: "M0 4.53h14.02v1.04H0zM11.08 0h.63v.62h-.63zm.63 4V1h-.63v2.98z"
2523
+ })]
2524
+ });
2525
+ }
2526
+ function Lightbox(props) {
2527
+ const {
2528
+ open
2529
+ } = props;
2530
+ if (!open) {
1622
2531
  return null;
1623
2532
  }
1624
2533
  return jsxs("div", {
@@ -1713,22 +2622,29 @@ function FormComponent(props) {
1713
2622
  });
1714
2623
  }
1715
2624
 
1716
- /**
1717
- *
1718
- * @param {string | undefined} expression
1719
- * @param {import('../../types').Data} data
2625
+ /**
2626
+ *
2627
+ * @param {string | undefined} expression
2628
+ * @param {import('../../types').Data} data
1720
2629
  */
1721
2630
  function useEvaluation(expression, data) {
2631
+ const initialData = useService('form')._getState().initialData;
1722
2632
  const conditionChecker = useService('conditionChecker', false);
1723
2633
  if (!conditionChecker) {
1724
2634
  return null;
1725
2635
  }
1726
- return conditionChecker.evaluate(expression, data);
2636
+
2637
+ // make sure we do not use data from hidden fields
2638
+ const filteredData = {
2639
+ ...initialData,
2640
+ ...conditionChecker.applyConditions(data, data)
2641
+ };
2642
+ return conditionChecker.evaluate(expression, filteredData);
1727
2643
  }
1728
2644
 
1729
- /**
1730
- *
1731
- * @param {string} value
2645
+ /**
2646
+ *
2647
+ * @param {string} value
1732
2648
  */
1733
2649
  function useExpressionValue(value) {
1734
2650
  const formData = useService('form')._getState().data;
@@ -1748,11 +2664,11 @@ function isExpression(value) {
1748
2664
  return isString(value) && value.startsWith('=');
1749
2665
  }
1750
2666
 
1751
- 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); }
2667
+ 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); }
1752
2668
  var ImagePlaceholder = (({
1753
2669
  styles = {},
1754
2670
  ...props
1755
- }) => /*#__PURE__*/React.createElement("svg", _extends$1({
2671
+ }) => /*#__PURE__*/React.createElement("svg", _extends$f({
1756
2672
  width: "64",
1757
2673
  height: "64",
1758
2674
  viewBox: "0 0 1280 1280",
@@ -1832,11 +2748,16 @@ function Numberfield(props) {
1832
2748
  description,
1833
2749
  id,
1834
2750
  label,
2751
+ appearance = {},
1835
2752
  validate = {},
1836
2753
  decimalDigits,
1837
2754
  serializeToString = false,
1838
2755
  increment: incrementValue
1839
2756
  } = field;
2757
+ const {
2758
+ prefixAdorner,
2759
+ suffixAdorner
2760
+ } = appearance;
1840
2761
  const {
1841
2762
  required
1842
2763
  } = validate;
@@ -1946,45 +2867,52 @@ function Numberfield(props) {
1946
2867
  id: prefixId(id, formId),
1947
2868
  label: label,
1948
2869
  required: required
1949
- }), jsxs("div", {
1950
- class: classNames('fjs-input-group', {
1951
- 'disabled': disabled
1952
- }, {
1953
- 'hasErrors': errors.length
1954
- }),
1955
- children: [jsx("input", {
1956
- ref: inputRef,
1957
- class: "fjs-input",
1958
- disabled: disabled,
1959
- id: prefixId(id, formId),
1960
- onKeyDown: onKeyDown,
1961
- onKeyPress: onKeyPress
1962
-
1963
- // @ts-ignore
1964
- ,
1965
- onInput: e => setValue(e.target.value),
1966
- type: "text",
1967
- autoComplete: "off",
1968
- step: arrowIncrementValue,
1969
- value: displayValue
1970
- }), jsxs("div", {
1971
- class: classNames('fjs-number-arrow-container', {
2870
+ }), jsx(InputAdorner, {
2871
+ disabled: disabled,
2872
+ pre: prefixAdorner,
2873
+ post: suffixAdorner,
2874
+ children: jsxs("div", {
2875
+ class: classNames('fjs-vertical-group', {
1972
2876
  'disabled': disabled
2877
+ }, {
2878
+ 'hasErrors': errors.length
1973
2879
  }),
1974
- children: [jsx("button", {
1975
- class: "fjs-number-arrow-up",
1976
- onClick: () => increment(),
1977
- tabIndex: -1,
1978
- children: "\u02C4"
1979
- }), jsx("div", {
1980
- class: "fjs-number-arrow-separator"
1981
- }), jsx("button", {
1982
- class: "fjs-number-arrow-down",
1983
- onClick: () => decrement(),
1984
- tabIndex: -1,
1985
- children: "\u02C5"
2880
+ children: [jsx("input", {
2881
+ ref: inputRef,
2882
+ class: "fjs-input",
2883
+ disabled: disabled,
2884
+ id: prefixId(id, formId),
2885
+ onKeyDown: onKeyDown,
2886
+ onKeyPress: onKeyPress
2887
+
2888
+ // @ts-ignore
2889
+ ,
2890
+ onInput: e => setValue(e.target.value),
2891
+ type: "text",
2892
+ autoComplete: "off",
2893
+ step: arrowIncrementValue,
2894
+ value: displayValue
2895
+ }), jsxs("div", {
2896
+ class: classNames('fjs-number-arrow-container', {
2897
+ 'disabled': disabled
2898
+ }),
2899
+ children: [jsx("button", {
2900
+ class: "fjs-number-arrow-up",
2901
+ type: "button",
2902
+ onClick: () => increment(),
2903
+ tabIndex: -1,
2904
+ children: "\u02C4"
2905
+ }), jsx("div", {
2906
+ class: "fjs-number-arrow-separator"
2907
+ }), jsx("button", {
2908
+ class: "fjs-number-arrow-down",
2909
+ type: "button",
2910
+ onClick: () => decrement(),
2911
+ tabIndex: -1,
2912
+ children: "\u02C5"
2913
+ })]
1986
2914
  })]
1987
- })]
2915
+ })
1988
2916
  }), jsx(Description, {
1989
2917
  description: description
1990
2918
  }), jsx(Errors, {
@@ -2167,11 +3095,11 @@ Select.keyed = true;
2167
3095
  Select.emptyValue = null;
2168
3096
  Select.sanitizeValue = sanitizeSingleSelectValue;
2169
3097
 
2170
- 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); }
3098
+ 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); }
2171
3099
  var CloseIcon = (({
2172
3100
  styles = {},
2173
3101
  ...props
2174
- }) => /*#__PURE__*/React.createElement("svg", _extends({
3102
+ }) => /*#__PURE__*/React.createElement("svg", _extends$e({
2175
3103
  width: "16",
2176
3104
  height: "16",
2177
3105
  fill: "none",
@@ -2183,113 +3111,6 @@ var CloseIcon = (({
2183
3111
  fill: "currentColor"
2184
3112
  })));
2185
3113
 
2186
- function useKeyDownAction(targetKey, action, listenerElement = window) {
2187
- function downHandler({
2188
- key
2189
- }) {
2190
- if (key === targetKey) {
2191
- action();
2192
- }
2193
- }
2194
- useEffect(() => {
2195
- listenerElement.addEventListener('keydown', downHandler);
2196
- return () => {
2197
- listenerElement.removeEventListener('keydown', downHandler);
2198
- };
2199
- });
2200
- }
2201
-
2202
- const DEFAULT_LABEL_GETTER = value => value;
2203
- const NOOP = () => {};
2204
- function DropdownList(props) {
2205
- const {
2206
- keyEventsListener = window,
2207
- values = [],
2208
- getLabel = DEFAULT_LABEL_GETTER,
2209
- onValueSelected = NOOP,
2210
- height = 235,
2211
- emptyListMessage = 'No results'
2212
- } = props;
2213
- const [mouseControl, setMouseControl] = useState(true);
2214
- const [focusedValueIndex, setFocusedValueIndex] = useState(0);
2215
- const dropdownContainer = useRef();
2216
- const mouseScreenPos = useRef();
2217
- const focusedItem = useMemo(() => values.length ? values[focusedValueIndex] : null, [focusedValueIndex, values]);
2218
- const changeFocusedValueIndex = useCallback(delta => {
2219
- setFocusedValueIndex(x => Math.min(Math.max(0, x + delta), values.length - 1));
2220
- }, [values.length]);
2221
- useEffect(() => {
2222
- if (focusedValueIndex === 0) return;
2223
- if (!focusedValueIndex || !values.length) {
2224
- setFocusedValueIndex(0);
2225
- } else if (focusedValueIndex >= values.length) {
2226
- setFocusedValueIndex(values.length - 1);
2227
- }
2228
- }, [focusedValueIndex, values.length]);
2229
- useKeyDownAction('ArrowUp', () => {
2230
- if (values.length) {
2231
- changeFocusedValueIndex(-1);
2232
- setMouseControl(false);
2233
- }
2234
- }, keyEventsListener);
2235
- useKeyDownAction('ArrowDown', () => {
2236
- if (values.length) {
2237
- changeFocusedValueIndex(1);
2238
- setMouseControl(false);
2239
- }
2240
- }, keyEventsListener);
2241
- useKeyDownAction('Enter', () => {
2242
- if (focusedItem) {
2243
- onValueSelected(focusedItem);
2244
- }
2245
- }, keyEventsListener);
2246
- useEffect(() => {
2247
- const individualEntries = dropdownContainer.current.children;
2248
- if (individualEntries.length && !mouseControl) {
2249
- individualEntries[focusedValueIndex].scrollIntoView({
2250
- block: 'nearest',
2251
- inline: 'nearest'
2252
- });
2253
- }
2254
- }, [focusedValueIndex, mouseControl]);
2255
- const mouseMove = (e, i) => {
2256
- const userMoved = !mouseScreenPos.current || mouseScreenPos.current.x !== e.screenX && mouseScreenPos.current.y !== e.screenY;
2257
- if (userMoved) {
2258
- mouseScreenPos.current = {
2259
- x: e.screenX,
2260
- y: e.screenY
2261
- };
2262
- if (!mouseControl) {
2263
- setMouseControl(true);
2264
- setFocusedValueIndex(i);
2265
- }
2266
- }
2267
- };
2268
- return jsxs("div", {
2269
- ref: dropdownContainer,
2270
- tabIndex: -1,
2271
- class: "fjs-dropdownlist",
2272
- style: {
2273
- maxHeight: height
2274
- },
2275
- children: [!!values.length && values.map((v, i) => {
2276
- return jsx("div", {
2277
- class: 'fjs-dropdownlist-item' + (focusedValueIndex === i ? ' focused' : ''),
2278
- onMouseMove: e => mouseMove(e, i),
2279
- onMouseEnter: mouseControl ? () => setFocusedValueIndex(i) : undefined,
2280
- onMouseDown: e => {
2281
- e.preventDefault();
2282
- onValueSelected(v);
2283
- },
2284
- children: getLabel(v)
2285
- });
2286
- }), !values.length && jsx("div", {
2287
- class: "fjs-dropdownlist-empty",
2288
- children: emptyListMessage
2289
- })]
2290
- });
2291
- }
2292
-
2293
3114
  const type$3 = 'taglist';
2294
3115
  function Taglist(props) {
2295
3116
  const {
@@ -2473,20 +3294,261 @@ Taglist.keyed = true;
2473
3294
  Taglist.emptyValue = [];
2474
3295
  Taglist.sanitizeValue = sanitizeMultiSelectValue;
2475
3296
 
3297
+ 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); }
3298
+ var ButtonIcon = (({
3299
+ styles = {},
3300
+ ...props
3301
+ }) => /*#__PURE__*/React.createElement("svg", _extends$d({
3302
+ xmlns: "http://www.w3.org/2000/svg",
3303
+ width: "54",
3304
+ height: "54"
3305
+ }, props), /*#__PURE__*/React.createElement("path", {
3306
+ fillRule: "evenodd",
3307
+ d: "M45 17a3 3 0 013 3v14a3 3 0 01-3 3H9a3 3 0 01-3-3V20a3 3 0 013-3h36zm-9 8.889H18v2.222h18V25.89z"
3308
+ })));
3309
+
3310
+ 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); }
3311
+ var CheckboxIcon = (({
3312
+ styles = {},
3313
+ ...props
3314
+ }) => /*#__PURE__*/React.createElement("svg", _extends$c({
3315
+ xmlns: "http://www.w3.org/2000/svg",
3316
+ width: "54",
3317
+ height: "54"
3318
+ }, props), /*#__PURE__*/React.createElement("path", {
3319
+ d: "M34 18H20a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2V20a2 2 0 00-2-2zm-9 14l-5-5 1.41-1.41L25 29.17l7.59-7.59L34 23l-9 9z"
3320
+ })));
3321
+
3322
+ 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); }
3323
+ var ChecklistIcon = (({
3324
+ styles = {},
3325
+ ...props
3326
+ }) => /*#__PURE__*/React.createElement("svg", _extends$b({
3327
+ width: "54",
3328
+ height: "54",
3329
+ fill: "none",
3330
+ xmlns: "http://www.w3.org/2000/svg"
3331
+ }, props), /*#__PURE__*/React.createElement("path", {
3332
+ fillRule: "evenodd",
3333
+ clipRule: "evenodd",
3334
+ d: "M19 24h-6v6h6v-6zm-6-2a2 2 0 00-2 2v6a2 2 0 002 2h6a2 2 0 002-2v-6a2 2 0 00-2-2h-6zm6 18h-6v6h6v-6zm-6-2a2 2 0 00-2 2v6a2 2 0 002 2h6a2 2 0 002-2v-6a2 2 0 00-2-2h-6zm6-30h-6v6h6V8zm-6-2a2 2 0 00-2 2v6a2 2 0 002 2h6a2 2 0 002-2V8a2 2 0 00-2-2h-6z",
3335
+ fill: "#22242A"
3336
+ }), /*#__PURE__*/React.createElement("path", {
3337
+ d: "M26 26a1 1 0 011-1h15a1 1 0 011 1v2a1 1 0 01-1 1H27a1 1 0 01-1-1v-2zm0 16a1 1 0 011-1h15a1 1 0 011 1v2a1 1 0 01-1 1H27a1 1 0 01-1-1v-2zm0-32a1 1 0 011-1h15a1 1 0 011 1v2a1 1 0 01-1 1H27a1 1 0 01-1-1v-2z",
3338
+ fill: "#22242A"
3339
+ })));
3340
+
3341
+ 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); }
3342
+ var DatetimeIcon = (({
3343
+ styles = {},
3344
+ ...props
3345
+ }) => /*#__PURE__*/React.createElement("svg", _extends$a({
3346
+ xmlns: "http://www.w3.org/2000/svg",
3347
+ width: "54",
3348
+ height: "54",
3349
+ fill: "none"
3350
+ }, props), /*#__PURE__*/React.createElement("path", {
3351
+ fill: "#000",
3352
+ fillRule: "evenodd",
3353
+ d: "M37.908 13.418h-5.004v-2.354h-1.766v2.354H21.13v-2.354h-1.766v2.354H14.36c-1.132 0-2.06.928-2.06 2.06v23.549c0 1.132.928 2.06 2.06 2.06h6.77v-1.766h-6.358a.707.707 0 01-.706-.706V15.89c0-.39.316-.707.706-.707h4.592v2.355h1.766v-2.355h10.008v2.355h1.766v-2.355h4.592c.39 0 .707.317.707.707v6.358h1.765v-6.77c0-1.133-.927-2.06-2.06-2.06z",
3354
+ clipRule: "evenodd"
3355
+ }), /*#__PURE__*/React.createElement("path", {
3356
+ fill: "#000",
3357
+ d: "M35.13 37.603l1.237-1.237-3.468-3.475v-5.926h-1.754v6.654l3.984 3.984z"
3358
+ }), /*#__PURE__*/React.createElement("path", {
3359
+ fill: "#000",
3360
+ fillRule: "evenodd",
3361
+ d: "M23.08 36.962a9.678 9.678 0 1017.883-7.408 9.678 9.678 0 00-17.882 7.408zm4.54-10.292a7.924 7.924 0 118.805 13.177A7.924 7.924 0 0127.62 26.67z",
3362
+ clipRule: "evenodd"
3363
+ })));
3364
+
3365
+ 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); }
3366
+ var TaglistIcon = (({
3367
+ styles = {},
3368
+ ...props
3369
+ }) => /*#__PURE__*/React.createElement("svg", _extends$9({
3370
+ width: "54",
3371
+ height: "54",
3372
+ fill: "none",
3373
+ xmlns: "http://www.w3.org/2000/svg"
3374
+ }, props), /*#__PURE__*/React.createElement("path", {
3375
+ fillRule: "evenodd",
3376
+ clipRule: "evenodd",
3377
+ d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1z",
3378
+ fill: "#000"
3379
+ }), /*#__PURE__*/React.createElement("path", {
3380
+ d: "M11 22a1 1 0 011-1h19a1 1 0 011 1v10a1 1 0 01-1 1H12a1 1 0 01-1-1V22z",
3381
+ fill: "#505562"
3382
+ })));
3383
+
3384
+ 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); }
3385
+ var FormIcon = (({
3386
+ styles = {},
3387
+ ...props
3388
+ }) => /*#__PURE__*/React.createElement("svg", _extends$8({
3389
+ xmlns: "http://www.w3.org/2000/svg",
3390
+ width: "54",
3391
+ height: "54"
3392
+ }, props), /*#__PURE__*/React.createElement("rect", {
3393
+ x: "15",
3394
+ y: "17",
3395
+ width: "24",
3396
+ height: "4",
3397
+ rx: "1"
3398
+ }), /*#__PURE__*/React.createElement("rect", {
3399
+ x: "15",
3400
+ y: "25",
3401
+ width: "24",
3402
+ height: "4",
3403
+ rx: "1"
3404
+ }), /*#__PURE__*/React.createElement("rect", {
3405
+ x: "15",
3406
+ y: "33",
3407
+ width: "13",
3408
+ height: "4",
3409
+ rx: "1"
3410
+ })));
3411
+
3412
+ 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); }
3413
+ var ColumnsIcon = (({
3414
+ styles = {},
3415
+ ...props
3416
+ }) => /*#__PURE__*/React.createElement("svg", _extends$7({
3417
+ xmlns: "http://www.w3.org/2000/svg",
3418
+ width: "54",
3419
+ height: "54"
3420
+ }, props), /*#__PURE__*/React.createElement("path", {
3421
+ fillRule: "evenodd",
3422
+ d: "M8 33v5a1 1 0 001 1h4v2H9a3 3 0 01-3-3v-5h2zm18 6v2H15v-2h11zm13 0v2H28v-2h11zm9-6v5a3 3 0 01-3 3h-4v-2h4a1 1 0 00.993-.883L46 38v-5h2zM8 22v9H6v-9h2zm40 0v9h-2v-9h2zm-35-9v2H9a1 1 0 00-.993.883L8 16v4H6v-4a3 3 0 013-3h4zm32 0a3 3 0 013 3v4h-2v-4a1 1 0 00-.883-.993L45 15h-4v-2h4zm-6 0v2H28v-2h11zm-13 0v2H15v-2h11z"
3423
+ })));
3424
+
3425
+ 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); }
3426
+ var NumberIcon = (({
3427
+ styles = {},
3428
+ ...props
3429
+ }) => /*#__PURE__*/React.createElement("svg", _extends$6({
3430
+ xmlns: "http://www.w3.org/2000/svg",
3431
+ width: "54",
3432
+ height: "54"
3433
+ }, props), /*#__PURE__*/React.createElement("path", {
3434
+ fillRule: "evenodd",
3435
+ d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zM35 28.444h7l-3.5 4-3.5-4zM35 26h7l-3.5-4-3.5 4z"
3436
+ })));
3437
+
3438
+ 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); }
3439
+ var RadioIcon = (({
3440
+ styles = {},
3441
+ ...props
3442
+ }) => /*#__PURE__*/React.createElement("svg", _extends$5({
3443
+ xmlns: "http://www.w3.org/2000/svg",
3444
+ width: "54",
3445
+ height: "54"
3446
+ }, props), /*#__PURE__*/React.createElement("path", {
3447
+ 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 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"
3448
+ })));
3449
+
3450
+ 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); }
3451
+ var SelectIcon = (({
3452
+ styles = {},
3453
+ ...props
3454
+ }) => /*#__PURE__*/React.createElement("svg", _extends$4({
3455
+ xmlns: "http://www.w3.org/2000/svg",
3456
+ width: "54",
3457
+ height: "54"
3458
+ }, props), /*#__PURE__*/React.createElement("path", {
3459
+ fillRule: "evenodd",
3460
+ d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zm-12 7h9l-4.5 6-4.5-6z"
3461
+ })));
3462
+
3463
+ 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); }
3464
+ var TextIcon = (({
3465
+ styles = {},
3466
+ ...props
3467
+ }) => /*#__PURE__*/React.createElement("svg", _extends$3({
3468
+ xmlns: "http://www.w3.org/2000/svg",
3469
+ width: "54",
3470
+ height: "54"
3471
+ }, props), /*#__PURE__*/React.createElement("path", {
3472
+ d: "M20.58 33.77h-3l-1.18-3.08H11l-1.1 3.08H7l5.27-13.54h2.89zm-5-5.36l-1.86-5-1.83 5zM22 20.23h5.41a15.47 15.47 0 012.4.14 3.42 3.42 0 011.41.55 3.47 3.47 0 011 1.14 3 3 0 01.42 1.58 3.26 3.26 0 01-1.91 2.94 3.63 3.63 0 011.91 1.22 3.28 3.28 0 01.66 2 4 4 0 01-.43 1.8 3.63 3.63 0 01-1.09 1.4 3.89 3.89 0 01-1.83.65q-.69.07-3.3.09H22zm2.73 2.25v3.13h3.8a1.79 1.79 0 001.1-.49 1.41 1.41 0 00.41-1 1.49 1.49 0 00-.35-1 1.54 1.54 0 00-1-.48c-.27 0-1.05-.05-2.34-.05zm0 5.39v3.62h2.57a11.52 11.52 0 001.88-.09 1.65 1.65 0 001-.54 1.6 1.6 0 00.38-1.14 1.75 1.75 0 00-.29-1 1.69 1.69 0 00-.86-.62 9.28 9.28 0 00-2.41-.23zM44.35 28.79l2.65.84a5.94 5.94 0 01-2 3.29A5.74 5.74 0 0141.38 34a5.87 5.87 0 01-4.44-1.84 7.09 7.09 0 01-1.73-5A7.43 7.43 0 0137 21.87 6 6 0 0141.54 20a5.64 5.64 0 014 1.47A5.33 5.33 0 0147 24l-2.7.65a2.8 2.8 0 00-2.86-2.27A3.09 3.09 0 0039 23.42a5.31 5.31 0 00-.93 3.5 5.62 5.62 0 00.93 3.65 3 3 0 002.4 1.09 2.72 2.72 0 001.82-.66 4 4 0 001.13-2.21z"
3473
+ })));
3474
+
3475
+ 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); }
3476
+ var TextfieldIcon = (({
3477
+ styles = {},
3478
+ ...props
3479
+ }) => /*#__PURE__*/React.createElement("svg", _extends$2({
3480
+ xmlns: "http://www.w3.org/2000/svg",
3481
+ width: "54",
3482
+ height: "54"
3483
+ }, props), /*#__PURE__*/React.createElement("path", {
3484
+ fillRule: "evenodd",
3485
+ d: "M45 16a3 3 0 013 3v16a3 3 0 01-3 3H9a3 3 0 01-3-3V19a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v16a1 1 0 001 1h36a1 1 0 001-1V19a1 1 0 00-1-1zm-32 4v10h-2V22h2z"
3486
+ })));
3487
+
3488
+ 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); }
3489
+ var TextareaIcon = (({
3490
+ styles = {},
3491
+ ...props
3492
+ }) => /*#__PURE__*/React.createElement("svg", _extends$1({
3493
+ xmlns: "http://www.w3.org/2000/svg",
3494
+ width: "54",
3495
+ height: "54"
3496
+ }, props), /*#__PURE__*/React.createElement("path", {
3497
+ fillRule: "evenodd",
3498
+ d: "M45 13a3 3 0 013 3v22a3 3 0 01-3 3H9a3 3 0 01-3-3V16a3 3 0 013-3h36zm0 2H9a1 1 0 00-1 1v22a1 1 0 001 1h36a1 1 0 001-1V16a1 1 0 00-1-1zm-1.136 15.5l.848.849-6.363 6.363-.849-.848 6.364-6.364zm.264 3.5l.849.849-2.828 2.828-.849-.849L44.128 34zM13 19v10h-2V19h2z"
3499
+ })));
3500
+
3501
+ 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); }
3502
+ var ImageIcon = (({
3503
+ styles = {},
3504
+ ...props
3505
+ }) => /*#__PURE__*/React.createElement("svg", _extends({
3506
+ width: "54",
3507
+ height: "54",
3508
+ fill: "none",
3509
+ xmlns: "http://www.w3.org/2000/svg"
3510
+ }, props), /*#__PURE__*/React.createElement("path", {
3511
+ fillRule: "evenodd",
3512
+ clipRule: "evenodd",
3513
+ d: "M34.636 21.91A3.818 3.818 0 1127 21.908a3.818 3.818 0 017.636 0zm-2 0A1.818 1.818 0 1129 21.908a1.818 1.818 0 013.636 0z",
3514
+ fill: "#000"
3515
+ }), /*#__PURE__*/React.createElement("path", {
3516
+ fillRule: "evenodd",
3517
+ clipRule: "evenodd",
3518
+ d: "M15 13a2 2 0 00-2 2v24a2 2 0 002 2h24a2 2 0 002-2V15a2 2 0 00-2-2H15zm24 2H15v12.45l4.71-4.709a1.91 1.91 0 012.702 0l6.695 6.695 2.656-1.77a1.91 1.91 0 012.411.239L39 32.73V15zM15 39v-8.754c.06-.038.116-.083.168-.135l5.893-5.893 6.684 6.685a1.911 1.911 0 002.41.238l2.657-1.77 6.02 6.02c.052.051.108.097.168.135V39H15z",
3519
+ fill: "#000"
3520
+ })));
3521
+
3522
+ const iconsByType = {
3523
+ button: ButtonIcon,
3524
+ checkbox: CheckboxIcon,
3525
+ checklist: ChecklistIcon,
3526
+ columns: ColumnsIcon,
3527
+ datetime: DatetimeIcon,
3528
+ image: ImageIcon,
3529
+ number: NumberIcon,
3530
+ radio: RadioIcon,
3531
+ select: SelectIcon,
3532
+ taglist: TaglistIcon,
3533
+ text: TextIcon,
3534
+ textfield: TextfieldIcon,
3535
+ textarea: TextareaIcon,
3536
+ default: FormIcon
3537
+ };
3538
+
2476
3539
  const type$2 = 'text';
2477
3540
  function Text(props) {
2478
3541
  const {
2479
- field
3542
+ field,
3543
+ disabled
2480
3544
  } = props;
2481
3545
  const {
2482
3546
  text = ''
2483
3547
  } = field;
3548
+ const textValue = useExpressionValue(text) || '';
2484
3549
  return jsx("div", {
2485
3550
  class: formFieldClasses(type$2),
2486
- children: jsx(Markup, {
2487
- markup: safeMarkdown(text),
2488
- trim: false
2489
- })
3551
+ children: renderText(field, textValue, disabled)
2490
3552
  });
2491
3553
  }
2492
3554
  Text.create = function (options = {}) {
@@ -2498,6 +3560,37 @@ Text.create = function (options = {}) {
2498
3560
  Text.type = type$2;
2499
3561
  Text.keyed = false;
2500
3562
 
3563
+ // helper //////////////
3564
+
3565
+ function renderText(field, content, disabled) {
3566
+ const {
3567
+ text
3568
+ } = field;
3569
+ const Icon = iconsByType['text'];
3570
+ if (disabled) {
3571
+ if (!text) {
3572
+ return jsxs("div", {
3573
+ class: "fjs-form-field-placeholder",
3574
+ children: [jsx(Icon, {
3575
+ viewBox: "0 0 54 54"
3576
+ }), "Text view is empty"]
3577
+ });
3578
+ }
3579
+ if (isExpression$2(text)) {
3580
+ return jsxs("div", {
3581
+ class: "fjs-form-field-placeholder",
3582
+ children: [jsx(Icon, {
3583
+ viewBox: "0 0 54 54"
3584
+ }), "Text view is populated by an expression"]
3585
+ });
3586
+ }
3587
+ }
3588
+ return jsx(Markup, {
3589
+ markup: safeMarkdown(content),
3590
+ trim: false
3591
+ });
3592
+ }
3593
+
2501
3594
  const type$1 = 'textfield';
2502
3595
  function Textfield(props) {
2503
3596
  const {
@@ -2510,8 +3603,13 @@ function Textfield(props) {
2510
3603
  description,
2511
3604
  id,
2512
3605
  label,
3606
+ appearance = {},
2513
3607
  validate = {}
2514
3608
  } = field;
3609
+ const {
3610
+ prefixAdorner,
3611
+ suffixAdorner
3612
+ } = appearance;
2515
3613
  const {
2516
3614
  required
2517
3615
  } = validate;
@@ -2535,13 +3633,18 @@ function Textfield(props) {
2535
3633
  id: prefixId(id, formId),
2536
3634
  label: label,
2537
3635
  required: required
2538
- }), jsx("input", {
2539
- class: "fjs-input",
3636
+ }), jsx(InputAdorner, {
2540
3637
  disabled: disabled,
2541
- id: prefixId(id, formId),
2542
- onInput: onChange,
2543
- type: "text",
2544
- value: value
3638
+ pre: prefixAdorner,
3639
+ post: suffixAdorner,
3640
+ children: jsx("input", {
3641
+ class: "fjs-input",
3642
+ disabled: disabled,
3643
+ id: prefixId(id, formId),
3644
+ onInput: onChange,
3645
+ type: "text",
3646
+ value: value
3647
+ })
2545
3648
  }), jsx(Description, {
2546
3649
  description: description
2547
3650
  }), jsx(Errors, {
@@ -2643,7 +3746,7 @@ Textarea.sanitizeValue = ({
2643
3746
  value
2644
3747
  }) => isArray(value) || isObject(value) ? '' : String(value);
2645
3748
 
2646
- const formFields = [Button, Checkbox, Checklist, Default, Image, Numberfield, Radio, Select, Taglist, Text, Textfield, Textarea];
3749
+ const formFields = [Button, Checkbox, Checklist, Default, Image, Numberfield, Datetime, Radio, Select, Taglist, Text, Textfield, Textarea];
2647
3750
 
2648
3751
  class FormFields {
2649
3752
  constructor() {
@@ -3120,5 +4223,5 @@ function createForm(options) {
3120
4223
  });
3121
4224
  }
3122
4225
 
3123
- export { Button, Checkbox, Checklist, Default, Form, FormComponent, FormContext, FormFieldRegistry, FormFields, FormRenderContext, Image, Numberfield, Radio, Select, Taglist, Text, Textarea, Textfield, clone, createForm, createFormContainer, createInjector, findErrors, formFields, generateIdForType, generateIndexForType, getSchemaVariables, isRequired, pathParse, pathStringify, pathsEqual, schemaVersion };
4226
+ export { Button, Checkbox, Checklist, DATETIME_SUBTYPES, DATETIME_SUBTYPES_LABELS, DATETIME_SUBTYPE_PATH, DATE_DISALLOW_PAST_PATH, DATE_LABEL_PATH, Datetime, Default, Form, FormComponent, FormContext, FormFieldRegistry, FormFields, FormRenderContext, Image, MINUTES_IN_DAY, Numberfield, Radio, Select, 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, clone, createForm, createFormContainer, createInjector, findErrors, formFields, generateIdForType, generateIndexForType, getSchemaVariables, getValuesSource, iconsByType, isRequired, pathParse, pathStringify, pathsEqual, schemaVersion };
3124
4227
  //# sourceMappingURL=index.es.js.map