@bpmn-io/properties-panel 0.8.1 → 0.10.2

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 (175) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/assets/properties-panel.css +5 -17
  3. package/dist/index.esm.js +1610 -0
  4. package/dist/index.esm.js.map +1 -0
  5. package/dist/index.js +1651 -0
  6. package/dist/index.js.map +1 -0
  7. package/package.json +17 -7
  8. package/preact/LICENSE +21 -0
  9. package/preact/README.md +185 -0
  10. package/preact/compat/dist/compat.js +2 -0
  11. package/preact/compat/dist/compat.js.map +1 -0
  12. package/preact/compat/dist/compat.mjs +2 -0
  13. package/preact/compat/dist/compat.module.js +2 -0
  14. package/preact/compat/dist/compat.module.js.map +1 -0
  15. package/preact/compat/dist/compat.umd.js +2 -0
  16. package/preact/compat/dist/compat.umd.js.map +1 -0
  17. package/preact/compat/jsx-dev-runtime.js +1 -0
  18. package/preact/compat/jsx-dev-runtime.mjs +1 -0
  19. package/preact/compat/jsx-runtime.js +1 -0
  20. package/preact/compat/jsx-runtime.mjs +1 -0
  21. package/preact/compat/package.json +19 -0
  22. package/preact/compat/server.js +15 -0
  23. package/preact/compat/server.mjs +4 -0
  24. package/preact/compat/src/Children.js +21 -0
  25. package/preact/compat/src/PureComponent.js +15 -0
  26. package/preact/compat/src/forwardRef.js +51 -0
  27. package/preact/compat/src/index.d.ts +140 -0
  28. package/preact/compat/src/index.js +175 -0
  29. package/preact/compat/src/internal.d.ts +47 -0
  30. package/preact/compat/src/memo.js +34 -0
  31. package/preact/compat/src/portals.js +80 -0
  32. package/preact/compat/src/render.js +219 -0
  33. package/preact/compat/src/scheduler.js +24 -0
  34. package/preact/compat/src/suspense-list.d.ts +14 -0
  35. package/preact/compat/src/suspense-list.js +126 -0
  36. package/preact/compat/src/suspense.d.ts +15 -0
  37. package/preact/compat/src/suspense.js +270 -0
  38. package/preact/compat/src/util.js +28 -0
  39. package/preact/compat/test-utils.js +1 -0
  40. package/preact/debug/dist/debug.js +2 -0
  41. package/preact/debug/dist/debug.js.map +1 -0
  42. package/preact/debug/dist/debug.mjs +2 -0
  43. package/preact/debug/dist/debug.module.js +2 -0
  44. package/preact/debug/dist/debug.module.js.map +1 -0
  45. package/preact/debug/dist/debug.umd.js +2 -0
  46. package/preact/debug/dist/debug.umd.js.map +1 -0
  47. package/preact/debug/package.json +18 -0
  48. package/preact/debug/src/check-props.js +54 -0
  49. package/preact/debug/src/component-stack.js +146 -0
  50. package/preact/debug/src/constants.js +3 -0
  51. package/preact/debug/src/debug.js +442 -0
  52. package/preact/debug/src/index.js +6 -0
  53. package/preact/debug/src/internal.d.ts +82 -0
  54. package/preact/debug/src/util.js +11 -0
  55. package/preact/devtools/dist/devtools.js +2 -0
  56. package/preact/devtools/dist/devtools.js.map +1 -0
  57. package/preact/devtools/dist/devtools.mjs +2 -0
  58. package/preact/devtools/dist/devtools.module.js +2 -0
  59. package/preact/devtools/dist/devtools.module.js.map +1 -0
  60. package/preact/devtools/dist/devtools.umd.js +2 -0
  61. package/preact/devtools/dist/devtools.umd.js.map +1 -0
  62. package/preact/devtools/package.json +16 -0
  63. package/preact/devtools/src/devtools.js +10 -0
  64. package/preact/devtools/src/index.d.ts +8 -0
  65. package/preact/devtools/src/index.js +15 -0
  66. package/preact/dist/preact.js +2 -0
  67. package/preact/dist/preact.js.map +1 -0
  68. package/preact/dist/preact.min.js +2 -0
  69. package/preact/dist/preact.min.js.map +1 -0
  70. package/preact/dist/preact.mjs +2 -0
  71. package/preact/dist/preact.module.js +2 -0
  72. package/preact/dist/preact.module.js.map +1 -0
  73. package/preact/dist/preact.umd.js +2 -0
  74. package/preact/dist/preact.umd.js.map +1 -0
  75. package/preact/hooks/dist/hooks.js +2 -0
  76. package/preact/hooks/dist/hooks.js.map +1 -0
  77. package/preact/hooks/dist/hooks.mjs +2 -0
  78. package/preact/hooks/dist/hooks.module.js +2 -0
  79. package/preact/hooks/dist/hooks.module.js.map +1 -0
  80. package/preact/hooks/dist/hooks.umd.js +2 -0
  81. package/preact/hooks/dist/hooks.umd.js.map +1 -0
  82. package/preact/hooks/package.json +26 -0
  83. package/preact/hooks/src/index.d.ts +130 -0
  84. package/preact/hooks/src/index.js +386 -0
  85. package/preact/hooks/src/internal.d.ts +75 -0
  86. package/preact/jsx-runtime/dist/jsxRuntime.js +2 -0
  87. package/preact/jsx-runtime/dist/jsxRuntime.js.map +1 -0
  88. package/preact/jsx-runtime/dist/jsxRuntime.mjs +2 -0
  89. package/preact/jsx-runtime/dist/jsxRuntime.module.js +2 -0
  90. package/preact/jsx-runtime/dist/jsxRuntime.module.js.map +1 -0
  91. package/preact/jsx-runtime/dist/jsxRuntime.umd.js +2 -0
  92. package/preact/jsx-runtime/dist/jsxRuntime.umd.js.map +1 -0
  93. package/preact/jsx-runtime/package.json +19 -0
  94. package/preact/jsx-runtime/src/index.d.ts +50 -0
  95. package/preact/jsx-runtime/src/index.js +72 -0
  96. package/preact/package.json +268 -0
  97. package/preact/src/cjs.js +3 -0
  98. package/preact/src/clone-element.js +39 -0
  99. package/preact/src/component.js +225 -0
  100. package/preact/src/constants.js +3 -0
  101. package/preact/src/create-context.js +68 -0
  102. package/preact/src/create-element.js +100 -0
  103. package/preact/src/diff/catch-error.js +38 -0
  104. package/preact/src/diff/children.js +347 -0
  105. package/preact/src/diff/index.js +516 -0
  106. package/preact/src/diff/props.js +158 -0
  107. package/preact/src/index.d.ts +310 -0
  108. package/preact/src/index.js +13 -0
  109. package/preact/src/internal.d.ts +147 -0
  110. package/preact/src/jsx.d.ts +955 -0
  111. package/preact/src/options.js +17 -0
  112. package/preact/src/render.js +74 -0
  113. package/preact/src/util.js +23 -0
  114. package/preact/test-utils/dist/testUtils.js +2 -0
  115. package/preact/test-utils/dist/testUtils.js.map +1 -0
  116. package/preact/test-utils/dist/testUtils.mjs +2 -0
  117. package/preact/test-utils/dist/testUtils.module.js +2 -0
  118. package/preact/test-utils/dist/testUtils.module.js.map +1 -0
  119. package/preact/test-utils/dist/testUtils.umd.js +2 -0
  120. package/preact/test-utils/dist/testUtils.umd.js.map +1 -0
  121. package/preact/test-utils/package.json +19 -0
  122. package/preact/test-utils/src/index.d.ts +3 -0
  123. package/preact/test-utils/src/index.js +117 -0
  124. package/lib/PropertiesPanel.js +0 -126
  125. package/lib/PropertiesPanel.js.map +0 -1
  126. package/lib/components/DropdownButton.js +0 -109
  127. package/lib/components/DropdownButton.js.map +0 -1
  128. package/lib/components/Group.js +0 -75
  129. package/lib/components/Group.js.map +0 -1
  130. package/lib/components/Header.js +0 -49
  131. package/lib/components/Header.js.map +0 -1
  132. package/lib/components/HeaderButton.js +0 -16
  133. package/lib/components/HeaderButton.js.map +0 -1
  134. package/lib/components/ListGroup.js +0 -167
  135. package/lib/components/ListGroup.js.map +0 -1
  136. package/lib/components/ListItem.js +0 -37
  137. package/lib/components/ListItem.js.map +0 -1
  138. package/lib/components/entries/Checkbox.js +0 -81
  139. package/lib/components/entries/Checkbox.js.map +0 -1
  140. package/lib/components/entries/Collapsible.js +0 -48
  141. package/lib/components/entries/Collapsible.js.map +0 -1
  142. package/lib/components/entries/List.js +0 -204
  143. package/lib/components/entries/List.js.map +0 -1
  144. package/lib/components/entries/NumberField.js +0 -108
  145. package/lib/components/entries/NumberField.js.map +0 -1
  146. package/lib/components/entries/Select.js +0 -107
  147. package/lib/components/entries/Select.js.map +0 -1
  148. package/lib/components/entries/Simple.js +0 -56
  149. package/lib/components/entries/Simple.js.map +0 -1
  150. package/lib/components/entries/TextArea.js +0 -96
  151. package/lib/components/entries/TextArea.js.map +0 -1
  152. package/lib/components/entries/TextField.js +0 -121
  153. package/lib/components/entries/TextField.js.map +0 -1
  154. package/lib/components/entries/ToggleSwitch.js +0 -87
  155. package/lib/components/entries/ToggleSwitch.js.map +0 -1
  156. package/lib/components/icons/index.js +0 -51
  157. package/lib/components/icons/index.js.map +0 -1
  158. package/lib/context/LayoutContext.js +0 -9
  159. package/lib/context/LayoutContext.js.map +0 -1
  160. package/lib/context/index.js +0 -2
  161. package/lib/context/index.js.map +0 -1
  162. package/lib/features/debounce-input/debounceInput.js +0 -14
  163. package/lib/features/debounce-input/debounceInput.js.map +0 -1
  164. package/lib/features/debounce-input/index.js +0 -5
  165. package/lib/features/debounce-input/index.js.map +0 -1
  166. package/lib/hooks/index.js +0 -4
  167. package/lib/hooks/index.js.map +0 -1
  168. package/lib/hooks/useKeyFactory.js +0 -39
  169. package/lib/hooks/useKeyFactory.js.map +0 -1
  170. package/lib/hooks/useLayoutState.js +0 -36
  171. package/lib/hooks/useLayoutState.js.map +0 -1
  172. package/lib/hooks/usePrevious.js +0 -16
  173. package/lib/hooks/usePrevious.js.map +0 -1
  174. package/lib/index.js +0 -2
  175. package/lib/index.js.map +0 -1
package/dist/index.js ADDED
@@ -0,0 +1,1651 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var hooks = require('../preact/hooks');
6
+ var minDash = require('min-dash');
7
+ var classnames = require('classnames');
8
+ var jsxRuntime = require('../preact/jsx-runtime');
9
+ var minDom = require('min-dom');
10
+ var preact = require('../preact');
11
+ require('../preact/compat');
12
+
13
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
14
+
15
+ var classnames__default = /*#__PURE__*/_interopDefaultLegacy(classnames);
16
+
17
+ /**
18
+ * @typedef { { getElementLabel: Function, getTypeLabel: Function, getElementIcon: Function } } HeaderProvider
19
+ */
20
+
21
+ /**
22
+ * @param {Object} props
23
+ * @param {Object} props.element,
24
+ * @param {HeaderProvider} props.headerProvider
25
+ */
26
+ function Header(props) {
27
+ const {
28
+ element,
29
+ headerProvider
30
+ } = props;
31
+ const {
32
+ getElementLabel,
33
+ getTypeLabel,
34
+ getElementIcon
35
+ } = headerProvider;
36
+ const label = getElementLabel(element);
37
+ const type = getTypeLabel(element);
38
+ const ElementIcon = getElementIcon(element);
39
+ return jsxRuntime.jsxs("div", {
40
+ class: "bio-properties-panel-header",
41
+ children: [jsxRuntime.jsx("div", {
42
+ class: "bio-properties-panel-header-icon",
43
+ children: ElementIcon && jsxRuntime.jsx(ElementIcon, {
44
+ width: "32",
45
+ height: "32",
46
+ viewBox: "0 0 32 32"
47
+ })
48
+ }), jsxRuntime.jsxs("div", {
49
+ class: "bio-properties-panel-header-labels",
50
+ children: [jsxRuntime.jsx("div", {
51
+ title: type,
52
+ class: "bio-properties-panel-header-type",
53
+ children: type
54
+ }), getElementLabel(element) ? jsxRuntime.jsx("div", {
55
+ title: label,
56
+ class: "bio-properties-panel-header-label",
57
+ children: label
58
+ }) : null]
59
+ })]
60
+ });
61
+ }
62
+
63
+ /**
64
+ * @pinussilvestrus: we need to introduce our own hook to persist the previous
65
+ * state on updates.
66
+ *
67
+ * cf. https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state
68
+ */
69
+
70
+ function usePrevious(value) {
71
+ const ref = hooks.useRef();
72
+ hooks.useEffect(() => {
73
+ ref.current = value;
74
+ });
75
+ return ref.current;
76
+ }
77
+
78
+ const KEY_LENGTH = 6;
79
+ /**
80
+ * Create a persistent key factory for plain objects without id.
81
+ *
82
+ * @example
83
+ * ```jsx
84
+ * function List({ objects }) {
85
+ * const getKey = useKeyFactory();
86
+ * return (<ol>{
87
+ * objects.map(obj => {
88
+ * const key = getKey(obj);
89
+ * return <li key={key}>obj.name</li>
90
+ * })
91
+ * }</ol>);
92
+ * }
93
+ * ```
94
+ *
95
+ * @param {any[]} dependencies
96
+ * @returns {(element: object) => string}
97
+ */
98
+
99
+ function useKeyFactory(dependencies = []) {
100
+ const map = hooks.useMemo(() => new Map(), dependencies);
101
+
102
+ const getKey = el => {
103
+ let key = map.get(el);
104
+
105
+ if (!key) {
106
+ key = Math.random().toString().slice(-KEY_LENGTH);
107
+ map.set(el, key);
108
+ }
109
+
110
+ return key;
111
+ };
112
+
113
+ return getKey;
114
+ }
115
+
116
+ const DescriptionContext = preact.createContext({
117
+ description: {},
118
+ getDescriptionForId: () => {}
119
+ });
120
+
121
+ const LayoutContext = preact.createContext({
122
+ layout: {},
123
+ setLayout: () => {},
124
+ getLayoutForKey: () => {},
125
+ setLayoutForKey: () => {}
126
+ });
127
+
128
+ /**
129
+ * Creates a state that persists in the global LayoutContext.
130
+ *
131
+ * @example
132
+ * ```jsx
133
+ * function Group(props) {
134
+ * const [ open, setOpen ] = useLayoutState([ 'groups', 'foo', 'open' ], false);
135
+ * }
136
+ * ```
137
+ *
138
+ * @param {(string|number)[]} path
139
+ * @param {any} [defaultValue]
140
+ *
141
+ * @returns {[ any, Function ]}
142
+ */
143
+
144
+ function useLayoutState(path, defaultValue) {
145
+ const {
146
+ getLayoutForKey,
147
+ setLayoutForKey
148
+ } = hooks.useContext(LayoutContext);
149
+ const layoutForKey = getLayoutForKey(path, defaultValue);
150
+ const [value, set] = hooks.useState(layoutForKey);
151
+
152
+ const setState = newValue => {
153
+ // (1) set component state
154
+ set(newValue); // (2) set context
155
+
156
+ setLayoutForKey(path, newValue);
157
+ };
158
+
159
+ return [value, setState];
160
+ }
161
+
162
+ /**
163
+ * Accesses the global DescriptionContext and returns a description for a given id and element.
164
+ *
165
+ * @example
166
+ * ```jsx
167
+ * function TextField(props) {
168
+ * const description = useDescriptionContext('input1', element);
169
+ * }
170
+ * ```
171
+ *
172
+ * @param {string} id
173
+ * @param {djs.model.Base} element
174
+ *
175
+ * @returns {string}
176
+ */
177
+
178
+ function useDescriptionContext(id, element) {
179
+ const {
180
+ getDescriptionForId
181
+ } = hooks.useContext(DescriptionContext);
182
+ return getDescriptionForId(id, element);
183
+ }
184
+
185
+ var ArrowIcon = function ArrowIcon(props) {
186
+ return jsxRuntime.jsx("svg", { ...props,
187
+ children: jsxRuntime.jsx("path", {
188
+ fillRule: "evenodd",
189
+ d: "m11.657 8-4.95 4.95a1 1 0 0 1-1.414-1.414L8.828 8 5.293 4.464A1 1 0 1 1 6.707 3.05L11.657 8z"
190
+ })
191
+ });
192
+ };
193
+
194
+ ArrowIcon.defaultProps = {
195
+ xmlns: "http://www.w3.org/2000/svg",
196
+ width: "16",
197
+ height: "16"
198
+ };
199
+
200
+ var CreateIcon = function CreateIcon(props) {
201
+ return jsxRuntime.jsx("svg", { ...props,
202
+ children: jsxRuntime.jsx("path", {
203
+ fillRule: "evenodd",
204
+ d: "M9 13V9h4a1 1 0 0 0 0-2H9V3a1 1 0 1 0-2 0v4H3a1 1 0 1 0 0 2h4v4a1 1 0 0 0 2 0z"
205
+ })
206
+ });
207
+ };
208
+
209
+ CreateIcon.defaultProps = {
210
+ xmlns: "http://www.w3.org/2000/svg",
211
+ width: "16",
212
+ height: "16"
213
+ };
214
+
215
+ var DeleteIcon = function DeleteIcon(props) {
216
+ return jsxRuntime.jsx("svg", { ...props,
217
+ children: jsxRuntime.jsx("path", {
218
+ fillRule: "evenodd",
219
+ d: "M12 6v7c0 1.1-.4 1.55-1.5 1.55h-5C4.4 14.55 4 14.1 4 13V6h8zm-1.5 1.5h-5v4.3c0 .66.5 1.2 1.111 1.2H9.39c.611 0 1.111-.54 1.111-1.2V7.5zM13 3h-2l-1-1H6L5 3H3v1.5h10V3z"
220
+ })
221
+ });
222
+ };
223
+
224
+ DeleteIcon.defaultProps = {
225
+ xmlns: "http://www.w3.org/2000/svg",
226
+ width: "16",
227
+ height: "16"
228
+ };
229
+
230
+ function Group(props) {
231
+ const {
232
+ id,
233
+ entries = [],
234
+ label
235
+ } = props;
236
+ const [open, setOpen] = useLayoutState(['groups', id, 'open'], false);
237
+
238
+ const toggleOpen = () => setOpen(!open);
239
+
240
+ const [edited, setEdited] = hooks.useState(false); // set edited state depending on all entries
241
+
242
+ hooks.useEffect(() => {
243
+ const hasOneEditedEntry = entries.find(entry => {
244
+ const {
245
+ id,
246
+ isEdited
247
+ } = entry;
248
+ const entryNode = minDom.query(`[data-entry-id="${id}"]`);
249
+
250
+ if (!minDash.isFunction(isEdited) || !entryNode) {
251
+ return false;
252
+ }
253
+
254
+ const inputNode = minDom.query('.bio-properties-panel-input', entryNode);
255
+ return isEdited(inputNode);
256
+ });
257
+ setEdited(hasOneEditedEntry);
258
+ }, [entries]);
259
+ return jsxRuntime.jsxs("div", {
260
+ class: "bio-properties-panel-group",
261
+ "data-group-id": 'group-' + id,
262
+ children: [jsxRuntime.jsxs("div", {
263
+ class: classnames__default["default"]('bio-properties-panel-group-header', edited ? '' : 'empty', open ? 'open' : ''),
264
+ onClick: toggleOpen,
265
+ children: [jsxRuntime.jsx("div", {
266
+ title: label,
267
+ class: "bio-properties-panel-group-header-title",
268
+ children: label
269
+ }), jsxRuntime.jsxs("div", {
270
+ class: "bio-properties-panel-group-header-buttons",
271
+ children: [edited && jsxRuntime.jsx(DataMarker, {}), jsxRuntime.jsx("button", {
272
+ title: "Toggle section",
273
+ class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
274
+ children: jsxRuntime.jsx(ArrowIcon, {
275
+ class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
276
+ })
277
+ })]
278
+ })]
279
+ }), jsxRuntime.jsx("div", {
280
+ class: classnames__default["default"]('bio-properties-panel-group-entries', open ? 'open' : ''),
281
+ children: entries.map(e => e.component)
282
+ })]
283
+ });
284
+ }
285
+
286
+ function DataMarker() {
287
+ return jsxRuntime.jsx("div", {
288
+ title: "Section contains data",
289
+ class: "bio-properties-panel-dot"
290
+ });
291
+ }
292
+
293
+ const DEFAULT_LAYOUT = {
294
+ open: true
295
+ };
296
+ const DEFAULT_DESCRIPTION = {};
297
+ /**
298
+ * @typedef { {
299
+ * component: import('preact').ComponentChild,
300
+ * id: String,
301
+ * isEdited?: Function
302
+ * } } EntryDefinition
303
+ *
304
+ * @typedef { {
305
+ * autoFocusEntry: String,
306
+ * autoOpen?: Boolean,
307
+ * entries: Array<EntryDefinition>,
308
+ * id: String,
309
+ * label: String,
310
+ * remove: (event: MouseEvent) => void
311
+ * } } ListItemDefinition
312
+ *
313
+ * @typedef { {
314
+ * add: (event: MouseEvent) => void,
315
+ * component: import('preact').Component,
316
+ * element: Object,
317
+ * id: String,
318
+ * items: Array<ListItemDefinition>,
319
+ * label: String,
320
+ * shouldSort?: Boolean,
321
+ * shouldOpen?: Boolean
322
+ * } } ListGroupDefinition
323
+ *
324
+ * @typedef { {
325
+ * component?: import('preact').Component,
326
+ * entries: Array<EntryDefinition>,
327
+ * id: String,
328
+ * label: String
329
+ * } } GroupDefinition
330
+ *
331
+ * @typedef { {
332
+ * [id: String]: GetDescriptionFunction
333
+ * } } DescriptionConfig
334
+ *
335
+ * @callback { {
336
+ * @param {string} id
337
+ * @param {djs.model.base} element
338
+ * @returns {string}
339
+ * } } GetDescriptionFunction
340
+ *
341
+ */
342
+
343
+ /**
344
+ * A basic properties panel component. Describes *how* content will be rendered, accepts
345
+ * data from implementor to describe *what* will be rendered.
346
+ *
347
+ * @param {Object} props
348
+ * @param {Object} props.element
349
+ * @param {import('./components/Header').HeaderProvider} props.headerProvider
350
+ * @param {Array<GroupDefinition|ListGroupDefinition>} props.groups
351
+ * @param {Object} [props.layoutConfig]
352
+ * @param {Function} [props.layoutChanged]
353
+ * @param {DescriptionConfig} [props.descriptionConfig]
354
+ * @param {Function} [props.descriptionLoaded]
355
+ */
356
+
357
+ function PropertiesPanel(props) {
358
+ const {
359
+ element,
360
+ headerProvider,
361
+ groups,
362
+ layoutConfig = {},
363
+ layoutChanged,
364
+ descriptionConfig = {},
365
+ descriptionLoaded
366
+ } = props; // set-up layout context
367
+
368
+ const [layout, setLayout] = hooks.useState(createLayout(layoutConfig));
369
+ hooks.useEffect(() => {
370
+ if (typeof layoutChanged === 'function') {
371
+ layoutChanged(layout);
372
+ }
373
+ }, [layout, layoutChanged]);
374
+
375
+ const getLayoutForKey = (key, defaultValue) => {
376
+ return minDash.get(layout, key, defaultValue);
377
+ };
378
+
379
+ const setLayoutForKey = (key, config) => {
380
+ const newLayout = minDash.assign({}, layout);
381
+ minDash.set(newLayout, key, config);
382
+ setLayout(newLayout);
383
+ };
384
+
385
+ const layoutContext = {
386
+ layout,
387
+ setLayout,
388
+ getLayoutForKey,
389
+ setLayoutForKey
390
+ }; // set-up description context
391
+
392
+ const description = createDescriptionContext(descriptionConfig);
393
+
394
+ if (typeof descriptionLoaded === 'function') {
395
+ descriptionLoaded(description);
396
+ }
397
+
398
+ const getDescriptionForId = (id, element) => {
399
+ return description[id] && description[id](element);
400
+ };
401
+
402
+ const descriptionContext = {
403
+ description,
404
+ getDescriptionForId
405
+ };
406
+
407
+ if (!element) {
408
+ return jsxRuntime.jsx("div", {
409
+ class: "bio-properties-panel-placeholder",
410
+ children: "Select an element to edit its properties."
411
+ });
412
+ }
413
+
414
+ return jsxRuntime.jsx(DescriptionContext.Provider, {
415
+ value: descriptionContext,
416
+ children: jsxRuntime.jsx(LayoutContext.Provider, {
417
+ value: layoutContext,
418
+ children: jsxRuntime.jsxs("div", {
419
+ class: classnames__default["default"]('bio-properties-panel', layout.open ? 'open' : ''),
420
+ children: [jsxRuntime.jsx(Header, {
421
+ element: element,
422
+ headerProvider: headerProvider
423
+ }), jsxRuntime.jsx("div", {
424
+ class: "bio-properties-panel-scroll-container",
425
+ children: groups.map(group => {
426
+ const {
427
+ component: GroupComponent = Group,
428
+ id
429
+ } = group;
430
+ return jsxRuntime.jsx(GroupComponent, {
431
+ element: element,
432
+ ...group
433
+ }, id);
434
+ })
435
+ })]
436
+ })
437
+ })
438
+ });
439
+ } // helpers //////////////////
440
+
441
+ function createLayout(overrides) {
442
+ return { ...DEFAULT_LAYOUT,
443
+ ...overrides
444
+ };
445
+ }
446
+
447
+ function createDescriptionContext(overrides) {
448
+ return { ...DEFAULT_DESCRIPTION,
449
+ ...overrides
450
+ };
451
+ }
452
+
453
+ function DropdownButton(props) {
454
+ const {
455
+ class: className,
456
+ children,
457
+ menuItems = []
458
+ } = props;
459
+ const dropdownRef = hooks.useRef(null);
460
+ const menuRef = hooks.useRef(null);
461
+ const [open, setOpen] = hooks.useState(false);
462
+
463
+ const close = () => setOpen(false);
464
+
465
+ function onDropdownToggle(event) {
466
+ if (menuRef.current && menuRef.current.contains(event.target)) {
467
+ return;
468
+ }
469
+
470
+ event.stopPropagation();
471
+ setOpen(open => !open);
472
+ }
473
+
474
+ function onActionClick(event, action) {
475
+ event.stopPropagation();
476
+ close();
477
+ action();
478
+ }
479
+
480
+ useGlobalClick([dropdownRef.current], () => close());
481
+ return jsxRuntime.jsxs("div", {
482
+ class: classnames__default["default"]('bio-properties-panel-dropdown-button', {
483
+ open
484
+ }, className),
485
+ onClick: onDropdownToggle,
486
+ ref: dropdownRef,
487
+ children: [children, jsxRuntime.jsx("div", {
488
+ class: "bio-properties-panel-dropdown-button__menu",
489
+ ref: menuRef,
490
+ children: menuItems.map((item, index) => jsxRuntime.jsx(MenuItem, {
491
+ onClick: onActionClick,
492
+ item: item
493
+ }, index))
494
+ })]
495
+ });
496
+ }
497
+
498
+ function MenuItem({
499
+ item,
500
+ onClick
501
+ }) {
502
+ if (item.separator) {
503
+ return jsxRuntime.jsx("div", {
504
+ class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--separator"
505
+ });
506
+ }
507
+
508
+ if (item.action) {
509
+ return jsxRuntime.jsx("button", {
510
+ class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--actionable",
511
+ onClick: event => onClick(event, item.action),
512
+ children: item.entry
513
+ });
514
+ }
515
+
516
+ return jsxRuntime.jsx("div", {
517
+ class: "bio-properties-panel-dropdown-button__menu-item",
518
+ children: item.entry
519
+ });
520
+ }
521
+ /**
522
+ *
523
+ * @param {Array<null | Element>} ignoredElements
524
+ * @param {Function} callback
525
+ */
526
+
527
+
528
+ function useGlobalClick(ignoredElements, callback) {
529
+ hooks.useEffect(() => {
530
+ /**
531
+ * @param {MouseEvent} event
532
+ */
533
+ function listener(event) {
534
+ if (ignoredElements.some(element => element && element.contains(event.target))) {
535
+ return;
536
+ }
537
+
538
+ callback();
539
+ }
540
+
541
+ document.addEventListener('click', listener, {
542
+ capture: true
543
+ });
544
+ return () => document.removeEventListener('click', listener, {
545
+ capture: true
546
+ });
547
+ }, [...ignoredElements, callback]);
548
+ }
549
+
550
+ function HeaderButton(props) {
551
+ const {
552
+ children = null,
553
+ class: classname,
554
+ onClick = () => {},
555
+ ...otherProps
556
+ } = props;
557
+ return jsxRuntime.jsx("button", { ...otherProps,
558
+ onClick: onClick,
559
+ class: classnames__default["default"]('bio-properties-panel-group-header-button', classname),
560
+ children: children
561
+ });
562
+ }
563
+
564
+ function CollapsibleEntry(props) {
565
+ const {
566
+ id,
567
+ entries = [],
568
+ label,
569
+ remove,
570
+ open: shouldOpen
571
+ } = props;
572
+ const [open, setOpen] = hooks.useState(shouldOpen);
573
+
574
+ const toggleOpen = () => setOpen(!open); // todo(pinussilvestrus): translate once we have a translate mechanism for the core
575
+
576
+
577
+ const placeholderLabel = '<empty>';
578
+ return jsxRuntime.jsxs("div", {
579
+ "data-entry-id": id,
580
+ class: classnames__default["default"]('bio-properties-panel-collapsible-entry', open ? 'open' : ''),
581
+ children: [jsxRuntime.jsxs("div", {
582
+ class: "bio-properties-panel-collapsible-entry-header",
583
+ onClick: toggleOpen,
584
+ children: [jsxRuntime.jsx("div", {
585
+ title: label || placeholderLabel,
586
+ class: classnames__default["default"]('bio-properties-panel-collapsible-entry-header-title', !label && 'empty'),
587
+ children: label || placeholderLabel
588
+ }), jsxRuntime.jsx("button", {
589
+ title: "Toggle list item",
590
+ class: "bio-properties-panel-arrow bio-properties-panel-collapsible-entry-arrow",
591
+ children: jsxRuntime.jsx(ArrowIcon, {
592
+ class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
593
+ })
594
+ }), remove ? jsxRuntime.jsx("button", {
595
+ title: "Delete item",
596
+ class: "bio-properties-panel-remove-entry",
597
+ onClick: remove,
598
+ children: jsxRuntime.jsx(DeleteIcon, {})
599
+ }) : null]
600
+ }), jsxRuntime.jsx("div", {
601
+ class: classnames__default["default"]('bio-properties-panel-collapsible-entry-entries', open ? 'open' : ''),
602
+ children: entries.map(e => e.component)
603
+ })]
604
+ });
605
+ }
606
+
607
+ function ListItem(props) {
608
+ const {
609
+ autoOpen,
610
+ autoFocusEntry
611
+ } = props; // focus specified entry on auto open
612
+
613
+ hooks.useEffect(() => {
614
+ if (autoOpen && autoFocusEntry) {
615
+ const entry = minDom.query(`[data-entry-id="${autoFocusEntry}"]`);
616
+ const focusableInput = minDom.query('.bio-properties-panel-input', entry);
617
+
618
+ if (focusableInput) {
619
+ if (minDash.isFunction(focusableInput.select)) {
620
+ focusableInput.select();
621
+ } else if (minDash.isFunction(focusableInput.focus)) {
622
+ focusableInput.focus();
623
+ }
624
+ }
625
+ }
626
+ }, [autoOpen, autoFocusEntry]);
627
+ return jsxRuntime.jsx("div", {
628
+ class: "bio-properties-panel-list-item",
629
+ children: jsxRuntime.jsx(CollapsibleEntry, { ...props,
630
+ open: autoOpen
631
+ })
632
+ });
633
+ }
634
+
635
+ const noop = () => {};
636
+ /**
637
+ * @param {import('../PropertiesPanel').ListGroupDefinition} props
638
+ */
639
+
640
+
641
+ function ListGroup(props) {
642
+ const {
643
+ element,
644
+ id,
645
+ items,
646
+ label,
647
+ add,
648
+ shouldSort = true,
649
+ shouldOpen = true
650
+ } = props;
651
+ const [open, setOpen] = useLayoutState(['groups', id, 'open'], false);
652
+ const [ordering, setOrdering] = hooks.useState([]);
653
+ const [newItemAdded, setNewItemAdded] = hooks.useState(false);
654
+ const prevItems = usePrevious(items);
655
+ const prevElement = usePrevious(element);
656
+ const elementChanged = element !== prevElement;
657
+ const shouldHandleEffects = !elementChanged && (shouldSort || shouldOpen); // reset initial ordering when element changes (before first render)
658
+
659
+ if (elementChanged) {
660
+ setOrdering(createOrdering(shouldSort ? sortItems(items) : items));
661
+ } // keep ordering in sync to items - and open changes
662
+ // (0) set initial ordering from given items
663
+
664
+
665
+ hooks.useEffect(() => {
666
+ if (!prevItems || !shouldSort) {
667
+ setOrdering(createOrdering(items));
668
+ }
669
+ }, [items, element]); // (1) items were added
670
+
671
+ hooks.useEffect(() => {
672
+ if (shouldHandleEffects && prevItems && items.length > prevItems.length) {
673
+ let add = [];
674
+ items.forEach(item => {
675
+ if (!ordering.includes(item.id)) {
676
+ add.push(item.id);
677
+ }
678
+ });
679
+ let newOrdering = ordering; // open if not open and configured
680
+
681
+ if (!open && shouldOpen) {
682
+ toggleOpen(); // if I opened and I should sort, then sort items
683
+
684
+ if (shouldSort) {
685
+ newOrdering = createOrdering(sortItems(items));
686
+ }
687
+ } // add new items on top or bottom depending on sorting behavior
688
+
689
+
690
+ newOrdering = newOrdering.filter(item => !add.includes(item));
691
+
692
+ if (shouldSort) {
693
+ newOrdering.unshift(...add);
694
+ } else {
695
+ newOrdering.push(...add);
696
+ }
697
+
698
+ setOrdering(newOrdering);
699
+ setNewItemAdded(true);
700
+ } else {
701
+ setNewItemAdded(false);
702
+ }
703
+ }, [items, open, shouldHandleEffects]); // (2) sort items on open if shouldSort is set
704
+
705
+ hooks.useEffect(() => {
706
+ if (shouldSort && open && !newItemAdded) {
707
+ setOrdering(createOrdering(sortItems(items)));
708
+ }
709
+ }, [open, shouldSort]); // (3) items were deleted
710
+
711
+ hooks.useEffect(() => {
712
+ if (shouldHandleEffects && prevItems && items.length < prevItems.length) {
713
+ let keep = [];
714
+ ordering.forEach(o => {
715
+ if (getItem(items, o)) {
716
+ keep.push(o);
717
+ }
718
+ });
719
+ setOrdering(keep);
720
+ }
721
+ }, [items, shouldHandleEffects]);
722
+
723
+ const toggleOpen = () => setOpen(!open);
724
+
725
+ const hasItems = !!items.length;
726
+ return jsxRuntime.jsxs("div", {
727
+ class: "bio-properties-panel-group",
728
+ "data-group-id": 'group-' + id,
729
+ children: [jsxRuntime.jsxs("div", {
730
+ class: classnames__default["default"]('bio-properties-panel-group-header', hasItems ? '' : 'empty', hasItems && open ? 'open' : ''),
731
+ onClick: hasItems ? toggleOpen : noop,
732
+ children: [jsxRuntime.jsx("div", {
733
+ title: label,
734
+ class: "bio-properties-panel-group-header-title",
735
+ children: label
736
+ }), jsxRuntime.jsxs("div", {
737
+ class: "bio-properties-panel-group-header-buttons",
738
+ children: [add ? jsxRuntime.jsxs("button", {
739
+ title: "Create new list item",
740
+ class: "bio-properties-panel-group-header-button bio-properties-panel-add-entry",
741
+ onClick: add,
742
+ children: [jsxRuntime.jsx(CreateIcon, {}), !hasItems ? jsxRuntime.jsx("span", {
743
+ class: "bio-properties-panel-add-entry-label",
744
+ children: "Create"
745
+ }) : null]
746
+ }) : null, hasItems ? jsxRuntime.jsx("div", {
747
+ title: `List contains ${items.length} item${items.length != 1 ? 's' : ''}`,
748
+ class: "bio-properties-panel-list-badge",
749
+ children: items.length
750
+ }) : null, hasItems ? jsxRuntime.jsx("button", {
751
+ title: "Toggle section",
752
+ class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
753
+ children: jsxRuntime.jsx(ArrowIcon, {
754
+ class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
755
+ })
756
+ }) : null]
757
+ })]
758
+ }), jsxRuntime.jsx("div", {
759
+ class: classnames__default["default"]('bio-properties-panel-list', open && hasItems ? 'open' : ''),
760
+ children: ordering.map((o, index) => {
761
+ const item = getItem(items, o);
762
+
763
+ if (!item) {
764
+ return;
765
+ }
766
+
767
+ return jsxRuntime.jsx(ListItem, {
768
+ // if item was added, open first or last item based on ordering
769
+ autoOpen: newItemAdded && (shouldSort ? index === 0 : index === ordering.length - 1),
770
+ ...item
771
+ }, item.id);
772
+ })
773
+ })]
774
+ });
775
+ } // helpers ////////////////////
776
+
777
+ /**
778
+ * Sorts given items alphanumeric by label
779
+ */
780
+
781
+ function sortItems(items) {
782
+ return minDash.sortBy(items, i => i.label.toLowerCase());
783
+ }
784
+
785
+ function getItem(items, id) {
786
+ return minDash.find(items, i => i.id === id);
787
+ }
788
+
789
+ function createOrdering(items) {
790
+ return items.map(i => i.id);
791
+ }
792
+
793
+ function Description(props) {
794
+ const {
795
+ element,
796
+ forId,
797
+ value
798
+ } = props;
799
+ const contextDescription = useDescriptionContext(forId, element);
800
+ const description = value || contextDescription;
801
+
802
+ if (description) {
803
+ return jsxRuntime.jsx("div", {
804
+ class: "bio-properties-panel-description",
805
+ children: description
806
+ });
807
+ }
808
+ }
809
+
810
+ function Checkbox(props) {
811
+ const {
812
+ id,
813
+ label,
814
+ onChange,
815
+ disabled,
816
+ value = false
817
+ } = props;
818
+
819
+ const handleChange = ({
820
+ target
821
+ }) => {
822
+ onChange(target.checked);
823
+ };
824
+
825
+ return jsxRuntime.jsxs("div", {
826
+ class: "bio-properties-panel-checkbox",
827
+ children: [jsxRuntime.jsx("input", {
828
+ id: prefixId$6(id),
829
+ name: id,
830
+ type: "checkbox",
831
+ class: "bio-properties-panel-input",
832
+ onChange: handleChange,
833
+ checked: value,
834
+ disabled: disabled
835
+ }), jsxRuntime.jsx("label", {
836
+ for: prefixId$6(id),
837
+ class: "bio-properties-panel-label",
838
+ children: label
839
+ })]
840
+ });
841
+ }
842
+ /**
843
+ * @param {Object} props
844
+ * @param {Object} props.element
845
+ * @param {String} props.id
846
+ * @param {String} props.description
847
+ * @param {String} props.label
848
+ * @param {Function} props.getValue
849
+ * @param {Function} props.setValue
850
+ * @param {boolean} [props.disabled]
851
+ */
852
+
853
+
854
+ function CheckboxEntry(props) {
855
+ const {
856
+ element,
857
+ id,
858
+ description,
859
+ label,
860
+ getValue,
861
+ setValue,
862
+ disabled
863
+ } = props;
864
+ const value = getValue(element);
865
+ return jsxRuntime.jsxs("div", {
866
+ class: "bio-properties-panel-entry bio-properties-panel-checkbox-entry",
867
+ "data-entry-id": id,
868
+ children: [jsxRuntime.jsx(Checkbox, {
869
+ id: id,
870
+ label: label,
871
+ onChange: setValue,
872
+ value: value,
873
+ disabled: disabled
874
+ }), jsxRuntime.jsx(Description, {
875
+ forId: id,
876
+ element: element,
877
+ value: description
878
+ })]
879
+ });
880
+ }
881
+ function isEdited$6(node) {
882
+ return node && !!node.checked;
883
+ } // helpers /////////////////
884
+
885
+ function prefixId$6(id) {
886
+ return `bio-properties-panel-${id}`;
887
+ }
888
+
889
+ function List(props) {
890
+ const {
891
+ id,
892
+ element,
893
+ items = [],
894
+ renderItem,
895
+ label = '<empty>',
896
+ open: shouldOpen,
897
+ onAdd,
898
+ onRemove,
899
+ autoFocusEntry,
900
+ compareFn
901
+ } = props;
902
+ const [open, setOpen] = hooks.useState(!!shouldOpen);
903
+ const hasItems = !!items.length;
904
+
905
+ const toggleOpen = () => hasItems && setOpen(!open);
906
+
907
+ const opening = !usePrevious(open) && open;
908
+ const elementChanged = usePrevious(element) !== element;
909
+ const shouldReset = opening || elementChanged;
910
+ const sortedItems = useSortedItems(items, compareFn, shouldReset);
911
+ const newItems = useNewItems(items, elementChanged);
912
+ hooks.useEffect(() => {
913
+ if (open && !hasItems) {
914
+ setOpen(false);
915
+ }
916
+ }, [open, hasItems]);
917
+ /**
918
+ * @param {MouseEvent} event
919
+ */
920
+
921
+ function addItem(event) {
922
+ event.stopPropagation();
923
+ onAdd();
924
+
925
+ if (!open) {
926
+ setOpen(true);
927
+ }
928
+ }
929
+
930
+ return jsxRuntime.jsxs("div", {
931
+ "data-entry-id": id,
932
+ class: classnames__default["default"]('bio-properties-panel-entry', 'bio-properties-panel-list-entry', hasItems ? '' : 'empty', open ? 'open' : ''),
933
+ children: [jsxRuntime.jsxs("div", {
934
+ class: "bio-properties-panel-list-entry-header",
935
+ onClick: toggleOpen,
936
+ children: [jsxRuntime.jsx("div", {
937
+ title: label,
938
+ class: classnames__default["default"]('bio-properties-panel-list-entry-header-title', open && 'open'),
939
+ children: label
940
+ }), jsxRuntime.jsxs("div", {
941
+ class: "bio-properties-panel-list-entry-header-buttons",
942
+ children: [jsxRuntime.jsxs("button", {
943
+ title: "Create new list item",
944
+ onClick: addItem,
945
+ class: "bio-properties-panel-add-entry",
946
+ children: [jsxRuntime.jsx(CreateIcon, {}), !hasItems ? jsxRuntime.jsx("span", {
947
+ class: "bio-properties-panel-add-entry-label",
948
+ children: "Create"
949
+ }) : null]
950
+ }), hasItems && jsxRuntime.jsx("div", {
951
+ title: `List contains ${items.length} item${items.length != 1 ? 's' : ''}`,
952
+ class: "bio-properties-panel-list-badge",
953
+ children: items.length
954
+ }), hasItems && jsxRuntime.jsx("button", {
955
+ title: "Toggle list item",
956
+ class: "bio-properties-panel-arrow",
957
+ children: jsxRuntime.jsx(ArrowIcon, {
958
+ class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
959
+ })
960
+ })]
961
+ })]
962
+ }), hasItems && jsxRuntime.jsx(ItemsList, {
963
+ autoFocusEntry: autoFocusEntry,
964
+ id: id,
965
+ open: open,
966
+ items: sortedItems,
967
+ newItems: newItems,
968
+ onRemove: onRemove,
969
+ renderItem: renderItem
970
+ })]
971
+ });
972
+ }
973
+
974
+ function ItemsList(props) {
975
+ const {
976
+ autoFocusEntry,
977
+ id,
978
+ items,
979
+ newItems,
980
+ open,
981
+ onRemove,
982
+ renderItem
983
+ } = props;
984
+ const getKey = useKeyFactory();
985
+ const newItem = newItems[0];
986
+ hooks.useEffect(() => {
987
+ if (newItem && autoFocusEntry) {
988
+ // (0) select the parent entry (containing all list items)
989
+ const entry = minDom.query(`[data-entry-id="${id}"]`); // (1) select the first input or a custom element to be focussed
990
+
991
+ const selector = typeof autoFocusEntry === 'boolean' ? '.bio-properties-panel-input' : autoFocusEntry;
992
+ const focusableInput = minDom.query(selector, entry); // (2) set focus
993
+
994
+ if (focusableInput) {
995
+ if (minDash.isFunction(focusableInput.select)) {
996
+ focusableInput.select();
997
+ } else if (minDash.isFunction(focusableInput.focus)) {
998
+ focusableInput.focus();
999
+ }
1000
+ }
1001
+ }
1002
+ }, [newItem, autoFocusEntry, id]);
1003
+ return jsxRuntime.jsx("ol", {
1004
+ class: classnames__default["default"]('bio-properties-panel-list-entry-items', open ? 'open' : ''),
1005
+ children: items.map((item, index) => {
1006
+ const key = getKey(item);
1007
+ return jsxRuntime.jsxs("li", {
1008
+ class: "bio-properties-panel-list-entry-item",
1009
+ children: [renderItem(item, index, item === newItem), onRemove && jsxRuntime.jsx("button", {
1010
+ type: "button",
1011
+ title: "Delete item",
1012
+ class: "bio-properties-panel-remove-entry bio-properties-panel-remove-list-entry",
1013
+ onClick: () => onRemove && onRemove(item),
1014
+ children: jsxRuntime.jsx(DeleteIcon, {})
1015
+ })]
1016
+ }, key);
1017
+ })
1018
+ });
1019
+ }
1020
+ /**
1021
+ * Place new items in the beginning of the list and sort the rest with provided function.
1022
+ *
1023
+ * @template Item
1024
+ * @param {Item[]} currentItems
1025
+ * @param {(a: Item, b: Item) => 0 | 1 | -1} [compareFn] function used to sort items
1026
+ * @param {boolean} [shouldReset=false] set to `true` to reset state of the hook
1027
+ * @returns {Item[]}
1028
+ */
1029
+
1030
+
1031
+ function useSortedItems(currentItems, compareFn, shouldReset = false) {
1032
+ const itemsRef = hooks.useRef(currentItems.slice()); // (1) Reset and optionally sort.
1033
+
1034
+ if (shouldReset) {
1035
+ itemsRef.current = currentItems.slice();
1036
+
1037
+ if (compareFn) {
1038
+ itemsRef.current.sort(compareFn);
1039
+ }
1040
+ } else {
1041
+ const items = itemsRef.current; // (2) Add new item to the list.
1042
+
1043
+ for (const item of currentItems) {
1044
+ if (!items.includes(item)) {
1045
+ // Unshift or push depending on whether we have a compareFn
1046
+ compareFn ? items.unshift(item) : items.push(item);
1047
+ }
1048
+ } // (3) Filter out removed items.
1049
+
1050
+
1051
+ itemsRef.current = items.filter(item => currentItems.includes(item));
1052
+ }
1053
+
1054
+ return itemsRef.current;
1055
+ }
1056
+
1057
+ function useNewItems(items = [], shouldReset) {
1058
+ const previousItems = usePrevious(items.slice()) || [];
1059
+
1060
+ if (shouldReset) {
1061
+ return [];
1062
+ }
1063
+
1064
+ return previousItems ? items.filter(item => !previousItems.includes(item)) : [];
1065
+ }
1066
+
1067
+ function NumberField(props) {
1068
+ const {
1069
+ debounce,
1070
+ disabled,
1071
+ id,
1072
+ label,
1073
+ max,
1074
+ min,
1075
+ onInput,
1076
+ step,
1077
+ value = ''
1078
+ } = props;
1079
+ const handleInput = hooks.useMemo(() => {
1080
+ return debounce(event => {
1081
+ const {
1082
+ validity,
1083
+ value
1084
+ } = event.target;
1085
+
1086
+ if (validity.valid) {
1087
+ onInput(value ? parseFloat(value) : undefined);
1088
+ }
1089
+ });
1090
+ }, [onInput, debounce]);
1091
+ return jsxRuntime.jsxs("div", {
1092
+ class: "bio-properties-panel-numberfield",
1093
+ children: [jsxRuntime.jsx("label", {
1094
+ for: prefixId$5(id),
1095
+ class: "bio-properties-panel-label",
1096
+ children: label
1097
+ }), jsxRuntime.jsx("input", {
1098
+ id: prefixId$5(id),
1099
+ type: "number",
1100
+ name: id,
1101
+ spellCheck: "false",
1102
+ autoComplete: "off",
1103
+ disabled: disabled,
1104
+ class: "bio-properties-panel-input",
1105
+ max: max,
1106
+ min: min,
1107
+ onInput: handleInput,
1108
+ step: step,
1109
+ value: value
1110
+ })]
1111
+ });
1112
+ }
1113
+ /**
1114
+ * @param {Object} props
1115
+ * @param {Boolean} props.debounce
1116
+ * @param {String} props.description
1117
+ * @param {Boolean} props.disabled
1118
+ * @param {Object} props.element
1119
+ * @param {Function} props.getValue
1120
+ * @param {String} props.id
1121
+ * @param {String} props.label
1122
+ * @param {String} props.max
1123
+ * @param {String} props.min
1124
+ * @param {Function} props.setValue
1125
+ * @param {String} props.step
1126
+ */
1127
+
1128
+
1129
+ function NumberFieldEntry(props) {
1130
+ const {
1131
+ debounce,
1132
+ description,
1133
+ disabled,
1134
+ element,
1135
+ getValue,
1136
+ id,
1137
+ label,
1138
+ max,
1139
+ min,
1140
+ setValue,
1141
+ step
1142
+ } = props;
1143
+ const value = getValue(element);
1144
+ return jsxRuntime.jsxs("div", {
1145
+ class: "bio-properties-panel-entry",
1146
+ "data-entry-id": id,
1147
+ children: [jsxRuntime.jsx(NumberField, {
1148
+ debounce: debounce,
1149
+ disabled: disabled,
1150
+ id: id,
1151
+ label: label,
1152
+ onInput: setValue,
1153
+ max: max,
1154
+ min: min,
1155
+ step: step,
1156
+ value: value
1157
+ }), jsxRuntime.jsx(Description, {
1158
+ forId: id,
1159
+ element: element,
1160
+ value: description
1161
+ })]
1162
+ });
1163
+ }
1164
+ function isEdited$5(node) {
1165
+ return node && !!node.value;
1166
+ } // helpers /////////////////
1167
+
1168
+ function prefixId$5(id) {
1169
+ return `bio-properties-panel-${id}`;
1170
+ }
1171
+
1172
+ function Select(props) {
1173
+ const {
1174
+ id,
1175
+ label,
1176
+ onChange,
1177
+ options = [],
1178
+ value,
1179
+ disabled
1180
+ } = props;
1181
+
1182
+ const handleChange = ({
1183
+ target
1184
+ }) => {
1185
+ onChange(target.value);
1186
+ };
1187
+
1188
+ return jsxRuntime.jsxs("div", {
1189
+ class: "bio-properties-panel-select",
1190
+ children: [jsxRuntime.jsx("label", {
1191
+ for: prefixId$4(id),
1192
+ class: "bio-properties-panel-label",
1193
+ children: label
1194
+ }), jsxRuntime.jsx("select", {
1195
+ id: prefixId$4(id),
1196
+ name: id,
1197
+ class: "bio-properties-panel-input",
1198
+ onInput: handleChange,
1199
+ value: value,
1200
+ disabled: disabled,
1201
+ children: options.map((option, idx) => {
1202
+ return jsxRuntime.jsx("option", {
1203
+ value: option.value,
1204
+ disabled: option.disabled,
1205
+ children: option.label
1206
+ }, idx);
1207
+ })
1208
+ })]
1209
+ });
1210
+ }
1211
+ /**
1212
+ * @param {object} props
1213
+ * @param {object} props.element
1214
+ * @param {string} props.id
1215
+ * @param {string} [props.description]
1216
+ * @param {string} props.label
1217
+ * @param {Function} props.getValue
1218
+ * @param {Function} props.setValue
1219
+ * @param {Function} props.getOptions
1220
+ * @param {boolean} [props.disabled]
1221
+ */
1222
+
1223
+
1224
+ function SelectEntry(props) {
1225
+ const {
1226
+ element,
1227
+ id,
1228
+ description,
1229
+ label,
1230
+ getValue,
1231
+ setValue,
1232
+ getOptions,
1233
+ disabled
1234
+ } = props;
1235
+ const value = getValue(element);
1236
+ const options = getOptions(element);
1237
+ return jsxRuntime.jsxs("div", {
1238
+ class: "bio-properties-panel-entry",
1239
+ "data-entry-id": id,
1240
+ children: [jsxRuntime.jsx(Select, {
1241
+ id: id,
1242
+ label: label,
1243
+ value: value,
1244
+ onChange: setValue,
1245
+ options: options,
1246
+ disabled: disabled
1247
+ }), jsxRuntime.jsx(Description, {
1248
+ forId: id,
1249
+ element: element,
1250
+ value: description
1251
+ })]
1252
+ });
1253
+ }
1254
+ function isEdited$4(node) {
1255
+ return node && !!node.value;
1256
+ } // helpers /////////////////
1257
+
1258
+ function prefixId$4(id) {
1259
+ return `bio-properties-panel-${id}`;
1260
+ }
1261
+
1262
+ function Simple(props) {
1263
+ const {
1264
+ debounce,
1265
+ disabled,
1266
+ element,
1267
+ getValue,
1268
+ id,
1269
+ onBlur,
1270
+ onFocus,
1271
+ setValue
1272
+ } = props;
1273
+ const handleInput = hooks.useMemo(() => {
1274
+ return debounce(({
1275
+ target
1276
+ }) => setValue(target.value.length ? target.value : undefined));
1277
+ }, [setValue, debounce]);
1278
+ const value = getValue(element);
1279
+ return jsxRuntime.jsx("div", {
1280
+ class: "bio-properties-panel-simple",
1281
+ children: jsxRuntime.jsx("input", {
1282
+ id: prefixId$3(id),
1283
+ type: "text",
1284
+ name: id,
1285
+ spellCheck: "false",
1286
+ autoComplete: "off",
1287
+ disabled: disabled,
1288
+ class: "bio-properties-panel-input",
1289
+ onInput: handleInput,
1290
+ "aria-label": value || '<empty>',
1291
+ onFocus: onFocus,
1292
+ onBlur: onBlur,
1293
+ value: value || ''
1294
+ })
1295
+ });
1296
+ }
1297
+ function isEdited$3(node) {
1298
+ return node && !!node.value;
1299
+ } // helpers /////////////////
1300
+
1301
+ function prefixId$3(id) {
1302
+ return `bio-properties-panel-${id}`;
1303
+ }
1304
+
1305
+ function TextArea(props) {
1306
+ const {
1307
+ id,
1308
+ label,
1309
+ rows = 2,
1310
+ debounce,
1311
+ onInput,
1312
+ value = '',
1313
+ disabled,
1314
+ monospace
1315
+ } = props;
1316
+ const handleInput = hooks.useMemo(() => {
1317
+ return debounce(({
1318
+ target
1319
+ }) => onInput(target.value.length ? target.value : undefined));
1320
+ }, [onInput, debounce]);
1321
+ return jsxRuntime.jsxs("div", {
1322
+ class: "bio-properties-panel-textarea",
1323
+ children: [jsxRuntime.jsx("label", {
1324
+ for: prefixId$2(id),
1325
+ class: "bio-properties-panel-label",
1326
+ children: label
1327
+ }), jsxRuntime.jsx("textarea", {
1328
+ id: prefixId$2(id),
1329
+ name: id,
1330
+ spellCheck: "false",
1331
+ class: classnames__default["default"]('bio-properties-panel-input', monospace ? 'bio-properties-panel-input-monospace' : ''),
1332
+ onInput: handleInput,
1333
+ onFocus: props.onFocus,
1334
+ onBlur: props.onBlur,
1335
+ rows: rows,
1336
+ value: value,
1337
+ disabled: disabled
1338
+ })]
1339
+ });
1340
+ }
1341
+ /**
1342
+ * @param {object} props
1343
+ * @param {object} props.element
1344
+ * @param {string} props.id
1345
+ * @param {string} props.description
1346
+ * @param {boolean} props.debounce
1347
+ * @param {string} props.label
1348
+ * @param {Function} props.getValue
1349
+ * @param {Function} props.setValue
1350
+ * @param {number} props.rows
1351
+ * @param {boolean} props.monospace
1352
+ * @param {boolean} [props.disabled]
1353
+ */
1354
+
1355
+
1356
+ function TextAreaEntry(props) {
1357
+ const {
1358
+ element,
1359
+ id,
1360
+ description,
1361
+ debounce,
1362
+ label,
1363
+ getValue,
1364
+ setValue,
1365
+ rows,
1366
+ monospace,
1367
+ disabled
1368
+ } = props;
1369
+ const value = getValue(element);
1370
+ return jsxRuntime.jsxs("div", {
1371
+ class: "bio-properties-panel-entry",
1372
+ "data-entry-id": id,
1373
+ children: [jsxRuntime.jsx(TextArea, {
1374
+ id: id,
1375
+ label: label,
1376
+ value: value,
1377
+ onInput: setValue,
1378
+ rows: rows,
1379
+ debounce: debounce,
1380
+ monospace: monospace,
1381
+ disabled: disabled
1382
+ }), jsxRuntime.jsx(Description, {
1383
+ forId: id,
1384
+ element: element,
1385
+ value: description
1386
+ })]
1387
+ });
1388
+ }
1389
+ function isEdited$2(node) {
1390
+ return node && !!node.value;
1391
+ } // helpers /////////////////
1392
+
1393
+ function prefixId$2(id) {
1394
+ return `bio-properties-panel-${id}`;
1395
+ }
1396
+
1397
+ function Textfield(props) {
1398
+ const {
1399
+ debounce,
1400
+ disabled = false,
1401
+ id,
1402
+ label,
1403
+ onInput,
1404
+ value = ''
1405
+ } = props;
1406
+ const handleInput = hooks.useMemo(() => {
1407
+ return debounce(({
1408
+ target
1409
+ }) => onInput(target.value.length ? target.value : undefined));
1410
+ }, [onInput, debounce]);
1411
+ return jsxRuntime.jsxs("div", {
1412
+ class: "bio-properties-panel-textfield",
1413
+ children: [jsxRuntime.jsx("label", {
1414
+ for: prefixId$1(id),
1415
+ class: "bio-properties-panel-label",
1416
+ children: label
1417
+ }), jsxRuntime.jsx("input", {
1418
+ id: prefixId$1(id),
1419
+ type: "text",
1420
+ name: id,
1421
+ spellCheck: "false",
1422
+ autoComplete: "off",
1423
+ disabled: disabled,
1424
+ class: "bio-properties-panel-input",
1425
+ onInput: handleInput,
1426
+ onFocus: props.onFocus,
1427
+ onBlur: props.onBlur,
1428
+ value: value || ''
1429
+ })]
1430
+ });
1431
+ }
1432
+ /**
1433
+ * @param {Object} props
1434
+ * @param {Object} props.element
1435
+ * @param {String} props.id
1436
+ * @param {String} props.description
1437
+ * @param {Boolean} props.debounce
1438
+ * @param {Boolean} props.disabled
1439
+ * @param {String} props.label
1440
+ * @param {Function} props.getValue
1441
+ * @param {Function} props.setValue
1442
+ * @param {Function} props.validate
1443
+ */
1444
+
1445
+
1446
+ function TextfieldEntry(props) {
1447
+ const {
1448
+ element,
1449
+ id,
1450
+ description,
1451
+ debounce,
1452
+ disabled,
1453
+ label,
1454
+ getValue,
1455
+ setValue,
1456
+ validate
1457
+ } = props;
1458
+ const [error, setError] = hooks.useState(null);
1459
+ const [invalidValueCache, setInvalidValueCache] = hooks.useState(null);
1460
+ let value = getValue(element);
1461
+ const prevValue = usePrevious(value); // validate again when value prop changed
1462
+
1463
+ hooks.useEffect(() => {
1464
+ const err = validate ? validate(value) : null;
1465
+ setError(err);
1466
+ }, [value]); // validate on change
1467
+
1468
+ const handleChange = newValue => {
1469
+ const err = validate ? validate(newValue) : null;
1470
+
1471
+ if (err) {
1472
+ setInvalidValueCache(newValue);
1473
+ } else {
1474
+ setValue(newValue);
1475
+ }
1476
+
1477
+ setError(err);
1478
+ }; // keep showing invalid value on errors, although it was not set
1479
+
1480
+
1481
+ if (prevValue === value && error) {
1482
+ value = invalidValueCache;
1483
+ }
1484
+
1485
+ return jsxRuntime.jsxs("div", {
1486
+ class: classnames__default["default"]('bio-properties-panel-entry', error ? 'has-error' : ''),
1487
+ "data-entry-id": id,
1488
+ children: [jsxRuntime.jsx(Textfield, {
1489
+ id: id,
1490
+ label: label,
1491
+ value: value,
1492
+ onInput: handleChange,
1493
+ debounce: debounce,
1494
+ disabled: disabled
1495
+ }), jsxRuntime.jsx(Description, {
1496
+ forId: id,
1497
+ element: element,
1498
+ value: description
1499
+ }), error && jsxRuntime.jsx("div", {
1500
+ class: "bio-properties-panel-error",
1501
+ children: error
1502
+ })]
1503
+ });
1504
+ }
1505
+ function isEdited$1(node) {
1506
+ return node && !!node.value;
1507
+ } // helpers /////////////////
1508
+
1509
+ function prefixId$1(id) {
1510
+ return `bio-properties-panel-${id}`;
1511
+ }
1512
+
1513
+ function ToggleSwitch(props) {
1514
+ const {
1515
+ id,
1516
+ label,
1517
+ onInput,
1518
+ value,
1519
+ switcherLabel
1520
+ } = props;
1521
+
1522
+ const handleInput = async () => {
1523
+ onInput(!value);
1524
+ };
1525
+
1526
+ return jsxRuntime.jsxs("div", {
1527
+ class: "bio-properties-panel-toggle-switch",
1528
+ children: [jsxRuntime.jsx("label", {
1529
+ class: "bio-properties-panel-label",
1530
+ for: prefixId(id),
1531
+ children: label
1532
+ }), jsxRuntime.jsxs("div", {
1533
+ class: "bio-properties-panel-field-wrapper",
1534
+ children: [jsxRuntime.jsxs("label", {
1535
+ class: "bio-properties-panel-toggle-switch__switcher",
1536
+ children: [jsxRuntime.jsx("input", {
1537
+ id: prefixId(id),
1538
+ class: "bio-properties-panel-input",
1539
+ type: "checkbox",
1540
+ name: id,
1541
+ onInput: handleInput,
1542
+ checked: value
1543
+ }), jsxRuntime.jsx("span", {
1544
+ class: "bio-properties-panel-toggle-switch__slider"
1545
+ })]
1546
+ }), jsxRuntime.jsx("p", {
1547
+ class: "bio-properties-panel-toggle-switch__label",
1548
+ children: switcherLabel
1549
+ })]
1550
+ })]
1551
+ });
1552
+ }
1553
+ /**
1554
+ * @param {Object} props
1555
+ * @param {Object} props.element
1556
+ * @param {String} props.id
1557
+ * @param {String} props.description
1558
+ * @param {String} props.label
1559
+ * @param {String} props.switcherLabel
1560
+ * @param {Function} props.getValue
1561
+ * @param {Function} props.setValue
1562
+ */
1563
+
1564
+
1565
+ function ToggleSwitchEntry(props) {
1566
+ const {
1567
+ element,
1568
+ id,
1569
+ description,
1570
+ label,
1571
+ switcherLabel,
1572
+ getValue,
1573
+ setValue
1574
+ } = props;
1575
+ const value = getValue(element);
1576
+ return jsxRuntime.jsxs("div", {
1577
+ class: "bio-properties-panel-entry bio-properties-panel-toggle-switch-entry",
1578
+ "data-entry-id": id,
1579
+ children: [jsxRuntime.jsx(ToggleSwitch, {
1580
+ id: id,
1581
+ label: label,
1582
+ value: value,
1583
+ onInput: setValue,
1584
+ switcherLabel: switcherLabel
1585
+ }), jsxRuntime.jsx(Description, {
1586
+ forId: id,
1587
+ element: element,
1588
+ value: description
1589
+ })]
1590
+ });
1591
+ }
1592
+ function isEdited(node) {
1593
+ return node && !!node.checked;
1594
+ } // helpers /////////////////
1595
+
1596
+ function prefixId(id) {
1597
+ return `bio-properties-panel-${id}`;
1598
+ }
1599
+
1600
+ const DEFAULT_DEBOUNCE_TIME = 300;
1601
+ function debounceInput(debounceDelay) {
1602
+ return function _debounceInput(fn) {
1603
+ if (debounceDelay !== false) {
1604
+ var debounceTime = minDash.isNumber(debounceDelay) ? debounceDelay : DEFAULT_DEBOUNCE_TIME;
1605
+ return minDash.debounce(fn, debounceTime);
1606
+ } else {
1607
+ return fn;
1608
+ }
1609
+ };
1610
+ }
1611
+ debounceInput.$inject = ['config.debounceInput'];
1612
+
1613
+ var index = {
1614
+ debounceInput: ['factory', debounceInput]
1615
+ };
1616
+
1617
+ exports.ArrowIcon = ArrowIcon;
1618
+ exports.CheckboxEntry = CheckboxEntry;
1619
+ exports.CollapsibleEntry = CollapsibleEntry;
1620
+ exports.CreateIcon = CreateIcon;
1621
+ exports.DebounceInputModule = index;
1622
+ exports.DeleteIcon = DeleteIcon;
1623
+ exports.DescriptionContext = DescriptionContext;
1624
+ exports.DescriptionEntry = Description;
1625
+ exports.DropdownButton = DropdownButton;
1626
+ exports.Group = Group;
1627
+ exports.Header = Header;
1628
+ exports.HeaderButton = HeaderButton;
1629
+ exports.LayoutContext = LayoutContext;
1630
+ exports.ListEntry = List;
1631
+ exports.ListGroup = ListGroup;
1632
+ exports.ListItem = ListItem;
1633
+ exports.NumberFieldEntry = NumberFieldEntry;
1634
+ exports.PropertiesPanel = PropertiesPanel;
1635
+ exports.SelectEntry = SelectEntry;
1636
+ exports.SimpleEntry = Simple;
1637
+ exports.TextAreaEntry = TextAreaEntry;
1638
+ exports.TextFieldEntry = TextfieldEntry;
1639
+ exports.ToggleSwitchEntry = ToggleSwitchEntry;
1640
+ exports.isCheckboxEntryEdited = isEdited$6;
1641
+ exports.isNumberFieldEntryEdited = isEdited$5;
1642
+ exports.isSelectEntryEdited = isEdited$4;
1643
+ exports.isSimpleEntryEdited = isEdited$3;
1644
+ exports.isTextAreaEntryEdited = isEdited$2;
1645
+ exports.isTextFieldEntryEdited = isEdited$1;
1646
+ exports.isToggleSwitchEntryEdited = isEdited;
1647
+ exports.useDescriptionContext = useDescriptionContext;
1648
+ exports.useKeyFactory = useKeyFactory;
1649
+ exports.useLayoutState = useLayoutState;
1650
+ exports.usePrevious = usePrevious;
1651
+ //# sourceMappingURL=index.js.map