@nyaruka/temba-components 0.125.0 → 0.126.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.
@@ -313,6 +313,7 @@ export class TembaChart extends RapidElement {
313
313
  this.maxSplits = 2;
314
314
  this.xType = 'category';
315
315
  this.yType = 'count';
316
+ this.xFormat = 'MMM dd';
316
317
  this.hideOther = false;
317
318
  this.splits = [];
318
319
  this.dataname = 'Counts';
@@ -565,11 +566,13 @@ export class TembaChart extends RapidElement {
565
566
  type: this.xType,
566
567
  grid: { display: false },
567
568
  stacked: true,
568
- time: {
569
- unit: 'day',
570
- tooltipFormat: 'DDD',
571
- displayFormats: { day: 'MMM dd' }
572
- }
569
+ ...(this.xType === 'time' && {
570
+ time: {
571
+ unit: 'day',
572
+ tooltipFormat: 'DDD',
573
+ displayFormats: { day: this.xFormat }
574
+ }
575
+ })
573
576
  }
574
577
  }
575
578
  }
@@ -667,6 +670,9 @@ __decorate([
667
670
  __decorate([
668
671
  property({ type: String })
669
672
  ], TembaChart.prototype, "yType", void 0);
673
+ __decorate([
674
+ property({ type: String })
675
+ ], TembaChart.prototype, "xFormat", void 0);
670
676
  __decorate([
671
677
  property({ type: Boolean })
672
678
  ], 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: String })\n yType: 'count' | 'duration' = 'count';\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 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 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 ...(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 time: {\n unit: 'day',\n tooltipFormat: 'DDD',\n displayFormats: { day: 'MMM dd' }\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: String })\n yType: 'count' | 'duration' = 'count';\n\n @property({ type: String })\n xFormat: 'MMM dd' | 'DD' | 'EEE' = 'MMM dd';\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 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 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 ...(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 ...(this.xType === 'time' && {\n time: {\n unit: 'day',\n tooltipFormat: 'DDD',\n displayFormats: { day: this.xFormat }\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"]}
@@ -7,8 +7,9 @@ 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
+ const SAVE_QUIET_TIME = 500;
10
11
  export class Editor extends RapidElement {
11
- // Unfortunately, jsplumb requires that we be in light DOM
12
+ // unfortunately, jsplumb requires that we be in light DOM
12
13
  createRenderRoot() {
13
14
  return this;
14
15
  }
@@ -22,7 +23,7 @@ export class Editor extends RapidElement {
22
23
  #grid {
23
24
  position: relative;
24
25
  background-color: #f9f9f9;
25
- background-position: 13px 13px;
26
+ background-position: 10px 10px;
26
27
  background-image: linear-gradient(
27
28
  0deg,
28
29
  transparent 24%,
@@ -66,11 +67,11 @@ export class Editor extends RapidElement {
66
67
  }
67
68
 
68
69
  .jtk-endpoint {
69
- z-index: 1;
70
+ z-index: 600;
70
71
  }
71
72
 
72
73
  .plumb-source {
73
- z-index: 300;
74
+ z-index: 600;
74
75
  border: 0px solid var(--color-connectors);
75
76
  }
76
77
 
@@ -94,7 +95,7 @@ export class Editor extends RapidElement {
94
95
 
95
96
  .plumb-target {
96
97
  margin-top: -6px;
97
- z-index: 200;
98
+ z-index: 600;
98
99
  opacity: 0;
99
100
  cursor: pointer;
100
101
  }
@@ -102,6 +103,29 @@ export class Editor extends RapidElement {
102
103
  body .plumb-connector path {
103
104
  stroke: var(--color-connectors) !important;
104
105
  stroke-width: 3px;
106
+ z-index: 10;
107
+ }
108
+
109
+ body .plumb-connector {
110
+ z-index: 10;
111
+ }
112
+
113
+ body .plumb-connector.elevated {
114
+ z-index: 550;
115
+ }
116
+
117
+ body .plumb-connector.elevated path {
118
+ stroke: var(--color-connectors) !important;
119
+ stroke-width: 3px;
120
+ z-index: 550;
121
+ }
122
+
123
+ body .plumb-connector.elevated .plumb-arrow {
124
+ fill: var(--color-connectors);
125
+ stroke: var(--color-connectors);
126
+ stroke-width: 0px;
127
+ margin-top: 6px;
128
+ z-index: 550;
105
129
  }
106
130
 
107
131
  body .plumb-connector .plumb-arrow {
@@ -109,6 +133,7 @@ export class Editor extends RapidElement {
109
133
  stroke: var(--color-connectors);
110
134
  stroke-width: 0px;
111
135
  margin-top: 6px;
136
+ z-index: 10;
112
137
  }
113
138
 
114
139
  body svg.jtk-connector.jtk-hover path {
@@ -119,11 +144,14 @@ export class Editor extends RapidElement {
119
144
  body .plumb-connector.jtk-hover .plumb-arrow {
120
145
  fill: var(--color-success) !important;
121
146
  stroke-width: 0px;
147
+ z-index: 10;
122
148
  }
123
149
  `;
124
150
  }
125
151
  constructor() {
126
152
  super();
153
+ // timer for debounced saving
154
+ this.saveTimer = null;
127
155
  }
128
156
  firstUpdated(changes) {
129
157
  super.firstUpdated(changes);
@@ -137,6 +165,40 @@ export class Editor extends RapidElement {
137
165
  if (changes.has('canvasSize')) {
138
166
  // console.log('Setting canvas size', this.canvasSize);
139
167
  }
168
+ if (changes.has('dirtyDate')) {
169
+ if (this.dirtyDate) {
170
+ this.debouncedSave();
171
+ }
172
+ }
173
+ }
174
+ debouncedSave() {
175
+ // Clear any existing timer
176
+ if (this.saveTimer !== null) {
177
+ clearTimeout(this.saveTimer);
178
+ }
179
+ this.saveTimer = window.setTimeout(() => {
180
+ const now = new Date();
181
+ const timeSinceLastChange = now.getTime() - this.dirtyDate.getTime();
182
+ if (timeSinceLastChange >= SAVE_QUIET_TIME) {
183
+ this.saveChanges();
184
+ this.saveTimer = null;
185
+ }
186
+ else {
187
+ this.debouncedSave();
188
+ }
189
+ }, SAVE_QUIET_TIME);
190
+ }
191
+ saveChanges() {
192
+ // post the flow definition to the server
193
+ getStore().postJSON(`/flow/revisions/${this.flow}`, this.definition);
194
+ getStore().getState().setDirtyDate(null);
195
+ }
196
+ disconnectedCallback() {
197
+ super.disconnectedCallback();
198
+ if (this.saveTimer !== null) {
199
+ clearTimeout(this.saveTimer);
200
+ this.saveTimer = null;
201
+ }
140
202
  }
141
203
  render() {
142
204
  // we have to embed our own style since we are in light DOM
@@ -178,4 +240,7 @@ __decorate([
178
240
  __decorate([
179
241
  fromStore(zustand, (state) => state.canvasSize)
180
242
  ], Editor.prototype, "canvasSize", void 0);
243
+ __decorate([
244
+ fromStore(zustand, (state) => state.dirtyDate)
245
+ ], Editor.prototype, "dirtyDate", void 0);
181
246
  //# sourceMappingURL=Editor.js.map
@@ -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,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"]}
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,14 +1,30 @@
1
1
  import { __decorate } from "tslib";
2
2
  import { css, html } from 'lit';
3
3
  import { EDITOR_CONFIG } from './config';
4
- import { state } from 'lit/decorators.js';
4
+ import { property } from 'lit/decorators.js';
5
5
  import { RapidElement } from '../RapidElement';
6
6
  import { getClasses } from '../utils';
7
7
  import { getStore } from '../store/Store';
8
8
  export class EditorNode extends RapidElement {
9
+ constructor() {
10
+ super(...arguments);
11
+ // Drag state properties
12
+ this.isDragging = false;
13
+ this.dragStartPos = { x: 0, y: 0 };
14
+ this.nodeStartPos = { left: 0, top: 0 };
15
+ // Bound event handlers to maintain proper 'this' context
16
+ this.boundMouseMove = this.handleMouseMove.bind(this);
17
+ this.boundMouseUp = this.handleMouseUp.bind(this);
18
+ }
9
19
  createRenderRoot() {
10
20
  return this;
11
21
  }
22
+ /**
23
+ * Snaps a coordinate value to the nearest 20px grid position
24
+ */
25
+ snapToGrid(value) {
26
+ return Math.round(value / 20) * 20;
27
+ }
12
28
  static get styles() {
13
29
  return css `
14
30
  .node {
@@ -19,6 +35,19 @@ export class EditorNode extends RapidElement {
19
35
  border-radius: calc(var(--curvature) * 1.5);
20
36
  overflow: hidden;
21
37
  color: #333;
38
+ cursor: move;
39
+ user-select: none;
40
+ z-index: 500;
41
+ }
42
+
43
+ .node:hover {
44
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
45
+ }
46
+
47
+ .node.dragging {
48
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.4);
49
+ transform: scale(1.02);
50
+ z-index: 1000;
22
51
  }
23
52
 
24
53
  .action {
@@ -109,7 +138,110 @@ export class EditorNode extends RapidElement {
109
138
  getStore()
110
139
  .getState()
111
140
  .expandCanvas(this.ui.position.left + rect.width, this.ui.position.top + rect.height);
141
+ // Add drag event listeners to the node
142
+ this.addDragEventListeners();
143
+ }
144
+ }
145
+ addDragEventListeners() {
146
+ const nodeElement = this.querySelector('.node');
147
+ if (!nodeElement)
148
+ return;
149
+ nodeElement.addEventListener('mousedown', this.handleMouseDown.bind(this));
150
+ document.addEventListener('mousemove', this.boundMouseMove);
151
+ document.addEventListener('mouseup', this.boundMouseUp);
152
+ }
153
+ handleMouseDown(event) {
154
+ // Only start dragging if clicking on the node itself, not on exits or other interactive elements
155
+ const target = event.target;
156
+ if (target.classList.contains('exit') || target.closest('.exit')) {
157
+ return;
158
+ }
159
+ this.isDragging = true;
160
+ this.dragStartPos = { x: event.clientX, y: event.clientY };
161
+ this.nodeStartPos = {
162
+ left: this.ui.position.left,
163
+ top: this.ui.position.top
164
+ };
165
+ // Add dragging class for visual feedback
166
+ const nodeElement = this.querySelector('.node');
167
+ if (nodeElement) {
168
+ nodeElement.classList.add('dragging');
169
+ }
170
+ // Elevate connections for this node during dragging
171
+ if (this.plumber) {
172
+ this.plumber.elevateNodeConnections(this.node.uuid);
112
173
  }
174
+ event.preventDefault();
175
+ event.stopPropagation();
176
+ }
177
+ handleMouseMove(event) {
178
+ if (!this.isDragging)
179
+ return;
180
+ const deltaX = event.clientX - this.dragStartPos.x;
181
+ const deltaY = event.clientY - this.dragStartPos.y;
182
+ const newLeft = this.nodeStartPos.left + deltaX;
183
+ const newTop = this.nodeStartPos.top + deltaY;
184
+ // Snap to 20px grid
185
+ const snappedLeft = this.snapToGrid(newLeft);
186
+ const snappedTop = this.snapToGrid(newTop);
187
+ // Update the UI position temporarily (for visual feedback)
188
+ const nodeElement = this.querySelector('.node');
189
+ if (nodeElement) {
190
+ nodeElement.style.left = `${snappedLeft}px`;
191
+ nodeElement.style.top = `${snappedTop}px`;
192
+ }
193
+ // Repaint connections during dragging for smooth updates
194
+ if (this.plumber) {
195
+ this.plumber.repaintEverything();
196
+ }
197
+ }
198
+ handleMouseUp(event) {
199
+ if (!this.isDragging)
200
+ return;
201
+ this.isDragging = false;
202
+ // Remove dragging class
203
+ const nodeElement = this.querySelector('.node');
204
+ if (nodeElement) {
205
+ nodeElement.classList.remove('dragging');
206
+ }
207
+ // Restore normal z-index for connections
208
+ if (this.plumber) {
209
+ this.plumber.restoreNodeConnections(this.node.uuid);
210
+ }
211
+ const deltaX = event.clientX - this.dragStartPos.x;
212
+ const deltaY = event.clientY - this.dragStartPos.y;
213
+ const newLeft = this.nodeStartPos.left + deltaX;
214
+ const newTop = this.nodeStartPos.top + deltaY;
215
+ // Snap to 20px grid for final position
216
+ const snappedLeft = this.snapToGrid(newLeft);
217
+ const snappedTop = this.snapToGrid(newTop);
218
+ // Update the store with the new snapped position
219
+ const newPosition = { left: snappedLeft, top: snappedTop };
220
+ getStore()
221
+ .getState()
222
+ .updateCanvasPositions({
223
+ [this.node.uuid]: newPosition
224
+ });
225
+ // Repaint connections if plumber is available
226
+ if (this.plumber) {
227
+ this.plumber.repaintEverything();
228
+ }
229
+ getStore().getState().updateNodePosition(this.node.uuid, newPosition);
230
+ // Fire a custom event with the new coordinates
231
+ /*this.fireCustomEvent(CustomEventType.Moved, {
232
+ nodeId: this.node.uuid,
233
+ position: newPosition,
234
+ oldPosition: {
235
+ left: this.nodeStartPos.left,
236
+ top: this.nodeStartPos.top
237
+ }
238
+ });*/
239
+ }
240
+ disconnectedCallback() {
241
+ super.disconnectedCallback();
242
+ // Clean up event listeners
243
+ document.removeEventListener('mousemove', this.boundMouseMove);
244
+ document.removeEventListener('mouseup', this.boundMouseUp);
113
245
  }
114
246
  renderTitle(config) {
115
247
  return html `<div class="title" style="background:${config.color}">
@@ -167,6 +299,9 @@ export class EditorNode extends RapidElement {
167
299
  ></div>`;
168
300
  }
169
301
  render() {
302
+ if (!this.node || !this.ui) {
303
+ return html `<div class="node">Loading...</div>`;
304
+ }
170
305
  return html `
171
306
  <div
172
307
  id="${this.node.uuid}"
@@ -189,12 +324,12 @@ export class EditorNode extends RapidElement {
189
324
  }
190
325
  }
191
326
  __decorate([
192
- state()
327
+ property({ type: Object })
193
328
  ], EditorNode.prototype, "plumber", void 0);
194
329
  __decorate([
195
- state()
330
+ property({ type: Object })
196
331
  ], EditorNode.prototype, "node", void 0);
197
332
  __decorate([
198
- state()
333
+ property({ type: Object })
199
334
  ], EditorNode.prototype, "ui", void 0);
200
335
  //# sourceMappingURL=EditorNode.js.map