@nyaruka/temba-components 0.131.3 → 0.133.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/demo/components/flow/example.html +1 -0
  3. package/demo/static/css/tailwind.css +30019 -0
  4. package/dist/temba-components.js +449 -417
  5. package/dist/temba-components.js.map +1 -1
  6. package/out-tsc/src/display/Chat.js +26 -6
  7. package/out-tsc/src/display/Chat.js.map +1 -1
  8. package/out-tsc/src/display/FloatingTab.js +4 -4
  9. package/out-tsc/src/display/FloatingTab.js.map +1 -1
  10. package/out-tsc/src/events.js.map +1 -1
  11. package/out-tsc/src/flow/CanvasNode.js +124 -58
  12. package/out-tsc/src/flow/CanvasNode.js.map +1 -1
  13. package/out-tsc/src/flow/Editor.js +89 -40
  14. package/out-tsc/src/flow/Editor.js.map +1 -1
  15. package/out-tsc/src/flow/NodeTypeSelector.js +8 -2
  16. package/out-tsc/src/flow/NodeTypeSelector.js.map +1 -1
  17. package/out-tsc/src/flow/config.js +17 -4
  18. package/out-tsc/src/flow/config.js.map +1 -1
  19. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +2 -2
  20. package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
  21. package/out-tsc/src/flow/nodes/split_by_run_result.js +6 -0
  22. package/out-tsc/src/flow/nodes/split_by_run_result.js.map +1 -1
  23. package/out-tsc/src/flow/types.js.map +1 -1
  24. package/out-tsc/src/layout/FloatingWindow.js +1 -2
  25. package/out-tsc/src/layout/FloatingWindow.js.map +1 -1
  26. package/out-tsc/src/list/ContentMenu.js +1 -0
  27. package/out-tsc/src/list/ContentMenu.js.map +1 -1
  28. package/out-tsc/src/list/SortableList.js +3 -2
  29. package/out-tsc/src/list/SortableList.js.map +1 -1
  30. package/out-tsc/src/live/ContactChat.js +105 -69
  31. package/out-tsc/src/live/ContactChat.js.map +1 -1
  32. package/out-tsc/src/store/AppState.js +39 -1
  33. package/out-tsc/src/store/AppState.js.map +1 -1
  34. package/out-tsc/src/utils.js +3 -3
  35. package/out-tsc/src/utils.js.map +1 -1
  36. package/out-tsc/test/ActionHelper.js +6 -5
  37. package/out-tsc/test/ActionHelper.js.map +1 -1
  38. package/out-tsc/test/actions/send_broadcast.test.js +1 -1
  39. package/out-tsc/test/actions/send_broadcast.test.js.map +1 -1
  40. package/out-tsc/test/nodes/split_by_run_result.test.js +83 -0
  41. package/out-tsc/test/nodes/split_by_run_result.test.js.map +1 -1
  42. package/out-tsc/test/temba-backwards-compatibility.test.js +30 -0
  43. package/out-tsc/test/temba-backwards-compatibility.test.js.map +1 -0
  44. package/out-tsc/test/temba-contact-chat.test.js +28 -13
  45. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  46. package/out-tsc/test/temba-floating-window.test.js +0 -2
  47. package/out-tsc/test/temba-floating-window.test.js.map +1 -1
  48. package/out-tsc/test/temba-flow-editor-node.test.js +109 -0
  49. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  50. package/out-tsc/test/temba-localization.test.js +24 -5
  51. package/out-tsc/test/temba-localization.test.js.map +1 -1
  52. package/out-tsc/test/temba-node-type-selector.test.js +70 -3
  53. package/out-tsc/test/temba-node-type-selector.test.js.map +1 -1
  54. package/out-tsc/test/temba-utils-uuid.test.js +45 -1
  55. package/out-tsc/test/temba-utils-uuid.test.js.map +1 -1
  56. package/out-tsc/test/utils.test.js +3 -3
  57. package/out-tsc/test/utils.test.js.map +1 -1
  58. package/package.json +1 -1
  59. package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
  60. package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
  61. package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
  62. package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
  63. package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
  64. package/screenshots/truth/actions/add_contact_urn/render/expression-facebook.png +0 -0
  65. package/screenshots/truth/actions/add_contact_urn/render/expression-phone.png +0 -0
  66. package/screenshots/truth/actions/add_contact_urn/render/facebook-id.png +0 -0
  67. package/screenshots/truth/actions/add_contact_urn/render/instagram-handle.png +0 -0
  68. package/screenshots/truth/actions/add_contact_urn/render/line-id.png +0 -0
  69. package/screenshots/truth/actions/add_contact_urn/render/phone-number.png +0 -0
  70. package/screenshots/truth/actions/add_contact_urn/render/telegram-id.png +0 -0
  71. package/screenshots/truth/actions/add_contact_urn/render/viber-id.png +0 -0
  72. package/screenshots/truth/actions/add_contact_urn/render/wechat-id.png +0 -0
  73. package/screenshots/truth/actions/add_contact_urn/render/whatsapp.png +0 -0
  74. package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
  75. package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
  76. package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
  77. package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
  78. package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
  79. package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
  80. package/screenshots/truth/actions/send_broadcast/render/contacts-only.png +0 -0
  81. package/screenshots/truth/actions/send_broadcast/render/groups-and-contacts.png +0 -0
  82. package/screenshots/truth/actions/send_broadcast/render/groups-only.png +0 -0
  83. package/screenshots/truth/actions/send_broadcast/render/many-groups.png +0 -0
  84. package/screenshots/truth/actions/send_broadcast/render/multiline-text.png +0 -0
  85. package/screenshots/truth/actions/send_broadcast/render/with-attachments.png +0 -0
  86. package/screenshots/truth/actions/send_email/render/complex-business-email.png +0 -0
  87. package/screenshots/truth/actions/send_email/render/empty-body.png +0 -0
  88. package/screenshots/truth/actions/send_email/render/empty-subject.png +0 -0
  89. package/screenshots/truth/actions/send_email/render/long-subject.png +0 -0
  90. package/screenshots/truth/actions/send_email/render/multiline-body.png +0 -0
  91. package/screenshots/truth/actions/send_email/render/multiple-recipients.png +0 -0
  92. package/screenshots/truth/actions/send_email/render/simple-email.png +0 -0
  93. package/screenshots/truth/actions/send_email/render/with-expressions.png +0 -0
  94. package/screenshots/truth/actions/send_msg/render/long-quick-replies.png +0 -0
  95. package/screenshots/truth/actions/send_msg/render/multiline-text-with-replies.png +0 -0
  96. package/screenshots/truth/actions/send_msg/render/simple-text.png +0 -0
  97. package/screenshots/truth/actions/send_msg/render/text-with-linebreaks.png +0 -0
  98. package/screenshots/truth/actions/send_msg/render/text-with-many-quick-replies.png +0 -0
  99. package/screenshots/truth/actions/send_msg/render/text-with-quick-replies.png +0 -0
  100. package/screenshots/truth/actions/send_msg/render/text-without-quick-replies.png +0 -0
  101. package/screenshots/truth/actions/start_session/render/contact-query.png +0 -0
  102. package/screenshots/truth/actions/start_session/render/contacts-only.png +0 -0
  103. package/screenshots/truth/actions/start_session/render/create-contact.png +0 -0
  104. package/screenshots/truth/actions/start_session/render/groups-and-contacts.png +0 -0
  105. package/screenshots/truth/actions/start_session/render/groups-only.png +0 -0
  106. package/screenshots/truth/actions/start_session/render/many-recipients.png +0 -0
  107. package/screenshots/truth/contacts/chat-failure.png +0 -0
  108. package/screenshots/truth/contacts/chat-for-archived-contact.png +0 -0
  109. package/screenshots/truth/contacts/chat-for-blocked-contact.png +0 -0
  110. package/screenshots/truth/contacts/chat-for-stopped-contact.png +0 -0
  111. package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
  112. package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
  113. package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
  114. package/screenshots/truth/floating-tab/default.png +0 -0
  115. package/screenshots/truth/floating-tab/gray.png +0 -0
  116. package/screenshots/truth/floating-tab/green.png +0 -0
  117. package/screenshots/truth/floating-tab/hover.png +0 -0
  118. package/screenshots/truth/floating-tab/purple.png +0 -0
  119. package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
  120. package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
  121. package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
  122. package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
  123. package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
  124. package/screenshots/truth/nodes/split_by_llm_categorize/render/basic-categorization.png +0 -0
  125. package/screenshots/truth/nodes/split_by_llm_categorize/render/custom-input-and-result-name.png +0 -0
  126. package/screenshots/truth/nodes/split_by_llm_categorize/render/feedback-categorization.png +0 -0
  127. package/screenshots/truth/nodes/split_by_llm_categorize/render/many-categories.png +0 -0
  128. package/screenshots/truth/nodes/split_by_llm_categorize/render/minimal-categories.png +0 -0
  129. package/screenshots/truth/nodes/split_by_random/render/ab-test-multiple-variants.png +0 -0
  130. package/screenshots/truth/nodes/split_by_random/render/sampling-split.png +0 -0
  131. package/screenshots/truth/nodes/split_by_random/render/three-way-split.png +0 -0
  132. package/screenshots/truth/nodes/split_by_random/render/two-bucket-split.png +0 -0
  133. package/screenshots/truth/nodes/wait_for_digits/render/basic-digits-wait.png +0 -0
  134. package/screenshots/truth/nodes/wait_for_digits/render/phone-number-collection.png +0 -0
  135. package/screenshots/truth/nodes/wait_for_digits/render/single-digit-with-timeout.png +0 -0
  136. package/screenshots/truth/nodes/wait_for_digits/render/verification-code.png +0 -0
  137. package/screenshots/truth/nodes/wait_for_response/render/basic-wait.png +0 -0
  138. package/screenshots/truth/nodes/wait_for_response/render/custom-result-name.png +0 -0
  139. package/screenshots/truth/nodes/wait_for_response/render/no-timeout.png +0 -0
  140. package/screenshots/truth/nodes/wait_for_response/render/short-timeout.png +0 -0
  141. package/src/display/Chat.ts +29 -7
  142. package/src/display/FloatingTab.ts +4 -4
  143. package/src/events.ts +1 -4
  144. package/src/flow/CanvasNode.ts +130 -57
  145. package/src/flow/Editor.ts +107 -40
  146. package/src/flow/NodeTypeSelector.ts +7 -1
  147. package/src/flow/config.ts +22 -4
  148. package/src/flow/nodes/split_by_llm_categorize.ts +2 -8
  149. package/src/flow/nodes/split_by_run_result.ts +7 -0
  150. package/src/flow/types.ts +2 -0
  151. package/src/layout/FloatingWindow.ts +1 -3
  152. package/src/list/ContentMenu.ts +1 -0
  153. package/src/list/SortableList.ts +3 -2
  154. package/src/live/ContactChat.ts +112 -78
  155. package/src/store/AppState.ts +53 -1
  156. package/src/utils.ts +3 -3
  157. package/test/ActionHelper.ts +13 -5
  158. package/test/actions/send_broadcast.test.ts +2 -1
  159. package/test/nodes/split_by_run_result.test.ts +99 -0
  160. package/test/temba-backwards-compatibility.test.ts +37 -0
  161. package/test/temba-contact-chat.test.ts +28 -13
  162. package/test/temba-floating-window.test.ts +0 -2
  163. package/test/temba-flow-editor-node.test.ts +129 -0
  164. package/test/temba-localization.test.ts +29 -5
  165. package/test/temba-node-type-selector.test.ts +89 -3
  166. package/test/temba-utils-uuid.test.ts +61 -1
  167. package/test/utils.test.ts +8 -3
  168. package/test-assets/contacts/history.json +22 -9
  169. package/web-test-runner.config.mjs +3 -3
@@ -42,16 +42,32 @@ export class Editor extends RapidElement {
42
42
  return this.isDragging;
43
43
  }
44
44
  getAvailableLanguages() {
45
- var _b, _c;
46
- // Use languages from flow definition if available, otherwise use defaults
47
- if (((_c = (_b = this.definition) === null || _b === void 0 ? void 0 : _b._ui) === null || _c === void 0 ? void 0 : _c.languages) &&
45
+ var _b, _c, _d;
46
+ // Use languages from workspace if available
47
+ if (((_b = this.workspace) === null || _b === void 0 ? void 0 : _b.languages) && this.workspace.languages.length > 0) {
48
+ const languageNames = new Intl.DisplayNames(['en'], { type: 'language' });
49
+ return this.workspace.languages
50
+ .map((code) => {
51
+ try {
52
+ const name = languageNames.of(code);
53
+ return name ? { code, name } : { code, name: code };
54
+ }
55
+ catch (_b) {
56
+ return { code, name: code };
57
+ }
58
+ })
59
+ .filter((lang) => lang.code && lang.name);
60
+ }
61
+ // Fall back to flow definition languages if available
62
+ if (((_d = (_c = this.definition) === null || _c === void 0 ? void 0 : _c._ui) === null || _d === void 0 ? void 0 : _d.languages) &&
48
63
  this.definition._ui.languages.length > 0) {
49
64
  return this.definition._ui.languages.map((lang) => ({
50
65
  code: typeof lang === 'string' ? lang : lang.iso || lang.code,
51
66
  name: typeof lang === 'string' ? lang : lang.name
52
67
  }));
53
68
  }
54
- return this.DEFAULT_LANGUAGES;
69
+ // No languages available
70
+ return [];
55
71
  }
56
72
  static get styles() {
57
73
  return css `
@@ -71,8 +87,6 @@ export class Editor extends RapidElement {
71
87
  );
72
88
  background-size: 20px 20px;
73
89
  background-position: 10px 10px;
74
- box-shadow: inset -5px 0 10px rgba(0, 0, 0, 0.05);
75
- border-top: 1px solid #e0e0e0;
76
90
  width: 100%;
77
91
  display: flex;
78
92
  }
@@ -421,12 +435,6 @@ export class Editor extends RapidElement {
421
435
  // Track previous target node to clear placeholder when moving between nodes
422
436
  this.previousActionDragTargetNodeUuid = null;
423
437
  this.canvasMouseDown = false;
424
- // Default languages if not specified in flow definition
425
- this.DEFAULT_LANGUAGES = [
426
- { code: 'eng', name: 'English' },
427
- { code: 'fra', name: 'French' },
428
- { code: 'esp', name: 'Spanish' }
429
- ];
430
438
  // Bound event handlers to maintain proper 'this' context
431
439
  this.boundMouseMove = this.handleMouseMove.bind(this);
432
440
  this.boundMouseUp = this.handleMouseUp.bind(this);
@@ -543,11 +551,18 @@ export class Editor extends RapidElement {
543
551
  saveChanges() {
544
552
  // post the flow definition to the server
545
553
  getStore()
546
- .postJSON(`/flow/revisions/${this.flow}`, this.definition)
554
+ .postJSON(`/flow/revisions/${this.flow}/`, this.definition)
547
555
  .then((response) => {
548
- // Update flow info with the response data
549
- if (response.json && response.json.info) {
550
- getStore().getState().setFlowInfo(response.json.info);
556
+ var _b;
557
+ // Update flow info and revision with the response data
558
+ if (response.json) {
559
+ const state = getStore().getState();
560
+ if (response.json.info) {
561
+ state.setFlowInfo(response.json.info);
562
+ }
563
+ if (((_b = response.json.revision) === null || _b === void 0 ? void 0 : _b.revision) !== undefined) {
564
+ state.setRevision(response.json.revision.revision);
565
+ }
551
566
  }
552
567
  })
553
568
  .catch((error) => {
@@ -594,6 +609,8 @@ export class Editor extends RapidElement {
594
609
  this.addEventListener(CustomEventType.AddActionRequested, this.handleAddActionRequested.bind(this));
595
610
  // Listen for node edit requests from flow nodes
596
611
  this.addEventListener(CustomEventType.NodeEditRequested, this.handleNodeEditRequested.bind(this));
612
+ // Listen for node deletion events
613
+ this.addEventListener(CustomEventType.NodeDeleted, this.handleNodeDeleted.bind(this));
597
614
  // Listen for canvas menu selections
598
615
  this.addEventListener(CustomEventType.Selection, (event) => {
599
616
  const target = event.target;
@@ -1245,6 +1262,12 @@ export class Editor extends RapidElement {
1245
1262
  this.editingNode = event.detail.node;
1246
1263
  this.editingNodeUI = event.detail.nodeUI;
1247
1264
  }
1265
+ handleNodeDeleted(event) {
1266
+ const nodeUuid = event.detail.uuid;
1267
+ if (nodeUuid) {
1268
+ this.deleteNodes([nodeUuid]);
1269
+ }
1270
+ }
1248
1271
  handleActionSaved(updatedAction) {
1249
1272
  var _b, _c;
1250
1273
  if (this.editingNode && this.editingAction) {
@@ -1399,7 +1422,7 @@ export class Editor extends RapidElement {
1399
1422
  return { left, top };
1400
1423
  }
1401
1424
  handleActionDragExternal(event) {
1402
- const { action, nodeUuid, actionIndex, mouseX, mouseY, actionHeight = 60 } = event.detail;
1425
+ const { action, nodeUuid, actionIndex, mouseX, mouseY, actionHeight = 60, isLastAction = false } = event.detail;
1403
1426
  // Check if mouse is over another execute_actions node
1404
1427
  const targetNode = this.getNodeAtPosition(mouseX, mouseY);
1405
1428
  if (targetNode && targetNode !== nodeUuid) {
@@ -1462,23 +1485,38 @@ export class Editor extends RapidElement {
1462
1485
  this.previousActionDragTargetNodeUuid = null;
1463
1486
  }
1464
1487
  this.actionDragTargetNodeUuid = null;
1465
- // Tell source node to hide ghost (we're not over a valid target)
1466
1488
  const sourceElement = this.querySelector(`temba-flow-node[data-node-uuid="${nodeUuid}"]`);
1467
- if (sourceElement) {
1468
- sourceElement.dispatchEvent(new CustomEvent('action-hide-ghost', {
1469
- detail: {},
1470
- bubbles: false
1471
- }));
1489
+ // Show canvas drop preview only if this is NOT the last action
1490
+ // Last actions can only be dropped on other nodes, not on canvas
1491
+ if (!isLastAction) {
1492
+ // Hide ghost when showing canvas preview (for canvas drops)
1493
+ if (sourceElement) {
1494
+ sourceElement.dispatchEvent(new CustomEvent('action-hide-ghost', {
1495
+ detail: {},
1496
+ bubbles: false
1497
+ }));
1498
+ }
1499
+ // Don't snap to grid for preview - let it follow cursor smoothly
1500
+ const position = this.calculateCanvasDropPosition(mouseX, mouseY, false);
1501
+ this.canvasDropPreview = {
1502
+ action,
1503
+ nodeUuid,
1504
+ actionIndex,
1505
+ position,
1506
+ actionHeight
1507
+ };
1508
+ }
1509
+ else {
1510
+ // For last action, keep ghost visible (can't drop on canvas)
1511
+ if (sourceElement) {
1512
+ sourceElement.dispatchEvent(new CustomEvent('action-show-ghost', {
1513
+ detail: {},
1514
+ bubbles: false
1515
+ }));
1516
+ }
1517
+ // Clear any existing preview for last action
1518
+ this.canvasDropPreview = null;
1472
1519
  }
1473
- // Don't snap to grid for preview - let it follow cursor smoothly
1474
- const position = this.calculateCanvasDropPosition(mouseX, mouseY, false);
1475
- this.canvasDropPreview = {
1476
- action,
1477
- nodeUuid,
1478
- actionIndex,
1479
- position,
1480
- actionHeight
1481
- };
1482
1520
  // Force re-render to update preview position
1483
1521
  this.requestUpdate();
1484
1522
  }
@@ -1498,8 +1536,8 @@ export class Editor extends RapidElement {
1498
1536
  this.actionDragTargetNodeUuid = null;
1499
1537
  }
1500
1538
  handleActionDropExternal(event) {
1501
- var _b, _c, _d;
1502
- const { action, nodeUuid, actionIndex, mouseX, mouseY } = event.detail;
1539
+ var _b, _c;
1540
+ const { action, nodeUuid, actionIndex, mouseX, mouseY, isLastAction = false } = event.detail;
1503
1541
  // Check if we're dropping on an existing execute_actions node
1504
1542
  const targetNodeUuid = this.actionDragTargetNodeUuid;
1505
1543
  if (targetNodeUuid && targetNodeUuid !== nodeUuid) {
@@ -1522,6 +1560,13 @@ export class Editor extends RapidElement {
1522
1560
  this.actionDragTargetNodeUuid = null;
1523
1561
  return;
1524
1562
  }
1563
+ // If this is the last action and we're not dropping on another node, do nothing
1564
+ // Last actions can only be moved to other nodes, not dropped on canvas
1565
+ if (isLastAction) {
1566
+ this.canvasDropPreview = null;
1567
+ this.actionDragTargetNodeUuid = null;
1568
+ return;
1569
+ }
1525
1570
  // Not dropping on another node, create a new one on canvas
1526
1571
  // Snap to grid for the final drop position
1527
1572
  const position = this.calculateCanvasDropPosition(mouseX, mouseY, true);
@@ -1532,12 +1577,13 @@ export class Editor extends RapidElement {
1532
1577
  const updatedActions = originalNode.actions.filter((_a, idx) => idx !== actionIndex);
1533
1578
  // if no actions remain, delete the node
1534
1579
  if (updatedActions.length === 0) {
1535
- (_b = getStore()) === null || _b === void 0 ? void 0 : _b.getState().removeNodes([nodeUuid]);
1580
+ // Use deleteNodes to properly clean up Plumber connections before removing
1581
+ this.deleteNodes([nodeUuid]);
1536
1582
  }
1537
1583
  else {
1538
1584
  // update the node
1539
1585
  const updatedNode = { ...originalNode, actions: updatedActions };
1540
- (_c = getStore()) === null || _c === void 0 ? void 0 : _c.getState().updateNode(nodeUuid, updatedNode);
1586
+ (_b = getStore()) === null || _b === void 0 ? void 0 : _b.getState().updateNode(nodeUuid, updatedNode);
1541
1587
  }
1542
1588
  // create a new execute_actions node with the dropped action
1543
1589
  const newNode = {
@@ -1556,7 +1602,7 @@ export class Editor extends RapidElement {
1556
1602
  config: {}
1557
1603
  };
1558
1604
  // add the new node
1559
- (_d = getStore()) === null || _d === void 0 ? void 0 : _d.getState().addNode(newNode, newNodeUI);
1605
+ (_c = getStore()) === null || _c === void 0 ? void 0 : _c.getState().addNode(newNode, newNodeUI);
1560
1606
  // clear the preview
1561
1607
  this.canvasDropPreview = null;
1562
1608
  this.actionDragTargetNodeUuid = null;
@@ -1965,7 +2011,7 @@ export class Editor extends RapidElement {
1965
2011
  header="Translations"
1966
2012
  .width=${360}
1967
2013
  .maxHeight=${600}
1968
- .top=${20}
2014
+ .top=${170}
1969
2015
  color="#6b7280"
1970
2016
  .hidden=${this.localizationWindowHidden}
1971
2017
  @temba-dialog-hidden=${this.handleLocalizationWindowClosed}
@@ -2123,6 +2169,7 @@ export class Editor extends RapidElement {
2123
2169
  icon="language"
2124
2170
  label="Translate Flow"
2125
2171
  color="#6b7280"
2172
+ top="180"
2126
2173
  .hidden=${!this.localizationWindowHidden}
2127
2174
  @temba-button-clicked=${this.handleLocalizationTabClick}
2128
2175
  ></temba-floating-tab>
@@ -2182,8 +2229,7 @@ export class Editor extends RapidElement {
2182
2229
  ? 'selected'
2183
2230
  : ''}"
2184
2231
  @mousedown=${this.handleMouseDown.bind(this)}
2185
- style="left:${position.left}px; top:${position.top}px; z-index: ${1000 +
2186
- position.top}"
2232
+ style="left:${position.left}px; top:${position.top}px;"
2187
2233
  uuid=${uuid}
2188
2234
  .data=${sticky}
2189
2235
  .dragging=${dragging}
@@ -2241,6 +2287,9 @@ __decorate([
2241
2287
  __decorate([
2242
2288
  fromStore(zustand, (state) => state.isTranslating)
2243
2289
  ], Editor.prototype, "isTranslating", void 0);
2290
+ __decorate([
2291
+ fromStore(zustand, (state) => state.workspace)
2292
+ ], Editor.prototype, "workspace", void 0);
2244
2293
  __decorate([
2245
2294
  state()
2246
2295
  ], Editor.prototype, "isDragging", void 0);