@bpmn-io/properties-panel 0.8.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/CHANGELOG.md +112 -85
  2. package/LICENSE +20 -20
  3. package/README.md +34 -34
  4. package/assets/properties-panel.css +891 -848
  5. package/dist/index.esm.js +1609 -0
  6. package/dist/index.esm.js.map +1 -0
  7. package/dist/index.js +1650 -0
  8. package/dist/index.js.map +1 -0
  9. package/package.json +87 -78
  10. package/preact/LICENSE +21 -0
  11. package/preact/README.md +185 -0
  12. package/preact/compat/dist/compat.js +2 -0
  13. package/preact/compat/dist/compat.js.map +1 -0
  14. package/preact/compat/dist/compat.mjs +2 -0
  15. package/preact/compat/dist/compat.module.js +2 -0
  16. package/preact/compat/dist/compat.module.js.map +1 -0
  17. package/preact/compat/dist/compat.umd.js +2 -0
  18. package/preact/compat/dist/compat.umd.js.map +1 -0
  19. package/preact/compat/jsx-dev-runtime.js +1 -0
  20. package/preact/compat/jsx-dev-runtime.mjs +1 -0
  21. package/preact/compat/jsx-runtime.js +1 -0
  22. package/preact/compat/jsx-runtime.mjs +1 -0
  23. package/preact/compat/package.json +19 -0
  24. package/preact/compat/server.js +15 -0
  25. package/preact/compat/server.mjs +4 -0
  26. package/preact/compat/src/Children.js +21 -0
  27. package/preact/compat/src/PureComponent.js +15 -0
  28. package/preact/compat/src/forwardRef.js +51 -0
  29. package/preact/compat/src/index.d.ts +140 -0
  30. package/preact/compat/src/index.js +175 -0
  31. package/preact/compat/src/internal.d.ts +47 -0
  32. package/preact/compat/src/memo.js +34 -0
  33. package/preact/compat/src/portals.js +80 -0
  34. package/preact/compat/src/render.js +219 -0
  35. package/preact/compat/src/scheduler.js +24 -0
  36. package/preact/compat/src/suspense-list.d.ts +14 -0
  37. package/preact/compat/src/suspense-list.js +126 -0
  38. package/preact/compat/src/suspense.d.ts +15 -0
  39. package/preact/compat/src/suspense.js +270 -0
  40. package/preact/compat/src/util.js +28 -0
  41. package/preact/compat/test-utils.js +1 -0
  42. package/preact/debug/dist/debug.js +2 -0
  43. package/preact/debug/dist/debug.js.map +1 -0
  44. package/preact/debug/dist/debug.mjs +2 -0
  45. package/preact/debug/dist/debug.module.js +2 -0
  46. package/preact/debug/dist/debug.module.js.map +1 -0
  47. package/preact/debug/dist/debug.umd.js +2 -0
  48. package/preact/debug/dist/debug.umd.js.map +1 -0
  49. package/preact/debug/package.json +18 -0
  50. package/preact/debug/src/check-props.js +54 -0
  51. package/preact/debug/src/component-stack.js +146 -0
  52. package/preact/debug/src/constants.js +3 -0
  53. package/preact/debug/src/debug.js +442 -0
  54. package/preact/debug/src/index.js +6 -0
  55. package/preact/debug/src/internal.d.ts +82 -0
  56. package/preact/debug/src/util.js +11 -0
  57. package/preact/devtools/dist/devtools.js +2 -0
  58. package/preact/devtools/dist/devtools.js.map +1 -0
  59. package/preact/devtools/dist/devtools.mjs +2 -0
  60. package/preact/devtools/dist/devtools.module.js +2 -0
  61. package/preact/devtools/dist/devtools.module.js.map +1 -0
  62. package/preact/devtools/dist/devtools.umd.js +2 -0
  63. package/preact/devtools/dist/devtools.umd.js.map +1 -0
  64. package/preact/devtools/package.json +16 -0
  65. package/preact/devtools/src/devtools.js +10 -0
  66. package/preact/devtools/src/index.d.ts +8 -0
  67. package/preact/devtools/src/index.js +15 -0
  68. package/preact/dist/preact.js +2 -0
  69. package/preact/dist/preact.js.map +1 -0
  70. package/preact/dist/preact.min.js +2 -0
  71. package/preact/dist/preact.min.js.map +1 -0
  72. package/preact/dist/preact.mjs +2 -0
  73. package/preact/dist/preact.module.js +2 -0
  74. package/preact/dist/preact.module.js.map +1 -0
  75. package/preact/dist/preact.umd.js +2 -0
  76. package/preact/dist/preact.umd.js.map +1 -0
  77. package/preact/hooks/dist/hooks.js +2 -0
  78. package/preact/hooks/dist/hooks.js.map +1 -0
  79. package/preact/hooks/dist/hooks.mjs +2 -0
  80. package/preact/hooks/dist/hooks.module.js +2 -0
  81. package/preact/hooks/dist/hooks.module.js.map +1 -0
  82. package/preact/hooks/dist/hooks.umd.js +2 -0
  83. package/preact/hooks/dist/hooks.umd.js.map +1 -0
  84. package/preact/hooks/package.json +26 -0
  85. package/preact/hooks/src/index.d.ts +130 -0
  86. package/preact/hooks/src/index.js +386 -0
  87. package/preact/hooks/src/internal.d.ts +75 -0
  88. package/preact/jsx-runtime/dist/jsxRuntime.js +2 -0
  89. package/preact/jsx-runtime/dist/jsxRuntime.js.map +1 -0
  90. package/preact/jsx-runtime/dist/jsxRuntime.mjs +2 -0
  91. package/preact/jsx-runtime/dist/jsxRuntime.module.js +2 -0
  92. package/preact/jsx-runtime/dist/jsxRuntime.module.js.map +1 -0
  93. package/preact/jsx-runtime/dist/jsxRuntime.umd.js +2 -0
  94. package/preact/jsx-runtime/dist/jsxRuntime.umd.js.map +1 -0
  95. package/preact/jsx-runtime/package.json +19 -0
  96. package/preact/jsx-runtime/src/index.d.ts +50 -0
  97. package/preact/jsx-runtime/src/index.js +72 -0
  98. package/preact/package.json +268 -0
  99. package/preact/src/cjs.js +3 -0
  100. package/preact/src/clone-element.js +39 -0
  101. package/preact/src/component.js +225 -0
  102. package/preact/src/constants.js +3 -0
  103. package/preact/src/create-context.js +68 -0
  104. package/preact/src/create-element.js +100 -0
  105. package/preact/src/diff/catch-error.js +38 -0
  106. package/preact/src/diff/children.js +347 -0
  107. package/preact/src/diff/index.js +516 -0
  108. package/preact/src/diff/props.js +158 -0
  109. package/preact/src/index.d.ts +310 -0
  110. package/preact/src/index.js +13 -0
  111. package/preact/src/internal.d.ts +147 -0
  112. package/preact/src/jsx.d.ts +955 -0
  113. package/preact/src/options.js +17 -0
  114. package/preact/src/render.js +74 -0
  115. package/preact/src/util.js +23 -0
  116. package/preact/test-utils/dist/testUtils.js +2 -0
  117. package/preact/test-utils/dist/testUtils.js.map +1 -0
  118. package/preact/test-utils/dist/testUtils.mjs +2 -0
  119. package/preact/test-utils/dist/testUtils.module.js +2 -0
  120. package/preact/test-utils/dist/testUtils.module.js.map +1 -0
  121. package/preact/test-utils/dist/testUtils.umd.js +2 -0
  122. package/preact/test-utils/dist/testUtils.umd.js.map +1 -0
  123. package/preact/test-utils/package.json +19 -0
  124. package/preact/test-utils/src/index.d.ts +3 -0
  125. package/preact/test-utils/src/index.js +117 -0
  126. package/lib/PropertiesPanel.js +0 -126
  127. package/lib/PropertiesPanel.js.map +0 -1
  128. package/lib/components/DropdownButton.js +0 -109
  129. package/lib/components/DropdownButton.js.map +0 -1
  130. package/lib/components/Group.js +0 -75
  131. package/lib/components/Group.js.map +0 -1
  132. package/lib/components/Header.js +0 -49
  133. package/lib/components/Header.js.map +0 -1
  134. package/lib/components/HeaderButton.js +0 -16
  135. package/lib/components/HeaderButton.js.map +0 -1
  136. package/lib/components/ListGroup.js +0 -167
  137. package/lib/components/ListGroup.js.map +0 -1
  138. package/lib/components/ListItem.js +0 -37
  139. package/lib/components/ListItem.js.map +0 -1
  140. package/lib/components/entries/Checkbox.js +0 -81
  141. package/lib/components/entries/Checkbox.js.map +0 -1
  142. package/lib/components/entries/Collapsible.js +0 -48
  143. package/lib/components/entries/Collapsible.js.map +0 -1
  144. package/lib/components/entries/List.js +0 -204
  145. package/lib/components/entries/List.js.map +0 -1
  146. package/lib/components/entries/NumberField.js +0 -108
  147. package/lib/components/entries/NumberField.js.map +0 -1
  148. package/lib/components/entries/Select.js +0 -107
  149. package/lib/components/entries/Select.js.map +0 -1
  150. package/lib/components/entries/Simple.js +0 -56
  151. package/lib/components/entries/Simple.js.map +0 -1
  152. package/lib/components/entries/TextArea.js +0 -96
  153. package/lib/components/entries/TextArea.js.map +0 -1
  154. package/lib/components/entries/TextField.js +0 -121
  155. package/lib/components/entries/TextField.js.map +0 -1
  156. package/lib/components/entries/ToggleSwitch.js +0 -87
  157. package/lib/components/entries/ToggleSwitch.js.map +0 -1
  158. package/lib/components/icons/index.js +0 -51
  159. package/lib/components/icons/index.js.map +0 -1
  160. package/lib/context/LayoutContext.js +0 -9
  161. package/lib/context/LayoutContext.js.map +0 -1
  162. package/lib/context/index.js +0 -2
  163. package/lib/context/index.js.map +0 -1
  164. package/lib/features/debounce-input/debounceInput.js +0 -14
  165. package/lib/features/debounce-input/debounceInput.js.map +0 -1
  166. package/lib/features/debounce-input/index.js +0 -5
  167. package/lib/features/debounce-input/index.js.map +0 -1
  168. package/lib/hooks/index.js +0 -4
  169. package/lib/hooks/index.js.map +0 -1
  170. package/lib/hooks/useKeyFactory.js +0 -39
  171. package/lib/hooks/useKeyFactory.js.map +0 -1
  172. package/lib/hooks/useLayoutState.js +0 -36
  173. package/lib/hooks/useLayoutState.js.map +0 -1
  174. package/lib/hooks/usePrevious.js +0 -16
  175. package/lib/hooks/usePrevious.js.map +0 -1
  176. package/lib/index.js +0 -2
  177. package/lib/index.js.map +0 -1
package/dist/index.js ADDED
@@ -0,0 +1,1650 @@
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
+ onFocus: onFocus,
1291
+ onBlur: onBlur,
1292
+ value: value || ''
1293
+ })
1294
+ });
1295
+ }
1296
+ function isEdited$3(node) {
1297
+ return node && !!node.value;
1298
+ } // helpers /////////////////
1299
+
1300
+ function prefixId$3(id) {
1301
+ return `bio-properties-panel-${id}`;
1302
+ }
1303
+
1304
+ function TextArea(props) {
1305
+ const {
1306
+ id,
1307
+ label,
1308
+ rows = 2,
1309
+ debounce,
1310
+ onInput,
1311
+ value = '',
1312
+ disabled,
1313
+ monospace
1314
+ } = props;
1315
+ const handleInput = hooks.useMemo(() => {
1316
+ return debounce(({
1317
+ target
1318
+ }) => onInput(target.value.length ? target.value : undefined));
1319
+ }, [onInput, debounce]);
1320
+ return jsxRuntime.jsxs("div", {
1321
+ class: "bio-properties-panel-textarea",
1322
+ children: [jsxRuntime.jsx("label", {
1323
+ for: prefixId$2(id),
1324
+ class: "bio-properties-panel-label",
1325
+ children: label
1326
+ }), jsxRuntime.jsx("textarea", {
1327
+ id: prefixId$2(id),
1328
+ name: id,
1329
+ spellCheck: "false",
1330
+ class: classnames__default["default"]('bio-properties-panel-input', monospace ? 'bio-properties-panel-input-monospace' : ''),
1331
+ onInput: handleInput,
1332
+ onFocus: props.onFocus,
1333
+ onBlur: props.onBlur,
1334
+ rows: rows,
1335
+ value: value,
1336
+ disabled: disabled
1337
+ })]
1338
+ });
1339
+ }
1340
+ /**
1341
+ * @param {object} props
1342
+ * @param {object} props.element
1343
+ * @param {string} props.id
1344
+ * @param {string} props.description
1345
+ * @param {boolean} props.debounce
1346
+ * @param {string} props.label
1347
+ * @param {Function} props.getValue
1348
+ * @param {Function} props.setValue
1349
+ * @param {number} props.rows
1350
+ * @param {boolean} props.monospace
1351
+ * @param {boolean} [props.disabled]
1352
+ */
1353
+
1354
+
1355
+ function TextAreaEntry(props) {
1356
+ const {
1357
+ element,
1358
+ id,
1359
+ description,
1360
+ debounce,
1361
+ label,
1362
+ getValue,
1363
+ setValue,
1364
+ rows,
1365
+ monospace,
1366
+ disabled
1367
+ } = props;
1368
+ const value = getValue(element);
1369
+ return jsxRuntime.jsxs("div", {
1370
+ class: "bio-properties-panel-entry",
1371
+ "data-entry-id": id,
1372
+ children: [jsxRuntime.jsx(TextArea, {
1373
+ id: id,
1374
+ label: label,
1375
+ value: value,
1376
+ onInput: setValue,
1377
+ rows: rows,
1378
+ debounce: debounce,
1379
+ monospace: monospace,
1380
+ disabled: disabled
1381
+ }), jsxRuntime.jsx(Description, {
1382
+ forId: id,
1383
+ element: element,
1384
+ value: description
1385
+ })]
1386
+ });
1387
+ }
1388
+ function isEdited$2(node) {
1389
+ return node && !!node.value;
1390
+ } // helpers /////////////////
1391
+
1392
+ function prefixId$2(id) {
1393
+ return `bio-properties-panel-${id}`;
1394
+ }
1395
+
1396
+ function Textfield(props) {
1397
+ const {
1398
+ debounce,
1399
+ disabled = false,
1400
+ id,
1401
+ label,
1402
+ onInput,
1403
+ value = ''
1404
+ } = props;
1405
+ const handleInput = hooks.useMemo(() => {
1406
+ return debounce(({
1407
+ target
1408
+ }) => onInput(target.value.length ? target.value : undefined));
1409
+ }, [onInput, debounce]);
1410
+ return jsxRuntime.jsxs("div", {
1411
+ class: "bio-properties-panel-textfield",
1412
+ children: [jsxRuntime.jsx("label", {
1413
+ for: prefixId$1(id),
1414
+ class: "bio-properties-panel-label",
1415
+ children: label
1416
+ }), jsxRuntime.jsx("input", {
1417
+ id: prefixId$1(id),
1418
+ type: "text",
1419
+ name: id,
1420
+ spellCheck: "false",
1421
+ autoComplete: "off",
1422
+ disabled: disabled,
1423
+ class: "bio-properties-panel-input",
1424
+ onInput: handleInput,
1425
+ onFocus: props.onFocus,
1426
+ onBlur: props.onBlur,
1427
+ value: value || ''
1428
+ })]
1429
+ });
1430
+ }
1431
+ /**
1432
+ * @param {Object} props
1433
+ * @param {Object} props.element
1434
+ * @param {String} props.id
1435
+ * @param {String} props.description
1436
+ * @param {Boolean} props.debounce
1437
+ * @param {Boolean} props.disabled
1438
+ * @param {String} props.label
1439
+ * @param {Function} props.getValue
1440
+ * @param {Function} props.setValue
1441
+ * @param {Function} props.validate
1442
+ */
1443
+
1444
+
1445
+ function TextfieldEntry(props) {
1446
+ const {
1447
+ element,
1448
+ id,
1449
+ description,
1450
+ debounce,
1451
+ disabled,
1452
+ label,
1453
+ getValue,
1454
+ setValue,
1455
+ validate
1456
+ } = props;
1457
+ const [error, setError] = hooks.useState(null);
1458
+ const [invalidValueCache, setInvalidValueCache] = hooks.useState(null);
1459
+ let value = getValue(element);
1460
+ const prevValue = usePrevious(value); // validate again when value prop changed
1461
+
1462
+ hooks.useEffect(() => {
1463
+ const err = validate ? validate(value) : null;
1464
+ setError(err);
1465
+ }, [value]); // validate on change
1466
+
1467
+ const handleChange = newValue => {
1468
+ const err = validate ? validate(newValue) : null;
1469
+
1470
+ if (err) {
1471
+ setInvalidValueCache(newValue);
1472
+ } else {
1473
+ setValue(newValue);
1474
+ }
1475
+
1476
+ setError(err);
1477
+ }; // keep showing invalid value on errors, although it was not set
1478
+
1479
+
1480
+ if (prevValue === value && error) {
1481
+ value = invalidValueCache;
1482
+ }
1483
+
1484
+ return jsxRuntime.jsxs("div", {
1485
+ class: classnames__default["default"]('bio-properties-panel-entry', error ? 'has-error' : ''),
1486
+ "data-entry-id": id,
1487
+ children: [jsxRuntime.jsx(Textfield, {
1488
+ id: id,
1489
+ label: label,
1490
+ value: value,
1491
+ onInput: handleChange,
1492
+ debounce: debounce,
1493
+ disabled: disabled
1494
+ }), jsxRuntime.jsx(Description, {
1495
+ forId: id,
1496
+ element: element,
1497
+ value: description
1498
+ }), error && jsxRuntime.jsx("div", {
1499
+ class: "bio-properties-panel-error",
1500
+ children: error
1501
+ })]
1502
+ });
1503
+ }
1504
+ function isEdited$1(node) {
1505
+ return node && !!node.value;
1506
+ } // helpers /////////////////
1507
+
1508
+ function prefixId$1(id) {
1509
+ return `bio-properties-panel-${id}`;
1510
+ }
1511
+
1512
+ function ToggleSwitch(props) {
1513
+ const {
1514
+ id,
1515
+ label,
1516
+ onInput,
1517
+ value,
1518
+ switcherLabel
1519
+ } = props;
1520
+
1521
+ const handleInput = async () => {
1522
+ onInput(!value);
1523
+ };
1524
+
1525
+ return jsxRuntime.jsxs("div", {
1526
+ class: "bio-properties-panel-toggle-switch",
1527
+ children: [jsxRuntime.jsx("label", {
1528
+ class: "bio-properties-panel-label",
1529
+ for: prefixId(id),
1530
+ children: label
1531
+ }), jsxRuntime.jsxs("div", {
1532
+ class: "bio-properties-panel-field-wrapper",
1533
+ children: [jsxRuntime.jsxs("label", {
1534
+ class: "bio-properties-panel-toggle-switch__switcher",
1535
+ children: [jsxRuntime.jsx("input", {
1536
+ id: prefixId(id),
1537
+ class: "bio-properties-panel-input",
1538
+ type: "checkbox",
1539
+ name: id,
1540
+ onInput: handleInput,
1541
+ checked: value
1542
+ }), jsxRuntime.jsx("span", {
1543
+ class: "bio-properties-panel-toggle-switch__slider"
1544
+ })]
1545
+ }), jsxRuntime.jsx("p", {
1546
+ class: "bio-properties-panel-toggle-switch__label",
1547
+ children: switcherLabel
1548
+ })]
1549
+ })]
1550
+ });
1551
+ }
1552
+ /**
1553
+ * @param {Object} props
1554
+ * @param {Object} props.element
1555
+ * @param {String} props.id
1556
+ * @param {String} props.description
1557
+ * @param {String} props.label
1558
+ * @param {String} props.switcherLabel
1559
+ * @param {Function} props.getValue
1560
+ * @param {Function} props.setValue
1561
+ */
1562
+
1563
+
1564
+ function ToggleSwitchEntry(props) {
1565
+ const {
1566
+ element,
1567
+ id,
1568
+ description,
1569
+ label,
1570
+ switcherLabel,
1571
+ getValue,
1572
+ setValue
1573
+ } = props;
1574
+ const value = getValue(element);
1575
+ return jsxRuntime.jsxs("div", {
1576
+ class: "bio-properties-panel-entry bio-properties-panel-toggle-switch-entry",
1577
+ "data-entry-id": id,
1578
+ children: [jsxRuntime.jsx(ToggleSwitch, {
1579
+ id: id,
1580
+ label: label,
1581
+ value: value,
1582
+ onInput: setValue,
1583
+ switcherLabel: switcherLabel
1584
+ }), jsxRuntime.jsx(Description, {
1585
+ forId: id,
1586
+ element: element,
1587
+ value: description
1588
+ })]
1589
+ });
1590
+ }
1591
+ function isEdited(node) {
1592
+ return node && !!node.checked;
1593
+ } // helpers /////////////////
1594
+
1595
+ function prefixId(id) {
1596
+ return `bio-properties-panel-${id}`;
1597
+ }
1598
+
1599
+ const DEFAULT_DEBOUNCE_TIME = 300;
1600
+ function debounceInput(debounceDelay) {
1601
+ return function _debounceInput(fn) {
1602
+ if (debounceDelay !== false) {
1603
+ var debounceTime = minDash.isNumber(debounceDelay) ? debounceDelay : DEFAULT_DEBOUNCE_TIME;
1604
+ return minDash.debounce(fn, debounceTime);
1605
+ } else {
1606
+ return fn;
1607
+ }
1608
+ };
1609
+ }
1610
+ debounceInput.$inject = ['config.debounceInput'];
1611
+
1612
+ var index = {
1613
+ debounceInput: ['factory', debounceInput]
1614
+ };
1615
+
1616
+ exports.ArrowIcon = ArrowIcon;
1617
+ exports.CheckboxEntry = CheckboxEntry;
1618
+ exports.CollapsibleEntry = CollapsibleEntry;
1619
+ exports.CreateIcon = CreateIcon;
1620
+ exports.DebounceInputModule = index;
1621
+ exports.DeleteIcon = DeleteIcon;
1622
+ exports.DescriptionContext = DescriptionContext;
1623
+ exports.DescriptionEntry = Description;
1624
+ exports.DropdownButton = DropdownButton;
1625
+ exports.Group = Group;
1626
+ exports.Header = Header;
1627
+ exports.HeaderButton = HeaderButton;
1628
+ exports.LayoutContext = LayoutContext;
1629
+ exports.ListEntry = List;
1630
+ exports.ListGroup = ListGroup;
1631
+ exports.ListItem = ListItem;
1632
+ exports.NumberFieldEntry = NumberFieldEntry;
1633
+ exports.PropertiesPanel = PropertiesPanel;
1634
+ exports.SelectEntry = SelectEntry;
1635
+ exports.SimpleEntry = Simple;
1636
+ exports.TextAreaEntry = TextAreaEntry;
1637
+ exports.TextFieldEntry = TextfieldEntry;
1638
+ exports.ToggleSwitchEntry = ToggleSwitchEntry;
1639
+ exports.isCheckboxEntryEdited = isEdited$6;
1640
+ exports.isNumberFieldEntryEdited = isEdited$5;
1641
+ exports.isSelectEntryEdited = isEdited$4;
1642
+ exports.isSimpleEntryEdited = isEdited$3;
1643
+ exports.isTextAreaEntryEdited = isEdited$2;
1644
+ exports.isTextFieldEntryEdited = isEdited$1;
1645
+ exports.isToggleSwitchEntryEdited = isEdited;
1646
+ exports.useDescriptionContext = useDescriptionContext;
1647
+ exports.useKeyFactory = useKeyFactory;
1648
+ exports.useLayoutState = useLayoutState;
1649
+ exports.usePrevious = usePrevious;
1650
+ //# sourceMappingURL=index.js.map