@unovis/ts 1.5.1-exf.12 → 1.5.1-exf.13
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.
- package/components/treemap/config.d.ts +2 -0
- package/components/treemap/config.js +1 -1
- package/components/treemap/config.js.map +1 -1
- package/components/treemap/index.js +37 -33
- package/components/treemap/index.js.map +1 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/utils/color.d.ts +14 -0
- package/utils/color.js +26 -2
- package/utils/color.js.map +1 -1
- package/utils/index.js +1 -1
|
@@ -24,5 +24,7 @@ export interface TreemapConfigInterface<Datum> extends ComponentConfigInterface
|
|
|
24
24
|
labelOffsetX?: number;
|
|
25
25
|
/** Label offset in the Y direction. Default: `4` */
|
|
26
26
|
labelOffsetY?: number;
|
|
27
|
+
/** Border radius of the tiles in pixels. Default: `2` */
|
|
28
|
+
tileBorderRadius?: number;
|
|
27
29
|
}
|
|
28
30
|
export declare const TreemapDefaultConfig: TreemapConfigInterface<unknown>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ComponentDefaultConfig } from '../../core/component/config.js';
|
|
2
2
|
|
|
3
|
-
const TreemapDefaultConfig = Object.assign(Object.assign({}, ComponentDefaultConfig), { id: (d, i) => { var _a; return (_a = d.id) !== null && _a !== void 0 ? _a : i; }, value: undefined, tileColor: undefined, layers: [], tilePadding: 2, tilePaddingTop: undefined, labelInternalNodes: false, labelOffsetX: 4, labelOffsetY: 4 });
|
|
3
|
+
const TreemapDefaultConfig = Object.assign(Object.assign({}, ComponentDefaultConfig), { id: (d, i) => { var _a; return (_a = d.id) !== null && _a !== void 0 ? _a : i; }, value: undefined, tileColor: undefined, layers: [], tilePadding: 2, tilePaddingTop: undefined, labelInternalNodes: false, labelOffsetX: 4, labelOffsetY: 4, tileBorderRadius: 2 });
|
|
4
4
|
|
|
5
5
|
export { TreemapDefaultConfig };
|
|
6
6
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sources":["../../../src/components/treemap/config.ts"],"sourcesContent":["import { ComponentConfigInterface, ComponentDefaultConfig } from 'core/component/config'\nimport { ColorAccessor, NumericAccessor, StringAccessor } from 'types/accessor'\nimport { TreemapNode } from './types'\n\nexport interface TreemapConfigInterface<Datum> extends ComponentConfigInterface {\n id?: ((d: Datum, i: number) => string | number);\n /* Numeric accessor for segment size value. Default: `undefined`. */\n value?: NumericAccessor<Datum>;\n\n /** Array of accessor functions to defined the nested groups. Default: `[]` */\n layers: StringAccessor<Datum>[];\n\n /** A function that accepts a value number and returns a string. Default: `undefined` */\n numberFormat?: (value: number) => string;\n\n /** Color accessor function for tiles. Default: `undefined` */\n tileColor?: ColorAccessor<TreemapNode<Datum>>;\n\n /** Padding passed to D3 treemap layout. Default: `2` */\n tilePadding?: number;\n\n /**\n * Top padding passed to D3 treemap layout.\n * Useful to make room for internal node labels.\n * Default: `undefined`\n */\n tilePaddingTop?: number;\n\n /** Label internal nodes. Default: `false` */\n labelInternalNodes?: boolean;\n\n /** Label offset in the X direction. Default: `4` */\n labelOffsetX?: number;\n\n /** Label offset in the Y direction. Default: `4` */\n labelOffsetY?: number;\n}\n\nexport const TreemapDefaultConfig: TreemapConfigInterface<unknown> = {\n ...ComponentDefaultConfig,\n id: (d: unknown, i: number): string | number => (d as { id: string }).id ?? i,\n value: undefined,\n tileColor: undefined,\n layers: [],\n tilePadding: 2,\n tilePaddingTop: undefined,\n labelInternalNodes: false,\n labelOffsetX: 4,\n labelOffsetY: 4,\n}\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"config.js","sources":["../../../src/components/treemap/config.ts"],"sourcesContent":["import { ComponentConfigInterface, ComponentDefaultConfig } from 'core/component/config'\nimport { ColorAccessor, NumericAccessor, StringAccessor } from 'types/accessor'\nimport { TreemapNode } from './types'\n\nexport interface TreemapConfigInterface<Datum> extends ComponentConfigInterface {\n id?: ((d: Datum, i: number) => string | number);\n /* Numeric accessor for segment size value. Default: `undefined`. */\n value?: NumericAccessor<Datum>;\n\n /** Array of accessor functions to defined the nested groups. Default: `[]` */\n layers: StringAccessor<Datum>[];\n\n /** A function that accepts a value number and returns a string. Default: `undefined` */\n numberFormat?: (value: number) => string;\n\n /** Color accessor function for tiles. Default: `undefined` */\n tileColor?: ColorAccessor<TreemapNode<Datum>>;\n\n /** Padding passed to D3 treemap layout. Default: `2` */\n tilePadding?: number;\n\n /**\n * Top padding passed to D3 treemap layout.\n * Useful to make room for internal node labels.\n * Default: `undefined`\n */\n tilePaddingTop?: number;\n\n /** Label internal nodes. Default: `false` */\n labelInternalNodes?: boolean;\n\n /** Label offset in the X direction. Default: `4` */\n labelOffsetX?: number;\n\n /** Label offset in the Y direction. Default: `4` */\n labelOffsetY?: number;\n\n /** Border radius of the tiles in pixels. Default: `2` */\n tileBorderRadius?: number;\n}\n\nexport const TreemapDefaultConfig: TreemapConfigInterface<unknown> = {\n ...ComponentDefaultConfig,\n id: (d: unknown, i: number): string | number => (d as { id: string }).id ?? i,\n value: undefined,\n tileColor: undefined,\n layers: [],\n tilePadding: 2,\n tilePaddingTop: undefined,\n labelInternalNodes: false,\n labelOffsetX: 4,\n labelOffsetY: 4,\n tileBorderRadius: 2,\n}\n"],"names":[],"mappings":";;AAyCO,MAAM,oBAAoB,GAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAC5B,sBAAsB,CAAA,EAAA,EACzB,EAAE,EAAE,CAAC,CAAU,EAAE,CAAS,KAAsB,EAAA,IAAA,EAAA,CAAA,CAAA,OAAA,CAAC,EAAA,GAAA,CAAoB,CAAC,EAAE,MAAI,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,CAAC,CAAA,EAAA,EAC7E,KAAK,EAAE,SAAS,EAChB,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,EAAE,EACV,WAAW,EAAE,CAAC,EACd,cAAc,EAAE,SAAS,EACzB,kBAAkB,EAAE,KAAK,EACzB,YAAY,EAAE,CAAC,EACf,YAAY,EAAE,CAAC,EACf,gBAAgB,EAAE,CAAC;;;;"}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { select } from 'd3-selection';
|
|
1
2
|
import { hierarchy, treemap } from 'd3-hierarchy';
|
|
2
3
|
import { group, max } from 'd3-array';
|
|
3
4
|
import { scaleLinear } from 'd3-scale';
|
|
5
|
+
import { wrapSVGText } from '../../utils/text.js';
|
|
4
6
|
import { ComponentCore } from '../../core/component/index.js';
|
|
5
7
|
import { SeriesDataModel } from '../../data-models/series.js';
|
|
6
|
-
import { getColor } from '../../utils/color.js';
|
|
8
|
+
import { getColor, getHexValue, brighter, isDarkBackground } from '../../utils/color.js';
|
|
7
9
|
import { isNumber, getString, getNumber } from '../../utils/data.js';
|
|
8
10
|
import { smartTransition } from '../../utils/d3.js';
|
|
9
11
|
import { TreemapDefaultConfig } from './config.js';
|
|
10
12
|
import * as style from './style.js';
|
|
11
|
-
import { tiles, tile,
|
|
13
|
+
import { tiles, tile, label } from './style.js';
|
|
12
14
|
|
|
13
15
|
const defaultNumberFormat = (value) => `${value}`;
|
|
14
16
|
class Treemap extends ComponentCore {
|
|
@@ -67,11 +69,11 @@ class Treemap extends ComponentCore {
|
|
|
67
69
|
});
|
|
68
70
|
const treemapData = treemapLayout(rootNode);
|
|
69
71
|
const descendants = treemapData.descendants();
|
|
70
|
-
// Set up the
|
|
72
|
+
// Set up the brightness increase scale based on depth
|
|
71
73
|
const maxDepth = max(descendants, d => d.depth);
|
|
72
|
-
const
|
|
74
|
+
const brightnessIncrease = scaleLinear()
|
|
73
75
|
.domain([1, maxDepth])
|
|
74
|
-
.range([
|
|
76
|
+
.range([0, 1]);
|
|
75
77
|
// Set fill color and opacity for each node
|
|
76
78
|
treemapData
|
|
77
79
|
.eachBefore((node) => {
|
|
@@ -79,12 +81,14 @@ class Treemap extends ComponentCore {
|
|
|
79
81
|
return;
|
|
80
82
|
node.children.forEach((child, i) => {
|
|
81
83
|
const treemapChild = child;
|
|
82
|
-
// Calculate color for this child using the color accessor function
|
|
83
|
-
|
|
84
|
+
// Calculate base color for this child using the color accessor function
|
|
85
|
+
let color = getColor(treemapChild, config.tileColor, i, treemapChild.depth !== 1);
|
|
84
86
|
// If no color for this child, use the parent's color
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
|
|
87
|
+
color = color !== null && color !== void 0 ? color : node._fill;
|
|
88
|
+
// Convert CSS variables to hex values if needed
|
|
89
|
+
const hexColor = color ? getHexValue(color, this.g.node()) : null;
|
|
90
|
+
// Make the color brighter based on depth
|
|
91
|
+
treemapChild._fill = hexColor ? brighter(hexColor, brightnessIncrease(treemapChild.depth)) : null;
|
|
88
92
|
});
|
|
89
93
|
});
|
|
90
94
|
// Render tiles
|
|
@@ -100,38 +104,26 @@ class Treemap extends ComponentCore {
|
|
|
100
104
|
tilesEnter
|
|
101
105
|
.append('clipPath')
|
|
102
106
|
.attr('id', d => `clip-${d._id}`)
|
|
103
|
-
.append('rect');
|
|
104
|
-
// Tile background rectangles
|
|
105
|
-
tilesEnter
|
|
106
107
|
.append('rect')
|
|
107
|
-
.attr('
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
.attr('y', d => d.y0)
|
|
111
|
-
.attr('width', d => d.x1 - d.x0)
|
|
112
|
-
.attr('height', d => d.y1 - d.y0);
|
|
113
|
-
tiles.merge(tilesEnter).select(`rect.${tileBackground}`)
|
|
114
|
-
.call(selection => smartTransition(selection, duration)
|
|
115
|
-
.attr('x', d => d.x0)
|
|
116
|
-
.attr('y', d => d.y0)
|
|
117
|
-
.attr('width', d => d.x1 - d.x0)
|
|
118
|
-
.attr('height', d => d.y1 - d.y0));
|
|
119
|
-
// Tile foreground rectangles
|
|
108
|
+
.attr('rx', config.tileBorderRadius)
|
|
109
|
+
.attr('ry', config.tileBorderRadius);
|
|
110
|
+
// Tile rectangles
|
|
120
111
|
tilesEnter
|
|
121
112
|
.append('rect')
|
|
122
|
-
.attr('class',
|
|
113
|
+
.attr('class', tile)
|
|
114
|
+
.attr('rx', config.tileBorderRadius)
|
|
115
|
+
.attr('ry', config.tileBorderRadius)
|
|
123
116
|
// Initialize tile positions so that the initial transition is smooth
|
|
124
117
|
.attr('x', d => d.x0)
|
|
125
118
|
.attr('y', d => d.y0)
|
|
126
119
|
.attr('width', d => d.x1 - d.x0)
|
|
127
120
|
.attr('height', d => d.y1 - d.y0)
|
|
128
121
|
.style('fill', d => { var _a; return (_a = d._fill) !== null && _a !== void 0 ? _a : getColor(d, config.tileColor); })
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
tiles.merge(tilesEnter).select(`rect.${tileForeground}`)
|
|
122
|
+
.style('opacity', 0);
|
|
123
|
+
tiles.merge(tilesEnter).select(`rect.${tile}`)
|
|
132
124
|
.call(selection => smartTransition(selection, duration)
|
|
133
125
|
.style('fill', d => { var _a; return (_a = d._fill) !== null && _a !== void 0 ? _a : getColor(d, config.tileColor); })
|
|
134
|
-
.style('
|
|
126
|
+
.style('opacity', 1)
|
|
135
127
|
.attr('x', d => d.x0)
|
|
136
128
|
.attr('y', d => d.y0)
|
|
137
129
|
.attr('width', d => d.x1 - d.x0)
|
|
@@ -156,9 +148,21 @@ class Treemap extends ComponentCore {
|
|
|
156
148
|
.attr('clip-path', d => `url(#clip-${d._id})`)
|
|
157
149
|
.attr('x', d => d.x0 + config.labelOffsetX)
|
|
158
150
|
.attr('y', d => d.y0 + config.labelOffsetY)
|
|
159
|
-
.
|
|
151
|
+
.each(function (d) {
|
|
152
|
+
var _a;
|
|
153
|
+
const text = select(this);
|
|
160
154
|
// @ts-expect-error This is a workaround for the D3 types
|
|
161
|
-
|
|
155
|
+
const label = `${d.data[0]}: ${numberFormat(d.value)}`;
|
|
156
|
+
text.text(label);
|
|
157
|
+
// Set text color based on background darkness
|
|
158
|
+
const backgroundColor = (_a = d._fill) !== null && _a !== void 0 ? _a : getColor(d, config.tileColor);
|
|
159
|
+
const textColor = backgroundColor && isDarkBackground(backgroundColor) ? '#ffffff' : '#000000';
|
|
160
|
+
text.style('fill', textColor);
|
|
161
|
+
// Apply text wrapping to leaf nodes
|
|
162
|
+
if (!d.children) {
|
|
163
|
+
const availableWidth = d.x1 - d.x0 - (2 * config.labelOffsetX);
|
|
164
|
+
wrapSVGText(text, availableWidth);
|
|
165
|
+
}
|
|
162
166
|
});
|
|
163
167
|
// Exit
|
|
164
168
|
const tilesExit = tiles.exit();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/treemap/index.ts"],"sourcesContent":["import { Selection } from 'd3-selection'\nimport { hierarchy, treemap } from 'd3-hierarchy'\nimport { group, max } from 'd3-array'\nimport { scaleLinear } from 'd3-scale'\nimport { ComponentCore } from 'core/component'\nimport { SeriesDataModel } from 'data-models/series'\nimport { getColor } from 'utils/color'\nimport { getString, getNumber, isNumber } from 'utils/data'\nimport { smartTransition } from 'utils/d3'\nimport { TreemapConfigInterface, TreemapDefaultConfig } from './config'\nimport { TreemapNode } from './types'\n\nimport * as s from './style'\n\nconst defaultNumberFormat = (value: number): string => `${value}`\n\nexport class Treemap<Datum> extends ComponentCore<Datum[], TreemapConfigInterface<Datum>> {\n static selectors = s\n protected _defaultConfig = TreemapDefaultConfig as TreemapConfigInterface<Datum>\n public config: TreemapConfigInterface<Datum> = this._defaultConfig\n\n datamodel: SeriesDataModel<Datum> = new SeriesDataModel()\n tiles: Selection<SVGGElement, unknown, SVGGElement, unknown>\n\n constructor (config?: TreemapConfigInterface<Datum>) {\n super()\n if (config) this.setConfig(config)\n this.tiles = this.g.append('g').attr('class', s.tiles)\n }\n\n _render (customDuration?: number): void {\n const { config, datamodel: { data }, _width, _height } = this\n const duration = isNumber(customDuration) ? customDuration : config.duration\n const { numberFormat = defaultNumberFormat } = config\n\n if (!config.layers?.length) {\n console.warn('Unovis | Treemap: No layers defined')\n return\n }\n\n // Map each layer accessor function to get string values from the data array\n const layerAccessors = config.layers.map(layerAccessor => {\n return (i: number) => getString(data[i], layerAccessor, i)\n })\n\n // Group the data indices by the layer accessors to create a hierarchical structure\n const nestedData = group(data.keys(), ...layerAccessors as [(d: number) => string])\n\n // Create the hierarchy from the grouped data,\n // which by itself is not quite right because there is an extra\n // level of nesting that we don't want, just above the leaf nodes.\n const rootNode = hierarchy(nestedData)\n\n // Compute the aggregation\n if (config.value) {\n rootNode.sum(index => typeof index === 'number' && getNumber(data[index], config.value, index))\n } else {\n rootNode.count()\n }\n\n // Fix the hierarchy by removing the extra level of nesting\n rootNode.each(d => {\n if (!d.children) {\n d.parent.children = null\n }\n })\n\n const treemapLayout = treemap()\n .size([_width, _height])\n .round(true)\n .padding(config.tilePadding)\n\n if (this.config.tilePaddingTop !== undefined) {\n treemapLayout.paddingTop(config.tilePaddingTop)\n }\n\n // Generate unique IDs for each node before creating the treemap layout\n let nodeId = 0\n rootNode.each(d => {\n (d as unknown as TreemapNode<Datum>)._id = `node-${nodeId++}`\n })\n\n const treemapData = treemapLayout(rootNode) as TreemapNode<Datum>\n const descendants = treemapData.descendants()\n\n // Set up the opacity scale based on depth\n const maxDepth = max(descendants, d => d.depth)\n const opacity = scaleLinear()\n .domain([1, maxDepth])\n .range([1, 0.2])\n\n // Set fill color and opacity for each node\n treemapData\n .eachBefore((node) => {\n if (!node.children) return\n node.children.forEach((child, i) => {\n const treemapChild = child as TreemapNode<Datum>\n\n // Calculate color for this child using the color accessor function\n const color = getColor(treemapChild, config.tileColor, i, treemapChild.depth !== 1)\n\n // If no color for this child, use the parent's color\n treemapChild._fill = color ?? (node as TreemapNode<Datum>)._fill\n\n // Set opacity based on depth\n treemapChild._fillOpacity = color === null ? opacity(treemapChild.depth) : null\n })\n })\n\n // Render tiles\n const visibleNodes = descendants.filter(d => d.depth > 0)\n const tiles = this.tiles\n .selectAll<SVGGElement, TreemapNode<Datum>>(`g.${s.tile}`)\n .data(visibleNodes, d => d._id)\n const tilesEnter = tiles\n .enter()\n .append('g')\n .attr('class', s.tile)\n\n // Add clipPath elements\n tilesEnter\n .append('clipPath')\n .attr('id', d => `clip-${d._id}`)\n .append('rect')\n\n // Tile background rectangles\n tilesEnter\n .append('rect')\n .attr('class', s.tileBackground)\n\n // Initialize tile positions so that the initial transition is smooth\n .attr('x', d => d.x0)\n .attr('y', d => d.y0)\n .attr('width', d => d.x1 - d.x0)\n .attr('height', d => d.y1 - d.y0)\n\n tiles.merge(tilesEnter).select(`rect.${s.tileBackground}`)\n .call(selection => smartTransition(selection, duration)\n .attr('x', d => d.x0)\n .attr('y', d => d.y0)\n .attr('width', d => d.x1 - d.x0)\n .attr('height', d => d.y1 - d.y0)\n )\n\n // Tile foreground rectangles\n tilesEnter\n .append('rect')\n .attr('class', s.tileForeground)\n // Initialize tile positions so that the initial transition is smooth\n .attr('x', d => d.x0)\n .attr('y', d => d.y0)\n .attr('width', d => d.x1 - d.x0)\n .attr('height', d => d.y1 - d.y0)\n .style('fill', d => d._fill ?? getColor(d, config.tileColor))\n\n // Make the tiles fade in on enter\n .style('fill-opacity', 0)\n\n tiles.merge(tilesEnter).select(`rect.${s.tileForeground}`)\n .call(selection => smartTransition(selection, duration)\n .style('fill', d => d._fill ?? getColor(d, config.tileColor))\n .style('fill-opacity', d => d._fillOpacity ?? 1)\n .attr('x', d => d.x0)\n .attr('y', d => d.y0)\n .attr('width', d => d.x1 - d.x0)\n .attr('height', d => d.y1 - d.y0)\n )\n\n // Update clipPath rects\n tiles.merge(tilesEnter).select('clipPath rect')\n .call(selection => smartTransition(selection, duration)\n .attr('x', d => d.x0)\n .attr('y', d => d.y0)\n .attr('width', d => d.x1 - d.x0)\n .attr('height', d => d.y1 - d.y0)\n )\n\n // Tile labels\n tilesEnter\n .append('text')\n .attr('class', s.label)\n .attr('clip-path', d => `url(#clip-${d._id})`)\n tiles.merge(tilesEnter)\n .filter(config.labelInternalNodes\n ? () => true\n : d => !d.children\n )\n .select(`text.${s.label}`)\n .attr('clip-path', d => `url(#clip-${d._id})`)\n .attr('x', d => d.x0 + config.labelOffsetX)\n .attr('y', d => d.y0 + config.labelOffsetY)\n .text(d => {\n // @ts-expect-error This is a workaround for the D3 types\n return `${d.data[0]}: ${numberFormat(d.value)}`\n })\n\n // Exit\n const tilesExit = tiles.exit()\n smartTransition(tilesExit, duration)\n .style('opacity', 0)\n .remove()\n }\n}\n"],"names":["s.tiles","s.tile","s.tileBackground","s.tileForeground","s.label","s"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/components/treemap/index.ts"],"sourcesContent":["import { Selection, select } from 'd3-selection'\nimport { hierarchy, treemap } from 'd3-hierarchy'\nimport { group, max } from 'd3-array'\nimport { scaleLinear } from 'd3-scale'\nimport { wrapSVGText } from 'utils/text'\nimport { ComponentCore } from 'core/component'\nimport { SeriesDataModel } from 'data-models/series'\nimport { getColor, brighter, getHexValue, isDarkBackground } from 'utils/color'\nimport { getString, getNumber, isNumber } from 'utils/data'\nimport { smartTransition } from 'utils/d3'\nimport { TreemapConfigInterface, TreemapDefaultConfig } from './config'\nimport { TreemapNode } from './types'\n\nimport * as s from './style'\n\nconst defaultNumberFormat = (value: number): string => `${value}`\n\nexport class Treemap<Datum> extends ComponentCore<Datum[], TreemapConfigInterface<Datum>> {\n static selectors = s\n protected _defaultConfig = TreemapDefaultConfig as TreemapConfigInterface<Datum>\n public config: TreemapConfigInterface<Datum> = this._defaultConfig\n\n datamodel: SeriesDataModel<Datum> = new SeriesDataModel()\n tiles: Selection<SVGGElement, unknown, SVGGElement, unknown>\n\n constructor (config?: TreemapConfigInterface<Datum>) {\n super()\n if (config) this.setConfig(config)\n this.tiles = this.g.append('g').attr('class', s.tiles)\n }\n\n _render (customDuration?: number): void {\n const { config, datamodel: { data }, _width, _height } = this\n const duration = isNumber(customDuration) ? customDuration : config.duration\n const { numberFormat = defaultNumberFormat } = config\n\n if (!config.layers?.length) {\n console.warn('Unovis | Treemap: No layers defined')\n return\n }\n\n // Map each layer accessor function to get string values from the data array\n const layerAccessors = config.layers.map(layerAccessor => {\n return (i: number) => getString(data[i], layerAccessor, i)\n })\n\n // Group the data indices by the layer accessors to create a hierarchical structure\n const nestedData = group(data.keys(), ...layerAccessors as [(d: number) => string])\n\n // Create the hierarchy from the grouped data,\n // which by itself is not quite right because there is an extra\n // level of nesting that we don't want, just above the leaf nodes.\n const rootNode = hierarchy(nestedData)\n\n // Compute the aggregation\n if (config.value) {\n rootNode.sum(index => typeof index === 'number' && getNumber(data[index], config.value, index))\n } else {\n rootNode.count()\n }\n\n // Fix the hierarchy by removing the extra level of nesting\n rootNode.each(d => {\n if (!d.children) {\n d.parent.children = null\n }\n })\n\n const treemapLayout = treemap()\n .size([_width, _height])\n .round(true)\n .padding(config.tilePadding)\n\n if (this.config.tilePaddingTop !== undefined) {\n treemapLayout.paddingTop(config.tilePaddingTop)\n }\n\n // Generate unique IDs for each node before creating the treemap layout\n let nodeId = 0\n rootNode.each(d => {\n (d as unknown as TreemapNode<Datum>)._id = `node-${nodeId++}`\n })\n\n const treemapData = treemapLayout(rootNode) as TreemapNode<Datum>\n const descendants = treemapData.descendants()\n\n // Set up the brightness increase scale based on depth\n const maxDepth = max(descendants, d => d.depth)\n const brightnessIncrease = scaleLinear()\n .domain([1, maxDepth])\n .range([0, 1])\n\n // Set fill color and opacity for each node\n treemapData\n .eachBefore((node) => {\n if (!node.children) return\n node.children.forEach((child, i) => {\n const treemapChild = child as TreemapNode<Datum>\n\n // Calculate base color for this child using the color accessor function\n let color = getColor(treemapChild, config.tileColor, i, treemapChild.depth !== 1)\n\n // If no color for this child, use the parent's color\n color = color ?? (node as TreemapNode<Datum>)._fill\n\n // Convert CSS variables to hex values if needed\n const hexColor = color ? getHexValue(color, this.g.node()) : null\n\n // Make the color brighter based on depth\n treemapChild._fill = hexColor ? brighter(hexColor, brightnessIncrease(treemapChild.depth)) : null\n })\n })\n\n // Render tiles\n const visibleNodes = descendants.filter(d => d.depth > 0)\n const tiles = this.tiles\n .selectAll<SVGGElement, TreemapNode<Datum>>(`g.${s.tile}`)\n .data(visibleNodes, d => d._id)\n const tilesEnter = tiles\n .enter()\n .append('g')\n .attr('class', s.tile)\n\n // Add clipPath elements\n tilesEnter\n .append('clipPath')\n .attr('id', d => `clip-${d._id}`)\n .append('rect')\n .attr('rx', config.tileBorderRadius)\n .attr('ry', config.tileBorderRadius)\n\n // Tile rectangles\n tilesEnter\n .append('rect')\n .attr('class', s.tile)\n .attr('rx', config.tileBorderRadius)\n .attr('ry', config.tileBorderRadius)\n // Initialize tile positions so that the initial transition is smooth\n .attr('x', d => d.x0)\n .attr('y', d => d.y0)\n .attr('width', d => d.x1 - d.x0)\n .attr('height', d => d.y1 - d.y0)\n .style('fill', d => d._fill ?? getColor(d, config.tileColor))\n .style('opacity', 0)\n\n tiles.merge(tilesEnter).select(`rect.${s.tile}`)\n .call(selection => smartTransition(selection, duration)\n .style('fill', d => d._fill ?? getColor(d, config.tileColor))\n .style('opacity', 1)\n .attr('x', d => d.x0)\n .attr('y', d => d.y0)\n .attr('width', d => d.x1 - d.x0)\n .attr('height', d => d.y1 - d.y0)\n )\n\n // Update clipPath rects\n tiles.merge(tilesEnter).select('clipPath rect')\n .call(selection => smartTransition(selection, duration)\n .attr('x', d => d.x0)\n .attr('y', d => d.y0)\n .attr('width', d => d.x1 - d.x0)\n .attr('height', d => d.y1 - d.y0)\n )\n\n // Tile labels\n tilesEnter\n .append('text')\n .attr('class', s.label)\n .attr('clip-path', d => `url(#clip-${d._id})`)\n tiles.merge(tilesEnter)\n .filter(config.labelInternalNodes\n ? () => true\n : d => !d.children\n )\n .select(`text.${s.label}`)\n .attr('clip-path', d => `url(#clip-${d._id})`)\n .attr('x', d => d.x0 + config.labelOffsetX)\n .attr('y', d => d.y0 + config.labelOffsetY)\n .each(function (d) {\n const text = select(this) as unknown as Selection<SVGTextElement, any, SVGElement, any>\n\n // @ts-expect-error This is a workaround for the D3 types\n const label = `${d.data[0]}: ${numberFormat(d.value)}`\n text.text(label)\n\n // Set text color based on background darkness\n const backgroundColor = d._fill ?? getColor(d, config.tileColor)\n const textColor = backgroundColor && isDarkBackground(backgroundColor) ? '#ffffff' : '#000000'\n text.style('fill', textColor)\n\n // Apply text wrapping to leaf nodes\n if (!d.children) {\n const availableWidth = d.x1 - d.x0 - (2 * config.labelOffsetX)\n wrapSVGText(text, availableWidth)\n }\n })\n\n // Exit\n const tilesExit = tiles.exit()\n smartTransition(tilesExit, duration)\n .style('opacity', 0)\n .remove()\n }\n}\n"],"names":["s.tiles","s.tile","s.label","s"],"mappings":";;;;;;;;;;;;;;AAeA,MAAM,mBAAmB,GAAG,CAAC,KAAa,KAAa,CAAA,EAAG,KAAK,CAAA,CAAE,CAAA;AAE3D,MAAO,OAAe,SAAQ,aAAqD,CAAA;AAQvF,IAAA,WAAA,CAAa,MAAsC,EAAA;AACjD,QAAA,KAAK,EAAE,CAAA;QAPC,IAAc,CAAA,cAAA,GAAG,oBAAqD,CAAA;AACzE,QAAA,IAAA,CAAA,MAAM,GAAkC,IAAI,CAAC,cAAc,CAAA;AAElE,QAAA,IAAA,CAAA,SAAS,GAA2B,IAAI,eAAe,EAAE,CAAA;AAKvD,QAAA,IAAI,MAAM;AAAE,YAAA,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;QAClC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,EAAEA,KAAO,CAAC,CAAA;KACvD;AAED,IAAA,OAAO,CAAE,cAAuB,EAAA;;AAC9B,QAAA,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAA;AAC7D,QAAA,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,GAAG,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAA;AAC5E,QAAA,MAAM,EAAE,YAAY,GAAG,mBAAmB,EAAE,GAAG,MAAM,CAAA;QAErD,IAAI,EAAC,CAAA,EAAA,GAAA,MAAM,CAAC,MAAM,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAE,MAAM,CAAA,EAAE;AAC1B,YAAA,OAAO,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAA;YACnD,OAAM;AACP,SAAA;;QAGD,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,IAAG;AACvD,YAAA,OAAO,CAAC,CAAS,KAAK,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAA;AAC5D,SAAC,CAAC,CAAA;;AAGF,QAAA,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,GAAG,cAAyC,CAAC,CAAA;;;;AAKnF,QAAA,MAAM,QAAQ,GAAG,SAAS,CAAC,UAAU,CAAC,CAAA;;QAGtC,IAAI,MAAM,CAAC,KAAK,EAAE;YAChB,QAAQ,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;AAChG,SAAA;AAAM,aAAA;YACL,QAAQ,CAAC,KAAK,EAAE,CAAA;AACjB,SAAA;;AAGD,QAAA,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAG;AAChB,YAAA,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE;AACf,gBAAA,CAAC,CAAC,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAA;AACzB,aAAA;AACH,SAAC,CAAC,CAAA;QAEF,MAAM,aAAa,GAAG,OAAO,EAAE;AAC5B,aAAA,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;aACvB,KAAK,CAAC,IAAI,CAAC;AACX,aAAA,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;AAE9B,QAAA,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,KAAK,SAAS,EAAE;AAC5C,YAAA,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,CAAA;AAChD,SAAA;;QAGD,IAAI,MAAM,GAAG,CAAC,CAAA;AACd,QAAA,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAG;AACf,YAAA,CAAmC,CAAC,GAAG,GAAG,QAAQ,MAAM,EAAE,EAAE,CAAA;AAC/D,SAAC,CAAC,CAAA;AAEF,QAAA,MAAM,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAuB,CAAA;AACjE,QAAA,MAAM,WAAW,GAAG,WAAW,CAAC,WAAW,EAAE,CAAA;;AAG7C,QAAA,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAA;QAC/C,MAAM,kBAAkB,GAAG,WAAW,EAAE;AACrC,aAAA,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AACrB,aAAA,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;;QAGhB,WAAW;AACR,aAAA,UAAU,CAAC,CAAC,IAAI,KAAI;YACnB,IAAI,CAAC,IAAI,CAAC,QAAQ;gBAAE,OAAM;YAC1B,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,KAAI;gBACjC,MAAM,YAAY,GAAG,KAA2B,CAAA;;AAGhD,gBAAA,IAAI,KAAK,GAAG,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,EAAE,YAAY,CAAC,KAAK,KAAK,CAAC,CAAC,CAAA;;gBAGjF,KAAK,GAAG,KAAK,KAAA,IAAA,IAAL,KAAK,KAAA,KAAA,CAAA,GAAL,KAAK,GAAK,IAA2B,CAAC,KAAK,CAAA;;gBAGnD,MAAM,QAAQ,GAAG,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAA;;gBAGjE,YAAY,CAAC,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAA;AACnG,aAAC,CAAC,CAAA;AACJ,SAAC,CAAC,CAAA;;AAGJ,QAAA,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;AACzD,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK;AACrB,aAAA,SAAS,CAAkC,CAAK,EAAA,EAAAC,IAAM,EAAE,CAAC;aACzD,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;QACjC,MAAM,UAAU,GAAG,KAAK;AACrB,aAAA,KAAK,EAAE;aACP,MAAM,CAAC,GAAG,CAAC;AACX,aAAA,IAAI,CAAC,OAAO,EAAEA,IAAM,CAAC,CAAA;;QAGxB,UAAU;aACP,MAAM,CAAC,UAAU,CAAC;AAClB,aAAA,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAA,KAAA,EAAQ,CAAC,CAAC,GAAG,CAAA,CAAE,CAAC;aAChC,MAAM,CAAC,MAAM,CAAC;AACd,aAAA,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC;AACnC,aAAA,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAA;;QAGtC,UAAU;aACP,MAAM,CAAC,MAAM,CAAC;AACd,aAAA,IAAI,CAAC,OAAO,EAAEA,IAAM,CAAC;AACrB,aAAA,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC;AACnC,aAAA,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,gBAAgB,CAAC;;aAEnC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;aACpB,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;AACpB,aAAA,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;AAC/B,aAAA,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;aAChC,KAAK,CAAC,MAAM,EAAE,CAAC,IAAG,EAAA,IAAA,EAAA,CAAA,CAAC,OAAA,CAAA,EAAA,GAAA,CAAC,CAAC,KAAK,MAAI,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA,EAAA,CAAC;AAC5D,aAAA,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;AAEtB,QAAA,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAQ,KAAA,EAAAA,IAAM,EAAE,CAAC;aAC7C,IAAI,CAAC,SAAS,IAAI,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC;aACpD,KAAK,CAAC,MAAM,EAAE,CAAC,IAAG,EAAA,IAAA,EAAA,CAAA,CAAC,OAAA,CAAA,EAAA,GAAA,CAAC,CAAC,KAAK,MAAI,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA,EAAA,CAAC;AAC5D,aAAA,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;aACnB,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;aACpB,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;AACpB,aAAA,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;AAC/B,aAAA,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAClC,CAAA;;QAGH,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC;aAC5C,IAAI,CAAC,SAAS,IAAI,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC;aACpD,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;aACpB,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;AACpB,aAAA,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;AAC/B,aAAA,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAClC,CAAA;;QAGH,UAAU;aACP,MAAM,CAAC,MAAM,CAAC;AACd,aAAA,IAAI,CAAC,OAAO,EAAEC,KAAO,CAAC;AACtB,aAAA,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,CAAA,UAAA,EAAa,CAAC,CAAC,GAAG,CAAA,CAAA,CAAG,CAAC,CAAA;AAChD,QAAA,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC;aACpB,MAAM,CAAC,MAAM,CAAC,kBAAkB;AAC/B,cAAE,MAAM,IAAI;cACV,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CACnB;AACA,aAAA,MAAM,CAAC,CAAQ,KAAA,EAAAA,KAAO,EAAE,CAAC;AACzB,aAAA,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,CAAA,UAAA,EAAa,CAAC,CAAC,GAAG,CAAA,CAAA,CAAG,CAAC;AAC7C,aAAA,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC;AAC1C,aAAA,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,YAAY,CAAC;aAC1C,IAAI,CAAC,UAAU,CAAC,EAAA;;AACf,YAAA,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAA+D,CAAA;;AAGvF,YAAA,MAAM,KAAK,GAAG,CAAA,EAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA,EAAA,EAAK,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAA;AACtD,YAAA,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;;AAGhB,YAAA,MAAM,eAAe,GAAG,CAAA,EAAA,GAAA,CAAC,CAAC,KAAK,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;AAChE,YAAA,MAAM,SAAS,GAAG,eAAe,IAAI,gBAAgB,CAAC,eAAe,CAAC,GAAG,SAAS,GAAG,SAAS,CAAA;AAC9F,YAAA,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;;AAG7B,YAAA,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE;AACf,gBAAA,MAAM,cAAc,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,CAAA;AAC9D,gBAAA,WAAW,CAAC,IAAI,EAAE,cAAc,CAAC,CAAA;AAClC,aAAA;AACH,SAAC,CAAC,CAAA;;AAGJ,QAAA,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;AAC9B,QAAA,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC;AACjC,aAAA,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;AACnB,aAAA,MAAM,EAAE,CAAA;KACZ;;AAxLM,OAAS,CAAA,SAAA,GAAGC,KAAC;;;;"}
|
package/index.js
CHANGED
|
@@ -63,7 +63,7 @@ export { NestedDonutDirection, NestedDonutSegmentLabelAlignment } from './compon
|
|
|
63
63
|
export { arrayOfIndices, clamp, clean, cloneDeep, countUnique, ensureArray, filterDataByRange, flatten, getBoolean, getExtent, getMax, getMin, getNearest, getNumber, getStackedData, getStackedExtent, getStackedValues, getString, getValue, groupBy, isAClassInstance, isArray, isEmpty, isEqual, isFunction, isNil, isNumber, isNumberWithinRange, isObject, isPlainObject, isString, isUndefined, merge, omit, shallowDiff, sortBy, throttle, unique, without } from './utils/data.js';
|
|
64
64
|
export { allowedSvgTextTags, escapeStringKeepHash, estimateStringPixelLength, estimateTextSize, estimateWrappedTextHeight, getPreciseStringLengthPx, getWrappedText, kebabCase, kebabCaseToCamel, renderTextIntoFrame, renderTextToSvgTextElement, splitString, trimSVGText, trimString, trimStringEnd, trimStringMiddle, trimStringStart, wrapSVGText } from './utils/text.js';
|
|
65
65
|
export { allowedSvgTags, getTransformValues, isStringSvg, sanitizeSvgString, transformValuesToString } from './utils/svg.js';
|
|
66
|
-
export { getColor, getHexValue, hexToBrightness, hexToRgb, rgbToBrightness, rgbaToRgb } from './utils/color.js';
|
|
66
|
+
export { brighter, getColor, getHexValue, hexToBrightness, hexToRgb, isDarkBackground, rgbToBrightness, rgbaToRgb } from './utils/color.js';
|
|
67
67
|
export { circlePath, convertLineToArc, polygon, roundedRectPath, scoreRectPath } from './utils/path.js';
|
|
68
68
|
export { getCSSVariableValue, getCSSVariableValueInPixels, getHref, getPixelValue, guid, isStringCSSVariable, parseUnit, rectIntersect, stringToHtmlId } from './utils/misc.js';
|
|
69
69
|
export { DefaultRange } from './utils/scale.js';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unovis/ts",
|
|
3
3
|
"description": "Modular data visualization framework for React, Angular, Svelte, Vue, Solid, and vanilla TypeScript or JavaScript",
|
|
4
|
-
"version": "1.5.1-exf.
|
|
4
|
+
"version": "1.5.1-exf.13",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/f5/unovis.git",
|
package/utils/color.d.ts
CHANGED
|
@@ -11,4 +11,18 @@ export declare function rgbToBrightness(rgb: RGBColor): number;
|
|
|
11
11
|
export declare function hexToBrightness(hex: string): number;
|
|
12
12
|
export declare function getHexValue(s: string, context: HTMLElement | SVGElement): string;
|
|
13
13
|
export declare function rgbaToRgb(rgba: string, backgroundColor?: string): RGBColor;
|
|
14
|
+
/**
|
|
15
|
+
* Determines if a background color is considered "dark" based on its brightness
|
|
16
|
+
* @param backgroundColor - The color to check (hex, rgb, or rgba)
|
|
17
|
+
* @param threshold - Optional brightness threshold (0-1, default 0.5)
|
|
18
|
+
* @returns true if the background is dark, false if it's light
|
|
19
|
+
*/
|
|
20
|
+
export declare function isDarkBackground(backgroundColor: string, threshold?: number): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Makes a color brighter by a certain amount
|
|
23
|
+
* @param inputColor - The color to brighten (hex, rgb, or rgba)
|
|
24
|
+
* @param amount - Amount to brighten by (0-1)
|
|
25
|
+
* @returns The brightened color in hex format
|
|
26
|
+
*/
|
|
27
|
+
export declare function brighter(inputColor: string, amount: number): string;
|
|
14
28
|
export {};
|
package/utils/color.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { color } from 'd3-color';
|
|
1
|
+
import { color, hcl } from 'd3-color';
|
|
2
2
|
import { getCSSColorVariable } from '../styles/colors.js';
|
|
3
3
|
import { getString, isNumber } from './data.js';
|
|
4
4
|
import { isStringCSSVariable, getCSSVariableValue } from './misc.js';
|
|
@@ -42,7 +42,31 @@ function rgbaToRgb(rgba, backgroundColor) {
|
|
|
42
42
|
g: Math.round((rgb.opacity * (rgb.g / 255) + (alpha * (bg.g / 255))) * 255),
|
|
43
43
|
b: Math.round((rgb.opacity * (rgb.b / 255) + (alpha * (bg.b / 255))) * 255),
|
|
44
44
|
};
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Determines if a background color is considered "dark" based on its brightness
|
|
48
|
+
* @param backgroundColor - The color to check (hex, rgb, or rgba)
|
|
49
|
+
* @param threshold - Optional brightness threshold (0-1, default 0.5)
|
|
50
|
+
* @returns true if the background is dark, false if it's light
|
|
51
|
+
*/
|
|
52
|
+
function isDarkBackground(backgroundColor, threshold = 0.6) {
|
|
53
|
+
const hex = getHexValue(backgroundColor, document.body);
|
|
54
|
+
if (!hex)
|
|
55
|
+
return false;
|
|
56
|
+
return hexToBrightness(hex) < threshold;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Makes a color brighter by a certain amount
|
|
60
|
+
* @param inputColor - The color to brighten (hex, rgb, or rgba)
|
|
61
|
+
* @param amount - Amount to brighten by (0-1)
|
|
62
|
+
* @returns The brightened color in hex format
|
|
63
|
+
*/
|
|
64
|
+
function brighter(inputColor, amount) {
|
|
65
|
+
const c = hcl(inputColor);
|
|
66
|
+
if (!c)
|
|
67
|
+
return inputColor;
|
|
68
|
+
return c.brighter(amount).formatHex();
|
|
45
69
|
}
|
|
46
70
|
|
|
47
|
-
export { getColor, getHexValue, hexToBrightness, hexToRgb, rgbToBrightness, rgbaToRgb };
|
|
71
|
+
export { brighter, getColor, getHexValue, hexToBrightness, hexToRgb, isDarkBackground, rgbToBrightness, rgbaToRgb };
|
|
48
72
|
//# sourceMappingURL=color.js.map
|
package/utils/color.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"color.js","sources":["../../src/utils/color.ts"],"sourcesContent":["import { color } from 'd3-color'\n\n// Core\nimport { getCSSColorVariable } from 'styles/colors'\n\n// Utils\nimport { ColorAccessor, StringAccessor } from 'types/accessor'\nimport { getString, isNumber } from 'utils/data'\nimport { isStringCSSVariable, getCSSVariableValue } from 'utils/misc'\n\ntype RGBColor = { r: number; g: number; b: number }\n\n/** Retrieves color from the data if provided, fallbacks to CSS variables if the index was passed */\nexport function getColor<T> (\n d: T,\n accessor: ColorAccessor<T>,\n index?: number,\n dontFallbackToCssVar?: boolean\n): string | null {\n if (Array.isArray(accessor) && isFinite(index)) return accessor[index % accessor.length]\n\n const value = getString(d, accessor as StringAccessor<T>, index)\n return (value || ((isNumber(index) && !dontFallbackToCssVar) ? `var(${getCSSColorVariable(index)})` : null))\n}\n\nexport function hexToRgb (hex: string): RGBColor {\n const parsed = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex)\n return parsed ? {\n r: parseInt(parsed[1], 16),\n g: parseInt(parsed[2], 16),\n b: parseInt(parsed[3], 16),\n } : { r: 0, g: 0, b: 0 }\n}\n\nexport function rgbToBrightness (rgb: RGBColor): number {\n return (0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b) / 255\n}\n\nexport function hexToBrightness (hex: string): number {\n const rgb = hexToRgb(hex)\n return rgbToBrightness(rgb)\n}\n\nexport function getHexValue (s: string, context: HTMLElement | SVGElement): string {\n const hex = isStringCSSVariable(s) ? getCSSVariableValue(s, context) : s\n return color(hex)?.formatHex()\n}\n\nexport function rgbaToRgb (rgba: string, backgroundColor?: string): RGBColor {\n const rgb = color(rgba)?.rgb()\n if (!rgb || rgb.opacity === 1) return rgb\n const alpha = 1 - rgb.opacity\n const bg = color(backgroundColor ?? '#fff').rgb()\n return {\n r: Math.round((rgb.opacity * (rgb.r / 255) + (alpha * (bg.r / 255))) * 255),\n g: Math.round((rgb.opacity * (rgb.g / 255) + (alpha * (bg.g / 255))) * 255),\n b: Math.round((rgb.opacity * (rgb.b / 255) + (alpha * (bg.b / 255))) * 255),\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"color.js","sources":["../../src/utils/color.ts"],"sourcesContent":["import { color, hcl } from 'd3-color'\n\n// Core\nimport { getCSSColorVariable } from 'styles/colors'\n\n// Utils\nimport { ColorAccessor, StringAccessor } from 'types/accessor'\nimport { getString, isNumber } from 'utils/data'\nimport { isStringCSSVariable, getCSSVariableValue } from 'utils/misc'\n\ntype RGBColor = { r: number; g: number; b: number }\n\n/** Retrieves color from the data if provided, fallbacks to CSS variables if the index was passed */\nexport function getColor<T> (\n d: T,\n accessor: ColorAccessor<T>,\n index?: number,\n dontFallbackToCssVar?: boolean\n): string | null {\n if (Array.isArray(accessor) && isFinite(index)) return accessor[index % accessor.length]\n\n const value = getString(d, accessor as StringAccessor<T>, index)\n return (value || ((isNumber(index) && !dontFallbackToCssVar) ? `var(${getCSSColorVariable(index)})` : null))\n}\n\nexport function hexToRgb (hex: string): RGBColor {\n const parsed = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex)\n return parsed ? {\n r: parseInt(parsed[1], 16),\n g: parseInt(parsed[2], 16),\n b: parseInt(parsed[3], 16),\n } : { r: 0, g: 0, b: 0 }\n}\n\nexport function rgbToBrightness (rgb: RGBColor): number {\n return (0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b) / 255\n}\n\nexport function hexToBrightness (hex: string): number {\n const rgb = hexToRgb(hex)\n return rgbToBrightness(rgb)\n}\n\nexport function getHexValue (s: string, context: HTMLElement | SVGElement): string {\n const hex = isStringCSSVariable(s) ? getCSSVariableValue(s, context) : s\n return color(hex)?.formatHex()\n}\n\nexport function rgbaToRgb (rgba: string, backgroundColor?: string): RGBColor {\n const rgb = color(rgba)?.rgb()\n if (!rgb || rgb.opacity === 1) return rgb\n const alpha = 1 - rgb.opacity\n const bg = color(backgroundColor ?? '#fff').rgb()\n return {\n r: Math.round((rgb.opacity * (rgb.r / 255) + (alpha * (bg.r / 255))) * 255),\n g: Math.round((rgb.opacity * (rgb.g / 255) + (alpha * (bg.g / 255))) * 255),\n b: Math.round((rgb.opacity * (rgb.b / 255) + (alpha * (bg.b / 255))) * 255),\n }\n}\n\n/**\n * Determines if a background color is considered \"dark\" based on its brightness\n * @param backgroundColor - The color to check (hex, rgb, or rgba)\n * @param threshold - Optional brightness threshold (0-1, default 0.5)\n * @returns true if the background is dark, false if it's light\n */\nexport function isDarkBackground (backgroundColor: string, threshold = 0.6): boolean {\n const hex = getHexValue(backgroundColor, document.body)\n if (!hex) return false\n return hexToBrightness(hex) < threshold\n}\n\n/**\n * Makes a color brighter by a certain amount\n * @param inputColor - The color to brighten (hex, rgb, or rgba)\n * @param amount - Amount to brighten by (0-1)\n * @returns The brightened color in hex format\n */\nexport function brighter (inputColor: string, amount: number): string {\n const c = hcl(inputColor)\n if (!c) return inputColor\n return c.brighter(amount).formatHex()\n}\n"],"names":[],"mappings":"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"}
|
package/utils/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { arrayOfIndices, clamp, clean, cloneDeep, countUnique, ensureArray, filterDataByRange, flatten, getBoolean, getExtent, getMax, getMin, getNearest, getNumber, getStackedData, getStackedExtent, getStackedValues, getString, getValue, groupBy, isAClassInstance, isArray, isEmpty, isEqual, isFunction, isNil, isNumber, isNumberWithinRange, isObject, isPlainObject, isString, isUndefined, merge, omit, shallowDiff, sortBy, throttle, unique, without } from './data.js';
|
|
2
2
|
export { allowedSvgTextTags, escapeStringKeepHash, estimateStringPixelLength, estimateTextSize, estimateWrappedTextHeight, getPreciseStringLengthPx, getWrappedText, kebabCase, kebabCaseToCamel, renderTextIntoFrame, renderTextToSvgTextElement, splitString, trimSVGText, trimString, trimStringEnd, trimStringMiddle, trimStringStart, wrapSVGText } from './text.js';
|
|
3
3
|
export { allowedSvgTags, getTransformValues, isStringSvg, sanitizeSvgString, transformValuesToString } from './svg.js';
|
|
4
|
-
export { getColor, getHexValue, hexToBrightness, hexToRgb, rgbToBrightness, rgbaToRgb } from './color.js';
|
|
4
|
+
export { brighter, getColor, getHexValue, hexToBrightness, hexToRgb, isDarkBackground, rgbToBrightness, rgbaToRgb } from './color.js';
|
|
5
5
|
export { circlePath, convertLineToArc, polygon, roundedRectPath, scoreRectPath } from './path.js';
|
|
6
6
|
export { getCSSVariableValue, getCSSVariableValueInPixels, getHref, getPixelValue, guid, isStringCSSVariable, parseUnit, rectIntersect, stringToHtmlId } from './misc.js';
|
|
7
7
|
import './type.js';
|