Skip to content

Commit 8d372ea

Browse files
committed
Improvement - VueUiMolecule - Add color dataset attribute
1 parent 6af18b9 commit 8d372ea

File tree

6 files changed

+131
-62
lines changed

6 files changed

+131
-62
lines changed

Diff for: TestingArena/ArenaVueUiMolecule.vue

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ const dataset = ref([
1313
{
1414
name: "Root",
1515
details: "This is the root node",
16+
color: 'red',
1617
nodes: [
1718
{
1819
name: 'node1',
1920
details: 'Lorem ipsum',
21+
color: 'blue',
2022
nodes: [
2123
{
22-
name: 'node1.1', details: 'Lorem ipsum', nodes: [
24+
name: 'node1.1', details: 'Lorem ipsum', color: 'green', nodes: [
2325
{ name: 'node1.1' },
2426
{ name: 'node1.2' },
2527
{ name: 'node1.3' },
@@ -205,7 +207,7 @@ const themeOptions = ref([
205207
"celebrationNight"
206208
])
207209
208-
const currentTheme = ref(themeOptions.value[6])
210+
const currentTheme = ref(themeOptions.value[0])
209211
210212
const config = computed(() => {
211213
const c = convertArrayToObject(model.value);

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,4 @@
107107
"vitest": "^3.1.1",
108108
"vue": "^3.5.13"
109109
}
110-
}
110+
}

Diff for: src/App.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ const components = ref([ //------|
120120
* Modify the index to display a component
121121
* [0] = VueUiXy
122122
*/
123-
const selectedComponent = ref(components.value[0]);
123+
const selectedComponent = ref(components.value[29]);
124124
125125
/**
126126
* Legacy testing arena where some non chart components can be tested

Diff for: src/components/vue-ui-molecule.vue

+79-56
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
<script setup>
22
import { ref, computed, nextTick, onMounted, watch } from "vue";
33
import {
4+
convertColorToHex,
45
convertCustomPalette,
56
createCsvContent,
67
createPolygonPath,
7-
createUid,
8+
createUid,
9+
deepClone,
810
downloadCsv,
911
error,
1012
functionReturnsString,
@@ -173,72 +175,92 @@ function processNodes(
173175
circleRadius = 24,
174176
rotation = 0,
175177
paletteIndex = 0,
176-
rootColor = "#BBBBBB"
178+
rootColor = "#BBBBBB",
179+
depth = 0
177180
) {
181+
if (!Array.isArray(data) || data.length === 0) return data;
178182
179-
if (data && data.length > 0) {
180-
const polygonPath = createPolygonPath({
181-
plot: center,
182-
radius,
183-
sides: data.length,
184-
rotation,
185-
});
183+
const polygonPath = createPolygonPath({
184+
plot: center,
185+
radius,
186+
sides: data.length,
187+
rotation
188+
});
186189
187-
data.forEach((node, index) => {
188-
const childCenter = polygonPath.coordinates[index];
189-
let color;
190-
191-
if (!node.ancestor) {
192-
color = rootColor;
193-
} else if (!node.ancestor.ancestor) {
194-
color = customPalette.value[paletteIndex] || palette[paletteIndex] || rootColor;
195-
paletteIndex += 1;
196-
} else {
197-
color = node.ancestor.color || rootColor;
198-
}
190+
data.forEach((node, idx) => {
191+
const childCenter = polygonPath.coordinates[idx];
192+
193+
const converted = node.color
194+
? (() => {
195+
let h = convertColorToHex(node.color);
196+
return h.startsWith("#") ? h : `#${h}`;
197+
})()
198+
: null;
199+
200+
let finalColor;
201+
if (converted) {
202+
finalColor = converted;
203+
} else if (depth === 0) {
204+
finalColor = rootColor;
205+
} else if (depth === 1) {
206+
finalColor = (
207+
customPalette.value[paletteIndex] ||
208+
palette[paletteIndex] ||
209+
rootColor
210+
);
211+
paletteIndex += 1;
212+
} else {
213+
finalColor = rootColor;
214+
}
215+
216+
node.polygonPath = { coordinates: [childCenter] };
217+
node.circleRadius = circleRadius;
218+
node.color = finalColor;
219+
node.uid = createUid();
220+
221+
if (Array.isArray(node.nodes) && node.nodes.length) {
222+
node.nodes = processNodes(
223+
node.nodes,
224+
childCenter,
225+
radius / 2.9,
226+
circleRadius/ 2.2,
227+
rotation + (Math.PI * idx) / node.nodes.length,
228+
paletteIndex,
229+
finalColor,
230+
depth + 1
231+
);
232+
}
233+
});
199234
200-
node.polygonPath = {
201-
coordinates: [childCenter],
202-
};
203-
204-
node.circleRadius = circleRadius;
205-
node.color = color;
206-
node.uid = createUid();
207-
208-
if (node.nodes && node.nodes.length > 0) {
209-
const nestedPaletteIndex = !node.ancestor || !node.ancestor.ancestor ? paletteIndex : 0;
210-
node.nodes = processNodes(
211-
node.nodes,
212-
childCenter,
213-
radius / 2.9,
214-
circleRadius / 2.2,
215-
rotation + (Math.PI * index) / node.nodes.length,
216-
nestedPaletteIndex,
217-
color
218-
);
219-
}
220-
});
221-
}
222235
return data;
223236
}
224237
225238
function generateGradientIDs(data) {
226-
const uniqueColors = new Set();
227-
function extractUniqueColors(nodes) {
228-
nodes.forEach((node) => {
229-
if (node.color && !uniqueColors.has(node.color)) {
230-
uniqueColors.add(node.color);
231-
}
232-
if (node.nodes && node.nodes.length > 0) {
233-
extractUniqueColors(node.nodes);
234-
}
239+
const colors = new Set();
240+
241+
function recurse(nodes) {
242+
nodes.forEach(node => {
243+
if (!node.color) return;
244+
245+
let hex = node.color;
246+
if (!/^#?[0-9A-F]{6}$/i.test(hex)) {
247+
hex = convertColorToHex(hex);
248+
}
249+
if (!hex.startsWith("#")) hex = `#${hex}`;
250+
251+
colors.add(hex);
252+
253+
if (Array.isArray(node.nodes) && node.nodes.length) {
254+
recurse(node.nodes);
255+
}
235256
});
236257
}
237-
extractUniqueColors(data);
258+
recurse(data);
238259
239260
const gradientIDs = {};
240-
Array.from(uniqueColors).forEach((color, index) => {
241-
gradientIDs[color] = `gradient_${index}`;
261+
Array.from(colors).forEach(col => {
262+
const safe = col.slice(1);
263+
gradientIDs[col] = `gradient_${safe}`;
242264
});
243265
244266
return gradientIDs;
@@ -249,7 +271,8 @@ const gradientIds = computed(() => {
249271
})
250272
251273
const convertedDataset = computed(() => {
252-
return processNodes(props.dataset);
274+
const dataCopy = deepClone(props.dataset);
275+
return processNodes(dataCopy);
253276
})
254277
255278
const dataTooltipSlot = ref(null);

Diff for: src/lib.js

+45-2
Original file line numberDiff line numberDiff line change
@@ -2211,8 +2211,8 @@ export function placeHTMLElementAtSVGCoordinates({ svgElement, x, y, offsetY = 0
22112211
};
22122212
}
22132213

2214-
export function placeXYTag({ svgElement, x, y, element, position}) {
2215-
if (!svgElement || ! element) return { top: 0, left: 0 };
2214+
export function placeXYTag({ svgElement, x, y, element, position }) {
2215+
if (!svgElement || !element) return { top: 0, left: 0 };
22162216

22172217
const point = svgElement.createSVGPoint();
22182218
point.x = x;
@@ -2229,6 +2229,48 @@ export function placeXYTag({ svgElement, x, y, element, position}) {
22292229
};
22302230
}
22312231

2232+
export function deepClone(value) {
2233+
if (value === null || typeof value !== 'object') {
2234+
return value;
2235+
}
2236+
2237+
if (value instanceof Date) {
2238+
return new Date(value.getTime());
2239+
}
2240+
2241+
if (value instanceof RegExp) {
2242+
return new RegExp(value.source, value.flags);
2243+
}
2244+
2245+
if (value instanceof Map) {
2246+
const result = new Map();
2247+
for (const [key, val] of value.entries()) {
2248+
result.set(key, deepClone(val));
2249+
}
2250+
return result;
2251+
}
2252+
2253+
if (value instanceof Set) {
2254+
const result = new Set();
2255+
for (const val of value.values()) {
2256+
result.add(deepClone(val));
2257+
}
2258+
return result;
2259+
}
2260+
2261+
if (Array.isArray(value)) {
2262+
return value.map(item => deepClone(item));
2263+
}
2264+
2265+
const result = {};
2266+
for (const key in value) {
2267+
if (Object.prototype.hasOwnProperty.call(value, key)) {
2268+
result[key] = deepClone(value[key]);
2269+
}
2270+
}
2271+
return result;
2272+
}
2273+
22322274
const lib = {
22332275
XMLNS,
22342276
abbreviate,
@@ -2268,6 +2310,7 @@ const lib = {
22682310
createWordCloudDatasetFromPlainText,
22692311
darkenHexColor,
22702312
dataLabel,
2313+
deepClone,
22712314
degreesToRadians,
22722315
downloadCsv,
22732316
error,

Diff for: types/vue-data-ui.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ declare module "vue-data-ui" {
735735
name: string;
736736
details?: string;
737737
nodes?: VueUiMoleculeDatasetNode[];
738+
color?: string;
738739
};
739740

740741
export type VueUiMoleculeConfig = {

0 commit comments

Comments
 (0)