@bpmn-io/properties-panel 0.2.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/assets/properties-panel.css +132 -71
- package/lib/PropertiesPanel.js +4 -1
- package/lib/PropertiesPanel.js.map +1 -1
- package/lib/components/Group.js +1 -1
- package/lib/components/Group.js.map +1 -1
- package/lib/components/ListGroup.js +20 -11
- package/lib/components/ListGroup.js.map +1 -1
- package/lib/components/entries/Collapsible.js +3 -2
- package/lib/components/entries/Collapsible.js.map +1 -1
- package/lib/components/entries/List.js +196 -0
- package/lib/components/entries/List.js.map +1 -0
- package/lib/components/entries/Simple.js +56 -0
- package/lib/components/entries/Simple.js.map +1 -0
- package/lib/components/entries/TextArea.js +9 -4
- package/lib/components/entries/TextArea.js.map +1 -1
- package/lib/hooks/index.js +1 -0
- package/lib/hooks/index.js.map +1 -1
- package/lib/hooks/useKeyFactory.js +39 -0
- package/lib/hooks/useKeyFactory.js.map +1 -0
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,25 @@ All notable changes to [`@bpmn-io/properties-panel`](https://github.com/bpmn-io/
|
|
|
6
6
|
|
|
7
7
|
___Note:__ Yet to be released changes appear here._
|
|
8
8
|
|
|
9
|
+
## 0.4.1
|
|
10
|
+
|
|
11
|
+
* `CHORE`: unbuild custom checkbox component ([#97](https://github.com/bpmn-io/properties-panel/pull/97))
|
|
12
|
+
|
|
13
|
+
## 0.4.0
|
|
14
|
+
|
|
15
|
+
* `FEAT`: add list entry ([#92](https://github.com/bpmn-io/properties-panel/issues/92))
|
|
16
|
+
* `FEAT`: add simple text entry ([#94](https://github.com/bpmn-io/properties-panel/pull/94))
|
|
17
|
+
* `FIX`: use default cursor when hovering collapsible headers ([#95](https://github.com/bpmn-io/properties-panel/pull/95))
|
|
18
|
+
|
|
19
|
+
## 0.3.0
|
|
20
|
+
|
|
21
|
+
* `FEAT`: use semantic HTML for buttons ([#45](https://github.com/bpmn-io/properties-panel/issues/45))
|
|
22
|
+
* `FIX`: prevent list ordering effects on element changes ([#89](https://github.com/bpmn-io/properties-panel/pull/89))
|
|
23
|
+
|
|
24
|
+
## 0.2.1
|
|
25
|
+
|
|
26
|
+
* `FIX`: do not use monospace as default font for text areas ([#87](https://github.com/bpmn-io/properties-panel/pull/87))
|
|
27
|
+
|
|
9
28
|
## 0.2.0
|
|
10
29
|
|
|
11
30
|
* `FEAT`: add number field entry ([#76](https://github.com/bpmn-io/properties-panel/pull/76))
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
--color-red-360-100-97: #fff0f0;
|
|
11
11
|
--color-red-360-100-45: #e60000;
|
|
12
12
|
|
|
13
|
+
--color-grey-225-10-35: hsl(225, 10%, 35%);
|
|
14
|
+
|
|
13
15
|
--color-cccccc: #cccccc;
|
|
14
16
|
--color-aaaaaa: #aaaaaa;
|
|
15
17
|
--color-white: white;
|
|
@@ -173,14 +175,6 @@
|
|
|
173
175
|
margin-right: 0;
|
|
174
176
|
}
|
|
175
177
|
|
|
176
|
-
.bio-properties-panel-group-header-buttons .bio-properties-panel-add-entry {
|
|
177
|
-
width: 20px;
|
|
178
|
-
height: 20px;
|
|
179
|
-
display: inherit;
|
|
180
|
-
justify-content: center;
|
|
181
|
-
align-items: center;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
178
|
.bio-properties-panel-group-header:not(.empty) .bio-properties-panel-add-entry {
|
|
185
179
|
visibility: hidden;
|
|
186
180
|
}
|
|
@@ -225,11 +219,6 @@
|
|
|
225
219
|
margin-bottom: 6px;
|
|
226
220
|
}
|
|
227
221
|
|
|
228
|
-
.bio-properties-panel-list-item .bio-properties-panel-collapsible-entry-entries {
|
|
229
|
-
padding-left: 15px;
|
|
230
|
-
margin-bottom: 10px;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
222
|
.bio-properties-panel-list-badge {
|
|
234
223
|
color: var(--color-white);
|
|
235
224
|
background-color: var(--color-black);
|
|
@@ -278,6 +267,9 @@
|
|
|
278
267
|
border-radius: 3px;
|
|
279
268
|
background-color: var(--color-input-background);
|
|
280
269
|
font-size: 14px;
|
|
270
|
+
font-style: normal;
|
|
271
|
+
font-weight: 400;
|
|
272
|
+
font-family: inherit;
|
|
281
273
|
}
|
|
282
274
|
|
|
283
275
|
.bio-properties-panel-input[type=number],
|
|
@@ -294,65 +286,19 @@ textarea.bio-properties-panel-input,
|
|
|
294
286
|
border: 1px solid var(--color-input-border-focus);
|
|
295
287
|
}
|
|
296
288
|
|
|
297
|
-
.bio-properties-panel-input
|
|
298
|
-
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
.bio-properties-panel-input[type="checkbox"] + label::after,
|
|
302
|
-
.bio-properties-panel-input[type="radio"] + label::after {
|
|
303
|
-
-webkit-transform: scale(0);
|
|
304
|
-
-ms-transform: scale(0);
|
|
305
|
-
-o-transform: scale(0);
|
|
306
|
-
transform: scale(0);
|
|
289
|
+
.bio-properties-panel-input-monospace {
|
|
290
|
+
font-family: monospace;
|
|
307
291
|
}
|
|
308
292
|
|
|
309
|
-
.bio-properties-panel-input[type="checkbox"]
|
|
310
|
-
|
|
311
|
-
-
|
|
312
|
-
-ms-transform: scale(1);
|
|
313
|
-
-o-transform: scale(1);
|
|
314
|
-
transform: scale(1);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
.bio-properties-panel-checkbox {
|
|
318
|
-
margin-top: 12px;
|
|
319
|
-
margin-bottom: 6px;
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
.bio-properties-panel-checkbox .bio-properties-panel-input {
|
|
323
|
-
position: absolute;
|
|
324
|
-
opacity: 0;
|
|
325
|
-
z-index: -1;
|
|
293
|
+
.bio-properties-panel-input[type="checkbox"], .bio-properties-panel-input[type="radio"] {
|
|
294
|
+
margin: 0;
|
|
295
|
+
vertical-align: middle;
|
|
326
296
|
}
|
|
327
297
|
|
|
328
|
-
.bio-properties-panel-checkbox .bio-properties-panel-label {
|
|
329
|
-
position: relative;
|
|
298
|
+
.bio-properties-panel-checkbox > .bio-properties-panel-label {
|
|
330
299
|
display: inline-block;
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
.bio-properties-panel-checkbox .bio-properties-panel-label::before,
|
|
335
|
-
.bio-properties-panel-checkbox .bio-properties-panel-label::after {
|
|
336
|
-
position: absolute;
|
|
337
|
-
top: 0;
|
|
338
|
-
left: 0;
|
|
339
|
-
display: block;
|
|
340
|
-
width: 16px;
|
|
341
|
-
height: 16px;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
.bio-properties-panel-checkbox .bio-properties-panel-label::before {
|
|
345
|
-
content: " ";
|
|
346
|
-
border: 1px solid var(--color-input-border);
|
|
347
|
-
border-radius: 3px;
|
|
348
|
-
background-color:var(--color-000000-opacity-5);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
.bio-properties-panel-checkbox .bio-properties-panel-label::after {
|
|
352
|
-
content: "\2714";
|
|
353
|
-
color: var(--color-text-base);
|
|
354
|
-
line-height: 1.5;
|
|
355
|
-
text-align: center;
|
|
300
|
+
margin-left: 4px;
|
|
301
|
+
vertical-align: middle;
|
|
356
302
|
}
|
|
357
303
|
|
|
358
304
|
textarea.bio-properties-panel-input {
|
|
@@ -374,6 +320,15 @@ textarea.bio-properties-panel-input {
|
|
|
374
320
|
font-size: 13px;
|
|
375
321
|
}
|
|
376
322
|
|
|
323
|
+
.bio-properties-panel-simple {
|
|
324
|
+
width: 100%;
|
|
325
|
+
margin-right: 12px;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.bio-properties-panel-simple + .bio-properties-panel-remove-entry {
|
|
329
|
+
margin: auto;
|
|
330
|
+
}
|
|
331
|
+
|
|
377
332
|
/**
|
|
378
333
|
* Toggle Switch
|
|
379
334
|
*/
|
|
@@ -454,6 +409,8 @@ textarea.bio-properties-panel-input {
|
|
|
454
409
|
}
|
|
455
410
|
|
|
456
411
|
.bio-properties-panel-collapsible-entry-entries {
|
|
412
|
+
padding-left: 15px;
|
|
413
|
+
margin-bottom: 10px;
|
|
457
414
|
position: relative;
|
|
458
415
|
display: none;
|
|
459
416
|
}
|
|
@@ -472,6 +429,7 @@ textarea.bio-properties-panel-input {
|
|
|
472
429
|
white-space: nowrap;
|
|
473
430
|
overflow: hidden;
|
|
474
431
|
text-overflow: ellipsis;
|
|
432
|
+
user-select: none;
|
|
475
433
|
}
|
|
476
434
|
|
|
477
435
|
.bio-properties-panel-collapsible-entry-arrow {
|
|
@@ -484,14 +442,21 @@ textarea.bio-properties-panel-input {
|
|
|
484
442
|
}
|
|
485
443
|
|
|
486
444
|
.bio-properties-panel-remove-entry {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
445
|
+
display: flex;
|
|
446
|
+
align-items: center;
|
|
447
|
+
justify-content: center;
|
|
490
448
|
width: 16px;
|
|
491
449
|
height: 16px;
|
|
450
|
+
|
|
451
|
+
margin-right: 14px;
|
|
452
|
+
padding: 0;
|
|
453
|
+
|
|
454
|
+
border: none;
|
|
455
|
+
background: none;
|
|
492
456
|
visibility: hidden;
|
|
493
457
|
}
|
|
494
458
|
|
|
459
|
+
.bio-properties-panel-list-entry-item:hover .bio-properties-panel-remove-entry,
|
|
495
460
|
.bio-properties-panel-collapsible-entry-header:hover .bio-properties-panel-remove-entry {
|
|
496
461
|
visibility: visible;
|
|
497
462
|
}
|
|
@@ -502,6 +467,102 @@ textarea.bio-properties-panel-input {
|
|
|
502
467
|
left: 10px;
|
|
503
468
|
width: 2px;
|
|
504
469
|
top: 0;
|
|
470
|
+
bottom: 12px;
|
|
471
|
+
background-color: var(--color-grey-225-10-35);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/* Side line extension for non-list entry or open list entry positioned as the last one. */
|
|
475
|
+
.bio-properties-panel-collapsible-entry-entries .bio-properties-panel-entry:not(.bio-properties-panel-list-entry):last-child,
|
|
476
|
+
.bio-properties-panel-list-entry.open:last-child {
|
|
477
|
+
position: relative;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
.bio-properties-panel-collapsible-entry-entries .bio-properties-panel-entry:not(.bio-properties-panel-list-entry):last-child::after,
|
|
481
|
+
.bio-properties-panel-list-entry.open:last-child::after {
|
|
482
|
+
content: "";
|
|
483
|
+
position: absolute;
|
|
484
|
+
left: -17px;
|
|
485
|
+
width: 2px;
|
|
486
|
+
top: 0;
|
|
505
487
|
bottom: 0;
|
|
506
|
-
background-color: var(--color-
|
|
488
|
+
background-color: var(--color-grey-225-10-35);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/* List entry */
|
|
492
|
+
|
|
493
|
+
.bio-properties-panel-list-entry {
|
|
494
|
+
position: relative;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.bio-properties-panel-list-entry-header {
|
|
498
|
+
display: flex;
|
|
499
|
+
justify-content: space-between;
|
|
500
|
+
|
|
501
|
+
height: 32px;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
.bio-properties-panel-list-entry::before {
|
|
505
|
+
content: "";
|
|
506
|
+
width: 8px;
|
|
507
|
+
height: 8px;
|
|
508
|
+
position: absolute;
|
|
509
|
+
left: -20px;
|
|
510
|
+
top: 13px;
|
|
511
|
+
border-radius: 50%;
|
|
512
|
+
background-color: var(--color-grey-225-10-35);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.bio-properties-panel-list-entry-header-title {
|
|
516
|
+
padding: 2px 0;
|
|
517
|
+
font-size: var(--text-size-base);
|
|
518
|
+
white-space: nowrap;
|
|
519
|
+
overflow: hidden;
|
|
520
|
+
text-overflow: ellipsis;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
.bio-properties-panel-list-entry-header-title.open {
|
|
524
|
+
font-weight: 600;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
.bio-properties-panel-list-entry-header-title,
|
|
528
|
+
.bio-properties-panel-list-entry-header-buttons {
|
|
529
|
+
display: flex;
|
|
530
|
+
align-items: center;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
.bio-properties-panel-list-entry-header-buttons > button {
|
|
534
|
+
display: inline-flex;
|
|
535
|
+
justify-content: center;
|
|
536
|
+
align-items: center;
|
|
537
|
+
align-self: center;
|
|
538
|
+
width: 20px;
|
|
539
|
+
height: 20px;
|
|
540
|
+
margin-right: 4px;
|
|
541
|
+
padding: 0;
|
|
542
|
+
border: none;
|
|
543
|
+
background: none;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.bio-properties-panel-list-entry-header-buttons > :last-child {
|
|
547
|
+
margin-right: 0;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.bio-properties-panel-list-entry-items {
|
|
551
|
+
padding: 0;
|
|
552
|
+
margin: 0;
|
|
553
|
+
|
|
554
|
+
list-style: none;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
.bio-properties-panel-list-entry-items:not(.open) {
|
|
558
|
+
display: none;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.bio-properties-panel-list-entry-item {
|
|
562
|
+
display: flex;
|
|
563
|
+
justify-content: space-between;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
.bio-properties-panel-list-entry-item > .bio-properties-panel-remove-entry {
|
|
567
|
+
margin-right: 2px;
|
|
507
568
|
}
|
package/lib/PropertiesPanel.js
CHANGED
|
@@ -27,6 +27,7 @@ const DEFAULT_LAYOUT = {
|
|
|
27
27
|
* @typedef { {
|
|
28
28
|
* add: import('preact').Component,
|
|
29
29
|
* component: import('preact').Component,
|
|
30
|
+
* element: Object,
|
|
30
31
|
* id: String,
|
|
31
32
|
* items: Array<ListItemDefinition>,
|
|
32
33
|
* label: String,
|
|
@@ -102,7 +103,9 @@ export default function PropertiesPanel(props) {
|
|
|
102
103
|
component: GroupComponent = Group,
|
|
103
104
|
id
|
|
104
105
|
} = group;
|
|
105
|
-
return _jsx(GroupComponent, {
|
|
106
|
+
return _jsx(GroupComponent, {
|
|
107
|
+
element: element,
|
|
108
|
+
...group
|
|
106
109
|
}, id);
|
|
107
110
|
})
|
|
108
111
|
})]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/PropertiesPanel.js"],"names":["useState","useEffect","classnames","Header","Group","LayoutContext","DEFAULT_LAYOUT","open","PropertiesPanel","props","element","headerProvider","groups","layoutConfig","layoutChanged","layout","setLayout","createLayoutContext","setLayoutForKey","key","config","layoutContext","map","group","component","GroupComponent","id","overrides"],"mappings":"AAAA,SACEA,QADF,EAEEC,SAFF,QAGO,cAHP;AAKA,OAAOC,UAAP,MAAuB,YAAvB;AAEA,OAAOC,MAAP,MAAmB,qBAAnB;AAEA,OAAOC,KAAP,MAAkB,oBAAlB;AAEA,SACEC,aADF,QAEO,WAFP;;;AAIA,MAAMC,cAAc,GAAG;AACrBC,EAAAA,IAAI,EAAE;AADe,CAAvB;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,eAAe,SAASC,eAAT,CAAyBC,KAAzB,EAAgC;AAC7C,QAAM;AACJC,IAAAA,OADI;AAEJC,IAAAA,cAFI;AAGJC,IAAAA,MAHI;AAIJC,IAAAA,YAAY,GAAG,EAJX;AAKJC,IAAAA;AALI,MAMFL,KANJ;AAQA,QAAM,CAAEM,MAAF,EAAUC,SAAV,IAAwBhB,QAAQ,CAACiB,mBAAmB,CAACJ,YAAD,CAApB,CAAtC;AAEAZ,EAAAA,SAAS,CAAC,MAAM;AACd,QAAI,OAAOa,aAAP,KAAyB,UAA7B,EAAyC;AACvCA,MAAAA,aAAa,CAACC,MAAD,CAAb;AACD;AACF,GAJQ,EAIN,CAAEA,MAAF,EAAUD,aAAV,CAJM,CAAT;;AAMA,QAAMI,eAAe,GAAG,CAACC,GAAD,EAAMC,MAAN,KAAiB;AACvCJ,IAAAA,SAAS,CAAC,EACR,GAAGD,MADK;AAER,OAACI,GAAD,GAAOC;AAFC,KAAD,CAAT;AAID,GALD;;AAOA,QAAMC,aAAa,GAAG;AACpBN,IAAAA,MADoB;AAEpBC,IAAAA,SAFoB;AAGpBE,IAAAA;AAHoB,GAAtB;;AAMA,MAAI,CAACR,OAAL,EAAc;AACZ,WAAO;AAAK,MAAA,KAAK,EAAC,kCAAX;AAAA;AAAA,MAAP;AACD;;AAED,SAAO,KAAC,aAAD,CAAe,QAAf;AAAwB,IAAA,KAAK,EAAGW,aAAhC;AAAA,cACL;AACE,MAAA,KAAK,EAAGnB,UAAU,CAChB,sBADgB,EAEhBa,MAAM,CAACR,IAAP,GAAc,MAAd,GAAuB,EAFP,CADpB;AAAA,iBAKE,KAAC,MAAD;AACE,QAAA,OAAO,EAAGG,OADZ;AAEE,QAAA,cAAc,EAAGC;AAFnB,QALF,EAQE;AAAK,QAAA,KAAK,EAAC,uCAAX;AAAA,kBAEIC,MAAM,CAACU,GAAP,CAAWC,KAAK,IAAI;AAElB,gBAAM;AACJC,YAAAA,SAAS,EAAEC,cAAc,GAAGrB,KADxB;AAEJsB,YAAAA;AAFI,cAGFH,KAHJ;AAKA,iBAAO,KAAC,cAAD,
|
|
1
|
+
{"version":3,"sources":["../src/PropertiesPanel.js"],"names":["useState","useEffect","classnames","Header","Group","LayoutContext","DEFAULT_LAYOUT","open","PropertiesPanel","props","element","headerProvider","groups","layoutConfig","layoutChanged","layout","setLayout","createLayoutContext","setLayoutForKey","key","config","layoutContext","map","group","component","GroupComponent","id","overrides"],"mappings":"AAAA,SACEA,QADF,EAEEC,SAFF,QAGO,cAHP;AAKA,OAAOC,UAAP,MAAuB,YAAvB;AAEA,OAAOC,MAAP,MAAmB,qBAAnB;AAEA,OAAOC,KAAP,MAAkB,oBAAlB;AAEA,SACEC,aADF,QAEO,WAFP;;;AAIA,MAAMC,cAAc,GAAG;AACrBC,EAAAA,IAAI,EAAE;AADe,CAAvB;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,eAAe,SAASC,eAAT,CAAyBC,KAAzB,EAAgC;AAC7C,QAAM;AACJC,IAAAA,OADI;AAEJC,IAAAA,cAFI;AAGJC,IAAAA,MAHI;AAIJC,IAAAA,YAAY,GAAG,EAJX;AAKJC,IAAAA;AALI,MAMFL,KANJ;AAQA,QAAM,CAAEM,MAAF,EAAUC,SAAV,IAAwBhB,QAAQ,CAACiB,mBAAmB,CAACJ,YAAD,CAApB,CAAtC;AAEAZ,EAAAA,SAAS,CAAC,MAAM;AACd,QAAI,OAAOa,aAAP,KAAyB,UAA7B,EAAyC;AACvCA,MAAAA,aAAa,CAACC,MAAD,CAAb;AACD;AACF,GAJQ,EAIN,CAAEA,MAAF,EAAUD,aAAV,CAJM,CAAT;;AAMA,QAAMI,eAAe,GAAG,CAACC,GAAD,EAAMC,MAAN,KAAiB;AACvCJ,IAAAA,SAAS,CAAC,EACR,GAAGD,MADK;AAER,OAACI,GAAD,GAAOC;AAFC,KAAD,CAAT;AAID,GALD;;AAOA,QAAMC,aAAa,GAAG;AACpBN,IAAAA,MADoB;AAEpBC,IAAAA,SAFoB;AAGpBE,IAAAA;AAHoB,GAAtB;;AAMA,MAAI,CAACR,OAAL,EAAc;AACZ,WAAO;AAAK,MAAA,KAAK,EAAC,kCAAX;AAAA;AAAA,MAAP;AACD;;AAED,SAAO,KAAC,aAAD,CAAe,QAAf;AAAwB,IAAA,KAAK,EAAGW,aAAhC;AAAA,cACL;AACE,MAAA,KAAK,EAAGnB,UAAU,CAChB,sBADgB,EAEhBa,MAAM,CAACR,IAAP,GAAc,MAAd,GAAuB,EAFP,CADpB;AAAA,iBAKE,KAAC,MAAD;AACE,QAAA,OAAO,EAAGG,OADZ;AAEE,QAAA,cAAc,EAAGC;AAFnB,QALF,EAQE;AAAK,QAAA,KAAK,EAAC,uCAAX;AAAA,kBAEIC,MAAM,CAACU,GAAP,CAAWC,KAAK,IAAI;AAElB,gBAAM;AACJC,YAAAA,SAAS,EAAEC,cAAc,GAAGrB,KADxB;AAEJsB,YAAAA;AAFI,cAGFH,KAHJ;AAKA,iBAAO,KAAC,cAAD;AAEL,YAAA,OAAO,EAAGb,OAFL;AAAA,eAGAa;AAHA,aACCG,EADD,CAAP;AAID,SAXD;AAFJ,QARF;AAAA;AADK,IAAP;AA2BD,C,CAGD;;AAEA,SAAST,mBAAT,CAA6BU,SAA7B,EAAwC;AACtC,SAAO,EACL,GAAGrB,cADE;AAEL,OAAGqB;AAFE,GAAP;AAID","sourcesContent":["import {\n useState,\n useEffect\n} from 'preact/hooks';\n\nimport classnames from 'classnames';\n\nimport Header from './components/Header';\n\nimport Group from './components/Group';\n\nimport {\n LayoutContext\n} from './context';\n\nconst DEFAULT_LAYOUT = {\n open: true\n};\n\n\n/**\n * @typedef { {\n * component: import('preact').ComponentChild,\n * id: String,\n * isEdited?: Function\n * } } EntryDefinition\n *\n * @typedef { {\n * autoFocusEntry: String,\n * autoOpen?: Boolean,\n * entries: Array<EntryDefinition>,\n * id: String,\n * label: String,\n * remove: import('preact').Component\n * } } ListItemDefinition\n *\n * @typedef { {\n * add: import('preact').Component,\n * component: import('preact').Component,\n * element: Object,\n * id: String,\n * items: Array<ListItemDefinition>,\n * label: String,\n * shouldSort?: Boolean\n * } } ListGroupDefinition\n *\n * @typedef { {\n * component?: import('preact').Component,\n * entries: Array<EntryDefinition>,\n * id: String,\n * label: String\n * } } GroupDefinition\n *\n */\n\n\n/**\n * A basic properties panel component. Describes *how* content will be rendered, accepts\n * data from implementor to describe *what* will be rendered.\n *\n * @param {Object} props\n * @param {Object} props.element\n * @param {import('./components/Header').HeaderProvider} props.headerProvider\n * @param {Array<GroupDefinition|ListGroupDefinition>} props.groups\n * @param {Object} [props.layoutConfig]\n * @param {Function} [props.layoutChanged]\n */\nexport default function PropertiesPanel(props) {\n const {\n element,\n headerProvider,\n groups,\n layoutConfig = {},\n layoutChanged\n } = props;\n\n const [ layout, setLayout ] = useState(createLayoutContext(layoutConfig));\n\n useEffect(() => {\n if (typeof layoutChanged === 'function') {\n layoutChanged(layout);\n }\n }, [ layout, layoutChanged ]);\n\n const setLayoutForKey = (key, config) => {\n setLayout({\n ...layout,\n [key]: config\n });\n };\n\n const layoutContext = {\n layout,\n setLayout,\n setLayoutForKey\n };\n\n if (!element) {\n return <div class=\"bio-properties-panel-placeholder\">Select an element to edit its properties.</div>;\n }\n\n return <LayoutContext.Provider value={ layoutContext }>\n <div\n class={ classnames(\n 'bio-properties-panel',\n layout.open ? 'open' : '')\n }>\n <Header\n element={ element }\n headerProvider={ headerProvider } />\n <div class=\"bio-properties-panel-scroll-container\">\n {\n groups.map(group => {\n\n const {\n component: GroupComponent = Group,\n id\n } = group;\n\n return <GroupComponent\n key={ id }\n element={ element }\n { ...group } />;\n })\n }\n </div>\n </div>\n </LayoutContext.Provider>;\n}\n\n\n// helpers //////////////////\n\nfunction createLayoutContext(overrides) {\n return {\n ...DEFAULT_LAYOUT,\n ...overrides\n };\n}\n"],"file":"PropertiesPanel.js"}
|
package/lib/components/Group.js
CHANGED
|
@@ -50,7 +50,7 @@ export default function Group(props) {
|
|
|
50
50
|
children: label
|
|
51
51
|
}), _jsxs("div", {
|
|
52
52
|
class: "bio-properties-panel-group-header-buttons",
|
|
53
|
-
children: [edited && _jsx(DataMarker, {}), _jsx("
|
|
53
|
+
children: [edited && _jsx(DataMarker, {}), _jsx("button", {
|
|
54
54
|
class: "bio-properties-panel-group-header-button",
|
|
55
55
|
children: _jsx(GroupArrowIcon, {
|
|
56
56
|
class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/Group.js"],"names":["useEffect","useState","classnames","query","domQuery","isFunction","GroupArrowIcon","Group","props","id","entries","label","open","setOpen","toggleOpen","edited","setEdited","hasOneEditedEntry","find","entry","isEdited","entryNode","inputNode","getTitleAttribute","map","e","component","DataMarker"],"mappings":"AAAA,SACEA,SADF,EAEEC,QAFF,QAGO,cAHP;AAKA,OAAOC,UAAP,MAAuB,YAAvB;AAEA,SACEC,KAAK,IAAIC,QADX,QAEO,SAFP;AAIA,SACEC,UADF,QAEO,UAFP;AAIA,SAASC,cAAT,QAA+B,SAA/B;AAEA;AACA;AACA;;;;AACA,eAAe,SAASC,KAAT,CAAeC,KAAf,EAAsB;AACnC,QAAM;AACJC,IAAAA,EADI;AAEJC,IAAAA,OAAO,GAAG,EAFN;AAGJC,IAAAA;AAHI,MAIFH,KAJJ;AAMA,QAAM,CAAEI,IAAF,EAAQC,OAAR,IAAoBZ,QAAQ,CAAC,KAAD,CAAlC;;AAEA,QAAMa,UAAU,GAAG,MAAMD,OAAO,CAAC,CAACD,IAAF,CAAhC;;AAEA,QAAM,CAAEG,MAAF,EAAUC,SAAV,IAAwBf,QAAQ,CAAC,KAAD,CAAtC,CAXmC,CAanC;;AACAD,EAAAA,SAAS,CAAC,MAAM;AACd,UAAMiB,iBAAiB,GAAGP,OAAO,CAACQ,IAAR,CAAaC,KAAK,IAAI;AAC9C,YAAM;AACJV,QAAAA,EADI;AAEJW,QAAAA;AAFI,UAGFD,KAHJ;AAKA,YAAME,SAAS,GAAGjB,QAAQ,CAAE,mBAAkBK,EAAG,IAAvB,CAA1B;;AAEA,UAAI,CAACJ,UAAU,CAACe,QAAD,CAAX,IAAyB,CAACC,SAA9B,EAAyC;AACvC,eAAO,KAAP;AACD;;AAED,YAAMC,SAAS,GAAGlB,QAAQ,CAAC,6BAAD,EAAgCiB,SAAhC,CAA1B;AAEA,aAAOD,QAAQ,CAACE,SAAD,CAAf;AACD,KAfyB,CAA1B;AAiBAN,IAAAA,SAAS,CAACC,iBAAD,CAAT;AACD,GAnBQ,EAmBN,CAAEP,OAAF,CAnBM,CAAT;AAqBA,SAAO;AAAK,IAAA,KAAK,EAAC,4BAAX;AAAwC,qBAAgB,WAAWD,EAAnE;AAAA,eACL;AAAK,MAAA,KAAK,EAAGP,UAAU,CACrB,mCADqB,EAErBa,MAAM,GAAG,EAAH,GAAQ,OAFO,CAAvB;AAGI,MAAA,OAAO,EAAGD,UAHd;AAAA,iBAIE;AAAK,QAAA,KAAK,EAAGS,iBAAiB,CAACZ,KAAD,EAAQI,MAAR,CAA9B;AAAgD,QAAA,KAAK,EAAC,yCAAtD;AAAA,kBACIJ;AADJ,QAJF,EAOE;AAAK,QAAA,KAAK,EAAC,2CAAX;AAAA,mBAEII,MAAM,IAAI,KAAC,UAAD,KAFd,EAIE;
|
|
1
|
+
{"version":3,"sources":["../../src/components/Group.js"],"names":["useEffect","useState","classnames","query","domQuery","isFunction","GroupArrowIcon","Group","props","id","entries","label","open","setOpen","toggleOpen","edited","setEdited","hasOneEditedEntry","find","entry","isEdited","entryNode","inputNode","getTitleAttribute","map","e","component","DataMarker"],"mappings":"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","sourcesContent":["import {\n useEffect,\n useState\n} from 'preact/hooks';\n\nimport classnames from 'classnames';\n\nimport {\n query as domQuery\n} from 'min-dom';\n\nimport {\n isFunction\n} from 'min-dash';\n\nimport { GroupArrowIcon } from './icons';\n\n/**\n * @param {import('../PropertiesPanel').GroupDefinition} props\n */\nexport default function Group(props) {\n const {\n id,\n entries = [],\n label\n } = props;\n\n const [ open, setOpen ] = useState(false);\n\n const toggleOpen = () => setOpen(!open);\n\n const [ edited, setEdited ] = useState(false);\n\n // set edited state depending on all entries\n useEffect(() => {\n const hasOneEditedEntry = entries.find(entry => {\n const {\n id,\n isEdited\n } = entry;\n\n const entryNode = domQuery(`[data-entry-id=\"${id}\"]`);\n\n if (!isFunction(isEdited) || !entryNode) {\n return false;\n }\n\n const inputNode = domQuery('.bio-properties-panel-input', entryNode);\n\n return isEdited(inputNode);\n });\n\n setEdited(hasOneEditedEntry);\n }, [ entries ]);\n\n return <div class=\"bio-properties-panel-group\" data-group-id={ 'group-' + id }>\n <div class={ classnames(\n 'bio-properties-panel-group-header',\n edited ? '' : 'empty'\n ) } onClick={ toggleOpen }>\n <div title={ getTitleAttribute(label, edited) } class=\"bio-properties-panel-group-header-title\">\n { label }\n </div>\n <div class=\"bio-properties-panel-group-header-buttons\">\n {\n edited && <DataMarker />\n }\n <button class=\"bio-properties-panel-group-header-button\">\n <GroupArrowIcon class={ open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right' } />\n </button>\n </div>\n </div>\n <div class={ classnames(\n 'bio-properties-panel-group-entries',\n open ? 'open' : ''\n ) }>\n {\n entries.map(e => e.component)\n }\n </div>\n </div>;\n}\n\nfunction DataMarker() {\n return (\n <div class=\"bio-properties-panel-dot\">\n <svg\n aria-label=\"edited\" role=\"img\" xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 100 100\"\n >\n <circle fill=\"currentColor\" cx=\"50\" cy=\"50\" r=\"50\" />\n </svg>\n </div>\n );\n}\n\n\n// helper //////////////\n\nfunction getTitleAttribute(label, edited) {\n return label + (edited ? ' (edited)' : '');\n}"],"file":"Group.js"}
|
|
@@ -15,6 +15,7 @@ const noop = () => {};
|
|
|
15
15
|
|
|
16
16
|
export default function ListGroup(props) {
|
|
17
17
|
const {
|
|
18
|
+
element,
|
|
18
19
|
id,
|
|
19
20
|
items,
|
|
20
21
|
label,
|
|
@@ -24,17 +25,25 @@ export default function ListGroup(props) {
|
|
|
24
25
|
const [open, setOpen] = useState(false);
|
|
25
26
|
const [ordering, setOrdering] = useState([]);
|
|
26
27
|
const [newItemAdded, setNewItemAdded] = useState(false);
|
|
27
|
-
const prevItems = usePrevious(items);
|
|
28
|
+
const prevItems = usePrevious(items);
|
|
29
|
+
const prevElement = usePrevious(element);
|
|
30
|
+
const elementChanged = element !== prevElement;
|
|
31
|
+
const shouldHandleEffects = !elementChanged && shouldSort; // reset initial ordering when element changes (before first render)
|
|
32
|
+
|
|
33
|
+
if (elementChanged) {
|
|
34
|
+
setOrdering(createOrdering(shouldSort ? sortItems(items) : items));
|
|
35
|
+
} // keep ordering in sync to items - and open changes
|
|
28
36
|
// (0) set initial ordering from given items
|
|
29
37
|
|
|
38
|
+
|
|
30
39
|
useEffect(() => {
|
|
31
40
|
if (!prevItems || !shouldSort) {
|
|
32
41
|
setOrdering(createOrdering(items));
|
|
33
42
|
}
|
|
34
|
-
}, [items]); // (1) items were added
|
|
43
|
+
}, [items, element]); // (1) items were added
|
|
35
44
|
|
|
36
45
|
useEffect(() => {
|
|
37
|
-
if (
|
|
46
|
+
if (shouldHandleEffects && prevItems && items.length > prevItems.length) {
|
|
38
47
|
let add = [];
|
|
39
48
|
items.forEach(item => {
|
|
40
49
|
if (!ordering.includes(item.id)) {
|
|
@@ -55,17 +64,17 @@ export default function ListGroup(props) {
|
|
|
55
64
|
} else {
|
|
56
65
|
setNewItemAdded(false);
|
|
57
66
|
}
|
|
58
|
-
}, [items, open]); // (2) sort items on open
|
|
67
|
+
}, [items, open, shouldHandleEffects]); // (2) sort items on open
|
|
59
68
|
|
|
60
69
|
useEffect(() => {
|
|
61
70
|
// we already sorted as items were added
|
|
62
|
-
if (
|
|
71
|
+
if (shouldHandleEffects && open && !newItemAdded) {
|
|
63
72
|
setOrdering(createOrdering(sortItems(items)));
|
|
64
73
|
}
|
|
65
|
-
}, [open]); // (3) items were deleted
|
|
74
|
+
}, [open, shouldHandleEffects]); // (3) items were deleted
|
|
66
75
|
|
|
67
76
|
useEffect(() => {
|
|
68
|
-
if (
|
|
77
|
+
if (shouldHandleEffects && prevItems && items.length < prevItems.length) {
|
|
69
78
|
let keep = [];
|
|
70
79
|
ordering.forEach(o => {
|
|
71
80
|
if (getItem(items, o)) {
|
|
@@ -74,7 +83,7 @@ export default function ListGroup(props) {
|
|
|
74
83
|
});
|
|
75
84
|
setOrdering(keep);
|
|
76
85
|
}
|
|
77
|
-
}, [items]);
|
|
86
|
+
}, [items, shouldHandleEffects]);
|
|
78
87
|
|
|
79
88
|
const toggleOpen = () => setOpen(!open);
|
|
80
89
|
|
|
@@ -92,14 +101,14 @@ export default function ListGroup(props) {
|
|
|
92
101
|
}), _jsxs("div", {
|
|
93
102
|
class: "bio-properties-panel-group-header-buttons",
|
|
94
103
|
children: [AddContainer ? _jsx(AddContainer, {
|
|
95
|
-
children: _jsx("
|
|
96
|
-
class: "bio-properties-panel-add-entry",
|
|
104
|
+
children: _jsx("button", {
|
|
105
|
+
class: "bio-properties-panel-group-header-button bio-properties-panel-add-entry",
|
|
97
106
|
children: _jsx(CreateIcon, {})
|
|
98
107
|
})
|
|
99
108
|
}) : null, hasItems ? _jsx("div", {
|
|
100
109
|
class: "bio-properties-panel-list-badge",
|
|
101
110
|
children: items.length
|
|
102
|
-
}) : null, hasItems ? _jsx("
|
|
111
|
+
}) : null, hasItems ? _jsx("button", {
|
|
103
112
|
class: "bio-properties-panel-group-header-button",
|
|
104
113
|
children: _jsx(GroupArrowIcon, {
|
|
105
114
|
class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/ListGroup.js"],"names":["useState","useEffect","classnames","find","sortBy","usePrevious","ListItem","CreateIcon","GroupArrowIcon","noop","ListGroup","props","id","items","label","add","AddContainer","shouldSort","open","setOpen","ordering","setOrdering","newItemAdded","setNewItemAdded","prevItems","createOrdering","length","forEach","item","includes","push","newOrdering","sortItems","removeDuplicates","keep","o","getItem","toggleOpen","hasItems","getTitleAttribute","map","index","i","toLowerCase","filter","indexOf","count"],"mappings":"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","sourcesContent":["import {\n useState,\n useEffect\n} from 'preact/hooks';\n\nimport classnames from 'classnames';\n\nimport {\n find,\n sortBy\n} from 'min-dash';\n\nimport {\n usePrevious\n} from '../hooks';\n\nimport ListItem from './ListItem';\n\nimport {\n CreateIcon,\n GroupArrowIcon\n} from './icons';\n\nconst noop = () => {};\n\n/**\n * @param {import('../PropertiesPanel').ListGroupDefinition} props\n */\nexport default function ListGroup(props) {\n const {\n id,\n items,\n label,\n add: AddContainer,\n shouldSort = true\n } = props;\n\n const [ open, setOpen ] = useState(false);\n const [ ordering, setOrdering ] = useState([]);\n const [ newItemAdded, setNewItemAdded ] = useState(false);\n\n const prevItems = usePrevious(items);\n\n\n // keep ordering in sync to items and open changes\n\n // (0) set initial ordering from given items\n useEffect(() => {\n if (!prevItems || !shouldSort) {\n setOrdering(createOrdering(items));\n }\n }, [ items ]);\n\n // (1) items were added\n useEffect(() => {\n if (shouldSort && prevItems && items.length > prevItems.length) {\n\n let add = [];\n\n items.forEach(item => {\n if (!ordering.includes(item.id)) {\n add.push(item.id);\n }\n });\n\n let newOrdering = ordering;\n\n // sort + open if closed\n if (!open) {\n newOrdering = createOrdering(sortItems(items));\n setOpen(true);\n }\n\n // add new items on top\n newOrdering = removeDuplicates([\n ...add,\n ...newOrdering\n ]);\n\n setOrdering(newOrdering);\n setNewItemAdded(true);\n } else {\n setNewItemAdded(false);\n }\n }, [ items, open ]);\n\n // (2) sort items on open\n useEffect(() => {\n\n // we already sorted as items were added\n if (shouldSort && open && !newItemAdded) {\n setOrdering(createOrdering(sortItems(items)));\n }\n }, [ open ]);\n\n // (3) items were deleted\n useEffect(() => {\n if (shouldSort && prevItems && items.length < prevItems.length) {\n let keep = [];\n\n ordering.forEach(o => {\n if (getItem(items, o)) {\n keep.push(o);\n }\n });\n\n setOrdering(keep);\n }\n }, [ items ]);\n\n const toggleOpen = () => setOpen(!open);\n\n const hasItems = !!items.length;\n\n\n return <div class=\"bio-properties-panel-group\" data-group-id={ 'group-' + id }>\n <div\n class={ classnames(\n 'bio-properties-panel-group-header',\n hasItems ? '' : 'empty'\n ) }\n onClick={ hasItems ? toggleOpen : noop }>\n <div title={ getTitleAttribute(label, items) } class=\"bio-properties-panel-group-header-title\">\n { label }\n </div>\n <div class=\"bio-properties-panel-group-header-buttons\">\n {\n AddContainer\n ? (\n <AddContainer>\n <div class=\"bio-properties-panel-add-entry\">\n <CreateIcon />\n </div>\n </AddContainer>\n )\n : null\n }\n {\n hasItems\n ? (\n <div class=\"bio-properties-panel-list-badge\">\n { items.length }\n </div>\n )\n : null\n }\n {\n hasItems\n ? (\n <div class=\"bio-properties-panel-group-header-button\">\n <GroupArrowIcon class={ open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right' } />\n </div>\n )\n : null\n }\n </div>\n </div>\n <div class={ classnames(\n 'bio-properties-panel-list',\n open && hasItems ? 'open' : ''\n ) }>\n {\n ordering.map((o, index) => {\n const item = getItem(items, o);\n\n if (!item) {\n return;\n }\n\n return (\n <ListItem\n key={ item.id }\n autoOpen={ index === 0 && newItemAdded } // open first item when recently added\n { ...item } />\n );\n })\n }\n </div>\n </div>;\n}\n\n\n// helpers ////////////////////\n\n/**\n * Sorts given items alphanumeric by label\n */\nfunction sortItems(items) {\n return sortBy(items, i => i.label.toLowerCase());\n}\n\nfunction getItem(items, id) {\n return find(items, i => i.id === id);\n}\n\nfunction createOrdering(items) {\n return items.map(i => i.id);\n}\n\nfunction removeDuplicates(items) {\n return items.filter((i, index) => items.indexOf(i) === index);\n}\n\nfunction getTitleAttribute(label, items) {\n const count = items.length;\n\n return label + (count ? ` (${count} item${count != 1 ? 's' : ''})` : '');\n}"],"file":"ListGroup.js"}
|
|
1
|
+
{"version":3,"sources":["../../src/components/ListGroup.js"],"names":["useState","useEffect","classnames","find","sortBy","usePrevious","ListItem","CreateIcon","GroupArrowIcon","noop","ListGroup","props","element","id","items","label","add","AddContainer","shouldSort","open","setOpen","ordering","setOrdering","newItemAdded","setNewItemAdded","prevItems","prevElement","elementChanged","shouldHandleEffects","createOrdering","sortItems","length","forEach","item","includes","push","newOrdering","removeDuplicates","keep","o","getItem","toggleOpen","hasItems","getTitleAttribute","map","index","i","toLowerCase","filter","indexOf","count"],"mappings":"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","sourcesContent":["import {\n useState,\n useEffect\n} from 'preact/hooks';\n\nimport classnames from 'classnames';\n\nimport {\n find,\n sortBy\n} from 'min-dash';\n\nimport {\n usePrevious\n} from '../hooks';\n\nimport ListItem from './ListItem';\n\nimport {\n CreateIcon,\n GroupArrowIcon\n} from './icons';\n\nconst noop = () => {};\n\n/**\n * @param {import('../PropertiesPanel').ListGroupDefinition} props\n */\nexport default function ListGroup(props) {\n const {\n element,\n id,\n items,\n label,\n add: AddContainer,\n shouldSort = true\n } = props;\n\n const [ open, setOpen ] = useState(false);\n const [ ordering, setOrdering ] = useState([]);\n const [ newItemAdded, setNewItemAdded ] = useState(false);\n\n const prevItems = usePrevious(items);\n const prevElement = usePrevious(element);\n\n const elementChanged = element !== prevElement;\n const shouldHandleEffects = !elementChanged && shouldSort;\n\n // reset initial ordering when element changes (before first render)\n if (elementChanged) {\n setOrdering(createOrdering(shouldSort ? sortItems(items) : items));\n }\n\n // keep ordering in sync to items - and open changes\n\n // (0) set initial ordering from given items\n useEffect(() => {\n if (!prevItems || !shouldSort) {\n setOrdering(createOrdering(items));\n }\n }, [ items, element ]);\n\n // (1) items were added\n useEffect(() => {\n if (shouldHandleEffects && prevItems && items.length > prevItems.length) {\n\n let add = [];\n\n items.forEach(item => {\n if (!ordering.includes(item.id)) {\n add.push(item.id);\n }\n });\n\n let newOrdering = ordering;\n\n // sort + open if closed\n if (!open) {\n newOrdering = createOrdering(sortItems(items));\n setOpen(true);\n }\n\n // add new items on top\n newOrdering = removeDuplicates([\n ...add,\n ...newOrdering\n ]);\n\n setOrdering(newOrdering);\n setNewItemAdded(true);\n } else {\n setNewItemAdded(false);\n }\n }, [ items, open, shouldHandleEffects ]);\n\n // (2) sort items on open\n useEffect(() => {\n\n // we already sorted as items were added\n if (shouldHandleEffects && open && !newItemAdded) {\n setOrdering(createOrdering(sortItems(items)));\n }\n }, [ open, shouldHandleEffects ]);\n\n // (3) items were deleted\n useEffect(() => {\n if (shouldHandleEffects && prevItems && items.length < prevItems.length) {\n let keep = [];\n\n ordering.forEach(o => {\n if (getItem(items, o)) {\n keep.push(o);\n }\n });\n\n setOrdering(keep);\n }\n }, [ items, shouldHandleEffects ]);\n\n const toggleOpen = () => setOpen(!open);\n\n const hasItems = !!items.length;\n\n return <div class=\"bio-properties-panel-group\" data-group-id={ 'group-' + id }>\n <div\n class={ classnames(\n 'bio-properties-panel-group-header',\n hasItems ? '' : 'empty'\n ) }\n onClick={ hasItems ? toggleOpen : noop }>\n <div title={ getTitleAttribute(label, items) } class=\"bio-properties-panel-group-header-title\">\n { label }\n </div>\n <div class=\"bio-properties-panel-group-header-buttons\">\n {\n AddContainer\n ? (\n <AddContainer>\n <button class=\"bio-properties-panel-group-header-button bio-properties-panel-add-entry\">\n <CreateIcon />\n </button>\n </AddContainer>\n )\n : null\n }\n {\n hasItems\n ? (\n <div class=\"bio-properties-panel-list-badge\">\n { items.length }\n </div>\n )\n : null\n }\n {\n hasItems\n ? (\n <button class=\"bio-properties-panel-group-header-button\">\n <GroupArrowIcon class={ open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right' } />\n </button>\n )\n : null\n }\n </div>\n </div>\n <div class={ classnames(\n 'bio-properties-panel-list',\n open && hasItems ? 'open' : ''\n ) }>\n {\n ordering.map((o, index) => {\n const item = getItem(items, o);\n\n if (!item) {\n return;\n }\n\n return (\n <ListItem\n key={ item.id }\n autoOpen={ index === 0 && newItemAdded } // open first item when recently added\n { ...item } />\n );\n })\n }\n </div>\n </div>;\n}\n\n\n// helpers ////////////////////\n\n/**\n * Sorts given items alphanumeric by label\n */\nfunction sortItems(items) {\n return sortBy(items, i => i.label.toLowerCase());\n}\n\nfunction getItem(items, id) {\n return find(items, i => i.id === id);\n}\n\nfunction createOrdering(items) {\n return items.map(i => i.id);\n}\n\nfunction removeDuplicates(items) {\n return items.filter((i, index) => items.indexOf(i) === index);\n}\n\nfunction getTitleAttribute(label, items) {\n const count = items.length;\n\n return label + (count ? ` (${count} item${count != 1 ? 's' : ''})` : '');\n}"],"file":"ListGroup.js"}
|
|
@@ -32,8 +32,9 @@ export default function CollapsibleEntry(props) {
|
|
|
32
32
|
class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
|
|
33
33
|
})
|
|
34
34
|
}), RemoveContainer ? _jsx(RemoveContainer, {
|
|
35
|
-
children: _jsx(
|
|
36
|
-
class: "bio-properties-panel-remove-entry"
|
|
35
|
+
children: _jsx("button", {
|
|
36
|
+
class: "bio-properties-panel-remove-entry",
|
|
37
|
+
children: _jsx(ListDeleteIcon, {})
|
|
37
38
|
})
|
|
38
39
|
}) : null]
|
|
39
40
|
}), _jsx("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/entries/Collapsible.js"],"names":["useState","classnames","ListArrowIcon","ListDeleteIcon","CollapsibleEntry","props","id","entries","label","remove","RemoveContainer","open","shouldOpen","setOpen","toggleOpen","placeholderLabel","map","e","component"],"mappings":"AAAA,SACEA,QADF,QAEO,cAFP;AAIA,OAAOC,UAAP,MAAuB,YAAvB;AAEA,SACEC,aADF,EAEEC,cAFF,QAGO,UAHP;;;AAMA,eAAe,SAASC,gBAAT,CAA0BC,KAA1B,EAAiC;AAC9C,QAAM;AACJC,IAAAA,EADI;AAEJC,IAAAA,OAAO,GAAG,EAFN;AAGJC,IAAAA,KAHI;AAIJC,IAAAA,MAAM,EAAEC,eAJJ;AAKJC,IAAAA,IAAI,EAAEC;AALF,MAMFP,KANJ;AAQA,QAAM,CAAEM,IAAF,EAAQE,OAAR,IAAoBb,QAAQ,CAACY,UAAD,CAAlC;;AAEA,QAAME,UAAU,GAAG,MAAMD,OAAO,CAAC,CAACF,IAAF,CAAhC,CAX8C,CAa9C;;;AACA,QAAMI,gBAAgB,GAAG,SAAzB;AAEA,SACE;AACE,qBAAgBT,EADlB;AAEE,IAAA,KAAK,EAAGL,UAAU,CAChB,wCADgB,EAEhBU,IAAI,GAAG,MAAH,GAAY,EAFA,CAFpB;AAAA,eAME;AAAK,MAAA,KAAK,EAAC,+CAAX;AAA2D,MAAA,OAAO,EAAGG,UAArE;AAAA,iBACE;AACE,QAAA,KAAK,EAAGb,UAAU,CAChB,qDADgB,EAEhB,CAACO,KAAD,IAAU,OAFM,CADpB;AAAA,kBAKIA,KAAK,IAAIO;AALb,QADF,EAQE;AAAK,QAAA,KAAK,EAAC,8CAAX;AAAA,kBACE,KAAC,aAAD;AAAe,UAAA,KAAK,EAAGJ,IAAI,GAAG,iCAAH,GAAuC;AAAlE;AADF,QARF,EAYID,eAAe,GAGX,KAAC,eAAD;AAAA,kBACE
|
|
1
|
+
{"version":3,"sources":["../../../src/components/entries/Collapsible.js"],"names":["useState","classnames","ListArrowIcon","ListDeleteIcon","CollapsibleEntry","props","id","entries","label","remove","RemoveContainer","open","shouldOpen","setOpen","toggleOpen","placeholderLabel","map","e","component"],"mappings":"AAAA,SACEA,QADF,QAEO,cAFP;AAIA,OAAOC,UAAP,MAAuB,YAAvB;AAEA,SACEC,aADF,EAEEC,cAFF,QAGO,UAHP;;;AAMA,eAAe,SAASC,gBAAT,CAA0BC,KAA1B,EAAiC;AAC9C,QAAM;AACJC,IAAAA,EADI;AAEJC,IAAAA,OAAO,GAAG,EAFN;AAGJC,IAAAA,KAHI;AAIJC,IAAAA,MAAM,EAAEC,eAJJ;AAKJC,IAAAA,IAAI,EAAEC;AALF,MAMFP,KANJ;AAQA,QAAM,CAAEM,IAAF,EAAQE,OAAR,IAAoBb,QAAQ,CAACY,UAAD,CAAlC;;AAEA,QAAME,UAAU,GAAG,MAAMD,OAAO,CAAC,CAACF,IAAF,CAAhC,CAX8C,CAa9C;;;AACA,QAAMI,gBAAgB,GAAG,SAAzB;AAEA,SACE;AACE,qBAAgBT,EADlB;AAEE,IAAA,KAAK,EAAGL,UAAU,CAChB,wCADgB,EAEhBU,IAAI,GAAG,MAAH,GAAY,EAFA,CAFpB;AAAA,eAME;AAAK,MAAA,KAAK,EAAC,+CAAX;AAA2D,MAAA,OAAO,EAAGG,UAArE;AAAA,iBACE;AACE,QAAA,KAAK,EAAGb,UAAU,CAChB,qDADgB,EAEhB,CAACO,KAAD,IAAU,OAFM,CADpB;AAAA,kBAKIA,KAAK,IAAIO;AALb,QADF,EAQE;AAAK,QAAA,KAAK,EAAC,8CAAX;AAAA,kBACE,KAAC,aAAD;AAAe,UAAA,KAAK,EAAGJ,IAAI,GAAG,iCAAH,GAAuC;AAAlE;AADF,QARF,EAYID,eAAe,GAGX,KAAC,eAAD;AAAA,kBACE;AAAQ,UAAA,KAAK,EAAC,mCAAd;AAAA,oBACE,KAAC,cAAD;AADF;AADF,QAHW,GASX,IArBR;AAAA,MANF,EA8BE;AAAK,MAAA,KAAK,EAAGT,UAAU,CACrB,gDADqB,EAErBU,IAAI,GAAG,MAAH,GAAY,EAFK,CAAvB;AAAA,gBAKIJ,OAAO,CAACS,GAAR,CAAYC,CAAC,IAAIA,CAAC,CAACC,SAAnB;AALJ,MA9BF;AAAA,IADF;AAyCD","sourcesContent":["import {\n useState\n} from 'preact/hooks';\n\nimport classnames from 'classnames';\n\nimport {\n ListArrowIcon,\n ListDeleteIcon,\n} from '../icons';\n\n\nexport default function CollapsibleEntry(props) {\n const {\n id,\n entries = [],\n label,\n remove: RemoveContainer,\n open: shouldOpen\n } = props;\n\n const [ open, setOpen ] = useState(shouldOpen);\n\n const toggleOpen = () => setOpen(!open);\n\n // todo(pinussilvestrus): translate once we have a translate mechanism for the core\n const placeholderLabel = '<empty>';\n\n return (\n <div\n data-entry-id={ id }\n class={ classnames(\n 'bio-properties-panel-collapsible-entry',\n open ? 'open' : ''\n ) }>\n <div class=\"bio-properties-panel-collapsible-entry-header\" onClick={ toggleOpen }>\n <div\n class={ classnames(\n 'bio-properties-panel-collapsible-entry-header-title',\n !label && 'empty'\n ) }>\n { label || placeholderLabel }\n </div>\n <div class=\"bio-properties-panel-collapsible-entry-arrow\">\n <ListArrowIcon class={ open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right' } />\n </div>\n {\n RemoveContainer\n ?\n (\n <RemoveContainer>\n <button class=\"bio-properties-panel-remove-entry\">\n <ListDeleteIcon />\n </button>\n </RemoveContainer>\n )\n : null\n }\n </div>\n <div class={ classnames(\n 'bio-properties-panel-collapsible-entry-entries',\n open ? 'open' : ''\n ) }>\n {\n entries.map(e => e.component)\n }\n </div>\n </div>\n );\n}"],"file":"Collapsible.js"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'preact/hooks';
|
|
2
|
+
import { query as domQuery } from 'min-dom';
|
|
3
|
+
import { useKeyFactory, usePrevious } from '../../hooks';
|
|
4
|
+
import classnames from 'classnames';
|
|
5
|
+
import { CreateIcon, GroupArrowIcon, ListDeleteIcon } from '../icons';
|
|
6
|
+
/**
|
|
7
|
+
* Entry for handling lists represented as nested entries.
|
|
8
|
+
*
|
|
9
|
+
* @template Item
|
|
10
|
+
* @param {object} props
|
|
11
|
+
* @param {string} props.id
|
|
12
|
+
* @param {*} props.element
|
|
13
|
+
* @param {Function} props.onAdd
|
|
14
|
+
* @param {(item: Item, index: number, isNew: boolean) => JSX.Element} props.renderItem
|
|
15
|
+
* @param {string} [props.label='<empty>']
|
|
16
|
+
* @param {Function} [props.onRemove]
|
|
17
|
+
* @param {Item[]} [props.items]
|
|
18
|
+
* @param {boolean} [props.open]
|
|
19
|
+
* @param {string} [props.autoFocusEntry]
|
|
20
|
+
* @param {(a: Item, b: Item) => -1 | 0 | 1} [props.compareFn]
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
25
|
+
import { jsxs as _jsxs } from "preact/jsx-runtime";
|
|
26
|
+
export default function List(props) {
|
|
27
|
+
const {
|
|
28
|
+
id,
|
|
29
|
+
element,
|
|
30
|
+
items = [],
|
|
31
|
+
renderItem,
|
|
32
|
+
label = '<empty>',
|
|
33
|
+
open: shouldOpen,
|
|
34
|
+
onAdd,
|
|
35
|
+
onRemove,
|
|
36
|
+
autoFocusEntry,
|
|
37
|
+
compareFn
|
|
38
|
+
} = props;
|
|
39
|
+
const [open, setOpen] = useState(!!shouldOpen);
|
|
40
|
+
const hasItems = !!items.length;
|
|
41
|
+
|
|
42
|
+
const toggleOpen = () => hasItems && setOpen(!open);
|
|
43
|
+
|
|
44
|
+
const opening = !usePrevious(open) && open;
|
|
45
|
+
const elementChanged = usePrevious(element) !== element;
|
|
46
|
+
const shouldReset = opening || elementChanged;
|
|
47
|
+
const sortedItems = useSortedItems(items, compareFn, shouldReset);
|
|
48
|
+
const newItems = useNewItems(items, elementChanged);
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (open && !hasItems) {
|
|
51
|
+
setOpen(false);
|
|
52
|
+
}
|
|
53
|
+
}, [open, hasItems]);
|
|
54
|
+
/**
|
|
55
|
+
* @param {MouseEvent} event
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
function addItem(event) {
|
|
59
|
+
event.stopPropagation();
|
|
60
|
+
onAdd();
|
|
61
|
+
|
|
62
|
+
if (!open) {
|
|
63
|
+
setOpen(true);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return _jsxs("div", {
|
|
68
|
+
"data-entry-id": id,
|
|
69
|
+
class: classnames('bio-properties-panel-entry', 'bio-properties-panel-list-entry', open ? 'open' : ''),
|
|
70
|
+
children: [_jsxs("div", {
|
|
71
|
+
class: "bio-properties-panel-list-entry-header",
|
|
72
|
+
onClick: toggleOpen,
|
|
73
|
+
children: [_jsx("div", {
|
|
74
|
+
title: getTitle(label, items),
|
|
75
|
+
class: classnames('bio-properties-panel-list-entry-header-title', open && 'open'),
|
|
76
|
+
children: label
|
|
77
|
+
}), _jsxs("div", {
|
|
78
|
+
class: "bio-properties-panel-list-entry-header-buttons",
|
|
79
|
+
children: [_jsx("button", {
|
|
80
|
+
onClick: addItem,
|
|
81
|
+
class: "bio-properties-panel-add-entry",
|
|
82
|
+
children: _jsx(CreateIcon, {})
|
|
83
|
+
}), hasItems && _jsx("div", {
|
|
84
|
+
class: "bio-properties-panel-list-badge",
|
|
85
|
+
children: items.length
|
|
86
|
+
}), hasItems && _jsx("button", {
|
|
87
|
+
class: "bio-properties-panel-list-entry-arrow",
|
|
88
|
+
children: _jsx(GroupArrowIcon, {
|
|
89
|
+
class: open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right'
|
|
90
|
+
})
|
|
91
|
+
})]
|
|
92
|
+
})]
|
|
93
|
+
}), hasItems && _jsx(ItemsList, {
|
|
94
|
+
autoFocusEntry: autoFocusEntry,
|
|
95
|
+
id: id,
|
|
96
|
+
open: open,
|
|
97
|
+
items: sortedItems,
|
|
98
|
+
newItems: newItems,
|
|
99
|
+
onRemove: onRemove,
|
|
100
|
+
renderItem: renderItem
|
|
101
|
+
})]
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function ItemsList(props) {
|
|
106
|
+
const {
|
|
107
|
+
autoFocusEntry,
|
|
108
|
+
id,
|
|
109
|
+
items,
|
|
110
|
+
newItems,
|
|
111
|
+
open,
|
|
112
|
+
onRemove,
|
|
113
|
+
renderItem
|
|
114
|
+
} = props;
|
|
115
|
+
const getKey = useKeyFactory();
|
|
116
|
+
const newItem = newItems[0];
|
|
117
|
+
useEffect(() => {
|
|
118
|
+
if (newItem && autoFocusEntry) {
|
|
119
|
+
const entry = domQuery(`[data-entry-id="${id}"]`);
|
|
120
|
+
const focusableInput = domQuery('.bio-properties-panel-input', entry);
|
|
121
|
+
|
|
122
|
+
if (focusableInput) {
|
|
123
|
+
focusableInput.focus();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}, [newItem, autoFocusEntry, id]);
|
|
127
|
+
return _jsx("ol", {
|
|
128
|
+
class: classnames('bio-properties-panel-list-entry-items', open ? 'open' : ''),
|
|
129
|
+
children: items.map((item, index) => {
|
|
130
|
+
const key = getKey(item);
|
|
131
|
+
return _jsxs("li", {
|
|
132
|
+
class: "bio-properties-panel-list-entry-item",
|
|
133
|
+
children: [renderItem(item, index, item === newItem), onRemove && _jsx("button", {
|
|
134
|
+
type: "button",
|
|
135
|
+
class: "bio-properties-panel-remove-entry",
|
|
136
|
+
onClick: () => onRemove && onRemove(item),
|
|
137
|
+
children: _jsx(ListDeleteIcon, {})
|
|
138
|
+
})]
|
|
139
|
+
}, key);
|
|
140
|
+
})
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function getTitle(label, items) {
|
|
145
|
+
if (!items.length) {
|
|
146
|
+
return label;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return `${label} (${items.length} items)`;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Place new items in the beginning of the list and sort the rest with provided function.
|
|
153
|
+
*
|
|
154
|
+
* @template Item
|
|
155
|
+
* @param {Item[]} currentItems
|
|
156
|
+
* @param {(a: Item, b: Item) => 0 | 1 | -1} [compareFn] function used to sort items
|
|
157
|
+
* @param {boolean} [shouldReset=false] set to `true` to reset state of the hook
|
|
158
|
+
* @returns {Item[]}
|
|
159
|
+
*/
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
function useSortedItems(currentItems, compareFn, shouldReset = false) {
|
|
163
|
+
const itemsRef = useRef(currentItems.slice()); // (1) Reset and optionally sort.
|
|
164
|
+
|
|
165
|
+
if (shouldReset) {
|
|
166
|
+
itemsRef.current = currentItems.slice();
|
|
167
|
+
|
|
168
|
+
if (compareFn) {
|
|
169
|
+
itemsRef.current.sort(compareFn);
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
const items = itemsRef.current; // (2) Move new items to the beginning of the list.
|
|
173
|
+
|
|
174
|
+
for (const item of currentItems) {
|
|
175
|
+
if (!items.includes(item)) {
|
|
176
|
+
items.unshift(item);
|
|
177
|
+
}
|
|
178
|
+
} // (3) Filter out removed items.
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
itemsRef.current = items.filter(item => currentItems.includes(item));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return itemsRef.current;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function useNewItems(items = [], shouldReset) {
|
|
188
|
+
const previousItems = usePrevious(items.slice()) || [];
|
|
189
|
+
|
|
190
|
+
if (shouldReset) {
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return previousItems ? items.filter(item => !previousItems.includes(item)) : [];
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=List.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/entries/List.js"],"names":["useEffect","useRef","useState","query","domQuery","useKeyFactory","usePrevious","classnames","CreateIcon","GroupArrowIcon","ListDeleteIcon","List","props","id","element","items","renderItem","label","open","shouldOpen","onAdd","onRemove","autoFocusEntry","compareFn","setOpen","hasItems","length","toggleOpen","opening","elementChanged","shouldReset","sortedItems","useSortedItems","newItems","useNewItems","addItem","event","stopPropagation","getTitle","ItemsList","getKey","newItem","entry","focusableInput","focus","map","item","index","key","currentItems","itemsRef","slice","current","sort","includes","unshift","filter","previousItems"],"mappings":"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","sourcesContent":["import {\n useEffect,\n useRef,\n useState\n} from 'preact/hooks';\n\nimport {\n query as domQuery\n} from 'min-dom';\n\nimport {\n useKeyFactory,\n usePrevious\n} from '../../hooks';\n\nimport classnames from 'classnames';\n\nimport {\n CreateIcon,\n GroupArrowIcon,\n ListDeleteIcon\n} from '../icons';\n\n/**\n * Entry for handling lists represented as nested entries.\n *\n * @template Item\n * @param {object} props\n * @param {string} props.id\n * @param {*} props.element\n * @param {Function} props.onAdd\n * @param {(item: Item, index: number, isNew: boolean) => JSX.Element} props.renderItem\n * @param {string} [props.label='<empty>']\n * @param {Function} [props.onRemove]\n * @param {Item[]} [props.items]\n * @param {boolean} [props.open]\n * @param {string} [props.autoFocusEntry]\n * @param {(a: Item, b: Item) => -1 | 0 | 1} [props.compareFn]\n * @returns\n */\nexport default function List(props) {\n const {\n id,\n element,\n items = [],\n renderItem,\n label = '<empty>',\n open: shouldOpen,\n onAdd,\n onRemove,\n autoFocusEntry,\n compareFn\n } = props;\n\n const [ open, setOpen ] = useState(!!shouldOpen);\n\n const hasItems = !!items.length;\n const toggleOpen = () => hasItems && setOpen(!open);\n\n const opening = !usePrevious(open) && open;\n const elementChanged = usePrevious(element) !== element;\n const shouldReset = opening || elementChanged;\n const sortedItems = useSortedItems(items, compareFn, shouldReset);\n\n const newItems = useNewItems(items, elementChanged);\n\n useEffect(() => {\n if (open && !hasItems) {\n setOpen(false);\n }\n }, [ open, hasItems ]);\n\n /**\n * @param {MouseEvent} event\n */\n function addItem(event) {\n event.stopPropagation();\n onAdd();\n\n if (!open) {\n setOpen(true);\n }\n }\n\n return (\n <div\n data-entry-id={ id }\n class={ classnames(\n 'bio-properties-panel-entry',\n 'bio-properties-panel-list-entry',\n open ? 'open' : ''\n ) }>\n <div class=\"bio-properties-panel-list-entry-header\" onClick={ toggleOpen }>\n <div\n title={ getTitle(label, items) }\n class={ classnames(\n 'bio-properties-panel-list-entry-header-title',\n open && 'open'\n ) }>\n { label }\n </div>\n <div\n class=\"bio-properties-panel-list-entry-header-buttons\"\n >\n <button onClick={ addItem } class=\"bio-properties-panel-add-entry\">\n <CreateIcon />\n </button>\n {\n hasItems && (\n <div class=\"bio-properties-panel-list-badge\">\n { items.length }\n </div>\n )\n }\n {\n hasItems && (\n <button class=\"bio-properties-panel-list-entry-arrow\">\n <GroupArrowIcon class={ open ? 'bio-properties-panel-arrow-down' : 'bio-properties-panel-arrow-right' } />\n </button>\n )\n }\n </div>\n </div>\n {\n hasItems && (\n <ItemsList\n autoFocusEntry={ autoFocusEntry }\n id={ id }\n open={ open }\n items={ sortedItems }\n newItems={ newItems }\n onRemove={ onRemove }\n renderItem={ renderItem }\n />\n )\n }\n </div>\n );\n}\n\nfunction ItemsList(props) {\n const {\n autoFocusEntry,\n id,\n items,\n newItems,\n open,\n onRemove,\n renderItem\n } = props;\n\n const getKey = useKeyFactory();\n\n const newItem = newItems[0];\n\n useEffect(() => {\n if (newItem && autoFocusEntry) {\n const entry = domQuery(`[data-entry-id=\"${id}\"]`);\n const focusableInput = domQuery('.bio-properties-panel-input', entry);\n\n if (focusableInput) {\n focusableInput.focus();\n }\n }\n }, [ newItem, autoFocusEntry, id ]);\n\n return (\n <ol class={ classnames(\n 'bio-properties-panel-list-entry-items',\n open ? 'open' : ''\n ) }>\n {\n items.map((item, index) => {\n const key = getKey(item);\n\n return (<li class=\"bio-properties-panel-list-entry-item\" key={ key }>\n {renderItem(item, index, item === newItem)}\n {\n onRemove && (\n <button\n type=\"button\"\n class=\"bio-properties-panel-remove-entry\"\n onClick={ () => onRemove && onRemove(item) }\n ><ListDeleteIcon /></button>\n )\n }\n </li>);\n })\n }\n </ol>);\n}\n\nfunction getTitle(label, items) {\n if (!items.length) {\n return label;\n }\n\n return `${label} (${items.length} items)`;\n}\n\n/**\n * Place new items in the beginning of the list and sort the rest with provided function.\n *\n * @template Item\n * @param {Item[]} currentItems\n * @param {(a: Item, b: Item) => 0 | 1 | -1} [compareFn] function used to sort items\n * @param {boolean} [shouldReset=false] set to `true` to reset state of the hook\n * @returns {Item[]}\n */\nfunction useSortedItems(currentItems, compareFn, shouldReset = false) {\n const itemsRef = useRef(currentItems.slice());\n\n // (1) Reset and optionally sort.\n if (shouldReset) {\n itemsRef.current = currentItems.slice();\n\n if (compareFn) {\n itemsRef.current.sort(compareFn);\n }\n } else {\n const items = itemsRef.current;\n\n // (2) Move new items to the beginning of the list.\n for (const item of currentItems) {\n if (!items.includes(item)) {\n items.unshift(item);\n }\n }\n\n // (3) Filter out removed items.\n itemsRef.current = items.filter(item => currentItems.includes(item));\n }\n\n return itemsRef.current;\n}\n\nfunction useNewItems(items = [], shouldReset) {\n const previousItems = usePrevious(items.slice()) || [];\n\n if (shouldReset) {\n return [];\n }\n\n return previousItems ? items.filter(item => !previousItems.includes(item)) : [];\n}\n"],"file":"List.js"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { useMemo } from 'preact/hooks';
|
|
2
|
+
/**
|
|
3
|
+
* @param {Object} props
|
|
4
|
+
* @param {Function} props.debounce
|
|
5
|
+
* @param {Boolean} [props.disabled]
|
|
6
|
+
* @param {Object} props.element
|
|
7
|
+
* @param {Function} props.getValue
|
|
8
|
+
* @param {String} props.id
|
|
9
|
+
* @param {Function} [props.onBlur]
|
|
10
|
+
* @param {Function} [props.onFocus]
|
|
11
|
+
* @param {Function} props.setValue
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
15
|
+
export default function Simple(props) {
|
|
16
|
+
const {
|
|
17
|
+
debounce,
|
|
18
|
+
disabled,
|
|
19
|
+
element,
|
|
20
|
+
getValue,
|
|
21
|
+
id,
|
|
22
|
+
onBlur,
|
|
23
|
+
onFocus,
|
|
24
|
+
setValue
|
|
25
|
+
} = props;
|
|
26
|
+
const handleInput = useMemo(() => {
|
|
27
|
+
return debounce(({
|
|
28
|
+
target
|
|
29
|
+
}) => setValue(target.value.length ? target.value : undefined));
|
|
30
|
+
}, [setValue, debounce]);
|
|
31
|
+
const value = getValue(element);
|
|
32
|
+
return _jsx("div", {
|
|
33
|
+
class: "bio-properties-panel-simple",
|
|
34
|
+
children: _jsx("input", {
|
|
35
|
+
id: prefixId(id),
|
|
36
|
+
type: "text",
|
|
37
|
+
name: id,
|
|
38
|
+
spellCheck: "false",
|
|
39
|
+
autoComplete: "off",
|
|
40
|
+
disabled: disabled,
|
|
41
|
+
class: "bio-properties-panel-input",
|
|
42
|
+
onInput: handleInput,
|
|
43
|
+
onFocus: onFocus,
|
|
44
|
+
onBlur: onBlur,
|
|
45
|
+
value: value || ''
|
|
46
|
+
})
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
export function isEdited(node) {
|
|
50
|
+
return node && !!node.value;
|
|
51
|
+
} // helpers /////////////////
|
|
52
|
+
|
|
53
|
+
function prefixId(id) {
|
|
54
|
+
return `bio-properties-panel-${id}`;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=Simple.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/entries/Simple.js"],"names":["useMemo","Simple","props","debounce","disabled","element","getValue","id","onBlur","onFocus","setValue","handleInput","target","value","length","undefined","prefixId","isEdited","node"],"mappings":"AAAA,SACEA,OADF,QAEO,cAFP;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA,eAAe,SAASC,MAAT,CAAgBC,KAAhB,EAAuB;AACpC,QAAM;AACJC,IAAAA,QADI;AAEJC,IAAAA,QAFI;AAGJC,IAAAA,OAHI;AAIJC,IAAAA,QAJI;AAKJC,IAAAA,EALI;AAMJC,IAAAA,MANI;AAOJC,IAAAA,OAPI;AAQJC,IAAAA;AARI,MASFR,KATJ;AAWA,QAAMS,WAAW,GAAGX,OAAO,CAAC,MAAM;AAChC,WAAOG,QAAQ,CAAC,CAAC;AAAES,MAAAA;AAAF,KAAD,KAAgBF,QAAQ,CAACE,MAAM,CAACC,KAAP,CAAaC,MAAb,GAAsBF,MAAM,CAACC,KAA7B,GAAqCE,SAAtC,CAAzB,CAAf;AACD,GAF0B,EAExB,CAAEL,QAAF,EAAYP,QAAZ,CAFwB,CAA3B;AAIA,QAAMU,KAAK,GAAGP,QAAQ,CAACD,OAAD,CAAtB;AAEA,SACE;AAAK,IAAA,KAAK,EAAC,6BAAX;AAAA,cACE;AACE,MAAA,EAAE,EAAGW,QAAQ,CAACT,EAAD,CADf;AAEE,MAAA,IAAI,EAAC,MAFP;AAGE,MAAA,IAAI,EAAGA,EAHT;AAIE,MAAA,UAAU,EAAC,OAJb;AAKE,MAAA,YAAY,EAAC,KALf;AAME,MAAA,QAAQ,EAAGH,QANb;AAOE,MAAA,KAAK,EAAC,4BAPR;AAQE,MAAA,OAAO,EAAGO,WARZ;AASE,MAAA,OAAO,EAAGF,OATZ;AAUE,MAAA,MAAM,EAAGD,MAVX;AAWE,MAAA,KAAK,EAAGK,KAAK,IAAI;AAXnB;AADF,IADF;AAgBD;AAED,OAAO,SAASI,QAAT,CAAkBC,IAAlB,EAAwB;AAC7B,SAAOA,IAAI,IAAI,CAAC,CAACA,IAAI,CAACL,KAAtB;AACD,C,CAGD;;AAEA,SAASG,QAAT,CAAkBT,EAAlB,EAAsB;AACpB,SAAQ,wBAAwBA,EAAI,EAApC;AACD","sourcesContent":["import {\n useMemo\n} from 'preact/hooks';\n\n/**\n * @param {Object} props\n * @param {Function} props.debounce\n * @param {Boolean} [props.disabled]\n * @param {Object} props.element\n * @param {Function} props.getValue\n * @param {String} props.id\n * @param {Function} [props.onBlur]\n * @param {Function} [props.onFocus]\n * @param {Function} props.setValue\n */\nexport default function Simple(props) {\n const {\n debounce,\n disabled,\n element,\n getValue,\n id,\n onBlur,\n onFocus,\n setValue\n } = props;\n\n const handleInput = useMemo(() => {\n return debounce(({ target }) => setValue(target.value.length ? target.value : undefined));\n }, [ setValue, debounce ]);\n\n const value = getValue(element);\n\n return (\n <div class=\"bio-properties-panel-simple\">\n <input\n id={ prefixId(id) }\n type=\"text\"\n name={ id }\n spellCheck=\"false\"\n autoComplete=\"off\"\n disabled={ disabled }\n class=\"bio-properties-panel-input\"\n onInput={ handleInput }\n onFocus={ onFocus }\n onBlur={ onBlur }\n value={ value || '' } />\n </div>\n );\n}\n\nexport function isEdited(node) {\n return node && !!node.value;\n}\n\n\n// helpers /////////////////\n\nfunction prefixId(id) {\n return `bio-properties-panel-${ id }`;\n}\n"],"file":"Simple.js"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useMemo } from 'preact/hooks';
|
|
2
|
+
import classnames from 'classnames';
|
|
2
3
|
import { jsx as _jsx } from "preact/jsx-runtime";
|
|
3
4
|
import { jsxs as _jsxs } from "preact/jsx-runtime";
|
|
4
5
|
|
|
@@ -9,7 +10,8 @@ function TextArea(props) {
|
|
|
9
10
|
rows = 2,
|
|
10
11
|
debounce,
|
|
11
12
|
onInput,
|
|
12
|
-
value = ''
|
|
13
|
+
value = '',
|
|
14
|
+
monospace
|
|
13
15
|
} = props;
|
|
14
16
|
const handleInput = useMemo(() => {
|
|
15
17
|
return debounce(({
|
|
@@ -26,7 +28,7 @@ function TextArea(props) {
|
|
|
26
28
|
id: prefixId(id),
|
|
27
29
|
name: id,
|
|
28
30
|
spellCheck: "false",
|
|
29
|
-
class:
|
|
31
|
+
class: classnames('bio-properties-panel-input', monospace ? 'bio-properties-panel-input-monospace' : ''),
|
|
30
32
|
onInput: handleInput,
|
|
31
33
|
onFocus: props.onFocus,
|
|
32
34
|
onBlur: props.onBlur,
|
|
@@ -45,6 +47,7 @@ function TextArea(props) {
|
|
|
45
47
|
* @param {Function} props.getValue
|
|
46
48
|
* @param {Function} props.setValue
|
|
47
49
|
* @param {Number} props.rows
|
|
50
|
+
* @param {Boolean} props.monospace
|
|
48
51
|
*/
|
|
49
52
|
|
|
50
53
|
|
|
@@ -57,7 +60,8 @@ export default function TextAreaEntry(props) {
|
|
|
57
60
|
label,
|
|
58
61
|
getValue,
|
|
59
62
|
setValue,
|
|
60
|
-
rows
|
|
63
|
+
rows,
|
|
64
|
+
monospace
|
|
61
65
|
} = props;
|
|
62
66
|
const value = getValue(element);
|
|
63
67
|
return _jsxs("div", {
|
|
@@ -69,7 +73,8 @@ export default function TextAreaEntry(props) {
|
|
|
69
73
|
value: value,
|
|
70
74
|
onInput: setValue,
|
|
71
75
|
rows: rows,
|
|
72
|
-
debounce: debounce
|
|
76
|
+
debounce: debounce,
|
|
77
|
+
monospace: monospace
|
|
73
78
|
}), description && _jsx("div", {
|
|
74
79
|
class: "bio-properties-panel-description",
|
|
75
80
|
children: description
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/entries/TextArea.js"],"names":["useMemo","TextArea","props","id","label","rows","debounce","onInput","value","handleInput","target","length","undefined","prefixId","onFocus","onBlur","TextAreaEntry","element","description","getValue","setValue","isEdited","node"],"mappings":"AAAA,SACEA,OADF,QAEO,cAFP
|
|
1
|
+
{"version":3,"sources":["../../../src/components/entries/TextArea.js"],"names":["useMemo","classnames","TextArea","props","id","label","rows","debounce","onInput","value","monospace","handleInput","target","length","undefined","prefixId","onFocus","onBlur","TextAreaEntry","element","description","getValue","setValue","isEdited","node"],"mappings":"AAAA,SACEA,OADF,QAEO,cAFP;AAIA,OAAOC,UAAP,MAAuB,YAAvB;;;;AAEA,SAASC,QAAT,CAAkBC,KAAlB,EAAyB;AAEvB,QAAM;AACJC,IAAAA,EADI;AAEJC,IAAAA,KAFI;AAGJC,IAAAA,IAAI,GAAG,CAHH;AAIJC,IAAAA,QAJI;AAKJC,IAAAA,OALI;AAMJC,IAAAA,KAAK,GAAG,EANJ;AAOJC,IAAAA;AAPI,MAQFP,KARJ;AAUA,QAAMQ,WAAW,GAAGX,OAAO,CAAC,MAAM;AAChC,WAAOO,QAAQ,CAAC,CAAC;AAAEK,MAAAA;AAAF,KAAD,KAAgBJ,OAAO,CAACI,MAAM,CAACH,KAAP,CAAaI,MAAb,GAAsBD,MAAM,CAACH,KAA7B,GAAqCK,SAAtC,CAAxB,CAAf;AACD,GAF0B,EAExB,CAAEN,OAAF,EAAWD,QAAX,CAFwB,CAA3B;AAIA,SACE;AAAK,IAAA,KAAK,EAAC,+BAAX;AAAA,eACE;AAAO,MAAA,GAAG,EAAGQ,QAAQ,CAACX,EAAD,CAArB;AAA4B,MAAA,KAAK,EAAC,4BAAlC;AAAA,gBAAiEC;AAAjE,MADF,EAEE;AACE,MAAA,EAAE,EAAGU,QAAQ,CAACX,EAAD,CADf;AAEE,MAAA,IAAI,EAAGA,EAFT;AAGE,MAAA,UAAU,EAAC,OAHb;AAIE,MAAA,KAAK,EAAGH,UAAU,CAChB,4BADgB,EAEhBS,SAAS,GAAG,sCAAH,GAA4C,EAFrC,CAJpB;AAQE,MAAA,OAAO,EAAGC,WARZ;AASE,MAAA,OAAO,EAAGR,KAAK,CAACa,OATlB;AAUE,MAAA,MAAM,EAAGb,KAAK,CAACc,MAVjB;AAWE,MAAA,IAAI,EAAGX,IAXT;AAYE,MAAA,KAAK,EAAGG;AAZV,MAFF;AAAA,IADF;AAkBD;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AACA,eAAe,SAASS,aAAT,CAAuBf,KAAvB,EAA8B;AAC3C,QAAM;AACJgB,IAAAA,OADI;AAEJf,IAAAA,EAFI;AAGJgB,IAAAA,WAHI;AAIJb,IAAAA,QAJI;AAKJF,IAAAA,KALI;AAMJgB,IAAAA,QANI;AAOJC,IAAAA,QAPI;AAQJhB,IAAAA,IARI;AASJI,IAAAA;AATI,MAUFP,KAVJ;AAYA,QAAMM,KAAK,GAAGY,QAAQ,CAACF,OAAD,CAAtB;AACA,SACE;AAAK,IAAA,KAAK,EAAC,4BAAX;AAAwC,qBAAgBf,EAAxD;AAAA,eACE,KAAC,QAAD;AACE,MAAA,EAAE,EAAGA,EADP;AAEE,MAAA,KAAK,EAAGC,KAFV;AAGE,MAAA,KAAK,EAAGI,KAHV;AAIE,MAAA,OAAO,EAAGa,QAJZ;AAKE,MAAA,IAAI,EAAGhB,IALT;AAME,MAAA,QAAQ,EAAGC,QANb;AAOE,MAAA,SAAS,EAAGG;AAPd,MADF,EASIU,WAAW,IAAI;AAAK,MAAA,KAAK,EAAC,kCAAX;AAAA,gBAAgDA;AAAhD,MATnB;AAAA,IADF;AAaD;AAED,OAAO,SAASG,QAAT,CAAkBC,IAAlB,EAAwB;AAC7B,SAAOA,IAAI,IAAI,CAAC,CAACA,IAAI,CAACf,KAAtB;AACD,C,CAGD;;AAEA,SAASM,QAAT,CAAkBX,EAAlB,EAAsB;AACpB,SAAQ,wBAAwBA,EAAI,EAApC;AACD","sourcesContent":["import {\n useMemo\n} from 'preact/hooks';\n\nimport classnames from 'classnames';\n\nfunction TextArea(props) {\n\n const {\n id,\n label,\n rows = 2,\n debounce,\n onInput,\n value = '',\n monospace\n } = props;\n\n const handleInput = useMemo(() => {\n return debounce(({ target }) => onInput(target.value.length ? target.value : undefined));\n }, [ onInput, debounce ]);\n\n return (\n <div class=\"bio-properties-panel-textarea\">\n <label for={ prefixId(id) } class=\"bio-properties-panel-label\">{ label }</label>\n <textarea\n id={ prefixId(id) }\n name={ id }\n spellCheck=\"false\"\n class={ classnames(\n 'bio-properties-panel-input',\n monospace ? 'bio-properties-panel-input-monospace' : '')\n }\n onInput={ handleInput }\n onFocus={ props.onFocus }\n onBlur={ props.onBlur }\n rows={ rows }\n value={ value } />\n </div>\n );\n}\n\n/**\n * @param {Object} props\n * @param {Object} props.element\n * @param {String} props.id\n * @param {String} props.description\n * @param {Boolean} props.debounce\n * @param {String} props.label\n * @param {Function} props.getValue\n * @param {Function} props.setValue\n * @param {Number} props.rows\n * @param {Boolean} props.monospace\n */\nexport default function TextAreaEntry(props) {\n const {\n element,\n id,\n description,\n debounce,\n label,\n getValue,\n setValue,\n rows,\n monospace\n } = props;\n\n const value = getValue(element);\n return (\n <div class=\"bio-properties-panel-entry\" data-entry-id={ id }>\n <TextArea\n id={ id }\n label={ label }\n value={ value }\n onInput={ setValue }\n rows={ rows }\n debounce={ debounce }\n monospace={ monospace } />\n { description && <div class=\"bio-properties-panel-description\">{ description }</div> }\n </div>\n );\n}\n\nexport function isEdited(node) {\n return node && !!node.value;\n}\n\n\n// helpers /////////////////\n\nfunction prefixId(id) {\n return `bio-properties-panel-${ id }`;\n}"],"file":"TextArea.js"}
|
package/lib/hooks/index.js
CHANGED
package/lib/hooks/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/index.js"],"names":["default","usePrevious"],"mappings":"AAAA,SAASA,OAAO,IAAIC,WAApB,QAAuC,eAAvC","sourcesContent":["export { default as usePrevious } from './usePrevious';"],"file":"index.js"}
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/index.js"],"names":["default","usePrevious","useKeyFactory"],"mappings":"AAAA,SAASA,OAAO,IAAIC,WAApB,QAAuC,eAAvC;AACA,SAASC,aAAT,QAA8B,iBAA9B","sourcesContent":["export { default as usePrevious } from './usePrevious';\nexport { useKeyFactory } from './useKeyFactory';"],"file":"index.js"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useMemo } from 'preact/hooks';
|
|
2
|
+
const KEY_LENGTH = 6;
|
|
3
|
+
/**
|
|
4
|
+
* Create a persistent key factory for plain objects without id.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```jsx
|
|
8
|
+
* function List({ objects }) {
|
|
9
|
+
* const getKey = useKeyFactory();
|
|
10
|
+
* return (<ol>{
|
|
11
|
+
* objects.map(obj => {
|
|
12
|
+
* const key = getKey(obj);
|
|
13
|
+
* return <li key={key}>obj.name</li>
|
|
14
|
+
* })
|
|
15
|
+
* }</ol>);
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @param {any[]} dependencies
|
|
20
|
+
* @returns {(element: object) => string}
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export function useKeyFactory(dependencies = []) {
|
|
24
|
+
const map = useMemo(() => new Map(), dependencies);
|
|
25
|
+
|
|
26
|
+
const getKey = el => {
|
|
27
|
+
let key = map.get(el);
|
|
28
|
+
|
|
29
|
+
if (!key) {
|
|
30
|
+
key = Math.random().toString().slice(-KEY_LENGTH);
|
|
31
|
+
map.set(el, key);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return key;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return getKey;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=useKeyFactory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/useKeyFactory.js"],"names":["useMemo","KEY_LENGTH","useKeyFactory","dependencies","map","Map","getKey","el","key","get","Math","random","toString","slice","set"],"mappings":"AAAA,SAASA,OAAT,QAAwB,cAAxB;AAEA,MAAMC,UAAU,GAAG,CAAnB;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,OAAO,SAASC,aAAT,CAAuBC,YAAY,GAAG,EAAtC,EAA0C;AAC/C,QAAMC,GAAG,GAAGJ,OAAO,CAAC,MAAM,IAAIK,GAAJ,EAAP,EAAkBF,YAAlB,CAAnB;;AAEA,QAAMG,MAAM,GAAGC,EAAE,IAAI;AACnB,QAAIC,GAAG,GAAGJ,GAAG,CAACK,GAAJ,CAAQF,EAAR,CAAV;;AAEA,QAAI,CAACC,GAAL,EAAU;AACRA,MAAAA,GAAG,GAAGE,IAAI,CAACC,MAAL,GAAcC,QAAd,GAAyBC,KAAzB,CAA+B,CAACZ,UAAhC,CAAN;AACAG,MAAAA,GAAG,CAACU,GAAJ,CAAQP,EAAR,EAAYC,GAAZ;AACD;;AAED,WAAOA,GAAP;AACD,GATD;;AAWA,SAAOF,MAAP;AACD","sourcesContent":["import { useMemo } from 'preact/hooks';\n\nconst KEY_LENGTH = 6;\n\n/**\n * Create a persistent key factory for plain objects without id.\n *\n * @example\n * ```jsx\n * function List({ objects }) {\n * const getKey = useKeyFactory();\n * return (<ol>{\n * objects.map(obj => {\n * const key = getKey(obj);\n * return <li key={key}>obj.name</li>\n * })\n * }</ol>);\n * }\n * ```\n *\n * @param {any[]} dependencies\n * @returns {(element: object) => string}\n */\nexport function useKeyFactory(dependencies = []) {\n const map = useMemo(() => new Map(), dependencies);\n\n const getKey = el => {\n let key = map.get(el);\n\n if (!key) {\n key = Math.random().toString().slice(-KEY_LENGTH);\n map.set(el, key);\n }\n\n return key;\n };\n\n return getKey;\n}\n"],"file":"useKeyFactory.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bpmn-io/properties-panel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Library for creating bpmn-io properties panels.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"all": "run-s lint test",
|
|
12
12
|
"build": "del-cli lib && babel -s -d lib src",
|
|
13
|
+
"build:watch": "babel -w -s -d lib src",
|
|
13
14
|
"lint": "eslint .",
|
|
14
15
|
"dev": "npm test -- --auto-watch --no-single-run",
|
|
15
16
|
"test": "karma start karma.config.js",
|
|
@@ -41,6 +42,7 @@
|
|
|
41
42
|
"@babel/core": "^7.14.3",
|
|
42
43
|
"@babel/plugin-transform-react-jsx": "^7.14.3",
|
|
43
44
|
"@testing-library/preact": "^2.0.1",
|
|
45
|
+
"@testing-library/preact-hooks": "^1.1.0",
|
|
44
46
|
"babel-loader": "^8.2.2",
|
|
45
47
|
"babel-plugin-inline-react-svg": "^2.0.1",
|
|
46
48
|
"chai": "^4.3.4",
|