@nyaruka/temba-components 0.142.2 → 0.142.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/temba-components.js +266 -192
  3. package/dist/temba-components.js.map +1 -1
  4. package/out-tsc/src/flow/CanvasMenu.js +8 -3
  5. package/out-tsc/src/flow/CanvasMenu.js.map +1 -1
  6. package/out-tsc/src/flow/CanvasNode.js +158 -9
  7. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  8. package/out-tsc/src/flow/Editor.js +473 -17
  9. package/out-tsc/src/flow/Editor.js.map +1 -1
  10. package/out-tsc/src/flow/NodeEditor.js +8 -8
  11. package/out-tsc/src/flow/NodeEditor.js.map +1 -1
  12. package/out-tsc/src/flow/Plumber.js +89 -27
  13. package/out-tsc/src/flow/Plumber.js.map +1 -1
  14. package/out-tsc/src/flow/StickyNote.js +63 -3
  15. package/out-tsc/src/flow/StickyNote.js.map +1 -1
  16. package/out-tsc/src/flow/actions/send_msg.js +11 -8
  17. package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
  18. package/out-tsc/src/flow/nodes/split_by_subflow.js +3 -1
  19. package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
  20. package/out-tsc/src/flow/utils.js +1 -3
  21. package/out-tsc/src/flow/utils.js.map +1 -1
  22. package/out-tsc/src/list/SortableList.js +104 -43
  23. package/out-tsc/src/list/SortableList.js.map +1 -1
  24. package/out-tsc/src/simulator/Simulator.js +5 -1
  25. package/out-tsc/src/simulator/Simulator.js.map +1 -1
  26. package/package.json +1 -1
  27. package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
  28. package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
  29. package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
  30. package/src/flow/CanvasMenu.ts +12 -4
  31. package/src/flow/CanvasNode.ts +185 -9
  32. package/src/flow/Editor.ts +552 -19
  33. package/src/flow/NodeEditor.ts +12 -12
  34. package/src/flow/Plumber.ts +101 -36
  35. package/src/flow/StickyNote.ts +76 -4
  36. package/src/flow/actions/send_msg.ts +11 -8
  37. package/src/flow/nodes/split_by_subflow.ts +3 -1
  38. package/src/flow/utils.ts +1 -3
  39. package/src/list/SortableList.ts +117 -47
  40. package/src/simulator/Simulator.ts +5 -1
@@ -388,9 +388,7 @@ export class NodeEditor extends RapidElement {
388
388
 
389
389
  .accordion-toggle-icon {
390
390
  color: #999;
391
- transition:
392
- transform 0.2s ease,
393
- opacity 0.3s ease;
391
+ transition: transform 0.2s ease, opacity 0.3s ease;
394
392
  }
395
393
 
396
394
  .accordion-toggle-icon.expanded {
@@ -2194,18 +2192,20 @@ export class NodeEditor extends RapidElement {
2194
2192
  class="accordion-checkmark-icon"
2195
2193
  ></temba-icon>`
2196
2194
  : showBubble
2197
- ? html`<div
2198
- class="accordion-count-bubble ${!showBubble
2199
- ? 'hidden'
2200
- : ''}"
2201
- >
2202
- ${valueCount}
2203
- </div>`
2204
- : ''}
2195
+ ? html`<div
2196
+ class="accordion-count-bubble ${!showBubble
2197
+ ? 'hidden'
2198
+ : ''}"
2199
+ >
2200
+ ${valueCount}
2201
+ </div>`
2202
+ : ''}
2205
2203
  </div>`}
2206
2204
  </div>
2207
2205
  <div
2208
- class="accordion-content ${isCollapsed ? 'collapsed' : 'expanded'}"
2206
+ class="accordion-content ${isCollapsed
2207
+ ? 'collapsed'
2208
+ : 'expanded'}"
2209
2209
  >
2210
2210
  ${section.items.map((item) =>
2211
2211
  this.renderLayoutItem(item, config, renderedFields)
@@ -2,6 +2,21 @@ import { isRightClick } from './utils';
2
2
 
3
3
  export type TargetFace = 'top' | 'left' | 'right';
4
4
 
5
+ /** Extract clientX/clientY from a MouseEvent or the first touch of a TouchEvent. */
6
+ function getClientCoords(e: MouseEvent | TouchEvent): {
7
+ clientX: number;
8
+ clientY: number;
9
+ } {
10
+ if ('touches' in e) {
11
+ const touch = e.touches[0] || (e as TouchEvent).changedTouches[0];
12
+ return { clientX: touch.clientX, clientY: touch.clientY };
13
+ }
14
+ return {
15
+ clientX: (e as MouseEvent).clientX,
16
+ clientY: (e as MouseEvent).clientY
17
+ };
18
+ }
19
+
5
20
  // Shared arrow/drag constants used by both Plumber and Editor
6
21
  export const ARROW_LENGTH = 13;
7
22
  export const ARROW_HALF_WIDTH = 6.5;
@@ -33,8 +48,8 @@ interface DragState {
33
48
  svgEl: SVGSVGElement;
34
49
  pathEl: SVGPathElement;
35
50
  arrowEl: SVGPolygonElement;
36
- onMove: (e: MouseEvent) => void;
37
- onUp: (e: MouseEvent) => void;
51
+ onMove: (e: MouseEvent | TouchEvent) => void;
52
+ onUp: (e: MouseEvent | TouchEvent) => void;
38
53
  }
39
54
 
40
55
  /**
@@ -242,56 +257,75 @@ export class Plumber {
242
257
  let pendingDrag: {
243
258
  startX: number;
244
259
  startY: number;
245
- onMove: (e: MouseEvent) => void;
246
- onUp: (e: MouseEvent) => void;
260
+ onMove: (e: MouseEvent | TouchEvent) => void;
261
+ onUp: (e: MouseEvent | TouchEvent) => void;
262
+ isTouch: boolean;
247
263
  } | null = null;
248
264
 
249
265
  const DRAG_THRESHOLD = 5;
250
266
 
251
- const onMouseDown = (e: MouseEvent) => {
252
- if (isRightClick(e)) return;
267
+ const beginPendingDrag = (e: MouseEvent | TouchEvent) => {
268
+ if ('button' in e && isRightClick(e)) return;
253
269
 
254
270
  // Don't start drag from exit if it already has a connection —
255
271
  // existing connections are picked up from the arrowhead instead
256
272
  if (this.connections.has(exitId)) return;
257
273
 
258
- const startX = e.clientX;
259
- const startY = e.clientY;
274
+ const isTouch = 'touches' in e;
275
+ if (isTouch) e.preventDefault();
276
+
277
+ const { clientX: startX, clientY: startY } = getClientCoords(e);
260
278
 
261
279
  const nodeEl = element.closest('temba-flow-node');
262
280
  const scope = nodeEl?.getAttribute('uuid') || '';
263
281
  const originalTargetId: string | null = null;
264
282
 
265
- const onMove = (me: MouseEvent) => {
266
- const dx = me.clientX - startX;
267
- const dy = me.clientY - startY;
283
+ const onMove = (me: MouseEvent | TouchEvent) => {
284
+ const { clientX, clientY } = getClientCoords(me);
285
+ const dx = clientX - startX;
286
+ const dy = clientY - startY;
268
287
  if (Math.sqrt(dx * dx + dy * dy) > DRAG_THRESHOLD) {
269
288
  // Exceeded threshold — start actual drag
270
- document.removeEventListener('mousemove', onMove);
271
- document.removeEventListener('mouseup', onUp);
272
- pendingDrag = null;
289
+ removePendingListeners();
273
290
  this.startDrag(exitId, scope, originalTargetId, me);
274
291
  }
275
292
  };
276
293
 
277
294
  const onUp = () => {
278
- // Mouse released without dragging — let click handler fire
295
+ // Released without dragging — let click handler fire
296
+ removePendingListeners();
297
+ };
298
+
299
+ const removePendingListeners = () => {
279
300
  document.removeEventListener('mousemove', onMove);
280
301
  document.removeEventListener('mouseup', onUp);
302
+ document.removeEventListener('touchmove', onMove);
303
+ document.removeEventListener('touchend', onUp);
304
+ document.removeEventListener('touchcancel', onUp);
281
305
  pendingDrag = null;
282
306
  };
283
307
 
284
308
  document.addEventListener('mousemove', onMove);
285
309
  document.addEventListener('mouseup', onUp);
286
- pendingDrag = { startX, startY, onMove, onUp };
310
+ document.addEventListener('touchmove', onMove, { passive: false });
311
+ document.addEventListener('touchend', onUp);
312
+ document.addEventListener('touchcancel', onUp);
313
+ pendingDrag = { startX, startY, onMove, onUp, isTouch };
287
314
  };
288
315
 
289
- element.addEventListener('mousedown', onMouseDown);
316
+ element.addEventListener('mousedown', beginPendingDrag);
317
+ element.addEventListener('touchstart', beginPendingDrag, {
318
+ passive: false
319
+ });
290
320
  this.sources.set(exitId, () => {
291
- element.removeEventListener('mousedown', onMouseDown);
321
+ element.removeEventListener('mousedown', beginPendingDrag);
322
+ element.removeEventListener('touchstart', beginPendingDrag);
292
323
  if (pendingDrag) {
293
324
  document.removeEventListener('mousemove', pendingDrag.onMove);
294
325
  document.removeEventListener('mouseup', pendingDrag.onUp);
326
+ document.removeEventListener('touchmove', pendingDrag.onMove);
327
+ document.removeEventListener('touchend', pendingDrag.onUp);
328
+ document.removeEventListener('touchcancel', pendingDrag.onUp);
295
329
  pendingDrag = null;
296
330
  }
297
331
  });
@@ -714,19 +748,23 @@ export class Plumber {
714
748
 
715
749
  // Make arrowhead draggable for picking up existing connections
716
750
  const DRAG_THRESHOLD = 5;
717
- const onArrowMouseDown = (e: MouseEvent) => {
718
- if (isRightClick(e)) return;
751
+ const onArrowDown = (e: MouseEvent | TouchEvent) => {
752
+ if ('button' in e && isRightClick(e)) return;
719
753
  e.stopPropagation();
754
+ if ('touches' in e) e.preventDefault();
720
755
 
721
- const startX = e.clientX;
722
- const startY = e.clientY;
756
+ const { clientX: startX, clientY: startY } = getClientCoords(e);
723
757
 
724
- const onMove = (me: MouseEvent) => {
725
- const dx = me.clientX - startX;
726
- const dy = me.clientY - startY;
758
+ const onMove = (me: MouseEvent | TouchEvent) => {
759
+ const { clientX, clientY } = getClientCoords(me);
760
+ const dx = clientX - startX;
761
+ const dy = clientY - startY;
727
762
  if (Math.sqrt(dx * dx + dy * dy) > DRAG_THRESHOLD) {
728
763
  document.removeEventListener('mousemove', onMove);
729
764
  document.removeEventListener('mouseup', onUp);
765
+ document.removeEventListener('touchmove', onMove);
766
+ document.removeEventListener('touchend', onUp);
767
+ document.removeEventListener('touchcancel', onUp);
730
768
  this.startDrag(exitId, scope, toId, me);
731
769
  }
732
770
  };
@@ -734,12 +772,21 @@ export class Plumber {
734
772
  const onUp = () => {
735
773
  document.removeEventListener('mousemove', onMove);
736
774
  document.removeEventListener('mouseup', onUp);
775
+ document.removeEventListener('touchmove', onMove);
776
+ document.removeEventListener('touchend', onUp);
777
+ document.removeEventListener('touchcancel', onUp);
737
778
  };
738
779
 
739
780
  document.addEventListener('mousemove', onMove);
740
781
  document.addEventListener('mouseup', onUp);
782
+ document.addEventListener('touchmove', onMove, { passive: false });
783
+ document.addEventListener('touchend', onUp);
784
+ document.addEventListener('touchcancel', onUp);
741
785
  };
742
- arrowEl.addEventListener('mousedown', onArrowMouseDown);
786
+ arrowEl.addEventListener('mousedown', onArrowDown);
787
+ arrowEl.addEventListener('touchstart', onArrowDown, { passive: false });
788
+ pathEl.addEventListener('mousedown', onArrowDown);
789
+ pathEl.addEventListener('touchstart', onArrowDown, { passive: false });
743
790
 
744
791
  // Mark the exit element as connected
745
792
  const exitEl = document.getElementById(exitId);
@@ -1202,10 +1249,18 @@ export class Plumber {
1202
1249
  exitId: string,
1203
1250
  scope: string,
1204
1251
  originalTargetId: string | null,
1205
- e: MouseEvent
1252
+ e: MouseEvent | TouchEvent
1206
1253
  ) {
1207
- // Remove existing connection SVG for this exit (the connection is being dragged away)
1208
- this.removeConnectionSVG(exitId);
1254
+ // Hide (don't remove) the existing connection SVG while dragging.
1255
+ // On iOS Safari, removing the element that received the original
1256
+ // touchstart can trigger touchcancel, prematurely ending the drag.
1257
+ // We defer removal until the drag ends.
1258
+ const oldConn = this.connections.get(exitId);
1259
+ if (oldConn) {
1260
+ oldConn.svgEl.style.display = 'none';
1261
+ const overlay = this.overlays.get(exitId);
1262
+ if (overlay) overlay.style.display = 'none';
1263
+ }
1209
1264
 
1210
1265
  const { svgEl, pathEl, arrowEl } = this.createSVGElement();
1211
1266
  svgEl.classList.add('dragging');
@@ -1283,26 +1338,33 @@ export class Plumber {
1283
1338
  };
1284
1339
 
1285
1340
  // Initial path to cursor (convert viewport to canvas coordinates)
1286
- const cursorX = this.toCanvas(e.clientX - canvasRect.left);
1287
- const cursorY = this.toCanvas(e.clientY - canvasRect.top);
1341
+ const { clientX: initX, clientY: initY } = getClientCoords(e);
1342
+ const cursorX = this.toCanvas(initX - canvasRect.left);
1343
+ const cursorY = this.toCanvas(initY - canvasRect.top);
1288
1344
  updateDragPath(cursorX, cursorY);
1289
1345
 
1290
1346
  this.connectionDragging = true;
1291
1347
 
1292
- const onMove = (me: MouseEvent) => {
1348
+ const onMove = (me: MouseEvent | TouchEvent) => {
1349
+ if ('touches' in me) me.preventDefault();
1293
1350
  // Re-read canvasRect each move since scroll may have changed
1294
1351
  const rect = this.canvas.getBoundingClientRect();
1295
- const cx = this.toCanvas(me.clientX - rect.left);
1296
- const cy = this.toCanvas(me.clientY - rect.top);
1352
+ const { clientX, clientY } = getClientCoords(me);
1353
+ const cx = this.toCanvas(clientX - rect.left);
1354
+ const cy = this.toCanvas(clientY - rect.top);
1297
1355
  updateDragPath(cx, cy);
1298
1356
  };
1299
1357
 
1300
- const onUp = (_me: MouseEvent) => {
1358
+ const onUp = (_me: MouseEvent | TouchEvent) => {
1301
1359
  document.removeEventListener('mousemove', onMove);
1302
1360
  document.removeEventListener('mouseup', onUp);
1361
+ document.removeEventListener('touchmove', onMove);
1362
+ document.removeEventListener('touchend', onUp);
1363
+ document.removeEventListener('touchcancel', onUp);
1303
1364
 
1304
- // Remove the drag SVG
1365
+ // Remove the drag SVG and the hidden old connection SVG
1305
1366
  svgEl.remove();
1367
+ this.removeConnectionSVG(exitId);
1306
1368
  this.connectionDragging = false;
1307
1369
  this.dragState = null;
1308
1370
 
@@ -1317,6 +1379,9 @@ export class Plumber {
1317
1379
 
1318
1380
  document.addEventListener('mousemove', onMove);
1319
1381
  document.addEventListener('mouseup', onUp);
1382
+ document.addEventListener('touchmove', onMove, { passive: false });
1383
+ document.addEventListener('touchend', onUp);
1384
+ document.addEventListener('touchcancel', onUp);
1320
1385
 
1321
1386
  this.dragState = {
1322
1387
  sourceId: exitId,
@@ -21,6 +21,11 @@ export class StickyNote extends RapidElement {
21
21
  @property({ type: Boolean })
22
22
  private colorPickerExpanded = false;
23
23
 
24
+ // On touch devices, contenteditable starts false to prevent Apple Pencil
25
+ // Scribble from hijacking touches. It is set to true on explicit tap.
26
+ private isTouchDevice = navigator.maxTouchPoints > 0;
27
+ private editingField: HTMLElement | null = null;
28
+
24
29
  @fromStore(zustand, (state: AppState) => state.isTranslating)
25
30
  private isTranslating!: boolean;
26
31
 
@@ -289,6 +294,7 @@ export class StickyNote extends RapidElement {
289
294
  }
290
295
 
291
296
  private handleTitleBlur(event: FocusEvent): void {
297
+ this.handleContentBlurForTouch(event);
292
298
  const target = event.target as HTMLElement;
293
299
  const newTitle = target.textContent || '';
294
300
 
@@ -304,6 +310,7 @@ export class StickyNote extends RapidElement {
304
310
  }
305
311
 
306
312
  private handleBodyBlur(event: FocusEvent): void {
313
+ this.handleContentBlurForTouch(event);
307
314
  const target = event.target as HTMLElement;
308
315
  const newBody = target.innerText || '';
309
316
 
@@ -318,6 +325,46 @@ export class StickyNote extends RapidElement {
318
325
  this.requestUpdate();
319
326
  }
320
327
 
328
+ /* c8 ignore start -- touch-only handlers untestable in headless Chromium */
329
+ private handleDragHandleTouchStart(event: TouchEvent): void {
330
+ // Prevent Apple Pencil Scribble from activating on the adjacent
331
+ // contenteditable fields when touching/dragging the handle.
332
+ event.preventDefault();
333
+ }
334
+
335
+ /**
336
+ * On touch devices, contenteditable is off by default. A tap on the
337
+ * title or body enables it and focuses the element for editing.
338
+ */
339
+ private handleContentTap(event: TouchEvent): void {
340
+ if (!this.isTouchDevice) return;
341
+ const target = event.target as HTMLElement;
342
+ if (
343
+ !target.classList.contains('sticky-title') &&
344
+ !target.classList.contains('sticky-body')
345
+ )
346
+ return;
347
+
348
+ // Enable editing and focus
349
+ target.setAttribute('contenteditable', 'true');
350
+ this.editingField = target;
351
+ target.focus();
352
+ event.stopPropagation();
353
+ }
354
+
355
+ /**
356
+ * When a contenteditable field loses focus on a touch device,
357
+ * disable contenteditable again to prevent Scribble.
358
+ */
359
+ private handleContentBlurForTouch(event: FocusEvent): void {
360
+ const target = event.target as HTMLElement;
361
+ if (this.isTouchDevice && this.editingField === target) {
362
+ target.setAttribute('contenteditable', 'false');
363
+ this.editingField = null;
364
+ }
365
+ }
366
+ /* c8 ignore stop */
367
+
321
368
  private handleContentMouseDown(event: MouseEvent): void {
322
369
  // If this sticky note is selected, don't stop propagation
323
370
  // so that group dragging can work
@@ -356,11 +403,19 @@ export class StickyNote extends RapidElement {
356
403
  this.colorPickerExpanded = false;
357
404
  }
358
405
 
406
+ /* c8 ignore next 5 -- touch-only */
407
+ private handleColorPickerTap(event: TouchEvent): void {
408
+ event.stopPropagation();
409
+ event.preventDefault();
410
+ this.colorPickerExpanded = !this.colorPickerExpanded;
411
+ }
412
+
359
413
  private handleColorOptionClick(
360
- event: MouseEvent,
414
+ event: MouseEvent | TouchEvent,
361
415
  color: 'yellow' | 'blue' | 'pink' | 'green' | 'gray'
362
416
  ): void {
363
417
  event.stopPropagation();
418
+ event.preventDefault();
364
419
 
365
420
  if (this.data && color !== this.data.color) {
366
421
  getStore()
@@ -391,23 +446,29 @@ export class StickyNote extends RapidElement {
391
446
  data-uuid="${this.uuid}"
392
447
  >
393
448
  <div class="sticky-title-container">
394
- <temba-icon name="drag" class="drag-handle"></temba-icon>
449
+ <temba-icon
450
+ name="drag"
451
+ class="drag-handle"
452
+ @touchstart=${this.handleDragHandleTouchStart}
453
+ ></temba-icon>
395
454
  <div
396
455
  class="sticky-title"
397
- contenteditable="${!this.isTranslating}"
456
+ contenteditable="${!this.isTranslating && !this.isTouchDevice}"
398
457
  @blur="${this.handleTitleBlur}"
399
458
  @keydown="${this.handleTitleKeyDown}"
400
459
  @mousedown="${this.handleContentMouseDown}"
460
+ @touchend="${this.handleContentTap}"
401
461
  .textContent="${this.data.title}"
402
462
  ></div>
403
463
  </div>
404
464
  <div class="sticky-body-container">
405
465
  <div
406
466
  class="sticky-body"
407
- contenteditable="${!this.isTranslating}"
467
+ contenteditable="${!this.isTranslating && !this.isTouchDevice}"
408
468
  @blur="${this.handleBodyBlur}"
409
469
  @keydown="${this.handleBodyKeyDown}"
410
470
  @mousedown="${this.handleContentMouseDown}"
471
+ @touchend="${this.handleContentTap}"
411
472
  .textContent="${this.data.body}"
412
473
  ></div>
413
474
  ${!this.isTranslating
@@ -419,6 +480,7 @@ export class StickyNote extends RapidElement {
419
480
  class="color-picker"
420
481
  @mouseenter="${this.handleColorPickerMouseEnter}"
421
482
  @mouseleave="${this.handleColorPickerMouseLeave}"
483
+ @touchend="${this.handleColorPickerTap}"
422
484
  >
423
485
  <div
424
486
  class="color-options ${this.colorPickerExpanded
@@ -429,26 +491,36 @@ export class StickyNote extends RapidElement {
429
491
  class="color-option yellow"
430
492
  @click="${(e: MouseEvent) =>
431
493
  this.handleColorOptionClick(e, 'yellow')}"
494
+ @touchend="${(e: TouchEvent) =>
495
+ this.handleColorOptionClick(e, 'yellow')}"
432
496
  ></div>
433
497
  <div
434
498
  class="color-option blue"
435
499
  @click="${(e: MouseEvent) =>
436
500
  this.handleColorOptionClick(e, 'blue')}"
501
+ @touchend="${(e: TouchEvent) =>
502
+ this.handleColorOptionClick(e, 'blue')}"
437
503
  ></div>
438
504
  <div
439
505
  class="color-option pink"
440
506
  @click="${(e: MouseEvent) =>
441
507
  this.handleColorOptionClick(e, 'pink')}"
508
+ @touchend="${(e: TouchEvent) =>
509
+ this.handleColorOptionClick(e, 'pink')}"
442
510
  ></div>
443
511
  <div
444
512
  class="color-option green"
445
513
  @click="${(e: MouseEvent) =>
446
514
  this.handleColorOptionClick(e, 'green')}"
515
+ @touchend="${(e: TouchEvent) =>
516
+ this.handleColorOptionClick(e, 'green')}"
447
517
  ></div>
448
518
  <div
449
519
  class="color-option gray"
450
520
  @click="${(e: MouseEvent) =>
451
521
  this.handleColorOptionClick(e, 'gray')}"
522
+ @touchend="${(e: TouchEvent) =>
523
+ this.handleColorOptionClick(e, 'gray')}"
452
524
  ></div>
453
525
  </div>
454
526
  </div>
@@ -19,6 +19,17 @@ export const send_msg: ActionConfig = {
19
19
  render: (_node: Node, action: SendMsg) => {
20
20
  const text = action.text.replace(/\n/g, '<br>');
21
21
  return html`
22
+ ${action.template
23
+ ? html`<div
24
+ style="border: 1px solid #7dc8bc;padding: 0.5em;margin-bottom: 0.5em;border-radius: 4px; display:flex;align-items: flex-start;background: #f0faf7;color: #128C7E;font-size: 0.85em;"
25
+ >
26
+ <temba-icon
27
+ name="channel_wac"
28
+ style="--icon-size: 14px;"
29
+ ></temba-icon>
30
+ <div style="margin-left:0.4em">${action.template.name}</div>
31
+ </div>`
32
+ : null}
22
33
  ${renderClamped(html`${unsafeHTML(text)}`, action.text)}
23
34
  ${(action.quick_replies || [])?.length > 0
24
35
  ? html`<div class="quick-replies">
@@ -27,14 +38,6 @@ export const send_msg: ActionConfig = {
27
38
  })}
28
39
  </div>`
29
40
  : null}
30
- ${action.template
31
- ? html`<div
32
- style="border: 1px solid var(--color-widget-border);padding: 0.5em;margin-top: 1em;border-radius: var(--curvature); display:flex;background: rgba(0,0,0,.03);"
33
- >
34
- <temba-icon name="channel_wac"></temba-icon>
35
- <div style="margin-left:0.5em">${action.template.name}</div>
36
- </div>`
37
- : null}
38
41
  `;
39
42
  },
40
43
  form: {
@@ -33,7 +33,9 @@ export const split_by_subflow: NodeConfig = {
33
33
  ) as any;
34
34
  return html`
35
35
  <div class="body">
36
- ${enterFlowAction?.flow ? renderFlowLinks([enterFlowAction.flow], 'flow') : null}
36
+ ${enterFlowAction?.flow
37
+ ? renderFlowLinks([enterFlowAction.flow], 'flow')
38
+ : null}
37
39
  </div>
38
40
  `;
39
41
  },
package/src/flow/utils.ts CHANGED
@@ -162,9 +162,7 @@ export const renderFlowLinks = (flows: NamedObject[], icon?: string) => {
162
162
  itemElements.push(html`<div
163
163
  style="display:flex;items-align:center;margin-top:0.2em;"
164
164
  >
165
- ${icon
166
- ? html`<div style="margin-right:0.4em; width: 1em;"></div>`
167
- : null}
165
+ ${icon ? html`<div style="margin-right:0.4em; width: 1em;"></div>` : null}
168
166
  <div style="font-size:0.8em">+${remainingCount} more</div>
169
167
  </div>`);
170
168
  }