@kunpeng-js/properties-panel 0.0.0-stage → 2026.0.0-alpha2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +34 -2
  3. package/assets/properties-panel.css +4 -0
  4. package/dist/assets/properties-panel.css +1539 -0
  5. package/dist/index.esm.js +3958 -0
  6. package/dist/index.esm.js.map +1 -0
  7. package/dist/index.js +4053 -0
  8. package/dist/index.js.map +1 -0
  9. package/package.json +113 -3
  10. package/preact/LICENSE +21 -0
  11. package/preact/README.md +188 -0
  12. package/preact/compat/client.d.ts +13 -0
  13. package/preact/compat/client.js +21 -0
  14. package/preact/compat/client.mjs +24 -0
  15. package/preact/compat/dist/compat.js +2 -0
  16. package/preact/compat/dist/compat.js.map +1 -0
  17. package/preact/compat/dist/compat.mjs +2 -0
  18. package/preact/compat/dist/compat.module.js +2 -0
  19. package/preact/compat/dist/compat.module.js.map +1 -0
  20. package/preact/compat/dist/compat.umd.js +2 -0
  21. package/preact/compat/dist/compat.umd.js.map +1 -0
  22. package/preact/compat/jsx-dev-runtime.js +3 -0
  23. package/preact/compat/jsx-dev-runtime.mjs +3 -0
  24. package/preact/compat/jsx-runtime.js +3 -0
  25. package/preact/compat/jsx-runtime.mjs +3 -0
  26. package/preact/compat/package.json +55 -0
  27. package/preact/compat/scheduler.js +15 -0
  28. package/preact/compat/scheduler.mjs +23 -0
  29. package/preact/compat/server.browser.js +11 -0
  30. package/preact/compat/server.js +36 -0
  31. package/preact/compat/server.mjs +17 -0
  32. package/preact/compat/src/Children.js +21 -0
  33. package/preact/compat/src/PureComponent.js +16 -0
  34. package/preact/compat/src/forwardRef.js +44 -0
  35. package/preact/compat/src/hooks.js +67 -0
  36. package/preact/compat/src/index.d.ts +353 -0
  37. package/preact/compat/src/index.js +243 -0
  38. package/preact/compat/src/internal.d.ts +51 -0
  39. package/preact/compat/src/memo.js +31 -0
  40. package/preact/compat/src/portals.js +78 -0
  41. package/preact/compat/src/render.js +302 -0
  42. package/preact/compat/src/suspense-list.d.ts +16 -0
  43. package/preact/compat/src/suspense-list.js +127 -0
  44. package/preact/compat/src/suspense.d.ts +19 -0
  45. package/preact/compat/src/suspense.js +289 -0
  46. package/preact/compat/src/util.js +33 -0
  47. package/preact/compat/test-utils.js +1 -0
  48. package/preact/compat/test-utils.mjs +1 -0
  49. package/preact/debug/dist/debug.js +2 -0
  50. package/preact/debug/dist/debug.js.map +1 -0
  51. package/preact/debug/dist/debug.mjs +2 -0
  52. package/preact/debug/dist/debug.module.js +2 -0
  53. package/preact/debug/dist/debug.module.js.map +1 -0
  54. package/preact/debug/dist/debug.umd.js +2 -0
  55. package/preact/debug/dist/debug.umd.js.map +1 -0
  56. package/preact/debug/package.json +27 -0
  57. package/preact/debug/src/check-props.js +54 -0
  58. package/preact/debug/src/component-stack.js +146 -0
  59. package/preact/debug/src/constants.js +3 -0
  60. package/preact/debug/src/debug.js +593 -0
  61. package/preact/debug/src/index.d.ts +23 -0
  62. package/preact/debug/src/index.js +12 -0
  63. package/preact/debug/src/internal.d.ts +82 -0
  64. package/preact/debug/src/util.js +15 -0
  65. package/preact/devtools/dist/devtools.js +2 -0
  66. package/preact/devtools/dist/devtools.js.map +1 -0
  67. package/preact/devtools/dist/devtools.mjs +2 -0
  68. package/preact/devtools/dist/devtools.module.js +2 -0
  69. package/preact/devtools/dist/devtools.module.js.map +1 -0
  70. package/preact/devtools/dist/devtools.umd.js +2 -0
  71. package/preact/devtools/dist/devtools.umd.js.map +1 -0
  72. package/preact/devtools/package.json +25 -0
  73. package/preact/devtools/src/devtools.js +21 -0
  74. package/preact/devtools/src/index.d.ts +8 -0
  75. package/preact/devtools/src/index.js +15 -0
  76. package/preact/dist/preact.js +2 -0
  77. package/preact/dist/preact.js.map +1 -0
  78. package/preact/dist/preact.min.js +2 -0
  79. package/preact/dist/preact.min.js.map +1 -0
  80. package/preact/dist/preact.min.module.js +2 -0
  81. package/preact/dist/preact.min.module.js.map +1 -0
  82. package/preact/dist/preact.min.umd.js +2 -0
  83. package/preact/dist/preact.min.umd.js.map +1 -0
  84. package/preact/dist/preact.mjs +2 -0
  85. package/preact/dist/preact.module.js +2 -0
  86. package/preact/dist/preact.module.js.map +1 -0
  87. package/preact/dist/preact.umd.js +2 -0
  88. package/preact/dist/preact.umd.js.map +1 -0
  89. package/preact/hooks/dist/hooks.js +2 -0
  90. package/preact/hooks/dist/hooks.js.map +1 -0
  91. package/preact/hooks/dist/hooks.mjs +2 -0
  92. package/preact/hooks/dist/hooks.module.js +2 -0
  93. package/preact/hooks/dist/hooks.module.js.map +1 -0
  94. package/preact/hooks/dist/hooks.umd.js +2 -0
  95. package/preact/hooks/dist/hooks.umd.js.map +1 -0
  96. package/preact/hooks/package.json +35 -0
  97. package/preact/hooks/src/index.d.ts +145 -0
  98. package/preact/hooks/src/index.js +549 -0
  99. package/preact/hooks/src/internal.d.ts +108 -0
  100. package/preact/jsx-runtime/dist/jsxRuntime.js +2 -0
  101. package/preact/jsx-runtime/dist/jsxRuntime.js.map +1 -0
  102. package/preact/jsx-runtime/dist/jsxRuntime.mjs +2 -0
  103. package/preact/jsx-runtime/dist/jsxRuntime.module.js +2 -0
  104. package/preact/jsx-runtime/dist/jsxRuntime.module.js.map +1 -0
  105. package/preact/jsx-runtime/dist/jsxRuntime.umd.js +2 -0
  106. package/preact/jsx-runtime/dist/jsxRuntime.umd.js.map +1 -0
  107. package/preact/jsx-runtime/package.json +28 -0
  108. package/preact/jsx-runtime/src/index.d.ts +62 -0
  109. package/preact/jsx-runtime/src/index.js +206 -0
  110. package/preact/jsx-runtime/src/utils.js +36 -0
  111. package/preact/package.json +273 -0
  112. package/preact/src/cjs.js +3 -0
  113. package/preact/src/clone-element.js +48 -0
  114. package/preact/src/component.js +247 -0
  115. package/preact/src/constants.js +22 -0
  116. package/preact/src/create-context.js +60 -0
  117. package/preact/src/create-element.js +97 -0
  118. package/preact/src/diff/catch-error.js +46 -0
  119. package/preact/src/diff/children.js +451 -0
  120. package/preact/src/diff/index.js +693 -0
  121. package/preact/src/diff/props.js +184 -0
  122. package/preact/src/dom.d.ts +2548 -0
  123. package/preact/src/index-5.d.ts +399 -0
  124. package/preact/src/index.d.ts +373 -0
  125. package/preact/src/index.js +13 -0
  126. package/preact/src/internal.d.ts +194 -0
  127. package/preact/src/jsx.d.ts +2958 -0
  128. package/preact/src/options.js +16 -0
  129. package/preact/src/render.js +81 -0
  130. package/preact/src/util.js +28 -0
  131. package/preact/test-utils/dist/testUtils.js +2 -0
  132. package/preact/test-utils/dist/testUtils.js.map +1 -0
  133. package/preact/test-utils/dist/testUtils.mjs +2 -0
  134. package/preact/test-utils/dist/testUtils.module.js +2 -0
  135. package/preact/test-utils/dist/testUtils.module.js.map +1 -0
  136. package/preact/test-utils/dist/testUtils.umd.js +2 -0
  137. package/preact/test-utils/dist/testUtils.umd.js.map +1 -0
  138. package/preact/test-utils/package.json +28 -0
  139. package/preact/test-utils/src/index.d.ts +3 -0
  140. package/preact/test-utils/src/index.js +130 -0
package/dist/index.js ADDED
@@ -0,0 +1,4053 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let preact_hooks = require("../preact/hooks");
25
+ let min_dash = require("min-dash");
26
+ let preact_compat = require("../preact/compat");
27
+ preact_compat = __toESM(preact_compat);
28
+ let preact_jsx_runtime = require("../preact/jsx-runtime");
29
+ let preact = require("../preact");
30
+ let classnames = require("classnames");
31
+ classnames = __toESM(classnames);
32
+ let min_dom = require("min-dom");
33
+ let _codemirror_view = require("@codemirror/view");
34
+ let _codemirror_state = require("@codemirror/state");
35
+ let _codemirror_language = require("@codemirror/language");
36
+ let _codemirror_autocomplete = require("@codemirror/autocomplete");
37
+ let _codemirror_commands = require("@codemirror/commands");
38
+ let _codemirror_lang_json = require("@codemirror/lang-json");
39
+ let _codemirror_lint = require("@codemirror/lint");
40
+ let _kunpeng_js_expression_editor = require("@kunpeng-js/expression-editor");
41
+ _kunpeng_js_expression_editor = __toESM(_kunpeng_js_expression_editor);
42
+ let focus_trap = require("focus-trap");
43
+ focus_trap = __toESM(focus_trap);
44
+ //#region src/components/icons/index.js
45
+ var ArrowIcon = function ArrowIcon(props) {
46
+ return (0, preact_jsx_runtime.jsx)("svg", {
47
+ ...props,
48
+ children: (0, preact_jsx_runtime.jsx)("path", {
49
+ fillRule: "evenodd",
50
+ 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"
51
+ })
52
+ });
53
+ };
54
+ ArrowIcon.defaultProps = {
55
+ xmlns: "http://www.w3.org/2000/svg",
56
+ width: "16",
57
+ height: "16"
58
+ };
59
+ var CloseIcon = function CloseIcon(props) {
60
+ return (0, preact_jsx_runtime.jsx)("svg", {
61
+ ...props,
62
+ children: (0, preact_jsx_runtime.jsx)("path", {
63
+ fillRule: "evenodd",
64
+ d: "m12 4.7-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8 12 4.7Z",
65
+ fill: "currentColor"
66
+ })
67
+ });
68
+ };
69
+ CloseIcon.defaultProps = {
70
+ xmlns: "http://www.w3.org/2000/svg",
71
+ width: "16",
72
+ height: "16"
73
+ };
74
+ var CreateIcon = function CreateIcon(props) {
75
+ return (0, preact_jsx_runtime.jsx)("svg", {
76
+ ...props,
77
+ children: (0, preact_jsx_runtime.jsx)("path", {
78
+ fillRule: "evenodd",
79
+ 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"
80
+ })
81
+ });
82
+ };
83
+ CreateIcon.defaultProps = {
84
+ xmlns: "http://www.w3.org/2000/svg",
85
+ width: "16",
86
+ height: "16"
87
+ };
88
+ var DeleteIcon = function DeleteIcon(props) {
89
+ return (0, preact_jsx_runtime.jsx)("svg", {
90
+ ...props,
91
+ children: (0, preact_jsx_runtime.jsx)("path", {
92
+ fillRule: "evenodd",
93
+ 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"
94
+ })
95
+ });
96
+ };
97
+ DeleteIcon.defaultProps = {
98
+ xmlns: "http://www.w3.org/2000/svg",
99
+ width: "16",
100
+ height: "16"
101
+ };
102
+ var DragIcon = function DragIcon(props) {
103
+ return (0, preact_jsx_runtime.jsx)("svg", {
104
+ ...props,
105
+ children: (0, preact_jsx_runtime.jsx)("path", {
106
+ d: "M7 3H5v2h2V3zm4 0H9v2h2V3zM7 7H5v2h2V7zm4 0H9v2h2V7zm-4 4H5v2h2v-2zm4 0H9v2h2v-2z",
107
+ fill: "currentColor"
108
+ })
109
+ });
110
+ };
111
+ DragIcon.defaultProps = {
112
+ width: "16",
113
+ height: "16",
114
+ fill: "none",
115
+ xmlns: "http://www.w3.org/2000/svg"
116
+ };
117
+ var ExternalLinkIcon = function ExternalLinkIcon(props) {
118
+ return (0, preact_jsx_runtime.jsx)("svg", {
119
+ ...props,
120
+ children: (0, preact_jsx_runtime.jsx)("path", {
121
+ fillRule: "evenodd",
122
+ clipRule: "evenodd",
123
+ 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",
124
+ fill: "currentcolor"
125
+ })
126
+ });
127
+ };
128
+ ExternalLinkIcon.defaultProps = {
129
+ width: "16",
130
+ height: "16",
131
+ fill: "none",
132
+ xmlns: "http://www.w3.org/2000/svg"
133
+ };
134
+ var FeelIcon = function FeelIcon(props) {
135
+ return (0, preact_jsx_runtime.jsx)("svg", {
136
+ ...props,
137
+ children: (0, preact_jsx_runtime.jsx)("path", {
138
+ 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",
139
+ fill: "currentcolor"
140
+ })
141
+ });
142
+ };
143
+ FeelIcon.defaultProps = {
144
+ width: "14",
145
+ height: "14",
146
+ fill: "none",
147
+ xmlns: "http://www.w3.org/2000/svg"
148
+ };
149
+ var LaunchIcon = function LaunchIcon(props) {
150
+ return (0, preact_jsx_runtime.jsxs)("svg", {
151
+ ...props,
152
+ children: [(0, preact_jsx_runtime.jsx)("path", { d: "M26 28H6a2.003 2.003 0 0 1-2-2V6a2.003 2.003 0 0 1 2-2h10v2H6v20h20V16h2v10a2.003 2.003 0 0 1-2 2Z" }), (0, preact_jsx_runtime.jsx)("path", { d: "M20 2v2h6.586L18 12.586 19.414 14 28 5.414V12h2V2H20z" })]
153
+ });
154
+ };
155
+ LaunchIcon.defaultProps = {
156
+ xmlns: "http://www.w3.org/2000/svg",
157
+ viewBox: "0 0 32 32"
158
+ };
159
+ var OpenPopupIcon = function OpenPopupIcon(props) {
160
+ return (0, preact_jsx_runtime.jsx)("svg", {
161
+ ...props,
162
+ children: (0, preact_jsx_runtime.jsx)("path", { d: "M6 15v-1H2.7L7 9.7 6.3 9 2 13.3V10H1v5zM10 1v1h3.3L9 6.3l.7.7L14 2.7V6h1V1z" })
163
+ });
164
+ };
165
+ OpenPopupIcon.defaultProps = {
166
+ xmlns: "http://www.w3.org/2000/svg",
167
+ viewBox: "0 0 16 16"
168
+ };
169
+ //#endregion
170
+ //#region src/components/Header.js
171
+ /**
172
+ * @typedef { {
173
+ * getElementLabel: (element: object) => string,
174
+ * getTypeLabel: (element: object) => string,
175
+ * getElementIcon: (element: object) => import('preact').Component,
176
+ * getDocumentationRef: (element: object) => string
177
+ * } } HeaderProvider
178
+ */
179
+ /**
180
+ * @param {Object} props
181
+ * @param {Object} props.element,
182
+ * @param {HeaderProvider} props.headerProvider
183
+ */
184
+ function Header(props) {
185
+ const { element, headerProvider } = props;
186
+ const { getElementIcon, getDocumentationRef, getElementLabel, getTypeLabel } = headerProvider;
187
+ const label = getElementLabel(element);
188
+ const type = getTypeLabel(element);
189
+ const documentationRef = getDocumentationRef && getDocumentationRef(element);
190
+ const ElementIcon = getElementIcon(element);
191
+ return (0, preact_jsx_runtime.jsxs)("div", {
192
+ class: "bio-properties-panel-header",
193
+ children: [
194
+ (0, preact_jsx_runtime.jsx)("div", {
195
+ class: "bio-properties-panel-header-icon",
196
+ children: ElementIcon && (0, preact_jsx_runtime.jsx)(ElementIcon, {
197
+ width: "32",
198
+ height: "32",
199
+ viewBox: "0 0 32 32"
200
+ })
201
+ }),
202
+ (0, preact_jsx_runtime.jsxs)("div", {
203
+ class: "bio-properties-panel-header-labels",
204
+ children: [(0, preact_jsx_runtime.jsx)("div", {
205
+ class: "bio-properties-panel-header-type",
206
+ children: type
207
+ }), label ? (0, preact_jsx_runtime.jsx)("div", {
208
+ class: "bio-properties-panel-header-label",
209
+ children: label
210
+ }) : null]
211
+ }),
212
+ (0, preact_jsx_runtime.jsx)("div", {
213
+ class: "bio-properties-panel-header-actions",
214
+ children: documentationRef ? (0, preact_jsx_runtime.jsx)("a", {
215
+ rel: "noreferrer",
216
+ class: "bio-properties-panel-header-link",
217
+ href: documentationRef,
218
+ title: "Open documentation",
219
+ target: "_blank",
220
+ children: (0, preact_jsx_runtime.jsx)(ExternalLinkIcon, {})
221
+ }) : null
222
+ })
223
+ ]
224
+ });
225
+ }
226
+ //#endregion
227
+ //#region src/context/DescriptionContext.js
228
+ var DescriptionContext = (0, preact.createContext)({
229
+ description: {},
230
+ getDescriptionForId: () => {}
231
+ });
232
+ //#endregion
233
+ //#region src/context/ErrorsContext.js
234
+ var ErrorsContext = (0, preact.createContext)({ errors: {} });
235
+ //#endregion
236
+ //#region src/context/EventContext.js
237
+ /**
238
+ * @typedef {Function} <propertiesPanel.showEntry> callback
239
+ *
240
+ * @example
241
+ *
242
+ * useEvent('propertiesPanel.showEntry', ({ focus = false, ...rest }) => {
243
+ * // ...
244
+ * });
245
+ *
246
+ * @param {Object} context
247
+ * @param {boolean} [context.focus]
248
+ *
249
+ * @returns void
250
+ */
251
+ /**
252
+ * @typedef {Function} <propertiesPanel.showError> callback
253
+ *
254
+ * @example
255
+ *
256
+ * useEvent('propertiesPanel.showError', ({ focus = false, message, ...rest }) => {
257
+ * // ...
258
+ * });
259
+ *
260
+ * @param {Object} context
261
+ * @param {string} context.message
262
+ * @param {boolean} [context.focus]
263
+ *
264
+ * @returns void
265
+ */
266
+ var EventContext = (0, preact.createContext)({ eventBus: null });
267
+ //#endregion
268
+ //#region src/context/FeelLanguageContext.js
269
+ /**
270
+ * @typedef { {
271
+ * parserDialect?: import('@kunpeng-js/expression-editor').ParserDialect,
272
+ * builtins?: import('@kunpeng-js/expression-editor').Variable[],
273
+ * dialect?: import('@kunpeng-js/expression-editor').Dialect
274
+ * } } FeelLanguageContextType
275
+ */
276
+ /**
277
+ * @type {import('preact').Context<FeelLanguageContextType>}
278
+ */
279
+ var FeelLanguageContext = (0, preact.createContext)({});
280
+ //#endregion
281
+ //#region src/context/LayoutContext.js
282
+ var LayoutContext = (0, preact.createContext)({
283
+ layout: {},
284
+ setLayout: () => {},
285
+ getLayoutForKey: () => {},
286
+ setLayoutForKey: () => {}
287
+ });
288
+ //#endregion
289
+ //#region src/context/TooltipContext.js
290
+ var TooltipContext = (0, preact.createContext)({
291
+ tooltip: {},
292
+ getTooltipForId: () => {}
293
+ });
294
+ //#endregion
295
+ //#region src/hooks/useTooltipContext.js
296
+ /**
297
+ * Accesses the global TooltipContext and returns a tooltip for a given id and element.
298
+ *
299
+ * @example
300
+ * ```jsx
301
+ * function TextField(props) {
302
+ * const tooltip = useTooltipContext('input1', element);
303
+ * }
304
+ * ```
305
+ *
306
+ * @param {string} id
307
+ * @param {object} element
308
+ *
309
+ * @returns {string}
310
+ */
311
+ function useTooltipContext(id, element) {
312
+ const { getTooltipForId } = (0, preact_hooks.useContext)(TooltipContext);
313
+ return getTooltipForId(id, element);
314
+ }
315
+ //#endregion
316
+ //#region src/components/entries/Tooltip.js
317
+ /**
318
+ * @typedef {Object} TooltipProps
319
+ * @property {Object} [parent] - Parent element ref for portal rendering
320
+ * @property {String} [direction='right'] - Tooltip direction ( 'right', 'top')
321
+ * @property {String} [position] - Custom CSS position override
322
+ * @property {Number} [showDelay=250] - Delay in ms before showing tooltip on hover
323
+ * @property {Number} [hideDelay=250] - Delay in ms before hiding tooltip when mouse leaves, to avoid multiple tooltips from being opened, this should be the same as showDelay
324
+ * @property {*} [children] - Child elements to render inside the tooltip wrapper
325
+ */
326
+ /**
327
+ * Tooltip wrapper that provides context-based tooltip content lookup.
328
+ * All props are forwarded to the underlying Tooltip component.
329
+ *
330
+ * @param {TooltipProps & {
331
+ * forId: String,
332
+ * value?: String|Object,
333
+ * element?: Object
334
+ * }} props - Shared tooltip props plus wrapper-specific ones
335
+ */
336
+ function TooltipWrapper(props) {
337
+ const { forId, element } = props;
338
+ const contextDescription = useTooltipContext(forId, element);
339
+ const value = props.value || contextDescription;
340
+ if (!value) return props.children;
341
+ return (0, preact_jsx_runtime.jsx)(Tooltip, {
342
+ ...props,
343
+ value,
344
+ forId: `bio-properties-panel-${forId}`
345
+ });
346
+ }
347
+ /**
348
+ * @param {TooltipProps & {
349
+ * forId: String,
350
+ * value: String|Object
351
+ * }} props
352
+ */
353
+ function Tooltip(props) {
354
+ const { forId, value, parent, direction = "right", position, showDelay = 250, hideDelay = 250 } = props;
355
+ const [visible, setVisible] = (0, preact_hooks.useState)(false);
356
+ const showTimeoutRef = (0, preact_hooks.useRef)(null);
357
+ const hideTimeoutRef = (0, preact_hooks.useRef)(null);
358
+ const wrapperRef = (0, preact_hooks.useRef)(null);
359
+ const tooltipRef = (0, preact_hooks.useRef)(null);
360
+ const show = (_, delay) => {
361
+ clearTimeout(showTimeoutRef.current);
362
+ clearTimeout(hideTimeoutRef.current);
363
+ if (visible) return;
364
+ if (delay) showTimeoutRef.current = setTimeout(() => {
365
+ setVisible(true);
366
+ }, showDelay);
367
+ else setVisible(true);
368
+ };
369
+ const handleWrapperMouseEnter = (e) => {
370
+ show(e, true);
371
+ };
372
+ const hide = (delay = false) => {
373
+ clearTimeout(showTimeoutRef.current);
374
+ clearTimeout(hideTimeoutRef.current);
375
+ if (delay) hideTimeoutRef.current = setTimeout(() => {
376
+ setVisible(false);
377
+ }, hideDelay);
378
+ else setVisible(false);
379
+ };
380
+ (0, preact_hooks.useEffect)(() => {
381
+ return () => {
382
+ clearTimeout(showTimeoutRef.current);
383
+ clearTimeout(hideTimeoutRef.current);
384
+ };
385
+ }, []);
386
+ (0, preact_hooks.useEffect)(() => {
387
+ if (!visible) return;
388
+ const handleClickOutside = (e) => {
389
+ if (wrapperRef.current && !wrapperRef.current.contains(e.target) && tooltipRef.current && !tooltipRef.current.contains(e.target)) hide(false);
390
+ };
391
+ document.addEventListener("mousedown", handleClickOutside);
392
+ return () => {
393
+ document.removeEventListener("mousedown", handleClickOutside);
394
+ };
395
+ }, [visible, hide]);
396
+ const handleMouseLeave = ({ relatedTarget }) => {
397
+ if (relatedTarget === wrapperRef.current || relatedTarget === tooltipRef.current || relatedTarget?.parentElement === tooltipRef.current) return;
398
+ const selection = window.getSelection();
399
+ if (selection && selection.toString().length > 0) {
400
+ const selectionRange = selection.getRangeAt(0);
401
+ if (tooltipRef.current?.contains(selectionRange.commonAncestorContainer) || tooltipRef.current?.contains(selection.anchorNode) || tooltipRef.current?.contains(selection.focusNode)) return;
402
+ }
403
+ hide(true);
404
+ };
405
+ const handleTooltipMouseEnter = () => {
406
+ clearTimeout(hideTimeoutRef.current);
407
+ };
408
+ const handleFocusOut = (e) => {
409
+ const { relatedTarget } = e;
410
+ if (tooltipRef.current?.contains(relatedTarget) || wrapperRef.current?.contains(relatedTarget)) return;
411
+ hide(false);
412
+ };
413
+ const hideTooltipViaEscape = (e) => {
414
+ e.code === "Escape" && hide(false);
415
+ };
416
+ const renderTooltip = () => {
417
+ return (0, preact_jsx_runtime.jsxs)("div", {
418
+ class: `bio-properties-panel-tooltip ${direction}`,
419
+ role: "tooltip",
420
+ id: "bio-properties-panel-tooltip",
421
+ "aria-labelledby": forId,
422
+ style: position || getTooltipPosition(wrapperRef.current),
423
+ ref: tooltipRef,
424
+ onClick: (e) => e.stopPropagation(),
425
+ onMouseEnter: handleTooltipMouseEnter,
426
+ onMouseLeave: handleMouseLeave,
427
+ children: [(0, preact_jsx_runtime.jsx)("div", {
428
+ class: "bio-properties-panel-tooltip-content",
429
+ children: value
430
+ }), (0, preact_jsx_runtime.jsx)("div", { class: "bio-properties-panel-tooltip-arrow" })]
431
+ });
432
+ };
433
+ return (0, preact_jsx_runtime.jsxs)("div", {
434
+ class: "bio-properties-panel-tooltip-wrapper",
435
+ tabIndex: "0",
436
+ ref: wrapperRef,
437
+ onMouseEnter: handleWrapperMouseEnter,
438
+ onMouseLeave: handleMouseLeave,
439
+ onFocus: show,
440
+ onBlur: handleFocusOut,
441
+ onKeyDown: hideTooltipViaEscape,
442
+ children: [props.children, visible ? parent ? (0, preact_compat.createPortal)(renderTooltip(), parent.current) : renderTooltip() : null]
443
+ });
444
+ }
445
+ function getTooltipPosition(refElement) {
446
+ const refPosition = refElement.getBoundingClientRect();
447
+ return `right: ${`calc(100% - ${refPosition.x}px)`}; top: ${`${refPosition.top - 10}px`};`;
448
+ }
449
+ //#endregion
450
+ //#region src/hooks/useDescriptionContext.js
451
+ /**
452
+ * Accesses the global DescriptionContext and returns a description for a given id and element.
453
+ *
454
+ * @example
455
+ * ```jsx
456
+ * function TextField(props) {
457
+ * const description = useDescriptionContext('input1', element);
458
+ * }
459
+ * ```
460
+ *
461
+ * @param {string} id
462
+ * @param {object} element
463
+ *
464
+ * @returns {string}
465
+ */
466
+ function useDescriptionContext(id, element) {
467
+ const { getDescriptionForId } = (0, preact_hooks.useContext)(DescriptionContext);
468
+ return getDescriptionForId(id, element);
469
+ }
470
+ //#endregion
471
+ //#region src/hooks/useDebounce.js
472
+ function useDebounce(callback, debounceFn) {
473
+ const debouncedCallback = (0, preact_hooks.useCallback)(debounceFn(callback), [callback, debounceFn]);
474
+ (0, preact_hooks.useEffect)(() => {
475
+ return () => {
476
+ debouncedCallback.cancel?.();
477
+ };
478
+ }, [debouncedCallback]);
479
+ return debouncedCallback;
480
+ }
481
+ //#endregion
482
+ //#region src/hooks/useError.js
483
+ function useError(id) {
484
+ const { errors } = (0, preact_hooks.useContext)(ErrorsContext);
485
+ return errors[id];
486
+ }
487
+ function useErrors() {
488
+ const { errors } = (0, preact_hooks.useContext)(ErrorsContext);
489
+ return errors;
490
+ }
491
+ //#endregion
492
+ //#region src/hooks/useEvent.js
493
+ /**
494
+ * Subscribe to an event immediately. Update subscription after inputs changed.
495
+ *
496
+ * @param {string} event
497
+ * @param {Function} callback
498
+ */
499
+ function useEvent(event, callback, eventBus) {
500
+ const eventContext = (0, preact_hooks.useContext)(EventContext);
501
+ if (!eventBus) ({eventBus} = eventContext);
502
+ const didMount = (0, preact_hooks.useRef)(false);
503
+ if (eventBus && !didMount.current) eventBus.on(event, callback);
504
+ (0, preact_hooks.useEffect)(() => {
505
+ if (eventBus && didMount.current) eventBus.on(event, callback);
506
+ didMount.current = true;
507
+ return () => {
508
+ if (eventBus) eventBus.off(event, callback);
509
+ };
510
+ }, [
511
+ callback,
512
+ event,
513
+ eventBus
514
+ ]);
515
+ }
516
+ //#endregion
517
+ //#region src/hooks/useKeyFactory.js
518
+ /**
519
+ * Create a persistent key factory for plain objects without id.
520
+ *
521
+ * @example
522
+ * ```jsx
523
+ * function List({ objects }) {
524
+ * const getKey = useKeyFactory();
525
+ * return (<ol>{
526
+ * objects.map(obj => {
527
+ * const key = getKey(obj);
528
+ * return <li key={key}>obj.name</li>
529
+ * })
530
+ * }</ol>);
531
+ * }
532
+ * ```
533
+ *
534
+ * @param {any[]} dependencies
535
+ * @returns {(element: object) => string}
536
+ */
537
+ function useKeyFactory(dependencies = []) {
538
+ const map = (0, preact_hooks.useMemo)(() => /* @__PURE__ */ new Map(), dependencies);
539
+ const getKey = (el) => {
540
+ let key = map.get(el);
541
+ if (!key) {
542
+ key = Math.random().toString().slice(-6);
543
+ map.set(el, key);
544
+ }
545
+ return key;
546
+ };
547
+ return getKey;
548
+ }
549
+ //#endregion
550
+ //#region src/hooks/useLayoutState.js
551
+ /**
552
+ * Creates a state that persists in the global LayoutContext.
553
+ *
554
+ * @example
555
+ * ```jsx
556
+ * function Group(props) {
557
+ * const [ open, setOpen ] = useLayoutState([ 'groups', 'foo', 'open' ], false);
558
+ * }
559
+ * ```
560
+ *
561
+ * @param {(string|number)[]} path
562
+ * @param {any} [defaultValue]
563
+ *
564
+ * @returns {[ any, Function ]}
565
+ */
566
+ function useLayoutState(path, defaultValue) {
567
+ const { getLayoutForKey, setLayoutForKey } = (0, preact_hooks.useContext)(LayoutContext);
568
+ return [getLayoutForKey(path, defaultValue), (0, preact_hooks.useCallback)((newValue) => {
569
+ setLayoutForKey(path, newValue);
570
+ }, [setLayoutForKey])];
571
+ }
572
+ //#endregion
573
+ //#region src/hooks/usePrevious.js
574
+ /**
575
+ * @pinussilvestrus: we need to introduce our own hook to persist the previous
576
+ * state on updates.
577
+ *
578
+ * cf. https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state
579
+ */
580
+ function usePrevious(value) {
581
+ const ref = (0, preact_hooks.useRef)();
582
+ (0, preact_hooks.useEffect)(() => {
583
+ ref.current = value;
584
+ });
585
+ return ref.current;
586
+ }
587
+ //#endregion
588
+ //#region src/hooks/useShowEntryEvent.js
589
+ /**
590
+ * Subscribe to `propertiesPanel.showEntry`.
591
+ *
592
+ * @param {string} id
593
+ *
594
+ * @returns {import('preact').Ref}
595
+ */
596
+ function useShowEntryEvent(id) {
597
+ const { onShow } = (0, preact_hooks.useContext)(LayoutContext);
598
+ const ref = (0, preact_hooks.useRef)();
599
+ const focus = (0, preact_hooks.useRef)(false);
600
+ const onShowEntry = (0, preact_hooks.useCallback)((event) => {
601
+ if (event.id === id) {
602
+ onShow();
603
+ if (!focus.current) focus.current = true;
604
+ }
605
+ }, [id]);
606
+ (0, preact_hooks.useEffect)(() => {
607
+ if (focus.current && ref.current) {
608
+ if ((0, min_dash.isFunction)(ref.current.focus)) ref.current.focus();
609
+ if ((0, min_dash.isFunction)(ref.current.select)) ref.current.select();
610
+ focus.current = false;
611
+ }
612
+ });
613
+ useEvent("propertiesPanel.showEntry", onShowEntry);
614
+ return ref;
615
+ }
616
+ //#endregion
617
+ //#region src/hooks/useStickyIntersectionObserver.js
618
+ /**
619
+ * @callback setSticky
620
+ * @param {boolean} value
621
+ */
622
+ /**
623
+ * Use IntersectionObserver to identify when DOM element is in sticky mode.
624
+ * If sticky is observered setSticky(true) will be called.
625
+ * If sticky mode is left, setSticky(false) will be called.
626
+ *
627
+ *
628
+ * @param {Object} ref
629
+ * @param {string} scrollContainerSelector
630
+ * @param {setSticky} setSticky
631
+ */
632
+ function useStickyIntersectionObserver(ref, scrollContainerSelector, setSticky) {
633
+ const [scrollContainer, setScrollContainer] = (0, preact_hooks.useState)((0, min_dom.query)(scrollContainerSelector));
634
+ const updateScrollContainer = (0, preact_hooks.useCallback)(() => {
635
+ const newScrollContainer = (0, min_dom.query)(scrollContainerSelector);
636
+ if (newScrollContainer !== scrollContainer) setScrollContainer(newScrollContainer);
637
+ }, [scrollContainerSelector, scrollContainer]);
638
+ (0, preact_hooks.useEffect)(() => {
639
+ updateScrollContainer();
640
+ }, [updateScrollContainer]);
641
+ useEvent("propertiesPanel.attach", updateScrollContainer);
642
+ useEvent("propertiesPanel.detach", updateScrollContainer);
643
+ (0, preact_hooks.useEffect)(() => {
644
+ const Observer = IntersectionObserver;
645
+ if (!Observer) return;
646
+ if (!ref.current || !scrollContainer) return;
647
+ const observer = new Observer((entries) => {
648
+ if (scrollContainer.scrollHeight === 0) return;
649
+ entries.forEach((entry) => {
650
+ if (entry.intersectionRatio < 1) setSticky(true);
651
+ else if (entry.intersectionRatio === 1) setSticky(false);
652
+ });
653
+ }, {
654
+ root: scrollContainer,
655
+ rootMargin: "0px 0px 999999% 0px",
656
+ threshold: [1]
657
+ });
658
+ observer.observe(ref.current);
659
+ return () => {
660
+ observer.unobserve(ref.current);
661
+ };
662
+ }, [
663
+ ref.current,
664
+ scrollContainer,
665
+ setSticky
666
+ ]);
667
+ }
668
+ //#endregion
669
+ //#region src/hooks/useStaticCallback.js
670
+ /**
671
+ * Creates a static function reference with changing body.
672
+ * This is necessary when external libraries require a callback function
673
+ * that has references to state variables.
674
+ *
675
+ * Usage:
676
+ * const callback = useStaticCallback((val) => {val === currentState});
677
+ *
678
+ * The `callback` reference is static and can be safely used in external
679
+ * libraries or as a prop that does not cause rerendering of children.
680
+ *
681
+ * @param {Function} callback function with changing reference
682
+ * @returns {Function} static function reference
683
+ */
684
+ function useStaticCallback(callback) {
685
+ const callbackRef = (0, preact_hooks.useRef)(callback);
686
+ callbackRef.current = callback;
687
+ return (0, preact_hooks.useCallback)((...args) => callbackRef.current(...args), []);
688
+ }
689
+ //#endregion
690
+ //#region src/hooks/useElementVisible.js
691
+ function useElementVisible(element) {
692
+ const [visible, setVisible] = (0, preact_hooks.useState)(!!element && !!element.clientHeight);
693
+ (0, preact_hooks.useLayoutEffect)(() => {
694
+ if (!element) return;
695
+ const resizeObserver = new ResizeObserver(([entry]) => {
696
+ requestAnimationFrame(() => {
697
+ const newVisible = !!entry.contentRect.height;
698
+ if (newVisible !== visible) setVisible(newVisible);
699
+ });
700
+ });
701
+ resizeObserver.observe(element);
702
+ return () => resizeObserver.disconnect();
703
+ }, [element, visible]);
704
+ return visible;
705
+ }
706
+ //#endregion
707
+ //#region src/components/Group.js
708
+ /**
709
+ * @param {import('../PropertiesPanel').GroupDefinition} props
710
+ */
711
+ function Group(props) {
712
+ const { element, entries = [], id, label, shouldOpen = false } = props;
713
+ const groupRef = (0, preact_hooks.useRef)(null);
714
+ const [open, setOpen] = useLayoutState([
715
+ "groups",
716
+ id,
717
+ "open"
718
+ ], shouldOpen);
719
+ const onShow = (0, preact_hooks.useCallback)(() => setOpen(true), [setOpen]);
720
+ const toggleOpen = () => setOpen(!open);
721
+ const [edited, setEdited] = (0, preact_hooks.useState)(false);
722
+ const [sticky, setSticky] = (0, preact_hooks.useState)(false);
723
+ (0, preact_hooks.useEffect)(() => {
724
+ const scheduled = requestAnimationFrame(() => {
725
+ const hasOneEditedEntry = entries.find((entry) => {
726
+ const { id, isEdited } = entry;
727
+ const entryNode = (0, min_dom.query)(`[data-entry-id="${id}"]`);
728
+ if (!(0, min_dash.isFunction)(isEdited) || !entryNode) return false;
729
+ return isEdited((0, min_dom.query)(".bio-properties-panel-input", entryNode));
730
+ });
731
+ setEdited(hasOneEditedEntry);
732
+ });
733
+ return () => cancelAnimationFrame(scheduled);
734
+ }, [entries, setEdited]);
735
+ const allErrors = useErrors();
736
+ const hasErrors = entries.some((entry) => allErrors[entry.id]);
737
+ useStickyIntersectionObserver(groupRef, "div.bio-properties-panel-scroll-container", setSticky);
738
+ const propertiesPanelContext = {
739
+ ...(0, preact_hooks.useContext)(LayoutContext),
740
+ onShow
741
+ };
742
+ return (0, preact_jsx_runtime.jsxs)("div", {
743
+ class: "bio-properties-panel-group",
744
+ "data-group-id": "group-" + id,
745
+ ref: groupRef,
746
+ children: [(0, preact_jsx_runtime.jsxs)("div", {
747
+ class: (0, classnames.default)("bio-properties-panel-group-header", edited ? "" : "empty", open ? "open" : "", sticky && open ? "sticky" : ""),
748
+ onClick: toggleOpen,
749
+ children: [(0, preact_jsx_runtime.jsx)("div", {
750
+ class: "bio-properties-panel-group-header-title",
751
+ children: (0, preact_jsx_runtime.jsx)(TooltipWrapper, {
752
+ value: props.tooltip,
753
+ forId: "group-" + id,
754
+ element,
755
+ parent: groupRef,
756
+ children: label
757
+ })
758
+ }), (0, preact_jsx_runtime.jsxs)("div", {
759
+ class: "bio-properties-panel-group-header-buttons",
760
+ children: [(0, preact_jsx_runtime.jsx)(DataMarker, {
761
+ edited,
762
+ hasErrors
763
+ }), (0, preact_jsx_runtime.jsx)("button", {
764
+ type: "button",
765
+ title: "Toggle section",
766
+ class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
767
+ children: (0, preact_jsx_runtime.jsx)(ArrowIcon, { class: open ? "bio-properties-panel-arrow-down" : "bio-properties-panel-arrow-right" })
768
+ })]
769
+ })]
770
+ }), (0, preact_jsx_runtime.jsx)("div", {
771
+ class: (0, classnames.default)("bio-properties-panel-group-entries", open ? "open" : ""),
772
+ children: (0, preact_jsx_runtime.jsx)(LayoutContext.Provider, {
773
+ value: propertiesPanelContext,
774
+ children: entries.map((entry) => {
775
+ const { component: Component, id } = entry;
776
+ return (0, preact.createElement)(Component, {
777
+ ...entry,
778
+ element,
779
+ key: id
780
+ });
781
+ })
782
+ })
783
+ })]
784
+ });
785
+ }
786
+ function DataMarker(props) {
787
+ const { edited, hasErrors } = props;
788
+ if (hasErrors) return (0, preact_jsx_runtime.jsx)("div", {
789
+ title: "Section contains an error",
790
+ class: "bio-properties-panel-dot bio-properties-panel-dot--error"
791
+ });
792
+ if (edited) return (0, preact_jsx_runtime.jsx)("div", {
793
+ title: "Section contains edits",
794
+ class: "bio-properties-panel-dot"
795
+ });
796
+ return null;
797
+ }
798
+ //#endregion
799
+ //#region src/components/Placeholder.js
800
+ /**
801
+ * @typedef { {
802
+ * text: (element: object) => string,
803
+ * icon?: (element: Object) => import('preact').Component
804
+ * } } PlaceholderDefinition
805
+ *
806
+ * @param { PlaceholderDefinition } props
807
+ */
808
+ function Placeholder(props) {
809
+ const { text, icon: Icon } = props;
810
+ return (0, preact_jsx_runtime.jsx)("div", {
811
+ class: "bio-properties-panel open",
812
+ children: (0, preact_jsx_runtime.jsxs)("section", {
813
+ class: "bio-properties-panel-placeholder",
814
+ children: [Icon && (0, preact_jsx_runtime.jsx)(Icon, { class: "bio-properties-panel-placeholder-icon" }), (0, preact_jsx_runtime.jsx)("p", {
815
+ class: "bio-properties-panel-placeholder-text",
816
+ children: text
817
+ })]
818
+ })
819
+ });
820
+ }
821
+ //#endregion
822
+ //#region src/PropertiesPanel.js
823
+ var DEFAULT_LAYOUT = {};
824
+ var DEFAULT_DESCRIPTION = {};
825
+ var DEFAULT_TOOLTIP = {};
826
+ /**
827
+ * @typedef { {
828
+ * component: import('preact').Component,
829
+ * id: String,
830
+ * isEdited?: Function
831
+ * } } EntryDefinition
832
+ *
833
+ * @typedef { {
834
+ * autoFocusEntry: String,
835
+ * autoOpen?: Boolean,
836
+ * entries: Array<EntryDefinition>,
837
+ * id: String,
838
+ * label: String,
839
+ * remove: (event: MouseEvent) => void
840
+ * } } ListItemDefinition
841
+ *
842
+ * @typedef { {
843
+ * add: (event: MouseEvent) => void,
844
+ * component: import('preact').Component,
845
+ * element: Object,
846
+ * id: String,
847
+ * items: Array<ListItemDefinition>,
848
+ * label: String,
849
+ * shouldOpen?: Boolean
850
+ * } } ListGroupDefinition
851
+ *
852
+ * @typedef { {
853
+ * component?: import('preact').Component,
854
+ * entries: Array<EntryDefinition>,
855
+ * id: String,
856
+ * label: String,
857
+ * shouldOpen?: Boolean
858
+ * } } GroupDefinition
859
+ *
860
+ * @typedef { {
861
+ * [id: String]: GetDescriptionFunction
862
+ * } } DescriptionConfig
863
+ *
864
+ * @typedef { {
865
+ * [id: String]: GetTooltipFunction
866
+ * } } TooltipConfig
867
+ *
868
+ * @callback { {
869
+ * @param {string} id
870
+ * @param {Object} element
871
+ * @returns {string}
872
+ * } } GetDescriptionFunction
873
+ *
874
+ * @callback { {
875
+ * @param {string} id
876
+ * @param {Object} element
877
+ * @returns {string}
878
+ * } } GetTooltipFunction
879
+ *
880
+ * @typedef { {
881
+ * getEmpty: (element: object) => import('./components/Placeholder').PlaceholderDefinition,
882
+ * getMultiple: (element: Object) => import('./components/Placeholder').PlaceholderDefinition
883
+ * } } PlaceholderProvider
884
+ *
885
+ */
886
+ /**
887
+ * A basic properties panel component. Describes *how* content will be rendered, accepts
888
+ * data from implementor to describe *what* will be rendered.
889
+ *
890
+ * @param {Object} props
891
+ * @param {Object|Array} props.element
892
+ * @param {import('./components/Header').HeaderProvider} props.headerProvider
893
+ * @param {PlaceholderProvider} [props.placeholderProvider]
894
+ * @param {Array<GroupDefinition|ListGroupDefinition>} props.groups
895
+ * @param {Object} [props.layoutConfig]
896
+ * @param {Function} [props.layoutChanged]
897
+ * @param {DescriptionConfig} [props.descriptionConfig]
898
+ * @param {Function} [props.descriptionLoaded]
899
+ * @param {TooltipConfig} [props.tooltipConfig]
900
+ * @param {Function} [props.tooltipLoaded]
901
+ * @param {HTMLElement} [props.feelPopupContainer]
902
+ * @param {Function} [props.getFeelPopupLinks]
903
+ * @param {Object} [props.eventBus]
904
+ */
905
+ function PropertiesPanel(props) {
906
+ const { element, headerProvider, placeholderProvider, groups, layoutConfig, layoutChanged, descriptionConfig, descriptionLoaded, tooltipConfig, tooltipLoaded, eventBus } = props;
907
+ const [layout, setLayout] = (0, preact_hooks.useState)(createLayout(layoutConfig));
908
+ useUpdateLayoutEffect(() => {
909
+ const newLayout = createLayout(layoutConfig);
910
+ setLayout(newLayout);
911
+ }, [layoutConfig]);
912
+ (0, preact_hooks.useEffect)(() => {
913
+ if (typeof layoutChanged === "function") layoutChanged(layout);
914
+ }, [layout, layoutChanged]);
915
+ const getLayoutForKey = (key, defaultValue) => {
916
+ return (0, min_dash.get)(layout, key, defaultValue);
917
+ };
918
+ const setLayoutForKey = (key, config) => {
919
+ const newLayout = (0, min_dash.assign)({}, layout);
920
+ (0, min_dash.set)(newLayout, key, config);
921
+ setLayout(newLayout);
922
+ };
923
+ const layoutContext = {
924
+ layout,
925
+ setLayout,
926
+ getLayoutForKey,
927
+ setLayoutForKey
928
+ };
929
+ const description = (0, preact_hooks.useMemo)(() => createDescriptionContext(descriptionConfig), [descriptionConfig]);
930
+ (0, preact_hooks.useEffect)(() => {
931
+ if (typeof descriptionLoaded === "function") descriptionLoaded(description);
932
+ }, [description, descriptionLoaded]);
933
+ const getDescriptionForId = (id, element) => {
934
+ return description[id] && description[id](element);
935
+ };
936
+ const descriptionContext = {
937
+ description,
938
+ getDescriptionForId
939
+ };
940
+ const tooltip = (0, preact_hooks.useMemo)(() => createTooltipContext(tooltipConfig), [tooltipConfig]);
941
+ (0, preact_hooks.useEffect)(() => {
942
+ if (typeof tooltipLoaded === "function") tooltipLoaded(tooltip);
943
+ }, [tooltip, tooltipLoaded]);
944
+ const getTooltipForId = (id, element) => {
945
+ return tooltip[id] && tooltip[id](element);
946
+ };
947
+ const tooltipContext = {
948
+ tooltip,
949
+ getTooltipForId
950
+ };
951
+ const [errors, setErrors] = (0, preact_hooks.useState)({});
952
+ const onSetErrors = ({ errors }) => setErrors(errors);
953
+ useEvent("propertiesPanel.setErrors", onSetErrors, eventBus);
954
+ const errorsContext = { errors };
955
+ const eventContext = { eventBus };
956
+ const propertiesPanelContext = { element };
957
+ if (placeholderProvider && !element) return (0, preact_jsx_runtime.jsx)(Placeholder, { ...placeholderProvider.getEmpty() });
958
+ if (placeholderProvider && (0, min_dash.isArray)(element)) return (0, preact_jsx_runtime.jsx)(Placeholder, { ...placeholderProvider.getMultiple() });
959
+ return (0, preact_jsx_runtime.jsx)(LayoutContext.Provider, {
960
+ value: propertiesPanelContext,
961
+ children: (0, preact_jsx_runtime.jsx)(ErrorsContext.Provider, {
962
+ value: errorsContext,
963
+ children: (0, preact_jsx_runtime.jsx)(DescriptionContext.Provider, {
964
+ value: descriptionContext,
965
+ children: (0, preact_jsx_runtime.jsx)(TooltipContext.Provider, {
966
+ value: tooltipContext,
967
+ children: (0, preact_jsx_runtime.jsx)(LayoutContext.Provider, {
968
+ value: layoutContext,
969
+ children: (0, preact_jsx_runtime.jsx)(EventContext.Provider, {
970
+ value: eventContext,
971
+ children: (0, preact_jsx_runtime.jsxs)("div", {
972
+ class: "bio-properties-panel",
973
+ children: [(0, preact_jsx_runtime.jsx)(Header, {
974
+ element,
975
+ headerProvider
976
+ }), (0, preact_jsx_runtime.jsx)("div", {
977
+ class: "bio-properties-panel-scroll-container",
978
+ children: groups.map((group) => {
979
+ const { component: Component = Group, id } = group;
980
+ return (0, preact.createElement)(Component, {
981
+ ...group,
982
+ key: id,
983
+ element
984
+ });
985
+ })
986
+ })]
987
+ })
988
+ })
989
+ })
990
+ })
991
+ })
992
+ })
993
+ });
994
+ }
995
+ function createLayout(overrides = {}, defaults = DEFAULT_LAYOUT) {
996
+ return {
997
+ ...defaults,
998
+ ...overrides
999
+ };
1000
+ }
1001
+ function createDescriptionContext(overrides = {}) {
1002
+ return {
1003
+ ...DEFAULT_DESCRIPTION,
1004
+ ...overrides
1005
+ };
1006
+ }
1007
+ function createTooltipContext(overrides = {}) {
1008
+ return {
1009
+ ...DEFAULT_TOOLTIP,
1010
+ ...overrides
1011
+ };
1012
+ }
1013
+ /**
1014
+ * This hook behaves like useLayoutEffect, but does not trigger on the first render.
1015
+ *
1016
+ * @param {Function} effect
1017
+ * @param {Array} deps
1018
+ */
1019
+ function useUpdateLayoutEffect(effect, deps) {
1020
+ const isMounted = (0, preact_hooks.useRef)(false);
1021
+ (0, preact_hooks.useLayoutEffect)(() => {
1022
+ if (isMounted.current) return effect();
1023
+ else isMounted.current = true;
1024
+ }, deps);
1025
+ }
1026
+ //#endregion
1027
+ //#region src/components/DropdownButton.js
1028
+ /**
1029
+ *
1030
+ * @param {object} props
1031
+ * @param {string} [props.class]
1032
+ * @param {import('preact').Component[]} [props.menuItems]
1033
+ * @returns
1034
+ */
1035
+ function DropdownButton(props) {
1036
+ const { class: className, children, menuItems = [] } = props;
1037
+ const dropdownRef = (0, preact_hooks.useRef)(null);
1038
+ const menuRef = (0, preact_hooks.useRef)(null);
1039
+ const [open, setOpen] = (0, preact_hooks.useState)(false);
1040
+ const close = () => setOpen(false);
1041
+ function onDropdownToggle(event) {
1042
+ if (menuRef.current && menuRef.current.contains(event.target)) return;
1043
+ event.stopPropagation();
1044
+ setOpen((open) => !open);
1045
+ }
1046
+ function onActionClick(event, action) {
1047
+ event.stopPropagation();
1048
+ close();
1049
+ action();
1050
+ }
1051
+ useGlobalClick([dropdownRef.current], () => close());
1052
+ return (0, preact_jsx_runtime.jsxs)("div", {
1053
+ class: (0, classnames.default)("bio-properties-panel-dropdown-button", { open }, className),
1054
+ onClick: onDropdownToggle,
1055
+ ref: dropdownRef,
1056
+ children: [children, (0, preact_jsx_runtime.jsx)("div", {
1057
+ class: "bio-properties-panel-dropdown-button__menu",
1058
+ ref: menuRef,
1059
+ children: menuItems.map((item, index) => (0, preact_jsx_runtime.jsx)(MenuItem, {
1060
+ onClick: onActionClick,
1061
+ item
1062
+ }, index))
1063
+ })]
1064
+ });
1065
+ }
1066
+ function MenuItem({ item, onClick }) {
1067
+ if (item.separator) return (0, preact_jsx_runtime.jsx)("div", { class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--separator" });
1068
+ if (item.action) return (0, preact_jsx_runtime.jsx)("button", {
1069
+ type: "button",
1070
+ class: "bio-properties-panel-dropdown-button__menu-item bio-properties-panel-dropdown-button__menu-item--actionable",
1071
+ onClick: (event) => onClick(event, item.action),
1072
+ children: item.entry
1073
+ });
1074
+ return (0, preact_jsx_runtime.jsx)("div", {
1075
+ class: "bio-properties-panel-dropdown-button__menu-item",
1076
+ children: item.entry
1077
+ });
1078
+ }
1079
+ /**
1080
+ *
1081
+ * @param {Array<null | Element>} ignoredElements
1082
+ * @param {Function} callback
1083
+ */
1084
+ function useGlobalClick(ignoredElements, callback) {
1085
+ (0, preact_hooks.useEffect)(() => {
1086
+ /**
1087
+ * @param {MouseEvent} event
1088
+ */
1089
+ function listener(event) {
1090
+ if (ignoredElements.some((element) => element && element.contains(event.target))) return;
1091
+ callback();
1092
+ }
1093
+ document.addEventListener("click", listener, { capture: true });
1094
+ return () => document.removeEventListener("click", listener, { capture: true });
1095
+ }, [...ignoredElements, callback]);
1096
+ }
1097
+ //#endregion
1098
+ //#region src/components/HeaderButton.js
1099
+ function HeaderButton(props) {
1100
+ const { children = null, class: classname, onClick = () => {}, ...otherProps } = props;
1101
+ return (0, preact_jsx_runtime.jsx)("button", {
1102
+ type: "button",
1103
+ ...otherProps,
1104
+ onClick,
1105
+ class: (0, classnames.default)("bio-properties-panel-group-header-button", classname),
1106
+ children
1107
+ });
1108
+ }
1109
+ //#endregion
1110
+ //#region src/components/util/translateFallback.js
1111
+ /**
1112
+ * @typedef { {
1113
+ * [key: string]: string;
1114
+ * } } TranslateReplacements
1115
+ */
1116
+ /**
1117
+ * A simple translation stub to be used for multi-language support.
1118
+ * Can be easily replaced with a more sophisticated solution.
1119
+ *
1120
+ * @param {string} template to interpolate
1121
+ * @param {TranslateReplacements} [replacements] a map with substitutes
1122
+ *
1123
+ * @return {string} the translated string
1124
+ */
1125
+ function translateFallback(template, replacements) {
1126
+ replacements = replacements || {};
1127
+ return template.replace(/{([^}]+)}/g, function(_, key) {
1128
+ return replacements[key] || "{" + key + "}";
1129
+ });
1130
+ }
1131
+ //#endregion
1132
+ //#region src/components/entries/Collapsible.js
1133
+ function CollapsibleEntry(props) {
1134
+ const { element, entries = [], id, label, open: shouldOpen, remove, translate = translateFallback } = props;
1135
+ const [open, setOpen] = (0, preact_hooks.useState)(shouldOpen);
1136
+ const toggleOpen = () => setOpen(!open);
1137
+ const { onShow } = (0, preact_hooks.useContext)(LayoutContext);
1138
+ const propertiesPanelContext = {
1139
+ ...(0, preact_hooks.useContext)(LayoutContext),
1140
+ onShow: (0, preact_hooks.useCallback)(() => {
1141
+ setOpen(true);
1142
+ if ((0, min_dash.isFunction)(onShow)) onShow();
1143
+ }, [onShow, setOpen])
1144
+ };
1145
+ const placeholderLabel = translate("<empty>");
1146
+ return (0, preact_jsx_runtime.jsxs)("div", {
1147
+ "data-entry-id": id,
1148
+ class: (0, classnames.default)("bio-properties-panel-collapsible-entry", open ? "open" : ""),
1149
+ children: [(0, preact_jsx_runtime.jsxs)("div", {
1150
+ class: "bio-properties-panel-collapsible-entry-header",
1151
+ onClick: toggleOpen,
1152
+ children: [
1153
+ (0, preact_jsx_runtime.jsx)("div", {
1154
+ class: (0, classnames.default)("bio-properties-panel-collapsible-entry-header-title", !label && "empty"),
1155
+ children: label || placeholderLabel
1156
+ }),
1157
+ (0, preact_jsx_runtime.jsx)("button", {
1158
+ type: "button",
1159
+ title: translate("Toggle list item"),
1160
+ class: "bio-properties-panel-arrow bio-properties-panel-collapsible-entry-arrow",
1161
+ children: (0, preact_jsx_runtime.jsx)(ArrowIcon, { class: open ? "bio-properties-panel-arrow-down" : "bio-properties-panel-arrow-right" })
1162
+ }),
1163
+ remove ? (0, preact_jsx_runtime.jsx)("button", {
1164
+ type: "button",
1165
+ title: translate("Delete item"),
1166
+ class: "bio-properties-panel-remove-entry",
1167
+ onClick: remove,
1168
+ children: (0, preact_jsx_runtime.jsx)(DeleteIcon, {})
1169
+ }) : null
1170
+ ]
1171
+ }), (0, preact_jsx_runtime.jsx)("div", {
1172
+ class: (0, classnames.default)("bio-properties-panel-collapsible-entry-entries", open ? "open" : ""),
1173
+ children: (0, preact_jsx_runtime.jsx)(LayoutContext.Provider, {
1174
+ value: propertiesPanelContext,
1175
+ children: entries.map((entry) => {
1176
+ const { component: Component, id } = entry;
1177
+ return (0, preact.createElement)(Component, {
1178
+ ...entry,
1179
+ element,
1180
+ key: id
1181
+ });
1182
+ })
1183
+ })
1184
+ })]
1185
+ });
1186
+ }
1187
+ //#endregion
1188
+ //#region src/components/ListItem.js
1189
+ /**
1190
+ * @param {import('../PropertiesPanel').ListItemDefinition} props
1191
+ */
1192
+ function ListItem(props) {
1193
+ const { autoFocusEntry, autoOpen, translate = translateFallback } = props;
1194
+ (0, preact_hooks.useEffect)(() => {
1195
+ if (autoOpen && autoFocusEntry) {
1196
+ const entry = (0, min_dom.query)(`[data-entry-id="${autoFocusEntry}"]`);
1197
+ const focusableInput = (0, min_dom.query)(".bio-properties-panel-input", entry);
1198
+ if (focusableInput) {
1199
+ if ((0, min_dash.isFunction)(focusableInput.select)) focusableInput.select();
1200
+ else if ((0, min_dash.isFunction)(focusableInput.focus)) focusableInput.focus();
1201
+ focusableInput.scrollIntoView();
1202
+ }
1203
+ }
1204
+ }, [autoOpen, autoFocusEntry]);
1205
+ return (0, preact_jsx_runtime.jsx)("div", {
1206
+ class: "bio-properties-panel-list-item",
1207
+ children: (0, preact_jsx_runtime.jsx)(CollapsibleEntry, {
1208
+ ...props,
1209
+ open: autoOpen,
1210
+ translate
1211
+ })
1212
+ });
1213
+ }
1214
+ //#endregion
1215
+ //#region src/components/ListGroup.js
1216
+ var noop$6 = () => {};
1217
+ /**
1218
+ * @param {import('../PropertiesPanel').ListGroupDefinition} props
1219
+ */
1220
+ function ListGroup(props) {
1221
+ const { add, element, id, items, label, shouldOpen = false, translate = translateFallback } = props;
1222
+ (0, preact_hooks.useEffect)(() => {
1223
+ if (props.shouldSort != void 0) console.warn("the property 'shouldSort' is no longer supported");
1224
+ }, [props.shouldSort]);
1225
+ const groupRef = (0, preact_hooks.useRef)(null);
1226
+ const [open, setOpen] = useLayoutState([
1227
+ "groups",
1228
+ id,
1229
+ "open"
1230
+ ], shouldOpen);
1231
+ const [sticky, setSticky] = (0, preact_hooks.useState)(false);
1232
+ const onShow = (0, preact_hooks.useCallback)(() => setOpen(true), [setOpen]);
1233
+ const [localItems, setLocalItems] = (0, preact_hooks.useState)([]);
1234
+ const [addTriggered, setAddTriggered] = (0, preact_hooks.useState)(false);
1235
+ const prevElement = usePrevious(element);
1236
+ const toggleOpen = (0, preact_hooks.useCallback)(() => setOpen(!open), [open]);
1237
+ const openItemIds = element === prevElement && open && addTriggered ? getNewItemIds(items, localItems) : [];
1238
+ (0, preact_hooks.useEffect)(() => {
1239
+ setLocalItems(items);
1240
+ setAddTriggered(false);
1241
+ }, [items]);
1242
+ useStickyIntersectionObserver(groupRef, "div.bio-properties-panel-scroll-container", setSticky);
1243
+ const hasItems = !!items.length;
1244
+ const propertiesPanelContext = {
1245
+ ...(0, preact_hooks.useContext)(LayoutContext),
1246
+ onShow
1247
+ };
1248
+ const handleAddClick = (e) => {
1249
+ setAddTriggered(true);
1250
+ setOpen(true);
1251
+ add(e);
1252
+ };
1253
+ const allErrors = useErrors();
1254
+ const hasError = items.some((item) => {
1255
+ if (allErrors[item.id]) return true;
1256
+ if (!item.entries) return;
1257
+ return item.entries.some((entry) => allErrors[entry.id]);
1258
+ });
1259
+ return (0, preact_jsx_runtime.jsxs)("div", {
1260
+ class: "bio-properties-panel-group",
1261
+ "data-group-id": "group-" + id,
1262
+ ref: groupRef,
1263
+ children: [(0, preact_jsx_runtime.jsxs)("div", {
1264
+ class: (0, classnames.default)("bio-properties-panel-group-header", hasItems ? "" : "empty", hasItems && open ? "open" : "", sticky && open ? "sticky" : ""),
1265
+ onClick: hasItems ? toggleOpen : noop$6,
1266
+ children: [(0, preact_jsx_runtime.jsx)("div", {
1267
+ class: "bio-properties-panel-group-header-title",
1268
+ children: (0, preact_jsx_runtime.jsx)(TooltipWrapper, {
1269
+ value: props.tooltip,
1270
+ forId: "group-" + id,
1271
+ element,
1272
+ parent: groupRef,
1273
+ children: label
1274
+ })
1275
+ }), (0, preact_jsx_runtime.jsxs)("div", {
1276
+ class: "bio-properties-panel-group-header-buttons",
1277
+ children: [
1278
+ add ? (0, preact_jsx_runtime.jsxs)("button", {
1279
+ type: "button",
1280
+ title: translate("Create new list item"),
1281
+ class: "bio-properties-panel-group-header-button bio-properties-panel-add-entry",
1282
+ onClick: handleAddClick,
1283
+ children: [(0, preact_jsx_runtime.jsx)(CreateIcon, {}), !hasItems ? (0, preact_jsx_runtime.jsx)("span", {
1284
+ class: "bio-properties-panel-add-entry-label",
1285
+ children: translate("Create")
1286
+ }) : null]
1287
+ }) : null,
1288
+ hasItems ? (0, preact_jsx_runtime.jsx)("div", {
1289
+ title: translate(`List contains {numOfItems} item${items.length != 1 ? "s" : ""}`, { numOfItems: items.length }),
1290
+ class: (0, classnames.default)("bio-properties-panel-list-badge", hasError ? "bio-properties-panel-list-badge--error" : ""),
1291
+ children: items.length
1292
+ }) : null,
1293
+ hasItems ? (0, preact_jsx_runtime.jsx)("button", {
1294
+ type: "button",
1295
+ title: translate("Toggle section"),
1296
+ class: "bio-properties-panel-group-header-button bio-properties-panel-arrow",
1297
+ children: (0, preact_jsx_runtime.jsx)(ArrowIcon, { class: open ? "bio-properties-panel-arrow-down" : "bio-properties-panel-arrow-right" })
1298
+ }) : null
1299
+ ]
1300
+ })]
1301
+ }), (0, preact_jsx_runtime.jsx)("div", {
1302
+ class: (0, classnames.default)("bio-properties-panel-list", open && hasItems ? "open" : ""),
1303
+ children: (0, preact_jsx_runtime.jsx)(LayoutContext.Provider, {
1304
+ value: propertiesPanelContext,
1305
+ children: items.map((item, index) => {
1306
+ if (!item) return;
1307
+ const { id } = item;
1308
+ const autoOpen = openItemIds.includes(item.id);
1309
+ return (0, preact.createElement)(ListItem, {
1310
+ ...item,
1311
+ autoOpen,
1312
+ element,
1313
+ index,
1314
+ key: id,
1315
+ translate
1316
+ });
1317
+ })
1318
+ })
1319
+ })]
1320
+ });
1321
+ }
1322
+ function getNewItemIds(newItems, oldItems) {
1323
+ const newIds = newItems.map((item) => item.id);
1324
+ const oldIds = oldItems.map((item) => item.id);
1325
+ return newIds.filter((itemId) => !oldIds.includes(itemId));
1326
+ }
1327
+ //#endregion
1328
+ //#region src/components/entries/Description.js
1329
+ /**
1330
+ * @param {Object} props
1331
+ * @param {Object} props.element
1332
+ * @param {String} props.forId - id of the entry the description is used for
1333
+ * @param {String} props.value
1334
+ */
1335
+ function Description(props) {
1336
+ const { element, forId, value } = props;
1337
+ const contextDescription = useDescriptionContext(forId, element);
1338
+ const description = value || contextDescription;
1339
+ if (description) return (0, preact_jsx_runtime.jsx)("div", {
1340
+ class: "bio-properties-panel-description",
1341
+ children: description
1342
+ });
1343
+ }
1344
+ //#endregion
1345
+ //#region src/components/entries/Checkbox.js
1346
+ function Checkbox(props) {
1347
+ const { id, label, onChange, disabled, value = false, onFocus, onBlur, tooltip } = props;
1348
+ const [localValue, setLocalValue] = (0, preact_hooks.useState)(value);
1349
+ const handleChangeCallback = ({ target }) => {
1350
+ onChange(target.checked);
1351
+ };
1352
+ const handleChange = (e) => {
1353
+ handleChangeCallback(e);
1354
+ setLocalValue(e.target.value);
1355
+ };
1356
+ (0, preact_hooks.useEffect)(() => {
1357
+ if (value === localValue) return;
1358
+ setLocalValue(value);
1359
+ }, [value]);
1360
+ const ref = useShowEntryEvent(id);
1361
+ return (0, preact_jsx_runtime.jsxs)("div", {
1362
+ class: "bio-properties-panel-checkbox",
1363
+ children: [(0, preact_jsx_runtime.jsx)("input", {
1364
+ ref,
1365
+ id: prefixId$8(id),
1366
+ name: id,
1367
+ onFocus,
1368
+ onBlur,
1369
+ type: "checkbox",
1370
+ class: "bio-properties-panel-input",
1371
+ onChange: handleChange,
1372
+ checked: localValue,
1373
+ disabled
1374
+ }), (0, preact_jsx_runtime.jsx)("label", {
1375
+ for: prefixId$8(id),
1376
+ class: "bio-properties-panel-label",
1377
+ children: (0, preact_jsx_runtime.jsx)(TooltipWrapper, {
1378
+ value: tooltip,
1379
+ forId: id,
1380
+ element: props.element,
1381
+ children: label
1382
+ })
1383
+ })]
1384
+ });
1385
+ }
1386
+ /**
1387
+ * @param {Object} props
1388
+ * @param {Object} props.element
1389
+ * @param {String} props.id
1390
+ * @param {String} props.description
1391
+ * @param {String} props.label
1392
+ * @param {Function} props.getValue
1393
+ * @param {Function} props.setValue
1394
+ * @param {Function} props.onFocus
1395
+ * @param {Function} props.onBlur
1396
+ * @param {string|import('preact').Component} props.tooltip
1397
+ * @param {boolean} [props.disabled]
1398
+ */
1399
+ function CheckboxEntry(props) {
1400
+ const { element, id, description, label, getValue, setValue, disabled, onFocus, onBlur, tooltip } = props;
1401
+ const value = getValue(element);
1402
+ const error = useError(id);
1403
+ return (0, preact_jsx_runtime.jsxs)("div", {
1404
+ class: "bio-properties-panel-entry bio-properties-panel-checkbox-entry",
1405
+ "data-entry-id": id,
1406
+ children: [
1407
+ (0, preact_jsx_runtime.jsx)(Checkbox, {
1408
+ disabled,
1409
+ id,
1410
+ label,
1411
+ onChange: setValue,
1412
+ onFocus,
1413
+ onBlur,
1414
+ value,
1415
+ tooltip,
1416
+ element
1417
+ }, element),
1418
+ error && (0, preact_jsx_runtime.jsx)("div", {
1419
+ class: "bio-properties-panel-error",
1420
+ children: error
1421
+ }),
1422
+ (0, preact_jsx_runtime.jsx)(Description, {
1423
+ forId: id,
1424
+ element,
1425
+ value: description
1426
+ })
1427
+ ]
1428
+ });
1429
+ }
1430
+ function isEdited(node) {
1431
+ return node && !!node.checked;
1432
+ }
1433
+ function prefixId$8(id) {
1434
+ return `bio-properties-panel-${id}`;
1435
+ }
1436
+ //#endregion
1437
+ //#region src/components/entries/CheckboxGroup.js
1438
+ /**
1439
+ * @param {Object} props
1440
+ * @param {Object} props.element
1441
+ * @param {String} props.id
1442
+ * @param {String} props.label
1443
+ * @param {Array<{label: String, value: *}>} props.options
1444
+ * @param {Function} props.getValue
1445
+ * @param {Function} props.setValue
1446
+ * @param {String} [props.description]
1447
+ * @param {string|import('preact').Component} [props.tooltip]
1448
+ * @param {boolean} [props.disabled]
1449
+ * @param {Function} [props.onFocus]
1450
+ * @param {Function} [props.onBlur]
1451
+ */
1452
+ function CheckboxGroup(props) {
1453
+ const { element, id, label, description, tooltip, options = [], getValue, setValue, disabled, onFocus, onBlur } = props;
1454
+ const value = getValue(element) || [];
1455
+ const handleOptionChange = (optionValue, checked) => {
1456
+ const newValue = checked ? [...value, optionValue] : value.filter((v) => v !== optionValue);
1457
+ setValue(newValue);
1458
+ };
1459
+ return (0, preact_jsx_runtime.jsxs)("div", {
1460
+ class: "bio-properties-panel-entry bio-properties-panel-checkbox-group",
1461
+ "data-entry-id": id,
1462
+ children: [
1463
+ (0, preact_jsx_runtime.jsx)("div", {
1464
+ class: "bio-properties-panel-group-header",
1465
+ children: (0, preact_jsx_runtime.jsx)("p", {
1466
+ class: "bio-properties-panel-label",
1467
+ children: (0, preact_jsx_runtime.jsx)(TooltipWrapper, {
1468
+ value: tooltip,
1469
+ forId: id,
1470
+ element,
1471
+ children: label
1472
+ })
1473
+ })
1474
+ }),
1475
+ (0, preact_jsx_runtime.jsx)("div", {
1476
+ class: "bio-properties-panel-checkbox-group-entries",
1477
+ children: options.map((option) => (0, preact_jsx_runtime.jsx)(CheckboxEntry, {
1478
+ id: `${id}-${option.value}`,
1479
+ label: option.label,
1480
+ setValue: (checked) => handleOptionChange(option.value, checked),
1481
+ getValue: () => value.includes(option.value),
1482
+ disabled,
1483
+ onFocus,
1484
+ onBlur,
1485
+ element
1486
+ }, option.value))
1487
+ }),
1488
+ (0, preact_jsx_runtime.jsx)(Description, {
1489
+ forId: id,
1490
+ element,
1491
+ value: description
1492
+ })
1493
+ ]
1494
+ });
1495
+ }
1496
+ //#endregion
1497
+ //#region src/components/entries/JsonEditor.js
1498
+ var ExternalChange = _codemirror_state.Annotation.define();
1499
+ var parseJsonLinter = (0, _codemirror_lang_json.jsonParseLinter)();
1500
+ /**
1501
+ * A CodeMirror based JSON editor for the properties panel.
1502
+ *
1503
+ * @param {object} props
1504
+ * @param {string} props.id
1505
+ * @param {string} props.label
1506
+ * @param {string} [props.value]
1507
+ * @param {Function} props.onInput
1508
+ * @param {boolean} [props.disabled]
1509
+ * @param {string} [props.placeholder]
1510
+ * @param {string} [props.tooltip]
1511
+ * @param {object} [props.element]
1512
+ */
1513
+ function JsonEditor(props) {
1514
+ const { id, label, debounce, value = "", onInput: commitValue, disabled, placeholder, tooltip, element } = props;
1515
+ const containerRef = (0, preact_hooks.useRef)(null);
1516
+ const viewRef = (0, preact_hooks.useRef)(null);
1517
+ const editorRef = useShowEntryEvent(id);
1518
+ const handleChange = useDebounce(useStaticCallback((newValue) => {
1519
+ commitValue(newValue === "" ? void 0 : newValue);
1520
+ }), debounce);
1521
+ (0, preact_hooks.useEffect)(() => {
1522
+ const view = new _codemirror_view.EditorView({
1523
+ state: _codemirror_state.EditorState.create({
1524
+ doc: value,
1525
+ extensions: [
1526
+ (0, _codemirror_view.highlightSpecialChars)(),
1527
+ (0, _codemirror_commands.history)(),
1528
+ (0, _codemirror_view.drawSelection)(),
1529
+ (0, _codemirror_language.syntaxHighlighting)(_codemirror_language.defaultHighlightStyle, { fallback: true }),
1530
+ (0, _codemirror_language.foldGutter)(),
1531
+ (0, _codemirror_language.bracketMatching)(),
1532
+ (0, _codemirror_autocomplete.closeBrackets)(),
1533
+ _codemirror_view.keymap.of([
1534
+ ..._codemirror_commands.defaultKeymap,
1535
+ ..._codemirror_commands.historyKeymap,
1536
+ ..._codemirror_autocomplete.closeBracketsKeymap,
1537
+ ..._codemirror_language.foldKeymap
1538
+ ]),
1539
+ _codemirror_state.EditorState.tabSize.of(2),
1540
+ _codemirror_view.EditorView.lineWrapping,
1541
+ _codemirror_state.EditorState.readOnly.of(!!disabled),
1542
+ ...placeholder ? [(0, _codemirror_view.placeholder)(placeholder)] : [],
1543
+ _codemirror_view.EditorView.updateListener.of((update) => {
1544
+ const isExternal = update.transactions.some((tr) => tr.annotation(ExternalChange));
1545
+ if (update.docChanged && !isExternal) handleChange(update.state.doc.toString());
1546
+ }),
1547
+ (0, _codemirror_lang_json.json)(),
1548
+ (0, _codemirror_lint.linter)((view) => {
1549
+ if (!view.state.doc.toString().trim()) return [];
1550
+ return parseJsonLinter(view);
1551
+ }, { delay: 300 })
1552
+ ]
1553
+ }),
1554
+ parent: containerRef.current
1555
+ });
1556
+ viewRef.current = view;
1557
+ editorRef.current = view.contentDOM;
1558
+ const prefixedId = `bio-properties-panel-${id}`;
1559
+ view.contentDOM.setAttribute("id", prefixedId);
1560
+ view.contentDOM.setAttribute("aria-label", label);
1561
+ return () => {
1562
+ view.destroy();
1563
+ };
1564
+ }, []);
1565
+ (0, preact_hooks.useEffect)(() => {
1566
+ const view = viewRef.current;
1567
+ if (!view) return;
1568
+ const currentValue = view.state.doc.toString();
1569
+ if (value === currentValue) return;
1570
+ view.dispatch({
1571
+ changes: {
1572
+ from: 0,
1573
+ to: currentValue.length,
1574
+ insert: value || ""
1575
+ },
1576
+ annotations: ExternalChange.of(true)
1577
+ });
1578
+ }, [value]);
1579
+ const focusEditor = () => {
1580
+ viewRef.current && viewRef.current.focus();
1581
+ };
1582
+ return (0, preact_jsx_runtime.jsxs)("div", {
1583
+ class: "bio-properties-panel-json-editor",
1584
+ children: [(0, preact_jsx_runtime.jsx)("label", {
1585
+ class: "bio-properties-panel-label",
1586
+ onClick: focusEditor,
1587
+ children: (0, preact_jsx_runtime.jsx)(TooltipWrapper, {
1588
+ value: tooltip,
1589
+ forId: id,
1590
+ element,
1591
+ children: label
1592
+ })
1593
+ }), (0, preact_jsx_runtime.jsx)("div", {
1594
+ class: (0, classnames.default)("bio-properties-panel-input", value && "edited"),
1595
+ ref: containerRef
1596
+ })]
1597
+ });
1598
+ }
1599
+ /**
1600
+ * Entry wrapper for JsonEditor, handles getValue/setValue, built-in JSON validation, error display, and description.
1601
+ *
1602
+ * @param {object} props
1603
+ * @param {object} props.element
1604
+ * @param {string} props.id
1605
+ * @param {string} [props.description]
1606
+ * @param {string} props.label
1607
+ * @param {Function} props.debounce
1608
+ * @param {Function} props.getValue
1609
+ * @param {Function} props.setValue
1610
+ * @param {boolean} [props.disabled]
1611
+ * @param {string} [props.placeholder]
1612
+ * @param {string} [props.tooltip]
1613
+ * @param {Function} [props.validate]
1614
+ * @param {Function} [props.translate]
1615
+ */
1616
+ function JsonEditorEntry(props) {
1617
+ const { element, id, description, debounce, label, getValue, setValue, disabled, placeholder, tooltip, validate, translate = translateFallback } = props;
1618
+ const globalError = useError(id);
1619
+ let value = getValue(element);
1620
+ const [localError, setLocalError] = (0, preact_hooks.useState)(() => computeError(validate, value, translate));
1621
+ const [editorValue, setEditorValue] = (0, preact_hooks.useState)(value);
1622
+ (0, preact_hooks.useEffect)(() => {
1623
+ if (value === editorValue) return;
1624
+ setEditorValue(value);
1625
+ setLocalError(computeError(validate, value, translate));
1626
+ }, [value, validate]);
1627
+ const onInput = useStaticCallback((newValue) => {
1628
+ setEditorValue(newValue);
1629
+ if (newValue !== getValue(element)) {
1630
+ const newValidationError = computeError(validate, newValue, translate);
1631
+ setValue(newValue, newValidationError);
1632
+ setLocalError(newValidationError);
1633
+ }
1634
+ });
1635
+ const error = globalError || localError;
1636
+ return (0, preact_jsx_runtime.jsxs)("div", {
1637
+ class: (0, classnames.default)("bio-properties-panel-entry", error && "has-error"),
1638
+ "data-entry-id": id,
1639
+ children: [
1640
+ (0, preact_jsx_runtime.jsx)(JsonEditor, {
1641
+ id,
1642
+ label,
1643
+ debounce,
1644
+ value,
1645
+ onInput,
1646
+ disabled,
1647
+ placeholder,
1648
+ tooltip,
1649
+ element
1650
+ }, element),
1651
+ error && (0, preact_jsx_runtime.jsx)("div", {
1652
+ class: "bio-properties-panel-error",
1653
+ children: error
1654
+ }),
1655
+ (0, preact_jsx_runtime.jsx)(Description, {
1656
+ forId: id,
1657
+ element,
1658
+ value: description
1659
+ })
1660
+ ]
1661
+ });
1662
+ }
1663
+ /**
1664
+ * Check if the JSON editor entry has been edited.
1665
+ */
1666
+ function isEdited$2(node) {
1667
+ return node && node.classList.contains("edited");
1668
+ }
1669
+ function computeError(validate, value, translate) {
1670
+ return ((0, min_dash.isFunction)(validate) ? validate(value) : null) || validateJson(value, translate);
1671
+ }
1672
+ function validateJson(value, translate = translateFallback) {
1673
+ if (!value || !value.trim()) return null;
1674
+ try {
1675
+ return (0, min_dash.isObject)(JSON.parse(value)) ? null : translate("JSON contains errors");
1676
+ } catch (e) {
1677
+ return translate("JSON contains errors");
1678
+ }
1679
+ }
1680
+ //#endregion
1681
+ //#region src/components/OpenPopupButton.js
1682
+ /**
1683
+ * Button to open popups.
1684
+ *
1685
+ * @param {Object} props
1686
+ * @param {Function} props.onClick - Callback to trigger when the button is clicked.
1687
+ * @param {string} [props.title] - Tooltip text for the button.
1688
+ * @param {boolean} [props.disabled] - Whether the button is disabled.
1689
+ * @param {string} [props.className] - Additional class names for the button.
1690
+ */
1691
+ function OpenPopupButton({ onClick, title = "Open pop-up editor" }) {
1692
+ return (0, preact_jsx_runtime.jsx)("button", {
1693
+ type: "button",
1694
+ title,
1695
+ class: "bio-properties-panel-open-feel-popup",
1696
+ onClick,
1697
+ children: (0, preact_jsx_runtime.jsx)(OpenPopupIcon, {})
1698
+ });
1699
+ }
1700
+ //#endregion
1701
+ //#region src/components/entries/templating/TemplatingEditor.js
1702
+ var noop$5 = () => {};
1703
+ /**
1704
+ * Buffer `.focus()` calls while the editor is not initialized.
1705
+ * Set Focus inside when the editor is ready.
1706
+ */
1707
+ var useBufferedFocus$1 = function(editor, ref) {
1708
+ const [buffer, setBuffer] = (0, preact_hooks.useState)(void 0);
1709
+ ref.current = (0, preact_hooks.useMemo)(() => ({ focus: (offset) => {
1710
+ if (editor) editor.focus(offset);
1711
+ else {
1712
+ if (typeof offset === "undefined") offset = Infinity;
1713
+ setBuffer(offset);
1714
+ }
1715
+ } }), [editor]);
1716
+ (0, preact_hooks.useEffect)(() => {
1717
+ if (typeof buffer !== "undefined" && editor) {
1718
+ editor.focus(buffer);
1719
+ setBuffer(false);
1720
+ }
1721
+ }, [editor, buffer]);
1722
+ };
1723
+ var TemplatingEditor = (0, preact_compat.forwardRef)((props, ref) => {
1724
+ const { onInput, disabled, tooltipContainer, enableGutters, value, onLint = noop$5, onOpenPopup = noop$5, popupOpen, contentAttributes = {}, hostLanguage = null, singleLine = false } = props;
1725
+ const inputRef = (0, preact_hooks.useRef)();
1726
+ const [editor, setEditor] = (0, preact_hooks.useState)();
1727
+ const [localValue, setLocalValue] = (0, preact_hooks.useState)(value || "");
1728
+ useBufferedFocus$1(editor, ref);
1729
+ const handleInput = useStaticCallback((newValue) => {
1730
+ onInput(newValue);
1731
+ setLocalValue(newValue);
1732
+ });
1733
+ (0, preact_hooks.useEffect)(() => {
1734
+ let editor;
1735
+ editor = new _kunpeng_js_expression_editor.ExpressionEditor({
1736
+ container: inputRef.current,
1737
+ onChange: handleInput,
1738
+ value: localValue,
1739
+ onLint,
1740
+ contentAttributes,
1741
+ tooltipContainer,
1742
+ enableGutters,
1743
+ hostLanguage,
1744
+ singleLine,
1745
+ lineWrap: true
1746
+ });
1747
+ setEditor(editor);
1748
+ return () => {
1749
+ onLint([]);
1750
+ inputRef.current.innerHTML = "";
1751
+ setEditor(null);
1752
+ };
1753
+ }, []);
1754
+ (0, preact_hooks.useEffect)(() => {
1755
+ if (!editor) return;
1756
+ if (value === localValue) return;
1757
+ editor.setValue(value);
1758
+ setLocalValue(value);
1759
+ }, [value]);
1760
+ const handleClick = () => {
1761
+ ref.current.focus();
1762
+ };
1763
+ return (0, preact_jsx_runtime.jsxs)("div", {
1764
+ class: (0, classnames.default)("bio-properties-panel-feelers-editor-container", popupOpen ? "popupOpen" : null),
1765
+ children: [
1766
+ popupOpen && (0, preact_jsx_runtime.jsx)("div", {
1767
+ class: "bio-properties-panel-feelers-editor__popup-placeholder",
1768
+ children: "Opened in popup"
1769
+ }),
1770
+ (0, preact_jsx_runtime.jsx)("div", {
1771
+ name: props.name,
1772
+ class: (0, classnames.default)("bio-properties-panel-feelers-editor bio-properties-panel-input", localValue ? "edited" : null, disabled ? "disabled" : null),
1773
+ ref: inputRef,
1774
+ onClick: handleClick
1775
+ }),
1776
+ !disabled && (0, preact_jsx_runtime.jsx)(OpenPopupButton, { onClick: () => onOpenPopup("feelers") })
1777
+ ]
1778
+ });
1779
+ });
1780
+ //#endregion
1781
+ //#region src/components/entries/expression/ExpressionEditor.js
1782
+ var noop$4 = () => {};
1783
+ /**
1784
+ * Buffer `.focus()` calls while the editor is not initialized.
1785
+ * Set Focus inside when the editor is ready.
1786
+ */
1787
+ var useBufferedFocus = function(editor, ref) {
1788
+ const [buffer, setBuffer] = (0, preact_hooks.useState)(void 0);
1789
+ ref.current = (0, preact_hooks.useMemo)(() => ({ focus: (offset) => {
1790
+ if (editor) editor.focus(offset);
1791
+ else {
1792
+ if (typeof offset === "undefined") offset = Infinity;
1793
+ setBuffer(offset);
1794
+ }
1795
+ } }), [editor]);
1796
+ (0, preact_hooks.useEffect)(() => {
1797
+ if (typeof buffer !== "undefined" && editor) {
1798
+ editor.focus(buffer);
1799
+ setBuffer(false);
1800
+ }
1801
+ }, [editor, buffer]);
1802
+ };
1803
+ var ExpressionEditor = (0, preact_compat.forwardRef)((props, ref) => {
1804
+ const { contentAttributes, enableGutters, value, onInput, onKeyDown: onKeyDownProp = noop$4, onFeelToggle = noop$4, onLint = noop$4, onOpenPopup = noop$4, placeholder, popupOpen, disabled, tooltipContainer, variables, feelLanguageContext } = props;
1805
+ const inputRef = (0, preact_hooks.useRef)();
1806
+ const [editor, setEditor] = (0, preact_hooks.useState)();
1807
+ const [localValue, setLocalValue] = (0, preact_hooks.useState)(value || "");
1808
+ const { builtins, dialect, parserDialect } = feelLanguageContext || {};
1809
+ useBufferedFocus(editor, ref);
1810
+ const handleInput = useStaticCallback((newValue) => {
1811
+ onInput(newValue);
1812
+ setLocalValue(newValue);
1813
+ });
1814
+ (0, preact_hooks.useEffect)(() => {
1815
+ let editor;
1816
+ const onKeyDown = (e) => {
1817
+ onKeyDownProp(e);
1818
+ if (e.key !== "Backspace" || !editor) return;
1819
+ const selection = editor.getSelection();
1820
+ const range = selection.ranges[selection.mainIndex];
1821
+ if (range.from === 0 && range.to === 0) onFeelToggle();
1822
+ };
1823
+ editor = new _kunpeng_js_expression_editor.default({
1824
+ container: inputRef.current,
1825
+ onChange: handleInput,
1826
+ onKeyDown,
1827
+ onLint,
1828
+ placeholder,
1829
+ tooltipContainer,
1830
+ value: localValue,
1831
+ variables,
1832
+ builtins,
1833
+ dialect,
1834
+ parserDialect,
1835
+ extensions: [...enableGutters ? [(0, _codemirror_view.lineNumbers)()] : [], _codemirror_view.EditorView.lineWrapping],
1836
+ contentAttributes
1837
+ });
1838
+ setEditor(editor);
1839
+ return () => {
1840
+ onLint([]);
1841
+ inputRef.current.innerHTML = "";
1842
+ setEditor(null);
1843
+ };
1844
+ }, []);
1845
+ (0, preact_hooks.useEffect)(() => {
1846
+ if (!editor) return;
1847
+ if (value === localValue) return;
1848
+ editor.setValue(value);
1849
+ setLocalValue(value);
1850
+ }, [value]);
1851
+ (0, preact_hooks.useEffect)(() => {
1852
+ if (!editor) return;
1853
+ editor.setVariables(variables);
1854
+ }, [variables]);
1855
+ (0, preact_hooks.useEffect)(() => {
1856
+ if (!editor) return;
1857
+ editor.setPlaceholder(placeholder);
1858
+ }, [placeholder]);
1859
+ const handleClick = () => {
1860
+ ref.current.focus();
1861
+ };
1862
+ return (0, preact_jsx_runtime.jsxs)("div", {
1863
+ class: (0, classnames.default)("bio-properties-panel-feel-editor-container", disabled ? "disabled" : null, popupOpen ? "popupOpen" : null),
1864
+ children: [
1865
+ popupOpen && (0, preact_jsx_runtime.jsx)("div", {
1866
+ class: "bio-properties-panel-feel-editor__open-popup-placeholder",
1867
+ children: "Opened in editor"
1868
+ }),
1869
+ (0, preact_jsx_runtime.jsx)("div", {
1870
+ name: props.name,
1871
+ class: (0, classnames.default)("bio-properties-panel-input", localValue ? "edited" : null),
1872
+ ref: inputRef,
1873
+ onClick: handleClick
1874
+ }),
1875
+ !disabled && (0, preact_jsx_runtime.jsx)(OpenPopupButton, { onClick: () => onOpenPopup("feel") })
1876
+ ]
1877
+ });
1878
+ });
1879
+ //#endregion
1880
+ //#region src/components/entries/expression/ExpressionIndicator.js
1881
+ function ExpressionIndicator(props) {
1882
+ const { active } = props;
1883
+ if (!active) return null;
1884
+ return (0, preact_jsx_runtime.jsx)("span", {
1885
+ class: "bio-properties-panel-expression-indicator",
1886
+ children: "="
1887
+ });
1888
+ }
1889
+ //#endregion
1890
+ //#region src/components/entries/expression/ExpressionIcon.js
1891
+ var noop$3 = () => {};
1892
+ /**
1893
+ * @param {Object} props
1894
+ * @param {Object} props.label
1895
+ * @param {String} props.feel
1896
+ */
1897
+ function ExpressionIcon(props) {
1898
+ const { feel = false, active, disabled = false, onClick = noop$3 } = props;
1899
+ const feelRequiredLabel = "Expression expression is mandatory";
1900
+ const feelOptionalLabel = `Click to ${active ? "remove" : "set a"} dynamic value with FEEL expression`;
1901
+ const handleClick = (e) => {
1902
+ onClick(e);
1903
+ if (!e.pointerType) e.stopPropagation();
1904
+ };
1905
+ return (0, preact_jsx_runtime.jsx)("button", {
1906
+ type: "button",
1907
+ class: (0, classnames.default)("bio-properties-panel-feel-icon", active ? "active" : null, feel === "required" ? "required" : "optional"),
1908
+ onClick: handleClick,
1909
+ disabled: feel === "required" || disabled,
1910
+ title: feel === "required" ? feelRequiredLabel : feelOptionalLabel,
1911
+ children: (0, preact_jsx_runtime.jsx)(FeelIcon, {})
1912
+ });
1913
+ }
1914
+ //#endregion
1915
+ //#region src/components/util/keyboardUtils.js
1916
+ /**
1917
+ * @param {KeyboardEvent} event
1918
+ * @return {boolean}
1919
+ */
1920
+ function isCmd(event) {
1921
+ if (event.altKey) return false;
1922
+ return event.ctrlKey || event.metaKey;
1923
+ }
1924
+ function isCmdWithChar(event) {
1925
+ return isCmd(event) && event.key.length === 1 && /^[a-zA-Z]$/.test(event.key);
1926
+ }
1927
+ //#endregion
1928
+ //#region src/components/entries/ToggleSwitch.js
1929
+ function ToggleSwitch(props) {
1930
+ const { id, label, onInput, value, switcherLabel, inline, onFocus, onBlur, inputRef, tooltip } = props;
1931
+ const [localValue, setLocalValue] = (0, preact_hooks.useState)(value);
1932
+ const handleInputCallback = async () => {
1933
+ onInput(!value);
1934
+ };
1935
+ const handleInput = (e) => {
1936
+ handleInputCallback(e);
1937
+ setLocalValue(e.target.value);
1938
+ };
1939
+ (0, preact_hooks.useEffect)(() => {
1940
+ if (value === localValue) return;
1941
+ setLocalValue(value);
1942
+ }, [value]);
1943
+ return (0, preact_jsx_runtime.jsxs)("div", {
1944
+ class: (0, classnames.default)("bio-properties-panel-toggle-switch", { inline }),
1945
+ children: [(0, preact_jsx_runtime.jsx)("label", {
1946
+ class: "bio-properties-panel-label",
1947
+ for: prefixId$7(id),
1948
+ children: (0, preact_jsx_runtime.jsx)(TooltipWrapper, {
1949
+ value: tooltip,
1950
+ forId: id,
1951
+ element: props.element,
1952
+ children: label
1953
+ })
1954
+ }), (0, preact_jsx_runtime.jsxs)("div", {
1955
+ class: "bio-properties-panel-field-wrapper",
1956
+ children: [(0, preact_jsx_runtime.jsxs)("label", {
1957
+ class: "bio-properties-panel-toggle-switch__switcher",
1958
+ children: [(0, preact_jsx_runtime.jsx)("input", {
1959
+ ref: inputRef,
1960
+ id: prefixId$7(id),
1961
+ class: "bio-properties-panel-input",
1962
+ type: "checkbox",
1963
+ onFocus,
1964
+ onBlur,
1965
+ name: id,
1966
+ onInput: handleInput,
1967
+ checked: !!localValue
1968
+ }), (0, preact_jsx_runtime.jsx)("span", { class: "bio-properties-panel-toggle-switch__slider" })]
1969
+ }), switcherLabel && (0, preact_jsx_runtime.jsx)("p", {
1970
+ class: "bio-properties-panel-toggle-switch__label",
1971
+ children: switcherLabel
1972
+ })]
1973
+ })]
1974
+ });
1975
+ }
1976
+ /**
1977
+ * @param {Object} props
1978
+ * @param {Object} props.element
1979
+ * @param {String} props.id
1980
+ * @param {String} props.description
1981
+ * @param {String} props.label
1982
+ * @param {String} props.switcherLabel
1983
+ * @param {Boolean} props.inline
1984
+ * @param {Function} props.getValue
1985
+ * @param {Function} props.setValue
1986
+ * @param {Function} props.onFocus
1987
+ * @param {Function} props.onBlur
1988
+ * @param {string|import('preact').Component} props.tooltip
1989
+ */
1990
+ function ToggleSwitchEntry(props) {
1991
+ const { element, id, description, label, switcherLabel, inline, getValue, setValue, onFocus, onBlur, tooltip } = props;
1992
+ const value = getValue(element);
1993
+ return (0, preact_jsx_runtime.jsxs)("div", {
1994
+ class: "bio-properties-panel-entry bio-properties-panel-toggle-switch-entry",
1995
+ "data-entry-id": id,
1996
+ children: [(0, preact_jsx_runtime.jsx)(ToggleSwitch, {
1997
+ id,
1998
+ label,
1999
+ value,
2000
+ onInput: setValue,
2001
+ onFocus,
2002
+ onBlur,
2003
+ switcherLabel,
2004
+ inline,
2005
+ tooltip,
2006
+ element
2007
+ }), (0, preact_jsx_runtime.jsx)(Description, {
2008
+ forId: id,
2009
+ element,
2010
+ value: description
2011
+ })]
2012
+ });
2013
+ }
2014
+ function isEdited$9(node) {
2015
+ return node && !!node.checked;
2016
+ }
2017
+ function prefixId$7(id) {
2018
+ return `bio-properties-panel-${id}`;
2019
+ }
2020
+ //#endregion
2021
+ //#region src/components/entries/NumberField.js
2022
+ function NumberField(props) {
2023
+ const { debounce, disabled, displayLabel = true, id, inputRef, label, max, min, onInput, step, value = "", onFocus, onBlur, tooltip } = props;
2024
+ const [localValue, setLocalValue] = (0, preact_hooks.useState)(value);
2025
+ const handleInputCallback = (0, preact_hooks.useMemo)(() => {
2026
+ return debounce((target) => {
2027
+ if (target.validity.valid) onInput(target.value ? parseFloat(target.value) : void 0);
2028
+ });
2029
+ }, [onInput, debounce]);
2030
+ const handleInput = (e) => {
2031
+ handleInputCallback(e.target);
2032
+ setLocalValue(e.target.value);
2033
+ };
2034
+ (0, preact_hooks.useEffect)(() => {
2035
+ if (value === localValue) return;
2036
+ setLocalValue(value);
2037
+ }, [value]);
2038
+ return (0, preact_jsx_runtime.jsxs)("div", {
2039
+ class: "bio-properties-panel-numberfield",
2040
+ children: [displayLabel && (0, preact_jsx_runtime.jsx)("label", {
2041
+ for: prefixId$6(id),
2042
+ class: "bio-properties-panel-label",
2043
+ children: (0, preact_jsx_runtime.jsx)(TooltipWrapper, {
2044
+ value: tooltip,
2045
+ forId: id,
2046
+ element: props.element,
2047
+ children: label
2048
+ })
2049
+ }), (0, preact_jsx_runtime.jsx)("input", {
2050
+ id: prefixId$6(id),
2051
+ ref: inputRef,
2052
+ type: "number",
2053
+ name: id,
2054
+ spellCheck: "false",
2055
+ autoComplete: "off",
2056
+ disabled,
2057
+ class: "bio-properties-panel-input",
2058
+ max,
2059
+ min,
2060
+ onInput: handleInput,
2061
+ onFocus,
2062
+ onBlur,
2063
+ step,
2064
+ value: localValue
2065
+ })]
2066
+ });
2067
+ }
2068
+ /**
2069
+ * @param {Object} props
2070
+ * @param {Boolean} props.debounce
2071
+ * @param {String} props.description
2072
+ * @param {Boolean} props.disabled
2073
+ * @param {Object} props.element
2074
+ * @param {Function} props.getValue
2075
+ * @param {String} props.id
2076
+ * @param {String} props.label
2077
+ * @param {String} props.max
2078
+ * @param {String} props.min
2079
+ * @param {Function} props.setValue
2080
+ * @param {Function} props.onFocus
2081
+ * @param {Function} props.onBlur
2082
+ * @param {String} props.step
2083
+ * @param {Function} props.validate
2084
+ */
2085
+ function NumberFieldEntry(props) {
2086
+ const { debounce, description, disabled, element, getValue, id, label, max, min, setValue, step, onFocus, onBlur, validate, tooltip } = props;
2087
+ const globalError = useError(id);
2088
+ const [localError, setLocalError] = (0, preact_hooks.useState)(null);
2089
+ let value = getValue(element);
2090
+ (0, preact_hooks.useEffect)(() => {
2091
+ if ((0, min_dash.isFunction)(validate)) {
2092
+ const newValidationError = validate(value) || null;
2093
+ setLocalError(newValidationError);
2094
+ }
2095
+ }, [value, validate]);
2096
+ const onInput = (newValue) => {
2097
+ let newValidationError = null;
2098
+ if ((0, min_dash.isFunction)(validate)) newValidationError = validate(newValue) || null;
2099
+ setValue(newValue, newValidationError);
2100
+ setLocalError(newValidationError);
2101
+ };
2102
+ const error = globalError || localError;
2103
+ return (0, preact_jsx_runtime.jsxs)("div", {
2104
+ class: (0, classnames.default)("bio-properties-panel-entry", error ? "has-error" : ""),
2105
+ "data-entry-id": id,
2106
+ children: [
2107
+ (0, preact_jsx_runtime.jsx)(NumberField, {
2108
+ debounce,
2109
+ disabled,
2110
+ id,
2111
+ label,
2112
+ onFocus,
2113
+ onBlur,
2114
+ onInput,
2115
+ max,
2116
+ min,
2117
+ step,
2118
+ value,
2119
+ tooltip
2120
+ }, element),
2121
+ error && (0, preact_jsx_runtime.jsx)("div", {
2122
+ class: "bio-properties-panel-error",
2123
+ children: error
2124
+ }),
2125
+ (0, preact_jsx_runtime.jsx)(Description, {
2126
+ forId: id,
2127
+ element,
2128
+ value: description
2129
+ })
2130
+ ]
2131
+ });
2132
+ }
2133
+ function isEdited$3(node) {
2134
+ return node && !!node.value;
2135
+ }
2136
+ function prefixId$6(id) {
2137
+ return `bio-properties-panel-${id}`;
2138
+ }
2139
+ //#endregion
2140
+ //#region src/components/entries/expression/Expression.js
2141
+ var noop$2 = () => {};
2142
+ /**
2143
+ * @typedef {'required'|'optional'|'static'} FeelType
2144
+ */
2145
+ /**
2146
+ * @param {Object} props
2147
+ * @param {Boolean} props.debounce
2148
+ * @param {String} props.id
2149
+ * @param {Object} props.element
2150
+ * @param {String} props.label
2151
+ * @param {String} props.hostLanguage
2152
+ * @param {Function} props.onInput
2153
+ * @param {Function} props.onBlur
2154
+ * @param {Function} props.onError
2155
+ * @param {FeelType} [props.feel]
2156
+ * @param {String} props.value
2157
+ * @param {Boolean} [props.singleLine]
2158
+ * @param {Function} props.tooltipContainer
2159
+ * @param {Function | import('preact').Component} props.OptionalComponent
2160
+ * @param {Boolean} props.disabled
2161
+ * @param {Array} props.variables
2162
+ * @param {string} [props.placeholder]
2163
+ * @param {string | import('preact').Component} props.tooltip
2164
+ */
2165
+ function FeelTextfield(props) {
2166
+ const { debounce, id, element, label, hostLanguage, onInput: commitValue, onBlur, onError, placeholder, feel, value = "", disabled = false, variables, singleLine, tooltipContainer, OptionalComponent = OptionalFeelInput, tooltip } = props;
2167
+ const [localValue, setLocalValue] = (0, preact_hooks.useState)(value);
2168
+ const editorRef = useShowEntryEvent(id);
2169
+ const containerRef = (0, preact_hooks.useRef)();
2170
+ const onInput = (0, preact_hooks.useCallback)((newValue) => {
2171
+ commitValue(newValue === "" || newValue === "=" ? void 0 : newValue);
2172
+ }, [commitValue]);
2173
+ const feelActive = (0, min_dash.isString)(localValue) && localValue.startsWith("=") || feel === "required";
2174
+ const feelOnlyValue = (0, min_dash.isString)(localValue) && localValue.startsWith("=") ? localValue.substring(1) : localValue;
2175
+ const feelLanguageContext = (0, preact_hooks.useContext)(FeelLanguageContext);
2176
+ const [focus, _setFocus] = (0, preact_hooks.useState)(void 0);
2177
+ const { eventBus } = (0, preact_hooks.useContext)(EventContext);
2178
+ const [isPopupOpen, setIsPopupOpen] = (0, preact_hooks.useState)(false);
2179
+ const setFocus = (offset = 0) => {
2180
+ const position = containerRef.current.contains(document.activeElement) ? document.activeElement.selectionStart : Infinity;
2181
+ _setFocus(position + offset);
2182
+ };
2183
+ /**
2184
+ * @type { import('min-dash').DebouncedFunction }
2185
+ */
2186
+ const handleInput = useDebounce(onInput, debounce);
2187
+ const handleFeelToggle = useStaticCallback(() => {
2188
+ if (feel === "required") return;
2189
+ if (!feelActive) {
2190
+ setLocalValue("=" + localValue);
2191
+ handleInput("=" + localValue);
2192
+ } else {
2193
+ setLocalValue(feelOnlyValue);
2194
+ handleInput(feelOnlyValue);
2195
+ }
2196
+ });
2197
+ const handleLocalInput = (newValue, useDebounce = true) => {
2198
+ if (feelActive) newValue = "=" + newValue;
2199
+ if (newValue === localValue) return;
2200
+ setLocalValue(newValue);
2201
+ if (useDebounce) handleInput(newValue);
2202
+ else onInput(newValue);
2203
+ if (!feelActive && (0, min_dash.isString)(newValue) && newValue.startsWith("=")) setFocus(-1);
2204
+ };
2205
+ const handleOnBlur = (e) => {
2206
+ handleInput.cancel?.();
2207
+ if (e.target.type === "checkbox") onInput(e.target.checked);
2208
+ else {
2209
+ const trimmedValue = e.target.value.trim();
2210
+ handleLocalInput(trimmedValue, false);
2211
+ }
2212
+ if (onBlur) onBlur(e);
2213
+ };
2214
+ const handleOnKeyDown = (e) => {
2215
+ if (isCmdWithChar(e)) handleInput.flush();
2216
+ };
2217
+ const handleLint = useStaticCallback((lint = []) => {
2218
+ if (lint.some((report) => report.type === "Syntax Error")) onError("Unparsable FEEL expression.");
2219
+ else onError(void 0);
2220
+ });
2221
+ const handleOpenPopup = (type = "feel") => {
2222
+ const isOpen = eventBus.fire("propertiesPanel.openPopup", {
2223
+ element,
2224
+ entryId: id,
2225
+ hostLanguage,
2226
+ label,
2227
+ onInput: handleLocalInput,
2228
+ singleLine,
2229
+ sourceElement: editorRef.current,
2230
+ tooltipContainer,
2231
+ type,
2232
+ value: feelOnlyValue,
2233
+ variables,
2234
+ feelLanguageContext
2235
+ });
2236
+ if (isOpen) eventBus.once("propertiesPanelPopup.close", () => {
2237
+ setIsPopupOpen(false);
2238
+ });
2239
+ setIsPopupOpen(isOpen === true);
2240
+ };
2241
+ (0, preact_hooks.useEffect)(() => {
2242
+ if (typeof focus !== "undefined") {
2243
+ editorRef.current.focus(focus);
2244
+ _setFocus(void 0);
2245
+ }
2246
+ }, [focus]);
2247
+ (0, preact_hooks.useEffect)(() => {
2248
+ if (value === localValue) return;
2249
+ if (!value) {
2250
+ setLocalValue(feelActive ? "=" : "");
2251
+ return;
2252
+ }
2253
+ setLocalValue(value);
2254
+ }, [value]);
2255
+ (0, preact_hooks.useEffect)(() => {
2256
+ return () => {
2257
+ eventBus.fire("propertiesPanel.closePopup");
2258
+ };
2259
+ }, []);
2260
+ (0, preact_hooks.useEffect)(() => {
2261
+ const copyHandler = (event) => {
2262
+ if (!feelActive) return;
2263
+ event.clipboardData.setData("application/FEEL", event.clipboardData.getData("text"));
2264
+ };
2265
+ const pasteHandler = (event) => {
2266
+ if (feelActive || isPopupOpen) return;
2267
+ if (event.clipboardData.getData("application/FEEL")) {
2268
+ setTimeout(() => {
2269
+ handleFeelToggle();
2270
+ setFocus();
2271
+ });
2272
+ return;
2273
+ }
2274
+ const input = event.target;
2275
+ const isFieldEmpty = !input.value;
2276
+ const isAllSelected = input.selectionStart === 0 && input.selectionEnd === input.value.length;
2277
+ if (isFieldEmpty || isAllSelected) {
2278
+ const trimmedValue = event.clipboardData.getData("text").trim();
2279
+ setLocalValue(trimmedValue);
2280
+ handleInput(trimmedValue);
2281
+ if (!feelActive && (0, min_dash.isString)(trimmedValue) && trimmedValue.startsWith("=")) setFocus(trimmedValue.length - 1);
2282
+ event.preventDefault();
2283
+ }
2284
+ };
2285
+ containerRef.current.addEventListener("copy", copyHandler);
2286
+ containerRef.current.addEventListener("cut", copyHandler);
2287
+ containerRef.current.addEventListener("paste", pasteHandler);
2288
+ return () => {
2289
+ containerRef.current.removeEventListener("copy", copyHandler);
2290
+ containerRef.current.removeEventListener("cut", copyHandler);
2291
+ containerRef.current.removeEventListener("paste", pasteHandler);
2292
+ };
2293
+ }, [
2294
+ containerRef,
2295
+ feelActive,
2296
+ handleFeelToggle,
2297
+ setFocus
2298
+ ]);
2299
+ return (0, preact_jsx_runtime.jsxs)("div", {
2300
+ class: (0, classnames.default)("bio-properties-panel-feel-entry", { "feel-active": feelActive }),
2301
+ children: [(0, preact_jsx_runtime.jsxs)("label", {
2302
+ for: prefixId$5(id),
2303
+ class: "bio-properties-panel-label",
2304
+ onClick: () => setFocus(),
2305
+ children: [(0, preact_jsx_runtime.jsx)(TooltipWrapper, {
2306
+ value: tooltip,
2307
+ forId: id,
2308
+ element: props.element,
2309
+ children: label
2310
+ }), (0, preact_jsx_runtime.jsx)(ExpressionIcon, {
2311
+ label,
2312
+ feel,
2313
+ onClick: handleFeelToggle,
2314
+ active: feelActive
2315
+ })]
2316
+ }), (0, preact_jsx_runtime.jsxs)("div", {
2317
+ class: "bio-properties-panel-feel-container",
2318
+ ref: containerRef,
2319
+ children: [(0, preact_jsx_runtime.jsx)(ExpressionIndicator, {
2320
+ active: feelActive,
2321
+ disabled: feel !== "optional" || disabled,
2322
+ onClick: handleFeelToggle
2323
+ }), feelActive ? (0, preact_jsx_runtime.jsx)(ExpressionEditor, {
2324
+ name: id,
2325
+ onInput: handleLocalInput,
2326
+ onKeyDown: handleOnKeyDown,
2327
+ contentAttributes: {
2328
+ "id": prefixId$5(id),
2329
+ "aria-label": label
2330
+ },
2331
+ disabled,
2332
+ popupOpen: isPopupOpen,
2333
+ onFeelToggle: () => {
2334
+ handleFeelToggle();
2335
+ setFocus(true);
2336
+ },
2337
+ onLint: handleLint,
2338
+ onOpenPopup: handleOpenPopup,
2339
+ placeholder,
2340
+ value: feelOnlyValue,
2341
+ variables,
2342
+ feelLanguageContext,
2343
+ ref: editorRef,
2344
+ tooltipContainer
2345
+ }) : (0, preact_jsx_runtime.jsx)(OptionalComponent, {
2346
+ ...props,
2347
+ popupOpen: isPopupOpen,
2348
+ onInput: handleLocalInput,
2349
+ onKeyDown: handleOnKeyDown,
2350
+ onBlur: handleOnBlur,
2351
+ contentAttributes: {
2352
+ "id": prefixId$5(id),
2353
+ "aria-label": label
2354
+ },
2355
+ value: localValue,
2356
+ ref: editorRef,
2357
+ onOpenPopup: handleOpenPopup,
2358
+ containerRef
2359
+ })]
2360
+ })]
2361
+ });
2362
+ }
2363
+ var OptionalFeelInput = (0, preact_compat.forwardRef)((props, ref) => {
2364
+ const { id, disabled, onInput, onKeyDown, value, onFocus, onBlur, placeholder } = props;
2365
+ const inputRef = (0, preact_hooks.useRef)();
2366
+ ref.current = { focus: (position) => {
2367
+ const input = inputRef.current;
2368
+ if (!input) return;
2369
+ input.focus();
2370
+ if (typeof position === "number") {
2371
+ if (position > value.length) position = value.length;
2372
+ input.setSelectionRange(position, position);
2373
+ }
2374
+ } };
2375
+ return (0, preact_jsx_runtime.jsx)("input", {
2376
+ id: prefixId$5(id),
2377
+ type: "text",
2378
+ ref: inputRef,
2379
+ name: id,
2380
+ spellCheck: "false",
2381
+ autoComplete: "off",
2382
+ disabled,
2383
+ class: "bio-properties-panel-input",
2384
+ onInput: (e) => onInput(e.target.value),
2385
+ onFocus,
2386
+ onKeyDown,
2387
+ onBlur,
2388
+ placeholder,
2389
+ value: value || ""
2390
+ });
2391
+ });
2392
+ var OptionalFeelNumberField = (0, preact_compat.forwardRef)((props, ref) => {
2393
+ const { id, debounce, disabled, onInput, value, min, max, step, onFocus, onBlur } = props;
2394
+ const inputRef = (0, preact_hooks.useRef)();
2395
+ ref.current = { focus: (position) => {
2396
+ const input = inputRef.current;
2397
+ if (!input) return;
2398
+ input.focus();
2399
+ if (typeof position === "number" && position !== Infinity) {
2400
+ if (position > value.length) position = value.length;
2401
+ input.setSelectionRange(position, position);
2402
+ }
2403
+ } };
2404
+ return (0, preact_jsx_runtime.jsx)(NumberField, {
2405
+ id,
2406
+ debounce,
2407
+ disabled,
2408
+ displayLabel: false,
2409
+ inputRef,
2410
+ max,
2411
+ min,
2412
+ onInput,
2413
+ step,
2414
+ value,
2415
+ onFocus,
2416
+ onBlur
2417
+ });
2418
+ });
2419
+ var OptionalFeelTextArea = (0, preact_compat.forwardRef)((props, ref) => {
2420
+ const { id, disabled, onInput, value, onFocus, onBlur, placeholder } = props;
2421
+ const inputRef = (0, preact_hooks.useRef)();
2422
+ ref.current = { focus: () => {
2423
+ const input = inputRef.current;
2424
+ if (!input) return;
2425
+ input.focus();
2426
+ input.setSelectionRange(0, 0);
2427
+ } };
2428
+ return (0, preact_jsx_runtime.jsx)("textarea", {
2429
+ id: prefixId$5(id),
2430
+ type: "text",
2431
+ ref: inputRef,
2432
+ name: id,
2433
+ spellCheck: "false",
2434
+ autoComplete: "off",
2435
+ disabled,
2436
+ class: "bio-properties-panel-input",
2437
+ onInput: (e) => onInput(e.target.value),
2438
+ onFocus,
2439
+ onBlur,
2440
+ placeholder,
2441
+ value: value || "",
2442
+ "data-gramm": "false"
2443
+ });
2444
+ });
2445
+ var OptionalFeelToggleSwitch = (0, preact_compat.forwardRef)((props, ref) => {
2446
+ const { id, onInput, value, onFocus, onBlur, switcherLabel } = props;
2447
+ const inputRef = (0, preact_hooks.useRef)();
2448
+ ref.current = { focus: () => {
2449
+ const input = inputRef.current;
2450
+ if (!input) return;
2451
+ input.focus();
2452
+ } };
2453
+ return (0, preact_jsx_runtime.jsx)(ToggleSwitch, {
2454
+ id,
2455
+ value,
2456
+ inputRef,
2457
+ onInput,
2458
+ onFocus,
2459
+ onBlur,
2460
+ switcherLabel
2461
+ });
2462
+ });
2463
+ var OptionalFeelCheckbox = (0, preact_compat.forwardRef)((props, ref) => {
2464
+ const { id, disabled, onInput, value, onFocus, onBlur } = props;
2465
+ const inputRef = (0, preact_hooks.useRef)();
2466
+ const handleChange = ({ target }) => {
2467
+ onInput(target.checked);
2468
+ };
2469
+ ref.current = { focus: () => {
2470
+ const input = inputRef.current;
2471
+ if (!input) return;
2472
+ input.focus();
2473
+ } };
2474
+ return (0, preact_jsx_runtime.jsx)("input", {
2475
+ ref: inputRef,
2476
+ id: prefixId$5(id),
2477
+ name: id,
2478
+ onFocus,
2479
+ onBlur,
2480
+ type: "checkbox",
2481
+ class: "bio-properties-panel-input",
2482
+ onChange: handleChange,
2483
+ checked: value,
2484
+ disabled
2485
+ });
2486
+ });
2487
+ /**
2488
+ * @param {Object} props
2489
+ * @param {Object} props.element
2490
+ * @param {String} props.id
2491
+ * @param {String} props.description
2492
+ * @param {Boolean} props.debounce
2493
+ * @param {Boolean} props.disabled
2494
+ * @param {FeelType} [props.feel]
2495
+ * @param {String} props.label
2496
+ * @param {Function} props.getValue
2497
+ * @param {Function} props.setValue
2498
+ * @param {Function} props.tooltipContainer
2499
+ * @param {Function} props.validate
2500
+ * @param {Function} props.show
2501
+ * @param {Function} props.example
2502
+ * @param {Array} props.variables
2503
+ * @param {Function} props.onFocus
2504
+ * @param {Function} props.onBlur
2505
+ * @param {string} [props.placeholder]
2506
+ * @param {string|import('preact').Component} props.tooltip
2507
+ */
2508
+ function FeelEntry(props) {
2509
+ const { element, id, description, debounce, disabled, feel, label, getValue, setValue, tooltipContainer, hostLanguage, singleLine, validate, show = noop$2, example, variables, onFocus, onBlur, placeholder, tooltip } = props;
2510
+ const [validationError, setValidationError] = (0, preact_hooks.useState)(null);
2511
+ const [localError, setLocalError] = (0, preact_hooks.useState)(null);
2512
+ let value = getValue(element);
2513
+ (0, preact_hooks.useEffect)(() => {
2514
+ if ((0, min_dash.isFunction)(validate)) {
2515
+ const newValidationError = validate(value) || null;
2516
+ setValidationError(newValidationError);
2517
+ }
2518
+ }, [value, validate]);
2519
+ const onInput = useStaticCallback((newValue) => {
2520
+ const value = getValue(element);
2521
+ let newValidationError = null;
2522
+ if ((0, min_dash.isFunction)(validate)) newValidationError = validate(newValue) || null;
2523
+ if (newValue !== value) setValue(newValue, newValidationError);
2524
+ setValidationError(newValidationError);
2525
+ });
2526
+ const onError = (0, preact_hooks.useCallback)((err) => {
2527
+ setLocalError(err);
2528
+ }, []);
2529
+ const error = useError(id) || localError || validationError;
2530
+ return (0, preact_jsx_runtime.jsxs)("div", {
2531
+ class: (0, classnames.default)(props.class, "bio-properties-panel-entry", error ? "has-error" : ""),
2532
+ "data-entry-id": id,
2533
+ children: [
2534
+ (0, preact.createElement)(FeelTextfield, {
2535
+ ...props,
2536
+ debounce,
2537
+ disabled,
2538
+ feel,
2539
+ id,
2540
+ key: element,
2541
+ label,
2542
+ onInput,
2543
+ onError,
2544
+ onFocus,
2545
+ onBlur,
2546
+ placeholder,
2547
+ example,
2548
+ hostLanguage,
2549
+ singleLine,
2550
+ show,
2551
+ value,
2552
+ variables,
2553
+ tooltipContainer,
2554
+ OptionalComponent: props.OptionalComponent,
2555
+ tooltip
2556
+ }),
2557
+ error && (0, preact_jsx_runtime.jsx)("div", {
2558
+ class: "bio-properties-panel-error",
2559
+ children: error
2560
+ }),
2561
+ (0, preact_jsx_runtime.jsx)(Description, {
2562
+ forId: id,
2563
+ element,
2564
+ value: description
2565
+ })
2566
+ ]
2567
+ });
2568
+ }
2569
+ /**
2570
+ * @param {Object} props
2571
+ * @param {Object} props.element
2572
+ * @param {String} props.id
2573
+ * @param {String} props.description
2574
+ * @param {Boolean} props.debounce
2575
+ * @param {Boolean} props.disabled
2576
+ * @param {String} props.max
2577
+ * @param {String} props.min
2578
+ * @param {String} props.step
2579
+ * @param {FeelType} [props.feel]
2580
+ * @param {String} props.label
2581
+ * @param {Function} props.getValue
2582
+ * @param {Function} props.setValue
2583
+ * @param {Function} props.tooltipContainer
2584
+ * @param {Function} props.validate
2585
+ * @param {Function} props.show
2586
+ * @param {Function} props.example
2587
+ * @param {Array} props.variables
2588
+ * @param {Function} props.onFocus
2589
+ * @param {Function} props.onBlur
2590
+ */
2591
+ function FeelNumberEntry(props) {
2592
+ return (0, preact_jsx_runtime.jsx)(FeelEntry, {
2593
+ class: "bio-properties-panel-feel-number",
2594
+ OptionalComponent: OptionalFeelNumberField,
2595
+ ...props
2596
+ });
2597
+ }
2598
+ /**
2599
+ * @param {Object} props
2600
+ * @param {Object} props.element
2601
+ * @param {String} props.id
2602
+ * @param {String} props.description
2603
+ * @param {Boolean} props.debounce
2604
+ * @param {Boolean} props.disabled
2605
+ * @param {FeelType} [props.feel]
2606
+ * @param {String} props.label
2607
+ * @param {Function} props.getValue
2608
+ * @param {Function} props.setValue
2609
+ * @param {Function} props.tooltipContainer
2610
+ * @param {Function} props.validate
2611
+ * @param {Function} props.show
2612
+ * @param {Function} props.example
2613
+ * @param {Array} props.variables
2614
+ * @param {Function} props.onFocus
2615
+ * @param {Function} props.onBlur
2616
+ * @param {string} [props.placeholder]
2617
+ */
2618
+ function FeelTextAreaEntry(props) {
2619
+ return (0, preact_jsx_runtime.jsx)(FeelEntry, {
2620
+ class: "bio-properties-panel-feel-textarea",
2621
+ OptionalComponent: OptionalFeelTextArea,
2622
+ ...props
2623
+ });
2624
+ }
2625
+ /**
2626
+ * @param {Object} props
2627
+ * @param {Object} props.element
2628
+ * @param {String} props.id
2629
+ * @param {String} props.description
2630
+ * @param {Boolean} props.debounce
2631
+ * @param {Boolean} props.disabled
2632
+ * @param {FeelType} [props.feel]
2633
+ * @param {String} props.label
2634
+ * @param {Function} props.getValue
2635
+ * @param {Function} props.setValue
2636
+ * @param {Function} props.tooltipContainer
2637
+ * @param {Function} props.validate
2638
+ * @param {Function} props.show
2639
+ * @param {Function} props.example
2640
+ * @param {Array} props.variables
2641
+ * @param {Function} props.onFocus
2642
+ * @param {Function} props.onBlur
2643
+ */
2644
+ function FeelToggleSwitchEntry(props) {
2645
+ return (0, preact_jsx_runtime.jsx)(FeelEntry, {
2646
+ class: "bio-properties-panel-feel-toggle-switch",
2647
+ OptionalComponent: OptionalFeelToggleSwitch,
2648
+ ...props
2649
+ });
2650
+ }
2651
+ /**
2652
+ * @param {Object} props
2653
+ * @param {Object} props.element
2654
+ * @param {String} props.id
2655
+ * @param {String} props.description
2656
+ * @param {Boolean} props.debounce
2657
+ * @param {Boolean} props.disabled
2658
+ * @param {FeelType} [props.feel]
2659
+ * @param {String} props.label
2660
+ * @param {Function} props.getValue
2661
+ * @param {Function} props.setValue
2662
+ * @param {Function} props.tooltipContainer
2663
+ * @param {Function} props.validate
2664
+ * @param {Function} props.show
2665
+ * @param {Function} props.example
2666
+ * @param {Array} props.variables
2667
+ * @param {Function} props.onFocus
2668
+ * @param {Function} props.onBlur
2669
+ */
2670
+ function FeelCheckboxEntry(props) {
2671
+ return (0, preact_jsx_runtime.jsx)(FeelEntry, {
2672
+ class: "bio-properties-panel-feel-checkbox",
2673
+ OptionalComponent: OptionalFeelCheckbox,
2674
+ ...props
2675
+ });
2676
+ }
2677
+ /**
2678
+ * @param {Object} props
2679
+ * @param {Object} props.element
2680
+ * @param {String} props.id
2681
+ * @param {String} props.description
2682
+ * @param {String} props.hostLanguage
2683
+ * @param {Boolean} props.singleLine
2684
+ * @param {Boolean} props.debounce
2685
+ * @param {Boolean} props.disabled
2686
+ * @param {FeelType} [props.feel]
2687
+ * @param {String} props.label
2688
+ * @param {Function} props.getValue
2689
+ * @param {Function} props.setValue
2690
+ * @param {Function} props.tooltipContainer
2691
+ * @param {Function} props.validate
2692
+ * @param {Function} props.show
2693
+ * @param {Function} props.example
2694
+ * @param {Array} props.variables
2695
+ * @param {Function} props.onFocus
2696
+ * @param {Function} props.onBlur
2697
+ */
2698
+ function FeelTemplatingEntry(props) {
2699
+ return (0, preact_jsx_runtime.jsx)(FeelEntry, {
2700
+ class: "bio-properties-panel-feel-templating",
2701
+ OptionalComponent: TemplatingEditor,
2702
+ ...props
2703
+ });
2704
+ }
2705
+ function isEdited$1(node) {
2706
+ if (!node) return false;
2707
+ if (node.type === "checkbox") return !!node.checked || node.classList.contains("edited");
2708
+ return !!node.value || node.classList.contains("edited");
2709
+ }
2710
+ function prefixId$5(id) {
2711
+ return `bio-properties-panel-${id}`;
2712
+ }
2713
+ //#endregion
2714
+ //#region src/components/entries/templating/Templating.js
2715
+ var noop$1 = () => {};
2716
+ /**
2717
+ * @param {Object} props
2718
+ * @param {Object} props.element
2719
+ * @param {String} props.id
2720
+ * @param {String} props.description
2721
+ * @param {Boolean} props.debounce
2722
+ * @param {Boolean} props.disabled
2723
+ * @param {String} props.label
2724
+ * @param {Function} props.getValue
2725
+ * @param {Function} props.setValue
2726
+ * @param {Function} props.tooltipContainer
2727
+ * @param {Function} props.validate
2728
+ * @param {Function} props.show
2729
+ */
2730
+ function TemplatingEntry(props) {
2731
+ const { element, id, description, debounce, disabled, label, getValue, setValue, tooltipContainer, validate, show = noop$1 } = props;
2732
+ const [validationError, setValidationError] = (0, preact_hooks.useState)(null);
2733
+ const [localError, setLocalError] = (0, preact_hooks.useState)(null);
2734
+ let value = getValue(element);
2735
+ (0, preact_hooks.useEffect)(() => {
2736
+ if ((0, min_dash.isFunction)(validate)) {
2737
+ const newValidationError = validate(value) || null;
2738
+ setValidationError(newValidationError);
2739
+ }
2740
+ }, [value, validate]);
2741
+ const onInput = useStaticCallback((newValue) => {
2742
+ let newValidationError = null;
2743
+ if ((0, min_dash.isFunction)(validate)) newValidationError = validate(newValue) || null;
2744
+ if (newValue !== value) setValue(newValue, newValidationError);
2745
+ setValidationError(newValidationError);
2746
+ });
2747
+ const onError = (0, preact_hooks.useCallback)((err) => {
2748
+ setLocalError(err);
2749
+ }, []);
2750
+ const temporaryError = useError(id);
2751
+ const error = localError || temporaryError || validationError;
2752
+ return (0, preact_jsx_runtime.jsxs)("div", {
2753
+ class: (0, classnames.default)("bio-properties-panel-entry", error ? "has-error" : ""),
2754
+ "data-entry-id": id,
2755
+ children: [
2756
+ (0, preact_jsx_runtime.jsx)(Templating, {
2757
+ debounce,
2758
+ disabled,
2759
+ id,
2760
+ label,
2761
+ onInput,
2762
+ onError,
2763
+ show,
2764
+ value,
2765
+ tooltipContainer
2766
+ }, element),
2767
+ error && (0, preact_jsx_runtime.jsx)("div", {
2768
+ class: "bio-properties-panel-error",
2769
+ children: error
2770
+ }),
2771
+ (0, preact_jsx_runtime.jsx)(Description, {
2772
+ forId: id,
2773
+ element,
2774
+ value: description
2775
+ })
2776
+ ]
2777
+ });
2778
+ }
2779
+ function Templating(props) {
2780
+ const { debounce, id, label, onInput, onError, value = "", disabled = false, tooltipContainer } = props;
2781
+ const [localValue, setLocalValue] = (0, preact_hooks.useState)(value);
2782
+ const editorRef = useShowEntryEvent(id);
2783
+ const containerRef = (0, preact_hooks.useRef)();
2784
+ const [focus, _setFocus] = (0, preact_hooks.useState)(void 0);
2785
+ const setFocus = (offset = 0) => {
2786
+ const position = containerRef.current.contains(document.activeElement) ? document.activeElement.selectionStart : Infinity;
2787
+ _setFocus(position + offset);
2788
+ };
2789
+ const handleInputCallback = (0, preact_hooks.useMemo)(() => {
2790
+ return debounce((newValue) => onInput(newValue.length ? newValue : void 0));
2791
+ }, [onInput, debounce]);
2792
+ const handleInput = (newValue) => {
2793
+ handleInputCallback(newValue);
2794
+ setLocalValue(newValue);
2795
+ };
2796
+ const handleLint = useStaticCallback((lint) => {
2797
+ if (!(lint && lint.length && lint.filter((e) => e.severity === "error") || []).length) {
2798
+ onError(void 0);
2799
+ return;
2800
+ }
2801
+ const error = lint[0];
2802
+ const message = `${error.source}: ${error.message}`;
2803
+ onError(message);
2804
+ });
2805
+ (0, preact_hooks.useEffect)(() => {
2806
+ if (typeof focus !== "undefined") {
2807
+ editorRef.current.focus(focus);
2808
+ _setFocus(void 0);
2809
+ }
2810
+ }, [focus]);
2811
+ (0, preact_hooks.useEffect)(() => {
2812
+ if (value === localValue) return;
2813
+ setLocalValue(value ? value : "");
2814
+ }, [value]);
2815
+ return (0, preact_jsx_runtime.jsxs)("div", {
2816
+ class: "bio-properties-panel-feelers",
2817
+ children: [(0, preact_jsx_runtime.jsx)("label", {
2818
+ id: prefixIdLabel(id),
2819
+ class: "bio-properties-panel-label",
2820
+ onClick: () => setFocus(),
2821
+ children: label
2822
+ }), (0, preact_jsx_runtime.jsx)("div", {
2823
+ class: "bio-properties-panel-feelers-input",
2824
+ ref: containerRef,
2825
+ children: (0, preact_jsx_runtime.jsx)(TemplatingEditor, {
2826
+ name: id,
2827
+ onInput: handleInput,
2828
+ contentAttributes: { "aria-labelledby": prefixIdLabel(id) },
2829
+ disabled,
2830
+ onLint: handleLint,
2831
+ value: localValue,
2832
+ ref: editorRef,
2833
+ tooltipContainer
2834
+ })
2835
+ })]
2836
+ });
2837
+ }
2838
+ function isEdited$6(node) {
2839
+ return node && (!!node.value || node.classList.contains("edited"));
2840
+ }
2841
+ function prefixIdLabel(id) {
2842
+ return `bio-properties-panel-feelers-${id}-label`;
2843
+ }
2844
+ //#endregion
2845
+ //#region src/components/entries/List.js
2846
+ /**
2847
+ * Entry for handling lists represented as nested entries.
2848
+ *
2849
+ * @template Item
2850
+ * @param {object} props
2851
+ * @param {string} props.id
2852
+ * @param {*} props.element
2853
+ * @param {Function} props.onAdd
2854
+ * @param {import('preact').Component} props.component
2855
+ * @param {string} [props.label='<empty>']
2856
+ * @param {Function} [props.onRemove]
2857
+ * @param {Item[]} [props.items]
2858
+ * @param {boolean} [props.open]
2859
+ * @param {string|boolean} [props.autoFocusEntry] either a custom selector string or true to focus the first input
2860
+ * @returns
2861
+ */
2862
+ function List(props) {
2863
+ const { id, element, items = [], component, label = "<empty>", open: shouldOpen, onAdd, onRemove, autoFocusEntry, ...restProps } = props;
2864
+ const entryRef = (0, preact_hooks.useRef)(null);
2865
+ const [open, setOpen] = (0, preact_hooks.useState)(!!shouldOpen);
2866
+ const [sticky, setSticky] = (0, preact_hooks.useState)(false);
2867
+ const hasItems = !!items.length;
2868
+ const toggleOpen = () => hasItems && setOpen(!open);
2869
+ const newItems = useNewItems(items, usePrevious(element) !== element);
2870
+ (0, preact_hooks.useEffect)(() => {
2871
+ if (open && !hasItems) setOpen(false);
2872
+ }, [open, hasItems]);
2873
+ /**
2874
+ * @param {MouseEvent} event
2875
+ */
2876
+ function addItem(event) {
2877
+ event.stopPropagation();
2878
+ onAdd();
2879
+ if (!open) setOpen(true);
2880
+ }
2881
+ useStickyIntersectionObserver(entryRef, "div.bio-properties-panel-scroll-container", setSticky);
2882
+ return (0, preact_jsx_runtime.jsxs)("div", {
2883
+ "data-entry-id": id,
2884
+ class: (0, classnames.default)("bio-properties-panel-entry", "bio-properties-panel-list-entry", hasItems ? "" : "empty", open ? "open" : ""),
2885
+ ref: entryRef,
2886
+ children: [(0, preact_jsx_runtime.jsxs)("div", {
2887
+ class: (0, classnames.default)("bio-properties-panel-list-entry-header", sticky && open ? "sticky" : ""),
2888
+ onClick: toggleOpen,
2889
+ children: [(0, preact_jsx_runtime.jsx)("div", {
2890
+ class: (0, classnames.default)("bio-properties-panel-list-entry-header-title", open && "open"),
2891
+ children: label
2892
+ }), (0, preact_jsx_runtime.jsxs)("div", {
2893
+ class: "bio-properties-panel-list-entry-header-buttons",
2894
+ children: [
2895
+ (0, preact_jsx_runtime.jsxs)("button", {
2896
+ type: "button",
2897
+ title: "Create new list item",
2898
+ onClick: addItem,
2899
+ class: "bio-properties-panel-add-entry",
2900
+ children: [(0, preact_jsx_runtime.jsx)(CreateIcon, {}), !hasItems ? (0, preact_jsx_runtime.jsx)("span", {
2901
+ class: "bio-properties-panel-add-entry-label",
2902
+ children: "Create"
2903
+ }) : null]
2904
+ }),
2905
+ hasItems && (0, preact_jsx_runtime.jsx)("div", {
2906
+ title: `List contains ${items.length} item${items.length != 1 ? "s" : ""}`,
2907
+ class: "bio-properties-panel-list-badge",
2908
+ children: items.length
2909
+ }),
2910
+ hasItems && (0, preact_jsx_runtime.jsx)("button", {
2911
+ type: "button",
2912
+ title: "Toggle list item",
2913
+ class: "bio-properties-panel-arrow",
2914
+ children: (0, preact_jsx_runtime.jsx)(ArrowIcon, { class: open ? "bio-properties-panel-arrow-down" : "bio-properties-panel-arrow-right" })
2915
+ })
2916
+ ]
2917
+ })]
2918
+ }), hasItems && (0, preact_jsx_runtime.jsx)(ItemsList, {
2919
+ ...restProps,
2920
+ autoFocusEntry,
2921
+ component,
2922
+ element,
2923
+ id,
2924
+ items,
2925
+ newItems,
2926
+ onRemove,
2927
+ open
2928
+ })]
2929
+ });
2930
+ }
2931
+ function ItemsList(props) {
2932
+ const { autoFocusEntry, component: Component, element, id, items, newItems, onRemove, open, ...restProps } = props;
2933
+ const getKey = useKeyFactory();
2934
+ const newItem = newItems[0];
2935
+ (0, preact_hooks.useEffect)(() => {
2936
+ if (newItem && autoFocusEntry) {
2937
+ const entry = (0, min_dom.query)(`[data-entry-id="${id}"]`);
2938
+ const focusableInput = (0, min_dom.query)(typeof autoFocusEntry === "boolean" ? ".bio-properties-panel-input" : autoFocusEntry, entry);
2939
+ if (focusableInput) {
2940
+ if ((0, min_dash.isFunction)(focusableInput.select)) focusableInput.select();
2941
+ else if ((0, min_dash.isFunction)(focusableInput.focus)) focusableInput.focus();
2942
+ }
2943
+ }
2944
+ }, [
2945
+ newItem,
2946
+ autoFocusEntry,
2947
+ id
2948
+ ]);
2949
+ return (0, preact_jsx_runtime.jsx)("ol", {
2950
+ class: (0, classnames.default)("bio-properties-panel-list-entry-items", open ? "open" : ""),
2951
+ children: items.map((item, index) => {
2952
+ const key = getKey(item);
2953
+ return (0, preact_jsx_runtime.jsxs)("li", {
2954
+ class: "bio-properties-panel-list-entry-item",
2955
+ children: [(0, preact_jsx_runtime.jsx)(Component, {
2956
+ ...restProps,
2957
+ element,
2958
+ id,
2959
+ index,
2960
+ item,
2961
+ open: item === newItem
2962
+ }), onRemove && (0, preact_jsx_runtime.jsx)("button", {
2963
+ type: "button",
2964
+ title: "Delete item",
2965
+ class: "bio-properties-panel-remove-entry bio-properties-panel-remove-list-entry",
2966
+ onClick: () => onRemove && onRemove(item),
2967
+ children: (0, preact_jsx_runtime.jsx)(DeleteIcon, {})
2968
+ })]
2969
+ }, key);
2970
+ })
2971
+ });
2972
+ }
2973
+ function useNewItems(items = [], shouldReset) {
2974
+ const previousItems = usePrevious(items.slice()) || [];
2975
+ if (shouldReset) return [];
2976
+ return previousItems ? items.filter((item) => !previousItems.includes(item)) : [];
2977
+ }
2978
+ //#endregion
2979
+ //#region src/components/entries/Select.js
2980
+ /**
2981
+ * @typedef { { value: string, label: string, disabled: boolean, children: { value: string, label: string, disabled: boolean } } } Option
2982
+ */
2983
+ /**
2984
+ * Provides basic select input.
2985
+ *
2986
+ * @param {object} props
2987
+ * @param {string} props.id
2988
+ * @param {string[]} props.path
2989
+ * @param {string} props.label
2990
+ * @param {Function} props.onChange
2991
+ * @param {Function} props.onFocus
2992
+ * @param {Function} props.onBlur
2993
+ * @param {Array<Option>} [props.options]
2994
+ * @param {string} props.value
2995
+ * @param {boolean} [props.disabled]
2996
+ */
2997
+ function Select(props) {
2998
+ const { id, label, onChange, options = [], value = "", disabled, onFocus, onBlur, tooltip } = props;
2999
+ const ref = useShowEntryEvent(id);
3000
+ const [localValue, setLocalValue] = (0, preact_hooks.useState)(value);
3001
+ const handleChangeCallback = ({ target }) => {
3002
+ onChange(target.value);
3003
+ };
3004
+ const handleChange = (e) => {
3005
+ handleChangeCallback(e);
3006
+ setLocalValue(e.target.value);
3007
+ };
3008
+ (0, preact_hooks.useEffect)(() => {
3009
+ if (value === localValue) return;
3010
+ setLocalValue(value);
3011
+ }, [value]);
3012
+ return (0, preact_jsx_runtime.jsxs)("div", {
3013
+ class: "bio-properties-panel-select",
3014
+ children: [(0, preact_jsx_runtime.jsx)("label", {
3015
+ for: prefixId$4(id),
3016
+ class: "bio-properties-panel-label",
3017
+ children: (0, preact_jsx_runtime.jsx)(TooltipWrapper, {
3018
+ value: tooltip,
3019
+ forId: id,
3020
+ element: props.element,
3021
+ children: label
3022
+ })
3023
+ }), (0, preact_jsx_runtime.jsx)("select", {
3024
+ ref,
3025
+ id: prefixId$4(id),
3026
+ name: id,
3027
+ class: "bio-properties-panel-input",
3028
+ onInput: handleChange,
3029
+ onFocus,
3030
+ onBlur,
3031
+ value: localValue,
3032
+ disabled,
3033
+ children: options.map((option, idx) => {
3034
+ if (option.children) return (0, preact_jsx_runtime.jsx)("optgroup", {
3035
+ label: option.label,
3036
+ children: option.children.map((child, idx) => (0, preact_jsx_runtime.jsx)("option", {
3037
+ value: child.value,
3038
+ disabled: child.disabled,
3039
+ children: child.label
3040
+ }, idx))
3041
+ }, idx);
3042
+ return (0, preact_jsx_runtime.jsx)("option", {
3043
+ value: option.value,
3044
+ disabled: option.disabled,
3045
+ children: option.label
3046
+ }, idx);
3047
+ })
3048
+ })]
3049
+ });
3050
+ }
3051
+ /**
3052
+ * @param {object} props
3053
+ * @param {object} props.element
3054
+ * @param {string} props.id
3055
+ * @param {string} [props.description]
3056
+ * @param {string} props.label
3057
+ * @param {Function} props.getValue
3058
+ * @param {Function} props.setValue
3059
+ * @param {Function} props.onFocus
3060
+ * @param {Function} props.onBlur
3061
+ * @param {Function} props.getOptions
3062
+ * @param {boolean} [props.disabled]
3063
+ * @param {Function} [props.validate]
3064
+ * @param {string|import('preact').Component} props.tooltip
3065
+ */
3066
+ function SelectEntry(props) {
3067
+ const { element, id, description, label, getValue, setValue, getOptions, disabled, onFocus, onBlur, validate, tooltip } = props;
3068
+ const options = getOptions(element);
3069
+ const globalError = useError(id);
3070
+ const [localError, setLocalError] = (0, preact_hooks.useState)(null);
3071
+ let value = getValue(element);
3072
+ (0, preact_hooks.useEffect)(() => {
3073
+ if ((0, min_dash.isFunction)(validate)) {
3074
+ const newValidationError = validate(value) || null;
3075
+ setLocalError(newValidationError);
3076
+ }
3077
+ }, [value, validate]);
3078
+ const onChange = (newValue) => {
3079
+ let newValidationError = null;
3080
+ if ((0, min_dash.isFunction)(validate)) newValidationError = validate(newValue) || null;
3081
+ setValue(newValue, newValidationError);
3082
+ setLocalError(newValidationError);
3083
+ };
3084
+ const error = globalError || localError;
3085
+ return (0, preact_jsx_runtime.jsxs)("div", {
3086
+ class: (0, classnames.default)("bio-properties-panel-entry", error ? "has-error" : ""),
3087
+ "data-entry-id": id,
3088
+ children: [
3089
+ (0, preact_jsx_runtime.jsx)(Select, {
3090
+ id,
3091
+ label,
3092
+ value,
3093
+ onChange,
3094
+ onFocus,
3095
+ onBlur,
3096
+ options,
3097
+ disabled,
3098
+ tooltip,
3099
+ element
3100
+ }, element),
3101
+ error && (0, preact_jsx_runtime.jsx)("div", {
3102
+ class: "bio-properties-panel-error",
3103
+ children: error
3104
+ }),
3105
+ (0, preact_jsx_runtime.jsx)(Description, {
3106
+ forId: id,
3107
+ element,
3108
+ value: description
3109
+ })
3110
+ ]
3111
+ });
3112
+ }
3113
+ function isEdited$4(node) {
3114
+ return node && !!node.value;
3115
+ }
3116
+ function prefixId$4(id) {
3117
+ return `bio-properties-panel-${id}`;
3118
+ }
3119
+ //#endregion
3120
+ //#region src/components/entries/Simple.js
3121
+ /**
3122
+ * @param {Object} props
3123
+ * @param {Function} props.debounce
3124
+ * @param {Boolean} [props.disabled]
3125
+ * @param {Object} props.element
3126
+ * @param {Function} props.getValue
3127
+ * @param {String} props.id
3128
+ * @param {Function} [props.onBlur]
3129
+ * @param {Function} [props.onFocus]
3130
+ * @param {Function} props.setValue
3131
+ */
3132
+ function Simple(props) {
3133
+ const { debounce, disabled, element, getValue, id, onBlur, onFocus, setValue } = props;
3134
+ const value = getValue(element);
3135
+ const [localValue, setLocalValue] = (0, preact_hooks.useState)(value);
3136
+ const handleInputCallback = (0, preact_hooks.useMemo)(() => {
3137
+ return debounce((target) => setValue(target.value.length ? target.value : void 0));
3138
+ }, [setValue, debounce]);
3139
+ const handleInput = (e) => {
3140
+ handleInputCallback(e.target);
3141
+ setLocalValue(e.target.value);
3142
+ };
3143
+ (0, preact_hooks.useEffect)(() => {
3144
+ if (value === localValue) return;
3145
+ setLocalValue(value);
3146
+ }, [value]);
3147
+ return (0, preact_jsx_runtime.jsx)("div", {
3148
+ class: "bio-properties-panel-simple",
3149
+ children: (0, preact_jsx_runtime.jsx)("input", {
3150
+ id: prefixId$3(id),
3151
+ type: "text",
3152
+ name: id,
3153
+ spellCheck: "false",
3154
+ autoComplete: "off",
3155
+ disabled,
3156
+ class: "bio-properties-panel-input",
3157
+ onInput: handleInput,
3158
+ "aria-label": localValue || "<empty>",
3159
+ onFocus,
3160
+ onBlur,
3161
+ value: localValue
3162
+ }, element)
3163
+ });
3164
+ }
3165
+ function isEdited$5(node) {
3166
+ return node && !!node.value;
3167
+ }
3168
+ function prefixId$3(id) {
3169
+ return `bio-properties-panel-${id}`;
3170
+ }
3171
+ //#endregion
3172
+ //#region src/components/entries/TextArea.js
3173
+ function resizeToContents(element) {
3174
+ element.style.height = "auto";
3175
+ element.style.height = `${element.scrollHeight + 2}px`;
3176
+ }
3177
+ function TextArea(props) {
3178
+ const { id, label, debounce, onInput: commitValue, value = "", disabled, monospace, onFocus, onBlur, onPaste, autoResize = true, placeholder, rows = autoResize ? 1 : 2, tooltip } = props;
3179
+ const [localValue, setLocalValue] = (0, preact_hooks.useState)(value);
3180
+ const ref = useShowEntryEvent(id);
3181
+ const onInput = (0, preact_hooks.useCallback)((newValue) => {
3182
+ commitValue(newValue === "" ? void 0 : newValue);
3183
+ }, [commitValue]);
3184
+ const visible = useElementVisible(ref.current);
3185
+ /**
3186
+ * @type { import('min-dash').DebouncedFunction }
3187
+ */
3188
+ const handleInput = useDebounce(onInput, debounce);
3189
+ const handleLocalInput = (e) => {
3190
+ autoResize && resizeToContents(e.target);
3191
+ if (e.target.value === localValue) return;
3192
+ setLocalValue(e.target.value);
3193
+ handleInput(e.target.value);
3194
+ };
3195
+ const handleOnBlur = (e) => {
3196
+ const trimmedValue = e.target.value.trim();
3197
+ handleInput.cancel?.();
3198
+ onInput(trimmedValue);
3199
+ setLocalValue(trimmedValue);
3200
+ if (onBlur) onBlur(e);
3201
+ };
3202
+ const handleOnPaste = (e) => {
3203
+ const input = e.target;
3204
+ const isFieldEmpty = !input.value;
3205
+ const isAllSelected = input.selectionStart === 0 && input.selectionEnd === input.value.length;
3206
+ if (isFieldEmpty || isAllSelected) {
3207
+ const trimmedValue = e.clipboardData.getData("text").trim();
3208
+ setLocalValue(trimmedValue);
3209
+ handleInput(trimmedValue);
3210
+ if (onPaste) onPaste(e);
3211
+ e.preventDefault();
3212
+ return;
3213
+ }
3214
+ if (onPaste) onPaste(e);
3215
+ };
3216
+ const handleOnKeyDown = (e) => {
3217
+ if (isCmdWithChar(e)) handleInput.flush();
3218
+ };
3219
+ (0, preact_hooks.useLayoutEffect)(() => {
3220
+ autoResize && resizeToContents(ref.current);
3221
+ }, []);
3222
+ (0, preact_hooks.useLayoutEffect)(() => {
3223
+ visible && autoResize && resizeToContents(ref.current);
3224
+ }, [visible]);
3225
+ (0, preact_hooks.useEffect)(() => {
3226
+ if (value === localValue) return;
3227
+ setLocalValue(value);
3228
+ }, [value]);
3229
+ return (0, preact_jsx_runtime.jsxs)("div", {
3230
+ class: "bio-properties-panel-textarea",
3231
+ children: [(0, preact_jsx_runtime.jsx)("label", {
3232
+ for: prefixId$2(id),
3233
+ class: "bio-properties-panel-label",
3234
+ children: (0, preact_jsx_runtime.jsx)(TooltipWrapper, {
3235
+ value: tooltip,
3236
+ forId: id,
3237
+ element: props.element,
3238
+ children: label
3239
+ })
3240
+ }), (0, preact_jsx_runtime.jsx)("textarea", {
3241
+ ref,
3242
+ id: prefixId$2(id),
3243
+ name: id,
3244
+ spellCheck: "false",
3245
+ class: (0, classnames.default)("bio-properties-panel-input", monospace ? "bio-properties-panel-input-monospace" : "", autoResize ? "auto-resize" : ""),
3246
+ onInput: handleLocalInput,
3247
+ onFocus,
3248
+ onKeyDown: handleOnKeyDown,
3249
+ onBlur: handleOnBlur,
3250
+ onPaste: handleOnPaste,
3251
+ placeholder,
3252
+ rows,
3253
+ value: localValue,
3254
+ disabled,
3255
+ "data-gramm": "false"
3256
+ })]
3257
+ });
3258
+ }
3259
+ /**
3260
+ * @param {object} props
3261
+ * @param {object} props.element
3262
+ * @param {string} props.id
3263
+ * @param {string} props.description
3264
+ * @param {boolean} props.debounce
3265
+ * @param {string} props.label
3266
+ * @param {Function} props.getValue
3267
+ * @param {Function} props.setValue
3268
+ * @param {Function} props.onFocus
3269
+ * @param {Function} props.onBlur
3270
+ * @param {Function} props.onPaste
3271
+ * @param {number} props.rows
3272
+ * @param {boolean} props.monospace
3273
+ * @param {Function} [props.validate]
3274
+ * @param {boolean} [props.disabled]
3275
+ */
3276
+ function TextAreaEntry(props) {
3277
+ const { element, id, description, debounce, label, getValue, setValue, rows, monospace, disabled, validate, onFocus, onBlur, onPaste, placeholder, autoResize, tooltip } = props;
3278
+ const globalError = useError(id);
3279
+ const [localError, setLocalError] = (0, preact_hooks.useState)(null);
3280
+ let value = getValue(element);
3281
+ (0, preact_hooks.useEffect)(() => {
3282
+ if ((0, min_dash.isFunction)(validate)) {
3283
+ const newValidationError = validate(value) || null;
3284
+ setLocalError(newValidationError);
3285
+ }
3286
+ }, [value, validate]);
3287
+ const onInput = useStaticCallback((newValue) => {
3288
+ const value = getValue(element);
3289
+ let newValidationError = null;
3290
+ if ((0, min_dash.isFunction)(validate)) newValidationError = validate(newValue) || null;
3291
+ if (newValue !== value) setValue(newValue, newValidationError);
3292
+ setLocalError(newValidationError);
3293
+ });
3294
+ const error = globalError || localError;
3295
+ return (0, preact_jsx_runtime.jsxs)("div", {
3296
+ class: (0, classnames.default)("bio-properties-panel-entry", error ? "has-error" : ""),
3297
+ "data-entry-id": id,
3298
+ children: [
3299
+ (0, preact_jsx_runtime.jsx)(TextArea, {
3300
+ id,
3301
+ label,
3302
+ value,
3303
+ onInput,
3304
+ onFocus,
3305
+ onBlur,
3306
+ onPaste,
3307
+ rows,
3308
+ debounce,
3309
+ monospace,
3310
+ disabled,
3311
+ placeholder,
3312
+ autoResize,
3313
+ tooltip,
3314
+ element
3315
+ }, element),
3316
+ error && (0, preact_jsx_runtime.jsx)("div", {
3317
+ class: "bio-properties-panel-error",
3318
+ children: error
3319
+ }),
3320
+ (0, preact_jsx_runtime.jsx)(Description, {
3321
+ forId: id,
3322
+ element,
3323
+ value: description
3324
+ })
3325
+ ]
3326
+ });
3327
+ }
3328
+ function isEdited$7(node) {
3329
+ return node && !!node.value;
3330
+ }
3331
+ function prefixId$2(id) {
3332
+ return `bio-properties-panel-${id}`;
3333
+ }
3334
+ //#endregion
3335
+ //#region src/components/entries/TextField.js
3336
+ function Textfield(props) {
3337
+ const { debounce, disabled = false, id, label, onInput: commitValue, onFocus, onBlur, onPaste, placeholder, value = "", tooltip } = props;
3338
+ const [localValue, setLocalValue] = (0, preact_hooks.useState)(value || "");
3339
+ const ref = useShowEntryEvent(id);
3340
+ const onInput = (0, preact_hooks.useCallback)((newValue) => {
3341
+ commitValue(newValue === "" ? void 0 : newValue);
3342
+ }, [commitValue]);
3343
+ /**
3344
+ * @type { import('min-dash').DebouncedFunction }
3345
+ */
3346
+ const handleInput = useDebounce(onInput, debounce);
3347
+ const handleOnBlur = (e) => {
3348
+ const trimmedValue = e.target.value.trim();
3349
+ handleInput.cancel?.();
3350
+ onInput(trimmedValue);
3351
+ setLocalValue(trimmedValue);
3352
+ if (onBlur) onBlur(e);
3353
+ };
3354
+ const handleOnPaste = (e) => {
3355
+ const input = e.target;
3356
+ const isFieldEmpty = !input.value;
3357
+ const isAllSelected = input.selectionStart === 0 && input.selectionEnd === input.value.length;
3358
+ if (isFieldEmpty || isAllSelected) {
3359
+ const trimmedValue = e.clipboardData.getData("text").trim();
3360
+ setLocalValue(trimmedValue);
3361
+ handleInput(trimmedValue);
3362
+ if (onPaste) onPaste(e);
3363
+ e.preventDefault();
3364
+ return;
3365
+ }
3366
+ if (onPaste) onPaste(e);
3367
+ };
3368
+ const handleLocalInput = (e) => {
3369
+ if (e.target.value === localValue) return;
3370
+ setLocalValue(e.target.value);
3371
+ handleInput(e.target.value);
3372
+ };
3373
+ (0, preact_hooks.useEffect)(() => {
3374
+ if (value === localValue) return;
3375
+ setLocalValue(value);
3376
+ }, [value]);
3377
+ const handleOnKeyDown = (e) => {
3378
+ if (isCmdWithChar(e)) handleInput.flush();
3379
+ };
3380
+ return (0, preact_jsx_runtime.jsxs)("div", {
3381
+ class: "bio-properties-panel-textfield",
3382
+ children: [(0, preact_jsx_runtime.jsx)("label", {
3383
+ for: prefixId$1(id),
3384
+ class: "bio-properties-panel-label",
3385
+ children: (0, preact_jsx_runtime.jsx)(TooltipWrapper, {
3386
+ value: tooltip,
3387
+ forId: id,
3388
+ element: props.element,
3389
+ children: label
3390
+ })
3391
+ }), (0, preact_jsx_runtime.jsx)("input", {
3392
+ ref,
3393
+ id: prefixId$1(id),
3394
+ type: "text",
3395
+ name: id,
3396
+ spellCheck: "false",
3397
+ autoComplete: "off",
3398
+ disabled,
3399
+ class: "bio-properties-panel-input",
3400
+ onInput: handleLocalInput,
3401
+ onFocus,
3402
+ onKeyDown: handleOnKeyDown,
3403
+ onBlur: handleOnBlur,
3404
+ onPaste: handleOnPaste,
3405
+ placeholder,
3406
+ value: localValue
3407
+ })]
3408
+ });
3409
+ }
3410
+ /**
3411
+ * @param {Object} props
3412
+ * @param {Object} props.element
3413
+ * @param {String} props.id
3414
+ * @param {String} props.description
3415
+ * @param {Boolean} props.debounce
3416
+ * @param {Boolean} props.disabled
3417
+ * @param {String} props.label
3418
+ * @param {Function} props.getValue
3419
+ * @param {Function} props.setValue
3420
+ * @param {Function} props.onFocus
3421
+ * @param {Function} props.onBlur
3422
+ * @param {string|import('preact').Component} props.tooltip
3423
+ * @param {Function} props.validate
3424
+ */
3425
+ function TextfieldEntry(props) {
3426
+ const { element, id, description, debounce, disabled, label, getValue, setValue, validate, onFocus, onBlur, onPaste, placeholder, tooltip } = props;
3427
+ const globalError = useError(id);
3428
+ const [localError, setLocalError] = (0, preact_hooks.useState)(null);
3429
+ let value = getValue(element);
3430
+ (0, preact_hooks.useEffect)(() => {
3431
+ if ((0, min_dash.isFunction)(validate)) {
3432
+ const newValidationError = validate(value) || null;
3433
+ setLocalError(newValidationError);
3434
+ }
3435
+ }, [value, validate]);
3436
+ const onInput = useStaticCallback((newValue) => {
3437
+ const value = getValue(element);
3438
+ let newValidationError = null;
3439
+ if ((0, min_dash.isFunction)(validate)) newValidationError = validate(newValue) || null;
3440
+ if (newValue !== value) setValue(newValue, newValidationError);
3441
+ setLocalError(newValidationError);
3442
+ });
3443
+ const error = globalError || localError;
3444
+ return (0, preact_jsx_runtime.jsxs)("div", {
3445
+ class: (0, classnames.default)("bio-properties-panel-entry", error ? "has-error" : ""),
3446
+ "data-entry-id": id,
3447
+ children: [
3448
+ (0, preact_jsx_runtime.jsx)(Textfield, {
3449
+ debounce,
3450
+ disabled,
3451
+ id,
3452
+ label,
3453
+ onInput,
3454
+ onFocus,
3455
+ onBlur,
3456
+ onPaste,
3457
+ placeholder,
3458
+ value,
3459
+ tooltip,
3460
+ element
3461
+ }, element),
3462
+ error && (0, preact_jsx_runtime.jsx)("div", {
3463
+ class: "bio-properties-panel-error",
3464
+ children: error
3465
+ }),
3466
+ (0, preact_jsx_runtime.jsx)(Description, {
3467
+ forId: id,
3468
+ element,
3469
+ value: description
3470
+ })
3471
+ ]
3472
+ });
3473
+ }
3474
+ function isEdited$8(node) {
3475
+ return node && !!node.value;
3476
+ }
3477
+ function prefixId$1(id) {
3478
+ return `bio-properties-panel-${id}`;
3479
+ }
3480
+ //#endregion
3481
+ //#region src/features/debounce-input/debounceInput.js
3482
+ var DEFAULT_DEBOUNCE_TIME = 600;
3483
+ /**
3484
+ * Creates a debounced version of a function, delaying its execution based on `debounceDelay`.
3485
+ *
3486
+ * - If `debounceDelay` is `false`, the function executes immediately without debouncing.
3487
+ * - If a number is provided, the function execution is delayed by the given time in milliseconds.
3488
+ *
3489
+ * @param { Boolean | Number } [debounceDelay=600]
3490
+ *
3491
+ * @example
3492
+ * const debounce = debounceInput();
3493
+ * const debouncedFn = debounce(fn);
3494
+ *
3495
+ * debouncedFn(); // Executes after 300ms (default) if no further calls occur.
3496
+ */
3497
+ function debounceInput(debounceDelay) {
3498
+ /**
3499
+ * Applies debounce to the provided function, with a previously setup delay.
3500
+ *
3501
+ * @template { (...args: any[]) => any } T
3502
+ *
3503
+ * @param {T} fn
3504
+ *
3505
+ * @return { (...p: Parameters<T>) => any }
3506
+ */
3507
+ return function debounce(fn) {
3508
+ if (debounceDelay === false) return fn;
3509
+ var debounceTime = (0, min_dash.isNumber)(debounceDelay) ? debounceDelay : DEFAULT_DEBOUNCE_TIME;
3510
+ return (0, min_dash.debounce)(fn, debounceTime);
3511
+ };
3512
+ }
3513
+ debounceInput.$inject = ["config.debounceInput"];
3514
+ //#endregion
3515
+ //#region src/features/debounce-input/index.js
3516
+ var debounce_input_default = { debounceInput: ["factory", debounceInput] };
3517
+ //#endregion
3518
+ //#region src/components/util/dragger.js
3519
+ /**
3520
+ * Add a dragger that calls back the passed function with
3521
+ * { event, delta } on drag.
3522
+ *
3523
+ * @example
3524
+ *
3525
+ * function dragMove(event, delta) {
3526
+ * // we are dragging (!!)
3527
+ * }
3528
+ *
3529
+ * domElement.addEventListener('dragstart', dragger(dragMove));
3530
+ *
3531
+ * @param {Function} fn
3532
+ * @param {Element} [dragPreview]
3533
+ *
3534
+ * @return {Function} drag start callback function
3535
+ */
3536
+ function createDragger(fn, dragPreview) {
3537
+ let self;
3538
+ let startX, startY;
3539
+ /** drag start */
3540
+ function onDragStart(event) {
3541
+ self = this;
3542
+ startX = event.clientX;
3543
+ startY = event.clientY;
3544
+ if (event.dataTransfer) event.dataTransfer.setDragImage(dragPreview || emptyCanvas(), 0, 0);
3545
+ document.addEventListener("dragover", onDrag, true);
3546
+ document.addEventListener("dragenter", preventDefault, true);
3547
+ document.addEventListener("dragend", onEnd);
3548
+ document.addEventListener("drop", preventDefault);
3549
+ }
3550
+ function onDrag(event) {
3551
+ const delta = {
3552
+ x: event.clientX - startX,
3553
+ y: event.clientY - startY
3554
+ };
3555
+ return fn.call(self, event, delta);
3556
+ }
3557
+ function onEnd() {
3558
+ document.removeEventListener("dragover", onDrag, true);
3559
+ document.removeEventListener("dragenter", preventDefault, true);
3560
+ document.removeEventListener("dragend", onEnd);
3561
+ document.removeEventListener("drop", preventDefault);
3562
+ }
3563
+ return onDragStart;
3564
+ }
3565
+ function preventDefault(event) {
3566
+ event.preventDefault();
3567
+ event.stopPropagation();
3568
+ }
3569
+ function emptyCanvas() {
3570
+ return (0, min_dom.domify)("<canvas width=\"0\" height=\"0\" />");
3571
+ }
3572
+ //#endregion
3573
+ //#region src/features/expression-popup/components/Popup.js
3574
+ var noop = () => {};
3575
+ /**
3576
+ * A generic popup component.
3577
+ *
3578
+ * @param {Object} props
3579
+ * @param {string} [props.className]
3580
+ * @param {boolean} [props.delayInitialFocus]
3581
+ * @param {{top: number, left: number}} [props.position]
3582
+ * @param {number} [props.width]
3583
+ * @param {number} [props.height]
3584
+ * @param {Function} props.onClose
3585
+ * @param {Function} [props.onPostActivate]
3586
+ * @param {Function} [props.onPostDeactivate]
3587
+ * @param {boolean} [props.returnFocus]
3588
+ * @param {boolean} [props.closeOnEscape]
3589
+ * @param {string} props.title
3590
+ * @param {Ref} [ref]
3591
+ */
3592
+ function PopupComponent(props, globalRef) {
3593
+ const { className, delayInitialFocus, position, width, height, onClose, onPostActivate = noop, onPostDeactivate = noop, returnFocus = true, closeOnEscape = true, title } = props;
3594
+ const focusTrapRef = (0, preact_hooks.useRef)(null);
3595
+ const localRef = (0, preact_hooks.useRef)(null);
3596
+ const popupRef = globalRef || localRef;
3597
+ const handleKeydown = (event) => {
3598
+ event.stopPropagation();
3599
+ if (closeOnEscape && event.key === "Escape") onClose();
3600
+ };
3601
+ const handleFocus = () => {
3602
+ if (focusTrapRef.current) focusTrapRef.current.activate();
3603
+ };
3604
+ let style = {};
3605
+ if (position) style = {
3606
+ ...style,
3607
+ top: position.top + "px",
3608
+ left: position.left + "px"
3609
+ };
3610
+ if (width) style.width = width + "px";
3611
+ if (height) style.height = height + "px";
3612
+ (0, preact_hooks.useEffect)(() => {
3613
+ if (popupRef.current) popupRef.current.addEventListener("focusin", handleFocus);
3614
+ return () => {
3615
+ if (popupRef.current) popupRef.current.removeEventListener("focusin", handleFocus);
3616
+ };
3617
+ }, [popupRef]);
3618
+ (0, preact_hooks.useEffect)(() => {
3619
+ if (popupRef.current) {
3620
+ focusTrapRef.current = focus_trap.createFocusTrap(popupRef.current, {
3621
+ clickOutsideDeactivates: true,
3622
+ delayInitialFocus,
3623
+ fallbackFocus: popupRef.current,
3624
+ onPostActivate,
3625
+ onPostDeactivate,
3626
+ returnFocusOnDeactivate: returnFocus
3627
+ });
3628
+ focusTrapRef.current.activate();
3629
+ }
3630
+ return () => focusTrapRef.current && focusTrapRef.current.deactivate();
3631
+ }, [popupRef]);
3632
+ return (0, preact_jsx_runtime.jsx)("div", {
3633
+ "aria-label": title,
3634
+ tabIndex: -1,
3635
+ ref: popupRef,
3636
+ onKeyDown: handleKeydown,
3637
+ role: "dialog",
3638
+ class: (0, classnames.default)("bio-properties-panel-popup", className),
3639
+ style,
3640
+ children: props.children
3641
+ });
3642
+ }
3643
+ var Popup = (0, preact_compat.forwardRef)(PopupComponent);
3644
+ Popup.Title = Title;
3645
+ Popup.Body = Body;
3646
+ Popup.Footer = Footer;
3647
+ function Title(props) {
3648
+ const { children, className, draggable, eventBus, title, showCloseButton = false, closeButtonTooltip = "Close popup", onClose, ...rest } = props;
3649
+ const context = (0, preact_hooks.useRef)({
3650
+ startPosition: null,
3651
+ newPosition: null
3652
+ });
3653
+ const dragPreviewRef = (0, preact_hooks.useRef)();
3654
+ const titleRef = (0, preact_hooks.useRef)();
3655
+ const onMove = (event, delta) => {
3656
+ cancel(event);
3657
+ const { x: dx, y: dy } = delta;
3658
+ const newPosition = {
3659
+ x: context.current.startPosition.x + dx,
3660
+ y: context.current.startPosition.y + dy
3661
+ };
3662
+ const popupParent = getPopupParent(titleRef.current);
3663
+ popupParent.style.top = newPosition.y + "px";
3664
+ popupParent.style.left = newPosition.x + "px";
3665
+ eventBus?.fire("feelPopup.dragover", {
3666
+ newPosition,
3667
+ delta
3668
+ });
3669
+ };
3670
+ const onMoveStart = (event) => {
3671
+ createDragger(onMove, dragPreviewRef.current)(event);
3672
+ event.stopPropagation();
3673
+ const bounds = getPopupParent(titleRef.current).getBoundingClientRect();
3674
+ context.current.startPosition = {
3675
+ x: bounds.left,
3676
+ y: bounds.top
3677
+ };
3678
+ eventBus?.fire("feelPopup.dragstart");
3679
+ };
3680
+ const onMoveEnd = () => {
3681
+ context.current.newPosition = null;
3682
+ eventBus?.fire("feelPopup.dragend");
3683
+ };
3684
+ return (0, preact_jsx_runtime.jsxs)("div", {
3685
+ class: (0, classnames.default)("bio-properties-panel-popup__header", draggable && "draggable", className),
3686
+ ref: titleRef,
3687
+ draggable,
3688
+ onDragStart: onMoveStart,
3689
+ onDragEnd: onMoveEnd,
3690
+ ...rest,
3691
+ children: [
3692
+ draggable && (0, preact_jsx_runtime.jsxs)(preact_jsx_runtime.Fragment, { children: [(0, preact_jsx_runtime.jsx)("div", {
3693
+ ref: dragPreviewRef,
3694
+ class: "bio-properties-panel-popup__drag-preview"
3695
+ }), (0, preact_jsx_runtime.jsx)("div", {
3696
+ class: "bio-properties-panel-popup__drag-handle",
3697
+ children: (0, preact_jsx_runtime.jsx)(DragIcon, {})
3698
+ })] }),
3699
+ (0, preact_jsx_runtime.jsx)("div", {
3700
+ class: "bio-properties-panel-popup__title",
3701
+ children: title
3702
+ }),
3703
+ children,
3704
+ showCloseButton && (0, preact_jsx_runtime.jsx)("button", {
3705
+ title: closeButtonTooltip,
3706
+ class: "bio-properties-panel-popup__close",
3707
+ onClick: onClose,
3708
+ children: (0, preact_jsx_runtime.jsx)(CloseIcon, {})
3709
+ })
3710
+ ]
3711
+ });
3712
+ }
3713
+ function Body(props) {
3714
+ const { children, className, ...rest } = props;
3715
+ return (0, preact_jsx_runtime.jsx)("div", {
3716
+ class: (0, classnames.default)("bio-properties-panel-popup__body", className),
3717
+ ...rest,
3718
+ children
3719
+ });
3720
+ }
3721
+ function Footer(props) {
3722
+ const { children, className, ...rest } = props;
3723
+ return (0, preact_jsx_runtime.jsx)("div", {
3724
+ class: (0, classnames.default)("bio-properties-panel-popup__footer", className),
3725
+ ...rest,
3726
+ children: props.children
3727
+ });
3728
+ }
3729
+ function getPopupParent(node) {
3730
+ return node.closest(".bio-properties-panel-popup");
3731
+ }
3732
+ function cancel(event) {
3733
+ event.preventDefault();
3734
+ event.stopPropagation();
3735
+ }
3736
+ /**
3737
+ * Expression editor popup component
3738
+ * @param {ExpressionPopupProps} props
3739
+ */
3740
+ function ExpressionPopup$1(props) {
3741
+ const { entryId, onInput, onClose, title, type, value, links, variables, position, hostLanguage, singleLine, sourceElement, tooltipContainer, eventBus, feelLanguageContext } = props;
3742
+ const editorRef = (0, preact_hooks.useRef)();
3743
+ const popupRef = (0, preact_hooks.useRef)();
3744
+ const isAutoCompletionOpen = (0, preact_hooks.useRef)(false);
3745
+ const handleSetReturnFocus = () => {
3746
+ sourceElement && sourceElement.focus();
3747
+ };
3748
+ const onKeyDownCapture = (event) => {
3749
+ if (event.key === "Escape") isAutoCompletionOpen.current = autoCompletionOpen(event.target);
3750
+ };
3751
+ const onKeyDown = (event) => {
3752
+ if (event.key === "Escape") {
3753
+ if (!isAutoCompletionOpen.current) {
3754
+ onClose();
3755
+ isAutoCompletionOpen.current = false;
3756
+ }
3757
+ }
3758
+ };
3759
+ (0, preact_hooks.useEffect)(() => {
3760
+ if (editorRef.current) editorRef.current.focus();
3761
+ }, [editorRef]);
3762
+ return (0, preact_jsx_runtime.jsxs)(Popup, {
3763
+ className: "bio-properties-panel-feel-popup",
3764
+ position,
3765
+ title,
3766
+ returnFocus: false,
3767
+ closeOnEscape: false,
3768
+ delayInitialFocus: false,
3769
+ onPostDeactivate: handleSetReturnFocus,
3770
+ height: 250,
3771
+ width: 700,
3772
+ ref: popupRef,
3773
+ children: [(0, preact_jsx_runtime.jsx)(Popup.Title, {
3774
+ title,
3775
+ eventBus,
3776
+ showCloseButton: true,
3777
+ closeButtonTooltip: "Save and close",
3778
+ onClose,
3779
+ draggable: true,
3780
+ children: (0, preact_jsx_runtime.jsx)(preact_jsx_runtime.Fragment, { children: (links || []).map((link, index) => {
3781
+ return (0, preact_jsx_runtime.jsxs)("a", {
3782
+ rel: "noreferrer",
3783
+ href: link.href,
3784
+ target: "_blank",
3785
+ class: "bio-properties-panel-feel-popup__title-link",
3786
+ children: [link.title, (0, preact_jsx_runtime.jsx)(LaunchIcon, {})]
3787
+ }, index);
3788
+ }) })
3789
+ }), (0, preact_jsx_runtime.jsx)(Popup.Body, { children: (0, preact_jsx_runtime.jsxs)("div", {
3790
+ onKeyDownCapture,
3791
+ onKeyDown,
3792
+ class: "bio-properties-panel-feel-popup__body",
3793
+ children: [type === "feel" && (0, preact_jsx_runtime.jsx)(ExpressionEditor, {
3794
+ enableGutters: true,
3795
+ id: prefixId(entryId),
3796
+ name: entryId,
3797
+ onInput,
3798
+ value,
3799
+ variables,
3800
+ feelLanguageContext,
3801
+ ref: editorRef,
3802
+ tooltipContainer
3803
+ }), type === "feelers" && (0, preact_jsx_runtime.jsx)(TemplatingEditor, {
3804
+ id: prefixId(entryId),
3805
+ contentAttributes: { "aria-label": title },
3806
+ enableGutters: true,
3807
+ hostLanguage,
3808
+ name: entryId,
3809
+ onInput,
3810
+ value,
3811
+ ref: editorRef,
3812
+ singleLine,
3813
+ tooltipContainer
3814
+ })]
3815
+ }) })]
3816
+ });
3817
+ }
3818
+ function prefixId(id) {
3819
+ return `bio-properties-panel-${id}`;
3820
+ }
3821
+ function autoCompletionOpen(element) {
3822
+ const editor = element.closest(".cm-editor");
3823
+ return editor ? editor.querySelector(".cm-tooltip-autocomplete") : null;
3824
+ }
3825
+ //#endregion
3826
+ //#region src/features/expression-popup/components/helpers.js
3827
+ function getPopupTitle({ element, label }) {
3828
+ let popupTitle = "";
3829
+ if (element && element.type) popupTitle = `${element.type} / `;
3830
+ return `${popupTitle}${label}`;
3831
+ }
3832
+ function getPopupPosition() {
3833
+ const viewportWidth = window.innerWidth || document.documentElement.clientWidth;
3834
+ const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
3835
+ return {
3836
+ left: Math.max(0, (viewportWidth - 700) / 2),
3837
+ top: Math.max(0, (viewportHeight - 250) / 2)
3838
+ };
3839
+ }
3840
+ //#endregion
3841
+ //#region src/features/expression-popup/ExpressionPopup.js
3842
+ /**
3843
+ * FEEL popup component, built as a singleton.
3844
+ *
3845
+ * In order to implement a custom replacement, handle the following events:
3846
+ * - `propertiesPanel.openPopup`
3847
+ * - `propertiesPanel.closePopup`
3848
+ * - `propertiesPanel.detach`
3849
+ *
3850
+ * Within the custom renderer, make sure to emit the following events:
3851
+ * - `feelPopup.open` - fired before the popup is mounted
3852
+ * - `feelPopup.opened` - fired after the popup is mounted. Event context contains the DOM node of the popup as `domNode`
3853
+ * - `feelPopup.close` - fired before the popup is unmounted. Event context contains the DOM node of the popup as `domNode`
3854
+ * - `feelPopup.closed` - fired after the popup is unmounted
3855
+ */
3856
+ var ExpressionPopup = class {
3857
+ constructor(eventBus, config = {}) {
3858
+ this._eventBus = eventBus;
3859
+ this._config = config;
3860
+ this._isOpen = false;
3861
+ eventBus.on("propertiesPanel.openPopup", (_, context) => {
3862
+ this.open(context.entryId, context, context.sourceElement);
3863
+ return true;
3864
+ });
3865
+ eventBus.on(["propertiesPanel.closePopup", "propertiesPanel.detach"], () => {
3866
+ this.close();
3867
+ });
3868
+ }
3869
+ /**
3870
+ * Check if the FEEL popup is open.
3871
+ * @return {Boolean}
3872
+ */
3873
+ isOpen() {
3874
+ return this._isOpen;
3875
+ }
3876
+ /**
3877
+ * Open the FEEL popup.
3878
+ *
3879
+ * @param {String} entryId
3880
+ * @param {Object} popupConfig
3881
+ * @param {HTMLElement} sourceElement
3882
+ */
3883
+ open(entryId, popupConfig, sourceElement) {
3884
+ this.close();
3885
+ this._openPopup({
3886
+ ...popupConfig,
3887
+ entryId,
3888
+ sourceElement
3889
+ });
3890
+ }
3891
+ /**
3892
+ * Close the FEEL popup.
3893
+ */
3894
+ close() {
3895
+ this._closePopup();
3896
+ }
3897
+ _openPopup(context) {
3898
+ const { element, label, sourceElement, type } = context;
3899
+ this._isOpen = true;
3900
+ this._eventBus.fire("propertiesPanelPopup.open", {
3901
+ container: this._config.feelPopupContainer,
3902
+ config: {
3903
+ ...context,
3904
+ links: this._config.getFeelPopupLinks?.(type) || [],
3905
+ onClose: () => {
3906
+ this._closePopup();
3907
+ setTimeout(() => {
3908
+ sourceElement && sourceElement.focus();
3909
+ }, 0);
3910
+ },
3911
+ position: getPopupPosition(),
3912
+ title: getPopupTitle({
3913
+ element,
3914
+ label
3915
+ })
3916
+ }
3917
+ });
3918
+ }
3919
+ _closePopup() {
3920
+ if (this._isOpen) {
3921
+ this._isOpen = false;
3922
+ this._eventBus.fire("propertiesPanelPopup.close");
3923
+ }
3924
+ }
3925
+ };
3926
+ ExpressionPopup.$inject = ["eventBus", "config.propertiesPanel"];
3927
+ //#endregion
3928
+ //#region src/features/expression-popup/ExpressionPopupRenderer.js
3929
+ var ExpressionPopupRenderer = class {
3930
+ constructor(eventBus) {
3931
+ this._eventBus = eventBus;
3932
+ this._container = null;
3933
+ this._element = null;
3934
+ eventBus.on("propertiesPanelPopup.open", (context) => {
3935
+ this._renderPopup(context);
3936
+ });
3937
+ eventBus.on("propertiesPanelPopup.close", () => {
3938
+ this._removePopup();
3939
+ });
3940
+ }
3941
+ _renderPopup(context) {
3942
+ let { container, config } = context;
3943
+ container = this._container = getContainer(container) || document.body;
3944
+ const element = this._element = createElement();
3945
+ container.appendChild(element);
3946
+ this._emit("feelPopup.open");
3947
+ (0, preact.render)((0, preact_jsx_runtime.jsx)(ExpressionPopup$1, {
3948
+ ...config,
3949
+ eventBus: this._eventBus
3950
+ }), element);
3951
+ this._emit("feelPopup.opened", { domNode: element });
3952
+ }
3953
+ _removePopup() {
3954
+ if (!this._container) return;
3955
+ this._emit("feelPopup.close", { domNode: this._element });
3956
+ (0, preact.render)(null, this._element);
3957
+ this._container.removeChild(this._element);
3958
+ this._container = null;
3959
+ this._emit("feelPopup.closed");
3960
+ }
3961
+ _emit(event, context) {
3962
+ this._eventBus.fire(event, context);
3963
+ }
3964
+ };
3965
+ ExpressionPopupRenderer.$inject = ["eventBus"];
3966
+ function createElement() {
3967
+ const element = document.createElement("div");
3968
+ element.classList.add("bio-properties-panel-popup-container");
3969
+ return element;
3970
+ }
3971
+ function getContainer(container) {
3972
+ if ((0, min_dash.isString)(container)) return (0, min_dom.query)(container);
3973
+ return container;
3974
+ }
3975
+ //#endregion
3976
+ //#region src/features/expression-popup/index.js
3977
+ var expression_popup_default = {
3978
+ __init__: ["expressionPopup", "expressionPopupRenderer"],
3979
+ expressionPopup: ["type", ExpressionPopup],
3980
+ expressionPopupRenderer: ["type", ExpressionPopupRenderer]
3981
+ };
3982
+ //#endregion
3983
+ exports.ArrowIcon = ArrowIcon;
3984
+ exports.CheckboxEntry = CheckboxEntry;
3985
+ exports.CheckboxGroup = CheckboxGroup;
3986
+ exports.CloseIcon = CloseIcon;
3987
+ exports.CollapsibleEntry = CollapsibleEntry;
3988
+ exports.CreateIcon = CreateIcon;
3989
+ exports.DebounceInputModule = debounce_input_default;
3990
+ exports.DeleteIcon = DeleteIcon;
3991
+ exports.DescriptionContext = DescriptionContext;
3992
+ exports.DescriptionEntry = Description;
3993
+ exports.DragIcon = DragIcon;
3994
+ exports.DropdownButton = DropdownButton;
3995
+ exports.ErrorsContext = ErrorsContext;
3996
+ exports.EventContext = EventContext;
3997
+ exports.ExpressionPopupModule = expression_popup_default;
3998
+ exports.ExternalLinkIcon = ExternalLinkIcon;
3999
+ exports.FeelCheckboxEntry = FeelCheckboxEntry;
4000
+ exports.FeelEntry = FeelEntry;
4001
+ exports.FeelIcon = FeelIcon;
4002
+ exports.FeelLanguageContext = FeelLanguageContext;
4003
+ exports.FeelNumberEntry = FeelNumberEntry;
4004
+ exports.FeelTemplatingEntry = FeelTemplatingEntry;
4005
+ exports.FeelTextAreaEntry = FeelTextAreaEntry;
4006
+ exports.FeelToggleSwitchEntry = FeelToggleSwitchEntry;
4007
+ exports.Group = Group;
4008
+ exports.Header = Header;
4009
+ exports.HeaderButton = HeaderButton;
4010
+ exports.JsonEditorEntry = JsonEditorEntry;
4011
+ exports.LaunchIcon = LaunchIcon;
4012
+ exports.LayoutContext = LayoutContext;
4013
+ exports.ListEntry = List;
4014
+ exports.ListGroup = ListGroup;
4015
+ exports.ListItem = ListItem;
4016
+ exports.NumberFieldEntry = NumberFieldEntry;
4017
+ exports.OpenPopupIcon = OpenPopupIcon;
4018
+ exports.Placeholder = Placeholder;
4019
+ exports.PropertiesPanel = PropertiesPanel;
4020
+ exports.PropertiesPanelContext = LayoutContext;
4021
+ exports.SelectEntry = SelectEntry;
4022
+ exports.SimpleEntry = Simple;
4023
+ exports.TemplatingEntry = TemplatingEntry;
4024
+ exports.TextAreaEntry = TextAreaEntry;
4025
+ exports.TextFieldEntry = TextfieldEntry;
4026
+ exports.ToggleSwitchEntry = ToggleSwitchEntry;
4027
+ exports.TooltipContext = TooltipContext;
4028
+ exports.TooltipEntry = TooltipWrapper;
4029
+ exports.isCheckboxEntryEdited = isEdited;
4030
+ exports.isFeelEntryEdited = isEdited$1;
4031
+ exports.isJsonEditorEntryEdited = isEdited$2;
4032
+ exports.isNumberFieldEntryEdited = isEdited$3;
4033
+ exports.isSelectEntryEdited = isEdited$4;
4034
+ exports.isSimpleEntryEdited = isEdited$5;
4035
+ exports.isTemplatingEntryEdited = isEdited$6;
4036
+ exports.isTextAreaEntryEdited = isEdited$7;
4037
+ exports.isTextFieldEntryEdited = isEdited$8;
4038
+ exports.isToggleSwitchEntryEdited = isEdited$9;
4039
+ exports.useDebounce = useDebounce;
4040
+ exports.useDescriptionContext = useDescriptionContext;
4041
+ exports.useElementVisible = useElementVisible;
4042
+ exports.useError = useError;
4043
+ exports.useErrors = useErrors;
4044
+ exports.useEvent = useEvent;
4045
+ exports.useKeyFactory = useKeyFactory;
4046
+ exports.useLayoutState = useLayoutState;
4047
+ exports.usePrevious = usePrevious;
4048
+ exports.useShowEntryEvent = useShowEntryEvent;
4049
+ exports.useStaticCallback = useStaticCallback;
4050
+ exports.useStickyIntersectionObserver = useStickyIntersectionObserver;
4051
+ exports.useTooltipContext = useTooltipContext;
4052
+
4053
+ //# sourceMappingURL=index.js.map