@unovis/ts 1.5.1-exf.12 → 1.5.1-exf.16
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/graph/config.d.ts +7 -0
- package/components/graph/config.js +1 -1
- package/components/graph/config.js.map +1 -1
- package/components/graph/modules/layout-helpers.js +1 -1
- package/components/graph/modules/layout-helpers.js.map +1 -1
- package/components/graph/modules/layout.js +1 -1
- package/components/graph/modules/layout.js.map +1 -1
- package/components/treemap/config.d.ts +10 -0
- package/components/treemap/config.js +1 -1
- package/components/treemap/config.js.map +1 -1
- package/components/treemap/index.d.ts +2 -0
- package/components/treemap/index.js +103 -43
- package/components/treemap/index.js.map +1 -1
- package/components/treemap/style.d.ts +3 -1
- package/components/treemap/style.js +17 -6
- package/components/treemap/style.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
|
@@ -2,6 +2,7 @@ import { D3BrushEvent } from 'd3-brush';
|
|
|
2
2
|
import { D3DragEvent } from 'd3-drag';
|
|
3
3
|
import { D3ZoomEvent, ZoomTransform } from 'd3-zoom';
|
|
4
4
|
import { Selection } from 'd3-selection';
|
|
5
|
+
import { ElkShape } from 'elkjs';
|
|
5
6
|
import type { GraphDataModel } from "../../data-models/graph";
|
|
6
7
|
import { ComponentConfigInterface } from "../../core/component/config";
|
|
7
8
|
import { TrimMode } from "../../types/text";
|
|
@@ -80,6 +81,12 @@ export interface GraphConfigInterface<N extends GraphInputNode, L extends GraphI
|
|
|
80
81
|
* E.g.: `[n => n.group, n => n.subGroup]`.
|
|
81
82
|
* Default: `undefined` */
|
|
82
83
|
layoutElkNodeGroups?: StringAccessor<N>[];
|
|
84
|
+
/** A function to be called per graph node to get the ELK shape object.
|
|
85
|
+
* This enables you to provide custom node dimensions (through the `width` and `height` properties)
|
|
86
|
+
* and coordinates (through the `x` and `y` properties) if needed.
|
|
87
|
+
* Default: `undefined`
|
|
88
|
+
*/
|
|
89
|
+
layoutElkGetNodeShape?: (d: GraphNode<N, L>, i: number) => ElkShape;
|
|
83
90
|
/** Link width accessor function ot constant value. Default: `1` */
|
|
84
91
|
linkWidth?: NumericAccessor<L>;
|
|
85
92
|
/** Link style accessor function or constant value. Default: `GraphLinkStyle.Solid` */
|
|
@@ -15,7 +15,7 @@ const GraphDefaultConfig = Object.assign(Object.assign({}, ComponentDefaultConfi
|
|
|
15
15
|
}, dagreLayoutSettings: {
|
|
16
16
|
rankdir: 'BT',
|
|
17
17
|
ranker: 'longest-path',
|
|
18
|
-
}, layoutElkSettings: undefined, layoutElkNodeGroups: undefined, linkFlowAnimDuration: 20000, linkFlowParticleSize: 2, linkWidth: 1, linkStyle: GraphLinkStyle.Solid, linkBandWidth: 0, linkArrow: undefined, linkStroke: undefined, linkFlow: false, linkLabel: undefined, linkLabelShiftFromCenter: true, linkNeighborSpacing: 8, linkDisabled: false, linkCurvature: 0, linkHighlightOnHover: true, linkSourcePointOffset: undefined, linkTargetPointOffset: undefined, selectedLinkId: undefined, nodeSize: 30, nodeStrokeWidth: 3, nodeShape: GraphNodeShape.Circle, nodeGaugeValue: 0, nodeIcon: (n) => n.icon, nodeIconSize: undefined, nodeLabel: (n) => n.label, nodeLabelTrim: true, nodeLabelTrimLength: 15, nodeLabelTrimMode: TrimMode.Middle, nodeSubLabel: '', nodeSubLabelTrim: true, nodeSubLabelTrimLength: 15, nodeSubLabelTrimMode: TrimMode.Middle, nodeSideLabels: undefined, nodeBottomIcon: undefined, nodeDisabled: false, nodeFill: (n) => n.fill, nodeGaugeFill: undefined, nodeStroke: (n) => n.stroke, nodeEnterPosition: undefined, nodeEnterScale: 0.75, nodeExitPosition: undefined, nodeExitScale: 0.75, nodeSort: undefined, nodeSelectionHighlightMode: GraphNodeSelectionHighlightMode.GreyoutNonConnected, nodeGaugeAnimDuration: 1500, selectedNodeId: undefined, selectedNodeIds: undefined, panels: undefined, onNodeDragStart: undefined, onNodeDrag: undefined, onNodeDragEnd: undefined, onZoom: undefined, onZoomStart: undefined, onZoomEnd: undefined, onLayoutCalculated: undefined, onNodeSelectionBrush: undefined, onNodeSelectionDrag: undefined, onRenderComplete: undefined, shouldDataUpdate: (prevData, nextData) => {
|
|
18
|
+
}, layoutElkSettings: undefined, layoutElkNodeGroups: undefined, layoutElkGetNodeShape: undefined, linkFlowAnimDuration: 20000, linkFlowParticleSize: 2, linkWidth: 1, linkStyle: GraphLinkStyle.Solid, linkBandWidth: 0, linkArrow: undefined, linkStroke: undefined, linkFlow: false, linkLabel: undefined, linkLabelShiftFromCenter: true, linkNeighborSpacing: 8, linkDisabled: false, linkCurvature: 0, linkHighlightOnHover: true, linkSourcePointOffset: undefined, linkTargetPointOffset: undefined, selectedLinkId: undefined, nodeSize: 30, nodeStrokeWidth: 3, nodeShape: GraphNodeShape.Circle, nodeGaugeValue: 0, nodeIcon: (n) => n.icon, nodeIconSize: undefined, nodeLabel: (n) => n.label, nodeLabelTrim: true, nodeLabelTrimLength: 15, nodeLabelTrimMode: TrimMode.Middle, nodeSubLabel: '', nodeSubLabelTrim: true, nodeSubLabelTrimLength: 15, nodeSubLabelTrimMode: TrimMode.Middle, nodeSideLabels: undefined, nodeBottomIcon: undefined, nodeDisabled: false, nodeFill: (n) => n.fill, nodeGaugeFill: undefined, nodeStroke: (n) => n.stroke, nodeEnterPosition: undefined, nodeEnterScale: 0.75, nodeExitPosition: undefined, nodeExitScale: 0.75, nodeSort: undefined, nodeSelectionHighlightMode: GraphNodeSelectionHighlightMode.GreyoutNonConnected, nodeGaugeAnimDuration: 1500, selectedNodeId: undefined, selectedNodeIds: undefined, panels: undefined, onNodeDragStart: undefined, onNodeDrag: undefined, onNodeDragEnd: undefined, onZoom: undefined, onZoomStart: undefined, onZoomEnd: undefined, onLayoutCalculated: undefined, onNodeSelectionBrush: undefined, onNodeSelectionDrag: undefined, onRenderComplete: undefined, shouldDataUpdate: (prevData, nextData) => {
|
|
19
19
|
return !isEqual(prevData, nextData);
|
|
20
20
|
} });
|
|
21
21
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sources":["../../../src/components/graph/config.ts"],"sourcesContent":["import { D3BrushEvent } from 'd3-brush'\nimport { D3DragEvent } from 'd3-drag'\nimport { D3ZoomEvent, ZoomTransform } from 'd3-zoom'\nimport { Selection } from 'd3-selection'\n\n// Core\nimport type { GraphDataModel } from 'data-models/graph'\n\n// Utils\nimport { isEqual } from 'utils/data'\n\n// Config\nimport { ComponentConfigInterface, ComponentDefaultConfig } from 'core/component/config'\n\n// Types\nimport { TrimMode } from 'types/text'\nimport { GraphInputLink, GraphInputNode, GraphInputData } from 'types/graph'\nimport { BooleanAccessor, ColorAccessor, NumericAccessor, StringAccessor, GenericAccessor } from 'types/accessor'\n\n// Local Types\nimport {\n GraphLayoutType,\n GraphCircleLabel,\n GraphLinkStyle,\n GraphLinkArrowStyle,\n GraphPanelConfig,\n GraphForceLayoutSettings,\n GraphElkLayoutSettings,\n GraphNodeShape,\n GraphDagreLayoutSetting,\n GraphNode,\n GraphLink,\n GraphNodeSelectionHighlightMode,\n} from './types'\n\n\nexport interface GraphConfigInterface<N extends GraphInputNode, L extends GraphInputLink> extends ComponentConfigInterface {\n // Zoom and drag\n /** Zoom level constraints. Default: [0.35, 1.25] */\n zoomScaleExtent?: [number, number];\n /** Disable zooming. Default: `false` */\n disableZoom?: boolean;\n /** Custom Zoom event filter to better control which actions should trigger zooming.\n * Learn more: https://d3js.org/d3-zoom#zoom_filter.\n * Default: `undefined` */\n zoomEventFilter?: (event: PointerEvent) => boolean;\n /** Disable node dragging. Default: `false` */\n disableDrag?: boolean;\n /** Disable brush for multiple node selection. Default: `false` */\n disableBrush?: boolean;\n /** Interval to re-render the graph when zooming. Default: `100` */\n zoomThrottledUpdateNodeThreshold?: number;\n\n // Layout general settings\n /** Type of the graph layout. Default: `GraphLayoutType.Force` */\n layoutType?: GraphLayoutType | string;\n /** Fit the graph to container on data or config updates, or on container resize. Default: `true` */\n layoutAutofit?: boolean;\n /** Tolerance constant defining whether the graph should be fitted to container\n * (on data or config update, or container resize) after a zoom / pan interaction or not.\n * `0` — Stop fitting after any pan or zoom\n * `Number.POSITIVE_INFINITY` — Always fit\n * Default: `8.0` */\n layoutAutofitTolerance?: number;\n /** Place non-connected nodes at the bottom of the graph. Default: `false` */\n layoutNonConnectedAside?: boolean;\n\n // Settings for Parallel and Concentric layouts\n /** Node group accessor function.\n * Only for `GraphLayoutType.Parallel`, `GraphLayoutType.ParallelHorizontal` and `GraphLayoutType.Concentric` layouts.\n * Default: `node => node.group` */\n layoutNodeGroup?: StringAccessor<N>;\n /** Order of the layout groups.\n * Only for `GraphLayoutType.Parallel`, `GraphLayoutType.ParallelHorizontal` and `GraphLayoutType.Concentric` layouts.\n * Default: `[]` */\n layoutGroupOrder?: string[];\n\n // Setting for Parallel layouts only\n /** Sets the number of nodes in a sub-group after which they'll continue on the next column (or row if `layoutType` is\n * `GraphLayoutType.ParallelHorizontal`).\n * Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.\n * Default: `6` */\n layoutParallelNodesPerColumn?: number;\n /** Node sub-group accessor function.\n * Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.\n * Default: `node => node.subgroup` */\n layoutParallelNodeSubGroup?: StringAccessor<N>;\n /** Number of sub-groups per row (or column if `layoutType` is `GraphLayoutType.ParallelHorizontal`) in a group.\n * Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.\n * Default: `1` */\n layoutParallelSubGroupsPerRow?: number;\n /** Spacing between groups.\n * Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.\n * Default: `undefined` */\n layoutParallelGroupSpacing?: number;\n /** Set a group by name to have priority in sorting the graph links.\n * Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.\n * Default: `undefined` */\n layoutParallelSortConnectionsByGroup?: string;\n\n // Force layout\n /** Force Layout settings, see the `d3-force` package for more details */\n forceLayoutSettings?: GraphForceLayoutSettings<N, L>;\n\n // Dagre layout\n /** Darge Layout settings, see the `dagrejs` package\n * for more details: https://github.com/dagrejs/dagre/wiki#configuring-the-layout\n */\n dagreLayoutSettings?: GraphDagreLayoutSetting;\n\n // ELK layout\n /** ELK layout options, see the `elkjs` package for more details: https://github.com/kieler/elkjs.\n * If you want to specify custom layout option for each node group, you can provide an accessor function that\n * receives group name ('root' for the top-level configuration) as the first argument and returns an object containing\n * layout options. Default: `undefined`\n */\n layoutElkSettings?: GenericAccessor<GraphElkLayoutSettings, string> | undefined;\n /** Array of accessor functions to define nested node groups for the ELK Layered layout.\n * E.g.: `[n => n.group, n => n.subGroup]`.\n * Default: `undefined` */\n layoutElkNodeGroups?: StringAccessor<N>[];\n\n // Links\n /** Link width accessor function ot constant value. Default: `1` */\n linkWidth?: NumericAccessor<L>;\n /** Link style accessor function or constant value. Default: `GraphLinkStyle.Solid` */\n linkStyle?: GenericAccessor<GraphLinkStyle, L>;\n /** Link band width accessor function or constant value. Default: `0` */\n linkBandWidth?: NumericAccessor<L>;\n /** Link arrow accessor function or constant value. Default: `undefined` */\n linkArrow?: GenericAccessor<GraphLinkArrowStyle | string | boolean, L> | undefined;\n /** Link stroke color accessor function or constant value. Default: `undefined` */\n linkStroke?: ColorAccessor<L>;\n /** Link disabled state accessor function or constant value. Default: `false` */\n linkDisabled?: BooleanAccessor<L>;\n /** Link flow animation accessor function or constant value. Default: `false` */\n linkFlow?: BooleanAccessor<L>;\n /** Animation duration of the flow (traffic) circles. Default: `20000` */\n linkFlowAnimDuration?: number;\n /** Size of the moving particles that represent traffic flow. Default: `2` */\n linkFlowParticleSize?: number;\n /** Link label accessor function or constant value. Default: `undefined` */\n linkLabel?: GenericAccessor<GraphCircleLabel | GraphCircleLabel[], L> | undefined;\n /** Shift label along the link center a little bit to avoid overlap with the link arrow. Default: `true` */\n linkLabelShiftFromCenter?: BooleanAccessor<L>;\n /** Spacing between neighboring links. Default: `8` */\n linkNeighborSpacing?: number;\n /** Curvature of the link. Recommended value range: [0:1.5].\n * `0` - straight line,\n * `1` - nice curvature,\n * `1.5` - very curve.\n * Default: `0` */\n linkCurvature?: NumericAccessor<L>;\n /** Highlight links on hover. Default: `true` */\n linkHighlightOnHover?: boolean;\n /** Offset [x,y] in pixels from the source node's center point where the link should start. Default: `undefined` */\n linkSourcePointOffset?: GenericAccessor<[number, number], GraphLink<N, L>>;\n /** Offset [x,y] in pixels from the target node's center point where the link should end. Default: `undefined` */\n linkTargetPointOffset?: GenericAccessor<[number, number], GraphLink<N, L>>;\n /** Set selected link by its unique id. Default: `undefined` */\n selectedLinkId?: number | string;\n\n // Nodes\n /** Node size accessor function or constant value. Default: `30` */\n nodeSize?: NumericAccessor<N>;\n /** Node stroke width accessor function or constant value. Default: `3` */\n nodeStrokeWidth?: NumericAccessor<N>;\n /** Node shape accessor function or constant value. Default: `GraphNodeShape.Circle` */\n nodeShape?: GenericAccessor<GraphNodeShape | string, N>;\n /** Node gauge outline accessor function or constant value in the range [0,100]. Default: `0` */\n nodeGaugeValue?: NumericAccessor<N>;\n /** Node gauge outline fill color accessor function or constant value. Default: `undefined` */\n nodeGaugeFill?: ColorAccessor<N>;\n /** Animation duration of the node gauge outline. Default: `1500` */\n nodeGaugeAnimDuration?: number;\n /** Node central icon accessor function or constant value. Default: `node => node.icon` */\n nodeIcon?: StringAccessor<N>;\n /** Node central icon size accessor function or constant value. Default: `undefined` */\n nodeIconSize?: NumericAccessor<N>;\n /** Node label accessor function or constant value. Default: `node => node.label` */\n nodeLabel?: StringAccessor<N>;\n /** Defines whether to trim the node labels or not. Default: `true` */\n nodeLabelTrim?: BooleanAccessor<N>;\n /** Node label trimming mode. Default: `TrimMode.Middle` */\n nodeLabelTrimMode?: GenericAccessor<TrimMode | string, N>;\n /** Node label maximum allowed text length above which the label will be trimmed. Default: `15` */\n nodeLabelTrimLength?: NumericAccessor<N>;\n /** Node sub-label accessor function or constant value: Default: `''` */\n nodeSubLabel?: StringAccessor<N>;\n /** Defines whether to trim the node sub-labels or not. Default: `true` */\n nodeSubLabelTrim?: BooleanAccessor<N>;\n /** Node sub-label trimming mode. Default: `TrimMode.Middle` */\n nodeSubLabelTrimMode?: GenericAccessor<TrimMode | string, N>;\n /** Node sub-label maximum allowed text length above which the label will be trimmed. Default: `15` */\n nodeSubLabelTrimLength?: NumericAccessor<N>;\n /** Node circular side labels accessor function. The function should return an array of GraphCircleLabel objects. Default: `undefined` */\n nodeSideLabels?: GenericAccessor<GraphCircleLabel[], N>;\n /** Node bottom icon accessor function. Default: `undefined` */\n nodeBottomIcon?: StringAccessor<N>;\n /** Node disabled state accessor function or constant value. Default: `false` */\n nodeDisabled?: BooleanAccessor<N>;\n /** Node fill color accessor function or constant value. Default: `node => node.fill` */\n nodeFill?: ColorAccessor<N>;\n /** Node stroke color accessor function or constant value. Default: `node => node.stroke` */\n nodeStroke?: ColorAccessor<N>;\n /** Sorting function to determine node placement. Default: `undefined` */\n nodeSort?: ((a: N, b: N) => number);\n /** Specify the initial position for entering nodes as [x, y]. Default: `undefined` */\n nodeEnterPosition?: GenericAccessor<[number, number], N> | undefined;\n /** Specify the initial scale for entering nodes in the range [0,1]. Default: `0.75` */\n nodeEnterScale?: NumericAccessor<N> | undefined;\n /** Specify the destination position for exiting nodes as [x, y]. Default: `undefined` */\n nodeExitPosition?: GenericAccessor<[number, number], N> | undefined;\n /** Specify the destination scale for exiting nodes in the range [0,1]. Default: `0.75` */\n nodeExitScale?: NumericAccessor<N> | undefined;\n /** Custom \"enter\" function for node rendering. Default: `undefined` */\n nodeEnterCustomRenderFunction?:\n (datum: GraphNode<N, L>, nodeGroupElementSelection: Selection<SVGGElement, GraphNode<N, L>, null, unknown>, config: GraphConfigInterface<N, L>, duration: number, zoomLevel: number) => void;\n /** Custom \"update\" function for node rendering. Default: `undefined` */\n nodeUpdateCustomRenderFunction?:\n (datum: GraphNode<N, L>, nodeGroupElementSelection: Selection<SVGGElement, GraphNode<N, L>, null, unknown>, config: GraphConfigInterface<N, L>, duration: number, zoomLevel: number) => void;\n /** Custom partial \"update\" function for node rendering which will be triggered after the following events:\n * - Full node update (`nodeUpdateCustomRenderFunction`);\n * - Background click;\n * - Node and Link mouseover and mouseout;\n * - Node brushing,\n * Default: `undefined` */\n nodePartialUpdateCustomRenderFunction?:\n (datum: GraphNode<N, L>, nodeGroupElementSelection: Selection<SVGGElement, GraphNode<N, L>, null, unknown>, config: GraphConfigInterface<N, L>, duration: number, zoomLevel: number) => void;\n /** Custom \"exit\" function for node rendering. Default: `undefined` */\n nodeExitCustomRenderFunction?:\n (datum: GraphNode<N, L>, nodeGroupElementSelection: Selection<SVGGElement, GraphNode<N, L>, null, unknown>, config: GraphConfigInterface<N, L>, duration: number, zoomLevel: number) => void;\n /** Custom render function that will be called while zooming / panning the graph. Default: `undefined` */\n nodeOnZoomCustomRenderFunction?:\n (datum: GraphNode<N, L>, nodeGroupElementSelection: Selection<SVGGElement, GraphNode<N, L>, null, unknown>, config: GraphConfigInterface<N, L>, zoomLevel: number) => void;\n /** Define the mode for highlighting selected nodes in the graph. Default: `GraphNodeSelectionHighlightMode.GreyoutNonConnected` */\n nodeSelectionHighlightMode?: GraphNodeSelectionHighlightMode;\n /** Set selected node by unique id. Default: `undefined` */\n selectedNodeId?: number | string;\n /** Set selected nodes by unique id. Default: `undefined` */\n selectedNodeIds?: number[] | string[];\n\n /** Panels configuration. An array of `GraphPanelConfig` objects. Default: `[]` */\n panels?: GraphPanelConfig[] | undefined;\n\n // Events\n /** Graph node drag start callback function. Default: `undefined` */\n onNodeDragStart?: (n: GraphNode<N, L>, event: D3DragEvent<SVGGElement, GraphNode<N, L>, unknown>) => void | undefined;\n /** Graph node drag callback function. Default: `undefined` */\n onNodeDrag?: (n: GraphNode<N, L>, event: D3DragEvent<SVGGElement, GraphNode<N, L>, unknown>) => void | undefined;\n /** Graph node drag end callback function. Default: `undefined` */\n onNodeDragEnd?: (n: GraphNode<N, L>, event: D3DragEvent<SVGGElement, GraphNode<N, L>, unknown>) => void | undefined;\n /** Zoom event callback. Default: `undefined` */\n onZoom?: (zoomScale: number, zoomScaleExtent: [number, number], event: D3ZoomEvent<SVGGElement, unknown> | undefined, transform: ZoomTransform) => void;\n /** Zoom start event callback. Default: `undefined` */\n onZoomStart?: (zoomScale: number, zoomScaleExtent: [number, number], event: D3ZoomEvent<SVGGElement, unknown> | undefined, transform: ZoomTransform) => void;\n /** Zoom end event callback. Default: `undefined` */\n onZoomEnd?: (zoomScale: number, zoomScaleExtent: [number, number], event: D3ZoomEvent<SVGGElement, unknown> | undefined, transform: ZoomTransform) => void;\n /** Callback function to be called when the graph layout is calculated. Default: `undefined` */\n onLayoutCalculated?: (nodes: GraphNode<N, L>[], links: GraphLink<N, L>[]) => void;\n /** Graph node selection brush callback function. Default: `undefined` */\n onNodeSelectionBrush?: (selectedNodes: GraphNode<N, L>[], event: D3BrushEvent<SVGGElement> | undefined) => void;\n /** Graph multiple node drag callback function. Default: `undefined` */\n onNodeSelectionDrag?: (selectedNodes: GraphNode<N, L>[], event: D3DragEvent<SVGGElement, GraphNode<N, L>, unknown>) => void;\n /** Callback function to be called when the graph rendering is complete. Default: `undefined` */\n onRenderComplete?: (\n g: Selection<SVGGElement, unknown, null, undefined>,\n nodes: GraphNode<N, L>[],\n links: GraphLink<N, L>[],\n config: GraphConfigInterface<N, L>,\n duration: number,\n zoomLevel: number,\n width: number,\n height: number\n ) => void;\n\n /** Determines whether the component should update when new data is provided.\n * This function takes the previous and new data as parameters and returns a boolean\n * indicating whether the update should proceed. Useful for fine-grained control over\n * update behavior when your data has a complex nested structure.\n * By default the `isEqual` function from Unovis will be used to do the comparison.\n */\n shouldDataUpdate?: (\n prevData: GraphInputData<N, L>,\n nextData: GraphInputData<N, L>,\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>\n ) => boolean;\n}\n\nexport const GraphDefaultConfig: GraphConfigInterface<GraphInputNode, GraphInputLink> = {\n ...ComponentDefaultConfig,\n duration: 1000,\n zoomScaleExtent: [0.35, 1.25],\n disableZoom: false,\n zoomEventFilter: undefined,\n disableDrag: false,\n disableBrush: false,\n zoomThrottledUpdateNodeThreshold: 100,\n layoutType: GraphLayoutType.Force,\n layoutAutofit: true,\n layoutAutofitTolerance: 8.0,\n layoutNonConnectedAside: false,\n\n layoutGroupOrder: [],\n layoutParallelSubGroupsPerRow: 1,\n layoutParallelNodesPerColumn: 6,\n layoutParallelGroupSpacing: undefined,\n layoutParallelSortConnectionsByGroup: undefined,\n layoutNodeGroup: (n: GraphInputNode): string => (n as { group: string }).group,\n layoutParallelNodeSubGroup: (n: GraphInputNode): string => (n as { subgroup: string }).subgroup,\n\n forceLayoutSettings: {\n linkDistance: 60,\n linkStrength: 0.45,\n charge: -500,\n forceXStrength: 0.15,\n forceYStrength: 0.25,\n numIterations: undefined,\n fixNodePositionAfterSimulation: false,\n },\n\n dagreLayoutSettings: {\n rankdir: 'BT',\n ranker: 'longest-path',\n },\n\n layoutElkSettings: undefined,\n layoutElkNodeGroups: undefined,\n\n linkFlowAnimDuration: 20000,\n linkFlowParticleSize: 2,\n linkWidth: 1,\n linkStyle: GraphLinkStyle.Solid,\n linkBandWidth: 0,\n linkArrow: undefined,\n linkStroke: undefined,\n linkFlow: false,\n linkLabel: undefined,\n linkLabelShiftFromCenter: true,\n linkNeighborSpacing: 8,\n linkDisabled: false,\n linkCurvature: 0,\n linkHighlightOnHover: true,\n linkSourcePointOffset: undefined,\n linkTargetPointOffset: undefined,\n selectedLinkId: undefined,\n\n nodeSize: 30,\n nodeStrokeWidth: 3,\n nodeShape: GraphNodeShape.Circle,\n nodeGaugeValue: 0,\n nodeIcon: (n: GraphInputNode): string => (n as { icon: string }).icon,\n nodeIconSize: undefined,\n nodeLabel: (n: GraphInputNode): string => (n as { label: string }).label,\n nodeLabelTrim: true,\n nodeLabelTrimLength: 15,\n nodeLabelTrimMode: TrimMode.Middle,\n nodeSubLabel: '',\n nodeSubLabelTrim: true,\n nodeSubLabelTrimLength: 15,\n nodeSubLabelTrimMode: TrimMode.Middle,\n nodeSideLabels: undefined,\n nodeBottomIcon: undefined,\n nodeDisabled: false,\n nodeFill: (n: GraphInputNode): string => (n as { fill: string }).fill,\n nodeGaugeFill: undefined,\n nodeStroke: (n: GraphInputNode): string => (n as { stroke: string }).stroke,\n nodeEnterPosition: undefined,\n nodeEnterScale: 0.75,\n nodeExitPosition: undefined,\n nodeExitScale: 0.75,\n nodeSort: undefined,\n nodeSelectionHighlightMode: GraphNodeSelectionHighlightMode.GreyoutNonConnected,\n nodeGaugeAnimDuration: 1500,\n\n selectedNodeId: undefined,\n selectedNodeIds: undefined,\n\n panels: undefined,\n\n onNodeDragStart: undefined,\n onNodeDrag: undefined,\n onNodeDragEnd: undefined,\n onZoom: undefined,\n onZoomStart: undefined,\n onZoomEnd: undefined,\n onLayoutCalculated: undefined,\n onNodeSelectionBrush: undefined,\n onNodeSelectionDrag: undefined,\n onRenderComplete: undefined,\n\n shouldDataUpdate: (prevData: GraphInputData<GraphInputNode, GraphInputLink>, nextData: GraphInputData<GraphInputNode, GraphInputLink>): boolean => {\n return !isEqual(prevData, nextData)\n },\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","sources":["../../../src/components/graph/config.ts"],"sourcesContent":["import { D3BrushEvent } from 'd3-brush'\nimport { D3DragEvent } from 'd3-drag'\nimport { D3ZoomEvent, ZoomTransform } from 'd3-zoom'\nimport { Selection } from 'd3-selection'\nimport { ElkShape } from 'elkjs'\n\n// Core\nimport type { GraphDataModel } from 'data-models/graph'\n\n// Utils\nimport { isEqual } from 'utils/data'\n\n// Config\nimport { ComponentConfigInterface, ComponentDefaultConfig } from 'core/component/config'\n\n// Types\nimport { TrimMode } from 'types/text'\nimport { GraphInputLink, GraphInputNode, GraphInputData } from 'types/graph'\nimport { BooleanAccessor, ColorAccessor, NumericAccessor, StringAccessor, GenericAccessor } from 'types/accessor'\n\n// Local Types\nimport {\n GraphLayoutType,\n GraphCircleLabel,\n GraphLinkStyle,\n GraphLinkArrowStyle,\n GraphPanelConfig,\n GraphForceLayoutSettings,\n GraphElkLayoutSettings,\n GraphNodeShape,\n GraphDagreLayoutSetting,\n GraphNode,\n GraphLink,\n GraphNodeSelectionHighlightMode,\n} from './types'\n\n\nexport interface GraphConfigInterface<N extends GraphInputNode, L extends GraphInputLink> extends ComponentConfigInterface {\n // Zoom and drag\n /** Zoom level constraints. Default: [0.35, 1.25] */\n zoomScaleExtent?: [number, number];\n /** Disable zooming. Default: `false` */\n disableZoom?: boolean;\n /** Custom Zoom event filter to better control which actions should trigger zooming.\n * Learn more: https://d3js.org/d3-zoom#zoom_filter.\n * Default: `undefined` */\n zoomEventFilter?: (event: PointerEvent) => boolean;\n /** Disable node dragging. Default: `false` */\n disableDrag?: boolean;\n /** Disable brush for multiple node selection. Default: `false` */\n disableBrush?: boolean;\n /** Interval to re-render the graph when zooming. Default: `100` */\n zoomThrottledUpdateNodeThreshold?: number;\n\n // Layout general settings\n /** Type of the graph layout. Default: `GraphLayoutType.Force` */\n layoutType?: GraphLayoutType | string;\n /** Fit the graph to container on data or config updates, or on container resize. Default: `true` */\n layoutAutofit?: boolean;\n /** Tolerance constant defining whether the graph should be fitted to container\n * (on data or config update, or container resize) after a zoom / pan interaction or not.\n * `0` — Stop fitting after any pan or zoom\n * `Number.POSITIVE_INFINITY` — Always fit\n * Default: `8.0` */\n layoutAutofitTolerance?: number;\n /** Place non-connected nodes at the bottom of the graph. Default: `false` */\n layoutNonConnectedAside?: boolean;\n\n // Settings for Parallel and Concentric layouts\n /** Node group accessor function.\n * Only for `GraphLayoutType.Parallel`, `GraphLayoutType.ParallelHorizontal` and `GraphLayoutType.Concentric` layouts.\n * Default: `node => node.group` */\n layoutNodeGroup?: StringAccessor<N>;\n /** Order of the layout groups.\n * Only for `GraphLayoutType.Parallel`, `GraphLayoutType.ParallelHorizontal` and `GraphLayoutType.Concentric` layouts.\n * Default: `[]` */\n layoutGroupOrder?: string[];\n\n // Setting for Parallel layouts only\n /** Sets the number of nodes in a sub-group after which they'll continue on the next column (or row if `layoutType` is\n * `GraphLayoutType.ParallelHorizontal`).\n * Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.\n * Default: `6` */\n layoutParallelNodesPerColumn?: number;\n /** Node sub-group accessor function.\n * Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.\n * Default: `node => node.subgroup` */\n layoutParallelNodeSubGroup?: StringAccessor<N>;\n /** Number of sub-groups per row (or column if `layoutType` is `GraphLayoutType.ParallelHorizontal`) in a group.\n * Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.\n * Default: `1` */\n layoutParallelSubGroupsPerRow?: number;\n /** Spacing between groups.\n * Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.\n * Default: `undefined` */\n layoutParallelGroupSpacing?: number;\n /** Set a group by name to have priority in sorting the graph links.\n * Only for `GraphLayoutType.Parallel` and `GraphLayoutType.ParallelHorizontal` layouts.\n * Default: `undefined` */\n layoutParallelSortConnectionsByGroup?: string;\n\n // Force layout\n /** Force Layout settings, see the `d3-force` package for more details */\n forceLayoutSettings?: GraphForceLayoutSettings<N, L>;\n\n // Dagre layout\n /** Darge Layout settings, see the `dagrejs` package\n * for more details: https://github.com/dagrejs/dagre/wiki#configuring-the-layout\n */\n dagreLayoutSettings?: GraphDagreLayoutSetting;\n\n // ELK layout\n /** ELK layout options, see the `elkjs` package for more details: https://github.com/kieler/elkjs.\n * If you want to specify custom layout option for each node group, you can provide an accessor function that\n * receives group name ('root' for the top-level configuration) as the first argument and returns an object containing\n * layout options. Default: `undefined`\n */\n layoutElkSettings?: GenericAccessor<GraphElkLayoutSettings, string> | undefined;\n /** Array of accessor functions to define nested node groups for the ELK Layered layout.\n * E.g.: `[n => n.group, n => n.subGroup]`.\n * Default: `undefined` */\n layoutElkNodeGroups?: StringAccessor<N>[];\n /** A function to be called per graph node to get the ELK shape object.\n * This enables you to provide custom node dimensions (through the `width` and `height` properties)\n * and coordinates (through the `x` and `y` properties) if needed.\n * Default: `undefined`\n */\n layoutElkGetNodeShape?: (d: GraphNode<N, L>, i: number) => ElkShape;\n\n // Links\n /** Link width accessor function ot constant value. Default: `1` */\n linkWidth?: NumericAccessor<L>;\n /** Link style accessor function or constant value. Default: `GraphLinkStyle.Solid` */\n linkStyle?: GenericAccessor<GraphLinkStyle, L>;\n /** Link band width accessor function or constant value. Default: `0` */\n linkBandWidth?: NumericAccessor<L>;\n /** Link arrow accessor function or constant value. Default: `undefined` */\n linkArrow?: GenericAccessor<GraphLinkArrowStyle | string | boolean, L> | undefined;\n /** Link stroke color accessor function or constant value. Default: `undefined` */\n linkStroke?: ColorAccessor<L>;\n /** Link disabled state accessor function or constant value. Default: `false` */\n linkDisabled?: BooleanAccessor<L>;\n /** Link flow animation accessor function or constant value. Default: `false` */\n linkFlow?: BooleanAccessor<L>;\n /** Animation duration of the flow (traffic) circles. Default: `20000` */\n linkFlowAnimDuration?: number;\n /** Size of the moving particles that represent traffic flow. Default: `2` */\n linkFlowParticleSize?: number;\n /** Link label accessor function or constant value. Default: `undefined` */\n linkLabel?: GenericAccessor<GraphCircleLabel | GraphCircleLabel[], L> | undefined;\n /** Shift label along the link center a little bit to avoid overlap with the link arrow. Default: `true` */\n linkLabelShiftFromCenter?: BooleanAccessor<L>;\n /** Spacing between neighboring links. Default: `8` */\n linkNeighborSpacing?: number;\n /** Curvature of the link. Recommended value range: [0:1.5].\n * `0` - straight line,\n * `1` - nice curvature,\n * `1.5` - very curve.\n * Default: `0` */\n linkCurvature?: NumericAccessor<L>;\n /** Highlight links on hover. Default: `true` */\n linkHighlightOnHover?: boolean;\n /** Offset [x,y] in pixels from the source node's center point where the link should start. Default: `undefined` */\n linkSourcePointOffset?: GenericAccessor<[number, number], GraphLink<N, L>>;\n /** Offset [x,y] in pixels from the target node's center point where the link should end. Default: `undefined` */\n linkTargetPointOffset?: GenericAccessor<[number, number], GraphLink<N, L>>;\n /** Set selected link by its unique id. Default: `undefined` */\n selectedLinkId?: number | string;\n\n // Nodes\n /** Node size accessor function or constant value. Default: `30` */\n nodeSize?: NumericAccessor<N>;\n /** Node stroke width accessor function or constant value. Default: `3` */\n nodeStrokeWidth?: NumericAccessor<N>;\n /** Node shape accessor function or constant value. Default: `GraphNodeShape.Circle` */\n nodeShape?: GenericAccessor<GraphNodeShape | string, N>;\n /** Node gauge outline accessor function or constant value in the range [0,100]. Default: `0` */\n nodeGaugeValue?: NumericAccessor<N>;\n /** Node gauge outline fill color accessor function or constant value. Default: `undefined` */\n nodeGaugeFill?: ColorAccessor<N>;\n /** Animation duration of the node gauge outline. Default: `1500` */\n nodeGaugeAnimDuration?: number;\n /** Node central icon accessor function or constant value. Default: `node => node.icon` */\n nodeIcon?: StringAccessor<N>;\n /** Node central icon size accessor function or constant value. Default: `undefined` */\n nodeIconSize?: NumericAccessor<N>;\n /** Node label accessor function or constant value. Default: `node => node.label` */\n nodeLabel?: StringAccessor<N>;\n /** Defines whether to trim the node labels or not. Default: `true` */\n nodeLabelTrim?: BooleanAccessor<N>;\n /** Node label trimming mode. Default: `TrimMode.Middle` */\n nodeLabelTrimMode?: GenericAccessor<TrimMode | string, N>;\n /** Node label maximum allowed text length above which the label will be trimmed. Default: `15` */\n nodeLabelTrimLength?: NumericAccessor<N>;\n /** Node sub-label accessor function or constant value: Default: `''` */\n nodeSubLabel?: StringAccessor<N>;\n /** Defines whether to trim the node sub-labels or not. Default: `true` */\n nodeSubLabelTrim?: BooleanAccessor<N>;\n /** Node sub-label trimming mode. Default: `TrimMode.Middle` */\n nodeSubLabelTrimMode?: GenericAccessor<TrimMode | string, N>;\n /** Node sub-label maximum allowed text length above which the label will be trimmed. Default: `15` */\n nodeSubLabelTrimLength?: NumericAccessor<N>;\n /** Node circular side labels accessor function. The function should return an array of GraphCircleLabel objects. Default: `undefined` */\n nodeSideLabels?: GenericAccessor<GraphCircleLabel[], N>;\n /** Node bottom icon accessor function. Default: `undefined` */\n nodeBottomIcon?: StringAccessor<N>;\n /** Node disabled state accessor function or constant value. Default: `false` */\n nodeDisabled?: BooleanAccessor<N>;\n /** Node fill color accessor function or constant value. Default: `node => node.fill` */\n nodeFill?: ColorAccessor<N>;\n /** Node stroke color accessor function or constant value. Default: `node => node.stroke` */\n nodeStroke?: ColorAccessor<N>;\n /** Sorting function to determine node placement. Default: `undefined` */\n nodeSort?: ((a: N, b: N) => number);\n /** Specify the initial position for entering nodes as [x, y]. Default: `undefined` */\n nodeEnterPosition?: GenericAccessor<[number, number], N> | undefined;\n /** Specify the initial scale for entering nodes in the range [0,1]. Default: `0.75` */\n nodeEnterScale?: NumericAccessor<N> | undefined;\n /** Specify the destination position for exiting nodes as [x, y]. Default: `undefined` */\n nodeExitPosition?: GenericAccessor<[number, number], N> | undefined;\n /** Specify the destination scale for exiting nodes in the range [0,1]. Default: `0.75` */\n nodeExitScale?: NumericAccessor<N> | undefined;\n /** Custom \"enter\" function for node rendering. Default: `undefined` */\n nodeEnterCustomRenderFunction?:\n (datum: GraphNode<N, L>, nodeGroupElementSelection: Selection<SVGGElement, GraphNode<N, L>, null, unknown>, config: GraphConfigInterface<N, L>, duration: number, zoomLevel: number) => void;\n /** Custom \"update\" function for node rendering. Default: `undefined` */\n nodeUpdateCustomRenderFunction?:\n (datum: GraphNode<N, L>, nodeGroupElementSelection: Selection<SVGGElement, GraphNode<N, L>, null, unknown>, config: GraphConfigInterface<N, L>, duration: number, zoomLevel: number) => void;\n /** Custom partial \"update\" function for node rendering which will be triggered after the following events:\n * - Full node update (`nodeUpdateCustomRenderFunction`);\n * - Background click;\n * - Node and Link mouseover and mouseout;\n * - Node brushing,\n * Default: `undefined` */\n nodePartialUpdateCustomRenderFunction?:\n (datum: GraphNode<N, L>, nodeGroupElementSelection: Selection<SVGGElement, GraphNode<N, L>, null, unknown>, config: GraphConfigInterface<N, L>, duration: number, zoomLevel: number) => void;\n /** Custom \"exit\" function for node rendering. Default: `undefined` */\n nodeExitCustomRenderFunction?:\n (datum: GraphNode<N, L>, nodeGroupElementSelection: Selection<SVGGElement, GraphNode<N, L>, null, unknown>, config: GraphConfigInterface<N, L>, duration: number, zoomLevel: number) => void;\n /** Custom render function that will be called while zooming / panning the graph. Default: `undefined` */\n nodeOnZoomCustomRenderFunction?:\n (datum: GraphNode<N, L>, nodeGroupElementSelection: Selection<SVGGElement, GraphNode<N, L>, null, unknown>, config: GraphConfigInterface<N, L>, zoomLevel: number) => void;\n /** Define the mode for highlighting selected nodes in the graph. Default: `GraphNodeSelectionHighlightMode.GreyoutNonConnected` */\n nodeSelectionHighlightMode?: GraphNodeSelectionHighlightMode;\n /** Set selected node by unique id. Default: `undefined` */\n selectedNodeId?: number | string;\n /** Set selected nodes by unique id. Default: `undefined` */\n selectedNodeIds?: number[] | string[];\n\n /** Panels configuration. An array of `GraphPanelConfig` objects. Default: `[]` */\n panels?: GraphPanelConfig[] | undefined;\n\n // Events\n /** Graph node drag start callback function. Default: `undefined` */\n onNodeDragStart?: (n: GraphNode<N, L>, event: D3DragEvent<SVGGElement, GraphNode<N, L>, unknown>) => void | undefined;\n /** Graph node drag callback function. Default: `undefined` */\n onNodeDrag?: (n: GraphNode<N, L>, event: D3DragEvent<SVGGElement, GraphNode<N, L>, unknown>) => void | undefined;\n /** Graph node drag end callback function. Default: `undefined` */\n onNodeDragEnd?: (n: GraphNode<N, L>, event: D3DragEvent<SVGGElement, GraphNode<N, L>, unknown>) => void | undefined;\n /** Zoom event callback. Default: `undefined` */\n onZoom?: (zoomScale: number, zoomScaleExtent: [number, number], event: D3ZoomEvent<SVGGElement, unknown> | undefined, transform: ZoomTransform) => void;\n /** Zoom start event callback. Default: `undefined` */\n onZoomStart?: (zoomScale: number, zoomScaleExtent: [number, number], event: D3ZoomEvent<SVGGElement, unknown> | undefined, transform: ZoomTransform) => void;\n /** Zoom end event callback. Default: `undefined` */\n onZoomEnd?: (zoomScale: number, zoomScaleExtent: [number, number], event: D3ZoomEvent<SVGGElement, unknown> | undefined, transform: ZoomTransform) => void;\n /** Callback function to be called when the graph layout is calculated. Default: `undefined` */\n onLayoutCalculated?: (nodes: GraphNode<N, L>[], links: GraphLink<N, L>[]) => void;\n /** Graph node selection brush callback function. Default: `undefined` */\n onNodeSelectionBrush?: (selectedNodes: GraphNode<N, L>[], event: D3BrushEvent<SVGGElement> | undefined) => void;\n /** Graph multiple node drag callback function. Default: `undefined` */\n onNodeSelectionDrag?: (selectedNodes: GraphNode<N, L>[], event: D3DragEvent<SVGGElement, GraphNode<N, L>, unknown>) => void;\n /** Callback function to be called when the graph rendering is complete. Default: `undefined` */\n onRenderComplete?: (\n g: Selection<SVGGElement, unknown, null, undefined>,\n nodes: GraphNode<N, L>[],\n links: GraphLink<N, L>[],\n config: GraphConfigInterface<N, L>,\n duration: number,\n zoomLevel: number,\n width: number,\n height: number\n ) => void;\n\n /** Determines whether the component should update when new data is provided.\n * This function takes the previous and new data as parameters and returns a boolean\n * indicating whether the update should proceed. Useful for fine-grained control over\n * update behavior when your data has a complex nested structure.\n * By default the `isEqual` function from Unovis will be used to do the comparison.\n */\n shouldDataUpdate?: (\n prevData: GraphInputData<N, L>,\n nextData: GraphInputData<N, L>,\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>\n ) => boolean;\n}\n\nexport const GraphDefaultConfig: GraphConfigInterface<GraphInputNode, GraphInputLink> = {\n ...ComponentDefaultConfig,\n duration: 1000,\n zoomScaleExtent: [0.35, 1.25],\n disableZoom: false,\n zoomEventFilter: undefined,\n disableDrag: false,\n disableBrush: false,\n zoomThrottledUpdateNodeThreshold: 100,\n layoutType: GraphLayoutType.Force,\n layoutAutofit: true,\n layoutAutofitTolerance: 8.0,\n layoutNonConnectedAside: false,\n\n layoutGroupOrder: [],\n layoutParallelSubGroupsPerRow: 1,\n layoutParallelNodesPerColumn: 6,\n layoutParallelGroupSpacing: undefined,\n layoutParallelSortConnectionsByGroup: undefined,\n layoutNodeGroup: (n: GraphInputNode): string => (n as { group: string }).group,\n layoutParallelNodeSubGroup: (n: GraphInputNode): string => (n as { subgroup: string }).subgroup,\n\n forceLayoutSettings: {\n linkDistance: 60,\n linkStrength: 0.45,\n charge: -500,\n forceXStrength: 0.15,\n forceYStrength: 0.25,\n numIterations: undefined,\n fixNodePositionAfterSimulation: false,\n },\n\n dagreLayoutSettings: {\n rankdir: 'BT',\n ranker: 'longest-path',\n },\n\n layoutElkSettings: undefined,\n layoutElkNodeGroups: undefined,\n layoutElkGetNodeShape: undefined,\n\n linkFlowAnimDuration: 20000,\n linkFlowParticleSize: 2,\n linkWidth: 1,\n linkStyle: GraphLinkStyle.Solid,\n linkBandWidth: 0,\n linkArrow: undefined,\n linkStroke: undefined,\n linkFlow: false,\n linkLabel: undefined,\n linkLabelShiftFromCenter: true,\n linkNeighborSpacing: 8,\n linkDisabled: false,\n linkCurvature: 0,\n linkHighlightOnHover: true,\n linkSourcePointOffset: undefined,\n linkTargetPointOffset: undefined,\n selectedLinkId: undefined,\n\n nodeSize: 30,\n nodeStrokeWidth: 3,\n nodeShape: GraphNodeShape.Circle,\n nodeGaugeValue: 0,\n nodeIcon: (n: GraphInputNode): string => (n as { icon: string }).icon,\n nodeIconSize: undefined,\n nodeLabel: (n: GraphInputNode): string => (n as { label: string }).label,\n nodeLabelTrim: true,\n nodeLabelTrimLength: 15,\n nodeLabelTrimMode: TrimMode.Middle,\n nodeSubLabel: '',\n nodeSubLabelTrim: true,\n nodeSubLabelTrimLength: 15,\n nodeSubLabelTrimMode: TrimMode.Middle,\n nodeSideLabels: undefined,\n nodeBottomIcon: undefined,\n nodeDisabled: false,\n nodeFill: (n: GraphInputNode): string => (n as { fill: string }).fill,\n nodeGaugeFill: undefined,\n nodeStroke: (n: GraphInputNode): string => (n as { stroke: string }).stroke,\n nodeEnterPosition: undefined,\n nodeEnterScale: 0.75,\n nodeExitPosition: undefined,\n nodeExitScale: 0.75,\n nodeSort: undefined,\n nodeSelectionHighlightMode: GraphNodeSelectionHighlightMode.GreyoutNonConnected,\n nodeGaugeAnimDuration: 1500,\n\n selectedNodeId: undefined,\n selectedNodeIds: undefined,\n\n panels: undefined,\n\n onNodeDragStart: undefined,\n onNodeDrag: undefined,\n onNodeDragEnd: undefined,\n onZoom: undefined,\n onZoomStart: undefined,\n onZoomEnd: undefined,\n onLayoutCalculated: undefined,\n onNodeSelectionBrush: undefined,\n onNodeSelectionDrag: undefined,\n onRenderComplete: undefined,\n\n shouldDataUpdate: (prevData: GraphInputData<GraphInputNode, GraphInputLink>, nextData: GraphInputData<GraphInputNode, GraphInputLink>): boolean => {\n return !isEqual(prevData, nextData)\n },\n}\n"],"names":[],"mappings":";;;;;AASA;MA+Ra,kBAAkB,GAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAC1B,sBAAsB,CACzB,EAAA,EAAA,QAAQ,EAAE,IAAI,EACd,eAAe,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAC7B,WAAW,EAAE,KAAK,EAClB,eAAe,EAAE,SAAS,EAC1B,WAAW,EAAE,KAAK,EAClB,YAAY,EAAE,KAAK,EACnB,gCAAgC,EAAE,GAAG,EACrC,UAAU,EAAE,eAAe,CAAC,KAAK,EACjC,aAAa,EAAE,IAAI,EACnB,sBAAsB,EAAE,GAAG,EAC3B,uBAAuB,EAAE,KAAK,EAE9B,gBAAgB,EAAE,EAAE,EACpB,6BAA6B,EAAE,CAAC,EAChC,4BAA4B,EAAE,CAAC,EAC/B,0BAA0B,EAAE,SAAS,EACrC,oCAAoC,EAAE,SAAS,EAC/C,eAAe,EAAE,CAAC,CAAiB,KAAc,CAAuB,CAAC,KAAK,EAC9E,0BAA0B,EAAE,CAAC,CAAiB,KAAc,CAA0B,CAAC,QAAQ,EAE/F,mBAAmB,EAAE;AACnB,QAAA,YAAY,EAAE,EAAE;AAChB,QAAA,YAAY,EAAE,IAAI;QAClB,MAAM,EAAE,CAAC,GAAG;AACZ,QAAA,cAAc,EAAE,IAAI;AACpB,QAAA,cAAc,EAAE,IAAI;AACpB,QAAA,aAAa,EAAE,SAAS;AACxB,QAAA,8BAA8B,EAAE,KAAK;AACtC,KAAA,EAED,mBAAmB,EAAE;AACnB,QAAA,OAAO,EAAE,IAAI;AACb,QAAA,MAAM,EAAE,cAAc;AACvB,KAAA,EAED,iBAAiB,EAAE,SAAS,EAC5B,mBAAmB,EAAE,SAAS,EAC9B,qBAAqB,EAAE,SAAS,EAEhC,oBAAoB,EAAE,KAAK,EAC3B,oBAAoB,EAAE,CAAC,EACvB,SAAS,EAAE,CAAC,EACZ,SAAS,EAAE,cAAc,CAAC,KAAK,EAC/B,aAAa,EAAE,CAAC,EAChB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,SAAS,EACrB,QAAQ,EAAE,KAAK,EACf,SAAS,EAAE,SAAS,EACpB,wBAAwB,EAAE,IAAI,EAC9B,mBAAmB,EAAE,CAAC,EACtB,YAAY,EAAE,KAAK,EACnB,aAAa,EAAE,CAAC,EAChB,oBAAoB,EAAE,IAAI,EAC1B,qBAAqB,EAAE,SAAS,EAChC,qBAAqB,EAAE,SAAS,EAChC,cAAc,EAAE,SAAS,EAEzB,QAAQ,EAAE,EAAE,EACZ,eAAe,EAAE,CAAC,EAClB,SAAS,EAAE,cAAc,CAAC,MAAM,EAChC,cAAc,EAAE,CAAC,EACjB,QAAQ,EAAE,CAAC,CAAiB,KAAc,CAAsB,CAAC,IAAI,EACrE,YAAY,EAAE,SAAS,EACvB,SAAS,EAAE,CAAC,CAAiB,KAAc,CAAuB,CAAC,KAAK,EACxE,aAAa,EAAE,IAAI,EACnB,mBAAmB,EAAE,EAAE,EACvB,iBAAiB,EAAE,QAAQ,CAAC,MAAM,EAClC,YAAY,EAAE,EAAE,EAChB,gBAAgB,EAAE,IAAI,EACtB,sBAAsB,EAAE,EAAE,EAC1B,oBAAoB,EAAE,QAAQ,CAAC,MAAM,EACrC,cAAc,EAAE,SAAS,EACzB,cAAc,EAAE,SAAS,EACzB,YAAY,EAAE,KAAK,EACnB,QAAQ,EAAE,CAAC,CAAiB,KAAc,CAAsB,CAAC,IAAI,EACrE,aAAa,EAAE,SAAS,EACxB,UAAU,EAAE,CAAC,CAAiB,KAAc,CAAwB,CAAC,MAAM,EAC3E,iBAAiB,EAAE,SAAS,EAC5B,cAAc,EAAE,IAAI,EACpB,gBAAgB,EAAE,SAAS,EAC3B,aAAa,EAAE,IAAI,EACnB,QAAQ,EAAE,SAAS,EACnB,0BAA0B,EAAE,+BAA+B,CAAC,mBAAmB,EAC/E,qBAAqB,EAAE,IAAI,EAE3B,cAAc,EAAE,SAAS,EACzB,eAAe,EAAE,SAAS,EAE1B,MAAM,EAAE,SAAS,EAEjB,eAAe,EAAE,SAAS,EAC1B,UAAU,EAAE,SAAS,EACrB,aAAa,EAAE,SAAS,EACxB,MAAM,EAAE,SAAS,EACjB,WAAW,EAAE,SAAS,EACtB,SAAS,EAAE,SAAS,EACpB,kBAAkB,EAAE,SAAS,EAC7B,oBAAoB,EAAE,SAAS,EAC/B,mBAAmB,EAAE,SAAS,EAC9B,gBAAgB,EAAE,SAAS,EAE3B,gBAAgB,EAAE,CAAC,QAAwD,EAAE,QAAwD,KAAa;AAChJ,QAAA,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;AACrC,KAAC;;;;"}
|
|
@@ -23,7 +23,7 @@ function toElkHierarchy(d, layoutOptions) {
|
|
|
23
23
|
const hierarchyNode = Array.from(d.entries()).map(([key, value]) => {
|
|
24
24
|
const children = toElkHierarchy(value, layoutOptions);
|
|
25
25
|
if (key) {
|
|
26
|
-
const layoutOps = isPlainObject(layoutOptions) ? DEFAULT_ELK_SETTINGS : merge(DEFAULT_ELK_SETTINGS, getValue(key, layoutOptions));
|
|
26
|
+
const layoutOps = isPlainObject(layoutOptions) ? merge(DEFAULT_ELK_SETTINGS, layoutOptions) : merge(DEFAULT_ELK_SETTINGS, getValue(key, layoutOptions));
|
|
27
27
|
return {
|
|
28
28
|
id: key,
|
|
29
29
|
layoutOptions: layoutOps,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-helpers.js","sources":["../../../../src/components/graph/modules/layout-helpers.ts"],"sourcesContent":["// Types\nimport type { ElkNode } from 'elkjs/lib/elk.bundled.js'\nimport { GraphInputLink, GraphInputNode } from 'types/graph'\nimport { GenericAccessor } from 'types/accessor'\n\n// Utils\nimport { getValue, isPlainObject, merge } from 'utils/data'\n\n// Local Types\nimport { GraphNode, GraphElkLayoutSettings } from '../types'\n\nexport const DEFAULT_ELK_SETTINGS = {\n hierarchyHandling: 'INCLUDE_CHILDREN',\n 'nodePlacement.strategy': 'NETWORK_SIMPLEX',\n 'elk.padding': '[top=15.0,left=15.0,bottom=15.0,right=15.0]',\n 'spacing.nodeNodeBetweenLayers': '50',\n 'spacing.edgeNodeBetweenLayers': '50',\n 'spacing.nodeNode': '10',\n}\n\nexport function positionNonConnectedNodes<N extends GraphInputNode, L extends GraphInputLink> (\n nodes: GraphNode<N, L>[],\n y: number,\n spacing: number,\n width: number,\n xStart = 0\n): void {\n nodes.forEach((d, i) => {\n const x = spacing / 2 + i * spacing\n const rowIdx = width ? Math.floor(x / width) : 0\n d.y = (y + rowIdx * spacing) || 0\n d.x = width ? x % width + xStart : x + xStart\n })\n}\n\nexport type GraphElkHierarchyNode<N extends GraphInputNode, L extends GraphInputLink> = {\n id: string;\n children: GraphNode<N, L>[] | GraphElkHierarchyNode<N, L>;\n layoutOptions: GraphElkLayoutSettings;\n}\n\nexport type GraphElkHierarchyNodeMap<N extends GraphInputNode, L extends GraphInputLink>\n = Map<string | undefined | null, GraphNode<N, L>[] | GraphElkHierarchyNodeMap<N, L>>\n\n\nexport function toElkHierarchy<N extends GraphInputNode, L extends GraphInputLink> (\n d: GraphElkHierarchyNodeMap<N, L> | GraphNode<N, L>[],\n layoutOptions: GenericAccessor<GraphElkLayoutSettings, string> | undefined\n): (GraphElkHierarchyNode<N, L> | GraphNode<N, L>)[] {\n if (!(d instanceof Map)) return d\n\n const hierarchyNode = Array.from(d.entries()).map(([key, value]) => {\n const children = toElkHierarchy(value, layoutOptions)\n if (key) {\n const layoutOps = isPlainObject(layoutOptions) ? DEFAULT_ELK_SETTINGS : merge(DEFAULT_ELK_SETTINGS, getValue(key, layoutOptions))\n return {\n id: key,\n layoutOptions: layoutOps,\n children,\n } as GraphElkHierarchyNode<N, L>\n } else {\n return children\n }\n }).flat()\n\n return hierarchyNode\n}\n\nexport function adjustElkHierarchyCoordinates (node: ElkNode): void {\n const parentX = node.x\n const parentY = node.y\n\n node.edges?.forEach(edge => {\n edge.sections?.forEach(section => {\n section.startPoint.x += parentX\n section.startPoint.y += parentY\n section.endPoint.x += parentX\n section.endPoint.y += parentY\n section.bendPoints?.forEach(bendPoint => {\n bendPoint.x += parentX\n bendPoint.y += parentY\n })\n })\n\n edge.labels?.forEach(label => {\n label.x += parentX\n label.y += parentY\n })\n })\n\n node.children?.forEach(child => {\n child.x += parentX\n child.y += parentY\n adjustElkHierarchyCoordinates(child)\n })\n}\n"],"names":[],"mappings":";;AAKA;AAMa,MAAA,oBAAoB,GAAG;AAClC,IAAA,iBAAiB,EAAE,kBAAkB;AACrC,IAAA,wBAAwB,EAAE,iBAAiB;AAC3C,IAAA,aAAa,EAAE,6CAA6C;AAC5D,IAAA,+BAA+B,EAAE,IAAI;AACrC,IAAA,+BAA+B,EAAE,IAAI;AACrC,IAAA,kBAAkB,EAAE,IAAI;EACzB;AAEe,SAAA,yBAAyB,CACvC,KAAwB,EACxB,CAAS,EACT,OAAe,EACf,KAAa,EACb,MAAM,GAAG,CAAC,EAAA;IAEV,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAI;QACrB,MAAM,CAAC,GAAG,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAA;AACnC,QAAA,MAAM,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;AAChD,QAAA,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,GAAG,OAAO,KAAK,CAAC,CAAA;AACjC,QAAA,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,MAAM,GAAG,CAAC,GAAG,MAAM,CAAA;AAC/C,KAAC,CAAC,CAAA;AACJ,CAAC;AAYe,SAAA,cAAc,CAC5B,CAAqD,EACrD,aAA0E,EAAA;AAE1E,IAAA,IAAI,EAAE,CAAC,YAAY,GAAG,CAAC;AAAE,QAAA,OAAO,CAAC,CAAA;IAEjC,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,KAAI;QACjE,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,EAAE,aAAa,CAAC,CAAA;AACrD,QAAA,IAAI,GAAG,EAAE;
|
|
1
|
+
{"version":3,"file":"layout-helpers.js","sources":["../../../../src/components/graph/modules/layout-helpers.ts"],"sourcesContent":["// Types\nimport type { ElkNode } from 'elkjs/lib/elk.bundled.js'\nimport { GraphInputLink, GraphInputNode } from 'types/graph'\nimport { GenericAccessor } from 'types/accessor'\n\n// Utils\nimport { getValue, isPlainObject, merge } from 'utils/data'\n\n// Local Types\nimport { GraphNode, GraphElkLayoutSettings } from '../types'\n\nexport const DEFAULT_ELK_SETTINGS = {\n hierarchyHandling: 'INCLUDE_CHILDREN',\n 'nodePlacement.strategy': 'NETWORK_SIMPLEX',\n 'elk.padding': '[top=15.0,left=15.0,bottom=15.0,right=15.0]',\n 'spacing.nodeNodeBetweenLayers': '50',\n 'spacing.edgeNodeBetweenLayers': '50',\n 'spacing.nodeNode': '10',\n}\n\nexport function positionNonConnectedNodes<N extends GraphInputNode, L extends GraphInputLink> (\n nodes: GraphNode<N, L>[],\n y: number,\n spacing: number,\n width: number,\n xStart = 0\n): void {\n nodes.forEach((d, i) => {\n const x = spacing / 2 + i * spacing\n const rowIdx = width ? Math.floor(x / width) : 0\n d.y = (y + rowIdx * spacing) || 0\n d.x = width ? x % width + xStart : x + xStart\n })\n}\n\nexport type GraphElkHierarchyNode<N extends GraphInputNode, L extends GraphInputLink> = {\n id: string;\n children: GraphNode<N, L>[] | GraphElkHierarchyNode<N, L>;\n layoutOptions: GraphElkLayoutSettings;\n}\n\nexport type GraphElkHierarchyNodeMap<N extends GraphInputNode, L extends GraphInputLink>\n = Map<string | undefined | null, GraphNode<N, L>[] | GraphElkHierarchyNodeMap<N, L>>\n\n\nexport function toElkHierarchy<N extends GraphInputNode, L extends GraphInputLink> (\n d: GraphElkHierarchyNodeMap<N, L> | GraphNode<N, L>[],\n layoutOptions: GenericAccessor<GraphElkLayoutSettings, string> | undefined\n): (GraphElkHierarchyNode<N, L> | GraphNode<N, L>)[] {\n if (!(d instanceof Map)) return d\n\n const hierarchyNode = Array.from(d.entries()).map(([key, value]) => {\n const children = toElkHierarchy(value, layoutOptions)\n if (key) {\n const layoutOps = isPlainObject(layoutOptions) ? merge(DEFAULT_ELK_SETTINGS, layoutOptions) : merge(DEFAULT_ELK_SETTINGS, getValue(key, layoutOptions))\n return {\n id: key,\n layoutOptions: layoutOps,\n children,\n } as GraphElkHierarchyNode<N, L>\n } else {\n return children\n }\n }).flat()\n\n return hierarchyNode\n}\n\nexport function adjustElkHierarchyCoordinates (node: ElkNode): void {\n const parentX = node.x\n const parentY = node.y\n\n node.edges?.forEach(edge => {\n edge.sections?.forEach(section => {\n section.startPoint.x += parentX\n section.startPoint.y += parentY\n section.endPoint.x += parentX\n section.endPoint.y += parentY\n section.bendPoints?.forEach(bendPoint => {\n bendPoint.x += parentX\n bendPoint.y += parentY\n })\n })\n\n edge.labels?.forEach(label => {\n label.x += parentX\n label.y += parentY\n })\n })\n\n node.children?.forEach(child => {\n child.x += parentX\n child.y += parentY\n adjustElkHierarchyCoordinates(child)\n })\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -380,7 +380,7 @@ function applyELKLayout(datamodel, config, width) {
|
|
|
380
380
|
const ELK = (yield import('elkjs/lib/elk.bundled.js')).default;
|
|
381
381
|
const elk = new ELK();
|
|
382
382
|
const labelApprxHeight = 30;
|
|
383
|
-
const nodes = datamodel.nodes.map(n => (Object.assign(Object.assign({}, n), { id: n._id, width: getNumber(n, config.nodeSize, n._index) + getNumber(n, config.nodeStrokeWidth, n._index), height: getNumber(n, config.nodeSize, n._index) + labelApprxHeight })));
|
|
383
|
+
const nodes = datamodel.nodes.map((n, i) => (Object.assign(Object.assign(Object.assign({}, n), { id: n._id, width: getNumber(n, config.nodeSize, n._index) + getNumber(n, config.nodeStrokeWidth, n._index), height: getNumber(n, config.nodeSize, n._index) + labelApprxHeight }), (config.layoutElkGetNodeShape ? config.layoutElkGetNodeShape(n, i) : {}))));
|
|
384
384
|
let elkNodes;
|
|
385
385
|
if (config.layoutElkNodeGroups) {
|
|
386
386
|
const groupingFunctions = config.layoutElkNodeGroups
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.js","sources":["../../../../src/components/graph/modules/layout.ts"],"sourcesContent":["import { min, max, group } from 'd3-array'\nimport type { SimulationNodeDatum } from 'd3-force'\nimport type { ElkNode } from 'elkjs/lib/elk.bundled.js'\nimport type { graphlib, Node } from 'dagre'\n\n// Core\nimport { GraphDataModel } from 'data-models/graph'\n\n// Utils\nimport { without, clamp, groupBy, unique, sortBy, getString, getNumber, getValue, merge, isFunction, isNil } from 'utils/data'\n\n// Types\nimport { GraphInputLink, GraphInputNode } from 'types/graph'\n\n// Local Types\nimport { GraphNode, GraphLink, GraphForceSimulationNode } from '../types'\n\n// Config\nimport { GraphConfigInterface } from '../config'\n\n// Helpers\nimport { getMaxNodeSize, configuredNodeSize, getNodeSize, getAverageNodeSize } from './node/helper'\nimport {\n DEFAULT_ELK_SETTINGS,\n adjustElkHierarchyCoordinates,\n positionNonConnectedNodes,\n toElkHierarchy,\n GraphElkHierarchyNode,\n} from './layout-helpers'\n\nexport function applyLayoutCircular<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number,\n height: number\n): void {\n const { nonConnectedNodes, connectedNodes, nodes } = datamodel\n const { layoutNonConnectedAside, nodeSize } = config\n\n const activeWidth = width\n const activeHeight = height\n\n // Handle layout nodes\n const layoutNodes = layoutNonConnectedAside ? connectedNodes : nodes\n const maxNodeSize = getMaxNodeSize(layoutNodes, nodeSize)\n const yRatio = activeHeight / maxNodeSize\n const yScaling = yRatio < layoutNodes.length / 2 ? layoutNodes.length / 2 / yRatio : 1\n const xRatio = activeWidth / maxNodeSize\n const xScaling = xRatio < layoutNodes.length / 2 ? layoutNodes.length / 2 / xRatio : 1\n const scaling = Math.max(xScaling, yScaling)\n\n layoutNodes.forEach((d, i) => {\n const rX = scaling * activeWidth / 2\n const rY = scaling * activeHeight / 2 // maxNodeSize * layoutNodes.length / 4\n const angle = 2 * i * Math.PI / layoutNodes.length\n d.x = activeWidth / 2 + rX * Math.cos(angle)\n d.y = activeHeight / 2 + rY * Math.sin(angle)\n })\n\n // Handle non-connected nodes\n if (layoutNonConnectedAside) {\n const maxSize = getMaxNodeSize(nonConnectedNodes, nodeSize)\n const maxY = max<number>(connectedNodes.map(d => d.y))\n const maxX = max<number>(connectedNodes.map(d => d.x))\n const minX = min<number>(connectedNodes.map(d => d.x))\n const graphWidth = maxX - minX\n positionNonConnectedNodes(nonConnectedNodes, maxY + maxSize * 3, maxSize * 2.25, Math.max(graphWidth, width), minX)\n }\n}\n\nexport function applyLayoutParallel<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number,\n height: number,\n orientation?: string\n): void {\n const { nonConnectedNodes, connectedNodes, nodes } = datamodel\n const {\n layoutNonConnectedAside, layoutGroupOrder, layoutParallelSortConnectionsByGroup, layoutParallelNodesPerColumn,\n layoutParallelSubGroupsPerRow, nodeSize, layoutNodeGroup, layoutParallelNodeSubGroup, layoutParallelGroupSpacing,\n } = config\n\n const activeWidth = width - configuredNodeSize(nodeSize)\n const activeHeight = height - configuredNodeSize(nodeSize) - (nonConnectedNodes.length ? configuredNodeSize(nodeSize) * 5 : 0)\n\n // Handle connected nodes\n const layoutNodes = layoutNonConnectedAside ? connectedNodes : nodes\n const groupNames = unique(layoutNodes.map(d => getString(d, layoutNodeGroup, d._index)))\n const groupNamesSorted: string[] = sortBy(groupNames, d => layoutGroupOrder.indexOf(d))\n\n const groups = groupNamesSorted.map(groupName => {\n const groupNodes = layoutNodes.filter(d => getString(d, layoutNodeGroup, d._index) === groupName)\n const groupedBySubgroup = groupBy(groupNodes, d => getString(d, layoutParallelNodeSubGroup, d._index))\n const subgroups = Object.keys(groupedBySubgroup).map(name => ({\n nodes: groupedBySubgroup[name],\n name,\n }))\n\n return {\n name: groupName,\n nodes: groupNodes,\n subgroups,\n }\n })\n\n // Sort\n const group = groups.find(g => g.name === layoutParallelSortConnectionsByGroup)\n if (group) {\n const sortMap: Record<string, number> = {}\n let idx = 0\n group.subgroups.forEach(subgroup => {\n subgroup.nodes.forEach(node => {\n node.links.forEach(link => {\n const linkTargetId = link?.target._id\n sortMap[linkTargetId] = idx\n idx = idx + 1\n })\n })\n })\n\n without(groups, group).forEach(g => {\n g.subgroups.forEach(subgroup => {\n subgroup.nodes.sort((a, b) => {\n return (sortMap[a._id] || 0) - (sortMap[b._id] || 0)\n })\n })\n })\n }\n\n const maxN = max(groups, d => d.nodes?.length)\n const labelApprxHeight = 40\n const labelMargin = 10\n const subgroupMargin = 40\n const maxNodeSize = getMaxNodeSize(layoutNodes, nodeSize)\n\n if (orientation === 'horizontal') {\n const minHorizontalStep = 2 * maxNodeSize + labelMargin\n const maxHorizontalStep = 3.5 * maxNodeSize + labelMargin\n const horizontalStep = clamp(activeWidth / (maxN - 1), minHorizontalStep, maxHorizontalStep)\n\n const maxVerticalStep = maxNodeSize * 4 + labelApprxHeight\n const minVerticalStep = maxNodeSize * 1.5 + labelApprxHeight\n const verticalStep = (maxNodeSize + layoutParallelGroupSpacing) || clamp(activeHeight / (groups.length - 1), minVerticalStep, maxVerticalStep)\n const subgroupNodeStep = maxNodeSize + labelApprxHeight + labelMargin\n\n let y0 = (groups.length < 2) ? height / 2 : 0\n groups.forEach(group => {\n let x0 = 0\n let dy = 0\n let subgroupMaxWidth = 0\n let groupWidth = 0\n let groupHeight = 0\n let k = 0\n group.subgroups.forEach(subgroup => {\n const subgroupRows = Math.ceil(subgroup.nodes.length / layoutParallelNodesPerColumn)\n let n = 0\n let x = x0\n let y = y0 + dy\n subgroup.nodes.forEach(d => {\n x = x + horizontalStep\n d.x = x\n d.y = y\n groupWidth = Math.max(groupWidth, x)\n\n n = n + 1\n if (n >= layoutParallelNodesPerColumn) {\n n = 0\n y += subgroupNodeStep\n x = x0\n }\n })\n\n const subgroupWidth = Math.min(subgroup.nodes.length, layoutParallelNodesPerColumn) * horizontalStep\n const subgroupHeight = subgroupRows * subgroupNodeStep\n subgroupMaxWidth = Math.max(subgroupMaxWidth, subgroupWidth)\n dy = dy + subgroupHeight + subgroupMargin\n k = k + 1\n if (k >= layoutParallelSubGroupsPerRow) {\n k = 0\n dy = 0\n x0 = x0 + subgroupMaxWidth + subgroupMargin\n subgroupMaxWidth = 0\n }\n\n groupHeight = Math.max(groupHeight, y)\n // x0 += Math.min(subgroup.nodes.length, layoutParallelNodesPerColumn) * horizontalStep + subgroupMargin\n })\n\n // Center group horizontally\n group.subgroups.forEach(subgroup => {\n subgroup.nodes.forEach(d => {\n d.x -= groupWidth / 2\n })\n })\n groupWidth = 0\n\n // Update y0 for the next group\n y0 = groupHeight + verticalStep\n })\n } else {\n const minHorizontalStep = 6 * maxNodeSize + labelMargin\n const maxHorizontalStep = 10 * maxNodeSize + labelMargin\n const horizontalStep = (maxNodeSize + layoutParallelGroupSpacing) || clamp(activeWidth / (maxN - 1), minHorizontalStep, maxHorizontalStep)\n\n const maxVerticalStep = maxNodeSize * 2.0 + labelApprxHeight\n const minVerticalStep = maxNodeSize * 1.5 + labelApprxHeight\n const verticalStep = clamp(activeHeight / (groups.length - 1), minVerticalStep, maxVerticalStep)\n const subgroupNodeStep = maxNodeSize * 2.0\n\n let x0 = (groups.length < 2) ? width / 2 : 0\n groups.forEach(group => {\n let y0 = 0\n let dx = 0 // Horizontal shift inside the group (column)\n let subgroupMaxHeight = 0\n let groupWidth = 0\n let groupHeight = 0\n\n let k = 0\n group.subgroups.forEach(subgroup => {\n const subgroupColumns = Math.ceil(subgroup.nodes.length / layoutParallelNodesPerColumn)\n let n = 0\n let y = y0\n let x = x0 + dx\n subgroup.nodes.forEach(d => {\n y = y + verticalStep\n d.x = x\n d.y = y\n groupHeight = Math.max(groupHeight, y)\n\n n = n + 1\n if (n >= layoutParallelNodesPerColumn) {\n n = 0\n x += subgroupNodeStep\n y = y0\n }\n })\n\n const subgroupHeight = Math.min(subgroup.nodes.length, layoutParallelNodesPerColumn) * verticalStep\n const subgroupWidth = subgroupColumns * subgroupNodeStep\n subgroupMaxHeight = Math.max(subgroupMaxHeight, subgroupHeight)\n dx = dx + subgroupWidth + subgroupMargin\n k = k + 1\n if (k >= layoutParallelSubGroupsPerRow) {\n k = 0\n dx = 0\n y0 = y0 + subgroupMaxHeight + subgroupMargin\n subgroupMaxHeight = 0\n }\n\n groupWidth = Math.max(groupWidth, x)\n })\n\n // Center group vertically\n group.subgroups.forEach(subgroup => {\n subgroup.nodes.forEach(d => {\n d.y -= groupHeight / 2\n })\n })\n groupHeight = 0\n\n // Update x0 for the next group\n x0 = groupWidth + horizontalStep\n })\n }\n\n // Handle non-connected nodes\n if (layoutNonConnectedAside) {\n const maxSize = getMaxNodeSize(nonConnectedNodes, nodeSize)\n const maxY = max<number>(connectedNodes.map(d => d.y)) || 0\n const maxX = max<number>(connectedNodes.map(d => d.x)) || 0\n const minX = min<number>(connectedNodes.map(d => d.x)) || 0\n const graphWidth = (maxX - minX) || width\n positionNonConnectedNodes(nonConnectedNodes, maxY + maxSize * 3, maxSize * 2.25, Math.max(graphWidth, width))\n }\n}\n\nexport async function applyLayoutDagre<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number\n): Promise<void> {\n const { nonConnectedNodes, connectedNodes, nodes, links } = datamodel\n const { nodeSize, layoutNonConnectedAside, dagreLayoutSettings, nodeStrokeWidth, nodeLabel } = config\n\n // eslint-disable-next-line @typescript-eslint/naming-convention,@typescript-eslint/ban-ts-comment\n // @ts-ignore\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const { Graph } = await import('@unovis/graphlibrary')\n // eslint-disable-next-line @typescript-eslint/naming-convention,@typescript-eslint/ban-ts-comment\n // @ts-ignore\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const { layout } = await import('@unovis/dagre-layout')\n\n // https://github.com/dagrejs/dagre/wiki\n const dagreGraph = new Graph() as graphlib.Graph<GraphNode<N, L>>\n\n // Set an object for the graph label\n dagreGraph.setGraph(dagreLayoutSettings)\n\n // Default to assigning a new object as a label for each new edge.\n dagreGraph.setDefaultEdgeLabel(() => ({}))\n\n // Add nodes to the graph. The first argument is the node id. The second is\n // metadata about the node. In this case we're going to add labels to each of\n // our nodes.\n const labelApprxHeight = 40\n const nds = (layoutNonConnectedAside ? connectedNodes : nodes)\n nds.forEach(node => {\n dagreGraph.setNode(`${node._index}`, {\n label: getString(node, nodeLabel, node._index),\n width: getNumber(node, nodeSize, node._index) * 1.5 + getNumber(node, nodeStrokeWidth, node._index),\n height: labelApprxHeight + getNumber(node, nodeSize, node._index) * 1.5,\n originalNode: node,\n })\n })\n\n // Add edges to the graph.\n links.forEach(link => {\n dagreGraph.setEdge(\n `${link.source._index}`,\n `${link.target._index}`\n )\n })\n\n // Calculate the layout\n layout(dagreGraph)\n\n // Apply coordinates to the graph\n dagreGraph.nodes().forEach(d => {\n const node = dagreGraph.node(d) as Node<GraphNode<N, L>> & { originalNode: GraphNode<N, L>}\n node.originalNode.x = node.x // width * d.x / dagreGraph._label.width\n node.originalNode.y = node.y // height * d.y / dagreGraph._label.height\n })\n\n // Handle non-connected nodes\n if (layoutNonConnectedAside) {\n const maxNodeSize = getMaxNodeSize(nonConnectedNodes, nodeSize)\n const maxY = max<number>(connectedNodes.map(d => d.y))\n const maxX = max<number>(connectedNodes.map(d => d.x))\n const minX = min<number>(connectedNodes.map(d => d.x))\n const graphWidth = maxX - minX\n positionNonConnectedNodes(nonConnectedNodes, maxY + maxNodeSize * 3, maxNodeSize * 2.25, Math.max(graphWidth, width), 0)\n }\n}\n\nexport function applyLayoutConcentric<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number,\n height: number\n): void {\n const { nonConnectedNodes, connectedNodes, nodes } = datamodel\n const { layoutNonConnectedAside, layoutGroupOrder, nodeSize, layoutNodeGroup } = config\n\n const layoutNodes = layoutNonConnectedAside ? connectedNodes : nodes\n\n const groupNames: string[] = unique(layoutNodes.map(d => getString(d, layoutNodeGroup, d._index)))\n const groupNamesSorted: string[] = sortBy(groupNames, d => layoutGroupOrder.indexOf(d))\n\n const groups = groupNamesSorted.map(groupName => ({\n name: groupName,\n nodes: layoutNodes.filter(d => getString(d, layoutNodeGroup, d._index) === groupName),\n }))\n\n // Handle connected nodes\n let r = 2 * getAverageNodeSize(groups[0]?.nodes ?? [], nodeSize)\n const widthToHeightRatio = width / height\n\n groups.forEach((group, i) => {\n const avgNodeSize = getAverageNodeSize(group.nodes, nodeSize)\n const requiredRadius = 1.1 * avgNodeSize * group.nodes.length / Math.PI\n if (r < requiredRadius) r = requiredRadius\n\n group.nodes.forEach((node, j) => {\n // If the first (central) group has only one node\n if (i === 0 && group.nodes.length === 1) {\n node.x = width / 2\n node.y = height / 2\n } else {\n let dAngle = 0\n if (i === 0 && group.nodes.length === 3) dAngle = Math.PI / 6\n if (i === 0 && group.nodes.length === 4) dAngle = Math.PI / 4\n const angle = 2 * j * Math.PI / group.nodes.length + i * Math.PI / 12 + dAngle\n node.x = width / 2 + r * Math.cos(angle) * widthToHeightRatio\n node.y = height / 2 + r * Math.sin(angle)\n }\n })\n\n const groupSpacing = avgNodeSize * 3\n r += groupSpacing\n })\n\n // Handle non-connected nodes\n if (layoutNonConnectedAside) {\n const maxSize = getMaxNodeSize(nonConnectedNodes, nodeSize)\n const maxY = max<number>(connectedNodes.map(d => d.y))\n const maxX = max<number>(connectedNodes.map(d => d.x))\n const minX = min<number>(connectedNodes.map(d => d.x))\n const graphWidth = maxX - minX\n positionNonConnectedNodes(nonConnectedNodes, maxY + maxSize * 3, maxSize * 2.25, graphWidth, minX)\n }\n}\n\nexport async function applyLayoutForce<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number\n): Promise<void> {\n const { layoutNonConnectedAside, forceLayoutSettings, nodeSize } = config\n\n const { forceSimulation, forceLink, forceManyBody, forceX, forceY, forceCollide } = await import('d3-force')\n\n const { nonConnectedNodes, connectedNodes, nodes, links } = datamodel\n\n\n // Apply fx and fy to nodes if present before running the simulation\n if (forceLayoutSettings.fixNodePositionAfterSimulation) {\n nodes.forEach((d: GraphForceSimulationNode<N, L>) => {\n d.fx = isNil(d._state.fx) ? undefined : d._state.fx\n d.fy = isNil(d._state.fy) ? undefined : d._state.fy\n })\n } else {\n nodes.forEach((d: GraphForceSimulationNode<N, L>) => {\n delete d._state.fx\n delete d._state.fy\n })\n }\n\n const simulation = forceSimulation(layoutNonConnectedAside ? connectedNodes : nodes)\n .force('link', forceLink(links)\n .id((d) => String((d as GraphNode<N, L>)._id))\n .distance((l, i) => isFunction(forceLayoutSettings.linkDistance) ? forceLayoutSettings.linkDistance(l, i) : forceLayoutSettings.linkDistance)\n .strength((l, i) => isFunction(forceLayoutSettings.linkStrength) ? forceLayoutSettings.linkStrength(l, i) : forceLayoutSettings.linkStrength)\n )\n .force('charge', forceManyBody().strength((d, i) => {\n if (isFunction(forceLayoutSettings.charge)) {\n return forceLayoutSettings.charge(d as GraphNode<N, L>, i)\n } else {\n const linkCount = links.reduce((count, l) => count + Number((l.source === d) || (l.target === d)), 0)\n return forceLayoutSettings.charge * Math.sqrt(linkCount)\n }\n }))\n .force('x', forceX().strength(forceLayoutSettings.forceXStrength))\n .force('y', forceY().strength(forceLayoutSettings.forceYStrength))\n .force('collide', forceCollide<SimulationNodeDatum & N>().radius((d, i) => getNodeSize(d, nodeSize, i)).iterations(1))\n .stop()\n\n // See https://bl.ocks.org/mbostock/1667139, https://github.com/d3/d3-force/blob/master/README.md#simulation_tick\n const numIterations = forceLayoutSettings.numIterations ?? Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay()))\n for (let i = 0, n = numIterations; i < n; ++i) {\n simulation.tick()\n }\n\n // Fix node positions to `_state` if requested.\n // And remove fx and fy from the node datum if present to make sure the nodes are not fixed\n // if the layout was changed to a different layout and then back to force\n if (forceLayoutSettings.fixNodePositionAfterSimulation) {\n nodes.forEach((d: GraphForceSimulationNode<N, L>) => {\n delete d.fx\n delete d.fy\n d._state.fx = d.x\n d._state.fy = d.y\n })\n }\n\n // Handle non-connected nodes\n if (layoutNonConnectedAside) {\n const maxSize = getMaxNodeSize(nonConnectedNodes, nodeSize)\n const maxY = max<number>(connectedNodes.map(d => d.y))\n const maxX = max<number>(connectedNodes.map(d => d.x))\n const minX = min<number>(connectedNodes.map(d => d.x))\n const graphWidth = maxX - minX\n positionNonConnectedNodes(nonConnectedNodes, maxY + maxSize * 6, maxSize * 2.25, Math.max(graphWidth, width), minX)\n }\n}\n\nexport async function applyELKLayout<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number\n): Promise<void> {\n const ELK = (await import('elkjs/lib/elk.bundled.js')).default\n const elk = new ELK()\n\n const labelApprxHeight = 30\n const nodes = datamodel.nodes.map(n => ({\n ...n,\n id: n._id,\n width: getNumber(n, config.nodeSize, n._index) + getNumber(n, config.nodeStrokeWidth, n._index),\n height: getNumber(n, config.nodeSize, n._index) + labelApprxHeight,\n }))\n\n let elkNodes: (GraphNode<N, L> | GraphElkHierarchyNode<N, L>)[]\n if (config.layoutElkNodeGroups) {\n const groupingFunctions = config.layoutElkNodeGroups\n .map(accessor => (d: GraphNode<N, L>) => getString(d, accessor, d._index)) as [(d: GraphNode<N, L>) => string]\n const grouped = group(nodes, ...groupingFunctions)\n elkNodes = toElkHierarchy(grouped, config.layoutElkSettings)\n } else {\n elkNodes = nodes\n }\n\n const rootNodeId = 'root'\n const elkGraph: ElkNode = {\n id: rootNodeId,\n layoutOptions: merge(DEFAULT_ELK_SETTINGS, getValue(rootNodeId, config.layoutElkSettings)),\n children: elkNodes as ElkNode[],\n edges: datamodel.links.map(l => ({\n id: l._id,\n sources: [l.source._id],\n targets: [l.target._id],\n })),\n }\n\n const layout = await elk.layout(elkGraph)\n adjustElkHierarchyCoordinates(layout)\n\n nodes.forEach((node, i) => {\n const found = datamodel.nodes.find(n => n._id === node.id)\n if (!found) return\n\n found.x = node.x\n found.y = node.y\n })\n\n // Handle non-connected nodes\n if (config.layoutNonConnectedAside) {\n const maxSize = getMaxNodeSize(datamodel.nonConnectedNodes, config.nodeSize)\n const maxY = max<number>(datamodel.connectedNodes.map(d => d.y)) || 0\n const maxX = max<number>(datamodel.connectedNodes.map(d => d.x)) || 0\n const minX = min<number>(datamodel.connectedNodes.map(d => d.x)) || 0\n const graphWidth = (maxX - minX) || width\n positionNonConnectedNodes(datamodel.nonConnectedNodes, maxY + maxSize * 3, maxSize * 2.25, Math.max(graphWidth, width))\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"layout.js","sources":["../../../../src/components/graph/modules/layout.ts"],"sourcesContent":["import { min, max, group } from 'd3-array'\nimport type { SimulationNodeDatum } from 'd3-force'\nimport type { ElkNode } from 'elkjs/lib/elk.bundled.js'\nimport type { graphlib, Node } from 'dagre'\n\n// Core\nimport { GraphDataModel } from 'data-models/graph'\n\n// Utils\nimport { without, clamp, groupBy, unique, sortBy, getString, getNumber, getValue, merge, isFunction, isNil } from 'utils/data'\n\n// Types\nimport { GraphInputLink, GraphInputNode } from 'types/graph'\n\n// Local Types\nimport { GraphNode, GraphLink, GraphForceSimulationNode } from '../types'\n\n// Config\nimport { GraphConfigInterface } from '../config'\n\n// Helpers\nimport { getMaxNodeSize, configuredNodeSize, getNodeSize, getAverageNodeSize } from './node/helper'\nimport {\n DEFAULT_ELK_SETTINGS,\n adjustElkHierarchyCoordinates,\n positionNonConnectedNodes,\n toElkHierarchy,\n GraphElkHierarchyNode,\n} from './layout-helpers'\n\nexport function applyLayoutCircular<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number,\n height: number\n): void {\n const { nonConnectedNodes, connectedNodes, nodes } = datamodel\n const { layoutNonConnectedAside, nodeSize } = config\n\n const activeWidth = width\n const activeHeight = height\n\n // Handle layout nodes\n const layoutNodes = layoutNonConnectedAside ? connectedNodes : nodes\n const maxNodeSize = getMaxNodeSize(layoutNodes, nodeSize)\n const yRatio = activeHeight / maxNodeSize\n const yScaling = yRatio < layoutNodes.length / 2 ? layoutNodes.length / 2 / yRatio : 1\n const xRatio = activeWidth / maxNodeSize\n const xScaling = xRatio < layoutNodes.length / 2 ? layoutNodes.length / 2 / xRatio : 1\n const scaling = Math.max(xScaling, yScaling)\n\n layoutNodes.forEach((d, i) => {\n const rX = scaling * activeWidth / 2\n const rY = scaling * activeHeight / 2 // maxNodeSize * layoutNodes.length / 4\n const angle = 2 * i * Math.PI / layoutNodes.length\n d.x = activeWidth / 2 + rX * Math.cos(angle)\n d.y = activeHeight / 2 + rY * Math.sin(angle)\n })\n\n // Handle non-connected nodes\n if (layoutNonConnectedAside) {\n const maxSize = getMaxNodeSize(nonConnectedNodes, nodeSize)\n const maxY = max<number>(connectedNodes.map(d => d.y))\n const maxX = max<number>(connectedNodes.map(d => d.x))\n const minX = min<number>(connectedNodes.map(d => d.x))\n const graphWidth = maxX - minX\n positionNonConnectedNodes(nonConnectedNodes, maxY + maxSize * 3, maxSize * 2.25, Math.max(graphWidth, width), minX)\n }\n}\n\nexport function applyLayoutParallel<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number,\n height: number,\n orientation?: string\n): void {\n const { nonConnectedNodes, connectedNodes, nodes } = datamodel\n const {\n layoutNonConnectedAside, layoutGroupOrder, layoutParallelSortConnectionsByGroup, layoutParallelNodesPerColumn,\n layoutParallelSubGroupsPerRow, nodeSize, layoutNodeGroup, layoutParallelNodeSubGroup, layoutParallelGroupSpacing,\n } = config\n\n const activeWidth = width - configuredNodeSize(nodeSize)\n const activeHeight = height - configuredNodeSize(nodeSize) - (nonConnectedNodes.length ? configuredNodeSize(nodeSize) * 5 : 0)\n\n // Handle connected nodes\n const layoutNodes = layoutNonConnectedAside ? connectedNodes : nodes\n const groupNames = unique(layoutNodes.map(d => getString(d, layoutNodeGroup, d._index)))\n const groupNamesSorted: string[] = sortBy(groupNames, d => layoutGroupOrder.indexOf(d))\n\n const groups = groupNamesSorted.map(groupName => {\n const groupNodes = layoutNodes.filter(d => getString(d, layoutNodeGroup, d._index) === groupName)\n const groupedBySubgroup = groupBy(groupNodes, d => getString(d, layoutParallelNodeSubGroup, d._index))\n const subgroups = Object.keys(groupedBySubgroup).map(name => ({\n nodes: groupedBySubgroup[name],\n name,\n }))\n\n return {\n name: groupName,\n nodes: groupNodes,\n subgroups,\n }\n })\n\n // Sort\n const group = groups.find(g => g.name === layoutParallelSortConnectionsByGroup)\n if (group) {\n const sortMap: Record<string, number> = {}\n let idx = 0\n group.subgroups.forEach(subgroup => {\n subgroup.nodes.forEach(node => {\n node.links.forEach(link => {\n const linkTargetId = link?.target._id\n sortMap[linkTargetId] = idx\n idx = idx + 1\n })\n })\n })\n\n without(groups, group).forEach(g => {\n g.subgroups.forEach(subgroup => {\n subgroup.nodes.sort((a, b) => {\n return (sortMap[a._id] || 0) - (sortMap[b._id] || 0)\n })\n })\n })\n }\n\n const maxN = max(groups, d => d.nodes?.length)\n const labelApprxHeight = 40\n const labelMargin = 10\n const subgroupMargin = 40\n const maxNodeSize = getMaxNodeSize(layoutNodes, nodeSize)\n\n if (orientation === 'horizontal') {\n const minHorizontalStep = 2 * maxNodeSize + labelMargin\n const maxHorizontalStep = 3.5 * maxNodeSize + labelMargin\n const horizontalStep = clamp(activeWidth / (maxN - 1), minHorizontalStep, maxHorizontalStep)\n\n const maxVerticalStep = maxNodeSize * 4 + labelApprxHeight\n const minVerticalStep = maxNodeSize * 1.5 + labelApprxHeight\n const verticalStep = (maxNodeSize + layoutParallelGroupSpacing) || clamp(activeHeight / (groups.length - 1), minVerticalStep, maxVerticalStep)\n const subgroupNodeStep = maxNodeSize + labelApprxHeight + labelMargin\n\n let y0 = (groups.length < 2) ? height / 2 : 0\n groups.forEach(group => {\n let x0 = 0\n let dy = 0\n let subgroupMaxWidth = 0\n let groupWidth = 0\n let groupHeight = 0\n let k = 0\n group.subgroups.forEach(subgroup => {\n const subgroupRows = Math.ceil(subgroup.nodes.length / layoutParallelNodesPerColumn)\n let n = 0\n let x = x0\n let y = y0 + dy\n subgroup.nodes.forEach(d => {\n x = x + horizontalStep\n d.x = x\n d.y = y\n groupWidth = Math.max(groupWidth, x)\n\n n = n + 1\n if (n >= layoutParallelNodesPerColumn) {\n n = 0\n y += subgroupNodeStep\n x = x0\n }\n })\n\n const subgroupWidth = Math.min(subgroup.nodes.length, layoutParallelNodesPerColumn) * horizontalStep\n const subgroupHeight = subgroupRows * subgroupNodeStep\n subgroupMaxWidth = Math.max(subgroupMaxWidth, subgroupWidth)\n dy = dy + subgroupHeight + subgroupMargin\n k = k + 1\n if (k >= layoutParallelSubGroupsPerRow) {\n k = 0\n dy = 0\n x0 = x0 + subgroupMaxWidth + subgroupMargin\n subgroupMaxWidth = 0\n }\n\n groupHeight = Math.max(groupHeight, y)\n // x0 += Math.min(subgroup.nodes.length, layoutParallelNodesPerColumn) * horizontalStep + subgroupMargin\n })\n\n // Center group horizontally\n group.subgroups.forEach(subgroup => {\n subgroup.nodes.forEach(d => {\n d.x -= groupWidth / 2\n })\n })\n groupWidth = 0\n\n // Update y0 for the next group\n y0 = groupHeight + verticalStep\n })\n } else {\n const minHorizontalStep = 6 * maxNodeSize + labelMargin\n const maxHorizontalStep = 10 * maxNodeSize + labelMargin\n const horizontalStep = (maxNodeSize + layoutParallelGroupSpacing) || clamp(activeWidth / (maxN - 1), minHorizontalStep, maxHorizontalStep)\n\n const maxVerticalStep = maxNodeSize * 2.0 + labelApprxHeight\n const minVerticalStep = maxNodeSize * 1.5 + labelApprxHeight\n const verticalStep = clamp(activeHeight / (groups.length - 1), minVerticalStep, maxVerticalStep)\n const subgroupNodeStep = maxNodeSize * 2.0\n\n let x0 = (groups.length < 2) ? width / 2 : 0\n groups.forEach(group => {\n let y0 = 0\n let dx = 0 // Horizontal shift inside the group (column)\n let subgroupMaxHeight = 0\n let groupWidth = 0\n let groupHeight = 0\n\n let k = 0\n group.subgroups.forEach(subgroup => {\n const subgroupColumns = Math.ceil(subgroup.nodes.length / layoutParallelNodesPerColumn)\n let n = 0\n let y = y0\n let x = x0 + dx\n subgroup.nodes.forEach(d => {\n y = y + verticalStep\n d.x = x\n d.y = y\n groupHeight = Math.max(groupHeight, y)\n\n n = n + 1\n if (n >= layoutParallelNodesPerColumn) {\n n = 0\n x += subgroupNodeStep\n y = y0\n }\n })\n\n const subgroupHeight = Math.min(subgroup.nodes.length, layoutParallelNodesPerColumn) * verticalStep\n const subgroupWidth = subgroupColumns * subgroupNodeStep\n subgroupMaxHeight = Math.max(subgroupMaxHeight, subgroupHeight)\n dx = dx + subgroupWidth + subgroupMargin\n k = k + 1\n if (k >= layoutParallelSubGroupsPerRow) {\n k = 0\n dx = 0\n y0 = y0 + subgroupMaxHeight + subgroupMargin\n subgroupMaxHeight = 0\n }\n\n groupWidth = Math.max(groupWidth, x)\n })\n\n // Center group vertically\n group.subgroups.forEach(subgroup => {\n subgroup.nodes.forEach(d => {\n d.y -= groupHeight / 2\n })\n })\n groupHeight = 0\n\n // Update x0 for the next group\n x0 = groupWidth + horizontalStep\n })\n }\n\n // Handle non-connected nodes\n if (layoutNonConnectedAside) {\n const maxSize = getMaxNodeSize(nonConnectedNodes, nodeSize)\n const maxY = max<number>(connectedNodes.map(d => d.y)) || 0\n const maxX = max<number>(connectedNodes.map(d => d.x)) || 0\n const minX = min<number>(connectedNodes.map(d => d.x)) || 0\n const graphWidth = (maxX - minX) || width\n positionNonConnectedNodes(nonConnectedNodes, maxY + maxSize * 3, maxSize * 2.25, Math.max(graphWidth, width))\n }\n}\n\nexport async function applyLayoutDagre<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number\n): Promise<void> {\n const { nonConnectedNodes, connectedNodes, nodes, links } = datamodel\n const { nodeSize, layoutNonConnectedAside, dagreLayoutSettings, nodeStrokeWidth, nodeLabel } = config\n\n // eslint-disable-next-line @typescript-eslint/naming-convention,@typescript-eslint/ban-ts-comment\n // @ts-ignore\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const { Graph } = await import('@unovis/graphlibrary')\n // eslint-disable-next-line @typescript-eslint/naming-convention,@typescript-eslint/ban-ts-comment\n // @ts-ignore\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const { layout } = await import('@unovis/dagre-layout')\n\n // https://github.com/dagrejs/dagre/wiki\n const dagreGraph = new Graph() as graphlib.Graph<GraphNode<N, L>>\n\n // Set an object for the graph label\n dagreGraph.setGraph(dagreLayoutSettings)\n\n // Default to assigning a new object as a label for each new edge.\n dagreGraph.setDefaultEdgeLabel(() => ({}))\n\n // Add nodes to the graph. The first argument is the node id. The second is\n // metadata about the node. In this case we're going to add labels to each of\n // our nodes.\n const labelApprxHeight = 40\n const nds = (layoutNonConnectedAside ? connectedNodes : nodes)\n nds.forEach(node => {\n dagreGraph.setNode(`${node._index}`, {\n label: getString(node, nodeLabel, node._index),\n width: getNumber(node, nodeSize, node._index) * 1.5 + getNumber(node, nodeStrokeWidth, node._index),\n height: labelApprxHeight + getNumber(node, nodeSize, node._index) * 1.5,\n originalNode: node,\n })\n })\n\n // Add edges to the graph.\n links.forEach(link => {\n dagreGraph.setEdge(\n `${link.source._index}`,\n `${link.target._index}`\n )\n })\n\n // Calculate the layout\n layout(dagreGraph)\n\n // Apply coordinates to the graph\n dagreGraph.nodes().forEach(d => {\n const node = dagreGraph.node(d) as Node<GraphNode<N, L>> & { originalNode: GraphNode<N, L>}\n node.originalNode.x = node.x // width * d.x / dagreGraph._label.width\n node.originalNode.y = node.y // height * d.y / dagreGraph._label.height\n })\n\n // Handle non-connected nodes\n if (layoutNonConnectedAside) {\n const maxNodeSize = getMaxNodeSize(nonConnectedNodes, nodeSize)\n const maxY = max<number>(connectedNodes.map(d => d.y))\n const maxX = max<number>(connectedNodes.map(d => d.x))\n const minX = min<number>(connectedNodes.map(d => d.x))\n const graphWidth = maxX - minX\n positionNonConnectedNodes(nonConnectedNodes, maxY + maxNodeSize * 3, maxNodeSize * 2.25, Math.max(graphWidth, width), 0)\n }\n}\n\nexport function applyLayoutConcentric<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number,\n height: number\n): void {\n const { nonConnectedNodes, connectedNodes, nodes } = datamodel\n const { layoutNonConnectedAside, layoutGroupOrder, nodeSize, layoutNodeGroup } = config\n\n const layoutNodes = layoutNonConnectedAside ? connectedNodes : nodes\n\n const groupNames: string[] = unique(layoutNodes.map(d => getString(d, layoutNodeGroup, d._index)))\n const groupNamesSorted: string[] = sortBy(groupNames, d => layoutGroupOrder.indexOf(d))\n\n const groups = groupNamesSorted.map(groupName => ({\n name: groupName,\n nodes: layoutNodes.filter(d => getString(d, layoutNodeGroup, d._index) === groupName),\n }))\n\n // Handle connected nodes\n let r = 2 * getAverageNodeSize(groups[0]?.nodes ?? [], nodeSize)\n const widthToHeightRatio = width / height\n\n groups.forEach((group, i) => {\n const avgNodeSize = getAverageNodeSize(group.nodes, nodeSize)\n const requiredRadius = 1.1 * avgNodeSize * group.nodes.length / Math.PI\n if (r < requiredRadius) r = requiredRadius\n\n group.nodes.forEach((node, j) => {\n // If the first (central) group has only one node\n if (i === 0 && group.nodes.length === 1) {\n node.x = width / 2\n node.y = height / 2\n } else {\n let dAngle = 0\n if (i === 0 && group.nodes.length === 3) dAngle = Math.PI / 6\n if (i === 0 && group.nodes.length === 4) dAngle = Math.PI / 4\n const angle = 2 * j * Math.PI / group.nodes.length + i * Math.PI / 12 + dAngle\n node.x = width / 2 + r * Math.cos(angle) * widthToHeightRatio\n node.y = height / 2 + r * Math.sin(angle)\n }\n })\n\n const groupSpacing = avgNodeSize * 3\n r += groupSpacing\n })\n\n // Handle non-connected nodes\n if (layoutNonConnectedAside) {\n const maxSize = getMaxNodeSize(nonConnectedNodes, nodeSize)\n const maxY = max<number>(connectedNodes.map(d => d.y))\n const maxX = max<number>(connectedNodes.map(d => d.x))\n const minX = min<number>(connectedNodes.map(d => d.x))\n const graphWidth = maxX - minX\n positionNonConnectedNodes(nonConnectedNodes, maxY + maxSize * 3, maxSize * 2.25, graphWidth, minX)\n }\n}\n\nexport async function applyLayoutForce<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number\n): Promise<void> {\n const { layoutNonConnectedAside, forceLayoutSettings, nodeSize } = config\n\n const { forceSimulation, forceLink, forceManyBody, forceX, forceY, forceCollide } = await import('d3-force')\n\n const { nonConnectedNodes, connectedNodes, nodes, links } = datamodel\n\n\n // Apply fx and fy to nodes if present before running the simulation\n if (forceLayoutSettings.fixNodePositionAfterSimulation) {\n nodes.forEach((d: GraphForceSimulationNode<N, L>) => {\n d.fx = isNil(d._state.fx) ? undefined : d._state.fx\n d.fy = isNil(d._state.fy) ? undefined : d._state.fy\n })\n } else {\n nodes.forEach((d: GraphForceSimulationNode<N, L>) => {\n delete d._state.fx\n delete d._state.fy\n })\n }\n\n const simulation = forceSimulation(layoutNonConnectedAside ? connectedNodes : nodes)\n .force('link', forceLink(links)\n .id((d) => String((d as GraphNode<N, L>)._id))\n .distance((l, i) => isFunction(forceLayoutSettings.linkDistance) ? forceLayoutSettings.linkDistance(l, i) : forceLayoutSettings.linkDistance)\n .strength((l, i) => isFunction(forceLayoutSettings.linkStrength) ? forceLayoutSettings.linkStrength(l, i) : forceLayoutSettings.linkStrength)\n )\n .force('charge', forceManyBody().strength((d, i) => {\n if (isFunction(forceLayoutSettings.charge)) {\n return forceLayoutSettings.charge(d as GraphNode<N, L>, i)\n } else {\n const linkCount = links.reduce((count, l) => count + Number((l.source === d) || (l.target === d)), 0)\n return forceLayoutSettings.charge * Math.sqrt(linkCount)\n }\n }))\n .force('x', forceX().strength(forceLayoutSettings.forceXStrength))\n .force('y', forceY().strength(forceLayoutSettings.forceYStrength))\n .force('collide', forceCollide<SimulationNodeDatum & N>().radius((d, i) => getNodeSize(d, nodeSize, i)).iterations(1))\n .stop()\n\n // See https://bl.ocks.org/mbostock/1667139, https://github.com/d3/d3-force/blob/master/README.md#simulation_tick\n const numIterations = forceLayoutSettings.numIterations ?? Math.ceil(Math.log(simulation.alphaMin()) / Math.log(1 - simulation.alphaDecay()))\n for (let i = 0, n = numIterations; i < n; ++i) {\n simulation.tick()\n }\n\n // Fix node positions to `_state` if requested.\n // And remove fx and fy from the node datum if present to make sure the nodes are not fixed\n // if the layout was changed to a different layout and then back to force\n if (forceLayoutSettings.fixNodePositionAfterSimulation) {\n nodes.forEach((d: GraphForceSimulationNode<N, L>) => {\n delete d.fx\n delete d.fy\n d._state.fx = d.x\n d._state.fy = d.y\n })\n }\n\n // Handle non-connected nodes\n if (layoutNonConnectedAside) {\n const maxSize = getMaxNodeSize(nonConnectedNodes, nodeSize)\n const maxY = max<number>(connectedNodes.map(d => d.y))\n const maxX = max<number>(connectedNodes.map(d => d.x))\n const minX = min<number>(connectedNodes.map(d => d.x))\n const graphWidth = maxX - minX\n positionNonConnectedNodes(nonConnectedNodes, maxY + maxSize * 6, maxSize * 2.25, Math.max(graphWidth, width), minX)\n }\n}\n\nexport async function applyELKLayout<N extends GraphInputNode, L extends GraphInputLink> (\n datamodel: GraphDataModel<N, L, GraphNode<N, L>, GraphLink<N, L>>,\n config: GraphConfigInterface<N, L>,\n width: number\n): Promise<void> {\n const ELK = (await import('elkjs/lib/elk.bundled.js')).default\n const elk = new ELK()\n\n const labelApprxHeight = 30\n const nodes = datamodel.nodes.map((n, i) => ({\n ...n,\n id: n._id,\n width: getNumber(n, config.nodeSize, n._index) + getNumber(n, config.nodeStrokeWidth, n._index),\n height: getNumber(n, config.nodeSize, n._index) + labelApprxHeight,\n ...(config.layoutElkGetNodeShape ? config.layoutElkGetNodeShape(n, i) : {}),\n }))\n\n let elkNodes: (GraphNode<N, L> | GraphElkHierarchyNode<N, L>)[]\n if (config.layoutElkNodeGroups) {\n const groupingFunctions = config.layoutElkNodeGroups\n .map(accessor => (d: GraphNode<N, L>) => getString(d, accessor, d._index)) as [(d: GraphNode<N, L>) => string]\n const grouped = group(nodes, ...groupingFunctions)\n elkNodes = toElkHierarchy(grouped, config.layoutElkSettings)\n } else {\n elkNodes = nodes\n }\n\n const rootNodeId = 'root'\n const elkGraph: ElkNode = {\n id: rootNodeId,\n layoutOptions: merge(DEFAULT_ELK_SETTINGS, getValue(rootNodeId, config.layoutElkSettings)),\n children: elkNodes as ElkNode[],\n edges: datamodel.links.map(l => ({\n id: l._id,\n sources: [l.source._id],\n targets: [l.target._id],\n })),\n }\n\n const layout = await elk.layout(elkGraph)\n adjustElkHierarchyCoordinates(layout)\n\n nodes.forEach((node, i) => {\n const found = datamodel.nodes.find(n => n._id === node.id)\n if (!found) return\n\n found.x = node.x\n found.y = node.y\n })\n\n // Handle non-connected nodes\n if (config.layoutNonConnectedAside) {\n const maxSize = getMaxNodeSize(datamodel.nonConnectedNodes, config.nodeSize)\n const maxY = max<number>(datamodel.connectedNodes.map(d => d.y)) || 0\n const maxX = max<number>(datamodel.connectedNodes.map(d => d.x)) || 0\n const minX = min<number>(datamodel.connectedNodes.map(d => d.x)) || 0\n const graphWidth = (maxX - minX) || width\n positionNonConnectedNodes(datamodel.nonConnectedNodes, maxY + maxSize * 3, maxSize * 2.25, Math.max(graphWidth, width))\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -24,5 +24,15 @@ 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;
|
|
29
|
+
/** Enable lightness variance for sibling tiles. Default: `false` */
|
|
30
|
+
enableLightnessVariance?: boolean;
|
|
31
|
+
/** Enable font size variation for leaf node labels based on value. Default: `false` */
|
|
32
|
+
enableTileLabelFontSizeVariation?: boolean;
|
|
33
|
+
/** Minimum font size in pixels for leaf node labels when font size variation is enabled. Default: `8` */
|
|
34
|
+
tileLabelMinFontSize?: number;
|
|
35
|
+
/** Maximum font size in pixels for leaf node labels when font size variation is enabled. Default: `32` */
|
|
36
|
+
tileLabelMaxFontSize?: number;
|
|
27
37
|
}
|
|
28
38
|
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, enableLightnessVariance: false, enableTileLabelFontSizeVariation: true, tileLabelMinFontSize: 8, tileLabelMaxFontSize: 48 });
|
|
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 /** Enable lightness variance for sibling tiles. Default: `false` */\n enableLightnessVariance?: boolean;\n\n /** Enable font size variation for leaf node labels based on value. Default: `false` */\n enableTileLabelFontSizeVariation?: boolean;\n\n /** Minimum font size in pixels for leaf node labels when font size variation is enabled. Default: `8` */\n tileLabelMinFontSize?: number;\n\n /** Maximum font size in pixels for leaf node labels when font size variation is enabled. Default: `32` */\n tileLabelMaxFontSize?: 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 enableLightnessVariance: false,\n enableTileLabelFontSizeVariation: true,\n tileLabelMinFontSize: 8,\n tileLabelMaxFontSize: 48,\n}\n"],"names":[],"mappings":";;AAqDa,MAAA,oBAAoB,GAC5B,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,MAAA,CAAA,EAAA,EAAA,sBAAsB,KACzB,EAAE,EAAE,CAAC,CAAU,EAAE,CAAS,KAAqB,EAAA,IAAA,EAAA,CAAA,CAAC,OAAA,CAAC,EAAA,GAAA,CAAoB,CAAC,EAAE,mCAAI,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,EACnB,uBAAuB,EAAE,KAAK,EAC9B,gCAAgC,EAAE,IAAI,EACtC,oBAAoB,EAAE,CAAC,EACvB,oBAAoB,EAAE,EAAE;;;;"}
|
|
@@ -9,6 +9,8 @@ export declare class Treemap<Datum> extends ComponentCore<Datum[], TreemapConfig
|
|
|
9
9
|
config: TreemapConfigInterface<Datum>;
|
|
10
10
|
datamodel: SeriesDataModel<Datum>;
|
|
11
11
|
tiles: Selection<SVGGElement, unknown, SVGGElement, unknown>;
|
|
12
|
+
private isTileLargeEnough;
|
|
13
|
+
private getTileLightness;
|
|
12
14
|
constructor(config?: TreemapConfigInterface<Datum>);
|
|
13
15
|
_render(customDuration?: number): void;
|
|
14
16
|
}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
+
import { select } from 'd3-selection';
|
|
1
2
|
import { hierarchy, treemap } from 'd3-hierarchy';
|
|
2
|
-
import { group, max } from 'd3-array';
|
|
3
|
-
import { scaleLinear } from 'd3-scale';
|
|
3
|
+
import { extent, group, max } from 'd3-array';
|
|
4
|
+
import { scaleLinear, scaleSqrt } from 'd3-scale';
|
|
5
|
+
import { hsl } from 'd3-color';
|
|
6
|
+
import { wrapSVGText } from '../../utils/text.js';
|
|
4
7
|
import { ComponentCore } from '../../core/component/index.js';
|
|
5
8
|
import { SeriesDataModel } from '../../data-models/series.js';
|
|
6
|
-
import { getColor } from '../../utils/color.js';
|
|
9
|
+
import { getColor, getHexValue, brighter, isDarkBackground } from '../../utils/color.js';
|
|
7
10
|
import { isNumber, getString, getNumber } from '../../utils/data.js';
|
|
8
11
|
import { smartTransition } from '../../utils/d3.js';
|
|
9
12
|
import { TreemapDefaultConfig } from './config.js';
|
|
10
13
|
import * as style from './style.js';
|
|
11
|
-
import { tiles,
|
|
14
|
+
import { tiles, tileGroup, tile, label } from './style.js';
|
|
12
15
|
|
|
16
|
+
const LIGHTNESS_VARIATION_AMOUNT = 0.08;
|
|
17
|
+
const MIN_TILE_SIZE_FOR_LABEL = 20;
|
|
13
18
|
const defaultNumberFormat = (value) => `${value}`;
|
|
14
19
|
class Treemap extends ComponentCore {
|
|
15
20
|
constructor(config) {
|
|
@@ -21,6 +26,21 @@ class Treemap extends ComponentCore {
|
|
|
21
26
|
this.setConfig(config);
|
|
22
27
|
this.tiles = this.g.append('g').attr('class', tiles);
|
|
23
28
|
}
|
|
29
|
+
isTileLargeEnough(d) {
|
|
30
|
+
const w = d.x1 - d.x0;
|
|
31
|
+
const h = d.y1 - d.y0;
|
|
32
|
+
return (w >= MIN_TILE_SIZE_FOR_LABEL) && (h >= MIN_TILE_SIZE_FOR_LABEL);
|
|
33
|
+
}
|
|
34
|
+
getTileLightness(node, siblings) {
|
|
35
|
+
// Get the value extent of the sibling group
|
|
36
|
+
const [minValue, maxValue] = extent(siblings, d => d.value);
|
|
37
|
+
// If there's no range or no value, return default lightness
|
|
38
|
+
if (minValue === maxValue || !node.value)
|
|
39
|
+
return 0;
|
|
40
|
+
// Calculate relative position in the range (0 to 1)
|
|
41
|
+
// Larger values will be closer to 0 (darker)
|
|
42
|
+
return LIGHTNESS_VARIATION_AMOUNT * ((maxValue - node.value) / (maxValue - minValue));
|
|
43
|
+
}
|
|
24
44
|
_render(customDuration) {
|
|
25
45
|
var _a;
|
|
26
46
|
const { config, datamodel: { data }, _width, _height } = this;
|
|
@@ -67,71 +87,84 @@ class Treemap extends ComponentCore {
|
|
|
67
87
|
});
|
|
68
88
|
const treemapData = treemapLayout(rootNode);
|
|
69
89
|
const descendants = treemapData.descendants();
|
|
70
|
-
// Set up the
|
|
90
|
+
// Set up the brightness increase scale based on depth
|
|
71
91
|
const maxDepth = max(descendants, d => d.depth);
|
|
72
|
-
|
|
92
|
+
// Get value extent only from leaf nodes
|
|
93
|
+
const [minValue, maxValue] = extent(descendants.filter(d => !d.children), d => d.value);
|
|
94
|
+
const brightnessIncrease = scaleLinear()
|
|
73
95
|
.domain([1, maxDepth])
|
|
74
|
-
.range([
|
|
96
|
+
.range([0, 1]);
|
|
97
|
+
// Create font size scale for leaf nodes using sqrt scale
|
|
98
|
+
const fontSizeScale = scaleSqrt()
|
|
99
|
+
.domain([minValue || 1, maxValue || 1])
|
|
100
|
+
.range([config.tileLabelMinFontSize, config.tileLabelMaxFontSize])
|
|
101
|
+
.clamp(true);
|
|
75
102
|
// Set fill color and opacity for each node
|
|
76
103
|
treemapData
|
|
77
104
|
.eachBefore((node) => {
|
|
78
105
|
if (!node.children)
|
|
79
106
|
return;
|
|
80
|
-
|
|
107
|
+
// Get all children for value comparison
|
|
108
|
+
const children = node.children;
|
|
109
|
+
children.forEach((child, i) => {
|
|
81
110
|
const treemapChild = child;
|
|
82
|
-
// Calculate color for this child using the color accessor function
|
|
83
|
-
|
|
111
|
+
// Calculate base color for this child using the color accessor function
|
|
112
|
+
let color = getColor(treemapChild, config.tileColor, i, treemapChild.depth !== 1);
|
|
84
113
|
// If no color for this child, use the parent's color
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
|
|
114
|
+
color = color !== null && color !== void 0 ? color : node._fill;
|
|
115
|
+
// Convert CSS variables to hex values if needed
|
|
116
|
+
const hexColor = color ? getHexValue(color, this.g.node()) : null;
|
|
117
|
+
if (hexColor) {
|
|
118
|
+
// Convert to HSL for easier lightness manipulation
|
|
119
|
+
const hslColor = hsl(hexColor);
|
|
120
|
+
if (config.enableLightnessVariance) {
|
|
121
|
+
// Only apply lightness variation to leaf nodes
|
|
122
|
+
if (!treemapChild.children) {
|
|
123
|
+
const lightnessAdjustment = this.getTileLightness(treemapChild, children);
|
|
124
|
+
hslColor.l = Math.min(1, hslColor.l + lightnessAdjustment);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Make the color brighter based on depth
|
|
128
|
+
treemapChild._fill = brighter(hslColor.toString(), brightnessIncrease(treemapChild.depth));
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
treemapChild._fill = null;
|
|
132
|
+
}
|
|
88
133
|
});
|
|
89
134
|
});
|
|
90
135
|
// Render tiles
|
|
91
136
|
const visibleNodes = descendants.filter(d => d.depth > 0);
|
|
92
137
|
const tiles = this.tiles
|
|
93
|
-
.selectAll(`g.${
|
|
138
|
+
.selectAll(`g.${tileGroup}`)
|
|
94
139
|
.data(visibleNodes, d => d._id);
|
|
95
140
|
const tilesEnter = tiles
|
|
96
141
|
.enter()
|
|
97
142
|
.append('g')
|
|
98
|
-
.attr('class',
|
|
143
|
+
.attr('class', tileGroup);
|
|
99
144
|
// Add clipPath elements
|
|
100
145
|
tilesEnter
|
|
101
146
|
.append('clipPath')
|
|
102
147
|
.attr('id', d => `clip-${d._id}`)
|
|
103
|
-
.append('rect');
|
|
104
|
-
// Tile background rectangles
|
|
105
|
-
tilesEnter
|
|
106
148
|
.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
|
|
149
|
+
.attr('rx', config.tileBorderRadius)
|
|
150
|
+
.attr('ry', config.tileBorderRadius);
|
|
151
|
+
// Tile rectangles
|
|
120
152
|
tilesEnter
|
|
121
153
|
.append('rect')
|
|
122
|
-
.attr('class',
|
|
154
|
+
.attr('class', tile)
|
|
155
|
+
.attr('rx', config.tileBorderRadius)
|
|
156
|
+
.attr('ry', config.tileBorderRadius)
|
|
123
157
|
// Initialize tile positions so that the initial transition is smooth
|
|
124
158
|
.attr('x', d => d.x0)
|
|
125
159
|
.attr('y', d => d.y0)
|
|
126
160
|
.attr('width', d => d.x1 - d.x0)
|
|
127
161
|
.attr('height', d => d.y1 - d.y0)
|
|
128
162
|
.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}`)
|
|
163
|
+
.style('opacity', 0);
|
|
164
|
+
tiles.merge(tilesEnter).select(`rect.${tile}`)
|
|
132
165
|
.call(selection => smartTransition(selection, duration)
|
|
133
166
|
.style('fill', d => { var _a; return (_a = d._fill) !== null && _a !== void 0 ? _a : getColor(d, config.tileColor); })
|
|
134
|
-
.style('
|
|
167
|
+
.style('opacity', 1)
|
|
135
168
|
.attr('x', d => d.x0)
|
|
136
169
|
.attr('y', d => d.y0)
|
|
137
170
|
.attr('width', d => d.x1 - d.x0)
|
|
@@ -148,17 +181,44 @@ class Treemap extends ComponentCore {
|
|
|
148
181
|
.append('text')
|
|
149
182
|
.attr('class', label)
|
|
150
183
|
.attr('clip-path', d => `url(#clip-${d._id})`);
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
.
|
|
184
|
+
// Update all labels first
|
|
185
|
+
const mergedTiles = tiles.merge(tilesEnter);
|
|
186
|
+
// Hide labels that don't meet criteria
|
|
187
|
+
mergedTiles.select(`text.${label}`)
|
|
188
|
+
.style('display', d => {
|
|
189
|
+
const isAllowedNode = config.labelInternalNodes ? true : !d.children;
|
|
190
|
+
return isAllowedNode && this.isTileLargeEnough(d) ? null : 'none';
|
|
191
|
+
})
|
|
192
|
+
// Make the internal labels semibold
|
|
193
|
+
.style('font-weight', d => d.children ? '500' : 'normal');
|
|
194
|
+
// Update visible labels
|
|
195
|
+
mergedTiles.select(`text.${label}`)
|
|
196
|
+
.filter(d => {
|
|
197
|
+
const isAllowedNode = config.labelInternalNodes ? true : !d.children;
|
|
198
|
+
return isAllowedNode && this.isTileLargeEnough(d);
|
|
199
|
+
})
|
|
156
200
|
.attr('clip-path', d => `url(#clip-${d._id})`)
|
|
157
201
|
.attr('x', d => d.x0 + config.labelOffsetX)
|
|
158
202
|
.attr('y', d => d.y0 + config.labelOffsetY)
|
|
159
|
-
.
|
|
203
|
+
.each(function (d) {
|
|
204
|
+
var _a;
|
|
205
|
+
const text = select(this);
|
|
160
206
|
// @ts-expect-error This is a workaround for the D3 types
|
|
161
|
-
|
|
207
|
+
const label = `${d.data[0]}: ${numberFormat(d.value)}`;
|
|
208
|
+
text.text(label);
|
|
209
|
+
// Set text color based on background darkness
|
|
210
|
+
const backgroundColor = (_a = d._fill) !== null && _a !== void 0 ? _a : getColor(d, config.tileColor);
|
|
211
|
+
const textColor = backgroundColor && isDarkBackground(backgroundColor) ? '#ffffff' : '#000000';
|
|
212
|
+
text.style('fill', textColor);
|
|
213
|
+
// Apply font size scaling only to leaf nodes if enabled
|
|
214
|
+
if (!d.children && config.enableTileLabelFontSizeVariation) {
|
|
215
|
+
text.style('font-size', `${fontSizeScale(d.value)}px`);
|
|
216
|
+
}
|
|
217
|
+
// Apply text wrapping to leaf nodes
|
|
218
|
+
if (!d.children) {
|
|
219
|
+
const availableWidth = d.x1 - d.x0 - (2 * config.labelOffsetX);
|
|
220
|
+
wrapSVGText(text, availableWidth);
|
|
221
|
+
}
|
|
162
222
|
});
|
|
163
223
|
// Exit
|
|
164
224
|
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, extent } from 'd3-array'\nimport { scaleLinear, scaleSqrt } from 'd3-scale'\nimport { hsl } from 'd3-color'\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' // Minimum pixel size for showing labels\n\nconst LIGHTNESS_VARIATION_AMOUNT = 0.08\n\nconst MIN_TILE_SIZE_FOR_LABEL = 20\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 private isTileLargeEnough (d: TreemapNode<Datum>): boolean {\n const w = d.x1 - d.x0\n const h = d.y1 - d.y0\n return (w >= MIN_TILE_SIZE_FOR_LABEL) && (h >= MIN_TILE_SIZE_FOR_LABEL)\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 LIGHTNESS_VARIATION_AMOUNT * ((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 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 // Get value extent only from leaf nodes\n const [minValue, maxValue] = extent(descendants.filter(d => !d.children), d => d.value)\n\n const brightnessIncrease = scaleLinear()\n .domain([1, maxDepth])\n .range([0, 1])\n\n // Create font size scale for leaf nodes using sqrt scale\n const fontSizeScale = scaleSqrt()\n .domain([minValue || 1, maxValue || 1])\n .range([config.tileLabelMinFontSize, config.tileLabelMaxFontSize])\n .clamp(true)\n\n // Set fill color and opacity for each node\n treemapData\n .eachBefore((node) => {\n if (!node.children) return\n // Get all children for value comparison\n const children = node.children as TreemapNode<Datum>[]\n\n 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 if (hexColor) {\n // Convert to HSL for easier lightness manipulation\n const hslColor = hsl(hexColor)\n\n if (config.enableLightnessVariance) {\n // Only apply lightness variation to leaf nodes\n if (!treemapChild.children) {\n const lightnessAdjustment = this.getTileLightness(treemapChild, children)\n hslColor.l = Math.min(1, hslColor.l + lightnessAdjustment)\n }\n }\n\n // Make the color brighter based on depth\n treemapChild._fill = brighter(hslColor.toString(), brightnessIncrease(treemapChild.depth))\n } else {\n treemapChild._fill = null\n }\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.tileGroup}`)\n .data(visibleNodes, d => d._id)\n const tilesEnter = tiles\n .enter()\n .append('g')\n .attr('class', s.tileGroup)\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 // Update all labels first\n const mergedTiles = tiles.merge(tilesEnter)\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\n .style('font-weight', d => d.children ? '500' : 'normal')\n\n // Update visible labels\n mergedTiles.select(`text.${s.label}`)\n .filter(d => {\n const isAllowedNode = config.labelInternalNodes ? true : !d.children\n return isAllowedNode && this.isTileLargeEnough(d)\n })\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 font size scaling only to leaf nodes if enabled\n if (!d.children && config.enableTileLabelFontSizeVariation) {\n text.style('font-size', `${fontSizeScale(d.value)}px`)\n }\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.tileGroup","s.tile","s.label","s"],"mappings":"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"}
|
|
@@ -2,18 +2,20 @@ export declare const root: string;
|
|
|
2
2
|
export declare const variables: {
|
|
3
3
|
treemapTileStrokeColor: "--vis-treemap-tile-stroke-color";
|
|
4
4
|
treemapTileStrokeWidth: "--vis-treemap-tile-stroke-width";
|
|
5
|
+
treemapTileHoverStrokeColor: "--vis-treemap-tile-hover-stroke-color";
|
|
5
6
|
treemapTileFillColor: "--vis-treemap-tile-fill-color";
|
|
6
7
|
treemapTileBackgroundColor: "--vis-treemap-tile-background-color";
|
|
7
8
|
treemapTileCursor: "--vis-treemap-tile-cursor";
|
|
8
9
|
treemapLabelFontFamily: "--vis-treemap-label-font-family";
|
|
9
10
|
treemapLabelTextColor: "--vis-treemap-label-text-color";
|
|
10
11
|
treemapLabelFontSize: "--vis-treemap-label-font-size";
|
|
12
|
+
treemapLabelOpacity: "--vis-treemap-label-opacity";
|
|
11
13
|
darkTreemapTileStrokeColor: "--vis-dark-treemap-tile-stroke-color";
|
|
12
14
|
darkTreemapTileFillColor: "--vis-dark-treemap-tile-fill-color";
|
|
13
15
|
darkTreemapLabelTextColor: "--vis-dark-treemap-label-text-color";
|
|
14
16
|
};
|
|
15
17
|
export declare const tiles: string;
|
|
18
|
+
export declare const tileGroup: string;
|
|
16
19
|
export declare const tile: string;
|
|
17
|
-
export declare const tileBackground: string;
|
|
18
20
|
export declare const tileForeground: string;
|
|
19
21
|
export declare const label: string;
|
|
@@ -3,7 +3,8 @@ import { getCssVarNames, injectGlobalCssVariables } from '../../utils/style.js';
|
|
|
3
3
|
|
|
4
4
|
const cssVarDefaults = {
|
|
5
5
|
'--vis-treemap-tile-stroke-color': '#fff',
|
|
6
|
-
'--vis-treemap-tile-stroke-width': '
|
|
6
|
+
'--vis-treemap-tile-stroke-width': '2px',
|
|
7
|
+
'--vis-treemap-tile-hover-stroke-color': '#fff',
|
|
7
8
|
'--vis-treemap-tile-fill-color': '#B9BEC3',
|
|
8
9
|
'--vis-treemap-tile-background-color': '#fff',
|
|
9
10
|
'--vis-treemap-tile-cursor': 'default',
|
|
@@ -11,6 +12,8 @@ const cssVarDefaults = {
|
|
|
11
12
|
'--vis-treemap-label-font-family': undefined,
|
|
12
13
|
'--vis-treemap-label-text-color': '#5b5f6d',
|
|
13
14
|
'--vis-treemap-label-font-size': '12px',
|
|
15
|
+
/* Label opacity */
|
|
16
|
+
'--vis-treemap-label-opacity': 0.8,
|
|
14
17
|
/* Dark Theme */
|
|
15
18
|
'--vis-dark-treemap-tile-stroke-color': '#2c2c2c',
|
|
16
19
|
'--vis-dark-treemap-tile-fill-color': '#5b5f6d',
|
|
@@ -24,12 +27,18 @@ injectGlobalCssVariables(cssVarDefaults, root);
|
|
|
24
27
|
const tiles = css `
|
|
25
28
|
label: g-tiles;
|
|
26
29
|
`;
|
|
30
|
+
const tileGroup = css `
|
|
31
|
+
label: tile-group;
|
|
32
|
+
`;
|
|
27
33
|
const tile = css `
|
|
28
34
|
label: tile;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
stroke: var(--vis-treemap-tile-hover-stroke-color);
|
|
36
|
+
stroke-opacity: 0;
|
|
37
|
+
transition: stroke-opacity 100ms ease-in-out;
|
|
38
|
+
|
|
39
|
+
&:hover {
|
|
40
|
+
stroke-opacity: 1;
|
|
41
|
+
}
|
|
33
42
|
`;
|
|
34
43
|
const tileForeground = css `
|
|
35
44
|
label: tile-foreground;
|
|
@@ -39,8 +48,10 @@ const label = css `
|
|
|
39
48
|
text-anchor: start;
|
|
40
49
|
dominant-baseline: hanging;
|
|
41
50
|
user-select: none;
|
|
51
|
+
pointer-events: none;
|
|
42
52
|
font-size: var(--vis-treemap-label-font-size);
|
|
53
|
+
opacity: var(--vis-treemap-label-opacity);
|
|
43
54
|
`;
|
|
44
55
|
|
|
45
|
-
export { label, root, tile,
|
|
56
|
+
export { label, root, tile, tileForeground, tileGroup, tiles, variables };
|
|
46
57
|
//# 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': '
|
|
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-fill-color': '#B9BEC3',\n '--vis-treemap-tile-background-color': '#fff',\n '--vis-treemap-tile-cursor': 'default',\n /* Undefined by default to allow proper fallback to var(--vis-font-family) */\n '--vis-treemap-label-font-family': undefined as undefined,\n '--vis-treemap-label-text-color': '#5b5f6d',\n '--vis-treemap-label-font-size': '12px',\n\n /* Label opacity */\n '--vis-treemap-label-opacity': 0.8,\n\n /* Dark Theme */\n '--vis-dark-treemap-tile-stroke-color': '#2c2c2c',\n '--vis-dark-treemap-tile-fill-color': '#5b5f6d',\n '--vis-dark-treemap-label-text-color': '#fff',\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(--vis-treemap-tile-hover-stroke-color);\n stroke-opacity: 0;\n transition: stroke-opacity 100ms ease-in-out;\n\n &:hover {\n stroke-opacity: 1;\n }\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(--vis-treemap-label-font-size);\n opacity: var(--vis-treemap-label-opacity);\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,+BAA+B,EAAE,SAAS;AAC1C,IAAA,qCAAqC,EAAE,MAAM;AAC7C,IAAA,2BAA2B,EAAE,SAAS;;AAEtC,IAAA,iCAAiC,EAAE,SAAsB;AACzD,IAAA,gCAAgC,EAAE,SAAS;AAC3C,IAAA,+BAA+B,EAAE,MAAM;;AAGvC,IAAA,6BAA6B,EAAE,GAAG;;AAGlC,IAAA,sCAAsC,EAAE,SAAS;AACjD,IAAA,oCAAoC,EAAE,SAAS;AAC/C,IAAA,qCAAqC,EAAE,MAAM;CAC9C,CAAA;AAEM,MAAM,IAAI,GAAG,GAAG,CAAA;;EAEtB;MAEY,SAAS,GAAG,cAAc,CAAC,cAAc,EAAC;AACvD,wBAAwB,CAAC,cAAc,EAAE,IAAI,CAAC,CAAA;AAEvC,MAAM,KAAK,GAAG,GAAG,CAAA;;EAEvB;AAEM,MAAM,SAAS,GAAG,GAAG,CAAA;;EAE3B;AAEM,MAAM,IAAI,GAAG,GAAG,CAAA;;;;;;;;;EAStB;AAEM,MAAM,cAAc,GAAG,GAAG,CAAA;;EAEhC;AAEM,MAAM,KAAK,GAAG,GAAG,CAAA;;;;;;;;;;;;"}
|
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.16",
|
|
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.55) {
|
|
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.55): 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';
|