@nyaruka/temba-components 0.127.0 → 0.128.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 (70) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/demo/data/flows/sample-flow.json +127 -100
  3. package/demo/sticky-note-demo.html +152 -0
  4. package/dist/locales/es.js +5 -5
  5. package/dist/locales/es.js.map +1 -1
  6. package/dist/locales/fr.js +5 -5
  7. package/dist/locales/fr.js.map +1 -1
  8. package/dist/locales/locale-codes.js +11 -2
  9. package/dist/locales/locale-codes.js.map +1 -1
  10. package/dist/locales/pt.js +5 -5
  11. package/dist/locales/pt.js.map +1 -1
  12. package/dist/temba-components.js +346 -86
  13. package/dist/temba-components.js.map +1 -1
  14. package/out-tsc/src/chart/TembaChart.js +20 -3
  15. package/out-tsc/src/chart/TembaChart.js.map +1 -1
  16. package/out-tsc/src/flow/Editor.js +210 -1
  17. package/out-tsc/src/flow/Editor.js.map +1 -1
  18. package/out-tsc/src/flow/EditorNode.js +98 -139
  19. package/out-tsc/src/flow/EditorNode.js.map +1 -1
  20. package/out-tsc/src/flow/StickyNote.js +272 -0
  21. package/out-tsc/src/flow/StickyNote.js.map +1 -0
  22. package/out-tsc/src/list/RunList.js +2 -1
  23. package/out-tsc/src/list/RunList.js.map +1 -1
  24. package/out-tsc/src/list/SortableList.js +9 -0
  25. package/out-tsc/src/list/SortableList.js.map +1 -1
  26. package/out-tsc/src/locales/es.js +5 -5
  27. package/out-tsc/src/locales/es.js.map +1 -1
  28. package/out-tsc/src/locales/fr.js +5 -5
  29. package/out-tsc/src/locales/fr.js.map +1 -1
  30. package/out-tsc/src/locales/locale-codes.js +11 -2
  31. package/out-tsc/src/locales/locale-codes.js.map +1 -1
  32. package/out-tsc/src/locales/pt.js +5 -5
  33. package/out-tsc/src/locales/pt.js.map +1 -1
  34. package/out-tsc/src/store/AppState.js +33 -0
  35. package/out-tsc/src/store/AppState.js.map +1 -1
  36. package/out-tsc/src/vectoricon/index.js +2 -1
  37. package/out-tsc/src/vectoricon/index.js.map +1 -1
  38. package/out-tsc/temba-modules.js +2 -0
  39. package/out-tsc/temba-modules.js.map +1 -1
  40. package/out-tsc/test/temba-flow-editor-node.test.js +249 -5
  41. package/out-tsc/test/temba-flow-editor-node.test.js.map +1 -1
  42. package/out-tsc/test/temba-select.test.js +11 -17
  43. package/out-tsc/test/temba-select.test.js.map +1 -1
  44. package/out-tsc/test/utils.test.js +62 -0
  45. package/out-tsc/test/utils.test.js.map +1 -1
  46. package/package.json +1 -1
  47. package/screenshots/truth/sticky-note/blue.png +0 -0
  48. package/screenshots/truth/sticky-note/gray.png +0 -0
  49. package/screenshots/truth/sticky-note/green.png +0 -0
  50. package/screenshots/truth/sticky-note/pink.png +0 -0
  51. package/screenshots/truth/sticky-note/yellow.png +0 -0
  52. package/src/chart/TembaChart.ts +20 -3
  53. package/src/flow/Editor.ts +252 -2
  54. package/src/flow/EditorNode.ts +98 -156
  55. package/src/flow/StickyNote.ts +284 -0
  56. package/src/list/RunList.ts +2 -1
  57. package/src/list/SortableList.ts +11 -0
  58. package/src/locales/es.ts +18 -13
  59. package/src/locales/fr.ts +18 -13
  60. package/src/locales/locale-codes.ts +11 -2
  61. package/src/locales/pt.ts +18 -13
  62. package/src/store/AppState.ts +51 -1
  63. package/src/store/flow-definition.d.ts +8 -0
  64. package/src/vectoricon/index.ts +2 -1
  65. package/static/svg/index.pdf +137 -0
  66. package/temba-modules.ts +2 -0
  67. package/test/temba-flow-editor-node.test.ts +322 -6
  68. package/test/temba-select.test.ts +12 -20
  69. package/test/utils.test.ts +98 -0
  70. package/web-dev-server.config.mjs +30 -22
@@ -315,6 +315,7 @@ export class TembaChart extends RapidElement {
315
315
  this.xMaxTicks = 10;
316
316
  this.yType = 'count';
317
317
  this.xFormat = 'auto';
318
+ this.maxChartHeight = 250;
318
319
  this.hideOther = false;
319
320
  this.splits = [];
320
321
  this.dataname = 'Counts';
@@ -413,6 +414,18 @@ export class TembaChart extends RapidElement {
413
414
  });
414
415
  return [backgroundColors, borderColors];
415
416
  }
417
+ handleResize() {
418
+ if (this.chart) {
419
+ // recalculate canvas size based on parent container
420
+ const wrapper = this.shadowRoot.querySelector('#canvas-wrapper');
421
+ if (wrapper) {
422
+ if (wrapper.clientHeight > this.maxChartHeight) {
423
+ this.canvas.style.height = `${this.maxChartHeight}px`;
424
+ this.chart.resize();
425
+ }
426
+ }
427
+ }
428
+ }
416
429
  calculateSplits() {
417
430
  if (this.data) {
418
431
  const datasets = [];
@@ -546,15 +559,16 @@ export class TembaChart extends RapidElement {
546
559
  }
547
560
  },
548
561
  responsive: true,
562
+ aspectRatio: 2,
563
+ onResize: this.handleResize.bind(this),
549
564
  maintainAspectRatio: false,
565
+ animation: false,
550
566
  animations: {
551
567
  x: {
552
- // no horizontal motion
553
568
  duration: 0
554
569
  },
555
570
  y: {
556
- duration: 200,
557
- easing: 'easeOutCubic'
571
+ duration: 0
558
572
  }
559
573
  },
560
574
  scales: {
@@ -695,6 +709,9 @@ __decorate([
695
709
  __decorate([
696
710
  property({ type: String })
697
711
  ], TembaChart.prototype, "xFormat", void 0);
712
+ __decorate([
713
+ property({ type: Number })
714
+ ], TembaChart.prototype, "maxChartHeight", void 0);
698
715
  __decorate([
699
716
  property({ type: Boolean })
700
717
  ], TembaChart.prototype, "hideOther", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"TembaChart.js","sourceRoot":"","sources":["../../../src/chart/TembaChart.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAoC,MAAM,KAAK,CAAC;AAGlE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,sDAAsD;AACtD,OAAO,KAAoB,MAAM,eAAe,CAAC;AACjD,OAAO,uBAAuB,CAAC;AAC/B,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAExD,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;AAEhC,MAAM,eAAe,GAAgC,kBAAkB,CAAC;AACxE,MAAM,cAAc,GAAG;IACrB,sCAAsC;IACtC,kBAAkB,EAAE;QAClB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,kBAAkB,EAAE;QAClB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,kBAAkB,EAAE;QAClB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,oBAAoB,EAAE;QACpB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,oBAAoB,EAAE;QACpB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,qBAAqB,EAAE;QACrB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,qBAAqB,EAAE;QACrB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,4CAA4C;IAC5C,gBAAgB,EAAE;QAChB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,oBAAoB,EAAE;QACpB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,gBAAgB,EAAE;QAChB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,kBAAkB,EAAE;QAClB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,gBAAgB,EAAE;QAChB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IAED,8CAA8C;IAC9C,kBAAkB,EAAE;QAClB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,mBAAmB,EAAE;QACnB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,oBAAoB,EAAE;QACpB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,oBAAoB,EAAE;QACpB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,iBAAiB,EAAE;QACjB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,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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 { darkenColor, 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';\nimport ChartDataLabels from 'chartjs-plugin-datalabels';\n\nChart.register(ChartDataLabels);\n\nconst DEFAULT_PALETTE: keyof typeof COLOR_PALETTES = 'qualitative-set1';\nconst COLOR_PALETTES = {\n // Qualitative (categorical, no order)\n 'qualitative-set1': [\n '#5ea3db',\n '#c186e3',\n '#66c2a5',\n '#fc8d62',\n '#a6d854',\n '#ffd92f',\n '#e5c494',\n '#b3b3b3'\n ],\n 'qualitative-set2': [\n '#377eb8',\n '#984ea3',\n '#4daf4a',\n '#ff7f00',\n '#e41a1c',\n '#a65628',\n '#f781bf',\n '#ffff33'\n ],\n 'qualitative-set3': [\n '#1b9e77',\n '#d95f02',\n '#7570b3',\n '#e7298a',\n '#66a61e',\n '#e6ab02',\n '#a6761d'\n ],\n 'qualitative-paired': [\n '#1f78b4',\n '#a6cee3',\n '#6a3d9a',\n '#cab2d6',\n '#33a02c',\n '#b2df8a',\n '#e31a1c',\n '#fb9a99',\n '#ff7f00',\n '#fdbf6f'\n ],\n 'qualitative-accent': [\n '#7fc97f',\n '#beaed4',\n '#fdc086',\n '#ffff99',\n '#386cb0',\n '#f0027f',\n '#bf5b17',\n '#666666'\n ],\n 'qualitative-pastel1': [\n '#fbb4ae',\n '#b3cde3',\n '#ccebc5',\n '#decbe4',\n '#fed9a6',\n '#ffffcc',\n '#e5d8bd',\n '#fddaec'\n ],\n 'qualitative-pastel2': [\n '#b3e2cd',\n '#fdcdac',\n '#cbd5e8',\n '#f4cae4',\n '#e6f5c9',\n '#fff2ae',\n '#f1e2cc'\n ],\n // Diverging (for data with midpoint like 0)\n 'diverging-prgn': [\n '#40004b',\n '#762a83',\n '#9970ab',\n '#c2a5cf',\n '#e7d4e8',\n '#f7f7f7',\n '#d9f0d3',\n '#a6dba0',\n '#5aae61',\n '#1b7837',\n '#00441b'\n ],\n 'diverging-spectral': [\n '#9e0142',\n '#d53e4f',\n '#f46d43',\n '#fdae61',\n '#fee08b',\n '#ffffbf',\n '#e6f598',\n '#abdda4',\n '#66c2a5',\n '#3288bd',\n '#5e4fa2'\n ],\n 'diverging-piyg': [\n '#8e0152',\n '#c51b7d',\n '#de77ae',\n '#f1b6da',\n '#fde0ef',\n '#f7f7f7',\n '#e6f5d0',\n '#b8e186',\n '#7fbc41',\n '#4d9221',\n '#276419'\n ],\n 'diverging-rdylgn': [\n '#a50026',\n '#d73027',\n '#f46d43',\n '#fdae61',\n '#fee08b',\n '#ffffbf',\n '#d9ef8b',\n '#a6d96a',\n '#66bd63',\n '#1a9850',\n '#006837'\n ],\n 'diverging-brbg': [\n '#543005',\n '#8c510a',\n '#bf812d',\n '#dfc27d',\n '#f6e8c3',\n '#f5f5f5',\n '#c7eae5',\n '#80cdc1',\n '#35978f',\n '#01665e',\n '#003c30'\n ],\n\n // Sequential (for continuous or ordered data)\n 'sequential-blues': [\n '#f7fbff',\n '#deebf7',\n '#c6dbef',\n '#9ecae1',\n '#6baed6',\n '#4292c6',\n '#2171b5',\n '#08519c',\n '#08306b'\n ],\n 'sequential-greens': [\n '#f7fcf5',\n '#e5f5e0',\n '#c7e9c0',\n '#a1d99b',\n '#74c476',\n '#41ab5d',\n '#238b45',\n '#006d2c',\n '#00441b'\n ],\n 'sequential-oranges': [\n '#fff5eb',\n '#fee6ce',\n '#fdd0a2',\n '#fdae6b',\n '#fd8d3c',\n '#f16913',\n '#d94801',\n '#a63603',\n '#7f2704'\n ],\n 'sequential-purples': [\n '#fcfbfd',\n '#efedf5',\n '#dadaeb',\n '#bcbddc',\n '#9e9ac8',\n '#807dba',\n '#6a51a3',\n '#54278f',\n '#3f007d'\n ],\n 'sequential-reds': [\n '#fff5f0',\n '#fee0d2',\n '#fcbba1',\n '#fc9272',\n '#fb6a4a',\n '#ef3b2c',\n '#cb181d',\n '#a50f15',\n '#67000d'\n ],\n 'sequential-ylgnbu': [\n '#ffffd9',\n '#edf8b1',\n '#c7e9b4',\n '#7fcdbb',\n '#41b6c4',\n '#1d91c0',\n '#225ea8',\n '#253494',\n '#081d58'\n ]\n};\n\nconst otherBackgroundColor = 'rgba(212, 212, 212, 0.5)';\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: String })\n xType: 'category' | 'time' = 'category';\n\n @property({ type: Number })\n xMaxTicks: number = 10;\n\n @property({ type: String })\n yType: 'count' | 'duration' = 'count';\n\n @property({ type: String })\n xFormat: 'MMM yy' | 'MMM yyyy' | 'MMM dd' | 'DD' | 'EEE' | 'auto' = 'auto';\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 showAll: boolean = false;\n\n @property({ type: Number })\n colorIndex: number = 0;\n\n @state()\n showConfig: boolean = false;\n\n @property({ type: String })\n palette: keyof typeof COLOR_PALETTES;\n\n @property({ type: Number })\n opacity: number = 1;\n\n @property({ type: Number })\n seriesBorderRadius: number = 2;\n\n @property({ type: Number })\n seriesBorderWidth: number = 1;\n\n @property({ type: Boolean, attribute: 'percent' })\n showPercent: boolean = false;\n\n // head-room for labels when percentages are visible\n private getInflatedMax(): number | undefined {\n if (!this.showPercent || !this.data) return undefined;\n\n // total stacked value for each x-index\n const totals: number[] = Array(this.data.labels.length).fill(0);\n for (const ds of this.datasets) {\n ds.data.forEach((v, i) => (totals[i] += v));\n }\n const maxStack = Math.max(...totals);\n return maxStack > 0 ? maxStack * 1.15 : undefined;\n }\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 if (changes.has('chartType')) {\n if (this.chartType === 'line') {\n this.seriesBorderWidth = Math.max(1, this.seriesBorderWidth);\n }\n }\n\n if (changes.has('showPercent') && this.chart) {\n const yScale = (this.chart.options.scales as any).y;\n yScale.ticks.display = !this.showPercent;\n yScale.grid.display = !this.showPercent;\n yScale.border.display = !this.showPercent;\n yScale.max = this.showPercent ? this.getInflatedMax() : undefined;\n this.chart.update();\n }\n }\n\n /**\n * Returns a tuple: [backgroundColors[], borderColors[]].\n * Border colors are darkened versions of the base palette (before transparency).\n * Background colors have transparency applied.\n */\n get colors(): [string[], string[]] {\n const baseColors =\n COLOR_PALETTES[this.palette] || COLOR_PALETTES[DEFAULT_PALETTE];\n // clamp transparency between 0 and 1\n const alpha = Math.max(0, Math.min(1, this.opacity));\n // borders darken base color, no transparency\n const borderColors = baseColors.map((color) => darkenColor(color, 0.25));\n // backgrounds apply transparency to base color\n const backgroundColors = baseColors.map((color) => {\n // if already rgba, just replace the alpha\n if (color.startsWith('rgba')) {\n return color.replace(\n /rgba\\(([^,]+),([^,]+),([^,]+),([^)]+)\\)/,\n (_m, r, g, b) => {\n return `rgba(${r},${g},${b},${alpha})`;\n }\n );\n }\n // if already rgb, convert to rgba\n if (color.startsWith('rgb(')) {\n return color.replace(\n /rgb\\(([^,]+),([^,]+),([^,]+)\\)/,\n (_m, r, g, b) => {\n return `rgba(${r},${g},${b},${alpha})`;\n }\n );\n }\n // if hex, convert to rgba\n if (color.startsWith('#')) {\n let hex = color.replace('#', '');\n if (hex.length === 3) {\n hex = hex\n .split('')\n .map((c) => c + c)\n .join('');\n }\n const num = parseInt(hex, 16);\n const r = (num >> 16) & 255;\n const g = (num >> 8) & 255;\n const b = num & 255;\n return `rgba(${r},${g},${b},${alpha})`;\n }\n // fallback\n return color;\n });\n return [backgroundColors, borderColors];\n }\n\n private calculateSplits() {\n if (this.data) {\n const datasets = [];\n const sums = [];\n const [backgroundColors, borderColors] = this.colors;\n for (const dataset of this.data.datasets) {\n if (\n !this.showAll &&\n this.splits.find((s) => s === dataset.label) === undefined\n ) {\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 const colorIdx =\n (datasets.length + this.colorIndex) % backgroundColors.length;\n const bgColor = backgroundColors[colorIdx];\n const borderColor = borderColors[colorIdx];\n datasets.push({\n ...dataset,\n backgroundColor: bgColor,\n borderColor,\n borderWidth: this.seriesBorderWidth,\n borderRadius: this.seriesBorderRadius\n });\n }\n }\n\n if (datasets.length === 0) {\n const idx = this.colorIndex % backgroundColors.length;\n datasets.push({\n label: this.single ? this.dataname : `All ${this.dataname}`,\n data: sums,\n backgroundColor: backgroundColors[idx],\n borderColor: borderColors[idx],\n borderWidth: this.seriesBorderWidth,\n borderRadius: this.seriesBorderRadius\n });\n } else {\n if (!this.hideOther && !this.showAll) {\n datasets.push({\n label: 'Other',\n data: sums,\n backgroundColor: otherBackgroundColor,\n borderColor: darkenColor(otherBackgroundColor, 0.05),\n borderWidth: 1,\n borderRadius: this.seriesBorderRadius\n });\n }\n }\n this.datasets = datasets;\n }\n }\n\n public updateChart(): void {\n if (this.datasets?.length > 0) {\n const grandTotal =\n this.datasets.reduce(\n (sum: number, ds: any) =>\n sum +\n (ds.data as number[]).reduce(\n (dsSum: number, v: number) => dsSum + (v ?? 0),\n 0\n ),\n 0\n ) || undefined;\n\n const percentFormatter = (value: number): string => {\n const pct = grandTotal ? (value / grandTotal) * 100 : 0;\n if (pct === 0) {\n return '';\n }\n return `${Math.round(pct)}%`;\n };\n\n if (this.chart) {\n this.chart.data.labels = this.data.labels;\n this.chart.data.datasets = this.datasets;\n\n // update y-axis max dynamically\n if (this.showPercent) {\n (this.chart.options.scales as any).y.max = this.getInflatedMax();\n }\n\n const datalabels = this.chart.options.plugins.datalabels || {};\n datalabels.display = this.showPercent;\n if (this.showPercent) {\n datalabels.formatter = percentFormatter;\n } else {\n delete datalabels.formatter;\n }\n this.chart.options.plugins.datalabels = datalabels;\n\n this.chart.update();\n } else {\n let format = this.xFormat;\n if (this.xType === 'time' && this.xFormat === 'auto') {\n const firstDate = this.data.labels[0];\n const lastDate = this.data.labels[this.data.labels.length - 1];\n\n const first = Date.parse(firstDate);\n const last = Date.parse(lastDate);\n\n const dayDiff = Math.ceil((last - first) / (1000 * 60 * 60 * 24));\n format = 'MMM dd';\n if (dayDiff > 365) {\n format = 'MMM yyyy';\n }\n }\n\n const chartData = {\n type: this.chartType,\n data: {\n labels: this.data.labels,\n datasets: this.datasets\n },\n options: {\n maxBarThickness: 80,\n plugins: {\n legend: { display: this.legend },\n tooltip: {\n callbacks: {\n label: (context: any) => {\n const label = context.dataset.label || '';\n const value = context.parsed.y;\n if (this.yType === 'duration') {\n return `${label}: ${formatDurationFromSeconds(value)}`;\n }\n return `${label}: ${value}`;\n }\n }\n },\n datalabels: {\n display: this.showPercent,\n anchor: 'end',\n align: 'end',\n offset: -3,\n clamp: true,\n ...(this.showPercent && { formatter: percentFormatter }),\n color: '#666',\n font: { weight: '600' }\n }\n },\n responsive: true,\n maintainAspectRatio: false,\n animations: {\n x: {\n // no horizontal motion\n duration: 0\n },\n y: {\n duration: 200,\n easing: 'easeOutCubic'\n }\n },\n scales: {\n y: {\n min: 0,\n ...(this.showPercent && { max: this.getInflatedMax() }),\n stacked: true,\n grid: {\n color: 'rgba(0,0,0,0.04)',\n display: !this.showPercent, // hide gridlines in percent mode\n drawBorder: !this.showPercent // hides axis line when false\n },\n border: {\n display: !this.showPercent // Chart.js >= 4\n },\n ticks: {\n display: !this.showPercent,\n\n ...(this.yType === 'duration' &&\n !this.showPercent && {\n callback: (value: any) => formatDurationFromSeconds(value)\n })\n }\n },\n x: {\n type: this.xType,\n grid: { display: false },\n stacked: true,\n ticks: {\n maxTicksLimit: this.xMaxTicks\n },\n ...(this.xType === 'time' && {\n time: {\n unit: 'day',\n tooltipFormat: 'DDD',\n displayFormats: { day: format }\n }\n })\n }\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":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAoC,MAAM,KAAK,CAAC;AAGlE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,sDAAsD;AACtD,OAAO,KAAoB,MAAM,eAAe,CAAC;AACjD,OAAO,uBAAuB,CAAC;AAC/B,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAExD,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;AAEhC,MAAM,eAAe,GAAgC,kBAAkB,CAAC;AACxE,MAAM,cAAc,GAAG;IACrB,sCAAsC;IACtC,kBAAkB,EAAE;QAClB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,kBAAkB,EAAE;QAClB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,kBAAkB,EAAE;QAClB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,oBAAoB,EAAE;QACpB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,oBAAoB,EAAE;QACpB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,qBAAqB,EAAE;QACrB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,qBAAqB,EAAE;QACrB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,4CAA4C;IAC5C,gBAAgB,EAAE;QAChB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,oBAAoB,EAAE;QACpB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,gBAAgB,EAAE;QAChB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,kBAAkB,EAAE;QAClB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,gBAAgB,EAAE;QAChB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IAED,8CAA8C;IAC9C,kBAAkB,EAAE;QAClB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,mBAAmB,EAAE;QACnB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,oBAAoB,EAAE;QACpB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,oBAAoB,EAAE;QACpB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;KACV;IACD,iBAAiB,EAAE;QACjB,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,SAAS;QACT,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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 { darkenColor, 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';\nimport ChartDataLabels from 'chartjs-plugin-datalabels';\n\nChart.register(ChartDataLabels);\n\nconst DEFAULT_PALETTE: keyof typeof COLOR_PALETTES = 'qualitative-set1';\nconst COLOR_PALETTES = {\n // Qualitative (categorical, no order)\n 'qualitative-set1': [\n '#5ea3db',\n '#c186e3',\n '#66c2a5',\n '#fc8d62',\n '#a6d854',\n '#ffd92f',\n '#e5c494',\n '#b3b3b3'\n ],\n 'qualitative-set2': [\n '#377eb8',\n '#984ea3',\n '#4daf4a',\n '#ff7f00',\n '#e41a1c',\n '#a65628',\n '#f781bf',\n '#ffff33'\n ],\n 'qualitative-set3': [\n '#1b9e77',\n '#d95f02',\n '#7570b3',\n '#e7298a',\n '#66a61e',\n '#e6ab02',\n '#a6761d'\n ],\n 'qualitative-paired': [\n '#1f78b4',\n '#a6cee3',\n '#6a3d9a',\n '#cab2d6',\n '#33a02c',\n '#b2df8a',\n '#e31a1c',\n '#fb9a99',\n '#ff7f00',\n '#fdbf6f'\n ],\n 'qualitative-accent': [\n '#7fc97f',\n '#beaed4',\n '#fdc086',\n '#ffff99',\n '#386cb0',\n '#f0027f',\n '#bf5b17',\n '#666666'\n ],\n 'qualitative-pastel1': [\n '#fbb4ae',\n '#b3cde3',\n '#ccebc5',\n '#decbe4',\n '#fed9a6',\n '#ffffcc',\n '#e5d8bd',\n '#fddaec'\n ],\n 'qualitative-pastel2': [\n '#b3e2cd',\n '#fdcdac',\n '#cbd5e8',\n '#f4cae4',\n '#e6f5c9',\n '#fff2ae',\n '#f1e2cc'\n ],\n // Diverging (for data with midpoint like 0)\n 'diverging-prgn': [\n '#40004b',\n '#762a83',\n '#9970ab',\n '#c2a5cf',\n '#e7d4e8',\n '#f7f7f7',\n '#d9f0d3',\n '#a6dba0',\n '#5aae61',\n '#1b7837',\n '#00441b'\n ],\n 'diverging-spectral': [\n '#9e0142',\n '#d53e4f',\n '#f46d43',\n '#fdae61',\n '#fee08b',\n '#ffffbf',\n '#e6f598',\n '#abdda4',\n '#66c2a5',\n '#3288bd',\n '#5e4fa2'\n ],\n 'diverging-piyg': [\n '#8e0152',\n '#c51b7d',\n '#de77ae',\n '#f1b6da',\n '#fde0ef',\n '#f7f7f7',\n '#e6f5d0',\n '#b8e186',\n '#7fbc41',\n '#4d9221',\n '#276419'\n ],\n 'diverging-rdylgn': [\n '#a50026',\n '#d73027',\n '#f46d43',\n '#fdae61',\n '#fee08b',\n '#ffffbf',\n '#d9ef8b',\n '#a6d96a',\n '#66bd63',\n '#1a9850',\n '#006837'\n ],\n 'diverging-brbg': [\n '#543005',\n '#8c510a',\n '#bf812d',\n '#dfc27d',\n '#f6e8c3',\n '#f5f5f5',\n '#c7eae5',\n '#80cdc1',\n '#35978f',\n '#01665e',\n '#003c30'\n ],\n\n // Sequential (for continuous or ordered data)\n 'sequential-blues': [\n '#f7fbff',\n '#deebf7',\n '#c6dbef',\n '#9ecae1',\n '#6baed6',\n '#4292c6',\n '#2171b5',\n '#08519c',\n '#08306b'\n ],\n 'sequential-greens': [\n '#f7fcf5',\n '#e5f5e0',\n '#c7e9c0',\n '#a1d99b',\n '#74c476',\n '#41ab5d',\n '#238b45',\n '#006d2c',\n '#00441b'\n ],\n 'sequential-oranges': [\n '#fff5eb',\n '#fee6ce',\n '#fdd0a2',\n '#fdae6b',\n '#fd8d3c',\n '#f16913',\n '#d94801',\n '#a63603',\n '#7f2704'\n ],\n 'sequential-purples': [\n '#fcfbfd',\n '#efedf5',\n '#dadaeb',\n '#bcbddc',\n '#9e9ac8',\n '#807dba',\n '#6a51a3',\n '#54278f',\n '#3f007d'\n ],\n 'sequential-reds': [\n '#fff5f0',\n '#fee0d2',\n '#fcbba1',\n '#fc9272',\n '#fb6a4a',\n '#ef3b2c',\n '#cb181d',\n '#a50f15',\n '#67000d'\n ],\n 'sequential-ylgnbu': [\n '#ffffd9',\n '#edf8b1',\n '#c7e9b4',\n '#7fcdbb',\n '#41b6c4',\n '#1d91c0',\n '#225ea8',\n '#253494',\n '#081d58'\n ]\n};\n\nconst otherBackgroundColor = 'rgba(212, 212, 212, 0.5)';\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: String })\n xType: 'category' | 'time' = 'category';\n\n @property({ type: Number })\n xMaxTicks: number = 10;\n\n @property({ type: String })\n yType: 'count' | 'duration' = 'count';\n\n @property({ type: String })\n xFormat: 'MMM yy' | 'MMM yyyy' | 'MMM dd' | 'DD' | 'EEE' | 'auto' = 'auto';\n\n @property({ type: Number })\n maxChartHeight: number = 250;\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 showAll: boolean = false;\n\n @property({ type: Number })\n colorIndex: number = 0;\n\n @state()\n showConfig: boolean = false;\n\n @property({ type: String })\n palette: keyof typeof COLOR_PALETTES;\n\n @property({ type: Number })\n opacity: number = 1;\n\n @property({ type: Number })\n seriesBorderRadius: number = 2;\n\n @property({ type: Number })\n seriesBorderWidth: number = 1;\n\n @property({ type: Boolean, attribute: 'percent' })\n showPercent: boolean = false;\n\n // head-room for labels when percentages are visible\n private getInflatedMax(): number | undefined {\n if (!this.showPercent || !this.data) return undefined;\n\n // total stacked value for each x-index\n const totals: number[] = Array(this.data.labels.length).fill(0);\n for (const ds of this.datasets) {\n ds.data.forEach((v, i) => (totals[i] += v));\n }\n const maxStack = Math.max(...totals);\n return maxStack > 0 ? maxStack * 1.15 : undefined;\n }\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 if (changes.has('chartType')) {\n if (this.chartType === 'line') {\n this.seriesBorderWidth = Math.max(1, this.seriesBorderWidth);\n }\n }\n\n if (changes.has('showPercent') && this.chart) {\n const yScale = (this.chart.options.scales as any).y;\n yScale.ticks.display = !this.showPercent;\n yScale.grid.display = !this.showPercent;\n yScale.border.display = !this.showPercent;\n yScale.max = this.showPercent ? this.getInflatedMax() : undefined;\n this.chart.update();\n }\n }\n\n /**\n * Returns a tuple: [backgroundColors[], borderColors[]].\n * Border colors are darkened versions of the base palette (before transparency).\n * Background colors have transparency applied.\n */\n get colors(): [string[], string[]] {\n const baseColors =\n COLOR_PALETTES[this.palette] || COLOR_PALETTES[DEFAULT_PALETTE];\n // clamp transparency between 0 and 1\n const alpha = Math.max(0, Math.min(1, this.opacity));\n // borders darken base color, no transparency\n const borderColors = baseColors.map((color) => darkenColor(color, 0.25));\n // backgrounds apply transparency to base color\n const backgroundColors = baseColors.map((color) => {\n // if already rgba, just replace the alpha\n if (color.startsWith('rgba')) {\n return color.replace(\n /rgba\\(([^,]+),([^,]+),([^,]+),([^)]+)\\)/,\n (_m, r, g, b) => {\n return `rgba(${r},${g},${b},${alpha})`;\n }\n );\n }\n // if already rgb, convert to rgba\n if (color.startsWith('rgb(')) {\n return color.replace(\n /rgb\\(([^,]+),([^,]+),([^,]+)\\)/,\n (_m, r, g, b) => {\n return `rgba(${r},${g},${b},${alpha})`;\n }\n );\n }\n // if hex, convert to rgba\n if (color.startsWith('#')) {\n let hex = color.replace('#', '');\n if (hex.length === 3) {\n hex = hex\n .split('')\n .map((c) => c + c)\n .join('');\n }\n const num = parseInt(hex, 16);\n const r = (num >> 16) & 255;\n const g = (num >> 8) & 255;\n const b = num & 255;\n return `rgba(${r},${g},${b},${alpha})`;\n }\n // fallback\n return color;\n });\n return [backgroundColors, borderColors];\n }\n\n private handleResize() {\n if (this.chart) {\n // recalculate canvas size based on parent container\n const wrapper = this.shadowRoot.querySelector('#canvas-wrapper');\n if (wrapper) {\n if (wrapper.clientHeight > this.maxChartHeight) {\n this.canvas.style.height = `${this.maxChartHeight}px`;\n this.chart.resize();\n }\n }\n }\n }\n\n private calculateSplits() {\n if (this.data) {\n const datasets = [];\n const sums = [];\n const [backgroundColors, borderColors] = this.colors;\n for (const dataset of this.data.datasets) {\n if (\n !this.showAll &&\n this.splits.find((s) => s === dataset.label) === undefined\n ) {\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 const colorIdx =\n (datasets.length + this.colorIndex) % backgroundColors.length;\n const bgColor = backgroundColors[colorIdx];\n const borderColor = borderColors[colorIdx];\n datasets.push({\n ...dataset,\n backgroundColor: bgColor,\n borderColor,\n borderWidth: this.seriesBorderWidth,\n borderRadius: this.seriesBorderRadius\n });\n }\n }\n\n if (datasets.length === 0) {\n const idx = this.colorIndex % backgroundColors.length;\n datasets.push({\n label: this.single ? this.dataname : `All ${this.dataname}`,\n data: sums,\n backgroundColor: backgroundColors[idx],\n borderColor: borderColors[idx],\n borderWidth: this.seriesBorderWidth,\n borderRadius: this.seriesBorderRadius\n });\n } else {\n if (!this.hideOther && !this.showAll) {\n datasets.push({\n label: 'Other',\n data: sums,\n backgroundColor: otherBackgroundColor,\n borderColor: darkenColor(otherBackgroundColor, 0.05),\n borderWidth: 1,\n borderRadius: this.seriesBorderRadius\n });\n }\n }\n this.datasets = datasets;\n }\n }\n\n public updateChart(): void {\n if (this.datasets?.length > 0) {\n const grandTotal =\n this.datasets.reduce(\n (sum: number, ds: any) =>\n sum +\n (ds.data as number[]).reduce(\n (dsSum: number, v: number) => dsSum + (v ?? 0),\n 0\n ),\n 0\n ) || undefined;\n\n const percentFormatter = (value: number): string => {\n const pct = grandTotal ? (value / grandTotal) * 100 : 0;\n if (pct === 0) {\n return '';\n }\n return `${Math.round(pct)}%`;\n };\n\n if (this.chart) {\n this.chart.data.labels = this.data.labels;\n this.chart.data.datasets = this.datasets;\n\n // update y-axis max dynamically\n if (this.showPercent) {\n (this.chart.options.scales as any).y.max = this.getInflatedMax();\n }\n\n const datalabels = this.chart.options.plugins.datalabels || {};\n datalabels.display = this.showPercent;\n if (this.showPercent) {\n datalabels.formatter = percentFormatter;\n } else {\n delete datalabels.formatter;\n }\n this.chart.options.plugins.datalabels = datalabels;\n\n this.chart.update();\n } else {\n let format = this.xFormat;\n if (this.xType === 'time' && this.xFormat === 'auto') {\n const firstDate = this.data.labels[0];\n const lastDate = this.data.labels[this.data.labels.length - 1];\n\n const first = Date.parse(firstDate);\n const last = Date.parse(lastDate);\n\n const dayDiff = Math.ceil((last - first) / (1000 * 60 * 60 * 24));\n format = 'MMM dd';\n if (dayDiff > 365) {\n format = 'MMM yyyy';\n }\n }\n\n const chartData = {\n type: this.chartType,\n data: {\n labels: this.data.labels,\n datasets: this.datasets\n },\n options: {\n maxBarThickness: 80,\n plugins: {\n legend: { display: this.legend },\n tooltip: {\n callbacks: {\n label: (context: any) => {\n const label = context.dataset.label || '';\n const value = context.parsed.y;\n if (this.yType === 'duration') {\n return `${label}: ${formatDurationFromSeconds(value)}`;\n }\n return `${label}: ${value}`;\n }\n }\n },\n datalabels: {\n display: this.showPercent,\n anchor: 'end',\n align: 'end',\n offset: -3,\n clamp: true,\n ...(this.showPercent && { formatter: percentFormatter }),\n color: '#666',\n font: { weight: '600' }\n }\n },\n responsive: true,\n aspectRatio: 2,\n onResize: this.handleResize.bind(this),\n maintainAspectRatio: false,\n animation: false,\n animations: {\n x: {\n duration: 0\n },\n y: {\n duration: 0\n }\n },\n scales: {\n y: {\n min: 0,\n ...(this.showPercent && { max: this.getInflatedMax() }),\n stacked: true,\n grid: {\n color: 'rgba(0,0,0,0.04)',\n display: !this.showPercent, // hide gridlines in percent mode\n drawBorder: !this.showPercent // hides axis line when false\n },\n border: {\n display: !this.showPercent // Chart.js >= 4\n },\n ticks: {\n display: !this.showPercent,\n\n ...(this.yType === 'duration' &&\n !this.showPercent && {\n callback: (value: any) => formatDurationFromSeconds(value)\n })\n }\n },\n x: {\n type: this.xType,\n grid: { display: false },\n stacked: true,\n ticks: {\n maxTicksLimit: this.xMaxTicks\n },\n ...(this.xType === 'time' && {\n time: {\n unit: 'day',\n tooltipFormat: 'DDD',\n displayFormats: { day: format }\n }\n })\n }\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,13 +1,17 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { html } from 'lit-html';
3
3
  import { css, unsafeCSS } from 'lit';
4
- import { property } from 'lit/decorators.js';
4
+ import { property, state } from 'lit/decorators.js';
5
5
  import { getStore } from '../store/Store';
6
6
  import { fromStore, zustand } from '../store/AppState';
7
7
  import { RapidElement } from '../RapidElement';
8
8
  import { Plumber } from './Plumber';
9
9
  import { EditorNode } from './EditorNode';
10
+ export function snapToGrid(value) {
11
+ return Math.round(value / 20) * 20;
12
+ }
10
13
  const SAVE_QUIET_TIME = 500;
14
+ const DRAG_THRESHOLD = 10;
11
15
  export class Editor extends RapidElement {
12
16
  // unfortunately, jsplumb requires that we be in light DOM
13
17
  createRenderRoot() {
@@ -61,6 +65,15 @@ export class Editor extends RapidElement {
61
65
  margin: 20px;
62
66
  }
63
67
 
68
+ #canvas > .draggable {
69
+ position: absolute;
70
+ z-index: 100;
71
+ }
72
+
73
+ #canvas > .dragging {
74
+ z-index: 10000 !important;
75
+ }
76
+
64
77
  body .jtk-endpoint {
65
78
  width: initial;
66
79
  height: initial;
@@ -152,10 +165,20 @@ export class Editor extends RapidElement {
152
165
  super();
153
166
  // timer for debounced saving
154
167
  this.saveTimer = null;
168
+ // Drag state
169
+ this.isDragging = false;
170
+ this.isMouseDown = false;
171
+ this.dragStartPos = { x: 0, y: 0 };
172
+ this.currentDragItem = null;
173
+ this.startPos = { left: 0, top: 0 };
174
+ // Bound event handlers to maintain proper 'this' context
175
+ this.boundMouseMove = this.handleMouseMove.bind(this);
176
+ this.boundMouseUp = this.handleMouseUp.bind(this);
155
177
  }
156
178
  firstUpdated(changes) {
157
179
  super.firstUpdated(changes);
158
180
  this.plumber = new Plumber(this.querySelector('#canvas'));
181
+ this.setupGlobalEventListeners();
159
182
  if (changes.has('flow')) {
160
183
  getStore().getState().fetchRevision(`/flow/revisions/${this.flow}`);
161
184
  }
@@ -165,6 +188,9 @@ export class Editor extends RapidElement {
165
188
  if (changes.has('canvasSize')) {
166
189
  // console.log('Setting canvas size', this.canvasSize);
167
190
  }
191
+ if (changes.has('definition')) {
192
+ this.updateCanvasSize();
193
+ }
168
194
  if (changes.has('dirtyDate')) {
169
195
  if (this.dirtyDate) {
170
196
  this.debouncedSave();
@@ -199,13 +225,169 @@ export class Editor extends RapidElement {
199
225
  clearTimeout(this.saveTimer);
200
226
  this.saveTimer = null;
201
227
  }
228
+ document.removeEventListener('mousemove', this.boundMouseMove);
229
+ document.removeEventListener('mouseup', this.boundMouseUp);
230
+ }
231
+ setupGlobalEventListeners() {
232
+ document.addEventListener('mousemove', this.boundMouseMove);
233
+ document.addEventListener('mouseup', this.boundMouseUp);
234
+ }
235
+ getPosition(uuid, type) {
236
+ var _a, _b, _c;
237
+ if (type === 'node') {
238
+ return (_a = this.definition._ui.nodes[uuid]) === null || _a === void 0 ? void 0 : _a.position;
239
+ }
240
+ else {
241
+ return (_c = (_b = this.definition._ui.stickies) === null || _b === void 0 ? void 0 : _b[uuid]) === null || _c === void 0 ? void 0 : _c.position;
242
+ }
243
+ }
244
+ updatePosition(uuid, type, position) {
245
+ var _a;
246
+ if (type === 'node') {
247
+ getStore().getState().updateNodePosition(uuid, position);
248
+ }
249
+ else {
250
+ const currentSticky = (_a = this.definition._ui.stickies) === null || _a === void 0 ? void 0 : _a[uuid];
251
+ if (currentSticky) {
252
+ getStore()
253
+ .getState()
254
+ .updateStickyNote(uuid, {
255
+ ...currentSticky,
256
+ position
257
+ });
258
+ }
259
+ }
260
+ }
261
+ handleMouseDown(event) {
262
+ const element = event.currentTarget;
263
+ // Only start dragging if clicking on the element itself, not on exits or other interactive elements
264
+ const target = event.target;
265
+ if (target.classList.contains('exit') || target.closest('.exit')) {
266
+ return;
267
+ }
268
+ const uuid = element.getAttribute('uuid');
269
+ const type = element.tagName === 'TEMBA-FLOW-NODE' ? 'node' : 'sticky';
270
+ const position = this.getPosition(uuid, type);
271
+ if (!position)
272
+ return;
273
+ // Set up potential drag state, but don't start dragging yet
274
+ this.isMouseDown = true;
275
+ this.dragStartPos = { x: event.clientX, y: event.clientY };
276
+ this.startPos = { left: position.left, top: position.top };
277
+ this.currentDragItem = {
278
+ uuid,
279
+ position,
280
+ element,
281
+ type
282
+ };
283
+ event.preventDefault();
284
+ event.stopPropagation();
285
+ }
286
+ handleMouseMove(event) {
287
+ if (!this.isMouseDown || !this.currentDragItem)
288
+ return;
289
+ const deltaX = event.clientX - this.dragStartPos.x;
290
+ const deltaY = event.clientY - this.dragStartPos.y;
291
+ const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
292
+ // Only start dragging if we've moved beyond the threshold
293
+ if (!this.isDragging && distance > DRAG_THRESHOLD) {
294
+ this.isDragging = true;
295
+ // If this is a node, elevate connections
296
+ if (this.currentDragItem.type === 'node' && this.plumber) {
297
+ this.plumber.elevateNodeConnections(this.currentDragItem.uuid);
298
+ }
299
+ }
300
+ // If we're actually dragging, update positions
301
+ if (this.isDragging) {
302
+ const newLeft = this.startPos.left + deltaX;
303
+ const newTop = this.startPos.top + deltaY;
304
+ // Update the visual position during drag
305
+ this.currentDragItem.element.style.left = `${newLeft}px`;
306
+ this.currentDragItem.element.style.top = `${newTop}px`;
307
+ // Repaint connections if this is a node
308
+ if (this.currentDragItem.type === 'node' && this.plumber) {
309
+ this.plumber.repaintEverything();
310
+ }
311
+ }
312
+ }
313
+ handleMouseUp(event) {
314
+ if (!this.isMouseDown || !this.currentDragItem)
315
+ return;
316
+ // If we were actually dragging, handle the drag end
317
+ if (this.isDragging) {
318
+ // Restore normal z-index for node connections
319
+ if (this.currentDragItem.type === 'node' && this.plumber) {
320
+ this.plumber.restoreNodeConnections(this.currentDragItem.uuid);
321
+ }
322
+ const deltaX = event.clientX - this.dragStartPos.x;
323
+ const deltaY = event.clientY - this.dragStartPos.y;
324
+ const newLeft = this.startPos.left + deltaX;
325
+ const newTop = this.startPos.top + deltaY;
326
+ // Snap to 20px grid for final position
327
+ const snappedLeft = snapToGrid(newLeft);
328
+ const snappedTop = snapToGrid(newTop);
329
+ const newPosition = { left: snappedLeft, top: snappedTop };
330
+ // Update the store with the new snapped position
331
+ this.updatePosition(this.currentDragItem.uuid, this.currentDragItem.type, newPosition);
332
+ // Update canvas positions for nodes
333
+ if (this.currentDragItem.type === 'node') {
334
+ getStore()
335
+ .getState()
336
+ .updateCanvasPositions({
337
+ [this.currentDragItem.uuid]: newPosition
338
+ });
339
+ }
340
+ // Repaint connections if this is a node
341
+ if (this.currentDragItem.type === 'node' && this.plumber) {
342
+ this.plumber.repaintEverything();
343
+ }
344
+ }
345
+ // Reset all drag state
346
+ this.isDragging = false;
347
+ this.isMouseDown = false;
348
+ this.currentDragItem = null;
349
+ }
350
+ updateCanvasSize() {
351
+ var _a;
352
+ if (!this.definition)
353
+ return;
354
+ const store = getStore();
355
+ if (!store)
356
+ return;
357
+ // Calculate required canvas size based on all elements
358
+ let maxWidth = 0;
359
+ let maxHeight = 0;
360
+ // Check node positions
361
+ this.definition.nodes.forEach((node) => {
362
+ const ui = this.definition._ui.nodes[node.uuid];
363
+ if (ui && ui.position) {
364
+ const nodeElement = this.querySelector(`[id="${node.uuid}"]`);
365
+ if (nodeElement) {
366
+ const rect = nodeElement.getBoundingClientRect();
367
+ maxWidth = Math.max(maxWidth, ui.position.left + rect.width);
368
+ maxHeight = Math.max(maxHeight, ui.position.top + rect.height);
369
+ }
370
+ }
371
+ });
372
+ // Check sticky note positions
373
+ const stickies = ((_a = this.definition._ui) === null || _a === void 0 ? void 0 : _a.stickies) || {};
374
+ Object.values(stickies).forEach((sticky) => {
375
+ if (sticky.position) {
376
+ maxWidth = Math.max(maxWidth, sticky.position.left + 200); // Sticky note width
377
+ maxHeight = Math.max(maxHeight, sticky.position.top + 100); // Sticky note height
378
+ }
379
+ });
380
+ // Update canvas size in store
381
+ store.getState().expandCanvas(maxWidth, maxHeight);
202
382
  }
203
383
  render() {
384
+ var _a, _b;
204
385
  // we have to embed our own style since we are in light DOM
205
386
  const style = html `<style>
206
387
  ${unsafeCSS(Editor.styles.cssText)}
207
388
  ${unsafeCSS(EditorNode.styles.cssText)}
208
389
  </style>`;
390
+ const stickies = ((_b = (_a = this.definition) === null || _a === void 0 ? void 0 : _a._ui) === null || _b === void 0 ? void 0 : _b.stickies) || {};
209
391
  return html `${style}
210
392
  <div id="editor">
211
393
  <div
@@ -216,13 +398,34 @@ export class Editor extends RapidElement {
216
398
  <div id="canvas">
217
399
  ${this.definition
218
400
  ? this.definition.nodes.map((node) => {
401
+ var _a;
402
+ const position = this.definition._ui.nodes[node.uuid].position;
403
+ const dragging = this.isDragging && ((_a = this.currentDragItem) === null || _a === void 0 ? void 0 : _a.uuid) === node.uuid;
219
404
  return html `<temba-flow-node
405
+ class="draggable ${dragging ? 'dragging' : ''}"
406
+ @mousedown=${this.handleMouseDown.bind(this)}
407
+ uuid=${node.uuid}
408
+ style="left:${position.left}px; top:${position.top}px"
220
409
  .plumber=${this.plumber}
221
410
  .node=${node}
222
411
  .ui=${this.definition._ui.nodes[node.uuid]}
223
412
  ></temba-flow-node>`;
224
413
  })
225
414
  : html `<temba-loading></temba-loading>`}
415
+ ${Object.entries(stickies).map(([uuid, sticky]) => {
416
+ var _a;
417
+ const position = sticky.position || { left: 0, top: 0 };
418
+ const dragging = this.isDragging && ((_a = this.currentDragItem) === null || _a === void 0 ? void 0 : _a.uuid) === uuid;
419
+ return html `<temba-sticky-note
420
+ class="draggable ${dragging ? 'dragging' : ''}"
421
+ @mousedown=${this.handleMouseDown.bind(this)}
422
+ style="left:${position.left}px; top:${position.top}px; z-index: ${1000 +
423
+ position.top}"
424
+ uuid=${uuid}
425
+ .data=${sticky}
426
+ .dragging=${dragging}
427
+ ></temba-sticky-note>`;
428
+ })}
226
429
  </div>
227
430
  </div>
228
431
  </div>`;
@@ -243,4 +446,10 @@ __decorate([
243
446
  __decorate([
244
447
  fromStore(zustand, (state) => state.dirtyDate)
245
448
  ], Editor.prototype, "dirtyDate", void 0);
449
+ __decorate([
450
+ state()
451
+ ], Editor.prototype, "isDragging", void 0);
452
+ __decorate([
453
+ state()
454
+ ], Editor.prototype, "currentDragItem", void 0);
246
455
  //# sourceMappingURL=Editor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Editor.js","sourceRoot":"","sources":["../../../src/flow/Editor.ts"],"names":[],"mappings":"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","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\nconst SAVE_QUIET_TIME = 500;\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 // timer for debounced saving\n private saveTimer: number | null = null;\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 @fromStore(zustand, (state: AppState) => state.dirtyDate)\n private dirtyDate!: Date;\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: 10px 10px;\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: 600;\n }\n\n .plumb-source {\n z-index: 600;\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: 600;\n opacity: 0;\n cursor: pointer;\n }\n\n body .plumb-connector path {\n stroke: var(--color-connectors) !important;\n stroke-width: 3px;\n z-index: 10;\n }\n\n body .plumb-connector {\n z-index: 10;\n }\n\n body .plumb-connector.elevated {\n z-index: 550;\n }\n\n body .plumb-connector.elevated path {\n stroke: var(--color-connectors) !important;\n stroke-width: 3px;\n z-index: 550;\n }\n\n body .plumb-connector.elevated .plumb-arrow {\n fill: var(--color-connectors);\n stroke: var(--color-connectors);\n stroke-width: 0px;\n margin-top: 6px;\n z-index: 550;\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 z-index: 10;\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 z-index: 10;\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 if (changes.has('dirtyDate')) {\n if (this.dirtyDate) {\n this.debouncedSave();\n }\n }\n }\n\n private debouncedSave(): void {\n // Clear any existing timer\n if (this.saveTimer !== null) {\n clearTimeout(this.saveTimer);\n }\n\n this.saveTimer = window.setTimeout(() => {\n const now = new Date();\n const timeSinceLastChange = now.getTime() - this.dirtyDate.getTime();\n\n if (timeSinceLastChange >= SAVE_QUIET_TIME) {\n this.saveChanges();\n this.saveTimer = null;\n } else {\n this.debouncedSave();\n }\n }, SAVE_QUIET_TIME);\n }\n\n private saveChanges(): void {\n // post the flow definition to the server\n getStore().postJSON(`/flow/revisions/${this.flow}`, this.definition);\n getStore().getState().setDirtyDate(null);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.saveTimer !== null) {\n clearTimeout(this.saveTimer);\n this.saveTimer = null;\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":"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","sourcesContent":["import { html, TemplateResult } from 'lit-html';\nimport { css, PropertyValueMap, unsafeCSS } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { FlowDefinition, FlowPosition } 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 function snapToGrid(value: number): number {\n return Math.round(value / 20) * 20;\n}\n\nconst SAVE_QUIET_TIME = 500;\n\nexport interface DraggableItem {\n uuid: string;\n position: FlowPosition;\n element: HTMLElement;\n type: 'node' | 'sticky';\n}\n\nconst DRAG_THRESHOLD = 10;\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 // timer for debounced saving\n private saveTimer: number | null = null;\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 @fromStore(zustand, (state: AppState) => state.dirtyDate)\n private dirtyDate!: Date;\n\n // Drag state\n @state()\n private isDragging = false;\n private isMouseDown = false;\n private dragStartPos = { x: 0, y: 0 };\n\n @state()\n private currentDragItem: DraggableItem | null = null;\n private startPos = { left: 0, top: 0 };\n\n // Bound event handlers to maintain proper 'this' context\n private boundMouseMove = this.handleMouseMove.bind(this);\n private boundMouseUp = this.handleMouseUp.bind(this);\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: 10px 10px;\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 #canvas > .draggable {\n position: absolute;\n z-index: 100;\n }\n\n #canvas > .dragging {\n z-index: 10000 !important;\n }\n\n body .jtk-endpoint {\n width: initial;\n height: initial;\n }\n\n .jtk-endpoint {\n z-index: 600;\n }\n\n .plumb-source {\n z-index: 600;\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: 600;\n opacity: 0;\n cursor: pointer;\n }\n\n body .plumb-connector path {\n stroke: var(--color-connectors) !important;\n stroke-width: 3px;\n z-index: 10;\n }\n\n body .plumb-connector {\n z-index: 10;\n }\n\n body .plumb-connector.elevated {\n z-index: 550;\n }\n\n body .plumb-connector.elevated path {\n stroke: var(--color-connectors) !important;\n stroke-width: 3px;\n z-index: 550;\n }\n\n body .plumb-connector.elevated .plumb-arrow {\n fill: var(--color-connectors);\n stroke: var(--color-connectors);\n stroke-width: 0px;\n margin-top: 6px;\n z-index: 550;\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 z-index: 10;\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 z-index: 10;\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 this.setupGlobalEventListeners();\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 if (changes.has('definition')) {\n this.updateCanvasSize();\n }\n\n if (changes.has('dirtyDate')) {\n if (this.dirtyDate) {\n this.debouncedSave();\n }\n }\n }\n\n private debouncedSave(): void {\n // Clear any existing timer\n if (this.saveTimer !== null) {\n clearTimeout(this.saveTimer);\n }\n\n this.saveTimer = window.setTimeout(() => {\n const now = new Date();\n const timeSinceLastChange = now.getTime() - this.dirtyDate.getTime();\n\n if (timeSinceLastChange >= SAVE_QUIET_TIME) {\n this.saveChanges();\n this.saveTimer = null;\n } else {\n this.debouncedSave();\n }\n }, SAVE_QUIET_TIME);\n }\n\n private saveChanges(): void {\n // post the flow definition to the server\n getStore().postJSON(`/flow/revisions/${this.flow}`, this.definition);\n getStore().getState().setDirtyDate(null);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.saveTimer !== null) {\n clearTimeout(this.saveTimer);\n this.saveTimer = null;\n }\n document.removeEventListener('mousemove', this.boundMouseMove);\n document.removeEventListener('mouseup', this.boundMouseUp);\n }\n\n private setupGlobalEventListeners(): void {\n document.addEventListener('mousemove', this.boundMouseMove);\n document.addEventListener('mouseup', this.boundMouseUp);\n }\n\n private getPosition(uuid: string, type: 'node' | 'sticky'): FlowPosition {\n if (type === 'node') {\n return this.definition._ui.nodes[uuid]?.position;\n } else {\n return this.definition._ui.stickies?.[uuid]?.position;\n }\n }\n\n private updatePosition(\n uuid: string,\n type: 'node' | 'sticky',\n position: FlowPosition\n ): void {\n if (type === 'node') {\n getStore().getState().updateNodePosition(uuid, position);\n } else {\n const currentSticky = this.definition._ui.stickies?.[uuid];\n if (currentSticky) {\n getStore()\n .getState()\n .updateStickyNote(uuid, {\n ...currentSticky,\n position\n });\n }\n }\n }\n\n private handleMouseDown(event: MouseEvent): void {\n const element = event.currentTarget as HTMLElement;\n // Only start dragging if clicking on the element itself, not on exits or other interactive elements\n const target = event.target as HTMLElement;\n if (target.classList.contains('exit') || target.closest('.exit')) {\n return;\n }\n\n const uuid = element.getAttribute('uuid');\n const type = element.tagName === 'TEMBA-FLOW-NODE' ? 'node' : 'sticky';\n\n const position = this.getPosition(uuid, type);\n if (!position) return;\n\n // Set up potential drag state, but don't start dragging yet\n this.isMouseDown = true;\n this.dragStartPos = { x: event.clientX, y: event.clientY };\n this.startPos = { left: position.left, top: position.top };\n this.currentDragItem = {\n uuid,\n position,\n element,\n type\n };\n\n event.preventDefault();\n event.stopPropagation();\n }\n\n private handleMouseMove(event: MouseEvent): void {\n if (!this.isMouseDown || !this.currentDragItem) return;\n\n const deltaX = event.clientX - this.dragStartPos.x;\n const deltaY = event.clientY - this.dragStartPos.y;\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n\n // Only start dragging if we've moved beyond the threshold\n if (!this.isDragging && distance > DRAG_THRESHOLD) {\n this.isDragging = true;\n\n // If this is a node, elevate connections\n if (this.currentDragItem.type === 'node' && this.plumber) {\n this.plumber.elevateNodeConnections(this.currentDragItem.uuid);\n }\n }\n\n // If we're actually dragging, update positions\n if (this.isDragging) {\n const newLeft = this.startPos.left + deltaX;\n const newTop = this.startPos.top + deltaY;\n\n // Update the visual position during drag\n this.currentDragItem.element.style.left = `${newLeft}px`;\n this.currentDragItem.element.style.top = `${newTop}px`;\n\n // Repaint connections if this is a node\n if (this.currentDragItem.type === 'node' && this.plumber) {\n this.plumber.repaintEverything();\n }\n }\n }\n\n private handleMouseUp(event: MouseEvent): void {\n if (!this.isMouseDown || !this.currentDragItem) return;\n\n // If we were actually dragging, handle the drag end\n if (this.isDragging) {\n // Restore normal z-index for node connections\n if (this.currentDragItem.type === 'node' && this.plumber) {\n this.plumber.restoreNodeConnections(this.currentDragItem.uuid);\n }\n\n const deltaX = event.clientX - this.dragStartPos.x;\n const deltaY = event.clientY - this.dragStartPos.y;\n\n const newLeft = this.startPos.left + deltaX;\n const newTop = this.startPos.top + deltaY;\n\n // Snap to 20px grid for final position\n const snappedLeft = snapToGrid(newLeft);\n const snappedTop = snapToGrid(newTop);\n\n const newPosition = { left: snappedLeft, top: snappedTop };\n\n // Update the store with the new snapped position\n this.updatePosition(\n this.currentDragItem.uuid,\n this.currentDragItem.type,\n newPosition\n );\n\n // Update canvas positions for nodes\n if (this.currentDragItem.type === 'node') {\n getStore()\n .getState()\n .updateCanvasPositions({\n [this.currentDragItem.uuid]: newPosition\n });\n }\n\n // Repaint connections if this is a node\n if (this.currentDragItem.type === 'node' && this.plumber) {\n this.plumber.repaintEverything();\n }\n }\n\n // Reset all drag state\n this.isDragging = false;\n this.isMouseDown = false;\n this.currentDragItem = null;\n }\n\n private updateCanvasSize(): void {\n if (!this.definition) return;\n\n const store = getStore();\n if (!store) return;\n\n // Calculate required canvas size based on all elements\n let maxWidth = 0;\n let maxHeight = 0;\n\n // Check node positions\n this.definition.nodes.forEach((node) => {\n const ui = this.definition._ui.nodes[node.uuid];\n if (ui && ui.position) {\n const nodeElement = this.querySelector(`[id=\"${node.uuid}\"]`);\n if (nodeElement) {\n const rect = nodeElement.getBoundingClientRect();\n maxWidth = Math.max(maxWidth, ui.position.left + rect.width);\n maxHeight = Math.max(maxHeight, ui.position.top + rect.height);\n }\n }\n });\n\n // Check sticky note positions\n const stickies = this.definition._ui?.stickies || {};\n Object.values(stickies).forEach((sticky) => {\n if (sticky.position) {\n maxWidth = Math.max(maxWidth, sticky.position.left + 200); // Sticky note width\n maxHeight = Math.max(maxHeight, sticky.position.top + 100); // Sticky note height\n }\n });\n\n // Update canvas size in store\n store.getState().expandCanvas(maxWidth, maxHeight);\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 const stickies = this.definition?._ui?.stickies || {};\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 const position =\n this.definition._ui.nodes[node.uuid].position;\n\n const dragging =\n this.isDragging && this.currentDragItem?.uuid === node.uuid;\n\n return html`<temba-flow-node\n class=\"draggable ${dragging ? 'dragging' : ''}\"\n @mousedown=${this.handleMouseDown.bind(this)}\n uuid=${node.uuid}\n style=\"left:${position.left}px; top:${position.top}px\"\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 ${Object.entries(stickies).map(([uuid, sticky]) => {\n const position = sticky.position || { left: 0, top: 0 };\n const dragging =\n this.isDragging && this.currentDragItem?.uuid === uuid;\n return html`<temba-sticky-note\n class=\"draggable ${dragging ? 'dragging' : ''}\"\n @mousedown=${this.handleMouseDown.bind(this)}\n style=\"left:${position.left}px; top:${position.top}px; z-index: ${1000 +\n position.top}\"\n uuid=${uuid}\n .data=${sticky}\n .dragging=${dragging}\n ></temba-sticky-note>`;\n })}\n </div>\n </div>\n </div>`;\n }\n}\n"]}