@bpmn-io/properties-panel 3.10.1 → 3.12.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.
package/dist/index.mjs DELETED
@@ -1,4679 +0,0 @@
1
- import { options, Component, createElement, Fragment, toChildArray, render, createContext } from 'preact';
2
- import { isFunction, isString, isArray, get, assign, set, sortBy, find, isNumber, debounce } from 'min-dash';
3
- import classnames from 'classnames';
4
- import { query, domify } from 'min-dom';
5
- import { FeelersEditor } from 'feelers';
6
- import FeelEditor from '@bpmn-io/feel-editor';
7
- import { lineNumbers } from '@codemirror/view';
8
- import * as focusTrap from 'focus-trap';
9
-
10
- var t,
11
- r,
12
- u,
13
- i,
14
- o$1 = 0,
15
- f = [],
16
- c = [],
17
- e = options.__b,
18
- a = options.__r,
19
- v = options.diffed,
20
- l = options.__c,
21
- m = options.unmount;
22
- function d(t, u) {
23
- options.__h && options.__h(r, t, o$1 || u), o$1 = 0;
24
- var i = r.__H || (r.__H = {
25
- __: [],
26
- __h: []
27
- });
28
- return t >= i.__.length && i.__.push({
29
- __V: c
30
- }), i.__[t];
31
- }
32
- function h(n) {
33
- return o$1 = 1, s(B$1, n);
34
- }
35
- function s(n, u, i) {
36
- var o = d(t++, 2);
37
- if (o.t = n, !o.__c && (o.__ = [i ? i(u) : B$1(void 0, u), function (n) {
38
- var t = o.__N ? o.__N[0] : o.__[0],
39
- r = o.t(t, n);
40
- t !== r && (o.__N = [r, o.__[1]], o.__c.setState({}));
41
- }], o.__c = r, !r.u)) {
42
- var f = function (n, t, r) {
43
- if (!o.__c.__H) return !0;
44
- var u = o.__c.__H.__.filter(function (n) {
45
- return n.__c;
46
- });
47
- if (u.every(function (n) {
48
- return !n.__N;
49
- })) return !c || c.call(this, n, t, r);
50
- var i = !1;
51
- return u.forEach(function (n) {
52
- if (n.__N) {
53
- var t = n.__[0];
54
- n.__ = n.__N, n.__N = void 0, t !== n.__[0] && (i = !0);
55
- }
56
- }), !(!i && o.__c.props === n) && (!c || c.call(this, n, t, r));
57
- };
58
- r.u = !0;
59
- var c = r.shouldComponentUpdate,
60
- e = r.componentWillUpdate;
61
- r.componentWillUpdate = function (n, t, r) {
62
- if (this.__e) {
63
- var u = c;
64
- c = void 0, f(n, t, r), c = u;
65
- }
66
- e && e.call(this, n, t, r);
67
- }, r.shouldComponentUpdate = f;
68
- }
69
- return o.__N || o.__;
70
- }
71
- function p(u, i) {
72
- var o = d(t++, 3);
73
- !options.__s && z$1(o.__H, i) && (o.__ = u, o.i = i, r.__H.__h.push(o));
74
- }
75
- function y(u, i) {
76
- var o = d(t++, 4);
77
- !options.__s && z$1(o.__H, i) && (o.__ = u, o.i = i, r.__h.push(o));
78
- }
79
- function _$1(n) {
80
- return o$1 = 5, F$1(function () {
81
- return {
82
- current: n
83
- };
84
- }, []);
85
- }
86
- function F$1(n, r) {
87
- var u = d(t++, 7);
88
- return z$1(u.__H, r) ? (u.__V = n(), u.i = r, u.__h = n, u.__V) : u.__;
89
- }
90
- function T$1(n, t) {
91
- return o$1 = 8, F$1(function () {
92
- return n;
93
- }, t);
94
- }
95
- function q$1(n) {
96
- var u = r.context[n.__c],
97
- i = d(t++, 9);
98
- return i.c = n, u ? (null == i.__ && (i.__ = !0, u.sub(r)), u.props.value) : n.__;
99
- }
100
- function b() {
101
- for (var t; t = f.shift();) if (t.__P && t.__H) try {
102
- t.__H.__h.forEach(k$1), t.__H.__h.forEach(w$1), t.__H.__h = [];
103
- } catch (r) {
104
- t.__H.__h = [], options.__e(r, t.__v);
105
- }
106
- }
107
- options.__b = function (n) {
108
- r = null, e && e(n);
109
- }, options.__r = function (n) {
110
- a && a(n), t = 0;
111
- var i = (r = n.__c).__H;
112
- i && (u === r ? (i.__h = [], r.__h = [], i.__.forEach(function (n) {
113
- n.__N && (n.__ = n.__N), n.__V = c, n.__N = n.i = void 0;
114
- })) : (i.__h.forEach(k$1), i.__h.forEach(w$1), i.__h = [], t = 0)), u = r;
115
- }, options.diffed = function (t) {
116
- v && v(t);
117
- var o = t.__c;
118
- o && o.__H && (o.__H.__h.length && (1 !== f.push(o) && i === options.requestAnimationFrame || ((i = options.requestAnimationFrame) || j$1)(b)), o.__H.__.forEach(function (n) {
119
- n.i && (n.__H = n.i), n.__V !== c && (n.__ = n.__V), n.i = void 0, n.__V = c;
120
- })), u = r = null;
121
- }, options.__c = function (t, r) {
122
- r.some(function (t) {
123
- try {
124
- t.__h.forEach(k$1), t.__h = t.__h.filter(function (n) {
125
- return !n.__ || w$1(n);
126
- });
127
- } catch (u) {
128
- r.some(function (n) {
129
- n.__h && (n.__h = []);
130
- }), r = [], options.__e(u, t.__v);
131
- }
132
- }), l && l(t, r);
133
- }, options.unmount = function (t) {
134
- m && m(t);
135
- var r,
136
- u = t.__c;
137
- u && u.__H && (u.__H.__.forEach(function (n) {
138
- try {
139
- k$1(n);
140
- } catch (n) {
141
- r = n;
142
- }
143
- }), u.__H = void 0, r && options.__e(r, u.__v));
144
- };
145
- var g$1 = "function" == typeof requestAnimationFrame;
146
- function j$1(n) {
147
- var t,
148
- r = function () {
149
- clearTimeout(u), g$1 && cancelAnimationFrame(t), setTimeout(n);
150
- },
151
- u = setTimeout(r, 100);
152
- g$1 && (t = requestAnimationFrame(r));
153
- }
154
- function k$1(n) {
155
- var t = r,
156
- u = n.__c;
157
- "function" == typeof u && (n.__c = void 0, u()), r = t;
158
- }
159
- function w$1(n) {
160
- var t = r;
161
- n.__c = n.__(), r = t;
162
- }
163
- function z$1(n, t) {
164
- return !n || n.length !== t.length || t.some(function (t, r) {
165
- return t !== n[r];
166
- });
167
- }
168
- function B$1(n, t) {
169
- return "function" == typeof t ? t(n) : t;
170
- }
171
-
172
- function g(n, t) {
173
- for (var e in t) n[e] = t[e];
174
- return n;
175
- }
176
- function C(n, t) {
177
- for (var e in n) if ("__source" !== e && !(e in t)) return !0;
178
- for (var r in t) if ("__source" !== r && n[r] !== t[r]) return !0;
179
- return !1;
180
- }
181
- function w(n) {
182
- this.props = n;
183
- }
184
- (w.prototype = new Component()).isPureReactComponent = !0, w.prototype.shouldComponentUpdate = function (n, t) {
185
- return C(this.props, n) || C(this.state, t);
186
- };
187
- var R = options.__b;
188
- options.__b = function (n) {
189
- n.type && n.type.__f && n.ref && (n.props.ref = n.ref, n.ref = null), R && R(n);
190
- };
191
- var N = "undefined" != typeof Symbol && Symbol.for && Symbol.for("react.forward_ref") || 3911;
192
- function k(n) {
193
- function t(t) {
194
- var e = g({}, t);
195
- return delete e.ref, n(e, t.ref || null);
196
- }
197
- return t.$$typeof = N, t.render = t, t.prototype.isReactComponent = t.__f = !0, t.displayName = "ForwardRef(" + (n.displayName || n.name) + ")", t;
198
- }
199
- var T = options.__e;
200
- options.__e = function (n, t, e, r) {
201
- if (n.then) for (var u, o = t; o = o.__;) if ((u = o.__c) && u.__c) return null == t.__e && (t.__e = e.__e, t.__k = e.__k), u.__c(n, t);
202
- T(n, t, e, r);
203
- };
204
- var F = options.unmount;
205
- function I(n, t, e) {
206
- return n && (n.__c && n.__c.__H && (n.__c.__H.__.forEach(function (n) {
207
- "function" == typeof n.__c && n.__c();
208
- }), n.__c.__H = null), null != (n = g({}, n)).__c && (n.__c.__P === e && (n.__c.__P = t), n.__c = null), n.__k = n.__k && n.__k.map(function (n) {
209
- return I(n, t, e);
210
- })), n;
211
- }
212
- function L(n, t, e) {
213
- return n && e && (n.__v = null, n.__k = n.__k && n.__k.map(function (n) {
214
- return L(n, t, e);
215
- }), n.__c && n.__c.__P === t && (n.__e && e.insertBefore(n.__e, n.__d), n.__c.__e = !0, n.__c.__P = e)), n;
216
- }
217
- function U() {
218
- this.__u = 0, this.t = null, this.__b = null;
219
- }
220
- function D(n) {
221
- var t = n.__.__c;
222
- return t && t.__a && t.__a(n);
223
- }
224
- function V() {
225
- this.u = null, this.o = null;
226
- }
227
- options.unmount = function (n) {
228
- var t = n.__c;
229
- t && t.__R && t.__R(), t && !0 === n.__h && (n.type = null), F && F(n);
230
- }, (U.prototype = new Component()).__c = function (n, t) {
231
- var e = t.__c,
232
- r = this;
233
- null == r.t && (r.t = []), r.t.push(e);
234
- var u = D(r.__v),
235
- o = !1,
236
- i = function () {
237
- o || (o = !0, e.__R = null, u ? u(l) : l());
238
- };
239
- e.__R = i;
240
- var l = function () {
241
- if (! --r.__u) {
242
- if (r.state.__a) {
243
- var n = r.state.__a;
244
- r.__v.__k[0] = L(n, n.__c.__P, n.__c.__O);
245
- }
246
- var t;
247
- for (r.setState({
248
- __a: r.__b = null
249
- }); t = r.t.pop();) t.forceUpdate();
250
- }
251
- },
252
- c = !0 === t.__h;
253
- r.__u++ || c || r.setState({
254
- __a: r.__b = r.__v.__k[0]
255
- }), n.then(i, i);
256
- }, U.prototype.componentWillUnmount = function () {
257
- this.t = [];
258
- }, U.prototype.render = function (n, e) {
259
- if (this.__b) {
260
- if (this.__v.__k) {
261
- var r = document.createElement("div"),
262
- o = this.__v.__k[0].__c;
263
- this.__v.__k[0] = I(this.__b, r, o.__O = o.__P);
264
- }
265
- this.__b = null;
266
- }
267
- var i = e.__a && createElement(Fragment, null, n.fallback);
268
- return i && (i.__h = null), [createElement(Fragment, null, e.__a ? null : n.children), i];
269
- };
270
- var W = function (n, t, e) {
271
- if (++e[1] === e[0] && n.o.delete(t), n.props.revealOrder && ("t" !== n.props.revealOrder[0] || !n.o.size)) for (e = n.u; e;) {
272
- for (; e.length > 3;) e.pop()();
273
- if (e[1] < e[0]) break;
274
- n.u = e = e[2];
275
- }
276
- };
277
- function P(n) {
278
- return this.getChildContext = function () {
279
- return n.context;
280
- }, n.children;
281
- }
282
- function j(n) {
283
- var e = this,
284
- r = n.i;
285
- e.componentWillUnmount = function () {
286
- render(null, e.l), e.l = null, e.i = null;
287
- }, e.i && e.i !== r && e.componentWillUnmount(), e.l || (e.i = r, e.l = {
288
- nodeType: 1,
289
- parentNode: r,
290
- childNodes: [],
291
- appendChild: function (n) {
292
- this.childNodes.push(n), e.i.appendChild(n);
293
- },
294
- insertBefore: function (n, t) {
295
- this.childNodes.push(n), e.i.appendChild(n);
296
- },
297
- removeChild: function (n) {
298
- this.childNodes.splice(this.childNodes.indexOf(n) >>> 1, 1), e.i.removeChild(n);
299
- }
300
- }), render(createElement(P, {
301
- context: e.context
302
- }, n.__v), e.l);
303
- }
304
- function z(n, e) {
305
- var r = createElement(j, {
306
- __v: n,
307
- i: e
308
- });
309
- return r.containerInfo = e, r;
310
- }
311
- (V.prototype = new Component()).__a = function (n) {
312
- var t = this,
313
- e = D(t.__v),
314
- r = t.o.get(n);
315
- return r[0]++, function (u) {
316
- var o = function () {
317
- t.props.revealOrder ? (r.push(u), W(t, n, r)) : u();
318
- };
319
- e ? e(o) : o();
320
- };
321
- }, V.prototype.render = function (n) {
322
- this.u = null, this.o = new Map();
323
- var t = toChildArray(n.children);
324
- n.revealOrder && "b" === n.revealOrder[0] && t.reverse();
325
- for (var e = t.length; e--;) this.o.set(t[e], this.u = [1, 0, this.u]);
326
- return n.children;
327
- }, V.prototype.componentDidUpdate = V.prototype.componentDidMount = function () {
328
- var n = this;
329
- this.o.forEach(function (t, e) {
330
- W(n, e, t);
331
- });
332
- };
333
- var B = "undefined" != typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103,
334
- H = /^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image(!S)|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,
335
- Z = /^on(Ani|Tra|Tou|BeforeInp|Compo)/,
336
- Y = /[A-Z0-9]/g,
337
- $ = "undefined" != typeof document,
338
- q = function (n) {
339
- return ("undefined" != typeof Symbol && "symbol" == typeof Symbol() ? /fil|che|rad/ : /fil|che|ra/).test(n);
340
- };
341
- Component.prototype.isReactComponent = {}, ["componentWillMount", "componentWillReceiveProps", "componentWillUpdate"].forEach(function (t) {
342
- Object.defineProperty(Component.prototype, t, {
343
- configurable: !0,
344
- get: function () {
345
- return this["UNSAFE_" + t];
346
- },
347
- set: function (n) {
348
- Object.defineProperty(this, t, {
349
- configurable: !0,
350
- writable: !0,
351
- value: n
352
- });
353
- }
354
- });
355
- });
356
- var K = options.event;
357
- function Q() {}
358
- function X() {
359
- return this.cancelBubble;
360
- }
361
- function nn() {
362
- return this.defaultPrevented;
363
- }
364
- options.event = function (n) {
365
- return K && (n = K(n)), n.persist = Q, n.isPropagationStopped = X, n.isDefaultPrevented = nn, n.nativeEvent = n;
366
- };
367
- var en = {
368
- enumerable: !1,
369
- configurable: !0,
370
- get: function () {
371
- return this.class;
372
- }
373
- },
374
- rn = options.vnode;
375
- options.vnode = function (n) {
376
- "string" == typeof n.type && function (n) {
377
- var t = n.props,
378
- e = n.type,
379
- u = {};
380
- for (var o in t) {
381
- var i = t[o];
382
- if (!("value" === o && "defaultValue" in t && null == i || $ && "children" === o && "noscript" === e || "class" === o || "className" === o)) {
383
- var l = o.toLowerCase();
384
- "defaultValue" === o && "value" in t && null == t.value ? o = "value" : "download" === o && !0 === i ? i = "" : "ondoubleclick" === l ? o = "ondblclick" : "onchange" !== l || "input" !== e && "textarea" !== e || q(t.type) ? "onfocus" === l ? o = "onfocusin" : "onblur" === l ? o = "onfocusout" : Z.test(o) ? o = l : -1 === e.indexOf("-") && H.test(o) ? o = o.replace(Y, "-$&").toLowerCase() : null === i && (i = void 0) : l = o = "oninput", "oninput" === l && u[o = l] && (o = "oninputCapture"), u[o] = i;
385
- }
386
- }
387
- "select" == e && u.multiple && Array.isArray(u.value) && (u.value = toChildArray(t.children).forEach(function (n) {
388
- n.props.selected = -1 != u.value.indexOf(n.props.value);
389
- })), "select" == e && null != u.defaultValue && (u.value = toChildArray(t.children).forEach(function (n) {
390
- n.props.selected = u.multiple ? -1 != u.defaultValue.indexOf(n.props.value) : u.defaultValue == n.props.value;
391
- })), t.class && !t.className ? (u.class = t.class, Object.defineProperty(u, "className", en)) : (t.className && !t.class || t.class && t.className) && (u.class = u.className = t.className), n.props = u;
392
- }(n), n.$$typeof = B, rn && rn(n);
393
- };
394
- var un = options.__r;
395
- options.__r = function (n) {
396
- un && un(n);
397
- };
398
- var on = options.diffed;
399
- options.diffed = function (n) {
400
- on && on(n);
401
- var t = n.props,
402
- e = n.__e;
403
- null != e && "textarea" === n.type && "value" in t && t.value !== e.value && (e.value = null == t.value ? "" : t.value);
404
- };
405
-
406
- var _ = 0;
407
- function o(o, e, n, t, f, l) {
408
- var s,
409
- u,
410
- a = {};
411
- for (u in e) "ref" == u ? s = e[u] : a[u] = e[u];
412
- var i = {
413
- type: o,
414
- props: a,
415
- key: n,
416
- ref: s,
417
- __k: null,
418
- __: null,
419
- __b: 0,
420
- __e: null,
421
- __d: void 0,
422
- __c: null,
423
- __h: null,
424
- constructor: void 0,
425
- __v: --_,
426
- __source: f,
427
- __self: l
428
- };
429
- if ("function" == typeof o && (s = o.defaultProps)) for (u in s) void 0 === a[u] && (a[u] = s[u]);
430
- return options.vnode && options.vnode(i), i;
431
- }
432
-
433
- var ArrowIcon = function ArrowIcon(props) {
434
- return o("svg", {
435
- ...props,
436
- children: o("path", {
437
- fillRule: "evenodd",
438
- 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"
439
- })
440
- });
441
- };
442
- ArrowIcon.defaultProps = {
443
- xmlns: "http://www.w3.org/2000/svg",
444
- width: "16",
445
- height: "16"
446
- };
447
- var CreateIcon = function CreateIcon(props) {
448
- return o("svg", {
449
- ...props,
450
- children: o("path", {
451
- fillRule: "evenodd",
452
- 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"
453
- })
454
- });
455
- };
456
- CreateIcon.defaultProps = {
457
- xmlns: "http://www.w3.org/2000/svg",
458
- width: "16",
459
- height: "16"
460
- };
461
- var DeleteIcon = function DeleteIcon(props) {
462
- return o("svg", {
463
- ...props,
464
- children: o("path", {
465
- fillRule: "evenodd",
466
- 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"
467
- })
468
- });
469
- };
470
- DeleteIcon.defaultProps = {
471
- xmlns: "http://www.w3.org/2000/svg",
472
- width: "16",
473
- height: "16"
474
- };
475
- var DragIcon = function DragIcon(props) {
476
- return o("svg", {
477
- ...props,
478
- children: [o("path", {
479
- fill: "#fff",
480
- style: {
481
- mixBlendMode: "multiply"
482
- },
483
- d: "M0 0h16v16H0z"
484
- }), o("path", {
485
- fill: "#fff",
486
- style: {
487
- mixBlendMode: "multiply"
488
- },
489
- d: "M0 0h16v16H0z"
490
- }), o("path", {
491
- d: "M7 3H5v2h2V3zm4 0H9v2h2V3zM7 7H5v2h2V7zm4 0H9v2h2V7zm-4 4H5v2h2v-2zm4 0H9v2h2v-2z",
492
- fill: "#161616"
493
- })]
494
- });
495
- };
496
- DragIcon.defaultProps = {
497
- width: "16",
498
- height: "16",
499
- fill: "none",
500
- xmlns: "http://www.w3.org/2000/svg"
501
- };
502
- var ExternalLinkIcon = function ExternalLinkIcon(props) {
503
- return o("svg", {
504
- ...props,
505
- children: o("path", {
506
- fillRule: "evenodd",
507
- clipRule: "evenodd",
508
- d: "M12.637 12.637v-4.72h1.362v4.721c0 .36-.137.676-.411.95-.275.275-.591.412-.95.412H3.362c-.38 0-.703-.132-.967-.396A1.315 1.315 0 0 1 2 12.638V3.362c0-.38.132-.703.396-.967S2.982 2 3.363 2h4.553v1.363H3.363v9.274h9.274ZM14 2H9.28l-.001 1.362h2.408L5.065 9.984l.95.95 6.622-6.622v2.409H14V2Z",
509
- fill: "currentcolor"
510
- })
511
- });
512
- };
513
- ExternalLinkIcon.defaultProps = {
514
- width: "16",
515
- height: "16",
516
- fill: "none",
517
- xmlns: "http://www.w3.org/2000/svg"
518
- };
519
- var FeelIcon$1 = function FeelIcon(props) {
520
- return o("svg", {
521
- ...props,
522
- children: o("path", {
523
- d: "M3.617 11.99c-.137.684-.392 1.19-.765 1.518-.362.328-.882.492-1.558.492H0l.309-1.579h1.264l1.515-7.64h-.912l.309-1.579h.911l.236-1.191c.137-.685.387-1.192.75-1.52C4.753.164 5.277 0 5.953 0h1.294L6.94 1.579H5.675l-.323 1.623h1.264l-.309 1.579H5.043l-1.426 7.208ZM5.605 11.021l3.029-4.155L7.28 3.202h2.073l.706 2.547h.176l1.691-2.547H14l-3.014 4.051 1.338 3.768H10.25l-.706-2.606H9.37L7.678 11.02H5.605Z",
524
- fill: "currentcolor"
525
- })
526
- });
527
- };
528
- FeelIcon$1.defaultProps = {
529
- width: "14",
530
- height: "14",
531
- fill: "none",
532
- xmlns: "http://www.w3.org/2000/svg"
533
- };
534
-
535
- function Header(props) {
536
- const {
537
- element,
538
- headerProvider
539
- } = props;
540
- const {
541
- getElementIcon,
542
- getDocumentationRef,
543
- getElementLabel,
544
- getTypeLabel
545
- } = headerProvider;
546
- const label = getElementLabel(element);
547
- const type = getTypeLabel(element);
548
- const documentationRef = getDocumentationRef && getDocumentationRef(element);
549
- const ElementIcon = getElementIcon(element);
550
- return o("div", {
551
- class: "bio-properties-panel-header",
552
- children: [o("div", {
553
- class: "bio-properties-panel-header-icon",
554
- children: ElementIcon && o(ElementIcon, {
555
- width: "32",
556
- height: "32",
557
- viewBox: "0 0 32 32"
558
- })
559
- }), o("div", {
560
- class: "bio-properties-panel-header-labels",
561
- children: [o("div", {
562
- title: type,
563
- class: "bio-properties-panel-header-type",
564
- children: type
565
- }), label ? o("div", {
566
- title: label,
567
- class: "bio-properties-panel-header-label",
568
- children: label
569
- }) : null]
570
- }), o("div", {
571
- class: "bio-properties-panel-header-actions",
572
- children: documentationRef ? o("a", {
573
- rel: "noopener",
574
- class: "bio-properties-panel-header-link",
575
- href: documentationRef,
576
- title: "Open documentation",
577
- target: "_blank",
578
- children: o(ExternalLinkIcon, {})
579
- }) : null
580
- })]
581
- });
582
- }
583
-
584
- const DescriptionContext = createContext({
585
- description: {},
586
- getDescriptionForId: () => {}
587
- });
588
-
589
- const ErrorsContext = createContext({
590
- errors: {}
591
- });
592
-
593
- /**
594
- * @typedef {Function} <propertiesPanel.showEntry> callback
595
- *
596
- * @example
597
- *
598
- * useEvent('propertiesPanel.showEntry', ({ focus = false, ...rest }) => {
599
- * // ...
600
- * });
601
- *
602
- * @param {Object} context
603
- * @param {boolean} [context.focus]
604
- *
605
- * @returns void
606
- */
607
- const EventContext = createContext({
608
- eventBus: null
609
- });
610
-
611
- const LayoutContext = createContext({
612
- layout: {},
613
- setLayout: () => {},
614
- getLayoutForKey: () => {},
615
- setLayoutForKey: () => {}
616
- });
617
-
618
- const TooltipContext = createContext({
619
- tooltip: {},
620
- getTooltipForId: () => {}
621
- });
622
-
623
- /**
624
- * Accesses the global TooltipContext and returns a tooltip for a given id and element.
625
- *
626
- * @example
627
- * ```jsx
628
- * function TextField(props) {
629
- * const tooltip = useTooltipContext('input1', element);
630
- * }
631
- * ```
632
- *
633
- * @param {string} id
634
- * @param {object} element
635
- *
636
- * @returns {string}
637
- */
638
- function useTooltipContext(id, element) {
639
- const {
640
- getTooltipForId
641
- } = q$1(TooltipContext);
642
- return getTooltipForId(id, element);
643
- }
644
-
645
- function TooltipWrapper(props) {
646
- const {
647
- forId,
648
- element
649
- } = props;
650
- const contextDescription = useTooltipContext(forId, element);
651
- const value = props.value || contextDescription;
652
- if (!value) {
653
- return props.children;
654
- }
655
- return o(Tooltip, {
656
- ...props,
657
- value: value,
658
- forId: prefixId$9(forId)
659
- });
660
- }
661
- function Tooltip(props) {
662
- const {
663
- forId,
664
- value,
665
- parent
666
- } = props;
667
- const [visible, setShow] = h(false);
668
- const [focusedViaKeyboard, setFocusedViaKeyboard] = h(false);
669
- let timeout = null;
670
- const wrapperRef = _$1(null);
671
- const tooltipRef = _$1(null);
672
- const showTooltip = async event => {
673
- const show = () => setShow(true);
674
- if (!visible && !timeout) {
675
- if (event instanceof MouseEvent) {
676
- timeout = setTimeout(show, 200);
677
- } else {
678
- show();
679
- setFocusedViaKeyboard(true);
680
- }
681
- }
682
- };
683
- const hideTooltip = () => {
684
- setShow(false);
685
- setFocusedViaKeyboard(false);
686
- };
687
- const hideTooltipViaEscape = e => {
688
- e.code === 'Escape' && hideTooltip();
689
- };
690
- const isTooltipHovered = ({
691
- x,
692
- y
693
- }) => {
694
- const tooltip = tooltipRef.current;
695
- const wrapper = wrapperRef.current;
696
- return tooltip && (inBounds(x, y, wrapper.getBoundingClientRect()) || inBounds(x, y, tooltip.getBoundingClientRect()));
697
- };
698
- p(() => {
699
- const {
700
- current
701
- } = wrapperRef;
702
- if (!current) {
703
- return;
704
- }
705
- const hideHoveredTooltip = e => {
706
- const isFocused = document.activeElement === wrapperRef.current || document.activeElement.closest('.bio-properties-panel-tooltip');
707
- if (visible && !isTooltipHovered({
708
- x: e.x,
709
- y: e.y
710
- }) && !(isFocused && focusedViaKeyboard)) {
711
- hideTooltip();
712
- }
713
- };
714
- const hideFocusedTooltip = e => {
715
- const {
716
- relatedTarget
717
- } = e;
718
- const isTooltipChild = el => !!el.closest('.bio-properties-panel-tooltip');
719
- if (visible && !isHovered(wrapperRef.current) && relatedTarget && !isTooltipChild(relatedTarget)) {
720
- hideTooltip();
721
- }
722
- };
723
- document.addEventListener('wheel', hideHoveredTooltip);
724
- document.addEventListener('focusout', hideFocusedTooltip);
725
- document.addEventListener('mousemove', hideHoveredTooltip);
726
- return () => {
727
- document.removeEventListener('wheel', hideHoveredTooltip);
728
- document.removeEventListener('mousemove', hideHoveredTooltip);
729
- document.removeEventListener('focusout', hideFocusedTooltip);
730
- };
731
- }, [wrapperRef.current, visible, focusedViaKeyboard]);
732
- const renderTooltip = () => {
733
- return o("div", {
734
- class: "bio-properties-panel-tooltip",
735
- role: "tooltip",
736
- id: "bio-properties-panel-tooltip",
737
- "aria-labelledby": forId,
738
- style: getTooltipPosition(wrapperRef.current),
739
- ref: tooltipRef,
740
- onClick: e => e.stopPropagation(),
741
- children: [o("div", {
742
- class: "bio-properties-panel-tooltip-content",
743
- children: value
744
- }), o("div", {
745
- class: "bio-properties-panel-tooltip-arrow"
746
- })]
747
- });
748
- };
749
- return o("div", {
750
- class: "bio-properties-panel-tooltip-wrapper",
751
- tabIndex: "0",
752
- ref: wrapperRef,
753
- onMouseEnter: showTooltip,
754
- onMouseLeave: () => {
755
- clearTimeout(timeout);
756
- timeout = null;
757
- },
758
- onFocus: showTooltip,
759
- onKeyDown: hideTooltipViaEscape,
760
- children: [props.children, visible ? parent ? z(renderTooltip(), parent.current) : renderTooltip() : null]
761
- });
762
- }
763
-
764
- // helper
765
- function inBounds(x, y, bounds) {
766
- const {
767
- top,
768
- right,
769
- bottom,
770
- left
771
- } = bounds;
772
- return x >= left && x <= right && y >= top && y <= bottom;
773
- }
774
- function getTooltipPosition(refElement) {
775
- const refPosition = refElement.getBoundingClientRect();
776
- const right = `calc(100% - ${refPosition.x}px)`;
777
- const top = `${refPosition.top - 10}px`;
778
- return `right: ${right}; top: ${top};`;
779
- }
780
- function isHovered(element) {
781
- return element.matches(':hover');
782
- }
783
- function prefixId$9(id) {
784
- return `bio-properties-panel-${id}`;
785
- }
786
-
787
- /**
788
- * Accesses the global DescriptionContext and returns a description for a given id and element.
789
- *
790
- * @example
791
- * ```jsx
792
- * function TextField(props) {
793
- * const description = useDescriptionContext('input1', element);
794
- * }
795
- * ```
796
- *
797
- * @param {string} id
798
- * @param {object} element
799
- *
800
- * @returns {string}
801
- */
802
- function useDescriptionContext(id, element) {
803
- const {
804
- getDescriptionForId
805
- } = q$1(DescriptionContext);
806
- return getDescriptionForId(id, element);
807
- }
808
-
809
- function useError(id) {
810
- const {
811
- errors
812
- } = q$1(ErrorsContext);
813
- return errors[id];
814
- }
815
- function useErrors() {
816
- const {
817
- errors
818
- } = q$1(ErrorsContext);
819
- return errors;
820
- }
821
-
822
- /**
823
- * Subscribe to an event immediately. Update subscription after inputs changed.
824
- *
825
- * @param {string} event
826
- * @param {Function} callback
827
- */
828
- function useEvent(event, callback, eventBus) {
829
- const eventContext = q$1(EventContext);
830
- if (!eventBus) {
831
- ({
832
- eventBus
833
- } = eventContext);
834
- }
835
- const didMount = _$1(false);
836
-
837
- // (1) subscribe immediately
838
- if (eventBus && !didMount.current) {
839
- eventBus.on(event, callback);
840
- }
841
-
842
- // (2) update subscription after inputs changed
843
- p(() => {
844
- if (eventBus && didMount.current) {
845
- eventBus.on(event, callback);
846
- }
847
- didMount.current = true;
848
- return () => {
849
- if (eventBus) {
850
- eventBus.off(event, callback);
851
- }
852
- };
853
- }, [callback, event, eventBus]);
854
- }
855
-
856
- const KEY_LENGTH = 6;
857
-
858
- /**
859
- * Create a persistent key factory for plain objects without id.
860
- *
861
- * @example
862
- * ```jsx
863
- * function List({ objects }) {
864
- * const getKey = useKeyFactory();
865
- * return (<ol>{
866
- * objects.map(obj => {
867
- * const key = getKey(obj);
868
- * return <li key={key}>obj.name</li>
869
- * })
870
- * }</ol>);
871
- * }
872
- * ```
873
- *
874
- * @param {any[]} dependencies
875
- * @returns {(element: object) => string}
876
- */
877
- function useKeyFactory(dependencies = []) {
878
- const map = F$1(() => new Map(), dependencies);
879
- const getKey = el => {
880
- let key = map.get(el);
881
- if (!key) {
882
- key = Math.random().toString().slice(-KEY_LENGTH);
883
- map.set(el, key);
884
- }
885
- return key;
886
- };
887
- return getKey;
888
- }
889
-
890
- /**
891
- * Creates a state that persists in the global LayoutContext.
892
- *
893
- * @example
894
- * ```jsx
895
- * function Group(props) {
896
- * const [ open, setOpen ] = useLayoutState([ 'groups', 'foo', 'open' ], false);
897
- * }
898
- * ```
899
- *
900
- * @param {(string|number)[]} path
901
- * @param {any} [defaultValue]
902
- *
903
- * @returns {[ any, Function ]}
904
- */
905
- function useLayoutState(path, defaultValue) {
906
- const {
907
- getLayoutForKey,
908
- setLayoutForKey
909
- } = q$1(LayoutContext);
910
- const layoutForKey = getLayoutForKey(path, defaultValue);
911
- const setState = T$1(newValue => {
912
- setLayoutForKey(path, newValue);
913
- }, [setLayoutForKey]);
914
- return [layoutForKey, setState];
915
- }
916
-
917
- /**
918
- * @pinussilvestrus: we need to introduce our own hook to persist the previous
919
- * state on updates.
920
- *
921
- * cf. https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state
922
- */
923
-
924
- function usePrevious(value) {
925
- const ref = _$1();
926
- p(() => {
927
- ref.current = value;
928
- });
929
- return ref.current;
930
- }
931
-
932
- /**
933
- * Subscribe to `propertiesPanel.showEntry`.
934
- *
935
- * @param {string} id
936
- *
937
- * @returns {import('preact').Ref}
938
- */
939
- function useShowEntryEvent(id) {
940
- const {
941
- onShow
942
- } = q$1(LayoutContext);
943
- const ref = _$1();
944
- const focus = _$1(false);
945
- const onShowEntry = T$1(event => {
946
- if (event.id === id) {
947
- onShow();
948
- if (!focus.current) {
949
- focus.current = true;
950
- }
951
- }
952
- }, [id]);
953
- p(() => {
954
- if (focus.current && ref.current) {
955
- if (isFunction(ref.current.focus)) {
956
- ref.current.focus();
957
- }
958
- if (isFunction(ref.current.select)) {
959
- ref.current.select();
960
- }
961
- focus.current = false;
962
- }
963
- });
964
- useEvent('propertiesPanel.showEntry', onShowEntry);
965
- return ref;
966
- }
967
-
968
- /**
969
- * @callback setSticky
970
- * @param {boolean} value
971
- */
972
-
973
- /**
974
- * Use IntersectionObserver to identify when DOM element is in sticky mode.
975
- * If sticky is observered setSticky(true) will be called.
976
- * If sticky mode is left, setSticky(false) will be called.
977
- *
978
- *
979
- * @param {Object} ref
980
- * @param {string} scrollContainerSelector
981
- * @param {setSticky} setSticky
982
- */
983
- function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky) {
984
- const [scrollContainer, setScrollContainer] = h(query(scrollContainerSelector));
985
- const updateScrollContainer = T$1(() => {
986
- const newScrollContainer = query(scrollContainerSelector);
987
- if (newScrollContainer !== scrollContainer) {
988
- setScrollContainer(newScrollContainer);
989
- }
990
- }, [scrollContainerSelector, scrollContainer]);
991
- p(() => {
992
- updateScrollContainer();
993
- }, [updateScrollContainer]);
994
- useEvent('propertiesPanel.attach', updateScrollContainer);
995
- useEvent('propertiesPanel.detach', updateScrollContainer);
996
- p(() => {
997
- const Observer = IntersectionObserver;
998
-
999
- // return early if IntersectionObserver is not available
1000
- if (!Observer) {
1001
- return;
1002
- }
1003
-
1004
- // TODO(@barmac): test this
1005
- if (!ref.current || !scrollContainer) {
1006
- return;
1007
- }
1008
- const observer = new Observer(entries => {
1009
- // scroll container is unmounted, do not update sticky state
1010
- if (scrollContainer.scrollHeight === 0) {
1011
- return;
1012
- }
1013
- entries.forEach(entry => {
1014
- if (entry.intersectionRatio < 1) {
1015
- setSticky(true);
1016
- } else if (entry.intersectionRatio === 1) {
1017
- setSticky(false);
1018
- }
1019
- });
1020
- }, {
1021
- root: scrollContainer,
1022
- rootMargin: '0px 0px 999999% 0px',
1023
- // Use bottom margin to avoid stickyness when scrolling out to bottom
1024
- threshold: [1]
1025
- });
1026
- observer.observe(ref.current);
1027
-
1028
- // Unobserve if unmounted
1029
- return () => {
1030
- observer.unobserve(ref.current);
1031
- };
1032
- }, [ref.current, scrollContainer, setSticky]);
1033
- }
1034
-
1035
- /**
1036
- * Creates a static function reference with changing body.
1037
- * This is necessary when external libraries require a callback function
1038
- * that has references to state variables.
1039
- *
1040
- * Usage:
1041
- * const callback = useStaticCallback((val) => {val === currentState});
1042
- *
1043
- * The `callback` reference is static and can be safely used in external
1044
- * libraries or as a prop that does not cause rerendering of children.
1045
- *
1046
- * @param {Function} callback function with changing reference
1047
- * @returns {Function} static function reference
1048
- */
1049
- function useStaticCallback(callback) {
1050
- const callbackRef = _$1(callback);
1051
- callbackRef.current = callback;
1052
- return T$1((...args) => callbackRef.current(...args), []);
1053
- }
1054
-
1055
- function Group(props) {
1056
- const {
1057
- element,
1058
- entries = [],
1059
- id,
1060
- label,
1061
- shouldOpen = false
1062
- } = props;
1063
- const groupRef = _$1(null);
1064
- const [open, setOpen] = useLayoutState(['groups', id, 'open'], shouldOpen);
1065
- const onShow = T$1(() => setOpen(true), [setOpen]);
1066
- const toggleOpen = () => setOpen(!open);
1067
- const [edited, setEdited] = h(false);
1068
- const [sticky, setSticky] = h(false);
1069
-
1070
- // set edited state depending on all entries
1071
- p(() => {
1072
- // TODO(@barmac): replace with CSS when `:has()` is supported in all major browsers, or rewrite as in https://github.com/camunda/camunda-modeler/issues/3815#issuecomment-1733038161
1073
- const scheduled = requestAnimationFrame(() => {
1074
- const hasOneEditedEntry = entries.find(entry => {
1075
- const {
1076
- id,
1077
- isEdited
1078
- } = entry;
1079
- const entryNode = query(`[data-entry-id="${id}"]`);
1080
- if (!isFunction(isEdited) || !entryNode) {
1081
- return false;
1082
- }
1083
- const inputNode = query('.bio-properties-panel-input', entryNode);
1084
- return isEdited(inputNode);
1085
- });
1086
- setEdited(hasOneEditedEntry);
1087
- });
1088
- return () => cancelAnimationFrame(scheduled);
1089
- }, [entries, setEdited]);
1090
-
1091
- // set error state depending on all entries
1092
- const allErrors = useErrors();
1093
- const hasErrors = entries.some(entry => allErrors[entry.id]);
1094
-
1095
- // set css class when group is sticky to top
1096
- useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);
1097
- const propertiesPanelContext = {
1098
- ...q$1(LayoutContext),
1099
- onShow
1100
- };
1101
- return o("div", {
1102
- class: "bio-properties-panel-group",
1103
- "data-group-id": 'group-' + id,
1104
- ref: groupRef,
1105
- children: [o("div", {
1106
- class: classnames('bio-properties-panel-group-header', edited ? '' : 'empty', open ? 'open' : '', sticky && open ? 'sticky' : ''),
1107
- onClick: toggleOpen,
1108
- children: [o("div", {
1109
- title: props.tooltip ? null : label,
1110
- "data-title": label,
1111
- class: "bio-properties-panel-group-header-title",
1112
- children: o(TooltipWrapper, {
1113
- value: props.tooltip,
1114
- forId: 'group-' + id,
1115
- element: element,
1116
- parent: groupRef,
1117
- children: label
1118
- })
1119
- }), o("div", {
1120
- class: "bio-properties-panel-group-header-buttons",
1121
- children: [o(DataMarker, {
1122
- edited: edited,
1123
- hasErrors: hasErrors
1124
- }), o("button", {
1125
- title: "Toggle section",
1126
- class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
1127
- children: o(ArrowIcon, {
1128
- class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
1129
- })
1130
- })]
1131
- })]
1132
- }), o("div", {
1133
- class: classnames('bio-properties-panel-group-entries', open ? 'open' : ''),
1134
- children: o(LayoutContext.Provider, {
1135
- value: propertiesPanelContext,
1136
- children: entries.map(entry => {
1137
- const {
1138
- component: Component,
1139
- id
1140
- } = entry;
1141
- return createElement(Component, {
1142
- ...entry,
1143
- element: element,
1144
- key: id
1145
- });
1146
- })
1147
- })
1148
- })]
1149
- });
1150
- }
1151
- function DataMarker(props) {
1152
- const {
1153
- edited,
1154
- hasErrors
1155
- } = props;
1156
- if (hasErrors) {
1157
- return o("div", {
1158
- title: "Section contains an error",
1159
- class: "bio-properties-panel-dot bio-properties-panel-dot--error"
1160
- });
1161
- }
1162
- if (edited) {
1163
- return o("div", {
1164
- title: "Section contains data",
1165
- class: "bio-properties-panel-dot"
1166
- });
1167
- }
1168
- return null;
1169
- }
1170
-
1171
- /**
1172
- * @typedef { {
1173
- * text: (element: object) => string,
1174
- * icon?: (element: Object) => import('preact').Component
1175
- * } } PlaceholderDefinition
1176
- *
1177
- * @param { PlaceholderDefinition } props
1178
- */
1179
- function Placeholder(props) {
1180
- const {
1181
- text,
1182
- icon: Icon
1183
- } = props;
1184
- return o("div", {
1185
- class: "bio-properties-panel open",
1186
- children: o("section", {
1187
- class: "bio-properties-panel-placeholder",
1188
- children: [Icon && o(Icon, {
1189
- class: "bio-properties-panel-placeholder-icon"
1190
- }), o("p", {
1191
- class: "bio-properties-panel-placeholder-text",
1192
- children: text
1193
- })]
1194
- })
1195
- });
1196
- }
1197
-
1198
- function Description(props) {
1199
- const {
1200
- element,
1201
- forId,
1202
- value
1203
- } = props;
1204
- const contextDescription = useDescriptionContext(forId, element);
1205
- const description = value || contextDescription;
1206
- if (description) {
1207
- return o("div", {
1208
- class: "bio-properties-panel-description",
1209
- children: description
1210
- });
1211
- }
1212
- }
1213
-
1214
- const noop$6 = () => {};
1215
-
1216
- /**
1217
- * Buffer `.focus()` calls while the editor is not initialized.
1218
- * Set Focus inside when the editor is ready.
1219
- */
1220
- const useBufferedFocus$1 = function (editor, ref) {
1221
- const [buffer, setBuffer] = h(undefined);
1222
- ref.current = F$1(() => ({
1223
- focus: offset => {
1224
- if (editor) {
1225
- editor.focus(offset);
1226
- } else {
1227
- if (typeof offset === 'undefined') {
1228
- offset = Infinity;
1229
- }
1230
- setBuffer(offset);
1231
- }
1232
- }
1233
- }), [editor]);
1234
- p(() => {
1235
- if (typeof buffer !== 'undefined' && editor) {
1236
- editor.focus(buffer);
1237
- setBuffer(false);
1238
- }
1239
- }, [editor, buffer]);
1240
- };
1241
- const CodeEditor$1 = k((props, ref) => {
1242
- const {
1243
- onInput,
1244
- disabled,
1245
- tooltipContainer,
1246
- enableGutters,
1247
- value,
1248
- onLint = noop$6,
1249
- onPopupOpen = noop$6,
1250
- popupOpen,
1251
- contentAttributes = {},
1252
- hostLanguage = null,
1253
- singleLine = false
1254
- } = props;
1255
- const inputRef = _$1();
1256
- const [editor, setEditor] = h();
1257
- const [localValue, setLocalValue] = h(value || '');
1258
- useBufferedFocus$1(editor, ref);
1259
- const handleInput = useStaticCallback(newValue => {
1260
- onInput(newValue);
1261
- setLocalValue(newValue);
1262
- });
1263
- p(() => {
1264
- let editor;
1265
- editor = new FeelersEditor({
1266
- container: inputRef.current,
1267
- onChange: handleInput,
1268
- value: localValue,
1269
- onLint,
1270
- contentAttributes,
1271
- tooltipContainer,
1272
- enableGutters,
1273
- hostLanguage,
1274
- singleLine
1275
- });
1276
- setEditor(editor);
1277
- return () => {
1278
- onLint([]);
1279
- inputRef.current.innerHTML = '';
1280
- setEditor(null);
1281
- };
1282
- }, []);
1283
- p(() => {
1284
- if (!editor) {
1285
- return;
1286
- }
1287
- if (value === localValue) {
1288
- return;
1289
- }
1290
- editor.setValue(value);
1291
- setLocalValue(value);
1292
- }, [value]);
1293
- const handleClick = () => {
1294
- ref.current.focus();
1295
- };
1296
- return o("div", {
1297
- class: classnames('bio-properties-panel-feelers-editor-container', popupOpen ? 'popupOpen' : null),
1298
- children: [o("div", {
1299
- class: "bio-properties-panel-feelers-editor__open-popup-placeholder",
1300
- children: "Opened in editor"
1301
- }), o("div", {
1302
- name: props.name,
1303
- class: classnames('bio-properties-panel-feelers-editor bio-properties-panel-input', localValue ? 'edited' : null, disabled ? 'disabled' : null),
1304
- ref: inputRef,
1305
- onClick: handleClick
1306
- }), o("button", {
1307
- title: "Open pop-up editor",
1308
- class: "bio-properties-panel-open-feel-popup",
1309
- onClick: () => onPopupOpen('feelers'),
1310
- children: o(ExternalLinkIcon, {})
1311
- })]
1312
- });
1313
- });
1314
-
1315
- const noop$5 = () => {};
1316
-
1317
- /**
1318
- * Buffer `.focus()` calls while the editor is not initialized.
1319
- * Set Focus inside when the editor is ready.
1320
- */
1321
- const useBufferedFocus = function (editor, ref) {
1322
- const [buffer, setBuffer] = h(undefined);
1323
- ref.current = F$1(() => ({
1324
- focus: offset => {
1325
- if (editor) {
1326
- editor.focus(offset);
1327
- } else {
1328
- if (typeof offset === 'undefined') {
1329
- offset = Infinity;
1330
- }
1331
- setBuffer(offset);
1332
- }
1333
- }
1334
- }), [editor]);
1335
- p(() => {
1336
- if (typeof buffer !== 'undefined' && editor) {
1337
- editor.focus(buffer);
1338
- setBuffer(false);
1339
- }
1340
- }, [editor, buffer]);
1341
- };
1342
- const CodeEditor = k((props, ref) => {
1343
- const {
1344
- enableGutters,
1345
- value,
1346
- onInput,
1347
- onFeelToggle = noop$5,
1348
- onLint = noop$5,
1349
- onPopupOpen = noop$5,
1350
- popupOpen,
1351
- disabled,
1352
- tooltipContainer,
1353
- variables
1354
- } = props;
1355
- const inputRef = _$1();
1356
- const [editor, setEditor] = h();
1357
- const [localValue, setLocalValue] = h(value || '');
1358
- useBufferedFocus(editor, ref);
1359
- const handleInput = useStaticCallback(newValue => {
1360
- onInput(newValue);
1361
- setLocalValue(newValue);
1362
- });
1363
- p(() => {
1364
- let editor;
1365
-
1366
- /* Trigger FEEL toggle when
1367
- *
1368
- * - `backspace` is pressed
1369
- * - AND the cursor is at the beginning of the input
1370
- */
1371
- const onKeyDown = e => {
1372
- if (e.key !== 'Backspace' || !editor) {
1373
- return;
1374
- }
1375
- const selection = editor.getSelection();
1376
- const range = selection.ranges[selection.mainIndex];
1377
- if (range.from === 0 && range.to === 0) {
1378
- onFeelToggle();
1379
- }
1380
- };
1381
- editor = new FeelEditor({
1382
- container: inputRef.current,
1383
- onChange: handleInput,
1384
- onKeyDown: onKeyDown,
1385
- onLint: onLint,
1386
- tooltipContainer: tooltipContainer,
1387
- value: localValue,
1388
- variables: variables,
1389
- extensions: [...(enableGutters ? [lineNumbers()] : [])]
1390
- });
1391
- setEditor(editor);
1392
- return () => {
1393
- onLint([]);
1394
- inputRef.current.innerHTML = '';
1395
- setEditor(null);
1396
- };
1397
- }, []);
1398
- p(() => {
1399
- if (!editor) {
1400
- return;
1401
- }
1402
- if (value === localValue) {
1403
- return;
1404
- }
1405
- editor.setValue(value);
1406
- setLocalValue(value);
1407
- }, [value]);
1408
- p(() => {
1409
- if (!editor) {
1410
- return;
1411
- }
1412
- editor.setVariables(variables);
1413
- }, [variables]);
1414
- const handleClick = () => {
1415
- ref.current.focus();
1416
- };
1417
- return o("div", {
1418
- class: classnames('bio-properties-panel-feel-editor-container', disabled ? 'disabled' : null, popupOpen ? 'popupOpen' : null),
1419
- children: [o("div", {
1420
- class: "bio-properties-panel-feel-editor__open-popup-placeholder",
1421
- children: "Opened in editor"
1422
- }), o("div", {
1423
- name: props.name,
1424
- class: classnames('bio-properties-panel-input', localValue ? 'edited' : null),
1425
- ref: inputRef,
1426
- onClick: handleClick
1427
- }), o("button", {
1428
- title: "Open pop-up editor",
1429
- class: "bio-properties-panel-open-feel-popup",
1430
- onClick: () => onPopupOpen(),
1431
- children: o(ExternalLinkIcon, {})
1432
- })]
1433
- });
1434
- });
1435
-
1436
- function FeelIndicator(props) {
1437
- const {
1438
- active
1439
- } = props;
1440
- if (!active) {
1441
- return null;
1442
- }
1443
- return o("span", {
1444
- class: "bio-properties-panel-feel-indicator",
1445
- children: "="
1446
- });
1447
- }
1448
-
1449
- const noop$4 = () => {};
1450
-
1451
- /**
1452
- * @param {Object} props
1453
- * @param {Object} props.label
1454
- * @param {String} props.feel
1455
- */
1456
- function FeelIcon(props) {
1457
- const {
1458
- feel = false,
1459
- active,
1460
- disabled = false,
1461
- onClick = noop$4
1462
- } = props;
1463
- const feelRequiredLabel = 'FEEL expression is mandatory';
1464
- const feelOptionalLabel = `Click to ${active ? 'remove' : 'set a'} dynamic value with FEEL expression`;
1465
- const handleClick = e => {
1466
- onClick(e);
1467
-
1468
- // when pointer event was created from keyboard, keep focus on button
1469
- if (!e.pointerType) {
1470
- e.stopPropagation();
1471
- }
1472
- };
1473
- return o("button", {
1474
- class: classnames('bio-properties-panel-feel-icon', active ? 'active' : null, feel === 'required' ? 'required' : 'optional'),
1475
- onClick: handleClick,
1476
- disabled: feel === 'required' || disabled,
1477
- title: feel === 'required' ? feelRequiredLabel : feelOptionalLabel,
1478
- children: o(FeelIcon$1, {})
1479
- });
1480
- }
1481
-
1482
- const FeelPopupContext = createContext({
1483
- open: () => {},
1484
- close: () => {},
1485
- source: null
1486
- });
1487
-
1488
- /**
1489
- * Add a dragger that calls back the passed function with
1490
- * { event, delta } on drag.
1491
- *
1492
- * @example
1493
- *
1494
- * function dragMove(event, delta) {
1495
- * // we are dragging (!!)
1496
- * }
1497
- *
1498
- * domElement.addEventListener('dragstart', dragger(dragMove));
1499
- *
1500
- * @param {Function} fn
1501
- * @param {Element} [dragPreview]
1502
- *
1503
- * @return {Function} drag start callback function
1504
- */
1505
- function createDragger(fn, dragPreview) {
1506
- let self;
1507
- let startX, startY;
1508
-
1509
- /** drag start */
1510
- function onDragStart(event) {
1511
- self = this;
1512
- startX = event.clientX;
1513
- startY = event.clientY;
1514
-
1515
- // (1) prevent preview image
1516
- if (event.dataTransfer) {
1517
- event.dataTransfer.setDragImage(dragPreview || emptyCanvas(), 0, 0);
1518
- }
1519
-
1520
- // (2) setup drag listeners
1521
-
1522
- // attach drag + cleanup event
1523
- // we need to do this to make sure we track cursor
1524
- // movements before we reach other drag event handlers,
1525
- // e.g. in child containers.
1526
- document.addEventListener('dragover', onDrag, true);
1527
- document.addEventListener('dragenter', preventDefault, true);
1528
- document.addEventListener('dragend', onEnd);
1529
- document.addEventListener('drop', preventDefault);
1530
- }
1531
- function onDrag(event) {
1532
- const delta = {
1533
- x: event.clientX - startX,
1534
- y: event.clientY - startY
1535
- };
1536
-
1537
- // call provided fn with event, delta
1538
- return fn.call(self, event, delta);
1539
- }
1540
- function onEnd() {
1541
- document.removeEventListener('dragover', onDrag, true);
1542
- document.removeEventListener('dragenter', preventDefault, true);
1543
- document.removeEventListener('dragend', onEnd);
1544
- document.removeEventListener('drop', preventDefault);
1545
- }
1546
- return onDragStart;
1547
- }
1548
- function preventDefault(event) {
1549
- event.preventDefault();
1550
- event.stopPropagation();
1551
- }
1552
- function emptyCanvas() {
1553
- return domify('<canvas width="0" height="0" />');
1554
- }
1555
-
1556
- const noop$3 = () => {};
1557
-
1558
- /**
1559
- * A generic popup component.
1560
- *
1561
- * @param {Object} props
1562
- * @param {HTMLElement} [props.container]
1563
- * @param {string} [props.className]
1564
- * @param {boolean} [props.delayInitialFocus]
1565
- * @param {{x: number, y: number}} [props.position]
1566
- * @param {number} [props.width]
1567
- * @param {number} [props.height]
1568
- * @param {Function} props.onClose
1569
- * @param {Function} [props.onPostActivate]
1570
- * @param {Function} [props.onPostDeactivate]
1571
- * @param {boolean} [props.returnFocus]
1572
- * @param {boolean} [props.closeOnEscape]
1573
- * @param {string} props.title
1574
- * @param {Ref} [ref]
1575
- */
1576
- function PopupComponent(props, globalRef) {
1577
- const {
1578
- container,
1579
- className,
1580
- delayInitialFocus,
1581
- position,
1582
- width,
1583
- height,
1584
- onClose,
1585
- onPostActivate = noop$3,
1586
- onPostDeactivate = noop$3,
1587
- returnFocus = true,
1588
- closeOnEscape = true,
1589
- title
1590
- } = props;
1591
- const focusTrapRef = _$1(null);
1592
- const localRef = _$1(null);
1593
- const popupRef = globalRef || localRef;
1594
- const containerNode = F$1(() => getContainerNode(container), [container]);
1595
- const handleKeydown = event => {
1596
- // do not allow keyboard events to bubble
1597
- event.stopPropagation();
1598
- if (closeOnEscape && event.key === 'Escape') {
1599
- onClose();
1600
- }
1601
- };
1602
-
1603
- // re-activate focus trap on focus
1604
- const handleFocus = () => {
1605
- if (focusTrapRef.current) {
1606
- focusTrapRef.current.activate();
1607
- }
1608
- };
1609
- let style = {};
1610
- if (position) {
1611
- style = {
1612
- ...style,
1613
- top: position.top + 'px',
1614
- left: position.left + 'px'
1615
- };
1616
- }
1617
- if (width) {
1618
- style.width = width + 'px';
1619
- }
1620
- if (height) {
1621
- style.height = height + 'px';
1622
- }
1623
- p(() => {
1624
- if (popupRef.current) {
1625
- popupRef.current.addEventListener('focusin', handleFocus);
1626
- }
1627
- return () => {
1628
- popupRef.current.removeEventListener('focusin', handleFocus);
1629
- };
1630
- }, [popupRef]);
1631
- p(() => {
1632
- if (popupRef.current) {
1633
- focusTrapRef.current = focusTrap.createFocusTrap(popupRef.current, {
1634
- clickOutsideDeactivates: true,
1635
- delayInitialFocus,
1636
- fallbackFocus: popupRef.current,
1637
- onPostActivate,
1638
- onPostDeactivate,
1639
- returnFocusOnDeactivate: returnFocus
1640
- });
1641
- focusTrapRef.current.activate();
1642
- }
1643
- return () => focusTrapRef.current && focusTrapRef.current.deactivate();
1644
- }, [popupRef]);
1645
- return z(o("div", {
1646
- "aria-label": title,
1647
- tabIndex: -1,
1648
- ref: popupRef,
1649
- onKeyDown: handleKeydown,
1650
- role: "dialog",
1651
- class: classnames('bio-properties-panel-popup', className),
1652
- style: style,
1653
- children: props.children
1654
- }), containerNode || document.body);
1655
- }
1656
- const Popup = k(PopupComponent);
1657
- Popup.Title = Title;
1658
- Popup.Body = Body;
1659
- Popup.Footer = Footer;
1660
- function Title(props) {
1661
- const {
1662
- children,
1663
- className,
1664
- draggable,
1665
- emit = () => {},
1666
- title,
1667
- ...rest
1668
- } = props;
1669
-
1670
- // we can't use state as we need to
1671
- // manipulate this inside dragging events
1672
- const context = _$1({
1673
- startPosition: null,
1674
- newPosition: null
1675
- });
1676
- const dragPreviewRef = _$1();
1677
- const titleRef = _$1();
1678
- const onMove = (event, delta) => {
1679
- cancel(event);
1680
- const {
1681
- x: dx,
1682
- y: dy
1683
- } = delta;
1684
- const newPosition = {
1685
- x: context.current.startPosition.x + dx,
1686
- y: context.current.startPosition.y + dy
1687
- };
1688
- const popupParent = getPopupParent(titleRef.current);
1689
- popupParent.style.top = newPosition.y + 'px';
1690
- popupParent.style.left = newPosition.x + 'px';
1691
-
1692
- // notify interested parties
1693
- emit('dragover', {
1694
- newPosition,
1695
- delta
1696
- });
1697
- };
1698
- const onMoveStart = event => {
1699
- // initialize drag handler
1700
- const onDragStart = createDragger(onMove, dragPreviewRef.current);
1701
- onDragStart(event);
1702
- event.stopPropagation();
1703
- const popupParent = getPopupParent(titleRef.current);
1704
- const bounds = popupParent.getBoundingClientRect();
1705
- context.current.startPosition = {
1706
- x: bounds.left,
1707
- y: bounds.top
1708
- };
1709
-
1710
- // notify interested parties
1711
- emit('dragstart');
1712
- };
1713
- const onMoveEnd = () => {
1714
- context.current.newPosition = null;
1715
-
1716
- // notify interested parties
1717
- emit('dragend');
1718
- };
1719
- return o("div", {
1720
- class: classnames('bio-properties-panel-popup__header', draggable && 'draggable', className),
1721
- ref: titleRef,
1722
- draggable: draggable,
1723
- onDragStart: onMoveStart,
1724
- onDragEnd: onMoveEnd,
1725
- ...rest,
1726
- children: [draggable && o(Fragment, {
1727
- children: [o("div", {
1728
- ref: dragPreviewRef,
1729
- class: "bio-properties-panel-popup__drag-preview"
1730
- }), o("div", {
1731
- class: "bio-properties-panel-popup__drag-handle",
1732
- children: o(DragIcon, {})
1733
- })]
1734
- }), o("div", {
1735
- class: "bio-properties-panel-popup__title",
1736
- children: title
1737
- }), children]
1738
- });
1739
- }
1740
- function Body(props) {
1741
- const {
1742
- children,
1743
- className,
1744
- ...rest
1745
- } = props;
1746
- return o("div", {
1747
- class: classnames('bio-properties-panel-popup__body', className),
1748
- ...rest,
1749
- children: children
1750
- });
1751
- }
1752
- function Footer(props) {
1753
- const {
1754
- children,
1755
- className,
1756
- ...rest
1757
- } = props;
1758
- return o("div", {
1759
- class: classnames('bio-properties-panel-popup__footer', className),
1760
- ...rest,
1761
- children: props.children
1762
- });
1763
- }
1764
-
1765
- // helpers //////////////////////
1766
-
1767
- function getPopupParent(node) {
1768
- return node.closest('.bio-properties-panel-popup');
1769
- }
1770
- function cancel(event) {
1771
- event.preventDefault();
1772
- event.stopPropagation();
1773
- }
1774
- function getContainerNode(node) {
1775
- if (typeof node === 'string') {
1776
- return query(node);
1777
- }
1778
- return node;
1779
- }
1780
-
1781
- const FEEL_POPUP_WIDTH = 700;
1782
- const FEEL_POPUP_HEIGHT = 250;
1783
-
1784
- /**
1785
- * FEEL popup component, built as a singleton. Emits lifecycle events as follows:
1786
- * - `feelPopup.open` - fired before the popup is mounted
1787
- * - `feelPopup.opened` - fired after the popup is mounted. Event context contains the DOM node of the popup
1788
- * - `feelPopup.close` - fired before the popup is unmounted. Event context contains the DOM node of the popup
1789
- * - `feelPopup.closed` - fired after the popup is unmounted
1790
- */
1791
- function FEELPopupRoot(props) {
1792
- const {
1793
- element,
1794
- eventBus = {
1795
- fire() {},
1796
- on() {},
1797
- off() {}
1798
- },
1799
- popupContainer
1800
- } = props;
1801
- const prevElement = usePrevious(element);
1802
- const [popupConfig, setPopupConfig] = h({});
1803
- const [open, setOpen] = h(false);
1804
- const [source, setSource] = h(null);
1805
- const [sourceElement, setSourceElement] = h(null);
1806
- const emit = (type, context) => {
1807
- eventBus.fire('feelPopup.' + type, context);
1808
- };
1809
- const isOpen = T$1(() => {
1810
- return !!open;
1811
- }, [open]);
1812
- useUpdateEffect(() => {
1813
- if (!open) {
1814
- emit('closed');
1815
- }
1816
- }, [open]);
1817
- const handleOpen = (entryId, config, _sourceElement) => {
1818
- setSource(entryId);
1819
- setPopupConfig(config);
1820
- setOpen(true);
1821
- setSourceElement(_sourceElement);
1822
- emit('open');
1823
- };
1824
- const handleClose = () => {
1825
- setOpen(false);
1826
- setSource(null);
1827
- };
1828
- const feelPopupContext = {
1829
- open: handleOpen,
1830
- close: handleClose,
1831
- source
1832
- };
1833
-
1834
- // close popup on element change, cf. https://github.com/bpmn-io/properties-panel/issues/270
1835
- p(() => {
1836
- if (element && prevElement && element !== prevElement) {
1837
- handleClose();
1838
- }
1839
- }, [element]);
1840
-
1841
- // allow close and open via events
1842
- p(() => {
1843
- const handlePopupOpen = context => {
1844
- const {
1845
- entryId,
1846
- popupConfig,
1847
- sourceElement
1848
- } = context;
1849
- handleOpen(entryId, popupConfig, sourceElement);
1850
- };
1851
- const handleIsOpen = () => {
1852
- return isOpen();
1853
- };
1854
- eventBus.on('feelPopup._close', handleClose);
1855
- eventBus.on('feelPopup._open', handlePopupOpen);
1856
- eventBus.on('feelPopup._isOpen', handleIsOpen);
1857
- return () => {
1858
- eventBus.off('feelPopup._close', handleClose);
1859
- eventBus.off('feelPopup._open', handleOpen);
1860
- eventBus.off('feelPopup._isOpen', handleIsOpen);
1861
- };
1862
- }, [eventBus, isOpen]);
1863
- return o(FeelPopupContext.Provider, {
1864
- value: feelPopupContext,
1865
- children: [open && o(FeelPopupComponent, {
1866
- onClose: handleClose,
1867
- container: popupContainer,
1868
- sourceElement: sourceElement,
1869
- emit: emit,
1870
- ...popupConfig
1871
- }), props.children]
1872
- });
1873
- }
1874
- function FeelPopupComponent(props) {
1875
- const {
1876
- container,
1877
- id,
1878
- hostLanguage,
1879
- onInput,
1880
- onClose,
1881
- position,
1882
- singleLine,
1883
- sourceElement,
1884
- title,
1885
- tooltipContainer,
1886
- type,
1887
- value,
1888
- variables,
1889
- emit
1890
- } = props;
1891
- const editorRef = _$1();
1892
- const popupRef = _$1();
1893
- const isAutoCompletionOpen = _$1(false);
1894
- const handleSetReturnFocus = () => {
1895
- sourceElement && sourceElement.focus();
1896
- };
1897
- const onKeyDownCapture = event => {
1898
- // we use capture here to make sure we handle the event before the editor does
1899
- if (event.key === 'Escape') {
1900
- isAutoCompletionOpen.current = autoCompletionOpen(event.target);
1901
- }
1902
- };
1903
- const onKeyDown = event => {
1904
- if (event.key === 'Escape') {
1905
- // close popup only if auto completion is not open
1906
- // we need to do check this because the editor is not
1907
- // stop propagating the keydown event
1908
- // cf. https://discuss.codemirror.net/t/how-can-i-replace-the-default-autocompletion-keymap-v6/3322/5
1909
- if (!isAutoCompletionOpen.current) {
1910
- onClose();
1911
- isAutoCompletionOpen.current = false;
1912
- }
1913
- }
1914
- };
1915
- p(() => {
1916
- emit('opened', {
1917
- domNode: popupRef.current
1918
- });
1919
- return () => emit('close', {
1920
- domNode: popupRef.current
1921
- });
1922
- }, []);
1923
- return o(Popup, {
1924
- container: container,
1925
- className: "bio-properties-panel-feel-popup",
1926
- emit: emit,
1927
- position: position,
1928
- title: title,
1929
- onClose: onClose
1930
-
1931
- // handle focus manually on deactivate
1932
- ,
1933
- returnFocus: false,
1934
- closeOnEscape: false,
1935
- delayInitialFocus: false,
1936
- onPostDeactivate: handleSetReturnFocus,
1937
- height: FEEL_POPUP_HEIGHT,
1938
- width: FEEL_POPUP_WIDTH,
1939
- ref: popupRef,
1940
- children: [o(Popup.Title, {
1941
- title: title,
1942
- emit: emit,
1943
- draggable: true
1944
- }), o(Popup.Body, {
1945
- children: o("div", {
1946
- onKeyDownCapture: onKeyDownCapture,
1947
- onKeyDown: onKeyDown,
1948
- class: "bio-properties-panel-feel-popup__body",
1949
- children: [type === 'feel' && o(CodeEditor, {
1950
- enableGutters: true,
1951
- id: prefixId$8(id),
1952
- name: id,
1953
- onInput: onInput,
1954
- value: value,
1955
- variables: variables,
1956
- ref: editorRef,
1957
- tooltipContainer: tooltipContainer
1958
- }), type === 'feelers' && o(CodeEditor$1, {
1959
- id: prefixId$8(id),
1960
- contentAttributes: {
1961
- 'aria-label': title
1962
- },
1963
- enableGutters: true,
1964
- hostLanguage: hostLanguage,
1965
- name: id,
1966
- onInput: onInput,
1967
- value: value,
1968
- ref: editorRef,
1969
- singleLine: singleLine,
1970
- tooltipContainer: tooltipContainer
1971
- })]
1972
- })
1973
- }), o(Popup.Footer, {
1974
- children: o("button", {
1975
- onClick: onClose,
1976
- title: "Close pop-up editor",
1977
- class: "bio-properties-panel-feel-popup__close-btn",
1978
- children: "Close"
1979
- })
1980
- })]
1981
- });
1982
- }
1983
-
1984
- // helpers /////////////////
1985
-
1986
- function prefixId$8(id) {
1987
- return `bio-properties-panel-${id}`;
1988
- }
1989
- function autoCompletionOpen(element) {
1990
- return element.closest('.cm-editor').querySelector('.cm-tooltip-autocomplete');
1991
- }
1992
-
1993
- /**
1994
- * This hook behaves like useEffect, but does not trigger on the first render.
1995
- *
1996
- * @param {Function} effect
1997
- * @param {Array} deps
1998
- */
1999
- function useUpdateEffect(effect, deps) {
2000
- const isMounted = _$1(false);
2001
- p(() => {
2002
- if (isMounted.current) {
2003
- return effect();
2004
- } else {
2005
- isMounted.current = true;
2006
- }
2007
- }, deps);
2008
- }
2009
-
2010
- function ToggleSwitch(props) {
2011
- const {
2012
- id,
2013
- label,
2014
- onInput,
2015
- value,
2016
- switcherLabel,
2017
- inline,
2018
- onFocus,
2019
- onBlur,
2020
- inputRef,
2021
- tooltip
2022
- } = props;
2023
- const [localValue, setLocalValue] = h(value);
2024
- const handleInputCallback = async () => {
2025
- onInput(!value);
2026
- };
2027
- const handleInput = e => {
2028
- handleInputCallback();
2029
- setLocalValue(e.target.value);
2030
- };
2031
- p(() => {
2032
- if (value === localValue) {
2033
- return;
2034
- }
2035
- setLocalValue(value);
2036
- }, [value]);
2037
- return o("div", {
2038
- class: classnames('bio-properties-panel-toggle-switch', {
2039
- inline
2040
- }),
2041
- children: [o("label", {
2042
- class: "bio-properties-panel-label",
2043
- for: prefixId$7(id),
2044
- children: o(TooltipWrapper, {
2045
- value: tooltip,
2046
- forId: id,
2047
- element: props.element,
2048
- children: label
2049
- })
2050
- }), o("div", {
2051
- class: "bio-properties-panel-field-wrapper",
2052
- children: [o("label", {
2053
- class: "bio-properties-panel-toggle-switch__switcher",
2054
- children: [o("input", {
2055
- ref: inputRef,
2056
- id: prefixId$7(id),
2057
- class: "bio-properties-panel-input",
2058
- type: "checkbox",
2059
- onFocus: onFocus,
2060
- onBlur: onBlur,
2061
- name: id,
2062
- onInput: handleInput,
2063
- checked: !!localValue
2064
- }), o("span", {
2065
- class: "bio-properties-panel-toggle-switch__slider"
2066
- })]
2067
- }), switcherLabel && o("p", {
2068
- class: "bio-properties-panel-toggle-switch__label",
2069
- children: switcherLabel
2070
- })]
2071
- })]
2072
- });
2073
- }
2074
-
2075
- /**
2076
- * @param {Object} props
2077
- * @param {Object} props.element
2078
- * @param {String} props.id
2079
- * @param {String} props.description
2080
- * @param {String} props.label
2081
- * @param {String} props.switcherLabel
2082
- * @param {Boolean} props.inline
2083
- * @param {Function} props.getValue
2084
- * @param {Function} props.setValue
2085
- * @param {Function} props.onFocus
2086
- * @param {Function} props.onBlur
2087
- * @param {string|import('preact').Component} props.tooltip
2088
- */
2089
- function ToggleSwitchEntry(props) {
2090
- const {
2091
- element,
2092
- id,
2093
- description,
2094
- label,
2095
- switcherLabel,
2096
- inline,
2097
- getValue,
2098
- setValue,
2099
- onFocus,
2100
- onBlur,
2101
- tooltip
2102
- } = props;
2103
- const value = getValue(element);
2104
- return o("div", {
2105
- class: "bio-properties-panel-entry bio-properties-panel-toggle-switch-entry",
2106
- "data-entry-id": id,
2107
- children: [o(ToggleSwitch, {
2108
- id: id,
2109
- label: label,
2110
- value: value,
2111
- onInput: setValue,
2112
- onFocus: onFocus,
2113
- onBlur: onBlur,
2114
- switcherLabel: switcherLabel,
2115
- inline: inline,
2116
- tooltip: tooltip,
2117
- element: element
2118
- }), o(Description, {
2119
- forId: id,
2120
- element: element,
2121
- value: description
2122
- })]
2123
- });
2124
- }
2125
- function isEdited$8(node) {
2126
- return node && !!node.checked;
2127
- }
2128
-
2129
- // helpers /////////////////
2130
-
2131
- function prefixId$7(id) {
2132
- return `bio-properties-panel-${id}`;
2133
- }
2134
-
2135
- function NumberField(props) {
2136
- const {
2137
- debounce,
2138
- disabled,
2139
- displayLabel = true,
2140
- id,
2141
- inputRef,
2142
- label,
2143
- max,
2144
- min,
2145
- onInput,
2146
- step,
2147
- value = '',
2148
- onFocus,
2149
- onBlur
2150
- } = props;
2151
- const [localValue, setLocalValue] = h(value);
2152
- const handleInputCallback = F$1(() => {
2153
- return debounce(event => {
2154
- const {
2155
- validity,
2156
- value
2157
- } = event.target;
2158
- if (validity.valid) {
2159
- onInput(value ? parseFloat(value) : undefined);
2160
- }
2161
- });
2162
- }, [onInput, debounce]);
2163
- const handleInput = e => {
2164
- handleInputCallback(e);
2165
- setLocalValue(e.target.value);
2166
- };
2167
- p(() => {
2168
- if (value === localValue) {
2169
- return;
2170
- }
2171
- setLocalValue(value);
2172
- }, [value]);
2173
- return o("div", {
2174
- class: "bio-properties-panel-numberfield",
2175
- children: [displayLabel && o("label", {
2176
- for: prefixId$6(id),
2177
- class: "bio-properties-panel-label",
2178
- children: label
2179
- }), o("input", {
2180
- id: prefixId$6(id),
2181
- ref: inputRef,
2182
- type: "number",
2183
- name: id,
2184
- spellCheck: "false",
2185
- autoComplete: "off",
2186
- disabled: disabled,
2187
- class: "bio-properties-panel-input",
2188
- max: max,
2189
- min: min,
2190
- onInput: handleInput,
2191
- onFocus: onFocus,
2192
- onBlur: onBlur,
2193
- step: step,
2194
- value: localValue
2195
- })]
2196
- });
2197
- }
2198
-
2199
- /**
2200
- * @param {Object} props
2201
- * @param {Boolean} props.debounce
2202
- * @param {String} props.description
2203
- * @param {Boolean} props.disabled
2204
- * @param {Object} props.element
2205
- * @param {Function} props.getValue
2206
- * @param {String} props.id
2207
- * @param {String} props.label
2208
- * @param {String} props.max
2209
- * @param {String} props.min
2210
- * @param {Function} props.setValue
2211
- * @param {Function} props.onFocus
2212
- * @param {Function} props.onBlur
2213
- * @param {String} props.step
2214
- * @param {Function} props.validate
2215
- */
2216
- function NumberFieldEntry(props) {
2217
- const {
2218
- debounce,
2219
- description,
2220
- disabled,
2221
- element,
2222
- getValue,
2223
- id,
2224
- label,
2225
- max,
2226
- min,
2227
- setValue,
2228
- step,
2229
- onFocus,
2230
- onBlur,
2231
- validate
2232
- } = props;
2233
- const globalError = useError(id);
2234
- const [localError, setLocalError] = h(null);
2235
- let value = getValue(element);
2236
- p(() => {
2237
- if (isFunction(validate)) {
2238
- const newValidationError = validate(value) || null;
2239
- setLocalError(newValidationError);
2240
- }
2241
- }, [value]);
2242
- const onInput = newValue => {
2243
- let newValidationError = null;
2244
- if (isFunction(validate)) {
2245
- newValidationError = validate(newValue) || null;
2246
- }
2247
- setValue(newValue, newValidationError);
2248
- setLocalError(newValidationError);
2249
- };
2250
- const error = globalError || localError;
2251
- return o("div", {
2252
- class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
2253
- "data-entry-id": id,
2254
- children: [o(NumberField, {
2255
- debounce: debounce,
2256
- disabled: disabled,
2257
- id: id,
2258
- label: label,
2259
- onFocus: onFocus,
2260
- onBlur: onBlur,
2261
- onInput: onInput,
2262
- max: max,
2263
- min: min,
2264
- step: step,
2265
- value: value
2266
- }, element), error && o("div", {
2267
- class: "bio-properties-panel-error",
2268
- children: error
2269
- }), o(Description, {
2270
- forId: id,
2271
- element: element,
2272
- value: description
2273
- })]
2274
- });
2275
- }
2276
- function isEdited$7(node) {
2277
- return node && !!node.value;
2278
- }
2279
-
2280
- // helpers /////////////////
2281
-
2282
- function prefixId$6(id) {
2283
- return `bio-properties-panel-${id}`;
2284
- }
2285
-
2286
- const noop$2 = () => {};
2287
- function FeelTextfield(props) {
2288
- const {
2289
- debounce,
2290
- id,
2291
- element,
2292
- label,
2293
- hostLanguage,
2294
- onInput,
2295
- onError,
2296
- feel,
2297
- value = '',
2298
- disabled = false,
2299
- variables,
2300
- singleLine,
2301
- tooltipContainer,
2302
- OptionalComponent = OptionalFeelInput,
2303
- tooltip
2304
- } = props;
2305
- const [localValue, _setLocalValue] = h(value);
2306
- const editorRef = useShowEntryEvent(id);
2307
- const containerRef = _$1();
2308
- const feelActive = isString(localValue) && localValue.startsWith('=') || feel === 'required';
2309
- const feelOnlyValue = isString(localValue) && localValue.startsWith('=') ? localValue.substring(1) : localValue;
2310
- const [focus, _setFocus] = h(undefined);
2311
- const {
2312
- open: openPopup,
2313
- source: popupSource
2314
- } = q$1(FeelPopupContext);
2315
- const popuOpen = popupSource === id;
2316
- const setFocus = (offset = 0) => {
2317
- const hasFocus = containerRef.current.contains(document.activeElement);
2318
-
2319
- // Keep caret position if it is already focused, otherwise focus at the end
2320
- const position = hasFocus ? document.activeElement.selectionStart : Infinity;
2321
- _setFocus(position + offset);
2322
- };
2323
- const handleInputCallback = F$1(() => {
2324
- return debounce(newValue => {
2325
- onInput(newValue);
2326
- });
2327
- }, [onInput, debounce]);
2328
- const setLocalValue = newValue => {
2329
- _setLocalValue(newValue);
2330
- if (typeof newValue === 'undefined' || newValue === '' || newValue === '=') {
2331
- handleInputCallback(undefined);
2332
- } else {
2333
- handleInputCallback(newValue);
2334
- }
2335
- };
2336
- const handleFeelToggle = useStaticCallback(() => {
2337
- if (feel === 'required') {
2338
- return;
2339
- }
2340
- if (!feelActive) {
2341
- setLocalValue('=' + localValue);
2342
- } else {
2343
- setLocalValue(feelOnlyValue);
2344
- }
2345
- });
2346
- const handleLocalInput = newValue => {
2347
- if (feelActive) {
2348
- newValue = '=' + newValue;
2349
- }
2350
- if (newValue === localValue) {
2351
- return;
2352
- }
2353
- setLocalValue(newValue);
2354
- if (!feelActive && isString(newValue) && newValue.startsWith('=')) {
2355
- // focus is behind `=` sign that will be removed
2356
- setFocus(-1);
2357
- }
2358
- };
2359
- const handleLint = useStaticCallback(lint => {
2360
- if (!(lint && lint.length)) {
2361
- onError(undefined);
2362
- return;
2363
- }
2364
- const error = lint[0];
2365
- const message = `${error.source}: ${error.message}`;
2366
- onError(message);
2367
- });
2368
- const handlePopupOpen = (type = 'feel') => {
2369
- const popupOptions = {
2370
- id,
2371
- hostLanguage,
2372
- onInput: handleLocalInput,
2373
- position: calculatePopupPosition(containerRef.current),
2374
- singleLine,
2375
- title: getPopupTitle(element, label),
2376
- tooltipContainer,
2377
- type,
2378
- value: feelOnlyValue,
2379
- variables
2380
- };
2381
- openPopup(id, popupOptions, editorRef.current);
2382
- };
2383
- p(() => {
2384
- if (typeof focus !== 'undefined') {
2385
- editorRef.current.focus(focus);
2386
- _setFocus(undefined);
2387
- }
2388
- }, [focus]);
2389
- p(() => {
2390
- if (value === localValue) {
2391
- return;
2392
- }
2393
-
2394
- // External value change removed content => keep FEEL configuration
2395
- if (!value) {
2396
- setLocalValue(feelActive ? '=' : '');
2397
- return;
2398
- }
2399
- setLocalValue(value);
2400
- }, [value]);
2401
-
2402
- // copy-paste integration
2403
- p(() => {
2404
- const copyHandler = event => {
2405
- if (!feelActive) {
2406
- return;
2407
- }
2408
- event.clipboardData.setData('application/FEEL', event.clipboardData.getData('text'));
2409
- };
2410
- const pasteHandler = event => {
2411
- if (feelActive || popuOpen) {
2412
- return;
2413
- }
2414
- const data = event.clipboardData.getData('application/FEEL');
2415
- if (data) {
2416
- setTimeout(() => {
2417
- handleFeelToggle();
2418
- setFocus();
2419
- });
2420
- }
2421
- };
2422
- containerRef.current.addEventListener('copy', copyHandler);
2423
- containerRef.current.addEventListener('cut', copyHandler);
2424
- containerRef.current.addEventListener('paste', pasteHandler);
2425
- return () => {
2426
- containerRef.current.removeEventListener('copy', copyHandler);
2427
- containerRef.current.removeEventListener('cut', copyHandler);
2428
- containerRef.current.removeEventListener('paste', pasteHandler);
2429
- };
2430
- }, [containerRef, feelActive, handleFeelToggle, setFocus]);
2431
- return o("div", {
2432
- class: classnames('bio-properties-panel-feel-entry', {
2433
- 'feel-active': feelActive
2434
- }),
2435
- children: [o("label", {
2436
- for: prefixId$5(id),
2437
- class: "bio-properties-panel-label",
2438
- onClick: () => setFocus(),
2439
- children: [o(TooltipWrapper, {
2440
- value: tooltip,
2441
- forId: id,
2442
- element: props.element,
2443
- children: label
2444
- }), o(FeelIcon, {
2445
- label: label,
2446
- feel: feel,
2447
- onClick: handleFeelToggle,
2448
- active: feelActive
2449
- })]
2450
- }), o("div", {
2451
- class: "bio-properties-panel-feel-container",
2452
- ref: containerRef,
2453
- children: [o(FeelIndicator, {
2454
- active: feelActive,
2455
- disabled: feel !== 'optional' || disabled,
2456
- onClick: handleFeelToggle
2457
- }), feelActive ? o(CodeEditor, {
2458
- id: prefixId$5(id),
2459
- name: id,
2460
- onInput: handleLocalInput,
2461
- disabled: disabled,
2462
- popupOpen: popuOpen,
2463
- onFeelToggle: () => {
2464
- handleFeelToggle();
2465
- setFocus(true);
2466
- },
2467
- onLint: handleLint,
2468
- onPopupOpen: handlePopupOpen,
2469
- value: feelOnlyValue,
2470
- variables: variables,
2471
- ref: editorRef,
2472
- tooltipContainer: tooltipContainer
2473
- }) : o(OptionalComponent, {
2474
- ...props,
2475
- popupOpen: popuOpen,
2476
- onInput: handleLocalInput,
2477
- contentAttributes: {
2478
- 'id': prefixId$5(id),
2479
- 'aria-label': label
2480
- },
2481
- value: localValue,
2482
- ref: editorRef,
2483
- onPopupOpen: handlePopupOpen,
2484
- containerRef: containerRef
2485
- })]
2486
- })]
2487
- });
2488
- }
2489
- const OptionalFeelInput = k((props, ref) => {
2490
- const {
2491
- id,
2492
- disabled,
2493
- onInput,
2494
- value,
2495
- onFocus,
2496
- onBlur
2497
- } = props;
2498
- const inputRef = _$1();
2499
-
2500
- // To be consistent with the FEEL editor, set focus at start of input
2501
- // this ensures clean editing experience when switching with the keyboard
2502
- ref.current = {
2503
- focus: position => {
2504
- const input = inputRef.current;
2505
- if (!input) {
2506
- return;
2507
- }
2508
- input.focus();
2509
- if (typeof position === 'number') {
2510
- if (position > value.length) {
2511
- position = value.length;
2512
- }
2513
- input.setSelectionRange(position, position);
2514
- }
2515
- }
2516
- };
2517
- return o("input", {
2518
- id: prefixId$5(id),
2519
- type: "text",
2520
- ref: inputRef,
2521
- name: id,
2522
- spellCheck: "false",
2523
- autoComplete: "off",
2524
- disabled: disabled,
2525
- class: "bio-properties-panel-input",
2526
- onInput: e => onInput(e.target.value),
2527
- onFocus: onFocus,
2528
- onBlur: onBlur,
2529
- value: value || ''
2530
- });
2531
- });
2532
- const OptionalFeelNumberField = k((props, ref) => {
2533
- const {
2534
- id,
2535
- debounce,
2536
- disabled,
2537
- onInput,
2538
- value,
2539
- min,
2540
- max,
2541
- step,
2542
- onFocus,
2543
- onBlur
2544
- } = props;
2545
- const inputRef = _$1();
2546
-
2547
- // To be consistent with the FEEL editor, set focus at start of input
2548
- // this ensures clean editing experience when switching with the keyboard
2549
- ref.current = {
2550
- focus: position => {
2551
- const input = inputRef.current;
2552
- if (!input) {
2553
- return;
2554
- }
2555
- input.focus();
2556
- if (typeof position === 'number' && position !== Infinity) {
2557
- if (position > value.length) {
2558
- position = value.length;
2559
- }
2560
- input.setSelectionRange(position, position);
2561
- }
2562
- }
2563
- };
2564
- return o(NumberField, {
2565
- id: id,
2566
- debounce: debounce,
2567
- disabled: disabled,
2568
- displayLabel: false,
2569
- inputRef: inputRef,
2570
- max: max,
2571
- min: min,
2572
- onInput: onInput,
2573
- step: step,
2574
- value: value,
2575
- onFocus: onFocus,
2576
- onBlur: onBlur
2577
- });
2578
- });
2579
- const OptionalFeelTextArea = k((props, ref) => {
2580
- const {
2581
- id,
2582
- disabled,
2583
- onInput,
2584
- value,
2585
- onFocus,
2586
- onBlur
2587
- } = props;
2588
- const inputRef = _$1();
2589
-
2590
- // To be consistent with the FEEL editor, set focus at start of input
2591
- // this ensures clean editing experience when switching with the keyboard
2592
- ref.current = {
2593
- focus: () => {
2594
- const input = inputRef.current;
2595
- if (!input) {
2596
- return;
2597
- }
2598
- input.focus();
2599
- input.setSelectionRange(0, 0);
2600
- }
2601
- };
2602
- return o("textarea", {
2603
- id: prefixId$5(id),
2604
- type: "text",
2605
- ref: inputRef,
2606
- name: id,
2607
- spellCheck: "false",
2608
- autoComplete: "off",
2609
- disabled: disabled,
2610
- class: "bio-properties-panel-input",
2611
- onInput: e => onInput(e.target.value),
2612
- onFocus: onFocus,
2613
- onBlur: onBlur,
2614
- value: value || '',
2615
- "data-gramm": "false"
2616
- });
2617
- });
2618
- const OptionalFeelToggleSwitch = k((props, ref) => {
2619
- const {
2620
- id,
2621
- onInput,
2622
- value,
2623
- onFocus,
2624
- onBlur,
2625
- switcherLabel
2626
- } = props;
2627
- const inputRef = _$1();
2628
-
2629
- // To be consistent with the FEEL editor, set focus at start of input
2630
- // this ensures clean editing experience when switching with the keyboard
2631
- ref.current = {
2632
- focus: () => {
2633
- const input = inputRef.current;
2634
- if (!input) {
2635
- return;
2636
- }
2637
- input.focus();
2638
- }
2639
- };
2640
- return o(ToggleSwitch, {
2641
- id: id,
2642
- value: value,
2643
- inputRef: inputRef,
2644
- onInput: onInput,
2645
- onFocus: onFocus,
2646
- onBlur: onBlur,
2647
- switcherLabel: switcherLabel
2648
- });
2649
- });
2650
- const OptionalFeelCheckbox = k((props, ref) => {
2651
- const {
2652
- id,
2653
- disabled,
2654
- onInput,
2655
- value,
2656
- onFocus,
2657
- onBlur
2658
- } = props;
2659
- const inputRef = _$1();
2660
- const handleChange = ({
2661
- target
2662
- }) => {
2663
- onInput(target.checked);
2664
- };
2665
-
2666
- // To be consistent with the FEEL editor, set focus at start of input
2667
- // this ensures clean editing experience when switching with the keyboard
2668
- ref.current = {
2669
- focus: () => {
2670
- const input = inputRef.current;
2671
- if (!input) {
2672
- return;
2673
- }
2674
- input.focus();
2675
- }
2676
- };
2677
- return o("input", {
2678
- ref: inputRef,
2679
- id: prefixId$5(id),
2680
- name: id,
2681
- onFocus: onFocus,
2682
- onBlur: onBlur,
2683
- type: "checkbox",
2684
- class: "bio-properties-panel-input",
2685
- onChange: handleChange,
2686
- checked: value,
2687
- disabled: disabled
2688
- });
2689
- });
2690
-
2691
- /**
2692
- * @param {Object} props
2693
- * @param {Object} props.element
2694
- * @param {String} props.id
2695
- * @param {String} props.description
2696
- * @param {Boolean} props.debounce
2697
- * @param {Boolean} props.disabled
2698
- * @param {Boolean} props.feel
2699
- * @param {String} props.label
2700
- * @param {Function} props.getValue
2701
- * @param {Function} props.setValue
2702
- * @param {Function} props.tooltipContainer
2703
- * @param {Function} props.validate
2704
- * @param {Function} props.show
2705
- * @param {Function} props.example
2706
- * @param {Function} props.variables
2707
- * @param {Function} props.onFocus
2708
- * @param {Function} props.onBlur
2709
- * @param {string|import('preact').Component} props.tooltip
2710
- */
2711
- function FeelEntry(props) {
2712
- const {
2713
- element,
2714
- id,
2715
- description,
2716
- debounce,
2717
- disabled,
2718
- feel,
2719
- label,
2720
- getValue,
2721
- setValue,
2722
- tooltipContainer,
2723
- hostLanguage,
2724
- singleLine,
2725
- validate,
2726
- show = noop$2,
2727
- example,
2728
- variables,
2729
- onFocus,
2730
- onBlur,
2731
- tooltip
2732
- } = props;
2733
- const [validationError, setValidationError] = h(null);
2734
- const [localError, setLocalError] = h(null);
2735
- let value = getValue(element);
2736
- p(() => {
2737
- if (isFunction(validate)) {
2738
- const newValidationError = validate(value) || null;
2739
- setValidationError(newValidationError);
2740
- }
2741
- }, [value]);
2742
- const onInput = useStaticCallback(newValue => {
2743
- let newValidationError = null;
2744
- if (isFunction(validate)) {
2745
- newValidationError = validate(newValue) || null;
2746
- }
2747
-
2748
- // don't create multiple commandStack entries for the same value
2749
- if (newValue !== value) {
2750
- setValue(newValue, newValidationError);
2751
- }
2752
- setValidationError(newValidationError);
2753
- });
2754
- const onError = T$1(err => {
2755
- setLocalError(err);
2756
- }, []);
2757
- const temporaryError = useError(id);
2758
- const error = temporaryError || localError || validationError;
2759
- return o("div", {
2760
- class: classnames(props.class, 'bio-properties-panel-entry', error ? 'has-error' : ''),
2761
- "data-entry-id": id,
2762
- children: [createElement(FeelTextfield, {
2763
- ...props,
2764
- debounce: debounce,
2765
- disabled: disabled,
2766
- feel: feel,
2767
- id: id,
2768
- key: element,
2769
- label: label,
2770
- onInput: onInput,
2771
- onError: onError,
2772
- onFocus: onFocus,
2773
- onBlur: onBlur,
2774
- example: example,
2775
- hostLanguage: hostLanguage,
2776
- singleLine: singleLine,
2777
- show: show,
2778
- value: value,
2779
- variables: variables,
2780
- tooltipContainer: tooltipContainer,
2781
- OptionalComponent: props.OptionalComponent,
2782
- tooltip: tooltip
2783
- }), error && o("div", {
2784
- class: "bio-properties-panel-error",
2785
- children: error
2786
- }), o(Description, {
2787
- forId: id,
2788
- element: element,
2789
- value: description
2790
- })]
2791
- });
2792
- }
2793
-
2794
- /**
2795
- * @param {Object} props
2796
- * @param {Object} props.element
2797
- * @param {String} props.id
2798
- * @param {String} props.description
2799
- * @param {Boolean} props.debounce
2800
- * @param {Boolean} props.disabled
2801
- * @param {String} props.max
2802
- * @param {String} props.min
2803
- * @param {String} props.step
2804
- * @param {Boolean} props.feel
2805
- * @param {String} props.label
2806
- * @param {Function} props.getValue
2807
- * @param {Function} props.setValue
2808
- * @param {Function} props.tooltipContainer
2809
- * @param {Function} props.validate
2810
- * @param {Function} props.show
2811
- * @param {Function} props.example
2812
- * @param {Function} props.variables
2813
- * @param {Function} props.onFocus
2814
- * @param {Function} props.onBlur
2815
- */
2816
- function FeelNumberEntry(props) {
2817
- return o(FeelEntry, {
2818
- class: "bio-properties-panel-feel-number",
2819
- OptionalComponent: OptionalFeelNumberField,
2820
- ...props
2821
- });
2822
- }
2823
-
2824
- /**
2825
- * @param {Object} props
2826
- * @param {Object} props.element
2827
- * @param {String} props.id
2828
- * @param {String} props.description
2829
- * @param {Boolean} props.debounce
2830
- * @param {Boolean} props.disabled
2831
- * @param {Boolean} props.feel
2832
- * @param {String} props.label
2833
- * @param {Function} props.getValue
2834
- * @param {Function} props.setValue
2835
- * @param {Function} props.tooltipContainer
2836
- * @param {Function} props.validate
2837
- * @param {Function} props.show
2838
- * @param {Function} props.example
2839
- * @param {Function} props.variables
2840
- * @param {Function} props.onFocus
2841
- * @param {Function} props.onBlur
2842
- */
2843
- function FeelTextAreaEntry(props) {
2844
- return o(FeelEntry, {
2845
- class: "bio-properties-panel-feel-textarea",
2846
- OptionalComponent: OptionalFeelTextArea,
2847
- ...props
2848
- });
2849
- }
2850
-
2851
- /**
2852
- * @param {Object} props
2853
- * @param {Object} props.element
2854
- * @param {String} props.id
2855
- * @param {String} props.description
2856
- * @param {Boolean} props.debounce
2857
- * @param {Boolean} props.disabled
2858
- * @param {Boolean} props.feel
2859
- * @param {String} props.label
2860
- * @param {Function} props.getValue
2861
- * @param {Function} props.setValue
2862
- * @param {Function} props.tooltipContainer
2863
- * @param {Function} props.validate
2864
- * @param {Function} props.show
2865
- * @param {Function} props.example
2866
- * @param {Function} props.variables
2867
- * @param {Function} props.onFocus
2868
- * @param {Function} props.onBlur
2869
- */
2870
- function FeelToggleSwitchEntry(props) {
2871
- return o(FeelEntry, {
2872
- class: "bio-properties-panel-feel-toggle-switch",
2873
- OptionalComponent: OptionalFeelToggleSwitch,
2874
- ...props
2875
- });
2876
- }
2877
-
2878
- /**
2879
- * @param {Object} props
2880
- * @param {Object} props.element
2881
- * @param {String} props.id
2882
- * @param {String} props.description
2883
- * @param {Boolean} props.debounce
2884
- * @param {Boolean} props.disabled
2885
- * @param {Boolean} props.feel
2886
- * @param {String} props.label
2887
- * @param {Function} props.getValue
2888
- * @param {Function} props.setValue
2889
- * @param {Function} props.tooltipContainer
2890
- * @param {Function} props.validate
2891
- * @param {Function} props.show
2892
- * @param {Function} props.example
2893
- * @param {Function} props.variables
2894
- * @param {Function} props.onFocus
2895
- * @param {Function} props.onBlur
2896
- */
2897
- function FeelCheckboxEntry(props) {
2898
- return o(FeelEntry, {
2899
- class: "bio-properties-panel-feel-checkbox",
2900
- OptionalComponent: OptionalFeelCheckbox,
2901
- ...props
2902
- });
2903
- }
2904
-
2905
- /**
2906
- * @param {Object} props
2907
- * @param {Object} props.element
2908
- * @param {String} props.id
2909
- * @param {String} props.description
2910
- * @param {String} props.hostLanguage
2911
- * @param {Boolean} props.singleLine
2912
- * @param {Boolean} props.debounce
2913
- * @param {Boolean} props.disabled
2914
- * @param {Boolean} props.feel
2915
- * @param {String} props.label
2916
- * @param {Function} props.getValue
2917
- * @param {Function} props.setValue
2918
- * @param {Function} props.tooltipContainer
2919
- * @param {Function} props.validate
2920
- * @param {Function} props.show
2921
- * @param {Function} props.example
2922
- * @param {Function} props.variables
2923
- * @param {Function} props.onFocus
2924
- * @param {Function} props.onBlur
2925
- */
2926
- function FeelTemplatingEntry(props) {
2927
- return o(FeelEntry, {
2928
- class: "bio-properties-panel-feel-templating",
2929
- OptionalComponent: CodeEditor$1,
2930
- ...props
2931
- });
2932
- }
2933
- function isEdited$6(node) {
2934
- if (!node) {
2935
- return false;
2936
- }
2937
- if (node.type === 'checkbox') {
2938
- return !!node.checked || node.classList.contains('edited');
2939
- }
2940
- return !!node.value || node.classList.contains('edited');
2941
- }
2942
-
2943
- // helpers /////////////////
2944
-
2945
- function prefixId$5(id) {
2946
- return `bio-properties-panel-${id}`;
2947
- }
2948
- function calculatePopupPosition(element) {
2949
- const {
2950
- top,
2951
- left
2952
- } = element.getBoundingClientRect();
2953
- return {
2954
- left: left - FEEL_POPUP_WIDTH - 20,
2955
- top: top
2956
- };
2957
- }
2958
-
2959
- // todo(pinussilvestrus): make this configurable in the future
2960
- function getPopupTitle(element, label) {
2961
- let popupTitle = '';
2962
- if (element && element.type) {
2963
- popupTitle = `${element.type} / `;
2964
- }
2965
- return `${popupTitle}${label}`;
2966
- }
2967
-
2968
- const DEFAULT_LAYOUT = {};
2969
- const DEFAULT_DESCRIPTION = {};
2970
- const DEFAULT_TOOLTIP = {};
2971
-
2972
- /**
2973
- * @typedef { {
2974
- * component: import('preact').Component,
2975
- * id: String,
2976
- * isEdited?: Function
2977
- * } } EntryDefinition
2978
- *
2979
- * @typedef { {
2980
- * autoFocusEntry: String,
2981
- * autoOpen?: Boolean,
2982
- * entries: Array<EntryDefinition>,
2983
- * id: String,
2984
- * label: String,
2985
- * remove: (event: MouseEvent) => void
2986
- * } } ListItemDefinition
2987
- *
2988
- * @typedef { {
2989
- * add: (event: MouseEvent) => void,
2990
- * component: import('preact').Component,
2991
- * element: Object,
2992
- * id: String,
2993
- * items: Array<ListItemDefinition>,
2994
- * label: String,
2995
- * shouldSort?: Boolean,
2996
- * shouldOpen?: Boolean
2997
- * } } ListGroupDefinition
2998
- *
2999
- * @typedef { {
3000
- * component?: import('preact').Component,
3001
- * entries: Array<EntryDefinition>,
3002
- * id: String,
3003
- * label: String,
3004
- * shouldOpen?: Boolean
3005
- * } } GroupDefinition
3006
- *
3007
- * @typedef { {
3008
- * [id: String]: GetDescriptionFunction
3009
- * } } DescriptionConfig
3010
- *
3011
- * @typedef { {
3012
- * [id: String]: GetTooltipFunction
3013
- * } } TooltipConfig
3014
- *
3015
- * @callback { {
3016
- * @param {string} id
3017
- * @param {Object} element
3018
- * @returns {string}
3019
- * } } GetDescriptionFunction
3020
- *
3021
- * @callback { {
3022
- * @param {string} id
3023
- * @param {Object} element
3024
- * @returns {string}
3025
- * } } GetTooltipFunction
3026
- *
3027
- * @typedef { {
3028
- * getEmpty: (element: object) => import('./components/Placeholder').PlaceholderDefinition,
3029
- * getMultiple: (element: Object) => import('./components/Placeholder').PlaceholderDefinition
3030
- * } } PlaceholderProvider
3031
- *
3032
- */
3033
-
3034
- /**
3035
- * A basic properties panel component. Describes *how* content will be rendered, accepts
3036
- * data from implementor to describe *what* will be rendered.
3037
- *
3038
- * @param {Object} props
3039
- * @param {Object|Array} props.element
3040
- * @param {import('./components/Header').HeaderProvider} props.headerProvider
3041
- * @param {PlaceholderProvider} [props.placeholderProvider]
3042
- * @param {Array<GroupDefinition|ListGroupDefinition>} props.groups
3043
- * @param {Object} [props.layoutConfig]
3044
- * @param {Function} [props.layoutChanged]
3045
- * @param {DescriptionConfig} [props.descriptionConfig]
3046
- * @param {Function} [props.descriptionLoaded]
3047
- * @param {TooltipConfig} [props.tooltipConfig]
3048
- * @param {Function} [props.tooltipLoaded]
3049
- * @param {HTMLElement} [props.feelPopupContainer]
3050
- * @param {Object} [props.eventBus]
3051
- */
3052
- function PropertiesPanel(props) {
3053
- const {
3054
- element,
3055
- headerProvider,
3056
- placeholderProvider,
3057
- groups,
3058
- layoutConfig,
3059
- layoutChanged,
3060
- descriptionConfig,
3061
- descriptionLoaded,
3062
- tooltipConfig,
3063
- tooltipLoaded,
3064
- feelPopupContainer,
3065
- eventBus
3066
- } = props;
3067
-
3068
- // set-up layout context
3069
- const [layout, setLayout] = h(createLayout(layoutConfig));
3070
-
3071
- // react to external changes in the layout config
3072
- useUpdateLayoutEffect(() => {
3073
- const newLayout = createLayout(layoutConfig);
3074
- setLayout(newLayout);
3075
- }, [layoutConfig]);
3076
- p(() => {
3077
- if (typeof layoutChanged === 'function') {
3078
- layoutChanged(layout);
3079
- }
3080
- }, [layout, layoutChanged]);
3081
- const getLayoutForKey = (key, defaultValue) => {
3082
- return get(layout, key, defaultValue);
3083
- };
3084
- const setLayoutForKey = (key, config) => {
3085
- const newLayout = assign({}, layout);
3086
- set(newLayout, key, config);
3087
- setLayout(newLayout);
3088
- };
3089
- const layoutContext = {
3090
- layout,
3091
- setLayout,
3092
- getLayoutForKey,
3093
- setLayoutForKey
3094
- };
3095
-
3096
- // set-up description context
3097
- const description = F$1(() => createDescriptionContext(descriptionConfig), [descriptionConfig]);
3098
- p(() => {
3099
- if (typeof descriptionLoaded === 'function') {
3100
- descriptionLoaded(description);
3101
- }
3102
- }, [description, descriptionLoaded]);
3103
- const getDescriptionForId = (id, element) => {
3104
- return description[id] && description[id](element);
3105
- };
3106
- const descriptionContext = {
3107
- description,
3108
- getDescriptionForId
3109
- };
3110
-
3111
- // set-up tooltip context
3112
- const tooltip = F$1(() => createTooltipContext(tooltipConfig), [tooltipConfig]);
3113
- p(() => {
3114
- if (typeof tooltipLoaded === 'function') {
3115
- tooltipLoaded(tooltip);
3116
- }
3117
- }, [tooltip, tooltipLoaded]);
3118
- const getTooltipForId = (id, element) => {
3119
- return tooltip[id] && tooltip[id](element);
3120
- };
3121
- const tooltipContext = {
3122
- tooltip,
3123
- getTooltipForId
3124
- };
3125
- const [errors, setErrors] = h({});
3126
- const onSetErrors = ({
3127
- errors
3128
- }) => setErrors(errors);
3129
- useEvent('propertiesPanel.setErrors', onSetErrors, eventBus);
3130
- const errorsContext = {
3131
- errors
3132
- };
3133
- const eventContext = {
3134
- eventBus
3135
- };
3136
- const propertiesPanelContext = {
3137
- element
3138
- };
3139
-
3140
- // empty state
3141
- if (placeholderProvider && !element) {
3142
- return o(Placeholder, {
3143
- ...placeholderProvider.getEmpty()
3144
- });
3145
- }
3146
-
3147
- // multiple state
3148
- if (placeholderProvider && isArray(element)) {
3149
- return o(Placeholder, {
3150
- ...placeholderProvider.getMultiple()
3151
- });
3152
- }
3153
- return o(LayoutContext.Provider, {
3154
- value: propertiesPanelContext,
3155
- children: o(ErrorsContext.Provider, {
3156
- value: errorsContext,
3157
- children: o(DescriptionContext.Provider, {
3158
- value: descriptionContext,
3159
- children: o(TooltipContext.Provider, {
3160
- value: tooltipContext,
3161
- children: o(LayoutContext.Provider, {
3162
- value: layoutContext,
3163
- children: o(EventContext.Provider, {
3164
- value: eventContext,
3165
- children: o(FEELPopupRoot, {
3166
- element: element,
3167
- eventBus: eventBus,
3168
- popupContainer: feelPopupContainer,
3169
- children: o("div", {
3170
- class: "bio-properties-panel",
3171
- children: [o(Header, {
3172
- element: element,
3173
- headerProvider: headerProvider
3174
- }), o("div", {
3175
- class: "bio-properties-panel-scroll-container",
3176
- children: groups.map(group => {
3177
- const {
3178
- component: Component = Group,
3179
- id
3180
- } = group;
3181
- return createElement(Component, {
3182
- ...group,
3183
- key: id,
3184
- element: element
3185
- });
3186
- })
3187
- })]
3188
- })
3189
- })
3190
- })
3191
- })
3192
- })
3193
- })
3194
- })
3195
- });
3196
- }
3197
-
3198
- // helpers //////////////////
3199
-
3200
- function createLayout(overrides = {}, defaults = DEFAULT_LAYOUT) {
3201
- return {
3202
- ...defaults,
3203
- ...overrides
3204
- };
3205
- }
3206
- function createDescriptionContext(overrides = {}) {
3207
- return {
3208
- ...DEFAULT_DESCRIPTION,
3209
- ...overrides
3210
- };
3211
- }
3212
- function createTooltipContext(overrides = {}) {
3213
- return {
3214
- ...DEFAULT_TOOLTIP,
3215
- ...overrides
3216
- };
3217
- }
3218
-
3219
- // hooks //////////////////
3220
-
3221
- /**
3222
- * This hook behaves like useLayoutEffect, but does not trigger on the first render.
3223
- *
3224
- * @param {Function} effect
3225
- * @param {Array} deps
3226
- */
3227
- function useUpdateLayoutEffect(effect, deps) {
3228
- const isMounted = _$1(false);
3229
- y(() => {
3230
- if (isMounted.current) {
3231
- return effect();
3232
- } else {
3233
- isMounted.current = true;
3234
- }
3235
- }, deps);
3236
- }
3237
-
3238
- function DropdownButton(props) {
3239
- const {
3240
- class: className,
3241
- children,
3242
- menuItems = []
3243
- } = props;
3244
- const dropdownRef = _$1(null);
3245
- const menuRef = _$1(null);
3246
- const [open, setOpen] = h(false);
3247
- const close = () => setOpen(false);
3248
- function onDropdownToggle(event) {
3249
- if (menuRef.current && menuRef.current.contains(event.target)) {
3250
- return;
3251
- }
3252
- event.stopPropagation();
3253
- setOpen(open => !open);
3254
- }
3255
- function onActionClick(event, action) {
3256
- event.stopPropagation();
3257
- close();
3258
- action();
3259
- }
3260
- useGlobalClick([dropdownRef.current], () => close());
3261
- return o("div", {
3262
- class: classnames('bio-properties-panel-dropdown-button', {
3263
- open
3264
- }, className),
3265
- onClick: onDropdownToggle,
3266
- ref: dropdownRef,
3267
- children: [children, o("div", {
3268
- class: "bio-properties-panel-dropdown-button__menu",
3269
- ref: menuRef,
3270
- children: menuItems.map((item, index) => o(MenuItem, {
3271
- onClick: onActionClick,
3272
- item: item
3273
- }, index))
3274
- })]
3275
- });
3276
- }
3277
- function MenuItem({
3278
- item,
3279
- onClick
3280
- }) {
3281
- if (item.separator) {
3282
- return o("div", {
3283
- class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--separator"
3284
- });
3285
- }
3286
- if (item.action) {
3287
- return o("button", {
3288
- class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--actionable",
3289
- onClick: event => onClick(event, item.action),
3290
- children: item.entry
3291
- });
3292
- }
3293
- return o("div", {
3294
- class: "bio-properties-panel-dropdown-button__menu-item",
3295
- children: item.entry
3296
- });
3297
- }
3298
-
3299
- /**
3300
- *
3301
- * @param {Array<null | Element>} ignoredElements
3302
- * @param {Function} callback
3303
- */
3304
- function useGlobalClick(ignoredElements, callback) {
3305
- p(() => {
3306
- /**
3307
- * @param {MouseEvent} event
3308
- */
3309
- function listener(event) {
3310
- if (ignoredElements.some(element => element && element.contains(event.target))) {
3311
- return;
3312
- }
3313
- callback();
3314
- }
3315
- document.addEventListener('click', listener, {
3316
- capture: true
3317
- });
3318
- return () => document.removeEventListener('click', listener, {
3319
- capture: true
3320
- });
3321
- }, [...ignoredElements, callback]);
3322
- }
3323
-
3324
- function HeaderButton(props) {
3325
- const {
3326
- children = null,
3327
- class: classname,
3328
- onClick = () => {},
3329
- ...otherProps
3330
- } = props;
3331
- return o("button", {
3332
- ...otherProps,
3333
- onClick: onClick,
3334
- class: classnames('bio-properties-panel-group-header-button', classname),
3335
- children: children
3336
- });
3337
- }
3338
-
3339
- function CollapsibleEntry(props) {
3340
- const {
3341
- element,
3342
- entries = [],
3343
- id,
3344
- label,
3345
- open: shouldOpen,
3346
- remove
3347
- } = props;
3348
- const [open, setOpen] = h(shouldOpen);
3349
- const toggleOpen = () => setOpen(!open);
3350
- const {
3351
- onShow
3352
- } = q$1(LayoutContext);
3353
- const propertiesPanelContext = {
3354
- ...q$1(LayoutContext),
3355
- onShow: T$1(() => {
3356
- setOpen(true);
3357
- if (isFunction(onShow)) {
3358
- onShow();
3359
- }
3360
- }, [onShow, setOpen])
3361
- };
3362
-
3363
- // todo(pinussilvestrus): translate once we have a translate mechanism for the core
3364
- const placeholderLabel = '<empty>';
3365
- return o("div", {
3366
- "data-entry-id": id,
3367
- class: classnames('bio-properties-panel-collapsible-entry', open ? 'open' : ''),
3368
- children: [o("div", {
3369
- class: "bio-properties-panel-collapsible-entry-header",
3370
- onClick: toggleOpen,
3371
- children: [o("div", {
3372
- title: label || placeholderLabel,
3373
- class: classnames('bio-properties-panel-collapsible-entry-header-title', !label && 'empty'),
3374
- children: label || placeholderLabel
3375
- }), o("button", {
3376
- title: "Toggle list item",
3377
- class: "bio-properties-panel-arrow bio-properties-panel-collapsible-entry-arrow",
3378
- children: o(ArrowIcon, {
3379
- class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
3380
- })
3381
- }), remove ? o("button", {
3382
- title: "Delete item",
3383
- class: "bio-properties-panel-remove-entry",
3384
- onClick: remove,
3385
- children: o(DeleteIcon, {})
3386
- }) : null]
3387
- }), o("div", {
3388
- class: classnames('bio-properties-panel-collapsible-entry-entries', open ? 'open' : ''),
3389
- children: o(LayoutContext.Provider, {
3390
- value: propertiesPanelContext,
3391
- children: entries.map(entry => {
3392
- const {
3393
- component: Component,
3394
- id
3395
- } = entry;
3396
- return createElement(Component, {
3397
- ...entry,
3398
- element: element,
3399
- key: id
3400
- });
3401
- })
3402
- })
3403
- })]
3404
- });
3405
- }
3406
-
3407
- function ListItem(props) {
3408
- const {
3409
- autoFocusEntry,
3410
- autoOpen
3411
- } = props;
3412
-
3413
- // focus specified entry on auto open
3414
- p(() => {
3415
- if (autoOpen && autoFocusEntry) {
3416
- const entry = query(`[data-entry-id="${autoFocusEntry}"]`);
3417
- const focusableInput = query('.bio-properties-panel-input', entry);
3418
- if (focusableInput) {
3419
- if (isFunction(focusableInput.select)) {
3420
- focusableInput.select();
3421
- } else if (isFunction(focusableInput.focus)) {
3422
- focusableInput.focus();
3423
- }
3424
- }
3425
- }
3426
- }, [autoOpen, autoFocusEntry]);
3427
- return o("div", {
3428
- class: "bio-properties-panel-list-item",
3429
- children: o(CollapsibleEntry, {
3430
- ...props,
3431
- open: autoOpen
3432
- })
3433
- });
3434
- }
3435
-
3436
- const noop$1 = () => {};
3437
-
3438
- /**
3439
- * @param {import('../PropertiesPanel').ListGroupDefinition} props
3440
- */
3441
- function ListGroup(props) {
3442
- const {
3443
- add,
3444
- element,
3445
- id,
3446
- items,
3447
- label,
3448
- shouldOpen = true,
3449
- shouldSort = true
3450
- } = props;
3451
- const groupRef = _$1(null);
3452
- const [open, setOpen] = useLayoutState(['groups', id, 'open'], false);
3453
- const [sticky, setSticky] = h(false);
3454
- const onShow = T$1(() => setOpen(true), [setOpen]);
3455
- const [ordering, setOrdering] = h([]);
3456
- const [newItemAdded, setNewItemAdded] = h(false);
3457
-
3458
- // Flag to mark that add button was clicked in the last render cycle
3459
- const [addTriggered, setAddTriggered] = h(false);
3460
- const prevItems = usePrevious(items);
3461
- const prevElement = usePrevious(element);
3462
- const elementChanged = element !== prevElement;
3463
- const shouldHandleEffects = !elementChanged && (shouldSort || shouldOpen);
3464
-
3465
- // reset initial ordering when element changes (before first render)
3466
- if (elementChanged) {
3467
- setOrdering(createOrdering(shouldSort ? sortItems(items) : items));
3468
- }
3469
-
3470
- // keep ordering in sync to items - and open changes
3471
-
3472
- // (0) set initial ordering from given items
3473
- p(() => {
3474
- if (!prevItems || !shouldSort) {
3475
- setOrdering(createOrdering(items));
3476
- }
3477
- }, [items, element]);
3478
-
3479
- // (1) items were added
3480
- p(() => {
3481
- // reset addTriggered flag
3482
- setAddTriggered(false);
3483
- if (shouldHandleEffects && prevItems && items.length > prevItems.length) {
3484
- let add = [];
3485
- items.forEach(item => {
3486
- if (!ordering.includes(item.id)) {
3487
- add.push(item.id);
3488
- }
3489
- });
3490
- let newOrdering = ordering;
3491
-
3492
- // open if not open, configured and triggered by add button
3493
- //
3494
- // TODO(marstamm): remove once we refactor layout handling for listGroups.
3495
- // Ideally, opening should be handled as part of the `add` callback and
3496
- // not be a concern for the ListGroup component.
3497
- if (addTriggered && !open && shouldOpen) {
3498
- toggleOpen();
3499
- }
3500
-
3501
- // filter when not open and configured
3502
- if (!open && shouldSort) {
3503
- newOrdering = createOrdering(sortItems(items));
3504
- }
3505
-
3506
- // add new items on top or bottom depending on sorting behavior
3507
- newOrdering = newOrdering.filter(item => !add.includes(item));
3508
- if (shouldSort) {
3509
- newOrdering.unshift(...add);
3510
- } else {
3511
- newOrdering.push(...add);
3512
- }
3513
- setOrdering(newOrdering);
3514
- setNewItemAdded(addTriggered);
3515
- } else {
3516
- setNewItemAdded(false);
3517
- }
3518
- }, [items, open, shouldHandleEffects, addTriggered]);
3519
-
3520
- // (2) sort items on open if shouldSort is set
3521
- p(() => {
3522
- if (shouldSort && open && !newItemAdded) {
3523
- setOrdering(createOrdering(sortItems(items)));
3524
- }
3525
- }, [open, shouldSort]);
3526
-
3527
- // (3) items were deleted
3528
- p(() => {
3529
- if (shouldHandleEffects && prevItems && items.length < prevItems.length) {
3530
- let keep = [];
3531
- ordering.forEach(o => {
3532
- if (getItem(items, o)) {
3533
- keep.push(o);
3534
- }
3535
- });
3536
- setOrdering(keep);
3537
- }
3538
- }, [items, shouldHandleEffects]);
3539
-
3540
- // set css class when group is sticky to top
3541
- useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky);
3542
- const toggleOpen = () => setOpen(!open);
3543
- const hasItems = !!items.length;
3544
- const propertiesPanelContext = {
3545
- ...q$1(LayoutContext),
3546
- onShow
3547
- };
3548
- const handleAddClick = e => {
3549
- setAddTriggered(true);
3550
- add(e);
3551
- };
3552
- const allErrors = useErrors();
3553
- const hasError = items.some(item => {
3554
- if (allErrors[item.id]) {
3555
- return true;
3556
- }
3557
- if (!item.entries) {
3558
- return;
3559
- }
3560
-
3561
- // also check if the error is nested, e.g. for name-value entries
3562
- return item.entries.some(entry => allErrors[entry.id]);
3563
- });
3564
- return o("div", {
3565
- class: "bio-properties-panel-group",
3566
- "data-group-id": 'group-' + id,
3567
- ref: groupRef,
3568
- children: [o("div", {
3569
- class: classnames('bio-properties-panel-group-header', hasItems ? '' : 'empty', hasItems && open ? 'open' : '', sticky && open ? 'sticky' : ''),
3570
- onClick: hasItems ? toggleOpen : noop$1,
3571
- children: [o("div", {
3572
- title: props.tooltip ? null : label,
3573
- "data-title": label,
3574
- class: "bio-properties-panel-group-header-title",
3575
- children: o(TooltipWrapper, {
3576
- value: props.tooltip,
3577
- forId: 'group-' + id,
3578
- element: element,
3579
- parent: groupRef,
3580
- children: label
3581
- })
3582
- }), o("div", {
3583
- class: "bio-properties-panel-group-header-buttons",
3584
- children: [add ? o("button", {
3585
- title: "Create new list item",
3586
- class: "bio-properties-panel-group-header-button bio-properties-panel-add-entry",
3587
- onClick: handleAddClick,
3588
- children: [o(CreateIcon, {}), !hasItems ? o("span", {
3589
- class: "bio-properties-panel-add-entry-label",
3590
- children: "Create"
3591
- }) : null]
3592
- }) : null, hasItems ? o("div", {
3593
- title: `List contains ${items.length} item${items.length != 1 ? 's' : ''}`,
3594
- class: classnames('bio-properties-panel-list-badge', hasError ? 'bio-properties-panel-list-badge--error' : ''),
3595
- children: items.length
3596
- }) : null, hasItems ? o("button", {
3597
- title: "Toggle section",
3598
- class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
3599
- children: o(ArrowIcon, {
3600
- class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
3601
- })
3602
- }) : null]
3603
- })]
3604
- }), o("div", {
3605
- class: classnames('bio-properties-panel-list', open && hasItems ? 'open' : ''),
3606
- children: o(LayoutContext.Provider, {
3607
- value: propertiesPanelContext,
3608
- children: ordering.map((o, index) => {
3609
- const item = getItem(items, o);
3610
- if (!item) {
3611
- return;
3612
- }
3613
- const {
3614
- id
3615
- } = item;
3616
-
3617
- // if item was added, open it
3618
- // Existing items will not be affected as autoOpen is only applied on first render
3619
- const autoOpen = newItemAdded;
3620
- return createElement(ListItem, {
3621
- ...item,
3622
- autoOpen: autoOpen,
3623
- element: element,
3624
- index: index,
3625
- key: id
3626
- });
3627
- })
3628
- })
3629
- })]
3630
- });
3631
- }
3632
-
3633
- // helpers ////////////////////
3634
-
3635
- /**
3636
- * Sorts given items alphanumeric by label
3637
- */
3638
- function sortItems(items) {
3639
- return sortBy(items, i => i.label.toLowerCase());
3640
- }
3641
- function getItem(items, id) {
3642
- return find(items, i => i.id === id);
3643
- }
3644
- function createOrdering(items) {
3645
- return items.map(i => i.id);
3646
- }
3647
-
3648
- function Checkbox(props) {
3649
- const {
3650
- id,
3651
- label,
3652
- onChange,
3653
- disabled,
3654
- value = false,
3655
- onFocus,
3656
- onBlur,
3657
- tooltip
3658
- } = props;
3659
- const [localValue, setLocalValue] = h(value);
3660
- const handleChangeCallback = ({
3661
- target
3662
- }) => {
3663
- onChange(target.checked);
3664
- };
3665
- const handleChange = e => {
3666
- handleChangeCallback(e);
3667
- setLocalValue(e.target.value);
3668
- };
3669
- p(() => {
3670
- if (value === localValue) {
3671
- return;
3672
- }
3673
- setLocalValue(value);
3674
- }, [value]);
3675
- const ref = useShowEntryEvent(id);
3676
- return o("div", {
3677
- class: "bio-properties-panel-checkbox",
3678
- children: [o("input", {
3679
- ref: ref,
3680
- id: prefixId$4(id),
3681
- name: id,
3682
- onFocus: onFocus,
3683
- onBlur: onBlur,
3684
- type: "checkbox",
3685
- class: "bio-properties-panel-input",
3686
- onChange: handleChange,
3687
- checked: localValue,
3688
- disabled: disabled
3689
- }), o("label", {
3690
- for: prefixId$4(id),
3691
- class: "bio-properties-panel-label",
3692
- children: o(TooltipWrapper, {
3693
- value: tooltip,
3694
- forId: id,
3695
- element: props.element,
3696
- children: label
3697
- })
3698
- })]
3699
- });
3700
- }
3701
-
3702
- /**
3703
- * @param {Object} props
3704
- * @param {Object} props.element
3705
- * @param {String} props.id
3706
- * @param {String} props.description
3707
- * @param {String} props.label
3708
- * @param {Function} props.getValue
3709
- * @param {Function} props.setValue
3710
- * @param {Function} props.onFocus
3711
- * @param {Function} props.onBlur
3712
- * @param {string|import('preact').Component} props.tooltip
3713
- * @param {boolean} [props.disabled]
3714
- */
3715
- function CheckboxEntry(props) {
3716
- const {
3717
- element,
3718
- id,
3719
- description,
3720
- label,
3721
- getValue,
3722
- setValue,
3723
- disabled,
3724
- onFocus,
3725
- onBlur,
3726
- tooltip
3727
- } = props;
3728
- const value = getValue(element);
3729
- const error = useError(id);
3730
- return o("div", {
3731
- class: "bio-properties-panel-entry bio-properties-panel-checkbox-entry",
3732
- "data-entry-id": id,
3733
- children: [o(Checkbox, {
3734
- disabled: disabled,
3735
- id: id,
3736
- label: label,
3737
- onChange: setValue,
3738
- onFocus: onFocus,
3739
- onBlur: onBlur,
3740
- value: value,
3741
- tooltip: tooltip,
3742
- element: element
3743
- }, element), error && o("div", {
3744
- class: "bio-properties-panel-error",
3745
- children: error
3746
- }), o(Description, {
3747
- forId: id,
3748
- element: element,
3749
- value: description
3750
- })]
3751
- });
3752
- }
3753
- function isEdited$5(node) {
3754
- return node && !!node.checked;
3755
- }
3756
-
3757
- // helpers /////////////////
3758
-
3759
- function prefixId$4(id) {
3760
- return `bio-properties-panel-${id}`;
3761
- }
3762
-
3763
- const noop = () => {};
3764
-
3765
- /**
3766
- * @param {Object} props
3767
- * @param {Object} props.element
3768
- * @param {String} props.id
3769
- * @param {String} props.description
3770
- * @param {Boolean} props.debounce
3771
- * @param {Boolean} props.disabled
3772
- * @param {String} props.label
3773
- * @param {Function} props.getValue
3774
- * @param {Function} props.setValue
3775
- * @param {Function} props.tooltipContainer
3776
- * @param {Function} props.validate
3777
- * @param {Function} props.show
3778
- */
3779
- function TemplatingEntry(props) {
3780
- const {
3781
- element,
3782
- id,
3783
- description,
3784
- debounce,
3785
- disabled,
3786
- label,
3787
- getValue,
3788
- setValue,
3789
- tooltipContainer,
3790
- validate,
3791
- show = noop
3792
- } = props;
3793
- const [validationError, setValidationError] = h(null);
3794
- const [localError, setLocalError] = h(null);
3795
- let value = getValue(element);
3796
- p(() => {
3797
- if (isFunction(validate)) {
3798
- const newValidationError = validate(value) || null;
3799
- setValidationError(newValidationError);
3800
- }
3801
- }, [value]);
3802
- const onInput = useStaticCallback(newValue => {
3803
- let newValidationError = null;
3804
- if (isFunction(validate)) {
3805
- newValidationError = validate(newValue) || null;
3806
- }
3807
-
3808
- // don't create multiple commandStack entries for the same value
3809
- if (newValue !== value) {
3810
- setValue(newValue, newValidationError);
3811
- }
3812
- setValidationError(newValidationError);
3813
- });
3814
- const onError = T$1(err => {
3815
- setLocalError(err);
3816
- }, []);
3817
- const temporaryError = useError(id);
3818
- const error = localError || temporaryError || validationError;
3819
- return o("div", {
3820
- class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
3821
- "data-entry-id": id,
3822
- children: [o(Templating, {
3823
- debounce: debounce,
3824
- disabled: disabled,
3825
- id: id,
3826
- label: label,
3827
- onInput: onInput,
3828
- onError: onError,
3829
- show: show,
3830
- value: value,
3831
- tooltipContainer: tooltipContainer
3832
- }, element), error && o("div", {
3833
- class: "bio-properties-panel-error",
3834
- children: error
3835
- }), o(Description, {
3836
- forId: id,
3837
- element: element,
3838
- value: description
3839
- })]
3840
- });
3841
- }
3842
- function Templating(props) {
3843
- const {
3844
- debounce,
3845
- id,
3846
- label,
3847
- onInput,
3848
- onError,
3849
- value = '',
3850
- disabled = false,
3851
- tooltipContainer
3852
- } = props;
3853
- const [localValue, setLocalValue] = h(value);
3854
- const editorRef = useShowEntryEvent(id);
3855
- const containerRef = _$1();
3856
- const [focus, _setFocus] = h(undefined);
3857
- const setFocus = (offset = 0) => {
3858
- const hasFocus = containerRef.current.contains(document.activeElement);
3859
-
3860
- // Keep caret position if it is already focused, otherwise focus at the end
3861
- const position = hasFocus ? document.activeElement.selectionStart : Infinity;
3862
- _setFocus(position + offset);
3863
- };
3864
- const handleInputCallback = F$1(() => {
3865
- return debounce(newValue => onInput(newValue.length ? newValue : undefined));
3866
- }, [onInput, debounce]);
3867
- const handleInput = newValue => {
3868
- handleInputCallback(newValue);
3869
- setLocalValue(newValue);
3870
- };
3871
- const handleLint = useStaticCallback(lint => {
3872
- const errors = lint && lint.length && lint.filter(e => e.severity === 'error') || [];
3873
- if (!errors.length) {
3874
- onError(undefined);
3875
- return;
3876
- }
3877
- const error = lint[0];
3878
- const message = `${error.source}: ${error.message}`;
3879
- onError(message);
3880
- });
3881
- p(() => {
3882
- if (typeof focus !== 'undefined') {
3883
- editorRef.current.focus(focus);
3884
- _setFocus(undefined);
3885
- }
3886
- }, [focus]);
3887
- p(() => {
3888
- if (value === localValue) {
3889
- return;
3890
- }
3891
- setLocalValue(value ? value : '');
3892
- }, [value]);
3893
- return o("div", {
3894
- class: "bio-properties-panel-feelers",
3895
- children: [o("label", {
3896
- id: prefixIdLabel(id),
3897
- class: "bio-properties-panel-label",
3898
- onClick: () => setFocus(),
3899
- children: label
3900
- }), o("div", {
3901
- class: "bio-properties-panel-feelers-input",
3902
- ref: containerRef,
3903
- children: o(CodeEditor$1, {
3904
- name: id,
3905
- onInput: handleInput,
3906
- contentAttributes: {
3907
- 'aria-labelledby': prefixIdLabel(id)
3908
- },
3909
- disabled: disabled,
3910
- onLint: handleLint,
3911
- value: localValue,
3912
- ref: editorRef,
3913
- tooltipContainer: tooltipContainer
3914
- })
3915
- })]
3916
- });
3917
- }
3918
- function isEdited$4(node) {
3919
- return node && (!!node.value || node.classList.contains('edited'));
3920
- }
3921
-
3922
- // helpers /////////////////
3923
-
3924
- function prefixIdLabel(id) {
3925
- return `bio-properties-panel-feelers-${id}-label`;
3926
- }
3927
-
3928
- function List(props) {
3929
- const {
3930
- id,
3931
- element,
3932
- items = [],
3933
- component,
3934
- label = '<empty>',
3935
- open: shouldOpen,
3936
- onAdd,
3937
- onRemove,
3938
- autoFocusEntry,
3939
- compareFn,
3940
- ...restProps
3941
- } = props;
3942
- const [open, setOpen] = h(!!shouldOpen);
3943
- const hasItems = !!items.length;
3944
- const toggleOpen = () => hasItems && setOpen(!open);
3945
- const opening = !usePrevious(open) && open;
3946
- const elementChanged = usePrevious(element) !== element;
3947
- const shouldReset = opening || elementChanged;
3948
- const sortedItems = useSortedItems(items, compareFn, shouldReset);
3949
- const newItems = useNewItems(items, elementChanged);
3950
- p(() => {
3951
- if (open && !hasItems) {
3952
- setOpen(false);
3953
- }
3954
- }, [open, hasItems]);
3955
-
3956
- /**
3957
- * @param {MouseEvent} event
3958
- */
3959
- function addItem(event) {
3960
- event.stopPropagation();
3961
- onAdd();
3962
- if (!open) {
3963
- setOpen(true);
3964
- }
3965
- }
3966
- return o("div", {
3967
- "data-entry-id": id,
3968
- class: classnames('bio-properties-panel-entry', 'bio-properties-panel-list-entry', hasItems ? '' : 'empty', open ? 'open' : ''),
3969
- children: [o("div", {
3970
- class: "bio-properties-panel-list-entry-header",
3971
- onClick: toggleOpen,
3972
- children: [o("div", {
3973
- title: label,
3974
- class: classnames('bio-properties-panel-list-entry-header-title', open && 'open'),
3975
- children: label
3976
- }), o("div", {
3977
- class: "bio-properties-panel-list-entry-header-buttons",
3978
- children: [o("button", {
3979
- title: "Create new list item",
3980
- onClick: addItem,
3981
- class: "bio-properties-panel-add-entry",
3982
- children: [o(CreateIcon, {}), !hasItems ? o("span", {
3983
- class: "bio-properties-panel-add-entry-label",
3984
- children: "Create"
3985
- }) : null]
3986
- }), hasItems && o("div", {
3987
- title: `List contains ${items.length} item${items.length != 1 ? 's' : ''}`,
3988
- class: "bio-properties-panel-list-badge",
3989
- children: items.length
3990
- }), hasItems && o("button", {
3991
- title: "Toggle list item",
3992
- class: "bio-properties-panel-arrow",
3993
- children: o(ArrowIcon, {
3994
- class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
3995
- })
3996
- })]
3997
- })]
3998
- }), hasItems && o(ItemsList, {
3999
- ...restProps,
4000
- autoFocusEntry: autoFocusEntry,
4001
- component: component,
4002
- element: element,
4003
- id: id,
4004
- items: sortedItems,
4005
- newItems: newItems,
4006
- onRemove: onRemove,
4007
- open: open
4008
- })]
4009
- });
4010
- }
4011
- function ItemsList(props) {
4012
- const {
4013
- autoFocusEntry,
4014
- component: Component,
4015
- element,
4016
- id,
4017
- items,
4018
- newItems,
4019
- onRemove,
4020
- open,
4021
- ...restProps
4022
- } = props;
4023
- const getKey = useKeyFactory();
4024
- const newItem = newItems[0];
4025
- p(() => {
4026
- if (newItem && autoFocusEntry) {
4027
- // (0) select the parent entry (containing all list items)
4028
- const entry = query(`[data-entry-id="${id}"]`);
4029
-
4030
- // (1) select the first input or a custom element to be focussed
4031
- const selector = typeof autoFocusEntry === 'boolean' ? '.bio-properties-panel-input' : autoFocusEntry;
4032
- const focusableInput = query(selector, entry);
4033
-
4034
- // (2) set focus
4035
- if (focusableInput) {
4036
- if (isFunction(focusableInput.select)) {
4037
- focusableInput.select();
4038
- } else if (isFunction(focusableInput.focus)) {
4039
- focusableInput.focus();
4040
- }
4041
- }
4042
- }
4043
- }, [newItem, autoFocusEntry, id]);
4044
- return o("ol", {
4045
- class: classnames('bio-properties-panel-list-entry-items', open ? 'open' : ''),
4046
- children: items.map((item, index) => {
4047
- const key = getKey(item);
4048
- return o("li", {
4049
- class: "bio-properties-panel-list-entry-item",
4050
- children: [o(Component, {
4051
- ...restProps,
4052
- element: element,
4053
- id: id,
4054
- index: index,
4055
- item: item,
4056
- open: item === newItem
4057
- }), onRemove && o("button", {
4058
- type: "button",
4059
- title: "Delete item",
4060
- class: "bio-properties-panel-remove-entry bio-properties-panel-remove-list-entry",
4061
- onClick: () => onRemove && onRemove(item),
4062
- children: o(DeleteIcon, {})
4063
- })]
4064
- }, key);
4065
- })
4066
- });
4067
- }
4068
-
4069
- /**
4070
- * Place new items in the beginning of the list and sort the rest with provided function.
4071
- *
4072
- * @template Item
4073
- * @param {Item[]} currentItems
4074
- * @param {(a: Item, b: Item) => 0 | 1 | -1} [compareFn] function used to sort items
4075
- * @param {boolean} [shouldReset=false] set to `true` to reset state of the hook
4076
- * @returns {Item[]}
4077
- */
4078
- function useSortedItems(currentItems, compareFn, shouldReset = false) {
4079
- const itemsRef = _$1(currentItems.slice());
4080
-
4081
- // (1) Reset and optionally sort.
4082
- if (shouldReset) {
4083
- itemsRef.current = currentItems.slice();
4084
- if (compareFn) {
4085
- itemsRef.current.sort(compareFn);
4086
- }
4087
- } else {
4088
- const items = itemsRef.current;
4089
-
4090
- // (2) Add new item to the list.
4091
- for (const item of currentItems) {
4092
- if (!items.includes(item)) {
4093
- // Unshift or push depending on whether we have a compareFn
4094
- compareFn ? items.unshift(item) : items.push(item);
4095
- }
4096
- }
4097
-
4098
- // (3) Filter out removed items.
4099
- itemsRef.current = items.filter(item => currentItems.includes(item));
4100
- }
4101
- return itemsRef.current;
4102
- }
4103
- function useNewItems(items = [], shouldReset) {
4104
- const previousItems = usePrevious(items.slice()) || [];
4105
- if (shouldReset) {
4106
- return [];
4107
- }
4108
- return previousItems ? items.filter(item => !previousItems.includes(item)) : [];
4109
- }
4110
-
4111
- function Select(props) {
4112
- const {
4113
- id,
4114
- label,
4115
- onChange,
4116
- options = [],
4117
- value = '',
4118
- disabled,
4119
- onFocus,
4120
- onBlur,
4121
- tooltip
4122
- } = props;
4123
- const ref = useShowEntryEvent(id);
4124
- const [localValue, setLocalValue] = h(value);
4125
- const handleChangeCallback = ({
4126
- target
4127
- }) => {
4128
- onChange(target.value);
4129
- };
4130
- const handleChange = e => {
4131
- handleChangeCallback(e);
4132
- setLocalValue(e.target.value);
4133
- };
4134
- p(() => {
4135
- if (value === localValue) {
4136
- return;
4137
- }
4138
- setLocalValue(value);
4139
- }, [value]);
4140
- return o("div", {
4141
- class: "bio-properties-panel-select",
4142
- children: [o("label", {
4143
- for: prefixId$3(id),
4144
- class: "bio-properties-panel-label",
4145
- children: o(TooltipWrapper, {
4146
- value: tooltip,
4147
- forId: id,
4148
- element: props.element,
4149
- children: label
4150
- })
4151
- }), o("select", {
4152
- ref: ref,
4153
- id: prefixId$3(id),
4154
- name: id,
4155
- class: "bio-properties-panel-input",
4156
- onInput: handleChange,
4157
- onFocus: onFocus,
4158
- onBlur: onBlur,
4159
- value: localValue,
4160
- disabled: disabled,
4161
- children: options.map((option, idx) => {
4162
- if (option.children) {
4163
- return o("optgroup", {
4164
- label: option.label,
4165
- children: option.children.map((child, idx) => o("option", {
4166
- value: child.value,
4167
- disabled: child.disabled,
4168
- children: child.label
4169
- }, idx))
4170
- }, idx);
4171
- }
4172
- return o("option", {
4173
- value: option.value,
4174
- disabled: option.disabled,
4175
- children: option.label
4176
- }, idx);
4177
- })
4178
- })]
4179
- });
4180
- }
4181
-
4182
- /**
4183
- * @param {object} props
4184
- * @param {object} props.element
4185
- * @param {string} props.id
4186
- * @param {string} [props.description]
4187
- * @param {string} props.label
4188
- * @param {Function} props.getValue
4189
- * @param {Function} props.setValue
4190
- * @param {Function} props.onFocus
4191
- * @param {Function} props.onBlur
4192
- * @param {Function} props.getOptions
4193
- * @param {boolean} [props.disabled]
4194
- * @param {Function} [props.validate]
4195
- * @param {string|import('preact').Component} props.tooltip
4196
- */
4197
- function SelectEntry(props) {
4198
- const {
4199
- element,
4200
- id,
4201
- description,
4202
- label,
4203
- getValue,
4204
- setValue,
4205
- getOptions,
4206
- disabled,
4207
- onFocus,
4208
- onBlur,
4209
- validate,
4210
- tooltip
4211
- } = props;
4212
- const options = getOptions(element);
4213
- const globalError = useError(id);
4214
- const [localError, setLocalError] = h(null);
4215
- let value = getValue(element);
4216
- p(() => {
4217
- if (isFunction(validate)) {
4218
- const newValidationError = validate(value) || null;
4219
- setLocalError(newValidationError);
4220
- }
4221
- }, [value]);
4222
- const onChange = newValue => {
4223
- let newValidationError = null;
4224
- if (isFunction(validate)) {
4225
- newValidationError = validate(newValue) || null;
4226
- }
4227
- setValue(newValue, newValidationError);
4228
- setLocalError(newValidationError);
4229
- };
4230
- const error = globalError || localError;
4231
- return o("div", {
4232
- class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
4233
- "data-entry-id": id,
4234
- children: [o(Select, {
4235
- id: id,
4236
- label: label,
4237
- value: value,
4238
- onChange: onChange,
4239
- onFocus: onFocus,
4240
- onBlur: onBlur,
4241
- options: options,
4242
- disabled: disabled,
4243
- tooltip: tooltip,
4244
- element: element
4245
- }, element), error && o("div", {
4246
- class: "bio-properties-panel-error",
4247
- children: error
4248
- }), o(Description, {
4249
- forId: id,
4250
- element: element,
4251
- value: description
4252
- })]
4253
- });
4254
- }
4255
- function isEdited$3(node) {
4256
- return node && !!node.value;
4257
- }
4258
-
4259
- // helpers /////////////////
4260
-
4261
- function prefixId$3(id) {
4262
- return `bio-properties-panel-${id}`;
4263
- }
4264
-
4265
- function Simple(props) {
4266
- const {
4267
- debounce,
4268
- disabled,
4269
- element,
4270
- getValue,
4271
- id,
4272
- onBlur,
4273
- onFocus,
4274
- setValue
4275
- } = props;
4276
- const value = getValue(element);
4277
- const [localValue, setLocalValue] = h(value);
4278
- const handleInputCallback = F$1(() => {
4279
- return debounce(({
4280
- target
4281
- }) => setValue(target.value.length ? target.value : undefined));
4282
- }, [setValue, debounce]);
4283
- const handleInput = e => {
4284
- handleInputCallback(e);
4285
- setLocalValue(e.target.value);
4286
- };
4287
- p(() => {
4288
- if (value === localValue) {
4289
- return;
4290
- }
4291
- setLocalValue(value);
4292
- }, [value]);
4293
- return o("div", {
4294
- class: "bio-properties-panel-simple",
4295
- children: o("input", {
4296
- id: prefixId$2(id),
4297
- type: "text",
4298
- name: id,
4299
- spellCheck: "false",
4300
- autoComplete: "off",
4301
- disabled: disabled,
4302
- class: "bio-properties-panel-input",
4303
- onInput: handleInput,
4304
- "aria-label": localValue || '<empty>',
4305
- onFocus: onFocus,
4306
- onBlur: onBlur,
4307
- value: localValue
4308
- }, element)
4309
- });
4310
- }
4311
- function isEdited$2(node) {
4312
- return node && !!node.value;
4313
- }
4314
-
4315
- // helpers /////////////////
4316
-
4317
- function prefixId$2(id) {
4318
- return `bio-properties-panel-${id}`;
4319
- }
4320
-
4321
- function resizeToContents(element) {
4322
- element.style.height = 'auto';
4323
-
4324
- // a 2px pixel offset is required to prevent scrollbar from
4325
- // appearing on OS with a full length scroll bar (Windows/Linux)
4326
- element.style.height = `${element.scrollHeight + 2}px`;
4327
- }
4328
- function TextArea(props) {
4329
- const {
4330
- id,
4331
- label,
4332
- debounce,
4333
- onInput,
4334
- value = '',
4335
- disabled,
4336
- monospace,
4337
- onFocus,
4338
- onBlur,
4339
- autoResize,
4340
- rows = autoResize ? 1 : 2,
4341
- tooltip
4342
- } = props;
4343
- const [localValue, setLocalValue] = h(value);
4344
- const ref = useShowEntryEvent(id);
4345
- const handleInputCallback = F$1(() => {
4346
- return debounce(({
4347
- target
4348
- }) => onInput(target.value.length ? target.value : undefined));
4349
- }, [onInput, debounce]);
4350
- const handleInput = e => {
4351
- handleInputCallback(e);
4352
- autoResize && resizeToContents(e.target);
4353
- setLocalValue(e.target.value);
4354
- };
4355
- y(() => {
4356
- autoResize && resizeToContents(ref.current);
4357
- }, []);
4358
- p(() => {
4359
- if (value === localValue) {
4360
- return;
4361
- }
4362
- setLocalValue(value);
4363
- }, [value]);
4364
- return o("div", {
4365
- class: "bio-properties-panel-textarea",
4366
- children: [o("label", {
4367
- for: prefixId$1(id),
4368
- class: "bio-properties-panel-label",
4369
- children: o(TooltipWrapper, {
4370
- value: tooltip,
4371
- forId: id,
4372
- element: props.element,
4373
- children: label
4374
- })
4375
- }), o("textarea", {
4376
- ref: ref,
4377
- id: prefixId$1(id),
4378
- name: id,
4379
- spellCheck: "false",
4380
- class: classnames('bio-properties-panel-input', monospace ? 'bio-properties-panel-input-monospace' : '', autoResize ? 'auto-resize' : ''),
4381
- onInput: handleInput,
4382
- onFocus: onFocus,
4383
- onBlur: onBlur,
4384
- rows: rows,
4385
- value: localValue,
4386
- disabled: disabled,
4387
- "data-gramm": "false"
4388
- })]
4389
- });
4390
- }
4391
-
4392
- /**
4393
- * @param {object} props
4394
- * @param {object} props.element
4395
- * @param {string} props.id
4396
- * @param {string} props.description
4397
- * @param {boolean} props.debounce
4398
- * @param {string} props.label
4399
- * @param {Function} props.getValue
4400
- * @param {Function} props.setValue
4401
- * @param {Function} props.onFocus
4402
- * @param {Function} props.onBlur
4403
- * @param {number} props.rows
4404
- * @param {boolean} props.monospace
4405
- * @param {Function} [props.validate]
4406
- * @param {boolean} [props.disabled]
4407
- */
4408
- function TextAreaEntry(props) {
4409
- const {
4410
- element,
4411
- id,
4412
- description,
4413
- debounce,
4414
- label,
4415
- getValue,
4416
- setValue,
4417
- rows,
4418
- monospace,
4419
- disabled,
4420
- validate,
4421
- onFocus,
4422
- onBlur,
4423
- autoResize,
4424
- tooltip
4425
- } = props;
4426
- const globalError = useError(id);
4427
- const [localError, setLocalError] = h(null);
4428
- let value = getValue(element);
4429
- p(() => {
4430
- if (isFunction(validate)) {
4431
- const newValidationError = validate(value) || null;
4432
- setLocalError(newValidationError);
4433
- }
4434
- }, [value]);
4435
- const onInput = newValue => {
4436
- let newValidationError = null;
4437
- if (isFunction(validate)) {
4438
- newValidationError = validate(newValue) || null;
4439
- }
4440
- setValue(newValue, newValidationError);
4441
- setLocalError(newValidationError);
4442
- };
4443
- const error = globalError || localError;
4444
- return o("div", {
4445
- class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
4446
- "data-entry-id": id,
4447
- children: [o(TextArea, {
4448
- id: id,
4449
- label: label,
4450
- value: value,
4451
- onInput: onInput,
4452
- onFocus: onFocus,
4453
- onBlur: onBlur,
4454
- rows: rows,
4455
- debounce: debounce,
4456
- monospace: monospace,
4457
- disabled: disabled,
4458
- autoResize: autoResize,
4459
- tooltip: tooltip,
4460
- element: element
4461
- }, element), error && o("div", {
4462
- class: "bio-properties-panel-error",
4463
- children: error
4464
- }), o(Description, {
4465
- forId: id,
4466
- element: element,
4467
- value: description
4468
- })]
4469
- });
4470
- }
4471
- function isEdited$1(node) {
4472
- return node && !!node.value;
4473
- }
4474
-
4475
- // helpers /////////////////
4476
-
4477
- function prefixId$1(id) {
4478
- return `bio-properties-panel-${id}`;
4479
- }
4480
-
4481
- function Textfield(props) {
4482
- const {
4483
- debounce,
4484
- disabled = false,
4485
- id,
4486
- label,
4487
- onInput,
4488
- onFocus,
4489
- onBlur,
4490
- value = '',
4491
- tooltip
4492
- } = props;
4493
- const [localValue, setLocalValue] = h(value || '');
4494
- const ref = useShowEntryEvent(id);
4495
- const handleInputCallback = F$1(() => {
4496
- return debounce(({
4497
- target
4498
- }) => onInput(target.value.length ? target.value : undefined));
4499
- }, [onInput, debounce]);
4500
- const handleInput = e => {
4501
- handleInputCallback(e);
4502
- setLocalValue(e.target.value);
4503
- };
4504
- p(() => {
4505
- if (value === localValue) {
4506
- return;
4507
- }
4508
- setLocalValue(value);
4509
- }, [value]);
4510
- return o("div", {
4511
- class: "bio-properties-panel-textfield",
4512
- children: [o("label", {
4513
- for: prefixId(id),
4514
- class: "bio-properties-panel-label",
4515
- children: o(TooltipWrapper, {
4516
- value: tooltip,
4517
- forId: id,
4518
- element: props.element,
4519
- children: label
4520
- })
4521
- }), o("input", {
4522
- ref: ref,
4523
- id: prefixId(id),
4524
- type: "text",
4525
- name: id,
4526
- spellCheck: "false",
4527
- autoComplete: "off",
4528
- disabled: disabled,
4529
- class: "bio-properties-panel-input",
4530
- onInput: handleInput,
4531
- onFocus: onFocus,
4532
- onBlur: onBlur,
4533
- value: localValue
4534
- })]
4535
- });
4536
- }
4537
-
4538
- /**
4539
- * @param {Object} props
4540
- * @param {Object} props.element
4541
- * @param {String} props.id
4542
- * @param {String} props.description
4543
- * @param {Boolean} props.debounce
4544
- * @param {Boolean} props.disabled
4545
- * @param {String} props.label
4546
- * @param {Function} props.getValue
4547
- * @param {Function} props.setValue
4548
- * @param {Function} props.onFocus
4549
- * @param {Function} props.onBlur
4550
- * @param {string|import('preact').Component} props.tooltip
4551
- * @param {Function} props.validate
4552
- */
4553
- function TextfieldEntry(props) {
4554
- const {
4555
- element,
4556
- id,
4557
- description,
4558
- debounce,
4559
- disabled,
4560
- label,
4561
- getValue,
4562
- setValue,
4563
- validate,
4564
- onFocus,
4565
- onBlur,
4566
- tooltip
4567
- } = props;
4568
- const globalError = useError(id);
4569
- const [localError, setLocalError] = h(null);
4570
- let value = getValue(element);
4571
- p(() => {
4572
- if (isFunction(validate)) {
4573
- const newValidationError = validate(value) || null;
4574
- setLocalError(newValidationError);
4575
- }
4576
- }, [value]);
4577
- const onInput = newValue => {
4578
- let newValidationError = null;
4579
- if (isFunction(validate)) {
4580
- newValidationError = validate(newValue) || null;
4581
- }
4582
- setValue(newValue, newValidationError);
4583
- setLocalError(newValidationError);
4584
- };
4585
- const error = globalError || localError;
4586
- return o("div", {
4587
- class: classnames('bio-properties-panel-entry', error ? 'has-error' : ''),
4588
- "data-entry-id": id,
4589
- children: [o(Textfield, {
4590
- debounce: debounce,
4591
- disabled: disabled,
4592
- id: id,
4593
- label: label,
4594
- onInput: onInput,
4595
- onFocus: onFocus,
4596
- onBlur: onBlur,
4597
- value: value,
4598
- tooltip: tooltip,
4599
- element: element
4600
- }, element), error && o("div", {
4601
- class: "bio-properties-panel-error",
4602
- children: error
4603
- }), o(Description, {
4604
- forId: id,
4605
- element: element,
4606
- value: description
4607
- })]
4608
- });
4609
- }
4610
- function isEdited(node) {
4611
- return node && !!node.value;
4612
- }
4613
-
4614
- // helpers /////////////////
4615
-
4616
- function prefixId(id) {
4617
- return `bio-properties-panel-${id}`;
4618
- }
4619
-
4620
- const DEFAULT_DEBOUNCE_TIME = 300;
4621
- function debounceInput(debounceDelay) {
4622
- return function _debounceInput(fn) {
4623
- if (debounceDelay !== false) {
4624
- var debounceTime = isNumber(debounceDelay) ? debounceDelay : DEFAULT_DEBOUNCE_TIME;
4625
- return debounce(fn, debounceTime);
4626
- } else {
4627
- return fn;
4628
- }
4629
- };
4630
- }
4631
- debounceInput.$inject = ['config.debounceInput'];
4632
-
4633
- var index$1 = {
4634
- debounceInput: ['factory', debounceInput]
4635
- };
4636
-
4637
- class FeelPopupModule {
4638
- constructor(eventBus) {
4639
- this._eventBus = eventBus;
4640
- }
4641
-
4642
- /**
4643
- * Check if the FEEL popup is open.
4644
- * @return {Boolean}
4645
- */
4646
- isOpen() {
4647
- return this._eventBus.fire('feelPopup._isOpen');
4648
- }
4649
-
4650
- /**
4651
- * Open the FEEL popup.
4652
- *
4653
- * @param {String} entryId
4654
- * @param {Object} popupConfig
4655
- * @param {HTMLElement} sourceElement
4656
- */
4657
- open(entryId, popupConfig, sourceElement) {
4658
- return this._eventBus.fire('feelPopup._open', {
4659
- entryId,
4660
- popupConfig,
4661
- sourceElement
4662
- });
4663
- }
4664
-
4665
- /**
4666
- * Close the FEEL popup.
4667
- */
4668
- close() {
4669
- return this._eventBus.fire('feelPopup._close');
4670
- }
4671
- }
4672
- FeelPopupModule.$inject = ['eventBus'];
4673
-
4674
- var index = {
4675
- feelPopup: ['type', FeelPopupModule]
4676
- };
4677
-
4678
- export { ArrowIcon, CheckboxEntry, CollapsibleEntry, CreateIcon, index$1 as DebounceInputModule, DeleteIcon, DescriptionContext, Description as DescriptionEntry, DragIcon, DropdownButton, ErrorsContext, EventContext, ExternalLinkIcon, FeelCheckboxEntry, FeelEntry, FeelIcon$1 as FeelIcon, FeelNumberEntry, index as FeelPopupModule, FeelTemplatingEntry, FeelTextAreaEntry, FeelToggleSwitchEntry, Group, Header, HeaderButton, LayoutContext, List as ListEntry, ListGroup, ListItem, NumberFieldEntry, Placeholder, Popup, PropertiesPanel, LayoutContext as PropertiesPanelContext, SelectEntry, Simple as SimpleEntry, TemplatingEntry, TextAreaEntry, TextfieldEntry as TextFieldEntry, ToggleSwitchEntry, TooltipContext, isEdited$5 as isCheckboxEntryEdited, isEdited$6 as isFeelEntryEdited, isEdited$7 as isNumberFieldEntryEdited, isEdited$3 as isSelectEntryEdited, isEdited$2 as isSimpleEntryEdited, isEdited$4 as isTemplatingEntryEdited, isEdited$1 as isTextAreaEntryEdited, isEdited as isTextFieldEntryEdited, isEdited$8 as isToggleSwitchEntryEdited, useDescriptionContext, useError, useErrors, useEvent, useKeyFactory, useLayoutState, usePrevious, useShowEntryEvent, useStaticCallback, useStickyIntersectionObserver, useTooltipContext };
4679
- //# sourceMappingURL=index.mjs.map