@nyaruka/temba-components 0.124.0 → 0.124.2

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 (79) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/TEST_OPTIMIZATION.md +158 -0
  3. package/demo/alert/example.html +65 -0
  4. package/demo/button/example.html +71 -0
  5. package/demo/chart/example.html +56 -0
  6. package/demo/checkbox/example.html +72 -0
  7. package/demo/compose/example.html +72 -0
  8. package/demo/data/images/gus.png +0 -0
  9. package/demo/data/images/purrington.jpg +0 -0
  10. package/demo/data/server/opened-tickets.json +40 -0
  11. package/demo/data/server/response-time.json +27 -0
  12. package/demo/datepicker/example.html +69 -0
  13. package/demo/dialog/example.html +107 -0
  14. package/demo/dropdown/example.html +99 -0
  15. package/demo/index.html +152 -445
  16. package/demo/misc/example.html +72 -0
  17. package/demo/progress/example.html +59 -0
  18. package/demo/{drag-drop-demo.html → select/drag-and-drop.html} +2 -1
  19. package/demo/select/example.html +82 -0
  20. package/demo/select/multi.html +73 -0
  21. package/demo/slider/example.html +59 -0
  22. package/demo/sortable-list/example.html +99 -0
  23. package/demo/styles.css +183 -0
  24. package/demo/tabs/example.html +91 -0
  25. package/demo/textinput/completion.html +56 -0
  26. package/demo/textinput/example.html +61 -0
  27. package/dist/temba-components.js +23 -26
  28. package/dist/temba-components.js.map +1 -1
  29. package/out-tsc/src/chart/TembaChart.js +27 -22
  30. package/out-tsc/src/chart/TembaChart.js.map +1 -1
  31. package/out-tsc/src/flow/Editor.js +1 -1
  32. package/out-tsc/src/flow/Editor.js.map +1 -1
  33. package/out-tsc/src/select/Select.js +1 -1
  34. package/out-tsc/src/select/Select.js.map +1 -1
  35. package/out-tsc/src/thumbnail/Thumbnail.js +1 -1
  36. package/out-tsc/src/thumbnail/Thumbnail.js.map +1 -1
  37. package/out-tsc/test/temba-chart.test.js +1 -1
  38. package/out-tsc/test/temba-chart.test.js.map +1 -1
  39. package/out-tsc/test/temba-compose.test.js +6 -30
  40. package/out-tsc/test/temba-compose.test.js.map +1 -1
  41. package/out-tsc/test/temba-contact-chat.test.js +1 -2
  42. package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
  43. package/out-tsc/test/temba-dropdown.test.js +1 -1
  44. package/out-tsc/test/temba-dropdown.test.js.map +1 -1
  45. package/out-tsc/test/temba-omnibox.test.js +4 -0
  46. package/out-tsc/test/temba-omnibox.test.js.map +1 -1
  47. package/out-tsc/test/temba-select.test.js +49 -0
  48. package/out-tsc/test/temba-select.test.js.map +1 -1
  49. package/out-tsc/test/temba-toast.test.js +1 -2
  50. package/out-tsc/test/temba-toast.test.js.map +1 -1
  51. package/out-tsc/test/temba-utils-index.test.js +2 -2
  52. package/out-tsc/test/temba-utils-index.test.js.map +1 -1
  53. package/out-tsc/test/utils.test.js +31 -3
  54. package/out-tsc/test/utils.test.js.map +1 -1
  55. package/package.json +2 -3
  56. package/screenshots/truth/webchat/connected-state.png +0 -0
  57. package/src/chart/TembaChart.ts +29 -22
  58. package/src/flow/Editor.ts +1 -1
  59. package/src/select/Select.ts +1 -1
  60. package/src/thumbnail/Thumbnail.ts +1 -1
  61. package/test/temba-chart.test.ts +1 -1
  62. package/test/temba-compose.test.ts +11 -38
  63. package/test/temba-contact-chat.test.ts +4 -6
  64. package/test/temba-dropdown.test.ts +1 -1
  65. package/test/temba-omnibox.test.ts +5 -0
  66. package/test/temba-select.test.ts +67 -0
  67. package/test/temba-toast.test.ts +2 -2
  68. package/test/temba-utils-index.test.ts +2 -2
  69. package/test/utils.test.ts +39 -3
  70. package/web-test-runner.config.mjs +4 -2
  71. package/.storybook/main.js +0 -14
  72. package/.storybook/preview-head.html +0 -1
  73. package/.storybook/preview.js +0 -17
  74. package/demo/agents.html +0 -147
  75. package/demo/old.html +0 -573
  76. package/demo/remote.html +0 -3
  77. package/demo/test-drag-drop.html +0 -94
  78. package/screenshots/truth/compose/attachments-with-files-focused.png +0 -0
  79. package/stories/temba-checkbox.stories.md +0 -37
@@ -86,7 +86,6 @@ export class TembaChart extends RapidElement {
86
86
 
87
87
  .config {
88
88
  max-height: 0px;
89
- margin: 2em 0.5em;
90
89
  padding: 0em 1em;
91
90
  border-radius: var(--curvature);
92
91
  border: 1px solid transparent;
@@ -96,10 +95,8 @@ export class TembaChart extends RapidElement {
96
95
  }
97
96
 
98
97
  .config.show {
99
- padding: 1em;
98
+ padding: 2em 1em 1.5em 1em;
100
99
  max-height: 50px;
101
- background: rgba(0, 0, 0, 0.02);
102
- border: 1px solid rgba(0, 0, 0, 0.09);
103
100
  }
104
101
  `;
105
102
  }
@@ -110,12 +107,14 @@ export class TembaChart extends RapidElement {
110
107
  this.other = false;
111
108
  this.datasets = [];
112
109
  this.maxSplits = 2;
110
+ this.hideOther = false;
113
111
  this.splits = [];
114
112
  this.dataname = 'Counts';
115
113
  this.single = false;
116
114
  this.legend = false;
117
115
  this.config = false;
118
116
  this.formatDuration = false;
117
+ this.showAll = false;
119
118
  this.colorIndex = 0;
120
119
  this.showConfig = false;
121
120
  }
@@ -129,6 +128,9 @@ export class TembaChart extends RapidElement {
129
128
  }
130
129
  updated(changes) {
131
130
  super.updated(changes);
131
+ if (changes.has('splitNames')) {
132
+ this.splits = this.splitNames.split(',').map((s) => s.trim());
133
+ }
132
134
  if (changes.has('data') || changes.has('splits')) {
133
135
  this.calculateSplits();
134
136
  }
@@ -137,7 +139,7 @@ export class TembaChart extends RapidElement {
137
139
  }
138
140
  if (changes.has('url')) {
139
141
  const store = getStore();
140
- store.getUrl(this.url).then((response) => {
142
+ store.getUrl(this.url, { skipCache: true }).then((response) => {
141
143
  this.data = response.json.data;
142
144
  });
143
145
  }
@@ -148,7 +150,8 @@ export class TembaChart extends RapidElement {
148
150
  // keep a running list of values that is the sum at each index
149
151
  const sums = [];
150
152
  for (const dataset of this.data.datasets) {
151
- if (this.splits.find((s) => s === dataset.label) === undefined) {
153
+ if (!this.showAll &&
154
+ this.splits.find((s) => s === dataset.label) === undefined) {
152
155
  // update our sums
153
156
  for (let i = 0; i < dataset.data.length; i++) {
154
157
  if (sums[i] === undefined) {
@@ -178,13 +181,15 @@ export class TembaChart extends RapidElement {
178
181
  });
179
182
  }
180
183
  else {
181
- datasets.push({
182
- label: 'Other',
183
- data: sums,
184
- backgroundColor: otherBackgroundColor,
185
- borderColor: otherBorderColor,
186
- borderWidth: 1
187
- });
184
+ if (!this.hideOther && !this.showAll) {
185
+ datasets.push({
186
+ label: 'Other',
187
+ data: sums,
188
+ backgroundColor: otherBackgroundColor,
189
+ borderColor: otherBorderColor,
190
+ borderWidth: 1
191
+ });
192
+ }
188
193
  }
189
194
  this.datasets = datasets;
190
195
  }
@@ -228,15 +233,6 @@ export class TembaChart extends RapidElement {
228
233
  x: { from: 500 },
229
234
  y: { from: 500 }
230
235
  },
231
- animations: {
232
- tension: {
233
- duration: 1000,
234
- easing: 'linear',
235
- from: 1,
236
- to: 0,
237
- loop: true
238
- }
239
- },
240
236
  scales: {
241
237
  y: {
242
238
  min: 0,
@@ -350,6 +346,12 @@ __decorate([
350
346
  __decorate([
351
347
  property({ type: Number })
352
348
  ], TembaChart.prototype, "maxSplits", void 0);
349
+ __decorate([
350
+ property({ type: String, attribute: 'splits' })
351
+ ], TembaChart.prototype, "splitNames", void 0);
352
+ __decorate([
353
+ property({ type: Boolean })
354
+ ], TembaChart.prototype, "hideOther", void 0);
353
355
  __decorate([
354
356
  state()
355
357
  ], TembaChart.prototype, "splits", void 0);
@@ -368,6 +370,9 @@ __decorate([
368
370
  __decorate([
369
371
  property({ type: Boolean })
370
372
  ], TembaChart.prototype, "formatDuration", void 0);
373
+ __decorate([
374
+ property({ type: Boolean })
375
+ ], TembaChart.prototype, "showAll", void 0);
371
376
  __decorate([
372
377
  property({ type: Number })
373
378
  ], TembaChart.prototype, "colorIndex", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"TembaChart.js","sourceRoot":"","sources":["../../../src/chart/TembaChart.ts"],"names":[],"mappings":"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","sourcesContent":["import { RapidElement } from '../RapidElement';\nimport { property, state } from 'lit/decorators.js';\nimport { css, html, PropertyValueMap, TemplateResult } from 'lit';\n\nimport { Select, SelectOption } from '../select/Select';\nimport { getClasses } from '../utils';\nimport { getStore } from '../store/Store';\n\n// eslint-disable-next-line import/no-named-as-default\nimport Chart, { ChartType } from 'chart.js/auto';\nimport 'chartjs-adapter-luxon';\n\nconst colors = [\n 'rgba(54, 162, 235, 0.2)',\n 'rgba(255, 159, 64, 0.2)',\n 'rgba(75, 192, 192, 0.2)',\n 'rgba(153, 102, 255, 0.2)',\n 'rgba(255, 205, 86, 0.2)',\n 'rgba(255, 99, 132, 0.2)'\n];\n\nconst colorsBorder = [\n 'rgb(54, 162, 235)',\n 'rgb(255, 159, 64)',\n 'rgb(75, 192, 192)',\n 'rgb(153, 102, 255)',\n 'rgb(255, 205, 86)',\n 'rgb(255, 99, 132)'\n];\n\nconst otherBackgroundColor = 'rgba(201, 203, 207, 0.2)';\nconst otherBorderColor = 'rgb(201, 203, 207)';\n\n/**\n * Formats a duration in seconds to a human-readable string showing the two largest units.\n * Examples: 68787 -> \"19h 6m\", 958000 -> \"11d 2h\", 3661 -> \"1h 1m\"\n */\nexport function formatDurationFromSeconds(seconds: number): string {\n if (seconds === 0) {\n return '0s';\n }\n\n const totalDays = Math.floor(seconds / 86400);\n const remainingAfterDays = seconds % 86400;\n const remainingHours = Math.floor(remainingAfterDays / 3600);\n const remainingAfterHours = remainingAfterDays % 3600;\n const remainingMinutes = Math.floor(remainingAfterHours / 60);\n const remainingSeconds = remainingAfterHours % 60;\n\n const units = [];\n\n if (totalDays > 0) {\n units.push(`${totalDays}d`);\n }\n if (remainingHours > 0) {\n units.push(`${remainingHours}h`);\n }\n if (remainingMinutes > 0 && units.length < 2) {\n units.push(`${remainingMinutes}m`);\n }\n if (remainingSeconds > 0 && units.length < 2) {\n units.push(`${remainingSeconds}s`);\n }\n\n // Return the first two most significant units\n return units.slice(0, 2).join(' ');\n}\n\nexport interface RapidChartData {\n labels: string[];\n datasets: { label: string; data: number[] }[];\n}\n\nexport class TembaChart extends RapidElement {\n @property({ type: String })\n chartType: ChartType = 'bar';\n\n @property({ type: String })\n url: string;\n\n @property({ type: String })\n header: string = '';\n\n @property({ type: Boolean })\n other: boolean = false;\n\n @property({ type: Object })\n data: RapidChartData;\n\n @state()\n datasets: { label: string; data: number[] }[] = [];\n\n @property({ type: Number })\n maxSplits: number = 2;\n\n @state()\n splits: string[] = [];\n\n @property({ type: String })\n dataname = 'Counts';\n\n @property({ type: Boolean })\n single: boolean = false;\n\n @property({ type: Boolean })\n legend: boolean = false;\n\n @property({ type: Boolean })\n config: boolean = false;\n\n @property({ type: Boolean })\n formatDuration: boolean = false;\n\n @property({ type: Number })\n colorIndex: number = 0;\n\n @state()\n showConfig: boolean = false;\n\n chart: Chart;\n shadowRootDiv: HTMLDivElement;\n canvas: HTMLCanvasElement;\n ctx: CanvasRenderingContext2D;\n\n static get styles() {\n return css`\n .chart-title {\n font-size: 1.2em;\n font-weight: 600;\n text-align: center;\n }\n\n temba-select {\n display: block;\n }\n\n .config-toggle {\n margin-top: -2.5em;\n margin-right: -0.5em;\n color: #bbb;\n display: none;\n }\n\n .config-toggle:hover {\n color: #666;\n }\n\n .config-toggle.show {\n color: #666;\n display: block;\n }\n\n .config {\n max-height: 0px;\n margin: 2em 0.5em;\n padding: 0em 1em;\n border-radius: var(--curvature);\n border: 1px solid transparent;\n background: transparent;\n overflow: hidden;\n transition: all 0.2s ease-in-out;\n }\n\n .config.show {\n padding: 1em;\n max-height: 50px;\n background: rgba(0, 0, 0, 0.02);\n border: 1px solid rgba(0, 0, 0, 0.09);\n }\n `;\n }\n\n constructor() {\n super();\n }\n\n protected firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n const wrapper = this.shadowRoot.querySelector('#canvas-wrapper');\n this.canvas = document.createElement('canvas');\n this.canvas.setAttribute('height', '300px');\n wrapper.appendChild(this.canvas);\n this.ctx = this.canvas.getContext('2d');\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('data') || changes.has('splits')) {\n this.calculateSplits();\n }\n\n if (changes.has('datasets')) {\n this.updateChart();\n }\n\n if (changes.has('url')) {\n const store = getStore();\n store.getUrl(this.url).then((response) => {\n this.data = response.json.data;\n });\n }\n }\n\n private calculateSplits() {\n if (this.data) {\n const datasets = [];\n // keep a running list of values that is the sum at each index\n const sums = [];\n for (const dataset of this.data.datasets) {\n if (this.splits.find((s) => s === dataset.label) === undefined) {\n // update our sums\n for (let i = 0; i < dataset.data.length; i++) {\n if (sums[i] === undefined) {\n sums[i] = dataset.data[i];\n } else {\n sums[i] += dataset.data[i];\n }\n }\n } else {\n datasets.push({\n ...dataset,\n backgroundColor:\n colors[(datasets.length + this.colorIndex) % colors.length],\n borderColor:\n colorsBorder[\n (datasets.length + this.colorIndex) % colorsBorder.length\n ],\n borderWidth: 1\n });\n }\n }\n\n if (datasets.length === 0) {\n datasets.push({\n label: this.single ? this.dataname : `All ${this.dataname}`,\n data: sums,\n backgroundColor: colors[this.colorIndex % colors.length],\n borderColor: colorsBorder[this.colorIndex % colorsBorder.length],\n borderWidth: 1\n });\n } else {\n datasets.push({\n label: 'Other',\n data: sums,\n backgroundColor: otherBackgroundColor,\n borderColor: otherBorderColor,\n borderWidth: 1\n });\n }\n this.datasets = datasets;\n }\n }\n\n public updateChart(): void {\n if (this.datasets?.length > 0) {\n if (this.chart) {\n this.chart.data.labels = this.data.labels;\n this.chart.data.datasets = this.datasets;\n this.chart.update();\n } else {\n const chartData = {\n type: this.chartType,\n data: {\n labels: this.data.labels,\n datasets: this.datasets\n },\n options: {\n plugins: {\n legend: {\n display: this.legend\n },\n ...(this.formatDuration && {\n tooltip: {\n callbacks: {\n label: (context: any) => {\n const label = context.dataset.label || '';\n const value = context.parsed.y;\n const formattedValue = formatDurationFromSeconds(value);\n return `${label}: ${formattedValue}`;\n }\n }\n }\n })\n },\n responsive: true,\n maintainAspectRatio: false,\n animation: {\n x: { from: 500 },\n y: { from: 500 }\n },\n animations: {\n tension: {\n duration: 1000,\n easing: 'linear',\n from: 1,\n to: 0,\n loop: true\n }\n },\n scales: {\n y: {\n min: 0,\n stacked: true,\n ...(this.formatDuration && {\n ticks: {\n callback: (value: any) => {\n return formatDurationFromSeconds(value);\n }\n }\n })\n },\n x: {\n type: 'time',\n time: {\n unit: 'day',\n tooltipFormat: 'DDD', // Luxon for 'Feb 16, 2025'\n displayFormats: {\n day: 'MMM dd'\n }\n },\n grid: {\n display: false\n },\n stacked: true\n }\n }\n }\n };\n this.chart = new Chart(this.ctx, chartData as any);\n }\n }\n }\n\n private handleSplitsChanged(e: Event) {\n const select = e.target as Select<SelectOption>;\n this.splits = select.values.map((option) => {\n return option.value;\n });\n }\n\n private handleToggleConfig() {\n this.showConfig = !this.showConfig;\n if (!this.showConfig) {\n this.splits = [];\n }\n }\n\n protected render(): TemplateResult {\n return html`<div>\n ${this.header\n ? html`<div class=\"chart-title\">${this.header}</div>`\n : null}\n <div id=\"canvas-wrapper\"></div>\n ${this.config && this.data\n ? html`\n <div\n class=\"${getClasses({\n 'config-toggle': true,\n show: this.showConfig && this.data?.datasets?.length > 1\n })}\"\n style=\"display: flex; flex-direction: row; align-items: center; justify-content: space-between;\"\n >\n <div></div>\n <div>\n <temba-icon\n animateChange=\"spin\"\n name=\"${this.showConfig ? 'close' : 'settings'}\"\n clickable\n size=\"1.5\"\n @click=${this.handleToggleConfig}\n ></temba-icon>\n </div>\n </div>\n `\n : null}\n\n <div class=${getClasses({ config: true, show: this.showConfig })}>\n <temba-select\n multi\n placeholder=\"Select ${this.dataname}\"\n options=${JSON.stringify(\n this.data?.datasets.map((dataset) => ({\n name: dataset.label,\n value: dataset.label\n }))\n )}\n .values=${this.splits.map((s) => ({ name: s, value: s }))}\n @change=${this.handleSplitsChanged}\n >\n </temba-select>\n <div></div>\n </div>\n </div>`;\n }\n}\n"]}
1
+ {"version":3,"file":"TembaChart.js","sourceRoot":"","sources":["../../../src/chart/TembaChart.ts"],"names":[],"mappings":"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","sourcesContent":["import { RapidElement } from '../RapidElement';\nimport { property, state } from 'lit/decorators.js';\nimport { css, html, PropertyValueMap, TemplateResult } from 'lit';\n\nimport { Select, SelectOption } from '../select/Select';\nimport { getClasses } from '../utils';\nimport { getStore } from '../store/Store';\n\n// eslint-disable-next-line import/no-named-as-default\nimport Chart, { ChartType } from 'chart.js/auto';\nimport 'chartjs-adapter-luxon';\n\nconst colors = [\n 'rgba(54, 162, 235, 0.2)',\n 'rgba(255, 159, 64, 0.2)',\n 'rgba(75, 192, 192, 0.2)',\n 'rgba(153, 102, 255, 0.2)',\n 'rgba(255, 205, 86, 0.2)',\n 'rgba(255, 99, 132, 0.2)'\n];\n\nconst colorsBorder = [\n 'rgb(54, 162, 235)',\n 'rgb(255, 159, 64)',\n 'rgb(75, 192, 192)',\n 'rgb(153, 102, 255)',\n 'rgb(255, 205, 86)',\n 'rgb(255, 99, 132)'\n];\n\nconst otherBackgroundColor = 'rgba(201, 203, 207, 0.2)';\nconst otherBorderColor = 'rgb(201, 203, 207)';\n\n/**\n * Formats a duration in seconds to a human-readable string showing the two largest units.\n * Examples: 68787 -> \"19h 6m\", 958000 -> \"11d 2h\", 3661 -> \"1h 1m\"\n */\nexport function formatDurationFromSeconds(seconds: number): string {\n if (seconds === 0) {\n return '0s';\n }\n\n const totalDays = Math.floor(seconds / 86400);\n const remainingAfterDays = seconds % 86400;\n const remainingHours = Math.floor(remainingAfterDays / 3600);\n const remainingAfterHours = remainingAfterDays % 3600;\n const remainingMinutes = Math.floor(remainingAfterHours / 60);\n const remainingSeconds = remainingAfterHours % 60;\n\n const units = [];\n\n if (totalDays > 0) {\n units.push(`${totalDays}d`);\n }\n if (remainingHours > 0) {\n units.push(`${remainingHours}h`);\n }\n if (remainingMinutes > 0 && units.length < 2) {\n units.push(`${remainingMinutes}m`);\n }\n if (remainingSeconds > 0 && units.length < 2) {\n units.push(`${remainingSeconds}s`);\n }\n\n // Return the first two most significant units\n return units.slice(0, 2).join(' ');\n}\n\nexport interface RapidChartData {\n labels: string[];\n datasets: { label: string; data: number[] }[];\n}\n\nexport class TembaChart extends RapidElement {\n @property({ type: String })\n chartType: ChartType = 'bar';\n\n @property({ type: String })\n url: string;\n\n @property({ type: String })\n header: string = '';\n\n @property({ type: Boolean })\n other: boolean = false;\n\n @property({ type: Object })\n data: RapidChartData;\n\n @state()\n datasets: { label: string; data: number[] }[] = [];\n\n @property({ type: Number })\n maxSplits: number = 2;\n\n @property({ type: String, attribute: 'splits' })\n splitNames: string;\n\n @property({ type: Boolean })\n hideOther: boolean = false;\n\n @state()\n splits: string[] = [];\n\n @property({ type: String })\n dataname = 'Counts';\n\n @property({ type: Boolean })\n single: boolean = false;\n\n @property({ type: Boolean })\n legend: boolean = false;\n\n @property({ type: Boolean })\n config: boolean = false;\n\n @property({ type: Boolean })\n formatDuration: boolean = false;\n\n @property({ type: Boolean })\n showAll: boolean = false;\n\n @property({ type: Number })\n colorIndex: number = 0;\n\n @state()\n showConfig: boolean = false;\n\n chart: Chart;\n shadowRootDiv: HTMLDivElement;\n canvas: HTMLCanvasElement;\n ctx: CanvasRenderingContext2D;\n\n static get styles() {\n return css`\n .chart-title {\n font-size: 1.2em;\n font-weight: 600;\n text-align: center;\n }\n\n temba-select {\n display: block;\n }\n\n .config-toggle {\n margin-top: -2.5em;\n margin-right: -0.5em;\n color: #bbb;\n display: none;\n }\n\n .config-toggle:hover {\n color: #666;\n }\n\n .config-toggle.show {\n color: #666;\n display: block;\n }\n\n .config {\n max-height: 0px;\n padding: 0em 1em;\n border-radius: var(--curvature);\n border: 1px solid transparent;\n background: transparent;\n overflow: hidden;\n transition: all 0.2s ease-in-out;\n }\n\n .config.show {\n padding: 2em 1em 1.5em 1em;\n max-height: 50px;\n }\n `;\n }\n\n constructor() {\n super();\n }\n\n protected firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n const wrapper = this.shadowRoot.querySelector('#canvas-wrapper');\n this.canvas = document.createElement('canvas');\n this.canvas.setAttribute('height', '300px');\n wrapper.appendChild(this.canvas);\n this.ctx = this.canvas.getContext('2d');\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n\n if (changes.has('splitNames')) {\n this.splits = this.splitNames.split(',').map((s) => s.trim());\n }\n\n if (changes.has('data') || changes.has('splits')) {\n this.calculateSplits();\n }\n\n if (changes.has('datasets')) {\n this.updateChart();\n }\n\n if (changes.has('url')) {\n const store = getStore();\n store.getUrl(this.url, { skipCache: true }).then((response) => {\n this.data = response.json.data;\n });\n }\n }\n\n private calculateSplits() {\n if (this.data) {\n const datasets = [];\n // keep a running list of values that is the sum at each index\n const sums = [];\n for (const dataset of this.data.datasets) {\n if (\n !this.showAll &&\n this.splits.find((s) => s === dataset.label) === undefined\n ) {\n // update our sums\n for (let i = 0; i < dataset.data.length; i++) {\n if (sums[i] === undefined) {\n sums[i] = dataset.data[i];\n } else {\n sums[i] += dataset.data[i];\n }\n }\n } else {\n datasets.push({\n ...dataset,\n backgroundColor:\n colors[(datasets.length + this.colorIndex) % colors.length],\n borderColor:\n colorsBorder[\n (datasets.length + this.colorIndex) % colorsBorder.length\n ],\n borderWidth: 1\n });\n }\n }\n\n if (datasets.length === 0) {\n datasets.push({\n label: this.single ? this.dataname : `All ${this.dataname}`,\n data: sums,\n backgroundColor: colors[this.colorIndex % colors.length],\n borderColor: colorsBorder[this.colorIndex % colorsBorder.length],\n borderWidth: 1\n });\n } else {\n if (!this.hideOther && !this.showAll) {\n datasets.push({\n label: 'Other',\n data: sums,\n backgroundColor: otherBackgroundColor,\n borderColor: otherBorderColor,\n borderWidth: 1\n });\n }\n }\n this.datasets = datasets;\n }\n }\n\n public updateChart(): void {\n if (this.datasets?.length > 0) {\n if (this.chart) {\n this.chart.data.labels = this.data.labels;\n this.chart.data.datasets = this.datasets;\n this.chart.update();\n } else {\n const chartData = {\n type: this.chartType,\n data: {\n labels: this.data.labels,\n datasets: this.datasets\n },\n options: {\n plugins: {\n legend: {\n display: this.legend\n },\n ...(this.formatDuration && {\n tooltip: {\n callbacks: {\n label: (context: any) => {\n const label = context.dataset.label || '';\n const value = context.parsed.y;\n const formattedValue = formatDurationFromSeconds(value);\n return `${label}: ${formattedValue}`;\n }\n }\n }\n })\n },\n responsive: true,\n maintainAspectRatio: false,\n animation: {\n x: { from: 500 },\n y: { from: 500 }\n },\n scales: {\n y: {\n min: 0,\n stacked: true,\n ...(this.formatDuration && {\n ticks: {\n callback: (value: any) => {\n return formatDurationFromSeconds(value);\n }\n }\n })\n },\n x: {\n type: 'time',\n time: {\n unit: 'day',\n tooltipFormat: 'DDD', // Luxon for 'Feb 16, 2025'\n displayFormats: {\n day: 'MMM dd'\n }\n },\n grid: {\n display: false\n },\n stacked: true\n }\n }\n }\n };\n this.chart = new Chart(this.ctx, chartData as any);\n }\n }\n }\n\n private handleSplitsChanged(e: Event) {\n const select = e.target as Select<SelectOption>;\n this.splits = select.values.map((option) => {\n return option.value;\n });\n }\n\n private handleToggleConfig() {\n this.showConfig = !this.showConfig;\n if (!this.showConfig) {\n this.splits = [];\n }\n }\n\n protected render(): TemplateResult {\n return html`<div>\n ${this.header\n ? html`<div class=\"chart-title\">${this.header}</div>`\n : null}\n <div id=\"canvas-wrapper\"></div>\n ${this.config && this.data\n ? html`\n <div\n class=\"${getClasses({\n 'config-toggle': true,\n show: this.showConfig && this.data?.datasets?.length > 1\n })}\"\n style=\"display: flex; flex-direction: row; align-items: center; justify-content: space-between;\"\n >\n <div></div>\n <div>\n <temba-icon\n animateChange=\"spin\"\n name=\"${this.showConfig ? 'close' : 'settings'}\"\n clickable\n size=\"1.5\"\n @click=${this.handleToggleConfig}\n ></temba-icon>\n </div>\n </div>\n `\n : null}\n\n <div class=${getClasses({ config: true, show: this.showConfig })}>\n <temba-select\n multi\n placeholder=\"Select ${this.dataname}\"\n options=${JSON.stringify(\n this.data?.datasets.map((dataset) => ({\n name: dataset.label,\n value: dataset.label\n }))\n )}\n .values=${this.splits.map((s) => ({ name: s, value: s }))}\n @change=${this.handleSplitsChanged}\n >\n </temba-select>\n <div></div>\n </div>\n </div>`;\n }\n}\n"]}
@@ -135,7 +135,7 @@ export class Editor extends RapidElement {
135
135
  updated(changes) {
136
136
  super.updated(changes);
137
137
  if (changes.has('canvasSize')) {
138
- console.log('Setting canvas size', this.canvasSize);
138
+ // console.log('Setting canvas size', this.canvasSize);
139
139
  }
140
140
  }
141
141
  render() {
@@ -1 +1 @@
1
- {"version":3,"file":"Editor.js","sourceRoot":"","sources":["../../../src/flow/Editor.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAkB,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,GAAG,EAAoB,SAAS,EAAE,MAAM,KAAK,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAY,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,OAAO,MAAO,SAAQ,YAAY;IACtC,0DAA0D;IAC1D,gBAAgB;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAiBD,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2GT,CAAC;IACJ,CAAC;IAED;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAES,YAAY,CACpB,OAA0D;QAE1D,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1D,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,mBAAmB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAES,OAAO,CACf,OAA0D;QAE1D,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAEM,MAAM;QACX,2DAA2D;QAC3D,MAAM,KAAK,GAAG,IAAI,CAAA;QACd,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;QAChC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC;aAC/B,CAAC;QAEV,OAAO,IAAI,CAAA,GAAG,KAAK;;;;wCAIiB,IAAI,CAAC,UAAU,CAAC,KAAK,cAAc,IAAI;aAClE,UAAU,CAAC,MAAM;;;cAGhB,IAAI,CAAC,UAAU;YACf,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;gBACjC,OAAO,IAAI,CAAA;+BACE,IAAI,CAAC,OAAO;4BACf,IAAI;0BACN,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;sCACxB,CAAC;YACvB,CAAC,CAAC;YACJ,CAAC,CAAC,IAAI,CAAA,iCAAiC;;;aAGxC,CAAC;IACZ,CAAC;CACF;AA7KQ;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oCACP;AAGb;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;uCACJ;AAGf;IADP,SAAS,CAAC,OAAO,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC;0CAC1B;AAG5B;IADP,SAAS,CAAC,OAAO,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC;0CACH","sourcesContent":["import { html, TemplateResult } from 'lit-html';\nimport { css, PropertyValueMap, unsafeCSS } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { FlowDefinition } from '../store/flow-definition';\nimport { getStore } from '../store/Store';\nimport { AppState, fromStore, zustand } from '../store/AppState';\nimport { RapidElement } from '../RapidElement';\n\nimport { Plumber } from './Plumber';\nimport { EditorNode } from './EditorNode';\n\nexport class Editor extends RapidElement {\n // Unfortunately, jsplumb requires that we be in light DOM\n createRenderRoot() {\n return this;\n }\n\n // This is the master plumber\n private plumber: Plumber;\n\n @property({ type: String })\n public flow: string;\n\n @property({ type: String })\n public version: string;\n\n @fromStore(zustand, (state: AppState) => state.flowDefinition)\n private definition!: FlowDefinition;\n\n @fromStore(zustand, (state: AppState) => state.canvasSize)\n private canvasSize!: { width: number; height: number };\n\n static get styles() {\n return css`\n #editor {\n overflow: scroll;\n flex: 1;\n }\n\n #grid {\n position: relative;\n background-color: #f9f9f9;\n background-position: 13px 13px;\n background-image: linear-gradient(\n 0deg,\n transparent 24%,\n rgba(61, 177, 255, 0.15) 25%,\n rgba(61, 177, 255, 0.15) 26%,\n transparent 27%,\n transparent 74%,\n rgba(61, 177, 255, 0.15) 75%,\n rgba(61, 177, 255, 0.15) 76%,\n transparent 77%,\n transparent\n ),\n linear-gradient(\n 90deg,\n transparent 24%,\n rgba(61, 177, 255, 0.15) 25%,\n rgba(61, 177, 255, 0.15) 26%,\n transparent 27%,\n transparent 74%,\n rgba(61, 177, 255, 0.15) 75%,\n rgba(61, 177, 255, 0.15) 76%,\n transparent 77%,\n transparent\n );\n background-size: 40px 40px;\n box-shadow: inset -5px 0 10px rgba(0, 0, 0, 0.05);\n border-top: 1px solid #e0e0e0;\n display: inline-block;\n width: 100%;\n }\n\n #canvas {\n position: relative;\n padding: 20px;\n margin: 20px;\n }\n\n body .jtk-endpoint {\n width: initial;\n height: initial;\n }\n\n .jtk-endpoint {\n z-index: 1;\n }\n\n .plumb-source {\n z-index: 300;\n border: 0px solid var(--color-connectors);\n }\n\n .plumb-source.connected {\n box-shadow: 0 3px 3px 0px rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n }\n\n .plumb-source circle {\n fill: tomato;\n }\n\n .plumb-source.connected circle {\n fill: #fff;\n }\n\n .plumb-source svg {\n fill: var(--color-connectors) !important;\n stroke: var(--color-connectors);\n }\n\n .plumb-target {\n margin-top: -6px;\n z-index: 200;\n opacity: 0;\n cursor: pointer;\n }\n\n body .plumb-connector path {\n stroke: var(--color-connectors) !important;\n stroke-width: 3px;\n }\n\n body .plumb-connector .plumb-arrow {\n fill: var(--color-connectors);\n stroke: var(--color-connectors);\n stroke-width: 0px;\n margin-top: 6px;\n }\n\n body svg.jtk-connector.jtk-hover path {\n stroke: var(--color-success) !important;\n stroke-width: 3px;\n }\n\n body .plumb-connector.jtk-hover .plumb-arrow {\n fill: var(--color-success) !important;\n stroke-width: 0px;\n }\n `;\n }\n\n constructor() {\n super();\n }\n\n protected firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n this.plumber = new Plumber(this.querySelector('#canvas'));\n if (changes.has('flow')) {\n getStore().getState().fetchRevision(`/flow/revisions/${this.flow}`);\n }\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('canvasSize')) {\n console.log('Setting canvas size', this.canvasSize);\n }\n }\n\n public render(): TemplateResult {\n // we have to embed our own style since we are in light DOM\n const style = html`<style>\n ${unsafeCSS(Editor.styles.cssText)}\n ${unsafeCSS(EditorNode.styles.cssText)}\n </style>`;\n\n return html`${style}\n <div id=\"editor\">\n <div\n id=\"grid\"\n style=\"min-width:100%;width:${this.canvasSize.width}px; height:${this\n .canvasSize.height}px\"\n >\n <div id=\"canvas\">\n ${this.definition\n ? this.definition.nodes.map((node) => {\n return html`<temba-flow-node\n .plumber=${this.plumber}\n .node=${node}\n .ui=${this.definition._ui.nodes[node.uuid]}\n ></temba-flow-node>`;\n })\n : html`<temba-loading></temba-loading>`}\n </div>\n </div>\n </div>`;\n }\n}\n"]}
1
+ {"version":3,"file":"Editor.js","sourceRoot":"","sources":["../../../src/flow/Editor.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAkB,MAAM,UAAU,CAAC;AAChD,OAAO,EAAE,GAAG,EAAoB,SAAS,EAAE,MAAM,KAAK,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAY,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,OAAO,MAAO,SAAQ,YAAY;IACtC,0DAA0D;IAC1D,gBAAgB;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAiBD,MAAM,KAAK,MAAM;QACf,OAAO,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA2GT,CAAC;IACJ,CAAC;IAED;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAES,YAAY,CACpB,OAA0D;QAE1D,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1D,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACxB,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,mBAAmB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IAES,OAAO,CACf,OAA0D;QAE1D,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9B,uDAAuD;QACzD,CAAC;IACH,CAAC;IAEM,MAAM;QACX,2DAA2D;QAC3D,MAAM,KAAK,GAAG,IAAI,CAAA;QACd,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;QAChC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC;aAC/B,CAAC;QAEV,OAAO,IAAI,CAAA,GAAG,KAAK;;;;wCAIiB,IAAI,CAAC,UAAU,CAAC,KAAK,cAAc,IAAI;aAClE,UAAU,CAAC,MAAM;;;cAGhB,IAAI,CAAC,UAAU;YACf,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;gBACjC,OAAO,IAAI,CAAA;+BACE,IAAI,CAAC,OAAO;4BACf,IAAI;0BACN,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;sCACxB,CAAC;YACvB,CAAC,CAAC;YACJ,CAAC,CAAC,IAAI,CAAA,iCAAiC;;;aAGxC,CAAC;IACZ,CAAC;CACF;AA7KQ;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oCACP;AAGb;IADN,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;uCACJ;AAGf;IADP,SAAS,CAAC,OAAO,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC;0CAC1B;AAG5B;IADP,SAAS,CAAC,OAAO,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC;0CACH","sourcesContent":["import { html, TemplateResult } from 'lit-html';\nimport { css, PropertyValueMap, unsafeCSS } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { FlowDefinition } from '../store/flow-definition';\nimport { getStore } from '../store/Store';\nimport { AppState, fromStore, zustand } from '../store/AppState';\nimport { RapidElement } from '../RapidElement';\n\nimport { Plumber } from './Plumber';\nimport { EditorNode } from './EditorNode';\n\nexport class Editor extends RapidElement {\n // Unfortunately, jsplumb requires that we be in light DOM\n createRenderRoot() {\n return this;\n }\n\n // This is the master plumber\n private plumber: Plumber;\n\n @property({ type: String })\n public flow: string;\n\n @property({ type: String })\n public version: string;\n\n @fromStore(zustand, (state: AppState) => state.flowDefinition)\n private definition!: FlowDefinition;\n\n @fromStore(zustand, (state: AppState) => state.canvasSize)\n private canvasSize!: { width: number; height: number };\n\n static get styles() {\n return css`\n #editor {\n overflow: scroll;\n flex: 1;\n }\n\n #grid {\n position: relative;\n background-color: #f9f9f9;\n background-position: 13px 13px;\n background-image: linear-gradient(\n 0deg,\n transparent 24%,\n rgba(61, 177, 255, 0.15) 25%,\n rgba(61, 177, 255, 0.15) 26%,\n transparent 27%,\n transparent 74%,\n rgba(61, 177, 255, 0.15) 75%,\n rgba(61, 177, 255, 0.15) 76%,\n transparent 77%,\n transparent\n ),\n linear-gradient(\n 90deg,\n transparent 24%,\n rgba(61, 177, 255, 0.15) 25%,\n rgba(61, 177, 255, 0.15) 26%,\n transparent 27%,\n transparent 74%,\n rgba(61, 177, 255, 0.15) 75%,\n rgba(61, 177, 255, 0.15) 76%,\n transparent 77%,\n transparent\n );\n background-size: 40px 40px;\n box-shadow: inset -5px 0 10px rgba(0, 0, 0, 0.05);\n border-top: 1px solid #e0e0e0;\n display: inline-block;\n width: 100%;\n }\n\n #canvas {\n position: relative;\n padding: 20px;\n margin: 20px;\n }\n\n body .jtk-endpoint {\n width: initial;\n height: initial;\n }\n\n .jtk-endpoint {\n z-index: 1;\n }\n\n .plumb-source {\n z-index: 300;\n border: 0px solid var(--color-connectors);\n }\n\n .plumb-source.connected {\n box-shadow: 0 3px 3px 0px rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n }\n\n .plumb-source circle {\n fill: tomato;\n }\n\n .plumb-source.connected circle {\n fill: #fff;\n }\n\n .plumb-source svg {\n fill: var(--color-connectors) !important;\n stroke: var(--color-connectors);\n }\n\n .plumb-target {\n margin-top: -6px;\n z-index: 200;\n opacity: 0;\n cursor: pointer;\n }\n\n body .plumb-connector path {\n stroke: var(--color-connectors) !important;\n stroke-width: 3px;\n }\n\n body .plumb-connector .plumb-arrow {\n fill: var(--color-connectors);\n stroke: var(--color-connectors);\n stroke-width: 0px;\n margin-top: 6px;\n }\n\n body svg.jtk-connector.jtk-hover path {\n stroke: var(--color-success) !important;\n stroke-width: 3px;\n }\n\n body .plumb-connector.jtk-hover .plumb-arrow {\n fill: var(--color-success) !important;\n stroke-width: 0px;\n }\n `;\n }\n\n constructor() {\n super();\n }\n\n protected firstUpdated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.firstUpdated(changes);\n this.plumber = new Plumber(this.querySelector('#canvas'));\n if (changes.has('flow')) {\n getStore().getState().fetchRevision(`/flow/revisions/${this.flow}`);\n }\n }\n\n protected updated(\n changes: PropertyValueMap<any> | Map<PropertyKey, unknown>\n ): void {\n super.updated(changes);\n if (changes.has('canvasSize')) {\n // console.log('Setting canvas size', this.canvasSize);\n }\n }\n\n public render(): TemplateResult {\n // we have to embed our own style since we are in light DOM\n const style = html`<style>\n ${unsafeCSS(Editor.styles.cssText)}\n ${unsafeCSS(EditorNode.styles.cssText)}\n </style>`;\n\n return html`${style}\n <div id=\"editor\">\n <div\n id=\"grid\"\n style=\"min-width:100%;width:${this.canvasSize.width}px; height:${this\n .canvasSize.height}px\"\n >\n <div id=\"canvas\">\n ${this.definition\n ? this.definition.nodes.map((node) => {\n return html`<temba-flow-node\n .plumber=${this.plumber}\n .node=${node}\n .ui=${this.definition._ui.nodes[node.uuid]}\n ></temba-flow-node>`;\n })\n : html`<temba-loading></temba-loading>`}\n </div>\n </div>\n </div>`;\n }\n}\n"]}
@@ -1416,7 +1416,7 @@ export class Select extends FormElement {
1416
1416
  </div>
1417
1417
  `
1418
1418
  : null}
1419
- ${!this.input
1419
+ ${!this.input || this.multi
1420
1420
  ? this.renderSelectedItem(selected)
1421
1421
  : null}
1422
1422
  </div>