diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 24a68c31..98f51f9d 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,6 +9,14 @@ assignees: '' **Describe the bug** A clear and concise description of what the bug is. +Important: Are you using the component directly or through the universal component? +For example: + +```html + + + +``` **To Reproduce** Steps to reproduce the behavior: diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 4167aa06..bfcb29d1 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,8 +2,9 @@ name: Feature request about: Suggest an idea for this project title: "[FEATURE REQUEST]" -labels: "" -assignees: "" +labels: '' +assignees: '' + --- **Is your feature request related to a problem? Please describe.** diff --git a/README.md b/README.md index 6a917b61..1446818c 100755 --- a/README.md +++ b/README.md @@ -1,13 +1,14 @@


- + +

# vue-data-ui [![npm](https://img.shields.io/npm/v/vue-data-ui)](https://github.com/graphieros/vue-data-ui) -[![Static Badge](https://img.shields.io/badge/components-60-blue)](https://github.com/graphieros/vue-data-ui) +[![Static Badge](https://img.shields.io/badge/components-63-blue)](https://github.com/graphieros/vue-data-ui) [![GitHub issues](https://img.shields.io/github/issues/graphieros/vue-data-ui)](https://github.com/graphieros/vue-data-ui/issues) [![License](https://img.shields.io/badge/license-MIT-green)](https://github.com/graphieros/vue-data-ui?tab=MIT-1-ov-file#readme) [![MadeWithVueJs.com shield](https://madewithvuejs.com/storage/repo-shields/4526-shield.svg)](https://madewithvuejs.com/p/vue-data-ui/shield-link) @@ -24,6 +25,7 @@ Available components - [VueUiAgePyramid](https://vue-data-ui.graphieros.com/docs#vue-ui-age-pyramid) - [VueUiCandlestick](https://vue-data-ui.graphieros.com/docs#vue-ui-candlestick) - [VueUiChestnut](https://vue-data-ui.graphieros.com/docs#vue-ui-chestnut) +- [VueUiChord](https://vue-data-ui.graphieros.com/docs#vue-ui-chord) - [VueUiCirclePack](https://vue-data-ui.graphieros.com/docs#vue-ui-circle-pack) - [VueUiDonutEvolution](https://vue-data-ui.graphieros.com/docs#vue-ui-donut-evolution) - [VueUiDonut](https://vue-data-ui.graphieros.com/docs#vue-ui-donut) @@ -43,6 +45,7 @@ Available components - [VueUiQuickChart](https://vue-data-ui.graphieros.com/docs#vue-ui-quick-chart) - [VueUiRadar](https://vue-data-ui.graphieros.com/docs#vue-ui-radar) - [VueUiRelationCircle](https://vue-data-ui.graphieros.com/docs#vue-ui-relation-circle) +- [VueUiRidgeline](https://vue-data-ui.graphieros.com/docs#vue-ui-ridgeline) - [VueUiRings](https://vue-data-ui.graphieros.com/docs#vue-ui-rings) - [VueUiScatter](https://vue-data-ui.graphieros.com/docs#vue-ui-scatter) - [VueUiStackbar](https://vue-data-ui.graphieros.com/docs#vue-ui-stackbar) @@ -84,6 +87,10 @@ Available components - [VueUiRating](https://vue-data-ui.graphieros.com/docs#vue-ui-rating) - [VueUiSmiley](https://vue-data-ui.graphieros.com/docs#vue-ui-smiley) +## Maps + +- [VueUiWorld](https://vue-data-ui.graphieros.com/docs#vue-ui-world) + ## Utilities - [VueUiAccordion](https://vue-data-ui.graphieros.com/docs#vue-ui-accordion) @@ -283,6 +290,7 @@ The following charts bear these slots: - VueUiXy \* - VueUiXyCanvas - VueUiwaffle +- VueUiWorld \* VueUiXy slots specifically expose the following additional attributes: @@ -422,16 +430,17 @@ From the dataset you pass into the props, this component will produce the most a | ----------------------------- | ------------------------------------------ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ------ | | `VueUiAgePyramid` | `Array>` | `VueUiSparklineConfig` | `generatePdf`, `generateImage`, `generateCsv`, `toggleTable`, `toggleTooltip` | `#svg`, `#legend`, `#tooltip-before`, `#tooltip-after`, `#watermark`, `#chart-background` | ✅ | ✅ | | `VueUiCandlestick` | `Array>` | `VueUiCandlestickConfig` | `generatePdf`, `generateImage`, `generateCsv`, `toggleTable`, `toggleTooltip` | `#svg`, `#legend`, `#tooltip-before`, `#tooltip-after`, `#reset-action`, `#watermark`, `#chart-background` | ✅ | ✅ | -| `VueUiCirclePack` | `VueUiCirclePackDatasetItem[]` | `VueUiCirclePackConfig` | `@selectDatapoint`, `getData`, `generatePdf`, `generateImage`, `generateCsv`, `toggleTable` | `#svg`, `#legend`, `#watermark`, `#chart-background` , `#pattern`, `#zoom-label`, `#data-label` | ✅ | ✅ | | `VueUiChestnut` | `VueUiChestnutDatasetRoot[]` | `VueUiChestnutConfig` | `@selectRoot`, `@selectBranch`, `@selectNut`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable` | `#svg`, `#legend`, `#watermark`, `#chart-background` | ❌ | ✅ | +| `VueUiChord` | `VueUiChordDataset` | `VueUiChordConfig` | `@selectLegend`, `@selectGroup`, `@selectRibbon`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable` | `#svg`, `#legend`, `#watermark`, `#chart-background`, `#pattern` | ❌ | ✅ | +| `VueUiCirclePack` | `VueUiCirclePackDatasetItem[]` | `VueUiCirclePackConfig` | `@selectDatapoint`, `getData`, `generatePdf`, `generateImage`, `generateCsv`, `toggleTable` | `#svg`, `#legend`, `#watermark`, `#chart-background` , `#pattern`, `#zoom-label`, `#data-label` | ✅ | ✅ | | `VueUiDonutEvolution` | `VueUiDonutEvolutionDatasetItem[]` | `VueUiDonutEvolutionConfig` | `@selectLegend`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable` | `#svg`, `#legend`, `#reset-action`, `#watermark`, `#chart-background` | ❌ | ✅ | | `VueUiDonut` | `VueUiDonutDatasetItem[]` | `VueUiDonutConfig` | `@selectDatapoint`, `@selectLegend`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleLabels`, `toggleTooltip` | `#svg`, `#legend`, `#dataLabel`, `#tooltip-before`, `#tooltip-after`, `#plot-comment`, `#watermark`, `#chart-background`, `#pattern` | ✅ | ✅ | | `VueUiDumbbell` | `VueUiDumbbellDataset[]` | `VueUiDumbbellConfig` | `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable` | `#svg`, `#legend`, `#watermark`, `#chart-background` | ❌ | ✅ | -| `VueUiFlow` | `VueUiFlowDatasetItem[]` | `VueUiFlowConfig` | `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable` | `#svg`, `#watermark`, `#chart-background` | ❌ | ✅ | +| `VueUiFlow` | `VueUiFlowDatasetItem[]` | `VueUiFlowConfig` | `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleTooltip` | `#svg`, `#legend`, `#watermark`, `#chart-background`, `#tooltip-before`, `#tooltip-after`, | ✅ | ✅ | | `VueUiFunnel` | `VueUiFunnelDatasetItem[]` | `VueUiFunnelConfig` | `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable` | `#svg`, `#watermark`, `#chart-background` | ❌ | ✅ | | `VueUiGalaxy` | `VueUiGalaxyDatasetItem[]` | `VueUiGalaxyConfig` | `@selectDatapoint`, `@selectLegend`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleTooltip` | `#svg`, `#legend`,`#tooltip-before`, `#tooltip-after`, `#chart-background` | ✅ | ✅ | | `VueUiGauge` | `VueUiGaugeDataset` | `VueUiGaugeConfig` | `generatePdf`, `generateImage` | `#svg`, `#legend`, `#watermark`, `#chart-background`, `#pattern` | ❌ | ✅ | -| `VueUiHeatmap` | `VueUiHeatmapDatasetItem[]` | `VueUiHeatmapConfig` | `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleTooltip` | `#svg`, `#tooltip-before`, `#tooltip-after`, `#watermark`, `#chart-background` | ✅ | ✅ | +| `VueUiHeatmap` | `VueUiHeatmapDatasetItem[]` | `VueUiHeatmapConfig` | `@selectDatapoint`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleTooltip` | `#svg`, `#tooltip-before`, `#tooltip-after`, `#watermark`, `#chart-background` | ✅ | ✅ | | `VueUiHistoryPlot` | `VueUiHistoryPlotDatasetItem[]` | `VueUiHistoryPlotConfig` | `@selectDatapoint`, `@selectLegend`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleTooltip` | `#svg`, `#legend`, `#tooltip-before`, `#tooltip-after`, `#watermark`, `#chart-background` | ✅ | ✅ | | `VueUiMolecule` | `VueUiMoleculeDatasetNode[]` | `VueUiMoleculeConfig` | `@selectNode`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleLabels`, `toggleTooltip` | `#node`, `#svg`, `#tooltip-before`, `#tooltip-after`, `#watermark`, `#chart-background` | ✅ | ✅ | | `VueUiMoodRadar` | `VueUiMoodRadarDataset` | `VueUiMoodRadarConfig` | `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable` | `#svg`, `#legend`, `#watermark`, `#chart-background` | ❌ | ✅ | @@ -440,6 +449,7 @@ From the dataset you pass into the props, this component will produce the most a | `VueUiParallelCoordinatePlot` | `VueUiParallelCoordinatePlotDatasetItem[]` | `VueUiParallelCoordinatePlotConfig` | `@selectLegend`, `@selectDatapoint`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleLabels`, `toggleTooltip` | `#svg`, `#legend`, `#tooltip-before`, `#tooltip-after`, `#plot-comment`, `#watermark`, `#chart-background` | ✅ | ✅ | | `VueUiQuadrant` | `VueUiQuadrantDatasetItem[]` | `VueUiQuadrantConfig` | `@selectLegend`, `@selectPlot`, `@selectSide`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleLabels`, `toggleTooltip` | `#svg`, `#legend`, `#tooltip-before`, `#tooltip-after`, `#watermark`, `#chart-background` | ✅ | ✅ | | `VueUiRadar` | `VueUiRadarDataset` | `VueUiRadarConfig` | `@selectLegend`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleTooltip` | `#svg`, `#legend`, `#tooltip-before`, `#tooltip-after`, `#watermark`, `#chart-background` | ✅ | ✅ | +| `VueUiRidgeline` | `VueUiRidgelineDatasetItem[]` | `VueUiRidgelineConfig` | `@selectLegend`, `@selectX`, `@selectDatapoint`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable` | `#svg`, `#legend`, `#time-label`,`#watermark`, `#chart-background`, `#pattern` | ❌ | ✅ | | `VueUiRings` | `VueUiRingsDatasetItem[]` | `VueUiRingsConfig` | `@selectLegend`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleTooltip` | `#svg`, `#legend`, `#tooltip-before`, `#tooltip-after`, `#watermark`, `#chart-background`, `#pattern` | ✅ | ✅ | | `VueUiScatter` | `VueUiScatterDatasetItem[]` | `VueUiScatterConfig` | `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleTooltip` | `#svg`, `#legend`, `#tooltip-before`, `#tooltip-after`, `#watermark`, `#chart-background` | ✅ | ✅ | | `VueUiStackbar` | `VueUiStackbarDatasetItem[]` | `VueUiStackbarConfig` | `@selectLegend`, `@selectDatapoint`, `@selectTimeLabel`, `getData`, `generatePdf`, `generateCsv`, `generateImage`, `toggleTable`, `toggleLabels`, `toggleTooltip` | `#svg`, `#legend`, `#time-label`, `#tooltip-before`, `#tooltip-after`, `#reset-action`, `#watermark`, `#chart-background`, `#pattern` | ✅ | ✅ | @@ -460,6 +470,12 @@ From the dataset you pass into the props, this component will produce the most a | ------------ | ------------------- | ------------------ | --------------------------------------------- | ----------------------------------------- | -------------- | ------ | | `VueUi3dBar` | `VueUi3dBarDataset` | `VueUi3dBarConfig` | `generatePdf`, `generateImage`, `toggleTable` | `#svg`, `#watermark`, `#chart-background` | ❌ | ✅ | +### Maps + +| Name | dataset type | config type | emits / exposed methods | slots | custom tooltip | themes | +| ------------ | ------------------- | ------------------ | -------------------------------------------------------------------------------------------- | ----------------------------------------------------- | -------------- | ------ | +| `VueUiWorld` | `VueUiWorldDataset` | `VueUiWorldConfig` | `getData`, `generatePdf`, `generateImage`, `toggleTable`, `toggleTooltip`, `toggleAnnotator` | `#svg`, `#watermark`, `#pattern`, `#chart-background` | ✅ | ❌ | + ### Data tables | Name | dataset type | config type | emits / exposed methods | slots | themes | @@ -483,7 +499,7 @@ From the dataset you pass into the props, this component will produce the most a | `VueUiAccordion` | ❌ | `VueUiAccordionConfig` | ❌ | `#arrow`, `#title`, `#content` | | `VueUiAnnotator` | `VueUiAnnotatorDataset` | `VueUiAnnotatorConfig` | `@toggleOpenState`, `@saveAnnotations` | ❌ | | `VueUiCursor` | ❌ | `VueUiCursorConfig` | ❌ | ❌ | -| `VueUiDashboard` | `VueUiDashboardElement[]` | `VueUiDashboardConfig` | `@change` | `#content` | +| `VueUiDashboard` | `VueUiDashboardElement[]` | `VueUiDashboardConfig` | `@change` | `#content`, `#top`, `#bottom` | | `VueUiDigits` | `number` | `VueUiDigitsConfig` | ❌ | ❌ | | `VueUiKpi` | `number` | `VueUiKpiConfig` | ❌ | `#title`, `#value`, `#comment-before`, `#comment-after` | | `VueUiMiniLoader` | ❌ | `VueUiMiniLoaderConfig` | ❌ | ❌ | @@ -560,6 +576,27 @@ What happens when the button is clicked is taken care of by the component, excep ``` +You can pass a callback trhough the config, for each button, to override the default behavior: + +```ts +const config = { + userOptions: { + callbacks: { + pdf: (chartElement: HTMLElement) => { + console.log(chartElement); + }, + img: (base64: string) => { + console.log(base64); + }, + csv: (csvStr: string) => { + console.log(csvStr); + }, + // the other atributes also have the same names as the buttons + }, + }, +}; +``` + User options actions available per chart: | Chart name | User options actions slot names | @@ -570,11 +607,12 @@ User options actions available per chart: | VueUiCandlestick | optionTooltip, optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiCarouselTable | optionPdf, optionImg, optionCsv, optionAnimation, optionFullscreen | | VueUiChestnut | optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | +| VueUiChord | optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiCirclePack | optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiDonut | optionTooltip, optionPdf, optionImg, optionCsv, optionTable, optionLabels, optionFullscreen, optionAnnotator | | VueUiDonutEvolution | optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiDumbbell | optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | -| VueUiFlow | optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | +| VueUiFlow | optionTooltip, optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiFunnel | optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiGalaxy | optionTooltip, optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiGauge | optionPdf, optionImg, optionFullscreen, optionAnnotator | @@ -589,6 +627,7 @@ User options actions available per chart: | VueUiQuickChart | optionTooltip, optionPdf, optionImg, optionFullscreen, optionAnnotator | | VueUiRadar | optionTooltip, optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiRelationCircle | optionPdf, optionImg, optionFullscreen, optionAnnotator | +| VueUiRidgeline | optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiRings | optionTooltip, optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiScatter | optionTooltip, optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiSparkHistogram | (no user options menu) | @@ -608,6 +647,7 @@ User options actions available per chart: | VueUiWaffle | optionTooltip, optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiWheel | optionPdf, optionImg, optionFullscreen, optionAnnotator | | VueUiWordCloud | optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | +| VueUiWorld | optionTooltip, optionPdf, optionImg, optionCsv, optionTable, optionFullscreen, optionAnnotator | | VueUiXy | optionTooltip, optionPdf, optionImg, optionCsv, optionTable, optionLabels, optionFullscreen, optionStack, optionAnnotator | | VueUiXyCanvas | optionTooltip, optionPdf, optionImg, optionCsv, optionTable, optionLabels, optionFullscreen, optionStack, optionAnnotator | @@ -625,6 +665,7 @@ It is possible to provide a custom palette in the config prop through config.cus - VueUi3dBar - VueUiChestnut +- VueUiChord - VueUiCirclePack - VueUiDonut - VueUiDonutEvolution @@ -640,6 +681,7 @@ It is possible to provide a custom palette in the config prop through config.cus - VueUiQuickChart - VueUiRadar - VueUiRelationCircle +- VueUiRidgeline - VueUiRings - VueUiScatter - VueUiSparkStackbar @@ -652,6 +694,7 @@ It is possible to provide a custom palette in the config prop through config.cus - VueUiVerticalBar - VueUiWaffle - VueUiWordCloud +- VueUiWorld - VueUiXy - VueUiXyCanvas @@ -671,6 +714,7 @@ However the folowing charts can be made fully responsive, making them better to | VueUiBullet | - | | VueUiCarouselTable | - | | VueUiChestnut | - | +| VueUiChord | ✅ | | VueUiCirclePack | - | | VueUiDonut | ✅ | | VueUiDonutEvolution | - | @@ -690,6 +734,7 @@ However the folowing charts can be made fully responsive, making them better to | VueUiQuickChart | ✅ | | VueUiRadar | ✅ | | VueUiRelationCircle | ✅ | +| VueUiRidgeline | ✅ | | VueUiRings | ✅ | | VueUiScatter | ✅ | | VueUiSparkHistogram | - | @@ -710,6 +755,7 @@ However the folowing charts can be made fully responsive, making them better to | VueUiWaffle | ✅ | | VueUiWheel | ✅ | | VueUiWordCloud | ✅ | +| VueUiWorld | - | | VueUiXy | ✅ | | VueUiXyCanvas | ✅ | @@ -805,13 +851,16 @@ A pattern element must be used inside this slot. It will be injected inside a de The #pattern slot is available on the following components: +- VueUiChord - VueUiCirclePack - VueUiDonut - VueUiGauge +- VueUiRidgeline - VueUiRings - VueUiStackbar - VueUiVerticalBar - VueUiWaffle +- VueUiWorld - VueUiXy A set of 12 readymade patterns are available through the VueUiPattern component: @@ -866,6 +915,8 @@ import { lightenColor, shiftColorHue, createTSpans, + getCumulativeAverage, + getCumulativeMedian, } from "vue-data-ui"; ``` @@ -936,3 +987,95 @@ const textContent = createTSpans({ v-html="textContent" /> ``` + +### getCumulativeAverage + +```js +import { getCumulativeAverage } from "vue-data-ui"; + +// simple usage +const arr = [0, 1, 2, 3, 4]; +const cumulativeAvg = getCumulativeAverage({ values: arr }); + +// Ignore invalid values entirely +const arrWithInvalid = [1, null, 2, Infinity, NaN, undefined]; +const cumulativeAvgNoInvalid = getCumulativeAverage({ + values: arrWithInvalid, + config: { + keepInvalid: false, + }, +}); + +// Convert invalid values to zero +const cumulativeAvgZeroed = getCumulativeAverage({ + values: arrWithInvalid, + config: { + convertInvalidToZero: true, + }, +}); +``` + +### getCumulativeMedian + +```js +import { getCumulativeMedian } from "vue-data-ui"; + +// simple usage +const arr = [0, 1, 2, 3, 4]; +const cumulativeMed = getCumulativeMedian({ values: arr }); + +// Ignore invalid values entirely +const arrWithInvalid = [1, null, 2, Infinity, NaN, undefined]; +const cumulativeMedNoInvalid = getCumulativeMedian({ + values: arrWithInvalid, + config: { + keepInvalid: false, + }, +}); + +// Convert invalid values to zero +const cumulativeMedZeroed = getCumulativeMedian({ + values: arrWithInvalid, + config: { + convertInvalidToZero: true, + }, +}); +``` + +### mergeConfigs + +```js +import { mergeConfigs, getVueDataUiConfig } from "vue-data-ui"; +const defaultConfig = getVueDataUiConfig("vue_ui_xy"); + +// Create a full config with user overrides +const merged = mergeConfigs({ + defaultConfig, + userConfig: { + chart: { + backgroundColor: "#FF0000", + }, + }, +}); +``` + +## Multiline data labels + +Some components will display labels on mutliple lines when the provided text contains a line break. (example: "I contain\na line break"). +Below is a table of the places where such line breaks can be used: + +| Component | Label displayed | Where to use line breaks | +| --------------------------- | -------------------- | ------------------------------------------------------ | +| VueUiXy | Time labels (x axis) | config.chart.grid.labels.xAxisLabels.values | +| VueUiDonutEvolution | Time labels (x axis) | config.style.chart.layout.grid.xAxis.dataLabels.values | +| VueUiHistoryPlot | Plot labels | dataset names | +| VueUiParallelCoordinatePlot | Axis labels | config.style.chart.yAxis.labels.axisNames | +| VueUiQuadrant | Plot labels | dataset names | +| VueUiQuickChart | Time labels (x axis) | config.xyPeriods | +| VueUiRidgeline | Time labels (x axis) | config.style.chart.xAxis.labels.values | +| VueUiStackbar | Time labels (x axis) | config.style.chart.grid.x.timeLabels.values | +| VueUiStripPlot | x axis labels | dataset names | + +## PDF generation + +This package requires jspdf as a peer dependency. Please install it in your project if you intend on using the PDF printing feature. diff --git a/TestingArena/ArenaVueUi3dBar.vue b/TestingArena/ArenaVueUi3dBar.vue index 92afa53c..a4c72f53 100644 --- a/TestingArena/ArenaVueUi3dBar.vue +++ b/TestingArena/ArenaVueUi3dBar.vue @@ -177,7 +177,7 @@ const config = computed(() => { dataLabel: { ...c.style.chart.dataLabel, formatter: ({value, config}) => { - // console.log(config) + console.log(config) return `f | ${value}` } } diff --git a/TestingArena/ArenaVueUiCandlestick.vue b/TestingArena/ArenaVueUiCandlestick.vue index a68f4569..5522a63e 100644 --- a/TestingArena/ArenaVueUiCandlestick.vue +++ b/TestingArena/ArenaVueUiCandlestick.vue @@ -60,6 +60,7 @@ function alterDataset() { const model = ref([ { key: 'responsive', def: false, type: 'checkbox'}, + { key: 'responsiveProportionalSizing', def: false, type: 'checkbox'}, { key: 'userOptions.show', def: true, type: 'checkbox'}, { key: 'userOptions.buttons.pdf', def: true, type: 'checkbox'}, { key: 'userOptions.buttons.csv', def: true, type: 'checkbox'}, diff --git a/TestingArena/ArenaVueUiChord.vue b/TestingArena/ArenaVueUiChord.vue new file mode 100644 index 00000000..282273d2 --- /dev/null +++ b/TestingArena/ArenaVueUiChord.vue @@ -0,0 +1,171 @@ + + + \ No newline at end of file diff --git a/TestingArena/ArenaVueUiDonut.vue b/TestingArena/ArenaVueUiDonut.vue index e2c3b283..79b875bf 100644 --- a/TestingArena/ArenaVueUiDonut.vue +++ b/TestingArena/ArenaVueUiDonut.vue @@ -9,31 +9,31 @@ import LocalPattern from "../src/atoms/vue-ui-pattern.vue"; const dataset = ref([ { name: 'Serie 1', - values: [100], + values: [1], comment: 'This is a comment' }, { name: 'Serie 2', - values: [50] + values: [0] }, { name: 'Serie 3', - values: [25], + values: [0], comment: "This is another comment that is quite long to see how it fits on the chart and to see if it's nit overflowing." }, - { - name: 'Serie 4', - values: [12.5] - }, - { - name: 'Serie 5', - values: [6.125] - }, - { - name: 'Serie 6', - values: [25], - comment: 'Some other comment' - }, + // { + // name: 'Serie 4', + // values: [12.5] + // }, + // { + // name: 'Serie 5', + // values: [6.125] + // }, + // { + // name: 'Serie 6', + // values: [25], + // comment: 'Some other comment' + // }, ]); const alternateDataset = ref([ @@ -67,6 +67,15 @@ function alterDataset() { const model = ref([ { key: 'type', def: 'classic', type: 'select', options: ['classic', 'polar']}, + { key: 'style.chart.width', def: 512, type: 'number', min: 0, max: 512 }, + { key: 'style.chart.height', def: 512, type: 'number', min: 0, max: 512 }, + + { key: 'serieToggleAnimation.show', def: true, type: 'checkbox'}, + { key: 'serieToggleAnimation.durationMs', def: 500, type: 'number', min: 0, max: 5000, step: 100}, + { key: 'loadAnimation.show', def: true, type: 'checkbox'}, + { key: 'loadAnimation.durationMs', def: 1000, type: 'number', min: 0, max: 5000, step: 500}, + { key: 'loadAnimation.staggerMs', def: 50, type: 'number', min: 0, max: 1000, step: 25}, + { key: 'responsive', def: false, type: 'checkbox'}, { key: 'userOptions.show', def: true, type: 'checkbox', label: 'showUserOptions', category: 'general' }, { key: 'userOptions.buttons.pdf', def: true, type: 'checkbox' }, @@ -134,9 +143,9 @@ const model = ref([ { key: 'style.chart.layout.labels.hollow.average.value.suffix', def: '', type: 'text', label: ['hollow', 'average', 'value', 'is', 'suffix'], category: 'labels' }, { key: 'style.chart.layout.labels.hollow.average.value.offsetY', def: 0, type: 'number', min: -100, max: 100, label: ['hollow', 'average', 'value', 'is', 'offsetY'], category: 'labels' }, { key: 'style.chart.layout.labels.hollow.average.value.rounding', def: 0, type: 'number', min: 0, max: 6, label: ['hollow', 'average', 'value', 'is', 'rounding'], category: 'labels' }, - { key: 'style.chart.layout.donut.strokeWidth', def: 6, type: 'range', min: 3, max: 130, label: 'thickness', category: 'donut' }, + { key: 'style.chart.layout.donut.strokeWidth', def: 64, type: 'range', min: 3, max: 130, label: 'thickness', category: 'donut' }, { key: 'style.chart.layout.donut.borderWidth', def: 1, type: 'range', min: 0, max: 36, label: ['border', 'is', 'thickness'], category: 'donut' }, - { key: 'style.chart.layout.donut.useShadow', def: false, type: 'checkbox' }, + { key: 'style.chart.layout.donut.useShadow', def: true, type: 'checkbox' }, { key: 'style.chart.layout.donut.shadowColor', def: '#1A1A1A', type: 'color' }, { key: 'style.chart.legend.show', def: true, type: 'checkbox', label: 'show', category: 'legend' }, { key: 'style.chart.legend.backgroundColor', def: '#FFFFFF20', type: 'color', label: 'backgroundColor', category: 'legend' }, diff --git a/TestingArena/ArenaVueUiDonutEvolution.vue b/TestingArena/ArenaVueUiDonutEvolution.vue index e2e04de1..47157329 100644 --- a/TestingArena/ArenaVueUiDonutEvolution.vue +++ b/TestingArena/ArenaVueUiDonutEvolution.vue @@ -25,7 +25,21 @@ const dataset = ref([ name: "Serie 4", values: [5, null, 5, 5, 5, 5 ] } -]) +]); + +const monthValues = computed(() => { + const yearStart = 2026 + const arr = [] + + for (let i = 0; i < 13; i++) { + const d = new Date(yearStart, i, 1) + arr.push(d.getTime()) + } + + console.log(arr) + + return arr +}) const model = ref([ { key: 'userOptions.show', def: true, type: 'checkbox'}, @@ -147,7 +161,6 @@ const config = computed(() => { dataLabels: { ...c.style.chart.layout.dataLabels, formatter: ({value, config}) => { - console.log(config) return `f | ${value}` } }, @@ -157,19 +170,10 @@ const config = computed(() => { ...c.style.chart.layout.grid.xAxis, dataLabels: { ...c.style.chart.layout.grid.xAxis.dataLabels, - values: [ - '01-01-2025', - '02-01-2025', - '03-01-2025', - '04-01-2025', - '05-01-2025', - '06-01-2025', - '07-01-2025', - '08-01-2025', - '09-01-2025', - '10-01-2025', - '11-01-2025', - ] + values: monthValues.value, + datetimeFormatter: { + enable: true, + } } } } diff --git a/TestingArena/ArenaVueUiFlow.vue b/TestingArena/ArenaVueUiFlow.vue index 4e95766b..75fcd70a 100644 --- a/TestingArena/ArenaVueUiFlow.vue +++ b/TestingArena/ArenaVueUiFlow.vue @@ -9,21 +9,130 @@ import { useArena } from "../src/useArena"; const { local, build, vduiLocal, vduiBuild, toggleTable } = useArena() const dataset = ref([ - [ 'A1', 'B1', 10 ], - [ 'A1', 'B2', 10 ], - [ 'B1', 'C1', 5 ], - [ 'B1', 'C2', 5 ], - [ 'B1', 'C3', 5 ], - [ 'B1', 'C4', 5 ], - [ 'A2', 'B1', 10], - [ 'B2', 'C5', 10], - [ 'C3', 'D1', 2], - [ 'C4', 'D1', 2], - [ 'C5', 'D1', 2], - [ 'C2', 'D2', 2], - [ 'C3', 'D2', 1], + // root + ['Config', 'theme', 1], + ['Config', 'customPalette', 1], + ['Config', 'userOptions', 1], + ['Config', 'nodeCategories', 1], + ['Config', 'nodeCategoryColors', 1], + ['Config', 'style', 1], + ['Config', 'table', 1], + + // userOptions + ['userOptions', 'show', 1], + ['userOptions', 'showOnChartHover', 1], + ['userOptions', 'position', 1], + ['userOptions', 'buttons', 1], + ['buttons', 'pdf', 1], + ['buttons', 'csv', 1], + ['buttons', 'img', 1], + ['buttons', 'table', 1], + ['buttons', 'fullscreen', 1], + ['buttons', 'annotator', 1], + ['buttons', 'tooltip', 1], + ['userOptions', 'buttonTitles', 1], + + // style + ['style', 'fontFamily', 1], + ['style', 'chart', 1], + + // chart + ['chart', 'backgroundColor', 1], + ['chart', 'color', 1], + ['chart', 'padding', 1], + ['chart', 'title', 1], + ['chart', 'tooltip', 1], + ['chart', 'legend', 1], + ['chart', 'nodes', 1], + ['chart', 'links', 1], + + // padding + ['padding', 'top', 1], + ['padding', 'right', 1], + ['padding', 'bottom', 1], + ['padding', 'left', 1], + + // title + ['title', 'text', 1], + ['title', 'subtitle', 1], + ['subtitle', 'text', 1], + ['title', 'cy', 1], + + // tooltip + ['tooltip', 'show', 1], + ['tooltip', 'fontSize', 1], + ['tooltip', 'backgroundColor', 1], + ['tooltip', 'color', 1], + ['tooltip', 'borderColor', 1], + ['tooltip', 'borderWidth', 1], + ['tooltip', 'borderRadius', 1], + ['tooltip', 'backgroundOpacity', 1], + ['tooltip', 'position', 1], + ['tooltip', 'offsetY', 1], + ['tooltip', 'showPercentage', 1], + ['tooltip', 'roundingPercentage', 1], + ['tooltip', 'translations', 1], + ['translations', 'from', 1], + ['translations', 'to', 1], + ['translations', 'percentOfTotal', 1], + + // legend + ['legend', 'show', 1], + ['legend', 'backgroundColor', 1], + ['legend', 'color', 1], + ['legend', 'fontSize', 1], + ['legend', 'paddingBottom', 1], + ['legend', 'paddingTop', 1], + ['legend', 'bold', 1], + ['legend', 'cy', 1], + + // nodes + ['nodes', 'gap', 1], + ['nodes', 'minHeight', 1], + ['nodes', 'width', 1], + ['nodes', 'labels', 1], + ['nodes', 'stroke', 1], + ['nodes', 'strokeWidth', 1], + + // labels + ['labels', 'fontSize', 1], + ['labels', 'abbreviation', 1], + ['labels', 'prefix', 1], + ['labels', 'suffix', 1], + ['labels', 'rounding', 1], + ['labels', 'formatter', 1], + + // abbreviation + ['abbreviation', 'use', 1], + ['abbreviation', 'length', 1], + + // links + ['links', 'width', 1], + ['links', 'opacity', 1], + ['links', 'stroke', 1], + ['links', 'strokeWidth', 1], + + // table + ['table', 'show', 1], + ['table', 'responsiveBreakpoint', 1], + ['table', 'columnNames', 1], + ['columnNames', 'source', 1], + ['columnNames', 'target', 1], + ['columnNames', 'value', 1], + ['table', 'th', 1], + ['table', 'td', 1], + + // th + ['th', 'backgroundColor', 1], + ['th', 'color', 1], + ['th', 'outline', 1], + + // td + ['td', 'backgroundColor', 1], + ['td', 'color', 1], + ['td', 'outline', 1], ]); - + const model = ref([ { key: 'userOptions.show', def: true, type: 'checkbox' }, { key: 'userOptions.buttons.pdf', def: true, type: 'checkbox' }, @@ -31,15 +140,20 @@ const model = ref([ { key: 'userOptions.buttons.img', def: true, type: 'checkbox' }, { key: 'userOptions.buttons.table', def: true, type: 'checkbox' }, { key: 'userOptions.buttons.fullscreen', def: true, type: 'checkbox' }, - { key: 'userOptions.position', def: 'right', type: 'select', options: ['left', 'right']}, - { key: 'userOptions.showOnChartHover', def: true, type: 'checkbox'}, - { key: 'userOptions.keepStateOnChartLeave', def: true, type: 'checkbox'}, + { key: 'userOptions.position', def: 'right', type: 'select', options: ['left', 'right'] }, + { key: 'userOptions.showOnChartHover', def: true, type: 'checkbox' }, + { key: 'userOptions.keepStateOnChartLeave', def: true, type: 'checkbox' }, - { key: 'userOptions.print.scale', def: 2, type: 'number', min: 1, max: 5}, - { key: 'userOptions.print.allowTaint', def: true, type: 'checkbox'}, - { key: 'userOptions.print.useCORS', def: true, type: 'checkbox'}, + { key: 'style.chart.padding.top', def: 12, type: 'number', min: 0, max: 100,}, + { key: 'style.chart.padding.right', def: 12, type: 'number', min: 0, max: 100,}, + { key: 'style.chart.padding.bottom', def: 12, type: 'number', min: 0, max: 100,}, + { key: 'style.chart.padding.left', def: 12, type: 'number', min: 0, max: 100,}, + + { key: 'userOptions.print.scale', def: 2, type: 'number', min: 1, max: 5 }, + { key: 'userOptions.print.allowTaint', def: true, type: 'checkbox' }, + { key: 'userOptions.print.useCORS', def: true, type: 'checkbox' }, { key: 'userOptions.print.backgroundColor', def: '#FFFFFF' }, - + { key: 'style.fontFamily', def: 'inherit', type: 'text' }, { key: 'style.chart.backgroundColor', def: '#FFFFFF20', type: 'color' }, { key: 'style.chart.color', def: '#1A1A1A', type: 'color' }, @@ -62,7 +176,7 @@ const model = ref([ { key: 'style.chart.nodes.labels.abbreviation.use', def: true, type: 'checkbox' }, { key: 'style.chart.nodes.labels.abbreviation.length', def: 3, type: 'number', min: 1, max: 12 }, { key: 'style.chart.nodes.stroke', def: '#FFFFFF', type: 'color' }, - { key: 'style.chart.nodes.strokeWidth', def: 1, type: 'number', min: 0, max: 12}, + { key: 'style.chart.nodes.strokeWidth', def: 1, type: 'number', min: 0, max: 12 }, { key: 'style.chart.links.opacity', def: 0.8, type: 'number', min: 0, max: 1, step: 0.1 }, { key: 'style.chart.links.stroke', def: '#FFFFFF', type: 'color' }, { key: 'style.chart.links.strokeWidth', def: 1, type: 'number', min: 0, max: 12 }, @@ -87,6 +201,160 @@ const config = computed(() => { return { theme: currentTheme.value, ...c, + nodeCategories: { + // top‐level + theme: 'config', + customPalette: 'config', + userOptions: 'config', + nodeCategories: 'config', + nodeCategoryColors: 'config', + style: 'config', + table: 'config', + + // userOptions + show: 'userOptions', + showOnChartHover: 'userOptions', + position: 'userOptions', + buttons: 'userOptions', + buttonTitles: 'userOptions', + + // buttons + pdf: 'userOptionsButtons', + csv: 'userOptionsButtons', + img: 'userOptionsButtons', + table: 'userOptionsButtons', + fullscreen: 'userOptionsButtons', + annotator: 'userOptionsButtons', + tooltip: 'userOptionsButtons', + + // style + fontFamily: 'style', + chart: 'style', + + // chart + backgroundColor: 'chart', + color: 'chart', + padding: 'chart', + title: 'chart', + tooltip: 'chart', + legend: 'chart', + nodes: 'chart', + links: 'chart', + + // padding + top: 'chartPadding', + right: 'chartPadding', + bottom: 'chartPadding', + left: 'chartPadding', + + // title + text: 'chartTitle', + subtitle: 'chartTitle', + cy: 'chartTitle', + // subtitle.text lives under the same category + + // tooltip + show: 'chartTooltip', + fontSize: 'chartTooltip', + backgroundColor: 'chartTooltip', + color: 'chartTooltip', + borderColor: 'chartTooltip', + borderWidth: 'chartTooltip', + borderRadius: 'chartTooltip', + backgroundOpacity: 'chartTooltip', + position: 'chartTooltip', + offsetY: 'chartTooltip', + showPercentage: 'chartTooltip', + roundingPercentage: 'chartTooltip', + translations: 'chartTooltip', + from: 'chartTooltipTranslations', + to: 'chartTooltipTranslations', + percentOfTotal: 'chartTooltipTranslations', + + // legend + show: 'chartLegend', + backgroundColor: 'chartLegend', + color: 'chartLegend', + fontSize: 'chartLegend', + paddingBottom: 'chartLegend', + paddingTop: 'chartLegend', + bold: 'chartLegend', + cy: 'chartLegend', + + // nodes + gap: 'chartNodes', + minHeight: 'chartNodes', + width: 'chartNodes', + labels: 'chartNodes', + stroke: 'chartNodes', + strokeWidth: 'chartNodes', + + // labels + fontSize: 'chartLabels', + abbreviation: 'chartLabels', + prefix: 'chartLabels', + suffix: 'chartLabels', + rounding: 'chartLabels', + formatter: 'chartLabels', + + // abbreviation + use: 'chartLabelsAbbreviation', + length: 'chartLabelsAbbreviation', + + // links + width: 'chartLinks', + opacity: 'chartLinks', + stroke: 'chartLinks', + strokeWidth: 'chartLinks', + + // table + show: 'table', + responsiveBreakpoint: 'table', + columnNames: 'table', + th: 'table', + td: 'table', + + // columnNames + source: 'tableColumnNames', + target: 'tableColumnNames', + value: 'tableColumnNames', + + // th + backgroundColor: 'tableTh', + color: 'tableTh', + outline: 'tableTh', + + // td + backgroundColor: 'tableTd', + color: 'tableTd', + outline: 'tableTd', +}, + +nodeCategoryColors: { + // top‐level + config: '#1f77b4', + userOptions: '#ff7f0e', + userOptionsButtons: '#2ca02c', + style: '#d62728', + + // chart + chart: '#9467bd', + chartPadding: '#8c564b', + chartTitle: '#e377c2', + chartTooltip: '#bcbd22', + chartTooltipTranslations:'#17becf', + chartLegend: '#aec7e8', + chartNodes: '#98df8a', + chartLabels: '#ff9896', + chartLabelsAbbreviation:'#c5b0d5', + chartLinks: '#c49c94', + + // table + table: '#dbdb8d', + tableColumnNames: '#9edae5', + tableTh: '#393b79', + tableTd: '#5254a3', +}, style: { ...c.style, chart: { @@ -95,7 +363,7 @@ const config = computed(() => { ...c.style.chart.nodes, labels: { ...c.style.chart.nodes.labels, - formatter: ({value, config}) => { + formatter: ({ value, config }) => { // console.log(config) return `f | ${value}` } @@ -125,7 +393,7 @@ const step = ref(0);