Skip to content

Commit 52a3190

Browse files
authored
Merge pull request #211 from graphieros/ft-component-optimizations
Improve management of resizeObservers Import some atom components as async in chart components Fix - VueUiRidgeline & VueUiDonutEvolution - Display BaseDraggableDialog in direct parent in fullscreen mode
2 parents d63f30b + 34a369b commit 52a3190

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1249
-687
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vue-data-ui",
33
"private": false,
4-
"version": "2.12.6",
4+
"version": "2.12.7-beta.4",
55
"type": "module",
66
"description": "A user-empowering data visualization Vue 3 components library for eloquent data storytelling",
77
"keywords": [
@@ -109,4 +109,4 @@
109109
"vitest": "^3.2.4",
110110
"vue": "^3.5.17"
111111
}
112-
}
112+
}

src/App.vue

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -67,70 +67,65 @@ import ArenaVueUiChord from "../TestingArena/ArenaVueUiChord.vue"
6767
6868
const mapping = ref({
6969
VueUiXy: markRaw(ArenaVueUiXy),
70-
VueUiDonut: markRaw(ArenaVueUiDonut),
71-
VueUiTreemap: markRaw(ArenaVueUiTreemap),
70+
VueUiDonut: markRaw(ArenaVueUiDonut),
71+
VueUiTreemap: markRaw(ArenaVueUiTreemap),
7272
VueUiWaffle: markRaw(ArenaVueUiWaffle),
73-
VueUiRadar: markRaw(ArenaVueUiRadar),
74-
VueUiQuadrant: markRaw(ArenaVueUiQuadrant),
73+
VueUiRadar: markRaw(ArenaVueUiRadar),
74+
VueUiQuadrant: markRaw(ArenaVueUiQuadrant),
7575
VueUiGauge: markRaw(ArenaVueUiGauge),
76-
VueUiWheel: markRaw(ArenaVueUiWheel),
76+
VueUiWheel: markRaw(ArenaVueUiWheel),
7777
VueUiTiremarks: markRaw(ArenaVueUiTiremarks),
78-
VueUiChestnut: markRaw(ArenaVueUiChestnut),
79-
VueUiOnion: markRaw(ArenaVueUiOnion),
80-
VueUiVerticalBar: markRaw(ArenaVueUiVerticalBar),
81-
VueUiHeatmap: markRaw(ArenaVueUiHeatmap),
82-
VueUiScatter: markRaw(ArenaVueUiScatter),
83-
VueUiCandlestick: markRaw(ArenaVueUiCandlestick),
84-
VueUiSparkline: markRaw(ArenaVueUiSparkline),
78+
VueUiChestnut: markRaw(ArenaVueUiChestnut),
79+
VueUiOnion: markRaw(ArenaVueUiOnion),
80+
VueUiVerticalBar: markRaw(ArenaVueUiVerticalBar),
81+
VueUiHeatmap: markRaw(ArenaVueUiHeatmap),
82+
VueUiScatter: markRaw(ArenaVueUiScatter),
83+
VueUiCandlestick: markRaw(ArenaVueUiCandlestick),
84+
VueUiSparkline: markRaw(ArenaVueUiSparkline),
8585
VueUiSparkbar: markRaw(ArenaVueUiSparkbar),
86-
VueUiSparkStackbar: markRaw(ArenaVueUiSparkStackbar),
87-
VueUiSparkHistogram: markRaw(ArenaVueUiSparkHistogram),
88-
VueUiSparkgauge: markRaw(ArenaVueUiSparkGauge),
89-
VueUiSparkTrend: markRaw(ArenaVueUiSparkTrend),
86+
VueUiSparkStackbar: markRaw(ArenaVueUiSparkStackbar),
87+
VueUiSparkHistogram: markRaw(ArenaVueUiSparkHistogram),
88+
VueUiSparkgauge: markRaw(ArenaVueUiSparkGauge),
89+
VueUiSparkTrend: markRaw(ArenaVueUiSparkTrend),
9090
VueUiQuickChart: markRaw(ArenaVueUiQuickChart),
9191
VueUiAgePyramid: markRaw(ArenaVueUiAgePyramid),
92-
VueUiRelationCircle: markRaw(ArenaVueUiRelationCircle),
93-
VueUiThermometer: markRaw(ArenaVueUiThermometer),
94-
VueUiRings: markRaw(ArenaVueUiRings),
95-
VueUiDonutEvolution: markRaw(ArenaVueUiDonutEvolution),
92+
VueUiRelationCircle: markRaw(ArenaVueUiRelationCircle),
93+
VueUiThermometer: markRaw(ArenaVueUiThermometer),
94+
VueUiRings: markRaw(ArenaVueUiRings),
95+
VueUiDonutEvolution: markRaw(ArenaVueUiDonutEvolution),
9696
VueUiIcon: markRaw(ArenaVueUiIcon),
97-
VueUiMoodRadar: markRaw(ArenaVueUiMoodRadar),
98-
VueUiMolecule: markRaw(ArenaVueUiMolecule),
97+
VueUiMoodRadar: markRaw(ArenaVueUiMoodRadar),
98+
VueUiMolecule: markRaw(ArenaVueUiMolecule),
9999
VueUiNestedDonuts: markRaw(ArenaVueUiNestedDonuts),
100-
VueUiGalaxy: markRaw(ArenaVueUiGalaxy),
101-
VueUiStripPlot: markRaw(ArenaVueUiStripPlot),
102-
VueUiDumbbell: markRaw(ArenaVueUiDumbbell),
103-
VueUi3dBar: markRaw(ArenaVueUi3dBar),
100+
VueUiGalaxy: markRaw(ArenaVueUiGalaxy),
101+
VueUiStripPlot: markRaw(ArenaVueUiStripPlot),
102+
VueUiDumbbell: markRaw(ArenaVueUiDumbbell),
103+
VueUi3dBar: markRaw(ArenaVueUi3dBar),
104104
VueUiTableSparkline: markRaw(ArenaVueUiTableSparkline),
105-
VueUiTableHeatmap: markRaw(ArenaVueUiTableHeatmap),
106-
VueUiWordCloud: markRaw(ArenaVueUiWordCloud),
105+
VueUiTableHeatmap: markRaw(ArenaVueUiTableHeatmap),
106+
VueUiWordCloud: markRaw(ArenaVueUiWordCloud),
107107
VueUiXyCanvas: markRaw(ArenaVueUiXyCanvas),
108-
VueUiFlow: markRaw(ArenaVueUiFlow),
108+
VueUiFlow: markRaw(ArenaVueUiFlow),
109109
VueUiParallelCoordinatePlot: markRaw(ArenaVueUiParallelCoordinatePlot),
110110
VueUiTimer: markRaw(ArenaVueUiTimer),
111111
VueUiCarouselTable: markRaw(ArenaVueUiCarouselTable),
112-
VueUiGizmo: markRaw(ArenaVueUiGizmo),
113-
VueUiKpi: markRaw(ArenaVueUiKpi),
112+
VueUiGizmo: markRaw(ArenaVueUiGizmo),
113+
VueUiKpi: markRaw(ArenaVueUiKpi),
114114
VueUiStackbar: markRaw(ArenaVueUiStackbar),
115115
VueUiRating: markRaw(ArenaVueUiRating),
116116
VueUiSmiley: markRaw(ArenaVueUiSmiley),
117-
VueUiBullet: markRaw(ArenaVueUiBullet),
117+
VueUiBullet: markRaw(ArenaVueUiBullet),
118118
VueUiFunnel: markRaw(ArenaVueUiFunnel),
119119
VueUiHistoryPlot: markRaw(ArenaVueUiHistoryPlot),
120-
VueUiCirclePack: markRaw(ArenaVueUiCirclePack),
121-
VueUiWorld: markRaw(ArenaVueUiWorld),
120+
VueUiCirclePack: markRaw(ArenaVueUiCirclePack),
121+
VueUiWorld: markRaw(ArenaVueUiWorld),
122122
VueUiTable: markRaw(ArenaVueUiTable),
123123
VueUiRidgeline: markRaw(ArenaVueUiRidgeline),
124-
VueUiChord: markRaw(ArenaVueUiChord)
124+
VueUiChord: markRaw(ArenaVueUiChord),
125125
})
126126
127127
const options = computed(() => Object.keys(mapping.value));
128-
129-
/**
130-
* Modify the index to display a component
131-
* [0] = VueUiXy
132-
*/
133-
const selectedComponent = ref('VueUiChord');
128+
const selectedComponent = ref('VueUiChord');
134129
135130
/**
136131
* Legacy testing arena where some non chart components can be tested

src/atoms/BaseDraggableDialog.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ const props = defineProps({
77
backgroundColor: { type: String },
88
color: { type: String },
99
headerBg: { type: String },
10-
headerColor: { type: String }
10+
headerColor: { type: String },
11+
fullscreenParent: { type: HTMLElement },
12+
isFullscreen: { type: Boolean, default: false }
1113
});
1214
1315
const emit = defineEmits(["close"]);
@@ -182,7 +184,7 @@ onUnmounted(() => {
182184
</script>
183185
184186
<template>
185-
<Teleport to="body">
187+
<Teleport :to="isFullscreen ? fullscreenParent : 'body'">
186188
<div v-if="isOpen" data-cy="draggable-dialog" class="modal vue-ui-draggable-dialog" :style="modalStyle" @click.stop>
187189
<div class="modal-header" :style="{
188190
backgroundColor: headerBg,

src/components/vue-ui-3d-bar.cy.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,33 @@ describe('<VueUi3dBar />', () => {
2323
props: {
2424
dataset
2525
}
26-
}).then(({ wrapper }) => {
26+
}).then(() => {
27+
cy.wait(0)
2728
testCommonFeatures({ userOptions: true });
28-
29+
2930
cy.get('.vue-ui-3d-bar-stack').should('exist').and('have.length', 6)
3031
dataset.series.forEach((ds) => {
3132
cy.get(`[data-cy="bar-3d-value-${ds.value}"]`).should('exist').and('be.visible')
3233
})
34+
})
35+
});
3336

34-
cy.log('Props reactivity')
37+
it('handles dataset reactivity', () => {
38+
const dataset = components.find(c => c.name === 'VueUi3dBar').dataset2;
39+
cy.viewport(500, 500)
40+
cy.mount(VueUi3dBar, {
41+
props: {
42+
dataset
43+
}
44+
}).then(({ wrapper }) => {
3545
wrapper.setProps({
3646
dataset: {
3747
series: [dataset.series[0], dataset.series[1]]
3848
}
3949
}).then(() => {
4050
cy.get('.vue-ui-3d-bar-stack').should('exist').and('have.length', 2)
4151
});
42-
});
52+
})
4353
});
4454

4555
it('emits', () => {

src/components/vue-ui-3d-bar.vue

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup>
2-
import { ref, computed, onMounted, nextTick, watch } from "vue";
2+
import { ref, computed, onMounted, nextTick, watch, defineAsyncComponent } from "vue";
33
import {
44
applyDataLabel,
55
calcMarkerOffsetX,
@@ -22,19 +22,20 @@ import {
2222
themePalettes,
2323
XMLNS
2424
} from '../lib';
25-
import themes from "../themes.json";
26-
import Title from "../atoms/Title.vue";
27-
import UserOptions from "../atoms/UserOptions.vue";
28-
import Skeleton from "./vue-ui-skeleton.vue";
29-
import DataTable from "../atoms/DataTable.vue";
30-
import Accordion from "./vue-ui-accordion.vue";
3125
import { useNestedProp } from "../useNestedProp";
3226
import { usePrinter } from "../usePrinter";
3327
import { useConfig } from "../useConfig";
34-
import PackageVersion from "../atoms/PackageVersion.vue";
35-
import PenAndPaper from "../atoms/PenAndPaper.vue";
3628
import { useUserOptionState } from "../useUserOptionState";
3729
import { useChartAccessibility } from "../useChartAccessibility";
30+
import themes from "../themes.json";
31+
import Title from "../atoms/Title.vue"; // Must be ready in responsive mode
32+
33+
const Accordion = defineAsyncComponent(() => import('./vue-ui-accordion.vue'));
34+
const DataTable = defineAsyncComponent(() => import('../atoms/DataTable.vue'));
35+
const PackageVersion = defineAsyncComponent(() => import('../atoms/PackageVersion.vue'));
36+
const PenAndPaper = defineAsyncComponent(() => import('../atoms/PenAndPaper.vue'));
37+
const Skeleton = defineAsyncComponent(() => import('./vue-ui-skeleton.vue'));
38+
const UserOptions = defineAsyncComponent(() => import('../atoms/UserOptions.vue'));
3839
3940
const { vue_ui_3d_bar: DEFAULT_CONFIG } = useConfig();
4041

src/components/vue-ui-age-pyramid.vue

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup>
2-
import { ref, computed, nextTick, onMounted, watch } from "vue";
2+
import { ref, computed, nextTick, onMounted, watch, defineAsyncComponent, shallowRef, onBeforeUnmount } from "vue";
33
import {
44
applyDataLabel,
55
checkNaN,
@@ -16,21 +16,22 @@ import {
1616
XMLNS
1717
} from '../lib';
1818
import { throttle } from "../canvas-lib";
19-
import themes from "../themes.json";
20-
import Title from "../atoms/Title.vue";
21-
import UserOptions from "../atoms/UserOptions.vue";
22-
import Tooltip from "../atoms/Tooltip.vue";
23-
import DataTable from "../atoms/DataTable.vue";
24-
import Skeleton from "./vue-ui-skeleton.vue";
25-
import Accordion from "./vue-ui-accordion.vue";
2619
import { useNestedProp } from "../useNestedProp";
2720
import { usePrinter } from "../usePrinter";
2821
import { useResponsive } from "../useResponsive";
2922
import { useConfig } from "../useConfig";
30-
import PackageVersion from "../atoms/PackageVersion.vue";
31-
import PenAndPaper from "../atoms/PenAndPaper.vue";
3223
import { useUserOptionState } from "../useUserOptionState";
3324
import { useChartAccessibility } from "../useChartAccessibility";
25+
import themes from "../themes.json";
26+
import Title from "../atoms/Title.vue"; // Must be ready in responsive mode
27+
28+
const Accordion = defineAsyncComponent(() => import('./vue-ui-accordion.vue'));
29+
const DataTable = defineAsyncComponent(() => import('../atoms/DataTable.vue'));
30+
const PackageVersion = defineAsyncComponent(() => import('../atoms/PackageVersion.vue'));
31+
const PenAndPaper = defineAsyncComponent(() => import('../atoms/PenAndPaper.vue'));
32+
const Skeleton = defineAsyncComponent(() => import('./vue-ui-skeleton.vue'));
33+
const Tooltip = defineAsyncComponent(() => import('../atoms/Tooltip.vue'));
34+
const UserOptions = defineAsyncComponent(() => import('../atoms/UserOptions.vue'));
3435
3536
const { vue_ui_age_pyramid: DEFAULT_CONFIG } = useConfig();
3637
@@ -107,7 +108,8 @@ watch(() => props.config, (_newCfg) => {
107108
mutableConfig.value.showTooltip = FINAL_CONFIG.value.style.tooltip.show;
108109
}, { deep: true });
109110
110-
const resizeObserver = ref(null);
111+
const resizeObserver = shallowRef(null);
112+
const observedEl = shallowRef(null);
111113
112114
onMounted(() => {
113115
prepareChart();
@@ -136,11 +138,28 @@ function prepareChart() {
136138
});
137139
});
138140
141+
if (resizeObserver.value) {
142+
if (observedEl.value) {
143+
resizeObserver.value.unobserve(observedEl.value);
144+
}
145+
resizeObserver.value.disconnect();
146+
}
147+
139148
resizeObserver.value = new ResizeObserver(handleResize);
140-
resizeObserver.value.observe(agePyramid.value.parentNode);
149+
observedEl.value = agePyramid.value.parentNode;
150+
resizeObserver.value.observe(observedEl.value);
141151
}
142152
}
143153
154+
onBeforeUnmount(() => {
155+
if (resizeObserver.value) {
156+
if (observedEl.value) {
157+
resizeObserver.value.unobserve(observedEl.value);
158+
}
159+
resizeObserver.value.disconnect();
160+
}
161+
});
162+
144163
const { isPrinting, isImaging, generatePdf, generateImage } = usePrinter({
145164
elementId: `vue-ui-age-pyramid_${uid.value}`,
146165
fileName: FINAL_CONFIG.value.style.title.text || 'vue-ui-age-pyramid',
@@ -553,8 +572,8 @@ defineExpose({
553572
v-if="$slots['chart-background']"
554573
:x="drawingArea.left"
555574
:y="drawingArea.top"
556-
:width="drawingArea.width"
557-
:height="drawingArea.height"
575+
:width="Math.max(0.1, drawingArea.width)"
576+
:height="Math.max(0.1, drawingArea.height)"
558577
:style="{
559578
pointerEvents: 'none'
560579
}"

src/components/vue-ui-bullet.vue

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
<script setup>
2-
import { ref, computed, onMounted, watch, onBeforeUnmount } from "vue";
2+
import { ref, computed, onMounted, watch, onBeforeUnmount, defineAsyncComponent } from "vue";
33
import { useConfig } from "../useConfig";
44
import { XMLNS, createUid, error, getMissingDatasetAttributes, objectIsEmpty } from "../lib";
55
import { useNestedProp } from "../useNestedProp";
6-
import themes from "../themes.json";
76
import { convertColorToHex } from "../lib";
87
import { lightenHexColor } from "../lib";
98
import { calculateNiceScale } from "../lib";
109
import { applyDataLabel } from "../lib";
1110
import { dataLabel } from "../lib";
12-
import Title from "../atoms/Title.vue";
13-
import Legend from "../atoms/Legend.vue";
14-
import UserOptions from "../atoms/UserOptions.vue";
1511
import { usePrinter } from "../usePrinter";
16-
import PackageVersion from "../atoms/PackageVersion.vue";
17-
import PenAndPaper from "../atoms/PenAndPaper.vue";
18-
import Skeleton from "./vue-ui-skeleton.vue";
1912
import { useUserOptionState } from "../useUserOptionState";
2013
import { useChartAccessibility } from "../useChartAccessibility";
14+
import themes from "../themes.json";
15+
import Legend from "../atoms/Legend.vue"; // Must be ready in responsive mode
16+
import Title from "../atoms/Title.vue"; // Must be ready in responsive mode
17+
18+
const PackageVersion = defineAsyncComponent(() => import('../atoms/PackageVersion.vue'));
19+
const PenAndPaper = defineAsyncComponent(() => import('../atoms/PenAndPaper.vue'));
20+
const Skeleton = defineAsyncComponent(() => import('./vue-ui-skeleton.vue'));
21+
const UserOptions = defineAsyncComponent(() => import('../atoms/UserOptions.vue'));
2122
2223
const { vue_ui_bullet: DEFAULT_CONFIG } = useConfig();
2324

0 commit comments

Comments
 (0)