@bpmn-io/properties-panel 0.9.0 → 0.10.0

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