@nyaruka/temba-components 0.137.0 → 0.138.4
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/.devcontainer/Dockerfile +0 -9
- package/.devcontainer/devcontainer.json +8 -3
- package/.github/workflows/build.yml +6 -1
- package/.github/workflows/cla.yml +1 -1
- package/.github/workflows/publish.yml +6 -1
- package/CHANGELOG.md +42 -0
- package/dist/locales/es.js +5 -5
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/fr.js +5 -5
- package/dist/locales/fr.js.map +1 -1
- package/dist/locales/locale-codes.js +11 -2
- package/dist/locales/locale-codes.js.map +1 -1
- package/dist/locales/pt.js +5 -5
- package/dist/locales/pt.js.map +1 -1
- package/dist/temba-components.js +445 -278
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/display/FloatingTab.js +16 -8
- package/out-tsc/src/display/FloatingTab.js.map +1 -1
- package/out-tsc/src/flow/CanvasMenu.js +33 -15
- package/out-tsc/src/flow/CanvasMenu.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +49 -24
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +583 -70
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeTypeSelector.js +13 -11
- package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -1
- package/out-tsc/src/flow/Plumber.js +110 -64
- package/out-tsc/src/flow/Plumber.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +5 -1
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/list/RunList.js +2 -1
- package/out-tsc/src/list/RunList.js.map +1 -1
- package/out-tsc/src/list/TicketList.js +2 -1
- package/out-tsc/src/list/TicketList.js.map +1 -1
- package/out-tsc/src/locales/es.js +5 -5
- package/out-tsc/src/locales/es.js.map +1 -1
- package/out-tsc/src/locales/fr.js +5 -5
- package/out-tsc/src/locales/fr.js.map +1 -1
- package/out-tsc/src/locales/locale-codes.js +11 -2
- package/out-tsc/src/locales/locale-codes.js.map +1 -1
- package/out-tsc/src/locales/pt.js +5 -5
- package/out-tsc/src/locales/pt.js.map +1 -1
- package/out-tsc/src/simulator/Simulator.js +11 -4
- package/out-tsc/src/simulator/Simulator.js.map +1 -1
- package/out-tsc/src/store/AppState.js +17 -2
- package/out-tsc/src/store/AppState.js.map +1 -1
- package/out-tsc/test/temba-contact-fields.test.js +3 -3
- package/out-tsc/test/temba-contact-fields.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor-node.test.js +3 -1
- package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
- package/out-tsc/test/temba-flow-editor-revisions.test.js +106 -0
- package/out-tsc/test/temba-flow-editor-revisions.test.js.map +1 -0
- package/out-tsc/test/temba-flow-editor.test.js +14 -10
- package/out-tsc/test/temba-flow-editor.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber-connections.test.js +7 -1
- package/out-tsc/test/temba-flow-plumber-connections.test.js.map +1 -1
- package/out-tsc/test/temba-flow-plumber.test.js +6 -0
- package/out-tsc/test/temba-flow-plumber.test.js.map +1 -1
- package/out-tsc/test/temba-select.test.js +1 -0
- package/out-tsc/test/temba-select.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/floating-tab/gray.png +0 -0
- package/screenshots/truth/floating-tab/green.png +0 -0
- package/screenshots/truth/floating-tab/purple.png +0 -0
- package/screenshots/truth/node-type-selector/action-mode.png +0 -0
- package/screenshots/truth/node-type-selector/split-mode.png +0 -0
- package/src/display/FloatingTab.ts +18 -8
- package/src/flow/CanvasMenu.ts +38 -16
- package/src/flow/CanvasNode.ts +62 -29
- package/src/flow/Editor.ts +699 -74
- package/src/flow/NodeTypeSelector.ts +13 -11
- package/src/flow/Plumber.ts +123 -69
- package/src/flow/actions/set_contact_field.ts +5 -1
- package/src/list/RunList.ts +2 -1
- package/src/list/TicketList.ts +2 -1
- package/src/locales/es.ts +18 -13
- package/src/locales/fr.ts +18 -13
- package/src/locales/locale-codes.ts +11 -2
- package/src/locales/pt.ts +18 -13
- package/src/simulator/Simulator.ts +11 -5
- package/src/store/AppState.ts +18 -2
- package/test/temba-contact-fields.test.ts +8 -3
- package/test/temba-flow-editor-node.test.ts +3 -1
- package/test/temba-flow-editor-revisions.test.ts +134 -0
- package/test/temba-flow-editor.test.ts +16 -10
- package/test/temba-flow-plumber-connections.test.ts +7 -1
- package/test/temba-flow-plumber.test.ts +6 -0
- package/test/temba-select.test.ts +1 -0
|
@@ -154,12 +154,13 @@ export class NodeTypeSelector extends RapidElement {
|
|
|
154
154
|
|
|
155
155
|
.items-grid {
|
|
156
156
|
display: grid;
|
|
157
|
-
grid-template-columns: repeat(auto-fill, minmax(
|
|
157
|
+
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
158
158
|
gap: 0.75em;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
.node-item {
|
|
162
|
-
padding:
|
|
162
|
+
padding: 0.5em;
|
|
163
|
+
padding-left: 1em;
|
|
163
164
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
164
165
|
border-radius: calc(var(--curvature) * 0.75);
|
|
165
166
|
cursor: pointer;
|
|
@@ -193,7 +194,6 @@ export class NodeTypeSelector extends RapidElement {
|
|
|
193
194
|
font-weight: 500;
|
|
194
195
|
font-size: 1rem;
|
|
195
196
|
color: var(--color-text-dark);
|
|
196
|
-
margin-bottom: 0.25em;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
199
|
.node-item-type {
|
|
@@ -221,8 +221,14 @@ export class NodeTypeSelector extends RapidElement {
|
|
|
221
221
|
this.clickPosition = position;
|
|
222
222
|
this.open = true;
|
|
223
223
|
}
|
|
224
|
-
close() {
|
|
225
|
-
this.open
|
|
224
|
+
close(fireCanceledEvent = true) {
|
|
225
|
+
if (this.open) {
|
|
226
|
+
this.open = false;
|
|
227
|
+
// Fire canceled event so parent can clean up, but only if not from a selection
|
|
228
|
+
if (fireCanceledEvent) {
|
|
229
|
+
this.fireCustomEvent(CustomEventType.Canceled, {});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
226
232
|
}
|
|
227
233
|
/**
|
|
228
234
|
* Check if a config is available for the current flow type and features
|
|
@@ -255,7 +261,8 @@ export class NodeTypeSelector extends RapidElement {
|
|
|
255
261
|
nodeType,
|
|
256
262
|
position: this.clickPosition
|
|
257
263
|
});
|
|
258
|
-
|
|
264
|
+
// Close without firing canceled event since we made a selection
|
|
265
|
+
this.close(false);
|
|
259
266
|
}
|
|
260
267
|
handleOverlayClick() {
|
|
261
268
|
this.close();
|
|
@@ -449,7 +456,6 @@ export class NodeTypeSelector extends RapidElement {
|
|
|
449
456
|
<div class="node-item-title">
|
|
450
457
|
${item.config.name}
|
|
451
458
|
</div>
|
|
452
|
-
<div class="node-item-type">${item.type}</div>
|
|
453
459
|
</div>
|
|
454
460
|
`)}
|
|
455
461
|
</div>
|
|
@@ -482,9 +488,6 @@ export class NodeTypeSelector extends RapidElement {
|
|
|
482
488
|
<div class="node-item-title">
|
|
483
489
|
${item.config.name}
|
|
484
490
|
</div>
|
|
485
|
-
<div class="node-item-type">
|
|
486
|
-
${item.type}
|
|
487
|
-
</div>
|
|
488
491
|
</div>
|
|
489
492
|
`)}
|
|
490
493
|
</div>
|
|
@@ -512,7 +515,6 @@ export class NodeTypeSelector extends RapidElement {
|
|
|
512
515
|
<div class="node-item-title">
|
|
513
516
|
${item.config.name}
|
|
514
517
|
</div>
|
|
515
|
-
<div class="node-item-type">${item.type}</div>
|
|
516
518
|
</div>
|
|
517
519
|
`)}
|
|
518
520
|
</div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NodeTypeSelector.js","sourceRoot":"","sources":["../../../src/flow/NodeTypeSelector.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAkB,MAAM,KAAK,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACtD,OAAO,EAGL,aAAa,EACb,YAAY,EACZ,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,SAAS,CAAC;AAqBjB;;;GAGG;AACH,MAAM,OAAO,gBAAiB,SAAQ,YAAY;IAAlD;;QAyMS,SAAI,GAAG,KAAK,CAAC;QAGb,SAAI,GAA+C,QAAQ,CAAC;QAG5D,aAAQ,GAAW,SAAS,CAAC;QAG7B,aAAQ,GAAa,EAAE,CAAC;QAGvB,kBAAa,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IAuYzC,CAAC;IA3lBC,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAmMT,CAAC;IACJ,CAAC;IAiBM,IAAI,CACT,IAAgD,EAChD,QAAkC;QAElC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAEM,KAAK;QACV,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;IACpB,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,MAAiC;QACzD,yBAAyB;QACzB,IAAI,MAAM,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACnC,gEAAgE;YAChE,IAAI,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAClC,OAAO,KAAK,CAAC;YACf,CAAC;YACD,+DAA+D;YAC/D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAe,CAAC,EAAE,CAAC;gBACrD,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QACD,8DAA8D;QAE9D,gEAAgE;QAChE,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClD,KAAK,MAAM,eAAe,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAC9C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;oBAC7C,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,mBAAmB,CAAC,QAAgB;QAC1C,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,SAAS,EAAE;YAC9C,QAAQ;YACR,QAAQ,EAAE,IAAI,CAAC,aAAa;SACR,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAEO,kBAAkB;QACxB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAEO,aAAa;QACnB,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;YAClE,yBAAyB;YACzB,MAAM,cAAc,GAAG,IAAI,GAAG,EAG3B,CAAC;YACJ,MAAM,aAAa,GAAG,IAAI,GAAG,EAG1B,CAAC;YAEJ,+EAA+E;YAC/E,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;iBAC1B,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;gBACzB,0EAA0E;gBAC1E,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAChE,OAAO,CACL,CAAC,OAAO;oBACR,MAAM,CAAC,IAAI;oBACX,CAAC,MAAM,CAAC,eAAe;oBACvB,MAAM,CAAC,KAAK;oBACZ,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAC/B,CAAC;YACJ,CAAC,CAAC;iBACD,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;gBAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;gBAC3B,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC/B,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAChC,CAAC;gBACD,cAAc,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YACpD,CAAC,CAAC,CAAC;YAEL,mFAAmF;YACnF,kDAAkD;YAClD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;qBACxB,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;oBACzB,OAAO,CACL,IAAI,KAAK,iBAAiB;wBAC1B,IAAI,KAAK,MAAM,CAAC,IAAI,IAAI,6DAA6D;wBACrF,MAAM,CAAC,IAAI;wBACX,MAAM,CAAC,YAAY;wBACnB,MAAM,CAAC,KAAK;wBACZ,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAC/B,CAAC;gBACJ,CAAC,CAAC;qBACD,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;oBAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAM,CAAC;oBAC5B,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;wBAC9B,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBAC/B,CAAC;oBACD,aAAa,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;gBACnD,CAAC,CAAC,CAAC;YACP,CAAC;YAED,mEAAmE;YACnE,MAAM,UAAU,GAAmB,EAAE,CAAC;YAEtC,mDAAmD;YACnD,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACpD,uDAAuD;YACvD,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAErD,yDAAyD;YACzD,MAAM,sBAAsB,GAAG,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CACtE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE;gBACrB,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChD,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChD,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;YACJ,CAAC,CACF,CAAC;YAEF,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE;gBAChD,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;gBAC9C,iEAAiE;gBACjE,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBACtC,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBACjD,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBACjD,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,QAAQ,CAAC,KAAK;oBACpB,WAAW,EAAE,QAAQ,CAAC,WAAW;oBACjC,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,KAAK,EAAE,WAAW;oBAClB,WAAW,EAAE,KAAK;iBACnB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,qFAAqF;YACrF,gCAAgC;YAChC,mDAAmD;YACnD,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAEjD,MAAM,qBAAqB,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CACpE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE;gBACrB,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChD,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAChD,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;YACJ,CAAC,CACF,CAAC;YAEF,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE;gBAC/C,MAAM,QAAQ,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;gBAC9C,+DAA+D;gBAC/D,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBACtC,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC/C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC/C,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,UAAU,CAAC,IAAI,CAAC;oBACd,IAAI,EAAE,QAAQ,CAAC,KAAK;oBACpB,WAAW,EAAE,QAAQ,CAAC,WAAW;oBACjC,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,KAAK,EAAE,WAAW;oBAClB,WAAW,EAAE,IAAI;iBAClB,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YAEH,OAAO,UAAU,CAAC;QACpB,CAAC;aAAM,CAAC;YACN,wBAAwB;YACxB,MAAM,YAAY,GAAG,IAAI,GAAG,EAGzB,CAAC;YAEJ,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;iBACxB,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;gBACzB,8DAA8D;gBAC9D,yEAAyE;gBACzE,6DAA6D;gBAC7D,OAAO,CACL,IAAI,KAAK,iBAAiB;oBAC1B,IAAI,KAAK,MAAM,CAAC,IAAI;oBACpB,MAAM,CAAC,IAAI;oBACX,CAAC,MAAM,CAAC,YAAY;oBACpB,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAC/B,CAAC;YACJ,CAAC,CAAC;iBACD,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE;gBAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,YAAY,CAAC,KAAK,CAAC;gBACjD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC7B,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAC9B,CAAC;gBACD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAClD,CAAC,CAAC,CAAC;YAEL,yFAAyF;YACzF,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAClD,mDAAmD;YACnD,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAEjD,OAAO,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;iBACtC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE;gBACtB,MAAM,QAAQ,GACZ,oBAAoB,CAAC,KAAK,CAAC,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAC;gBAC9D,+DAA+D;gBAC/D,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;oBACtC,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC/C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC/C,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,OAAO;oBACL,IAAI,EAAE,QAAQ,CAAC,KAAK;oBACpB,WAAW,EAAE,QAAQ,CAAC,WAAW;oBACjC,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,KAAK,EAAE,WAAW;iBACnB,CAAC;YACJ,CAAC,CAAC;iBACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACb,qDAAqD;gBACrD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,IAAI,CACnD,CAAC,GAAG,EAAE,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,CACnD,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,IAAI,CACnD,CAAC,GAAG,EAAE,EAAE,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,CACnD,CAAC;gBACH,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC/C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC/C,OAAO,CACL,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAChE,CAAC;YACJ,CAAC,CAAC,CAAC;QACP,CAAC;IACH,CAAC;IAEM,MAAM;QACX,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO,IAAI,CAAA,EAAE,CAAC;QAChB,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACxC,MAAM,KAAK,GACT,IAAI,CAAC,IAAI,KAAK,OAAO;YACnB,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,qBAAqB;gBACrC,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,kBAAkB,CAAC;QAEzB,4DAA4D;QAC5D,MAAM,iBAAiB,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QACnE,MAAM,mBAAmB,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;QACpE,MAAM,mBAAmB,GAAG,mBAAmB,CAAC,MAAM,GAAG,CAAC,CAAC;QAE3D,OAAO,IAAI,CAAA;oCACqB,IAAI,CAAC,kBAAkB;mCACxB,CAAC,CAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE;;gBAEpD,KAAK;;;YAGT,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,qBAAqB;YAC7D,CAAC,CAAC,IAAI,CAAA;;oBAEE,iBAAiB,CAAC,GAAG,CACrB,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAA;;sDAEgB,QAAQ,CAAC,IAAI;;4BAEvC,QAAQ,CAAC,WAAW;;;4BAGpB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAClB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAA;;;uDAGa,QAAQ,CAAC,KAAK;yCAC5B,GAAG,EAAE,CACZ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;;;oCAGjC,IAAI,CAAC,MAAM,CAAC,IAAI;;8DAEU,IAAI,CAAC,IAAI;;6BAE1C,CACF;;;qBAGN,CACF;;kBAED,mBAAmB;gBACnB,CAAC,CAAC,IAAI,CAAA;;;;;;;;;0BASE,mBAAmB,CAAC,GAAG,CACvB,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAA;;4DAEgB,QAAQ,CAAC,IAAI;;kCAEvC,QAAQ,CAAC,WAAW;;;kCAGpB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAClB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAA;;;6DAGa,QAAQ,CAAC,KAAK;+CAC5B,GAAG,EAAE,CACZ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;;;0CAGjC,IAAI,CAAC,MAAM,CAAC,IAAI;;;0CAGhB,IAAI,CAAC,IAAI;;;mCAGhB,CACF;;;2BAGN,CACF;;qBAEJ;gBACH,CAAC,CAAC,EAAE;eACP;YACH,CAAC,CAAC,IAAI,CAAA;;oBAEE,UAAU,CAAC,GAAG,CACd,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAA;;sDAEgB,QAAQ,CAAC,IAAI;;4BAEvC,QAAQ,CAAC,WAAW;;;4BAGpB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAClB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAA;;;uDAGa,QAAQ,CAAC,KAAK;yCAC5B,GAAG,EAAE,CACZ,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;;;oCAGjC,IAAI,CAAC,MAAM,CAAC,IAAI;;8DAEU,IAAI,CAAC,IAAI;;6BAE1C,CACF;;;qBAGN,CACF;;eAEJ;;;iCAGkB,IAAI,CAAC,KAAK;;;KAGtC,CAAC;IACJ,CAAC;CACF;AAnZQ;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;8CACvB;AAGb;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CACwC;AAG5D;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;kDACS;AAG7B;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;kDACK;AAGvB;IADP,KAAK,EAAE;uDAC+B","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { NODE_CONFIG, ACTION_CONFIG } from './config';\nimport {\n NodeConfig,\n ActionConfig,\n ACTION_GROUPS,\n SPLIT_GROUPS,\n ACTION_GROUP_METADATA,\n SPLIT_GROUP_METADATA\n} from './types';\n\n/**\n * Event detail for node type selection\n */\nexport interface NodeTypeSelection {\n nodeType: string;\n position: { x: number; y: number };\n}\n\n/**\n * Categorizes node types for display\n */\ninterface NodeCategory {\n name: string;\n description: string;\n color: string;\n items: Array<{ type: string; config: NodeConfig | ActionConfig }>;\n isBranching?: boolean; // true if this category contains actions that branch/split\n}\n\n/**\n * NodeTypeSelector - A dialog for selecting which type of node to create\n * Shows categorized lists of available actions and splits\n */\nexport class NodeTypeSelector extends RapidElement {\n static get styles() {\n return css`\n :host {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 10001;\n display: none;\n }\n\n :host([open]) {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n }\n\n .dialog {\n position: relative;\n background: white;\n border-radius: var(--curvature);\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);\n max-width: 700px;\n max-height: 80vh;\n width: 90%;\n display: flex;\n flex-direction: column;\n }\n\n .header {\n padding: 1.5em;\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n }\n\n .header h2 {\n margin: 0;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--color-text-dark);\n }\n\n .content {\n overflow-y: auto;\n overflow-x: hidden;\n flex: 1;\n padding: 0;\n }\n\n .section-regular {\n padding: 1.5em;\n }\n\n .section-branching {\n background: linear-gradient(\n 135deg,\n rgba(170, 170, 170, 0.12),\n rgba(170, 170, 170, 0.08)\n );\n padding: 1.5em;\n margin: 0 -1.5em;\n padding-left: 3em;\n padding-right: 3em;\n }\n\n .section-header {\n margin-bottom: 1.5em;\n padding-top: 1em;\n }\n\n .section-title {\n font-weight: 700;\n font-size: 1.1rem;\n color: var(--color-text-dark);\n margin-bottom: 0.35em;\n display: flex;\n align-items: center;\n }\n\n .section-title::before {\n content: '';\n display: inline-block;\n height: 1.2em;\n background: linear-gradient(\n 135deg,\n var(--color-primary-dark),\n var(--color-primary)\n );\n border-radius: 2px;\n }\n\n .section-description {\n font-size: 0.9rem;\n color: var(--color-text);\n opacity: 0.7;\n margin-left: 0em;\n padding-bottom: 1em;\n }\n\n .category {\n margin-bottom: 2em;\n }\n\n .category:last-child {\n margin-bottom: 0;\n }\n\n .category-title {\n font-weight: 600;\n color: var(--color-text-dark);\n margin-bottom: 0.5em;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 0.9rem;\n opacity: 0.7;\n }\n\n .category-description {\n font-size: 0.85rem;\n color: var(--color-text);\n opacity: 0.6;\n margin-bottom: 0.75em;\n line-height: 1.4;\n }\n\n .items-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: 0.75em;\n }\n\n .node-item {\n padding: 1em;\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: calc(var(--curvature) * 0.75);\n cursor: pointer;\n transition: all 0.15s ease;\n background: white;\n position: relative;\n overflow: hidden;\n }\n\n .node-item::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 4px;\n height: 100%;\n background: var(--item-color, rgba(0, 0, 0, 0.1));\n }\n\n .node-item:hover {\n border-color: var(--item-color, var(--color-primary));\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n transform: translateY(-1px);\n }\n\n .node-item:hover::before {\n width: 6px;\n }\n\n .node-item-title {\n font-weight: 500;\n font-size: 1rem;\n color: var(--color-text-dark);\n margin-bottom: 0.25em;\n }\n\n .node-item-type {\n font-size: 0.75rem;\n color: var(--color-text);\n opacity: 0.6;\n font-family: monospace;\n }\n\n .footer {\n padding: 1em 1.5em;\n border-top: 1px solid rgba(0, 0, 0, 0.1);\n display: flex;\n justify-content: flex-end;\n }\n\n temba-button {\n --button-y: 0.5em;\n --button-x: 1.25em;\n }\n `;\n }\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n @property({ type: String })\n public mode: 'action' | 'split' | 'action-no-branching' = 'action';\n\n @property({ type: String })\n public flowType: string = 'message';\n\n @property({ type: Array })\n public features: string[] = [];\n\n @state()\n private clickPosition = { x: 0, y: 0 };\n\n public show(\n mode: 'action' | 'split' | 'action-no-branching',\n position: { x: number; y: number }\n ) {\n this.mode = mode;\n this.clickPosition = position;\n this.open = true;\n }\n\n public close() {\n this.open = false;\n }\n\n /**\n * Check if a config is available for the current flow type and features\n */\n private isConfigAvailable(config: NodeConfig | ActionConfig): boolean {\n // Check flow type filter\n if (config.flowTypes !== undefined) {\n // Empty array means not available for any flow type in selector\n if (config.flowTypes.length === 0) {\n return false;\n }\n // Non-empty array means check if current flow type is included\n if (!config.flowTypes.includes(this.flowType as any)) {\n return false;\n }\n }\n // undefined/null flowTypes means available for all flow types\n\n // Check features filter - all required features must be present\n if (config.features && config.features.length > 0) {\n for (const requiredFeature of config.features) {\n if (!this.features.includes(requiredFeature)) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n private handleNodeTypeClick(nodeType: string) {\n this.fireCustomEvent(CustomEventType.Selection, {\n nodeType,\n position: this.clickPosition\n } as NodeTypeSelection);\n this.close();\n }\n\n private handleOverlayClick() {\n this.close();\n }\n\n private getCategories(): NodeCategory[] {\n if (this.mode === 'action' || this.mode === 'action-no-branching') {\n // Group actions by group\n const actionsByGroup = new Map<\n string,\n Array<{ type: string; config: ActionConfig }>\n >();\n const splitsByGroup = new Map<\n string,\n Array<{ type: string; config: NodeConfig }>\n >();\n\n // Collect regular actions (from ACTION_CONFIG, unless hideFromActions is true)\n Object.entries(ACTION_CONFIG)\n .filter(([type, config]) => {\n // exclude aliases - if config has aliases, check if this type is an alias\n const isAlias = config.aliases && config.aliases.includes(type);\n return (\n !isAlias &&\n config.name &&\n !config.hideFromActions &&\n config.group &&\n this.isConfigAvailable(config)\n );\n })\n .forEach(([type, config]) => {\n const group = config.group;\n if (!actionsByGroup.has(group)) {\n actionsByGroup.set(group, []);\n }\n actionsByGroup.get(group)!.push({ type, config });\n });\n\n // Collect nodes that have showAsAction=true (these appear as \"with split\" actions)\n // Only if we're not in 'action-no-branching' mode\n if (this.mode === 'action') {\n Object.entries(NODE_CONFIG)\n .filter(([type, config]) => {\n return (\n type !== 'execute_actions' &&\n type === config.type && // exclude aliases (type won't match config.type for aliases)\n config.name &&\n config.showAsAction &&\n config.group &&\n this.isConfigAvailable(config)\n );\n })\n .forEach(([type, config]) => {\n const group = config.group!;\n if (!splitsByGroup.has(group)) {\n splitsByGroup.set(group, []);\n }\n splitsByGroup.get(group)!.push({ type, config });\n });\n }\n\n // Build categories - first regular actions, then splitting actions\n const categories: NodeCategory[] = [];\n\n // Get the implicit order from ACTION_GROUPS object\n const actionGroupOrder = Object.keys(ACTION_GROUPS);\n // Get the implicit order of actions from ACTION_CONFIG\n const actionConfigOrder = Object.keys(ACTION_CONFIG);\n\n // Add regular action categories sorted by implicit order\n const sortedActionCategories = Array.from(actionsByGroup.entries()).sort(\n ([groupA], [groupB]) => {\n const orderA = actionGroupOrder.indexOf(groupA);\n const orderB = actionGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n }\n );\n\n sortedActionCategories.forEach(([group, items]) => {\n const metadata = ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in ACTION_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = actionConfigOrder.indexOf(a.type);\n const orderB = actionConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n categories.push({\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems,\n isBranching: false\n });\n });\n\n // Add splitting action categories (with modified description to indicate they split)\n // Also sorted by implicit order\n // Get the implicit order of nodes from NODE_CONFIG\n const nodeConfigOrder = Object.keys(NODE_CONFIG);\n\n const sortedSplitCategories = Array.from(splitsByGroup.entries()).sort(\n ([groupA], [groupB]) => {\n const orderA = actionGroupOrder.indexOf(groupA);\n const orderB = actionGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n }\n );\n\n sortedSplitCategories.forEach(([group, items]) => {\n const metadata = ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in NODE_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = nodeConfigOrder.indexOf(a.type);\n const orderB = nodeConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n categories.push({\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems,\n isBranching: true\n });\n });\n\n return categories;\n } else {\n // Group splits by group\n const itemsByGroup = new Map<\n string,\n Array<{ type: string; config: NodeConfig }>\n >();\n\n Object.entries(NODE_CONFIG)\n .filter(([type, config]) => {\n // exclude execute_actions (it's the default action-only node)\n // exclude nodes that have showAsAction=true (they appear in action mode)\n // exclude aliases (type won't match config.type for aliases)\n return (\n type !== 'execute_actions' &&\n type === config.type &&\n config.name &&\n !config.showAsAction &&\n this.isConfigAvailable(config)\n );\n })\n .forEach(([type, config]) => {\n const group = config.group || SPLIT_GROUPS.split;\n if (!itemsByGroup.has(group)) {\n itemsByGroup.set(group, []);\n }\n itemsByGroup.get(group)!.push({ type, config });\n });\n\n // Convert to categories using group metadata, sorted by implicit order from SPLIT_GROUPS\n const splitGroupOrder = Object.keys(SPLIT_GROUPS);\n // Get the implicit order of nodes from NODE_CONFIG\n const nodeConfigOrder = Object.keys(NODE_CONFIG);\n\n return Array.from(itemsByGroup.entries())\n .map(([group, items]) => {\n const metadata =\n SPLIT_GROUP_METADATA[group] || ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in NODE_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = nodeConfigOrder.indexOf(a.type);\n const orderB = nodeConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n return {\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems\n };\n })\n .sort((a, b) => {\n // Find the group key by looking up metadata by title\n const groupA = Object.keys(SPLIT_GROUP_METADATA).find(\n (key) => SPLIT_GROUP_METADATA[key].title === a.name\n )!;\n const groupB = Object.keys(SPLIT_GROUP_METADATA).find(\n (key) => SPLIT_GROUP_METADATA[key].title === b.name\n )!;\n const orderA = splitGroupOrder.indexOf(groupA);\n const orderB = splitGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n }\n }\n\n public render(): TemplateResult {\n if (!this.open) {\n return html``;\n }\n\n const categories = this.getCategories();\n const title =\n this.mode === 'split'\n ? 'Select a Split'\n : this.mode === 'action-no-branching'\n ? 'Add Action'\n : 'Select an Action';\n\n // Separate regular and branching categories for action mode\n const regularCategories = categories.filter((c) => !c.isBranching);\n const branchingCategories = categories.filter((c) => c.isBranching);\n const hasBranchingSection = branchingCategories.length > 0;\n\n return html`\n <div class=\"overlay\" @click=${this.handleOverlayClick}></div>\n <div class=\"dialog\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"header\">\n <h2>${title}</h2>\n </div>\n <div class=\"content\">\n ${this.mode === 'action' || this.mode === 'action-no-branching'\n ? html`\n <div class=\"section-regular\">\n ${regularCategories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n <div class=\"node-item-type\">${item.type}</div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n ${hasBranchingSection\n ? html`\n <div class=\"section-branching\">\n <div class=\"section-header\">\n <div class=\"section-title\">Actions that Branch</div>\n <div class=\"section-description\">\n These actions also split the flow based on their\n outcome\n </div>\n </div>\n ${branchingCategories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n <div class=\"node-item-type\">\n ${item.type}\n </div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n `\n : ''}\n `\n : html`\n <div class=\"section-regular\">\n ${categories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n <div class=\"node-item-type\">${item.type}</div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n `}\n </div>\n <div class=\"footer\">\n <temba-button @click=${this.close} secondary>Cancel</temba-button>\n </div>\n </div>\n `;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"NodeTypeSelector.js","sourceRoot":"","sources":["../../../src/flow/NodeTypeSelector.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { RapidElement } from '../RapidElement';\nimport { CustomEventType } from '../interfaces';\nimport { NODE_CONFIG, ACTION_CONFIG } from './config';\nimport {\n NodeConfig,\n ActionConfig,\n ACTION_GROUPS,\n SPLIT_GROUPS,\n ACTION_GROUP_METADATA,\n SPLIT_GROUP_METADATA\n} from './types';\n\n/**\n * Event detail for node type selection\n */\nexport interface NodeTypeSelection {\n nodeType: string;\n position: { x: number; y: number };\n}\n\n/**\n * Categorizes node types for display\n */\ninterface NodeCategory {\n name: string;\n description: string;\n color: string;\n items: Array<{ type: string; config: NodeConfig | ActionConfig }>;\n isBranching?: boolean; // true if this category contains actions that branch/split\n}\n\n/**\n * NodeTypeSelector - A dialog for selecting which type of node to create\n * Shows categorized lists of available actions and splits\n */\nexport class NodeTypeSelector extends RapidElement {\n static get styles() {\n return css`\n :host {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n z-index: 10001;\n display: none;\n }\n\n :host([open]) {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .overlay {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n background: rgba(0, 0, 0, 0.5);\n }\n\n .dialog {\n position: relative;\n background: white;\n border-radius: var(--curvature);\n box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);\n max-width: 700px;\n max-height: 80vh;\n width: 90%;\n display: flex;\n flex-direction: column;\n }\n\n .header {\n padding: 1.5em;\n border-bottom: 1px solid rgba(0, 0, 0, 0.1);\n }\n\n .header h2 {\n margin: 0;\n font-size: 1.5rem;\n font-weight: 600;\n color: var(--color-text-dark);\n }\n\n .content {\n overflow-y: auto;\n overflow-x: hidden;\n flex: 1;\n padding: 0;\n }\n\n .section-regular {\n padding: 1.5em;\n }\n\n .section-branching {\n background: linear-gradient(\n 135deg,\n rgba(170, 170, 170, 0.12),\n rgba(170, 170, 170, 0.08)\n );\n padding: 1.5em;\n margin: 0 -1.5em;\n padding-left: 3em;\n padding-right: 3em;\n }\n\n .section-header {\n margin-bottom: 1.5em;\n padding-top: 1em;\n }\n\n .section-title {\n font-weight: 700;\n font-size: 1.1rem;\n color: var(--color-text-dark);\n margin-bottom: 0.35em;\n display: flex;\n align-items: center;\n }\n\n .section-title::before {\n content: '';\n display: inline-block;\n height: 1.2em;\n background: linear-gradient(\n 135deg,\n var(--color-primary-dark),\n var(--color-primary)\n );\n border-radius: 2px;\n }\n\n .section-description {\n font-size: 0.9rem;\n color: var(--color-text);\n opacity: 0.7;\n margin-left: 0em;\n padding-bottom: 1em;\n }\n\n .category {\n margin-bottom: 2em;\n }\n\n .category:last-child {\n margin-bottom: 0;\n }\n\n .category-title {\n font-weight: 600;\n color: var(--color-text-dark);\n margin-bottom: 0.5em;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-size: 0.9rem;\n opacity: 0.7;\n }\n\n .category-description {\n font-size: 0.85rem;\n color: var(--color-text);\n opacity: 0.6;\n margin-bottom: 0.75em;\n line-height: 1.4;\n }\n\n .items-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));\n gap: 0.75em;\n }\n\n .node-item {\n padding: 0.5em;\n padding-left: 1em;\n border: 1px solid rgba(0, 0, 0, 0.1);\n border-radius: calc(var(--curvature) * 0.75);\n cursor: pointer;\n transition: all 0.15s ease;\n background: white;\n position: relative;\n overflow: hidden;\n }\n\n .node-item::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n width: 4px;\n height: 100%;\n background: var(--item-color, rgba(0, 0, 0, 0.1));\n }\n\n .node-item:hover {\n border-color: var(--item-color, var(--color-primary));\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);\n transform: translateY(-1px);\n }\n\n .node-item:hover::before {\n width: 6px;\n }\n\n .node-item-title {\n font-weight: 500;\n font-size: 1rem;\n color: var(--color-text-dark);\n }\n\n .node-item-type {\n font-size: 0.75rem;\n color: var(--color-text);\n opacity: 0.6;\n font-family: monospace;\n }\n\n .footer {\n padding: 1em 1.5em;\n border-top: 1px solid rgba(0, 0, 0, 0.1);\n display: flex;\n justify-content: flex-end;\n }\n\n temba-button {\n --button-y: 0.5em;\n --button-x: 1.25em;\n }\n `;\n }\n\n @property({ type: Boolean, reflect: true })\n public open = false;\n\n @property({ type: String })\n public mode: 'action' | 'split' | 'action-no-branching' = 'action';\n\n @property({ type: String })\n public flowType: string = 'message';\n\n @property({ type: Array })\n public features: string[] = [];\n\n @state()\n private clickPosition = { x: 0, y: 0 };\n\n public show(\n mode: 'action' | 'split' | 'action-no-branching',\n position: { x: number; y: number }\n ) {\n this.mode = mode;\n this.clickPosition = position;\n this.open = true;\n }\n\n public close(fireCanceledEvent: boolean = true) {\n if (this.open) {\n this.open = false;\n // Fire canceled event so parent can clean up, but only if not from a selection\n if (fireCanceledEvent) {\n this.fireCustomEvent(CustomEventType.Canceled, {});\n }\n }\n }\n\n /**\n * Check if a config is available for the current flow type and features\n */\n private isConfigAvailable(config: NodeConfig | ActionConfig): boolean {\n // Check flow type filter\n if (config.flowTypes !== undefined) {\n // Empty array means not available for any flow type in selector\n if (config.flowTypes.length === 0) {\n return false;\n }\n // Non-empty array means check if current flow type is included\n if (!config.flowTypes.includes(this.flowType as any)) {\n return false;\n }\n }\n // undefined/null flowTypes means available for all flow types\n\n // Check features filter - all required features must be present\n if (config.features && config.features.length > 0) {\n for (const requiredFeature of config.features) {\n if (!this.features.includes(requiredFeature)) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n private handleNodeTypeClick(nodeType: string) {\n this.fireCustomEvent(CustomEventType.Selection, {\n nodeType,\n position: this.clickPosition\n } as NodeTypeSelection);\n // Close without firing canceled event since we made a selection\n this.close(false);\n }\n\n private handleOverlayClick() {\n this.close();\n }\n\n private getCategories(): NodeCategory[] {\n if (this.mode === 'action' || this.mode === 'action-no-branching') {\n // Group actions by group\n const actionsByGroup = new Map<\n string,\n Array<{ type: string; config: ActionConfig }>\n >();\n const splitsByGroup = new Map<\n string,\n Array<{ type: string; config: NodeConfig }>\n >();\n\n // Collect regular actions (from ACTION_CONFIG, unless hideFromActions is true)\n Object.entries(ACTION_CONFIG)\n .filter(([type, config]) => {\n // exclude aliases - if config has aliases, check if this type is an alias\n const isAlias = config.aliases && config.aliases.includes(type);\n return (\n !isAlias &&\n config.name &&\n !config.hideFromActions &&\n config.group &&\n this.isConfigAvailable(config)\n );\n })\n .forEach(([type, config]) => {\n const group = config.group;\n if (!actionsByGroup.has(group)) {\n actionsByGroup.set(group, []);\n }\n actionsByGroup.get(group)!.push({ type, config });\n });\n\n // Collect nodes that have showAsAction=true (these appear as \"with split\" actions)\n // Only if we're not in 'action-no-branching' mode\n if (this.mode === 'action') {\n Object.entries(NODE_CONFIG)\n .filter(([type, config]) => {\n return (\n type !== 'execute_actions' &&\n type === config.type && // exclude aliases (type won't match config.type for aliases)\n config.name &&\n config.showAsAction &&\n config.group &&\n this.isConfigAvailable(config)\n );\n })\n .forEach(([type, config]) => {\n const group = config.group!;\n if (!splitsByGroup.has(group)) {\n splitsByGroup.set(group, []);\n }\n splitsByGroup.get(group)!.push({ type, config });\n });\n }\n\n // Build categories - first regular actions, then splitting actions\n const categories: NodeCategory[] = [];\n\n // Get the implicit order from ACTION_GROUPS object\n const actionGroupOrder = Object.keys(ACTION_GROUPS);\n // Get the implicit order of actions from ACTION_CONFIG\n const actionConfigOrder = Object.keys(ACTION_CONFIG);\n\n // Add regular action categories sorted by implicit order\n const sortedActionCategories = Array.from(actionsByGroup.entries()).sort(\n ([groupA], [groupB]) => {\n const orderA = actionGroupOrder.indexOf(groupA);\n const orderB = actionGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n }\n );\n\n sortedActionCategories.forEach(([group, items]) => {\n const metadata = ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in ACTION_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = actionConfigOrder.indexOf(a.type);\n const orderB = actionConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n categories.push({\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems,\n isBranching: false\n });\n });\n\n // Add splitting action categories (with modified description to indicate they split)\n // Also sorted by implicit order\n // Get the implicit order of nodes from NODE_CONFIG\n const nodeConfigOrder = Object.keys(NODE_CONFIG);\n\n const sortedSplitCategories = Array.from(splitsByGroup.entries()).sort(\n ([groupA], [groupB]) => {\n const orderA = actionGroupOrder.indexOf(groupA);\n const orderB = actionGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n }\n );\n\n sortedSplitCategories.forEach(([group, items]) => {\n const metadata = ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in NODE_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = nodeConfigOrder.indexOf(a.type);\n const orderB = nodeConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n categories.push({\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems,\n isBranching: true\n });\n });\n\n return categories;\n } else {\n // Group splits by group\n const itemsByGroup = new Map<\n string,\n Array<{ type: string; config: NodeConfig }>\n >();\n\n Object.entries(NODE_CONFIG)\n .filter(([type, config]) => {\n // exclude execute_actions (it's the default action-only node)\n // exclude nodes that have showAsAction=true (they appear in action mode)\n // exclude aliases (type won't match config.type for aliases)\n return (\n type !== 'execute_actions' &&\n type === config.type &&\n config.name &&\n !config.showAsAction &&\n this.isConfigAvailable(config)\n );\n })\n .forEach(([type, config]) => {\n const group = config.group || SPLIT_GROUPS.split;\n if (!itemsByGroup.has(group)) {\n itemsByGroup.set(group, []);\n }\n itemsByGroup.get(group)!.push({ type, config });\n });\n\n // Convert to categories using group metadata, sorted by implicit order from SPLIT_GROUPS\n const splitGroupOrder = Object.keys(SPLIT_GROUPS);\n // Get the implicit order of nodes from NODE_CONFIG\n const nodeConfigOrder = Object.keys(NODE_CONFIG);\n\n return Array.from(itemsByGroup.entries())\n .map(([group, items]) => {\n const metadata =\n SPLIT_GROUP_METADATA[group] || ACTION_GROUP_METADATA[group];\n // Sort items within the category by their order in NODE_CONFIG\n const sortedItems = items.sort((a, b) => {\n const orderA = nodeConfigOrder.indexOf(a.type);\n const orderB = nodeConfigOrder.indexOf(b.type);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n return {\n name: metadata.title,\n description: metadata.description,\n color: metadata.color,\n items: sortedItems\n };\n })\n .sort((a, b) => {\n // Find the group key by looking up metadata by title\n const groupA = Object.keys(SPLIT_GROUP_METADATA).find(\n (key) => SPLIT_GROUP_METADATA[key].title === a.name\n )!;\n const groupB = Object.keys(SPLIT_GROUP_METADATA).find(\n (key) => SPLIT_GROUP_METADATA[key].title === b.name\n )!;\n const orderA = splitGroupOrder.indexOf(groupA);\n const orderB = splitGroupOrder.indexOf(groupB);\n return (\n (orderA === -1 ? 999 : orderA) - (orderB === -1 ? 999 : orderB)\n );\n });\n }\n }\n\n public render(): TemplateResult {\n if (!this.open) {\n return html``;\n }\n\n const categories = this.getCategories();\n const title =\n this.mode === 'split'\n ? 'Select a Split'\n : this.mode === 'action-no-branching'\n ? 'Add Action'\n : 'Select an Action';\n\n // Separate regular and branching categories for action mode\n const regularCategories = categories.filter((c) => !c.isBranching);\n const branchingCategories = categories.filter((c) => c.isBranching);\n const hasBranchingSection = branchingCategories.length > 0;\n\n return html`\n <div class=\"overlay\" @click=${this.handleOverlayClick}></div>\n <div class=\"dialog\" @click=${(e: Event) => e.stopPropagation()}>\n <div class=\"header\">\n <h2>${title}</h2>\n </div>\n <div class=\"content\">\n ${this.mode === 'action' || this.mode === 'action-no-branching'\n ? html`\n <div class=\"section-regular\">\n ${regularCategories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n ${hasBranchingSection\n ? html`\n <div class=\"section-branching\">\n <div class=\"section-header\">\n <div class=\"section-title\">Actions that Branch</div>\n <div class=\"section-description\">\n These actions also split the flow based on their\n outcome\n </div>\n </div>\n ${branchingCategories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n `\n : ''}\n `\n : html`\n <div class=\"section-regular\">\n ${categories.map(\n (category) => html`\n <div class=\"category\">\n <div class=\"category-title\">${category.name}</div>\n <div class=\"category-description\">\n ${category.description}\n </div>\n <div class=\"items-grid\">\n ${category.items.map(\n (item) => html`\n <div\n class=\"node-item\"\n style=\"--item-color: ${category.color}\"\n @click=${() =>\n this.handleNodeTypeClick(item.type)}\n >\n <div class=\"node-item-title\">\n ${item.config.name}\n </div>\n </div>\n `\n )}\n </div>\n </div>\n `\n )}\n </div>\n `}\n </div>\n <div class=\"footer\">\n <temba-button @click=${this.close} secondary>Cancel</temba-button>\n </div>\n </div>\n `;\n }\n}\n"]}
|
|
@@ -57,6 +57,43 @@ export const TARGET_DEFAULTS = {
|
|
|
57
57
|
target: true
|
|
58
58
|
};
|
|
59
59
|
export class Plumber {
|
|
60
|
+
initializeJSPlumb(canvas) {
|
|
61
|
+
this.jsPlumb = newInstance({
|
|
62
|
+
container: canvas,
|
|
63
|
+
connectionsDetachable: true,
|
|
64
|
+
endpointStyle: {
|
|
65
|
+
fill: 'green'
|
|
66
|
+
},
|
|
67
|
+
connector: CONNECTOR_DEFAULTS,
|
|
68
|
+
connectionOverlays: OVERLAYS_DEFAULTS
|
|
69
|
+
});
|
|
70
|
+
// Bind to connection events
|
|
71
|
+
this.jsPlumb.bind(EVENT_CONNECTION, (info) => {
|
|
72
|
+
this.connectionDragging = false;
|
|
73
|
+
this.notifyListeners(EVENT_CONNECTION, info);
|
|
74
|
+
});
|
|
75
|
+
// Bind to connection drag events
|
|
76
|
+
this.jsPlumb.bind(EVENT_CONNECTION_DRAG, (info) => {
|
|
77
|
+
this.connectionDragging = true;
|
|
78
|
+
this.notifyListeners(EVENT_CONNECTION_DRAG, info);
|
|
79
|
+
});
|
|
80
|
+
this.jsPlumb.bind(EVENT_CONNECTION_ABORT, (info) => {
|
|
81
|
+
this.connectionDragging = false;
|
|
82
|
+
this.notifyListeners(EVENT_CONNECTION_ABORT, info);
|
|
83
|
+
});
|
|
84
|
+
this.jsPlumb.bind(EVENT_CONNECTION_DETACHED, (info) => {
|
|
85
|
+
this.connectionDragging = false;
|
|
86
|
+
this.notifyListeners(EVENT_CONNECTION_DETACHED, info);
|
|
87
|
+
});
|
|
88
|
+
this.jsPlumb.bind(EVENT_REVERT, (info) => {
|
|
89
|
+
this.notifyListeners(EVENT_REVERT, info);
|
|
90
|
+
});
|
|
91
|
+
this.jsPlumb.bind(INTERCEPT_BEFORE_DROP, () => {
|
|
92
|
+
// we always deny automatic connections
|
|
93
|
+
return false;
|
|
94
|
+
});
|
|
95
|
+
this.jsPlumb.bind(INTERCEPT_BEFORE_DETACH, () => { });
|
|
96
|
+
}
|
|
60
97
|
constructor(canvas, editor) {
|
|
61
98
|
this.jsPlumb = null;
|
|
62
99
|
this.pendingConnections = [];
|
|
@@ -72,41 +109,7 @@ export class Plumber {
|
|
|
72
109
|
this.showContactsTimeout = null;
|
|
73
110
|
this.editor = editor;
|
|
74
111
|
ready(() => {
|
|
75
|
-
this.
|
|
76
|
-
container: canvas,
|
|
77
|
-
connectionsDetachable: true,
|
|
78
|
-
endpointStyle: {
|
|
79
|
-
fill: 'green'
|
|
80
|
-
},
|
|
81
|
-
connector: CONNECTOR_DEFAULTS,
|
|
82
|
-
connectionOverlays: OVERLAYS_DEFAULTS
|
|
83
|
-
});
|
|
84
|
-
// Bind to connection events
|
|
85
|
-
this.jsPlumb.bind(EVENT_CONNECTION, (info) => {
|
|
86
|
-
this.connectionDragging = false;
|
|
87
|
-
this.notifyListeners(EVENT_CONNECTION, info);
|
|
88
|
-
});
|
|
89
|
-
// Bind to connection drag events
|
|
90
|
-
this.jsPlumb.bind(EVENT_CONNECTION_DRAG, (info) => {
|
|
91
|
-
this.connectionDragging = true;
|
|
92
|
-
this.notifyListeners(EVENT_CONNECTION_DRAG, info);
|
|
93
|
-
});
|
|
94
|
-
this.jsPlumb.bind(EVENT_CONNECTION_ABORT, (info) => {
|
|
95
|
-
this.connectionDragging = false;
|
|
96
|
-
this.notifyListeners(EVENT_CONNECTION_ABORT, info);
|
|
97
|
-
});
|
|
98
|
-
this.jsPlumb.bind(EVENT_CONNECTION_DETACHED, (info) => {
|
|
99
|
-
this.connectionDragging = false;
|
|
100
|
-
this.notifyListeners(EVENT_CONNECTION_DETACHED, info);
|
|
101
|
-
});
|
|
102
|
-
this.jsPlumb.bind(EVENT_REVERT, (info) => {
|
|
103
|
-
this.notifyListeners(EVENT_REVERT, info);
|
|
104
|
-
});
|
|
105
|
-
this.jsPlumb.bind(INTERCEPT_BEFORE_DROP, () => {
|
|
106
|
-
// we always deny automatic connections
|
|
107
|
-
return false;
|
|
108
|
-
});
|
|
109
|
-
this.jsPlumb.bind(INTERCEPT_BEFORE_DETACH, () => { });
|
|
112
|
+
this.initializeJSPlumb(canvas);
|
|
110
113
|
});
|
|
111
114
|
}
|
|
112
115
|
notifyListeners(eventName, info) {
|
|
@@ -130,11 +133,15 @@ export class Plumber {
|
|
|
130
133
|
}
|
|
131
134
|
makeTarget(uuid) {
|
|
132
135
|
const element = document.getElementById(uuid);
|
|
133
|
-
|
|
136
|
+
if (!element)
|
|
137
|
+
return;
|
|
138
|
+
return this.jsPlumb.addEndpoint(element, TARGET_DEFAULTS);
|
|
134
139
|
}
|
|
135
140
|
makeSource(uuid) {
|
|
136
141
|
const element = document.getElementById(uuid);
|
|
137
|
-
|
|
142
|
+
if (!element)
|
|
143
|
+
return;
|
|
144
|
+
return this.jsPlumb.addEndpoint(element, SOURCE_DEFAULTS);
|
|
138
145
|
}
|
|
139
146
|
// we'll process our pending connections, but we want to debounce this
|
|
140
147
|
processPendingConnections() {
|
|
@@ -147,25 +154,30 @@ export class Plumber {
|
|
|
147
154
|
this.connectionWait = setTimeout(() => {
|
|
148
155
|
this.jsPlumb.batch(() => {
|
|
149
156
|
this.pendingConnections.forEach((connection) => {
|
|
157
|
+
var _a;
|
|
150
158
|
const { scope, fromId, toId } = connection;
|
|
151
|
-
|
|
152
|
-
const
|
|
153
|
-
//
|
|
154
|
-
this.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
endpoint:
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
159
|
+
// sources and targets must exist
|
|
160
|
+
const source = document.getElementById(fromId);
|
|
161
|
+
// const target = document.getElementById(toId);
|
|
162
|
+
this.revalidate([fromId, toId]);
|
|
163
|
+
// we need to find the source endpoint
|
|
164
|
+
const sourceEndpoint = (_a = this.jsPlumb
|
|
165
|
+
.getEndpoints(source)) === null || _a === void 0 ? void 0 : _a.find((endpoint) => endpoint.elementId === fromId ? true : false);
|
|
166
|
+
// update endpoint have connect css class
|
|
167
|
+
if (sourceEndpoint) {
|
|
168
|
+
sourceEndpoint.addClass('connected');
|
|
169
|
+
}
|
|
170
|
+
// each connection needs its own target endpoint
|
|
171
|
+
const targetEndpoint = this.makeTarget(toId);
|
|
172
|
+
if (!source || !targetEndpoint) {
|
|
173
|
+
console.warn(`Plumber: Cannot connect ${fromId} to ${toId}. Element(s) missing.`);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
// delete connections
|
|
177
|
+
this.jsPlumb.select({ source, targetEndpoint }).deleteAll();
|
|
166
178
|
this.jsPlumb.connect({
|
|
167
|
-
source,
|
|
168
|
-
target,
|
|
179
|
+
source: source,
|
|
180
|
+
target: targetEndpoint,
|
|
169
181
|
connector: {
|
|
170
182
|
...CONNECTOR_DEFAULTS,
|
|
171
183
|
options: { ...CONNECTOR_DEFAULTS.options, gap: [0, 5] }
|
|
@@ -177,7 +189,14 @@ export class Plumber {
|
|
|
177
189
|
});
|
|
178
190
|
this.pendingConnections = [];
|
|
179
191
|
});
|
|
180
|
-
|
|
192
|
+
// Force a repaint to ensure connections are positioned correctly
|
|
193
|
+
// especially after bulk updates or view switching
|
|
194
|
+
window.requestAnimationFrame(() => {
|
|
195
|
+
if (this.jsPlumb) {
|
|
196
|
+
this.jsPlumb.repaintEverything();
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}, 0);
|
|
181
200
|
}
|
|
182
201
|
connectIds(scope, fromId, toId) {
|
|
183
202
|
this.pendingConnections.push({ scope, fromId, toId });
|
|
@@ -510,17 +529,39 @@ export class Plumber {
|
|
|
510
529
|
});
|
|
511
530
|
});
|
|
512
531
|
}
|
|
513
|
-
|
|
532
|
+
reset() {
|
|
533
|
+
if (this.connectionWait) {
|
|
534
|
+
clearTimeout(this.connectionWait);
|
|
535
|
+
this.connectionWait = null;
|
|
536
|
+
}
|
|
537
|
+
this.pendingConnections = [];
|
|
538
|
+
this.jsPlumb.select().deleteAll();
|
|
539
|
+
this.jsPlumb._managedElements = {};
|
|
540
|
+
}
|
|
541
|
+
forgetNode(nodeId) {
|
|
542
|
+
if (!this.jsPlumb)
|
|
543
|
+
return;
|
|
544
|
+
const element = document.getElementById(nodeId);
|
|
545
|
+
if (!element)
|
|
546
|
+
return;
|
|
547
|
+
this.jsPlumb.deleteConnectionsForElement(element);
|
|
548
|
+
this.jsPlumb.removeAllEndpoints(element);
|
|
549
|
+
this.jsPlumb.unmanage(element);
|
|
550
|
+
}
|
|
551
|
+
removeNodeConnections(nodeId, exitIds) {
|
|
514
552
|
var _a;
|
|
515
553
|
if (!this.jsPlumb)
|
|
516
554
|
return;
|
|
517
555
|
const inbound = this.jsPlumb.select({ target: nodeId });
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
556
|
+
// Use provided exitIds or try to find them in DOM (fallback)
|
|
557
|
+
const exits = exitIds ||
|
|
558
|
+
Array.from(((_a = document.getElementById(nodeId)) === null || _a === void 0 ? void 0 : _a.querySelectorAll('.exit')) || []).map((exit) => {
|
|
559
|
+
return exit.id;
|
|
560
|
+
}) ||
|
|
561
|
+
[];
|
|
521
562
|
inbound.deleteAll();
|
|
522
|
-
this.jsPlumb.select({ source:
|
|
523
|
-
this.jsPlumb.selectEndpoints({ source:
|
|
563
|
+
this.jsPlumb.select({ source: exits }).deleteAll();
|
|
564
|
+
this.jsPlumb.selectEndpoints({ source: exits }).deleteAll();
|
|
524
565
|
}
|
|
525
566
|
removeExitConnection(exitId) {
|
|
526
567
|
if (!this.jsPlumb)
|
|
@@ -534,11 +575,16 @@ export class Plumber {
|
|
|
534
575
|
connections.forEach((connection) => {
|
|
535
576
|
this.jsPlumb.deleteConnection(connection);
|
|
536
577
|
});
|
|
537
|
-
// Re-create the source endpoint (now without connection)
|
|
538
|
-
this.jsPlumb.removeAllEndpoints(exitElement);
|
|
539
|
-
this.makeSource(exitId);
|
|
540
578
|
return connections.length > 0;
|
|
541
579
|
}
|
|
580
|
+
removeAllEndpoints(nodeId) {
|
|
581
|
+
if (!this.jsPlumb)
|
|
582
|
+
return;
|
|
583
|
+
const element = document.getElementById(nodeId);
|
|
584
|
+
if (!element)
|
|
585
|
+
return;
|
|
586
|
+
this.jsPlumb.removeAllEndpoints(element, true);
|
|
587
|
+
}
|
|
542
588
|
/**
|
|
543
589
|
* Set the removing state for an exit's connection
|
|
544
590
|
* @param exitId The ID of the exit whose connections should be marked as removing
|