@unovis/ts 1.7.0-pre.0 → 1.7.0-pre.2
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/annotations/config.d.ts +2 -0
- package/components/annotations/config.js +1 -1
- package/components/annotations/config.js.map +1 -1
- package/components/annotations/index.d.ts +1 -0
- package/components/annotations/index.js +25 -10
- package/components/annotations/index.js.map +1 -1
- package/components/annotations/style.d.ts +2 -0
- package/components/annotations/style.js +8 -1
- package/components/annotations/style.js.map +1 -1
- package/components/area/config.d.ts +9 -1
- package/components/area/config.js +1 -1
- package/components/area/config.js.map +1 -1
- package/components/area/index.d.ts +6 -0
- package/components/area/index.js +74 -4
- package/components/area/index.js.map +1 -1
- package/components/area/style.d.ts +1 -0
- package/components/area/style.js +7 -1
- package/components/area/style.js.map +1 -1
- package/components/axis/index.d.ts +2 -0
- package/components/axis/index.js +45 -7
- package/components/axis/index.js.map +1 -1
- package/components/bullet-legend/index.d.ts +2 -0
- package/components/bullet-legend/index.js +9 -5
- package/components/bullet-legend/index.js.map +1 -1
- package/components/bullet-legend/modules/shape.js +3 -2
- package/components/bullet-legend/modules/shape.js.map +1 -1
- package/components/crosshair/index.js +3 -2
- package/components/crosshair/index.js.map +1 -1
- package/components/flow-legend/config.d.ts +10 -0
- package/components/flow-legend/config.js +4 -0
- package/components/flow-legend/config.js.map +1 -1
- package/components/flow-legend/index.d.ts +6 -2
- package/components/flow-legend/index.js +34 -16
- package/components/flow-legend/index.js.map +1 -1
- package/components/flow-legend/style.d.ts +3 -3
- package/components/flow-legend/style.js +30 -26
- package/components/flow-legend/style.js.map +1 -1
- package/components/graph/modules/link/index.js +1 -1
- package/components/graph/modules/link/index.js.map +1 -1
- package/components/graph/modules/node/index.js +2 -1
- package/components/graph/modules/node/index.js.map +1 -1
- 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.d.ts +5 -2
- package/components/treemap/index.js +84 -69
- package/components/treemap/index.js.map +1 -1
- package/components/treemap/style.d.ts +1 -0
- package/components/treemap/style.js +5 -1
- package/components/treemap/style.js.map +1 -1
- package/package.json +7 -4
- package/utils/misc.js +13 -2
- package/utils/misc.js.map +1 -1
- package/utils/text.d.ts +1 -1
- package/utils/text.js +13 -15
- package/utils/text.js.map +1 -1
- package/utils/to-px.d.ts +1 -0
- package/utils/to-px.js +110 -0
- package/utils/to-px.js.map +1 -0
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { select } from 'd3-selection';
|
|
2
2
|
import { hierarchy, treemap } from 'd3-hierarchy';
|
|
3
|
-
import {
|
|
3
|
+
import { group, max, extent } from 'd3-array';
|
|
4
4
|
import { scaleLinear, scaleThreshold } from 'd3-scale';
|
|
5
5
|
import { hsl } from 'd3-color';
|
|
6
6
|
import { ComponentCore } from '../../core/component/index.js';
|
|
7
7
|
import { SeriesDataModel } from '../../data-models/series.js';
|
|
8
8
|
import { getColor, getHexValue, brighter, isColorDark } from '../../utils/color.js';
|
|
9
|
-
import { isNumber, getString, getNumber } from '../../utils/data.js';
|
|
9
|
+
import { isNumber, getString, getNumber, isFunction } from '../../utils/data.js';
|
|
10
10
|
import { smartTransition } from '../../utils/d3.js';
|
|
11
11
|
import { wrapSVGText, trimSVGText } from '../../utils/text.js';
|
|
12
12
|
import { cssvar } from '../../utils/style.js';
|
|
13
13
|
import { FitMode } from '../../types/text.js';
|
|
14
14
|
import { TreemapDefaultConfig } from './config.js';
|
|
15
15
|
import * as style from './style.js';
|
|
16
|
-
import { tiles, tileGroup, tile, clickableTile, labelGroup, label, variables, internalLabel } from './style.js';
|
|
16
|
+
import { tiles, tileGroup, tileExiting, tile, clickableTile, labelGroup, label, variables, internalLabel } from './style.js';
|
|
17
17
|
|
|
18
18
|
class Treemap extends ComponentCore {
|
|
19
19
|
constructor(config) {
|
|
@@ -25,21 +25,6 @@ class Treemap extends ComponentCore {
|
|
|
25
25
|
this.setConfig(config);
|
|
26
26
|
this.tiles = this.g.append('g').attr('class', tiles);
|
|
27
27
|
}
|
|
28
|
-
_isTileLargeEnough(d) {
|
|
29
|
-
const w = d.x1 - d.x0;
|
|
30
|
-
const h = d.y1 - d.y0;
|
|
31
|
-
return (w >= this.config.minTileSizeForLabel) && (h >= this.config.minTileSizeForLabel);
|
|
32
|
-
}
|
|
33
|
-
_getTileLightness(node, siblings) {
|
|
34
|
-
// Get the value extent of the sibling group
|
|
35
|
-
const [minValue, maxValue] = extent(siblings, d => d.value);
|
|
36
|
-
// If there's no range or no value, return default lightness
|
|
37
|
-
if (minValue === maxValue || !node.value)
|
|
38
|
-
return 0;
|
|
39
|
-
// Calculate relative position in the range (0 to 1)
|
|
40
|
-
// Larger values will be closer to 0 (darker)
|
|
41
|
-
return this.config.lightnessVariationAmount * ((maxValue - node.value) / (maxValue - minValue));
|
|
42
|
-
}
|
|
43
28
|
_render(customDuration) {
|
|
44
29
|
var _a;
|
|
45
30
|
super._render(customDuration);
|
|
@@ -145,73 +130,79 @@ class Treemap extends ComponentCore {
|
|
|
145
130
|
}
|
|
146
131
|
d._fill = brighter(hslColor.toString(), brightnessIncrease(d.depth));
|
|
147
132
|
});
|
|
148
|
-
|
|
133
|
+
/* Render tiles */
|
|
149
134
|
const tiles = this.tiles
|
|
150
|
-
.selectAll(`g.${tileGroup}`)
|
|
135
|
+
.selectAll(`g.${tileGroup}:not(.${tileExiting})`)
|
|
151
136
|
.data(visibleTiles, d => `${d.data.key}-${d.depth}`);
|
|
152
|
-
const tilesEnter = tiles
|
|
153
|
-
.enter()
|
|
137
|
+
const tilesEnter = tiles.enter()
|
|
154
138
|
.append('g')
|
|
155
139
|
.attr('class', tileGroup);
|
|
156
|
-
// Computes the rect border radius for a given tile.
|
|
157
|
-
// The rx and ry values are the minimum of the tile
|
|
158
|
-
// border radius and some fraction the width of the tile,
|
|
159
|
-
// based on the tileBorderRadiusFactor config.
|
|
160
|
-
// This ensures that the tile border radius is not
|
|
161
|
-
// larger than the tile size, which makes small tiles
|
|
162
|
-
// look better.
|
|
163
|
-
const getTileBorderRadius = (d) => Math.min(config.tileBorderRadius, (d.x1 - d.x0) * config.tileBorderRadiusFactor);
|
|
164
140
|
// Add clipPath elements
|
|
165
141
|
tilesEnter
|
|
166
142
|
.append('clipPath')
|
|
167
|
-
.attr('id', d => `clip-${this.uid}-${d._id}`)
|
|
168
143
|
.append('rect')
|
|
169
|
-
.attr('rx',
|
|
170
|
-
.attr('ry',
|
|
144
|
+
.attr('rx', d => this._getTileBorderRadius(d))
|
|
145
|
+
.attr('ry', d => this._getTileBorderRadius(d));
|
|
171
146
|
// Tile rectangles
|
|
172
|
-
const
|
|
147
|
+
const tileEnterRects = tilesEnter
|
|
173
148
|
.append('rect')
|
|
174
149
|
.classed(tile, true)
|
|
175
150
|
.classed(clickableTile, d => config.showTileClickAffordance && !d.children)
|
|
176
|
-
.attr('rx',
|
|
177
|
-
.attr('ry',
|
|
151
|
+
.attr('rx', d => this._getTileBorderRadius(d))
|
|
152
|
+
.attr('ry', d => this._getTileBorderRadius(d))
|
|
178
153
|
.attr('x', d => d.x0)
|
|
179
154
|
.attr('y', d => d.y0)
|
|
180
|
-
.attr('width',
|
|
181
|
-
.attr('height',
|
|
155
|
+
.attr('width', this._getTileWidth)
|
|
156
|
+
.attr('height', this._getTileHeight)
|
|
182
157
|
.style('fill', d => d._fill)
|
|
183
158
|
.style('opacity', 0)
|
|
184
159
|
.style('cursor', config.showTileClickAffordance ? d => !d.children ? 'pointer' : null : null);
|
|
185
|
-
|
|
160
|
+
if (config.tileShowHtmlTooltip)
|
|
161
|
+
tileEnterRects.append('title');
|
|
186
162
|
tilesEnter
|
|
187
163
|
.append('g')
|
|
188
164
|
.attr('class', labelGroup)
|
|
189
|
-
.attr('clip-path', d => `url(#clip-${this.uid}-${d._id})`)
|
|
190
165
|
.attr('transform', d => `translate(${d.x0 + config.labelOffsetX},${d.y0 + config.labelOffsetY})`)
|
|
191
166
|
.style('opacity', 0)
|
|
192
167
|
.append('text')
|
|
193
168
|
.attr('class', label)
|
|
194
169
|
.attr('x', 0)
|
|
195
170
|
.attr('y', 0);
|
|
196
|
-
|
|
197
|
-
const
|
|
171
|
+
/* Update */
|
|
172
|
+
const tilesMerged = tiles.merge(tilesEnter);
|
|
173
|
+
// Update clipPath elements
|
|
174
|
+
tilesMerged.select('clipPath')
|
|
175
|
+
.attr('id', d => `clip-${this.uid}-${d._id}`);
|
|
176
|
+
tilesMerged.select('clipPath rect')
|
|
177
|
+
.attr('width', d => Math.max(this._getTileWidth(d) - 2 * config.labelOffsetX, 0))
|
|
178
|
+
.attr('height', d => Math.max(this._getTileHeight(d) - 2 * config.labelOffsetY, 0));
|
|
179
|
+
const tileRectsMerged = tilesMerged.select(`rect.${tile}`);
|
|
198
180
|
smartTransition(tileRectsMerged, duration)
|
|
199
181
|
.style('fill', d => d._fill)
|
|
200
182
|
.style('opacity', 1)
|
|
201
183
|
.attr('x', d => d.x0)
|
|
202
184
|
.attr('y', d => d.y0)
|
|
203
|
-
.attr('width',
|
|
204
|
-
.attr('height',
|
|
205
|
-
tileRectsMerged.select('title')
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
.
|
|
210
|
-
|
|
211
|
-
const
|
|
185
|
+
.attr('width', this._getTileWidth)
|
|
186
|
+
.attr('height', this._getTileHeight);
|
|
187
|
+
const tileTitlesMerged = tileRectsMerged.select('title');
|
|
188
|
+
if (config.tileShowHtmlTooltip)
|
|
189
|
+
tileTitlesMerged.text(d => config.tileLabel(d));
|
|
190
|
+
else
|
|
191
|
+
tileTitlesMerged.remove();
|
|
192
|
+
// Apply clip-path to labels
|
|
193
|
+
const labelGroupsMerged = tilesMerged.select(`g.${labelGroup}`)
|
|
194
|
+
.attr('clip-path', d => `url(#clip-${this.uid}-${d._id})`);
|
|
195
|
+
// Transition group position and text opacity (fade-in)
|
|
196
|
+
smartTransition(labelGroupsMerged, duration)
|
|
197
|
+
.attr('transform', d => `translate(${d.x0 + config.labelOffsetX},${d.y0 + config.labelOffsetY})`)
|
|
198
|
+
.style('opacity', 1);
|
|
199
|
+
const textSelection = tilesMerged.select(`g.${labelGroup} text`);
|
|
212
200
|
textSelection
|
|
213
|
-
.text(d =>
|
|
214
|
-
|
|
201
|
+
.text(d => {
|
|
202
|
+
const shouldShowLabel = config.labelInternalNodes ? true : !d.children;
|
|
203
|
+
const isLargeEnough = this._isTileLargeEnough(d);
|
|
204
|
+
return (shouldShowLabel && isLargeEnough && isFunction(config.tileLabel)) ? config.tileLabel(d) : null;
|
|
205
|
+
})
|
|
215
206
|
.property('font-size-px', d => {
|
|
216
207
|
var _a;
|
|
217
208
|
const sqrtVal = Math.sqrt((_a = d.value) !== null && _a !== void 0 ? _a : 0);
|
|
@@ -226,32 +217,56 @@ class Treemap extends ComponentCore {
|
|
|
226
217
|
var _a;
|
|
227
218
|
const isLeafNode = !d.children;
|
|
228
219
|
const el = els[i];
|
|
220
|
+
if (!el.textContent)
|
|
221
|
+
return;
|
|
229
222
|
const text = select(el);
|
|
230
|
-
const
|
|
223
|
+
const maxLabelWidth = d.x1 - d.x0 - ((_a = config.labelOffsetX) !== null && _a !== void 0 ? _a : 0) * 2;
|
|
231
224
|
const fontSize = parseFloat(text.property('font-size-px')) || parseFloat(window.getComputedStyle(el).fontSize);
|
|
232
225
|
if (config.labelFit === FitMode.Wrap && isLeafNode) {
|
|
233
|
-
wrapSVGText(text,
|
|
226
|
+
wrapSVGText(text, maxLabelWidth);
|
|
234
227
|
}
|
|
235
228
|
else {
|
|
236
|
-
trimSVGText(text,
|
|
229
|
+
trimSVGText(text, maxLabelWidth, config.labelTrimMode, true, fontSize);
|
|
237
230
|
}
|
|
238
231
|
});
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
.
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
const isAllowedNode = config.labelInternalNodes ? true : !d.children;
|
|
247
|
-
return isAllowedNode && this._isTileLargeEnough(d) ? null : 'none';
|
|
248
|
-
})
|
|
249
|
-
// Make the internal labels semibold via class
|
|
250
|
-
.attr('class', d => d.children ? `${label} ${internalLabel}` : label);
|
|
251
|
-
smartTransition(tiles.exit(), duration)
|
|
232
|
+
// Make the internal labels semibold via class
|
|
233
|
+
tilesMerged.select(`text.${label}`)
|
|
234
|
+
.classed(internalLabel, d => !!d.children);
|
|
235
|
+
/* Exit */
|
|
236
|
+
const tilesExit = tiles.exit()
|
|
237
|
+
.classed(tileExiting, true);
|
|
238
|
+
smartTransition(tilesExit, duration)
|
|
252
239
|
.style('opacity', 0)
|
|
253
240
|
.remove();
|
|
254
241
|
}
|
|
242
|
+
_isTileLargeEnough(d) {
|
|
243
|
+
const w = this._getTileWidth(d);
|
|
244
|
+
const h = this._getTileHeight(d);
|
|
245
|
+
return (w >= this.config.minTileSizeForLabel) && (h >= this.config.minTileSizeForLabel);
|
|
246
|
+
}
|
|
247
|
+
_getTileLightness(node, siblings) {
|
|
248
|
+
// Get the value extent of the sibling group
|
|
249
|
+
const [minValue, maxValue] = extent(siblings, d => d.value);
|
|
250
|
+
// If there's no range or no value, return default lightness
|
|
251
|
+
if (minValue === maxValue || !node.value)
|
|
252
|
+
return 0;
|
|
253
|
+
// Calculate relative position in the range (0 to 1)
|
|
254
|
+
// Larger values will be closer to 0 (darker)
|
|
255
|
+
return this.config.lightnessVariationAmount * ((maxValue - node.value) / (maxValue - minValue));
|
|
256
|
+
}
|
|
257
|
+
// Computes the rect border radius for a given tile. The rx and ry values are the minimum of the tile
|
|
258
|
+
// border radius and some fraction the width of the tile, based on the tileBorderRadiusFactor config.
|
|
259
|
+
// This ensures that the tile border radius is not larger than the tile size, which makes small tiles
|
|
260
|
+
// look better.
|
|
261
|
+
_getTileBorderRadius(d) {
|
|
262
|
+
return Math.min(this.config.tileBorderRadius, this._getTileWidth(d) * this.config.tileBorderRadiusFactor);
|
|
263
|
+
}
|
|
264
|
+
_getTileHeight(d) {
|
|
265
|
+
return Math.max(d.y1 - d.y0, 0.5);
|
|
266
|
+
}
|
|
267
|
+
_getTileWidth(d) {
|
|
268
|
+
return Math.max(d.x1 - d.x0, 0.5);
|
|
269
|
+
}
|
|
255
270
|
}
|
|
256
271
|
Treemap.selectors = style;
|
|
257
272
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/components/treemap/index.ts"],"sourcesContent":["import { Selection, select } from 'd3-selection'\nimport { hierarchy, HierarchyNode, treemap } from 'd3-hierarchy'\nimport { group, max, extent } from 'd3-array'\nimport { scaleLinear, scaleThreshold } from 'd3-scale'\nimport { hsl } from 'd3-color'\n\n// Core\nimport { ComponentCore } from 'core/component'\n\n// Data Model\nimport { SeriesDataModel } from 'data-models/series'\n\n// Utils\nimport { getColor, brighter, getHexValue, isColorDark } from 'utils/color'\nimport { getString, getNumber, isNumber } from 'utils/data'\nimport { smartTransition } from 'utils/d3'\nimport { trimSVGText, wrapSVGText } from 'utils/text'\nimport { cssvar } from 'utils/style'\n\n// Types\nimport { FitMode } from 'types/text'\n\n// Config\nimport { TreemapConfigInterface, TreemapDefaultConfig } from './config'\n\n// Local Types\nimport { TreemapDatum, TreemapNode } from './types'\n\n// Styles\nimport * as s from './style'\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 private _isTileLargeEnough (d: TreemapNode<Datum>): boolean {\n const w = d.x1 - d.x0\n const h = d.y1 - d.y0\n return (w >= this.config.minTileSizeForLabel) && (h >= this.config.minTileSizeForLabel)\n }\n\n private _getTileLightness (node: TreemapNode<Datum>, siblings: TreemapNode<Datum>[]): number {\n // Get the value extent of the sibling group\n const [minValue, maxValue] = extent(siblings, d => d.value)\n\n // If there's no range or no value, return default lightness\n if (minValue === maxValue || !node.value) return 0\n\n // Calculate relative position in the range (0 to 1)\n // Larger values will be closer to 0 (darker)\n return this.config.lightnessVariationAmount * ((maxValue - node.value) / (maxValue - minValue))\n }\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 super._render(customDuration)\n const { config, datamodel: { data }, _width, _height } = this\n const duration = isNumber(customDuration) ? customDuration : config.duration\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 => isNumber(index) && 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(node => {\n if (!node.children && node.parent) {\n node.parent.children = null\n }\n })\n\n const treemapLayout = treemap()\n .size([_width, _height])\n .round(true)\n .padding(config.tilePadding)\n\n // Apply padding to the top of each tile,\n // but not for the root node.\n if (this.config.tilePaddingTop !== undefined) {\n treemapLayout.paddingTop(d => d.parent ? config.tilePaddingTop : 0)\n }\n\n // Compute the treemap layout\n const treemapData = treemapLayout(rootNode) as TreemapNode<Datum>\n\n // Process the resulting hierarchy into the type we need\n let nodeId = 0\n treemapData.each(node => {\n const n = node as unknown as HierarchyNode<[string, number[]]>\n // Generate unique IDs for each node\n node._id = `node-${nodeId++}`\n\n const treemapDatum: TreemapDatum<Datum> = {\n key: n.data[0],\n }\n\n // Populate the index and datum for leaf nodes\n const isLeafNode = !n.children\n if (isLeafNode) {\n treemapDatum.index = n.data[1][0]\n treemapDatum.datum = data[treemapDatum.index]\n }\n\n node.data = treemapDatum\n })\n\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\n const brightnessIncrease = scaleLinear()\n .domain([1, maxDepth])\n .range([0, 1])\n\n // Get all leaf node values and calculate their square roots\n // (since area is proportional to value)\n const leafValues = descendants.filter(d => !d.children).map(d => d.value)\n const maxLeafValue = Math.sqrt(max(leafValues)) || 0\n // Divide the range into three equal intervals based on the square root of values\n // This accounts for the fact that area is proportional to value\n const fontSizeScale = scaleThreshold<number, number>()\n .domain([\n maxLeafValue / 3, // First third of the max value\n (maxLeafValue * 2) / 3, // Second third of the max value\n ])\n .range([\n config.tileLabelSmallFontSize,\n config.tileLabelMediumFontSize,\n config.tileLabelLargeFontSize,\n ])\n\n const visibleTiles = descendants.filter(d => d.depth > 0)\n const firstLevelTiles = visibleTiles.filter(d => d.depth === 1)\n const nonFirstLevelTiles = visibleTiles.filter(d => d.depth > 1)\n\n // Set the fill color for the first level tiles\n firstLevelTiles.forEach((d, i) => {\n d._fill = getColor(d, config.tileColor, i)\n })\n\n // Set the fill color for the non-first level tiles\n nonFirstLevelTiles.forEach((d, i) => {\n const providedColor = getColor(d, config.tileColor, i, true)\n if (providedColor) {\n d._fill = providedColor\n return\n }\n\n const hslColor = hsl(getHexValue(d.parent?._fill, this.element))\n\n if (config.enableLightnessVariance && !d.children && d.parent) {\n const siblings = d.parent.children\n const lightnessAdjustment = this._getTileLightness(d, siblings)\n hslColor.l = Math.min(1, hslColor.l + lightnessAdjustment)\n }\n\n d._fill = brighter(hslColor.toString(), brightnessIncrease(d.depth))\n })\n\n\n // Render tiles\n const tiles = this.tiles\n .selectAll<SVGGElement, TreemapNode<Datum>>(`g.${s.tileGroup}`)\n .data(visibleTiles, d => `${d.data.key}-${d.depth}`)\n\n const tilesEnter = tiles\n .enter()\n .append('g')\n .attr('class', s.tileGroup)\n\n // Computes the rect border radius for a given tile.\n // The rx and ry values are the minimum of the tile\n // border radius and some fraction the width of the tile,\n // based on the tileBorderRadiusFactor config.\n // This ensures that the tile border radius is not\n // larger than the tile size, which makes small tiles\n // look better.\n const getTileBorderRadius = (d: TreemapNode<Datum>): number =>\n Math.min(config.tileBorderRadius, (d.x1 - d.x0) * config.tileBorderRadiusFactor)\n\n // Add clipPath elements\n tilesEnter\n .append('clipPath')\n .attr('id', d => `clip-${this.uid}-${d._id}`)\n .append('rect')\n .attr('rx', getTileBorderRadius)\n .attr('ry', getTileBorderRadius)\n\n // Tile rectangles\n const tileRects = tilesEnter\n .append('rect')\n .classed(s.tile, true)\n .classed(s.clickableTile, d => config.showTileClickAffordance && !d.children)\n .attr('rx', getTileBorderRadius)\n .attr('ry', getTileBorderRadius)\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)\n .style('opacity', 0)\n .style('cursor', config.showTileClickAffordance ? d => !d.children ? 'pointer' : null : null)\n\n tileRects.append('title')\n\n tilesEnter\n .append('g')\n .attr('class', s.labelGroup)\n .attr('clip-path', d => `url(#clip-${this.uid}-${d._id})`)\n .attr('transform', d => `translate(${d.x0 + config.labelOffsetX},${d.y0 + config.labelOffsetY})`)\n .style('opacity', 0)\n .append('text')\n .attr('class', s.label)\n .attr('x', 0)\n .attr('y', 0)\n\n const mergedTiles = tiles.merge(tilesEnter)\n const tileRectsMerged = mergedTiles.select(`rect.${s.tile}`)\n smartTransition(tileRectsMerged, duration)\n .style('fill', d => d._fill)\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 tileRectsMerged.select('title')\n .text(d => config.tileLabel(d))\n\n // Update clipPath rects\n mergedTiles.select('clipPath rect')\n .attr('width', d => d.x1 - d.x0 - 2 * config.labelOffsetX)\n .attr('height', d => d.y1 - d.y0 - 2 * config.labelOffsetY)\n\n const textSelection = mergedTiles.selectAll<SVGTextElement, TreemapNode<Datum>>(`g.${s.labelGroup} text`)\n textSelection\n .text(d => config.tileLabel(d))\n .attr('title', d => config.tileLabel(d))\n .property('font-size-px', d => {\n const sqrtVal = Math.sqrt(d.value ?? 0)\n return config.enableTileLabelFontSizeVariation && !d.children\n ? fontSizeScale(sqrtVal)\n : null // Use the default css variable value\n })\n .style('font-size', (_, i, els) => `${select(els[i]).property('font-size-px')}px`)\n .style('fill', d => cssvar(\n isColorDark(d._fill) ? s.variables.treemapLabelTextColorLight : s.variables.treemapLabelTextColor)\n )\n\n // Fit label (wrap or trim)\n textSelection.each((d, i, els) => {\n const isLeafNode = !d.children\n const el = els[i] as SVGTextElement\n const text = select(el)\n const tileWidth = d.x1 - d.x0 - (config.labelOffsetX ?? 0) * 2\n const fontSize = parseFloat(text.property('font-size-px')) || parseFloat(window.getComputedStyle(el).fontSize)\n\n if (config.labelFit === FitMode.Wrap && isLeafNode) {\n wrapSVGText(text, tileWidth)\n } else {\n trimSVGText(text, tileWidth, config.labelTrimMode, true, fontSize)\n }\n })\n\n // Transition group position and text opacity (fade-in)\n smartTransition(mergedTiles.select(`g.${s.labelGroup}`), duration)\n .attr('transform', d => `translate(${d.x0 + config.labelOffsetX},${d.y0 + config.labelOffsetY})`)\n .style('opacity', 1)\n\n // Hide labels that don't meet criteria\n mergedTiles.select(`text.${s.label}`)\n .style('display', d => {\n const isAllowedNode = config.labelInternalNodes ? true : !d.children\n return isAllowedNode && this._isTileLargeEnough(d) ? null : 'none'\n })\n // Make the internal labels semibold via class\n .attr('class', d => d.children ? `${s.label} ${s.internalLabel}` : s.label)\n\n smartTransition(tiles.exit(), duration)\n .style('opacity', 0)\n .remove()\n }\n}\n"],"names":["s.tiles","s.tileGroup","s.tile","s.clickableTile","s.labelGroup","s.label","s.variables","s.internalLabel","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, HierarchyNode, treemap } from 'd3-hierarchy'\nimport { group, max, extent } from 'd3-array'\nimport { scaleLinear, scaleThreshold } from 'd3-scale'\nimport { hsl } from 'd3-color'\n\n// Core\nimport { ComponentCore } from 'core/component'\n\n// Data Model\nimport { SeriesDataModel } from 'data-models/series'\n\n// Utils\nimport { getColor, brighter, getHexValue, isColorDark } from 'utils/color'\nimport { getString, getNumber, isNumber, isFunction } from 'utils/data'\nimport { smartTransition } from 'utils/d3'\nimport { trimSVGText, wrapSVGText } from 'utils/text'\nimport { cssvar } from 'utils/style'\n\n// Types\nimport { FitMode } from 'types/text'\n\n// Config\nimport { TreemapConfigInterface, TreemapDefaultConfig } from './config'\n\n// Local Types\nimport { TreemapDatum, TreemapNode } from './types'\n\n// Styles\nimport * as s from './style'\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 super._render(customDuration)\n const { config, datamodel: { data }, _width, _height } = this\n const duration = isNumber(customDuration) ? customDuration : config.duration\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 => isNumber(index) && 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(node => {\n if (!node.children && node.parent) {\n node.parent.children = null\n }\n })\n\n const treemapLayout = treemap()\n .size([_width, _height])\n .round(true)\n .padding(config.tilePadding)\n\n // Apply padding to the top of each tile,\n // but not for the root node.\n if (this.config.tilePaddingTop !== undefined) {\n treemapLayout.paddingTop(d => d.parent ? config.tilePaddingTop : 0)\n }\n\n // Compute the treemap layout\n const treemapData = treemapLayout(rootNode) as TreemapNode<Datum>\n\n // Process the resulting hierarchy into the type we need\n let nodeId = 0\n treemapData.each(node => {\n const n = node as unknown as HierarchyNode<[string, number[]]>\n // Generate unique IDs for each node\n node._id = `node-${nodeId++}`\n\n const treemapDatum: TreemapDatum<Datum> = {\n key: n.data[0],\n }\n\n // Populate the index and datum for leaf nodes\n const isLeafNode = !n.children\n if (isLeafNode) {\n treemapDatum.index = n.data[1][0]\n treemapDatum.datum = data[treemapDatum.index]\n }\n\n node.data = treemapDatum\n })\n\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\n const brightnessIncrease = scaleLinear()\n .domain([1, maxDepth])\n .range([0, 1])\n\n // Get all leaf node values and calculate their square roots\n // (since area is proportional to value)\n const leafValues = descendants.filter(d => !d.children).map(d => d.value)\n const maxLeafValue = Math.sqrt(max(leafValues)) || 0\n // Divide the range into three equal intervals based on the square root of values\n // This accounts for the fact that area is proportional to value\n const fontSizeScale = scaleThreshold<number, number>()\n .domain([\n maxLeafValue / 3, // First third of the max value\n (maxLeafValue * 2) / 3, // Second third of the max value\n ])\n .range([\n config.tileLabelSmallFontSize,\n config.tileLabelMediumFontSize,\n config.tileLabelLargeFontSize,\n ])\n\n const visibleTiles = descendants.filter(d => d.depth > 0)\n const firstLevelTiles = visibleTiles.filter(d => d.depth === 1)\n const nonFirstLevelTiles = visibleTiles.filter(d => d.depth > 1)\n\n // Set the fill color for the first level tiles\n firstLevelTiles.forEach((d, i) => {\n d._fill = getColor(d, config.tileColor, i)\n })\n\n // Set the fill color for the non-first level tiles\n nonFirstLevelTiles.forEach((d, i) => {\n const providedColor = getColor(d, config.tileColor, i, true)\n if (providedColor) {\n d._fill = providedColor\n return\n }\n\n const hslColor = hsl(getHexValue(d.parent?._fill, this.element))\n\n if (config.enableLightnessVariance && !d.children && d.parent) {\n const siblings = d.parent.children\n const lightnessAdjustment = this._getTileLightness(d, siblings)\n hslColor.l = Math.min(1, hslColor.l + lightnessAdjustment)\n }\n\n d._fill = brighter(hslColor.toString(), brightnessIncrease(d.depth))\n })\n\n\n /* Render tiles */\n const tiles = this.tiles\n .selectAll<SVGGElement, TreemapNode<Datum>>(`g.${s.tileGroup}:not(.${s.tileExiting})`)\n .data(visibleTiles, d => `${d.data.key}-${d.depth}`)\n\n const tilesEnter = tiles.enter()\n .append('g')\n .attr('class', s.tileGroup)\n\n // Add clipPath elements\n tilesEnter\n .append('clipPath')\n .append('rect')\n .attr('rx', d => this._getTileBorderRadius(d))\n .attr('ry', d => this._getTileBorderRadius(d))\n\n // Tile rectangles\n const tileEnterRects = tilesEnter\n .append('rect')\n .classed(s.tile, true)\n .classed(s.clickableTile, d => config.showTileClickAffordance && !d.children)\n .attr('rx', d => this._getTileBorderRadius(d))\n .attr('ry', d => this._getTileBorderRadius(d))\n .attr('x', d => d.x0)\n .attr('y', d => d.y0)\n .attr('width', this._getTileWidth)\n .attr('height', this._getTileHeight)\n .style('fill', d => d._fill)\n .style('opacity', 0)\n .style('cursor', config.showTileClickAffordance ? d => !d.children ? 'pointer' : null : null)\n\n if (config.tileShowHtmlTooltip) tileEnterRects.append('title')\n\n tilesEnter\n .append('g')\n .attr('class', s.labelGroup)\n .attr('transform', d => `translate(${d.x0 + config.labelOffsetX},${d.y0 + config.labelOffsetY})`)\n .style('opacity', 0)\n .append('text')\n .attr('class', s.label)\n .attr('x', 0)\n .attr('y', 0)\n\n /* Update */\n const tilesMerged = tiles.merge(tilesEnter)\n\n // Update clipPath elements\n tilesMerged.select<SVGClipPathElement>('clipPath')\n .attr('id', d => `clip-${this.uid}-${d._id}`)\n\n tilesMerged.select('clipPath rect')\n .attr('width', d => Math.max(this._getTileWidth(d) - 2 * config.labelOffsetX, 0))\n .attr('height', d => Math.max(this._getTileHeight(d) - 2 * config.labelOffsetY, 0))\n\n const tileRectsMerged = tilesMerged.select(`rect.${s.tile}`)\n smartTransition(tileRectsMerged, duration)\n .style('fill', d => d._fill)\n .style('opacity', 1)\n .attr('x', d => d.x0)\n .attr('y', d => d.y0)\n .attr('width', this._getTileWidth)\n .attr('height', this._getTileHeight)\n\n const tileTitlesMerged = tileRectsMerged.select('title')\n if (config.tileShowHtmlTooltip) tileTitlesMerged.text(d => config.tileLabel(d))\n else tileTitlesMerged.remove()\n\n // Apply clip-path to labels\n const labelGroupsMerged = tilesMerged.select<SVGGElement>(`g.${s.labelGroup}`)\n .attr('clip-path', d => `url(#clip-${this.uid}-${d._id})`)\n\n // Transition group position and text opacity (fade-in)\n smartTransition(labelGroupsMerged, duration)\n .attr('transform', d => `translate(${d.x0 + config.labelOffsetX},${d.y0 + config.labelOffsetY})`)\n .style('opacity', 1)\n\n const textSelection = tilesMerged.select<SVGTextElement>(`g.${s.labelGroup} text`)\n textSelection\n .text(d => {\n const shouldShowLabel = config.labelInternalNodes ? true : !d.children\n const isLargeEnough = this._isTileLargeEnough(d)\n return (shouldShowLabel && isLargeEnough && isFunction(config.tileLabel)) ? config.tileLabel(d) : null\n })\n .property('font-size-px', d => {\n const sqrtVal = Math.sqrt(d.value ?? 0)\n return config.enableTileLabelFontSizeVariation && !d.children\n ? fontSizeScale(sqrtVal)\n : null // Use the default css variable value\n })\n .style('font-size', (_, i, els) => `${select(els[i]).property('font-size-px')}px`)\n .style('fill', d => cssvar(\n isColorDark(d._fill) ? s.variables.treemapLabelTextColorLight : s.variables.treemapLabelTextColor)\n )\n\n // Fit label (wrap or trim)\n textSelection.each((d, i, els) => {\n const isLeafNode = !d.children\n const el = els[i] as SVGTextElement\n if (!el.textContent) return\n\n const text = select(el)\n const maxLabelWidth = d.x1 - d.x0 - (config.labelOffsetX ?? 0) * 2\n const fontSize = parseFloat(text.property('font-size-px')) || parseFloat(window.getComputedStyle(el).fontSize)\n\n if (config.labelFit === FitMode.Wrap && isLeafNode) {\n wrapSVGText(text, maxLabelWidth)\n } else {\n trimSVGText(text, maxLabelWidth, config.labelTrimMode, true, fontSize)\n }\n })\n\n // Make the internal labels semibold via class\n tilesMerged.select(`text.${s.label}`)\n .classed(s.internalLabel, d => !!d.children)\n\n /* Exit */\n const tilesExit = tiles.exit()\n .classed(s.tileExiting, true)\n\n smartTransition(tilesExit, duration)\n .style('opacity', 0)\n .remove()\n }\n\n private _isTileLargeEnough (d: TreemapNode<Datum>): boolean {\n const w = this._getTileWidth(d)\n const h = this._getTileHeight(d)\n return (w >= this.config.minTileSizeForLabel) && (h >= this.config.minTileSizeForLabel)\n }\n\n private _getTileLightness (node: TreemapNode<Datum>, siblings: TreemapNode<Datum>[]): number {\n // Get the value extent of the sibling group\n const [minValue, maxValue] = extent(siblings, d => d.value)\n\n // If there's no range or no value, return default lightness\n if (minValue === maxValue || !node.value) return 0\n\n // Calculate relative position in the range (0 to 1)\n // Larger values will be closer to 0 (darker)\n return this.config.lightnessVariationAmount * ((maxValue - node.value) / (maxValue - minValue))\n }\n\n // Computes the rect border radius for a given tile. The rx and ry values are the minimum of the tile\n // border radius and some fraction the width of the tile, based on the tileBorderRadiusFactor config.\n // This ensures that the tile border radius is not larger than the tile size, which makes small tiles\n // look better.\n private _getTileBorderRadius (d: TreemapNode<Datum>): number {\n return Math.min(this.config.tileBorderRadius, this._getTileWidth(d) * this.config.tileBorderRadiusFactor)\n }\n\n private _getTileHeight (d: TreemapNode<Datum>): number {\n return Math.max(d.y1 - d.y0, 0.5)\n }\n\n private _getTileWidth (d: TreemapNode<Datum>): number {\n return Math.max(d.x1 - d.x0, 0.5)\n }\n}\n"],"names":["s.tiles","s.tileGroup","s.tileExiting","s.tile","s.clickableTile","s.labelGroup","s.label","s.variables","s.internalLabel","s"],"mappings":";;;;;;;;;;;;;;;;;AA+BM,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,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAA;AAC7B,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;QAE5E,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,QAAQ,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;AACtF,SAAA;AAAM,aAAA;YACL,QAAQ,CAAC,KAAK,EAAE,CAAA;AACjB,SAAA;;AAGD,QAAA,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAG;YACnB,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,EAAE;AACjC,gBAAA,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAA;AAC5B,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;;;AAI9B,QAAA,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,KAAK,SAAS,EAAE;YAC5C,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC,cAAc,GAAG,CAAC,CAAC,CAAA;AACpE,SAAA;;AAGD,QAAA,MAAM,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAuB,CAAA;;QAGjE,IAAI,MAAM,GAAG,CAAC,CAAA;AACd,QAAA,WAAW,CAAC,IAAI,CAAC,IAAI,IAAG;YACtB,MAAM,CAAC,GAAG,IAAoD,CAAA;;AAE9D,YAAA,IAAI,CAAC,GAAG,GAAG,QAAQ,MAAM,EAAE,EAAE,CAAA;AAE7B,YAAA,MAAM,YAAY,GAAwB;AACxC,gBAAA,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;aACf,CAAA;;AAGD,YAAA,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC9B,YAAA,IAAI,UAAU,EAAE;AACd,gBAAA,YAAY,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;gBACjC,YAAY,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAA;AAC9C,aAAA;AAED,YAAA,IAAI,CAAC,IAAI,GAAG,YAAY,CAAA;AAC1B,SAAC,CAAC,CAAA;AAEF,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;QAE/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;;;QAIhB,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAA;AACzE,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAA;;;QAGpD,MAAM,aAAa,GAAG,cAAc,EAAkB;AACnD,aAAA,MAAM,CAAC;AACN,YAAA,YAAY,GAAG,CAAC;AAChB,YAAA,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC;SACvB,CAAC;AACD,aAAA,KAAK,CAAC;AACL,YAAA,MAAM,CAAC,sBAAsB;AAC7B,YAAA,MAAM,CAAC,uBAAuB;AAC9B,YAAA,MAAM,CAAC,sBAAsB;AAC9B,SAAA,CAAC,CAAA;AAEJ,QAAA,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;AACzD,QAAA,MAAM,eAAe,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAA;AAC/D,QAAA,MAAM,kBAAkB,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;;QAGhE,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAI;AAC/B,YAAA,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;AAC5C,SAAC,CAAC,CAAA;;QAGF,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAI;;AAClC,YAAA,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,EAAE,IAAI,CAAC,CAAA;AAC5D,YAAA,IAAI,aAAa,EAAE;AACjB,gBAAA,CAAC,CAAC,KAAK,GAAG,aAAa,CAAA;gBACvB,OAAM;AACP,aAAA;AAED,YAAA,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,CAAC,MAAA,CAAC,CAAC,MAAM,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;AAEhE,YAAA,IAAI,MAAM,CAAC,uBAAuB,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,MAAM,EAAE;AAC7D,gBAAA,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAA;gBAClC,MAAM,mBAAmB,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAA;AAC/D,gBAAA,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAA;AAC3D,aAAA;AAED,YAAA,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;AACtE,SAAC,CAAC,CAAA;;AAIF,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK;aACrB,SAAS,CAAkC,CAAK,EAAA,EAAAC,SAAW,SAASC,WAAa,CAAA,CAAA,CAAG,CAAC;AACrF,aAAA,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,CAAG,EAAA,CAAC,CAAC,IAAI,CAAC,GAAG,CAAI,CAAA,EAAA,CAAC,CAAC,KAAK,CAAA,CAAE,CAAC,CAAA;AAEtD,QAAA,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,EAAE;aAC7B,MAAM,CAAC,GAAG,CAAC;AACX,aAAA,IAAI,CAAC,OAAO,EAAED,SAAW,CAAC,CAAA;;QAG7B,UAAU;aACP,MAAM,CAAC,UAAU,CAAC;aAClB,MAAM,CAAC,MAAM,CAAC;AACd,aAAA,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAC7C,aAAA,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAA;;QAGhD,MAAM,cAAc,GAAG,UAAU;aAC9B,MAAM,CAAC,MAAM,CAAC;AACd,aAAA,OAAO,CAACE,IAAM,EAAE,IAAI,CAAC;AACrB,aAAA,OAAO,CAACC,aAAe,EAAE,CAAC,IAAI,MAAM,CAAC,uBAAuB,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC5E,aAAA,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;AAC7C,aAAA,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;aAC7C,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,IAAI,CAAC,aAAa,CAAC;AACjC,aAAA,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC;aACnC,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;AAC3B,aAAA,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;AACnB,aAAA,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,uBAAuB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC,CAAA;QAE/F,IAAI,MAAM,CAAC,mBAAmB;AAAE,YAAA,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAE9D,UAAU;aACP,MAAM,CAAC,GAAG,CAAC;AACX,aAAA,IAAI,CAAC,OAAO,EAAEC,UAAY,CAAC;aAC3B,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,CAAA,UAAA,EAAa,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,YAAY,CAAI,CAAA,EAAA,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,YAAY,CAAA,CAAA,CAAG,CAAC;AAChG,aAAA,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;aACnB,MAAM,CAAC,MAAM,CAAC;AACd,aAAA,IAAI,CAAC,OAAO,EAAEC,KAAO,CAAC;AACtB,aAAA,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AACZ,aAAA,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAA;;QAGf,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;;AAG3C,QAAA,WAAW,CAAC,MAAM,CAAqB,UAAU,CAAC;AAC/C,aAAA,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAA,KAAA,EAAQ,IAAI,CAAC,GAAG,CAAI,CAAA,EAAA,CAAC,CAAC,GAAG,CAAA,CAAE,CAAC,CAAA;AAE/C,QAAA,WAAW,CAAC,MAAM,CAAC,eAAe,CAAC;aAChC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;aAChF,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAA;AAErF,QAAA,MAAM,eAAe,GAAG,WAAW,CAAC,MAAM,CAAC,CAAQ,KAAA,EAAAH,IAAM,CAAE,CAAA,CAAC,CAAA;AAC5D,QAAA,eAAe,CAAC,eAAe,EAAE,QAAQ,CAAC;aACvC,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;AAC3B,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,IAAI,CAAC,aAAa,CAAC;AACjC,aAAA,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,CAAA;QAEtC,MAAM,gBAAgB,GAAG,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QACxD,IAAI,MAAM,CAAC,mBAAmB;AAAE,YAAA,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;;YAC1E,gBAAgB,CAAC,MAAM,EAAE,CAAA;;QAG9B,MAAM,iBAAiB,GAAG,WAAW,CAAC,MAAM,CAAc,CAAA,EAAA,EAAKE,UAAY,CAAA,CAAE,CAAC;AAC3E,aAAA,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,CAAA,UAAA,EAAa,IAAI,CAAC,GAAG,CAAI,CAAA,EAAA,CAAC,CAAC,GAAG,CAAA,CAAA,CAAG,CAAC,CAAA;;AAG5D,QAAA,eAAe,CAAC,iBAAiB,EAAE,QAAQ,CAAC;aACzC,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,CAAA,UAAA,EAAa,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,YAAY,CAAI,CAAA,EAAA,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,YAAY,CAAA,CAAA,CAAG,CAAC;AAChG,aAAA,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;AAEtB,QAAA,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,CAAiB,CAAK,EAAA,EAAAA,UAAY,CAAO,KAAA,CAAA,CAAC,CAAA;QAClF,aAAa;aACV,IAAI,CAAC,CAAC,IAAG;AACR,YAAA,MAAM,eAAe,GAAG,MAAM,CAAC,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAA;YACtE,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAA;YAChD,OAAO,CAAC,eAAe,IAAI,aAAa,IAAI,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;AACxG,SAAC,CAAC;AACD,aAAA,QAAQ,CAAC,cAAc,EAAE,CAAC,IAAG;;AAC5B,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA,EAAA,GAAA,CAAC,CAAC,KAAK,MAAI,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAA,CAAC,CAAC,CAAA;AACvC,YAAA,OAAO,MAAM,CAAC,gCAAgC,IAAI,CAAC,CAAC,CAAC,QAAQ;AAC3D,kBAAE,aAAa,CAAC,OAAO,CAAC;AACxB,kBAAE,IAAI,CAAA;AACV,SAAC,CAAC;aACD,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,CAAA,EAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAA,EAAA,CAAI,CAAC;AACjF,aAAA,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,MAAM,CACxB,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,GAAGE,SAAW,CAAC,0BAA0B,GAAGA,SAAW,CAAC,qBAAqB,CAAC,CACnG,CAAA;;QAGH,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,KAAI;;AAC/B,YAAA,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC9B,YAAA,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAmB,CAAA;YACnC,IAAI,CAAC,EAAE,CAAC,WAAW;gBAAE,OAAM;AAE3B,YAAA,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAA;YACvB,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA,EAAA,GAAA,MAAM,CAAC,YAAY,MAAA,IAAA,IAAA,EAAA,KAAA,KAAA,CAAA,GAAA,EAAA,GAAI,CAAC,IAAI,CAAC,CAAA;YAClE,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAA;YAE9G,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC,IAAI,IAAI,UAAU,EAAE;AAClD,gBAAA,WAAW,CAAC,IAAI,EAAE,aAAa,CAAC,CAAA;AACjC,aAAA;AAAM,iBAAA;AACL,gBAAA,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAA;AACvE,aAAA;AACH,SAAC,CAAC,CAAA;;QAGF,WAAW,CAAC,MAAM,CAAC,CAAA,KAAA,EAAQD,KAAO,EAAE,CAAC;AAClC,aAAA,OAAO,CAACE,aAAe,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;;AAG9C,QAAA,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,EAAE;AAC3B,aAAA,OAAO,CAACN,WAAa,EAAE,IAAI,CAAC,CAAA;AAE/B,QAAA,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC;AACjC,aAAA,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;AACnB,aAAA,MAAM,EAAE,CAAA;KACZ;AAEO,IAAA,kBAAkB,CAAE,CAAqB,EAAA;QAC/C,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAA;QAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAA;AAChC,QAAA,OAAO,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAA;KACxF;IAEO,iBAAiB,CAAE,IAAwB,EAAE,QAA8B,EAAA;;AAEjF,QAAA,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAA;;AAG3D,QAAA,IAAI,QAAQ,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,CAAC,CAAA;;;QAIlD,OAAO,IAAI,CAAC,MAAM,CAAC,wBAAwB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,KAAK,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAA;KAChG;;;;;AAMO,IAAA,oBAAoB,CAAE,CAAqB,EAAA;QACjD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAA;KAC1G;AAEO,IAAA,cAAc,CAAE,CAAqB,EAAA;AAC3C,QAAA,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;KAClC;AAEO,IAAA,aAAa,CAAE,CAAqB,EAAA;AAC1C,QAAA,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;KAClC;;AAxSM,OAAS,CAAA,SAAA,GAAGO,KAAC;;;;"}
|
|
@@ -13,6 +13,7 @@ export declare const variables: {
|
|
|
13
13
|
export declare const tiles: string;
|
|
14
14
|
export declare const tileGroup: string;
|
|
15
15
|
export declare const tile: string;
|
|
16
|
+
export declare const tileExiting: string;
|
|
16
17
|
export declare const clickableTile: string;
|
|
17
18
|
export declare const tileForeground: string;
|
|
18
19
|
export declare const label: string;
|
|
@@ -33,6 +33,10 @@ const tile = css `
|
|
|
33
33
|
stroke-opacity: var(${variables.treemapTileHoverStrokeOpacity})
|
|
34
34
|
}
|
|
35
35
|
`;
|
|
36
|
+
const tileExiting = css `
|
|
37
|
+
label: tile-exiting;
|
|
38
|
+
pointer-events: none;
|
|
39
|
+
`;
|
|
36
40
|
// The leaf tiles are clickable
|
|
37
41
|
const clickableTile = css `
|
|
38
42
|
label: clickable-tile;
|
|
@@ -60,5 +64,5 @@ const labelGroup = css `
|
|
|
60
64
|
label: label-group;
|
|
61
65
|
`;
|
|
62
66
|
|
|
63
|
-
export { clickableTile, internalLabel, label, labelGroup, root, tile, tileForeground, tileGroup, tiles, variables };
|
|
67
|
+
export { clickableTile, internalLabel, label, labelGroup, root, tile, tileExiting, tileForeground, tileGroup, tiles, variables };
|
|
64
68
|
//# sourceMappingURL=style.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"style.js","sources":["../../../src/components/treemap/style.ts"],"sourcesContent":["import { css } from '@emotion/css'\n\n// Utils\nimport { getCssVarNames, injectGlobalCssVariables } from 'utils/style'\n\nconst cssVarDefaults = {\n '--vis-treemap-tile-stroke-color': '#fff',\n '--vis-treemap-tile-stroke-width': '2px',\n '--vis-treemap-tile-hover-stroke-color': '#fff',\n '--vis-treemap-tile-hover-stroke-opacity': 0,\n\n /* Labels */\n '--vis-treemap-label-opacity': 0.8,\n '--vis-treemap-label-font-weight': 'normal',\n '--vis-treemap-label-text-color': '#000',\n '--vis-treemap-label-text-color-light': '#fff',\n '--vis-treemap-label-font-size': '12px',\n}\n\nexport const root = css`\n label: treemap-component;\n`\n\nexport const variables = getCssVarNames(cssVarDefaults)\ninjectGlobalCssVariables(cssVarDefaults, root)\n\nexport const tiles = css`\n label: g-tiles;\n`\n\nexport const tileGroup = css`\n label: tile-group;\n`\n\nexport const tile = css`\n label: tile;\n stroke: var(${variables.treemapTileHoverStrokeColor});\n stroke-opacity: 0;\n\n &:hover {\n stroke-opacity: var(${variables.treemapTileHoverStrokeOpacity})\n }\n`\n\n// The leaf tiles are clickable\nexport const clickableTile = css`\n label: clickable-tile;\n cursor: pointer;\n`\n\nexport const tileForeground = css`\n label: tile-foreground;\n`\n\nexport const label = css`\n label: label;\n text-anchor: start;\n dominant-baseline: hanging;\n user-select: none;\n pointer-events: none;\n font-size: var(${variables.treemapLabelFontSize});\n opacity: var(${variables.treemapLabelOpacity});\n fill: var(${variables.treemapLabelTextColor});\n font-weight: var(${variables.treemapLabelFontWeight});\n`\n\nexport const internalLabel = css`\n label: internal-label;\n font-weight: 500;\n`\n\nexport const labelGroup = css`\n label: label-group;\n`\n"],"names":[],"mappings":";;;AAKA,MAAM,cAAc,GAAG;AACrB,IAAA,iCAAiC,EAAE,MAAM;AACzC,IAAA,iCAAiC,EAAE,KAAK;AACxC,IAAA,uCAAuC,EAAE,MAAM;AAC/C,IAAA,yCAAyC,EAAE,CAAC;;AAG5C,IAAA,6BAA6B,EAAE,GAAG;AAClC,IAAA,iCAAiC,EAAE,QAAQ;AAC3C,IAAA,gCAAgC,EAAE,MAAM;AACxC,IAAA,sCAAsC,EAAE,MAAM;AAC9C,IAAA,+BAA+B,EAAE,MAAM;CACxC,CAAA;AAEM,MAAM,IAAI,GAAG,GAAG,CAAA,CAAA;;EAEtB;MAEY,SAAS,GAAG,cAAc,CAAC,cAAc,EAAC;AACvD,wBAAwB,CAAC,cAAc,EAAE,IAAI,CAAC,CAAA;AAEvC,MAAM,KAAK,GAAG,GAAG,CAAA,CAAA;;EAEvB;AAEM,MAAM,SAAS,GAAG,GAAG,CAAA,CAAA;;EAE3B;AAEM,MAAM,IAAI,GAAG,GAAG,CAAA,CAAA;;AAEP,cAAA,EAAA,SAAS,CAAC,2BAA2B,CAAA;;;;AAI3B,wBAAA,EAAA,SAAS,CAAC,6BAA6B,CAAA;;EAEhE;AAED;AACO,MAAM,aAAa,GAAG,GAAG,CAAA,CAAA;;;EAG/B;AAEM,MAAM,cAAc,GAAG,GAAG,CAAA,CAAA;;EAEhC;AAEM,MAAM,KAAK,GAAG,GAAG,CAAA,CAAA;;;;;;AAML,iBAAA,EAAA,SAAS,CAAC,oBAAoB,CAAA;AAChC,eAAA,EAAA,SAAS,CAAC,mBAAmB,CAAA;AAChC,YAAA,EAAA,SAAS,CAAC,qBAAqB,CAAA;AACxB,mBAAA,EAAA,SAAS,CAAC,sBAAsB,CAAA;EACpD;AAEM,MAAM,aAAa,GAAG,GAAG,CAAA,CAAA;;;EAG/B;AAEM,MAAM,UAAU,GAAG,GAAG,CAAA,CAAA;;;;;;"}
|
|
1
|
+
{"version":3,"file":"style.js","sources":["../../../src/components/treemap/style.ts"],"sourcesContent":["import { css } from '@emotion/css'\n\n// Utils\nimport { getCssVarNames, injectGlobalCssVariables } from 'utils/style'\n\nconst cssVarDefaults = {\n '--vis-treemap-tile-stroke-color': '#fff',\n '--vis-treemap-tile-stroke-width': '2px',\n '--vis-treemap-tile-hover-stroke-color': '#fff',\n '--vis-treemap-tile-hover-stroke-opacity': 0,\n\n /* Labels */\n '--vis-treemap-label-opacity': 0.8,\n '--vis-treemap-label-font-weight': 'normal',\n '--vis-treemap-label-text-color': '#000',\n '--vis-treemap-label-text-color-light': '#fff',\n '--vis-treemap-label-font-size': '12px',\n}\n\nexport const root = css`\n label: treemap-component;\n`\n\nexport const variables = getCssVarNames(cssVarDefaults)\ninjectGlobalCssVariables(cssVarDefaults, root)\n\nexport const tiles = css`\n label: g-tiles;\n`\n\nexport const tileGroup = css`\n label: tile-group;\n`\n\nexport const tile = css`\n label: tile;\n stroke: var(${variables.treemapTileHoverStrokeColor});\n stroke-opacity: 0;\n\n &:hover {\n stroke-opacity: var(${variables.treemapTileHoverStrokeOpacity})\n }\n`\n\nexport const tileExiting = css`\n label: tile-exiting;\n pointer-events: none;\n`\n\n// The leaf tiles are clickable\nexport const clickableTile = css`\n label: clickable-tile;\n cursor: pointer;\n`\n\nexport const tileForeground = css`\n label: tile-foreground;\n`\n\nexport const label = css`\n label: label;\n text-anchor: start;\n dominant-baseline: hanging;\n user-select: none;\n pointer-events: none;\n font-size: var(${variables.treemapLabelFontSize});\n opacity: var(${variables.treemapLabelOpacity});\n fill: var(${variables.treemapLabelTextColor});\n font-weight: var(${variables.treemapLabelFontWeight});\n`\n\nexport const internalLabel = css`\n label: internal-label;\n font-weight: 500;\n`\n\nexport const labelGroup = css`\n label: label-group;\n`\n"],"names":[],"mappings":";;;AAKA,MAAM,cAAc,GAAG;AACrB,IAAA,iCAAiC,EAAE,MAAM;AACzC,IAAA,iCAAiC,EAAE,KAAK;AACxC,IAAA,uCAAuC,EAAE,MAAM;AAC/C,IAAA,yCAAyC,EAAE,CAAC;;AAG5C,IAAA,6BAA6B,EAAE,GAAG;AAClC,IAAA,iCAAiC,EAAE,QAAQ;AAC3C,IAAA,gCAAgC,EAAE,MAAM;AACxC,IAAA,sCAAsC,EAAE,MAAM;AAC9C,IAAA,+BAA+B,EAAE,MAAM;CACxC,CAAA;AAEM,MAAM,IAAI,GAAG,GAAG,CAAA,CAAA;;EAEtB;MAEY,SAAS,GAAG,cAAc,CAAC,cAAc,EAAC;AACvD,wBAAwB,CAAC,cAAc,EAAE,IAAI,CAAC,CAAA;AAEvC,MAAM,KAAK,GAAG,GAAG,CAAA,CAAA;;EAEvB;AAEM,MAAM,SAAS,GAAG,GAAG,CAAA,CAAA;;EAE3B;AAEM,MAAM,IAAI,GAAG,GAAG,CAAA,CAAA;;AAEP,cAAA,EAAA,SAAS,CAAC,2BAA2B,CAAA;;;;AAI3B,wBAAA,EAAA,SAAS,CAAC,6BAA6B,CAAA;;EAEhE;AAEM,MAAM,WAAW,GAAG,GAAG,CAAA,CAAA;;;EAG7B;AAED;AACO,MAAM,aAAa,GAAG,GAAG,CAAA,CAAA;;;EAG/B;AAEM,MAAM,cAAc,GAAG,GAAG,CAAA,CAAA;;EAEhC;AAEM,MAAM,KAAK,GAAG,GAAG,CAAA,CAAA;;;;;;AAML,iBAAA,EAAA,SAAS,CAAC,oBAAoB,CAAA;AAChC,eAAA,EAAA,SAAS,CAAC,mBAAmB,CAAA;AAChC,YAAA,EAAA,SAAS,CAAC,qBAAqB,CAAA;AACxB,mBAAA,EAAA,SAAS,CAAC,sBAAsB,CAAA;EACpD;AAEM,MAAM,aAAa,GAAG,GAAG,CAAA,CAAA;;;EAG/B;AAEM,MAAM,UAAU,GAAG,GAAG,CAAA,CAAA;;;;;;"}
|
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.7.0-pre.
|
|
4
|
+
"version": "1.7.0-pre.2",
|
|
5
5
|
"packageManager": "pnpm@10.23.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -34,9 +34,13 @@
|
|
|
34
34
|
"styles/index.js",
|
|
35
35
|
"dist/styles/index.js"
|
|
36
36
|
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "sha=$(tar cf - ./src | shasum); if [[ $(echo $sha) == $(< .srcsha) ]] && [[ -d \"./dist\" ]]; then echo \"Lib Build Exists\"; else npm run forcebuild; echo $sha > .srcsha; fi",
|
|
39
|
+
"forcebuild": "rimraf dist; rollup -c; rm -rf dist/.cache; cp LICENSE README.md package.json ./dist",
|
|
40
|
+
"publish:dist": "cd ./dist; npm publish"
|
|
41
|
+
},
|
|
37
42
|
"devDependencies": {
|
|
38
43
|
"@rollup/plugin-json": "^4.1.0",
|
|
39
|
-
"@types/to-px": "^1.1.2",
|
|
40
44
|
"@zerollup/ts-transform-paths": "^1.7.18",
|
|
41
45
|
"rimraf": "^3.0.2",
|
|
42
46
|
"rollup": "^2.61.1",
|
|
@@ -114,9 +118,8 @@
|
|
|
114
118
|
"supercluster": "^7.1.5",
|
|
115
119
|
"three": "^0.135.0",
|
|
116
120
|
"throttle-debounce": "^5.0.0",
|
|
117
|
-
"to-px": "^1.1.0",
|
|
118
121
|
"topojson-client": "^3.1.0",
|
|
119
122
|
"tslib": "^2.3.1",
|
|
120
123
|
"typescript": "~4.2.4"
|
|
121
124
|
}
|
|
122
|
-
}
|
|
125
|
+
}
|
package/utils/misc.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isString, getString } from './data.js';
|
|
2
|
-
import toPx from 'to-px';
|
|
2
|
+
import { toPx } from './to-px.js';
|
|
3
3
|
|
|
4
4
|
function guid() {
|
|
5
5
|
const s4 = () => Math.floor((1 + crypto.getRandomValues(new Uint32Array(1))[0]) * 0x10000)
|
|
@@ -13,11 +13,22 @@ function stringToHtmlId(str) {
|
|
|
13
13
|
function isStringCSSVariable(s) {
|
|
14
14
|
return isString(s) ? (s.substring(0, 6) === 'var(--') : false;
|
|
15
15
|
}
|
|
16
|
+
const cssVariableCache = new WeakMap();
|
|
16
17
|
function getCSSVariableValue(s, context) {
|
|
17
18
|
if (!isString(s))
|
|
18
19
|
return '';
|
|
19
20
|
const variableName = s.substr(4, s.length - 5);
|
|
20
|
-
|
|
21
|
+
let elementCache = cssVariableCache.get(context);
|
|
22
|
+
if (!elementCache) {
|
|
23
|
+
elementCache = new Map();
|
|
24
|
+
cssVariableCache.set(context, elementCache);
|
|
25
|
+
}
|
|
26
|
+
if (elementCache.has(variableName)) {
|
|
27
|
+
return elementCache.get(variableName);
|
|
28
|
+
}
|
|
29
|
+
const value = getComputedStyle(context).getPropertyValue(variableName);
|
|
30
|
+
elementCache.set(variableName, value);
|
|
31
|
+
return value;
|
|
21
32
|
}
|
|
22
33
|
function getCSSVariableValueInPixels(s, context) {
|
|
23
34
|
const val = getCSSVariableValue(s, context);
|
package/utils/misc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"misc.js","sources":["../../src/utils/misc.ts"],"sourcesContent":["import { StringAccessor } from 'types/accessor'\nimport { LengthUnit, Rect } from 'types/misc'\nimport { getString, isString } from 'utils/data'\nimport toPx from 'to-px'\n\nexport function guid (): string {\n const s4 = (): string =>\n Math.floor((1 + crypto.getRandomValues(new Uint32Array(1))[0]) * 0x10000)\n .toString(16)\n .substring(1)\n\n return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`\n}\n\nexport function stringToHtmlId (str: string): string {\n return (str || '').replace(/\\W/g, '_')\n}\n\nexport function isStringCSSVariable (s: string): boolean {\n return isString(s) ? (s.substring(0, 6) === 'var(--') : false\n}\n\nexport function getCSSVariableValue (s: string, context: HTMLElement | SVGElement): string {\n if (!isString(s)) return ''\n const variableName = s.substr(4, s.length - 5)\n return getComputedStyle(context).getPropertyValue(variableName)\n}\n\nexport function getCSSVariableValueInPixels (s: string, context: HTMLElement | SVGElement): number {\n const val = getCSSVariableValue(s, context)\n return toPx(val)\n}\n\nexport function getPixelValue (v: string | number): number | null {\n return typeof v === 'number' ? v : toPx(v)\n}\n\nexport function rectIntersect (rect1: Rect, rect2: Rect, tolerancePx = 0): boolean {\n const [left1, top1, right1, bottom1] = [\n rect1.x + tolerancePx,\n rect1.y + rect1.height - 2 * tolerancePx,\n rect1.x + rect1.width - 2 * tolerancePx,\n rect1.y + tolerancePx,\n ]\n const [left2, top2, right2, bottom2] = [\n rect2.x + tolerancePx,\n rect2.y + rect2.height - 2 * tolerancePx,\n rect2.x + rect2.width - 2 * tolerancePx,\n rect2.y + tolerancePx,\n ]\n\n return !(top1 < bottom2 || top2 < bottom1 || right1 < left2 || right2 < left1)\n}\n\nexport function getHref<T> (d: T, identifier: StringAccessor<T>): string {\n const id = getString(d, identifier)\n return id ? `url(#${id})` : null\n}\n\nfunction evaluateSimpleExpression (expr: string): number {\n // Handle multiplication and division first (higher precedence)\n // Keep applying until no more operations are found\n while (/(-?\\d+(?:\\.\\d+)?)\\s*([*/])\\s*(-?\\d+(?:\\.\\d+)?)/.test(expr)) {\n expr = expr.replace(/(-?\\d+(?:\\.\\d+)?)\\s*([*/])\\s*(-?\\d+(?:\\.\\d+)?)/, (_, a, op, b) => {\n const numA = parseFloat(a)\n const numB = parseFloat(b)\n return String(op === '*' ? numA * numB : numA / numB)\n })\n }\n\n // Handle addition and subtraction (lower precedence)\n // Keep applying until no more operations are found\n while (/(-?\\d+(?:\\.\\d+)?)\\s*([+-])\\s*(-?\\d+(?:\\.\\d+)?)/.test(expr)) {\n expr = expr.replace(/(-?\\d+(?:\\.\\d+)?)\\s*([+-])\\s*(-?\\d+(?:\\.\\d+)?)/, (_, a, op, b) => {\n const numA = parseFloat(a)\n const numB = parseFloat(b)\n return String(op === '+' ? numA + numB : numA - numB)\n })\n }\n\n const result = parseFloat(expr)\n if (isNaN(result)) throw new Error(`Invalid expression: ${expr}`)\n return result\n}\n\nfunction evaluateCalcExpression (expression: string, basis: number): number {\n try {\n // Replace percentages and pixels with resolved values\n let expr = expression\n .replace(/(\\d+(?:\\.\\d+)?)%/g, (_, num) => String((basis * parseFloat(num)) / 100))\n .replace(/(\\d+(?:\\.\\d+)?)px/g, '$1')\n .replace(/\\s+/g, '')\n\n // Validate parentheses pairs before processing\n let parenCount = 0\n for (const char of expr) {\n if (char === '(') parenCount++\n else if (char === ')') parenCount--\n if (parenCount < 0) throw new Error('Mismatched parentheses: closing parenthesis without opening')\n }\n if (parenCount !== 0) throw new Error('Mismatched parentheses: unclosed opening parenthesis')\n\n // Check for invalid characters (only allow numbers, operators, decimal points, and parentheses)\n if (!/^[0-9+\\-*/.() ]+$/.test(expr)) throw new Error('Invalid characters in expression')\n\n // Check for empty parentheses\n if (/\\(\\s*\\)/.test(expr)) throw new Error('Empty parentheses not allowed')\n\n // Simple regex-based evaluation for basic expressions\n // Handles: number, number+number, number-number, number*number, number/number\n // And simple parentheses: (expression)\n\n // Evaluate parentheses first\n let iterations = 0\n const maxIterations = 100 // Prevent infinite loops\n while (expr.includes('(') && iterations < maxIterations) {\n const prevExpr = expr\n expr = expr.replace(/\\(([^()]+)\\)/g, (_, inner) => String(evaluateSimpleExpression(inner)))\n if (expr === prevExpr) throw new Error('Unable to resolve parentheses')\n iterations++\n }\n\n if (iterations >= maxIterations) throw new Error('Expression too complex or contains infinite recursion')\n if (expr.includes('(') || expr.includes(')')) throw new Error('Unresolved parentheses remain')\n\n return evaluateSimpleExpression(expr)\n } catch (error) {\n console.warn(`Failed to evaluate calc() expression: ${expression}`, error)\n return 0\n }\n}\n\nexport function parseUnit (value: LengthUnit, basis = 0): number {\n if (!value) return 0\n else if (typeof value === 'number') return value\n else if (typeof value === 'string' && value.startsWith('calc(') && value.endsWith(')')) {\n // Parse calc() expression\n const expression = value.slice(5, -1).trim() // Remove 'calc(' and ')'\n return evaluateCalcExpression(expression, basis)\n } else if (value.endsWith('%')) return basis * parseFloat(value) / 100\n else if (value.endsWith('px')) return parseFloat(value)\n else return parseFloat(value) || 0\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"misc.js","sources":["../../src/utils/misc.ts"],"sourcesContent":["import { StringAccessor } from 'types/accessor'\nimport { LengthUnit, Rect } from 'types/misc'\nimport { getString, isString } from 'utils/data'\nimport { toPx } from 'utils/to-px'\n\nexport function guid (): string {\n const s4 = (): string =>\n Math.floor((1 + crypto.getRandomValues(new Uint32Array(1))[0]) * 0x10000)\n .toString(16)\n .substring(1)\n\n return `${s4() + s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`\n}\n\nexport function stringToHtmlId (str: string): string {\n return (str || '').replace(/\\W/g, '_')\n}\n\nexport function isStringCSSVariable (s: string): boolean {\n return isString(s) ? (s.substring(0, 6) === 'var(--') : false\n}\n\nconst cssVariableCache = new WeakMap<HTMLElement | SVGElement, Map<string, string>>()\nexport function getCSSVariableValue (s: string, context: HTMLElement | SVGElement): string {\n if (!isString(s)) return ''\n const variableName = s.substr(4, s.length - 5)\n\n\n let elementCache = cssVariableCache.get(context)\n if (!elementCache) {\n elementCache = new Map()\n cssVariableCache.set(context, elementCache)\n }\n\n if (elementCache.has(variableName)) {\n return elementCache.get(variableName)\n }\n\n const value = getComputedStyle(context).getPropertyValue(variableName)\n elementCache.set(variableName, value)\n return value\n}\n\nexport function getCSSVariableValueInPixels (s: string, context: HTMLElement | SVGElement): number {\n const val = getCSSVariableValue(s, context)\n return toPx(val)\n}\n\nexport function getPixelValue (v: string | number): number | null {\n return typeof v === 'number' ? v : toPx(v)\n}\n\nexport function rectIntersect (rect1: Rect, rect2: Rect, tolerancePx = 0): boolean {\n const [left1, top1, right1, bottom1] = [\n rect1.x + tolerancePx,\n rect1.y + rect1.height - 2 * tolerancePx,\n rect1.x + rect1.width - 2 * tolerancePx,\n rect1.y + tolerancePx,\n ]\n const [left2, top2, right2, bottom2] = [\n rect2.x + tolerancePx,\n rect2.y + rect2.height - 2 * tolerancePx,\n rect2.x + rect2.width - 2 * tolerancePx,\n rect2.y + tolerancePx,\n ]\n\n return !(top1 < bottom2 || top2 < bottom1 || right1 < left2 || right2 < left1)\n}\n\nexport function getHref<T> (d: T, identifier: StringAccessor<T>): string {\n const id = getString(d, identifier)\n return id ? `url(#${id})` : null\n}\n\nfunction evaluateSimpleExpression (expr: string): number {\n // Handle multiplication and division first (higher precedence)\n // Keep applying until no more operations are found\n while (/(-?\\d+(?:\\.\\d+)?)\\s*([*/])\\s*(-?\\d+(?:\\.\\d+)?)/.test(expr)) {\n expr = expr.replace(/(-?\\d+(?:\\.\\d+)?)\\s*([*/])\\s*(-?\\d+(?:\\.\\d+)?)/, (_, a, op, b) => {\n const numA = parseFloat(a)\n const numB = parseFloat(b)\n return String(op === '*' ? numA * numB : numA / numB)\n })\n }\n\n // Handle addition and subtraction (lower precedence)\n // Keep applying until no more operations are found\n while (/(-?\\d+(?:\\.\\d+)?)\\s*([+-])\\s*(-?\\d+(?:\\.\\d+)?)/.test(expr)) {\n expr = expr.replace(/(-?\\d+(?:\\.\\d+)?)\\s*([+-])\\s*(-?\\d+(?:\\.\\d+)?)/, (_, a, op, b) => {\n const numA = parseFloat(a)\n const numB = parseFloat(b)\n return String(op === '+' ? numA + numB : numA - numB)\n })\n }\n\n const result = parseFloat(expr)\n if (isNaN(result)) throw new Error(`Invalid expression: ${expr}`)\n return result\n}\n\nfunction evaluateCalcExpression (expression: string, basis: number): number {\n try {\n // Replace percentages and pixels with resolved values\n let expr = expression\n .replace(/(\\d+(?:\\.\\d+)?)%/g, (_, num) => String((basis * parseFloat(num)) / 100))\n .replace(/(\\d+(?:\\.\\d+)?)px/g, '$1')\n .replace(/\\s+/g, '')\n\n // Validate parentheses pairs before processing\n let parenCount = 0\n for (const char of expr) {\n if (char === '(') parenCount++\n else if (char === ')') parenCount--\n if (parenCount < 0) throw new Error('Mismatched parentheses: closing parenthesis without opening')\n }\n if (parenCount !== 0) throw new Error('Mismatched parentheses: unclosed opening parenthesis')\n\n // Check for invalid characters (only allow numbers, operators, decimal points, and parentheses)\n if (!/^[0-9+\\-*/.() ]+$/.test(expr)) throw new Error('Invalid characters in expression')\n\n // Check for empty parentheses\n if (/\\(\\s*\\)/.test(expr)) throw new Error('Empty parentheses not allowed')\n\n // Simple regex-based evaluation for basic expressions\n // Handles: number, number+number, number-number, number*number, number/number\n // And simple parentheses: (expression)\n\n // Evaluate parentheses first\n let iterations = 0\n const maxIterations = 100 // Prevent infinite loops\n while (expr.includes('(') && iterations < maxIterations) {\n const prevExpr = expr\n expr = expr.replace(/\\(([^()]+)\\)/g, (_, inner) => String(evaluateSimpleExpression(inner)))\n if (expr === prevExpr) throw new Error('Unable to resolve parentheses')\n iterations++\n }\n\n if (iterations >= maxIterations) throw new Error('Expression too complex or contains infinite recursion')\n if (expr.includes('(') || expr.includes(')')) throw new Error('Unresolved parentheses remain')\n\n return evaluateSimpleExpression(expr)\n } catch (error) {\n console.warn(`Failed to evaluate calc() expression: ${expression}`, error)\n return 0\n }\n}\n\nexport function parseUnit (value: LengthUnit, basis = 0): number {\n if (!value) return 0\n else if (typeof value === 'number') return value\n else if (typeof value === 'string' && value.startsWith('calc(') && value.endsWith(')')) {\n // Parse calc() expression\n const expression = value.slice(5, -1).trim() // Remove 'calc(' and ')'\n return evaluateCalcExpression(expression, basis)\n } else if (value.endsWith('%')) return basis * parseFloat(value) / 100\n else if (value.endsWith('px')) return parseFloat(value)\n else return parseFloat(value) || 0\n}\n"],"names":[],"mappings":"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"}
|
package/utils/text.d.ts
CHANGED
|
@@ -129,7 +129,7 @@ export declare const allowedSvgTextTags: string[];
|
|
|
129
129
|
* @param {UnovisText | UnovisText[]} text - The text or array of texts to render.
|
|
130
130
|
* @param {UnovisTextOptions} options - The text options.
|
|
131
131
|
*/
|
|
132
|
-
export declare function renderTextToSvgTextElement(textElement: SVGTextElement, text: UnovisText | UnovisText[], options: UnovisTextOptions,
|
|
132
|
+
export declare function renderTextToSvgTextElement(textElement: SVGTextElement, text: UnovisText | UnovisText[], options: UnovisTextOptions, dominantBaseline?: string): void;
|
|
133
133
|
/**
|
|
134
134
|
* Renders a text or array of texts into a frame.
|
|
135
135
|
* Calling this function will replace the contents of the specified SVG group.
|
package/utils/text.js
CHANGED
|
@@ -376,7 +376,7 @@ function getWrappedText(text, width = undefined, height = undefined, fastMode =
|
|
|
376
376
|
* @param {number} [y] - The y-coordinate for the tspan elements.
|
|
377
377
|
* @returns {string[]} - The SVG tspan strings.
|
|
378
378
|
*/
|
|
379
|
-
function renderTextToTspanStrings(blocks, x = 0, y) {
|
|
379
|
+
function renderTextToTspanStrings(blocks, x = 0, y, dominantBaseline) {
|
|
380
380
|
return blocks.map((b, i) => {
|
|
381
381
|
const prevBlock = i > 0 ? blocks[i - 1] : undefined;
|
|
382
382
|
const prevBlockMarginBottomEm = prevBlock ? prevBlock.marginBottom / prevBlock.fontSize : 0;
|
|
@@ -396,12 +396,12 @@ function renderTextToTspanStrings(blocks, x = 0, y) {
|
|
|
396
396
|
return `<tspan xmlns="http://www.w3.org/2000/svg" ${attributesString}>${b._lines.map((line, k) => {
|
|
397
397
|
let dy;
|
|
398
398
|
if (i === 0 && k === 0)
|
|
399
|
-
dy =
|
|
399
|
+
dy = marginEm;
|
|
400
400
|
else if (k === 0)
|
|
401
401
|
dy = marginEm + b.lineHeight;
|
|
402
402
|
else
|
|
403
403
|
dy = b.lineHeight;
|
|
404
|
-
return `<tspan x="${x}" dy="${dy}em">${line.length ? line : ' '}</tspan>`;
|
|
404
|
+
return `<tspan x="${x}" dy="${dy}em" dominant-baseline="${dominantBaseline !== null && dominantBaseline !== void 0 ? dominantBaseline : 'auto'}">${line.length ? line : ' '}</tspan>`;
|
|
405
405
|
}).join('')}</tspan>`;
|
|
406
406
|
});
|
|
407
407
|
}
|
|
@@ -425,7 +425,7 @@ const allowedSvgTextTags = ['text', 'tspan', 'textPath', 'altGlyph', 'altGlyphDe
|
|
|
425
425
|
* @param {UnovisText | UnovisText[]} text - The text or array of texts to render.
|
|
426
426
|
* @param {UnovisTextOptions} options - The text options.
|
|
427
427
|
*/
|
|
428
|
-
function renderTextToSvgTextElement(textElement, text, options,
|
|
428
|
+
function renderTextToSvgTextElement(textElement, text, options, dominantBaseline) {
|
|
429
429
|
var _a, _b;
|
|
430
430
|
const wrappedText = getWrappedText(text, options.width, undefined, options.fastMode, options.separator, options.wordBreak);
|
|
431
431
|
const textElementX = (_a = options.x) !== null && _a !== void 0 ? _a : +textElement.getAttribute('x');
|
|
@@ -447,16 +447,14 @@ function renderTextToSvgTextElement(textElement, text, options, trimmed) {
|
|
|
447
447
|
else {
|
|
448
448
|
textElement.removeAttribute('transform');
|
|
449
449
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
});
|
|
459
|
-
}
|
|
450
|
+
const parser = new DOMParser();
|
|
451
|
+
textElement.textContent = '';
|
|
452
|
+
wrappedText.forEach(block => {
|
|
453
|
+
const svgCode = renderTextToTspanStrings([block], x, y, dominantBaseline).join('');
|
|
454
|
+
const svgCodeSanitized = striptags(svgCode, allowedSvgTextTags);
|
|
455
|
+
const parsedSvgCode = parser.parseFromString(svgCodeSanitized, 'image/svg+xml').firstChild;
|
|
456
|
+
textElement.appendChild(parsedSvgCode);
|
|
457
|
+
});
|
|
460
458
|
}
|
|
461
459
|
/**
|
|
462
460
|
* Renders a text or array of texts into a frame.
|
|
@@ -487,7 +485,7 @@ function renderTextIntoFrame(group, text, frameOptions) {
|
|
|
487
485
|
text-anchor="${getTextAnchorFromTextAlign(frameOptions.textAlign)}"
|
|
488
486
|
${translate}
|
|
489
487
|
>
|
|
490
|
-
${renderTextToTspanStrings(wrappedText, x, y).join('')}
|
|
488
|
+
${renderTextToTspanStrings(wrappedText, x, y, 'hanging').join('')}
|
|
491
489
|
</text>`;
|
|
492
490
|
const parser = new DOMParser();
|
|
493
491
|
const svgCodeSanitized = striptags(svgCode, allowedSvgTextTags);
|