@mui/x-charts-premium 8.26.0 → 9.0.0-alpha.0

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.
Files changed (134) hide show
  1. package/BarChartPremium/BarChartPremium.d.ts +14 -2
  2. package/BarChartPremium/BarChartPremium.js +11 -5
  3. package/BarChartPremium/RangeBar/AnimatedRangeBarElement.js +1 -1
  4. package/BarChartPremium/RangeBar/FocusedRangeBar.d.ts +2 -0
  5. package/BarChartPremium/RangeBar/FocusedRangeBar.js +70 -0
  6. package/BarChartPremium/RangeBar/RangeBarPlot.js +1 -1
  7. package/BarChartPremium/RangeBar/createGetRangeBarDimensions.d.ts +13 -0
  8. package/BarChartPremium/RangeBar/createGetRangeBarDimensions.js +42 -0
  9. package/BarChartPremium/RangeBar/seriesConfig/getSeriesWithDefaultValues.d.ts +2 -2
  10. package/BarChartPremium/RangeBar/seriesConfig/index.js +4 -1
  11. package/BarChartPremium/RangeBar/seriesConfig/keyboardFocusHandler.d.ts +3 -0
  12. package/BarChartPremium/RangeBar/seriesConfig/keyboardFocusHandler.js +22 -0
  13. package/BarChartPremium/RangeBar/seriesConfig/legend.js +0 -1
  14. package/BarChartPremium/RangeBar/seriesConfig/tooltipPosition.js +8 -2
  15. package/BarChartPremium/RangeBar/useRangeBarPlotData.d.ts +2 -9
  16. package/BarChartPremium/RangeBar/useRangeBarPlotData.js +16 -51
  17. package/BarChartPremium/index.d.ts +1 -0
  18. package/BarChartPremium/index.js +12 -0
  19. package/CHANGELOG.md +355 -3
  20. package/ChartContainerPremium/ChartContainerPremium.d.ts +17 -31
  21. package/ChartContainerPremium/ChartContainerPremium.js +15 -43
  22. package/ChartContainerPremium/useChartContainerPremiumProps.d.ts +10 -9
  23. package/ChartContainerPremium/useChartContainerPremiumProps.js +10 -27
  24. package/ChartDataProviderPremium/ChartDataProviderPremium.d.ts +7 -5
  25. package/ChartDataProviderPremium/ChartDataProviderPremium.js +6 -6
  26. package/ChartDataProviderPremium/index.d.ts +1 -1
  27. package/ChartDataProviderPremium/useChartDataProviderPremiumProps.d.ts +3 -3
  28. package/ChartZoomSlider/internals/previews/RangeBarPreviewPlot.js +1 -1
  29. package/ChartsContainer/index.d.ts +1 -0
  30. package/ChartsContainer/index.js +16 -0
  31. package/ChartsContainerPremium/ChartsContainerPremium.d.ts +37 -0
  32. package/ChartsContainerPremium/ChartsContainerPremium.js +52 -0
  33. package/ChartsContainerPremium/index.d.ts +2 -0
  34. package/ChartsContainerPremium/index.js +17 -0
  35. package/ChartsContainerPremium/useChartsContainerPremiumProps.d.ts +9 -0
  36. package/ChartsContainerPremium/useChartsContainerPremiumProps.js +33 -0
  37. package/ChartsContainerPro/index.d.ts +1 -0
  38. package/ChartsContainerPro/index.js +16 -0
  39. package/HeatmapPremium/HeatmapPlotPremium.d.ts +9 -0
  40. package/HeatmapPremium/HeatmapPlotPremium.js +29 -0
  41. package/HeatmapPremium/HeatmapPremium.d.ts +15 -0
  42. package/HeatmapPremium/HeatmapPremium.js +478 -0
  43. package/HeatmapPremium/HeatmapPremium.plugins.d.ts +4 -0
  44. package/HeatmapPremium/HeatmapPremium.plugins.js +9 -0
  45. package/HeatmapPremium/index.d.ts +1 -0
  46. package/HeatmapPremium/index.js +16 -0
  47. package/HeatmapPremium/useHeatmapPremiumProps.d.ts +16 -0
  48. package/HeatmapPremium/useHeatmapPremiumProps.js +26 -0
  49. package/HeatmapPremium/webgl/HeatmapWebGLPlot.d.ts +6 -0
  50. package/HeatmapPremium/webgl/HeatmapWebGLPlot.js +185 -0
  51. package/HeatmapPremium/webgl/HeatmapWebGLRenderer.d.ts +4 -0
  52. package/HeatmapPremium/webgl/HeatmapWebGLRenderer.js +23 -0
  53. package/HeatmapPremium/webgl/shaders.d.ts +3 -0
  54. package/HeatmapPremium/webgl/shaders.js +77 -0
  55. package/HeatmapPremium/webgl/useHeatmapPlotData.d.ts +12 -0
  56. package/HeatmapPremium/webgl/useHeatmapPlotData.js +58 -0
  57. package/HeatmapPremium/webgl/utils.d.ts +8 -0
  58. package/HeatmapPremium/webgl/utils.js +51 -0
  59. package/esm/BarChartPremium/BarChartPremium.d.ts +14 -2
  60. package/esm/BarChartPremium/BarChartPremium.js +12 -6
  61. package/esm/BarChartPremium/RangeBar/AnimatedRangeBarElement.js +1 -1
  62. package/esm/BarChartPremium/RangeBar/FocusedRangeBar.d.ts +2 -0
  63. package/esm/BarChartPremium/RangeBar/FocusedRangeBar.js +63 -0
  64. package/esm/BarChartPremium/RangeBar/RangeBarPlot.js +1 -1
  65. package/esm/BarChartPremium/RangeBar/createGetRangeBarDimensions.d.ts +13 -0
  66. package/esm/BarChartPremium/RangeBar/createGetRangeBarDimensions.js +36 -0
  67. package/esm/BarChartPremium/RangeBar/seriesConfig/getSeriesWithDefaultValues.d.ts +2 -2
  68. package/esm/BarChartPremium/RangeBar/seriesConfig/index.js +5 -2
  69. package/esm/BarChartPremium/RangeBar/seriesConfig/keyboardFocusHandler.d.ts +3 -0
  70. package/esm/BarChartPremium/RangeBar/seriesConfig/keyboardFocusHandler.js +16 -0
  71. package/esm/BarChartPremium/RangeBar/seriesConfig/legend.js +0 -1
  72. package/esm/BarChartPremium/RangeBar/seriesConfig/tooltipPosition.js +8 -2
  73. package/esm/BarChartPremium/RangeBar/useRangeBarPlotData.d.ts +2 -9
  74. package/esm/BarChartPremium/RangeBar/useRangeBarPlotData.js +16 -51
  75. package/esm/BarChartPremium/index.d.ts +1 -0
  76. package/esm/BarChartPremium/index.js +1 -0
  77. package/esm/ChartContainerPremium/ChartContainerPremium.d.ts +17 -31
  78. package/esm/ChartContainerPremium/ChartContainerPremium.js +16 -42
  79. package/esm/ChartContainerPremium/useChartContainerPremiumProps.d.ts +10 -9
  80. package/esm/ChartContainerPremium/useChartContainerPremiumProps.js +10 -25
  81. package/esm/ChartDataProviderPremium/ChartDataProviderPremium.d.ts +7 -5
  82. package/esm/ChartDataProviderPremium/ChartDataProviderPremium.js +6 -5
  83. package/esm/ChartDataProviderPremium/index.d.ts +1 -1
  84. package/esm/ChartDataProviderPremium/useChartDataProviderPremiumProps.d.ts +3 -3
  85. package/esm/ChartZoomSlider/internals/previews/RangeBarPreviewPlot.js +1 -1
  86. package/esm/ChartsContainer/index.d.ts +1 -0
  87. package/esm/ChartsContainer/index.js +2 -0
  88. package/esm/ChartsContainerPremium/ChartsContainerPremium.d.ts +37 -0
  89. package/esm/ChartsContainerPremium/ChartsContainerPremium.js +46 -0
  90. package/esm/ChartsContainerPremium/index.d.ts +2 -0
  91. package/esm/ChartsContainerPremium/index.js +2 -0
  92. package/esm/ChartsContainerPremium/useChartsContainerPremiumProps.d.ts +9 -0
  93. package/esm/ChartsContainerPremium/useChartsContainerPremiumProps.js +27 -0
  94. package/esm/ChartsContainerPro/index.d.ts +1 -0
  95. package/esm/ChartsContainerPro/index.js +2 -0
  96. package/esm/HeatmapPremium/HeatmapPlotPremium.d.ts +9 -0
  97. package/esm/HeatmapPremium/HeatmapPlotPremium.js +23 -0
  98. package/esm/HeatmapPremium/HeatmapPremium.d.ts +15 -0
  99. package/esm/HeatmapPremium/HeatmapPremium.js +472 -0
  100. package/esm/HeatmapPremium/HeatmapPremium.plugins.d.ts +4 -0
  101. package/esm/HeatmapPremium/HeatmapPremium.plugins.js +3 -0
  102. package/esm/HeatmapPremium/index.d.ts +1 -0
  103. package/esm/HeatmapPremium/index.js +1 -0
  104. package/esm/HeatmapPremium/useHeatmapPremiumProps.d.ts +16 -0
  105. package/esm/HeatmapPremium/useHeatmapPremiumProps.js +19 -0
  106. package/esm/HeatmapPremium/webgl/HeatmapWebGLPlot.d.ts +6 -0
  107. package/esm/HeatmapPremium/webgl/HeatmapWebGLPlot.js +178 -0
  108. package/esm/HeatmapPremium/webgl/HeatmapWebGLRenderer.d.ts +4 -0
  109. package/esm/HeatmapPremium/webgl/HeatmapWebGLRenderer.js +17 -0
  110. package/esm/HeatmapPremium/webgl/shaders.d.ts +3 -0
  111. package/esm/HeatmapPremium/webgl/shaders.js +71 -0
  112. package/esm/HeatmapPremium/webgl/useHeatmapPlotData.d.ts +12 -0
  113. package/esm/HeatmapPremium/webgl/useHeatmapPlotData.js +51 -0
  114. package/esm/HeatmapPremium/webgl/utils.d.ts +8 -0
  115. package/esm/HeatmapPremium/webgl/utils.js +41 -0
  116. package/esm/index.d.ts +5 -1
  117. package/esm/index.js +5 -2
  118. package/esm/internals/plugins/allPlugins.d.ts +1 -1
  119. package/esm/models/seriesType/rangeBar.d.ts +1 -1
  120. package/esm/typeOverloads/modules.d.ts +2 -1
  121. package/esm/utils/webgl/parseColor.d.ts +5 -0
  122. package/esm/utils/webgl/parseColor.js +78 -0
  123. package/esm/utils/webgl/useWebGLResizeObserver.d.ts +7 -0
  124. package/esm/utils/webgl/useWebGLResizeObserver.js +64 -0
  125. package/index.d.ts +5 -1
  126. package/index.js +33 -1
  127. package/internals/plugins/allPlugins.d.ts +1 -1
  128. package/models/seriesType/rangeBar.d.ts +1 -1
  129. package/package.json +9 -9
  130. package/typeOverloads/modules.d.ts +2 -1
  131. package/utils/webgl/parseColor.d.ts +5 -0
  132. package/utils/webgl/parseColor.js +84 -0
  133. package/utils/webgl/useWebGLResizeObserver.d.ts +7 -0
  134. package/utils/webgl/useWebGLResizeObserver.js +70 -0
@@ -0,0 +1,19 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
+ const _excluded = ["chartDataProviderProProps", "heatmapPlotProps"];
4
+ import { useHeatmapProps } from '@mui/x-charts-pro/internals';
5
+ export function useHeatmapPremiumProps(props) {
6
+ const _useHeatmapProps = useHeatmapProps(props),
7
+ {
8
+ chartDataProviderProProps,
9
+ heatmapPlotProps
10
+ } = _useHeatmapProps,
11
+ other = _objectWithoutPropertiesLoose(_useHeatmapProps, _excluded);
12
+ const heatmapPlotPremiumProps = _extends({}, heatmapPlotProps, {
13
+ renderer: props.renderer ?? 'svg-single'
14
+ });
15
+ return _extends({}, other, {
16
+ heatmapPlotPremiumProps,
17
+ chartDataProviderPremiumProps: chartDataProviderProProps
18
+ });
19
+ }
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ export declare function HeatmapWebGLPlot({
3
+ borderRadius
4
+ }: {
5
+ borderRadius?: number;
6
+ }): React.JSX.Element | null;
@@ -0,0 +1,178 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { useDrawingArea, useXScale, useYScale } from '@mui/x-charts/hooks';
5
+ import { useWebGLContext } from '@mui/x-charts/internals';
6
+ import useEventCallback from '@mui/utils/useEventCallback';
7
+ import { useHeatmapSeriesContext } from "../../hooks/index.js";
8
+ import { heatmapFragmentShaderSourceNoBorderRadius, heatmapFragmentShaderSourceWithBorderRadius, heatmapVertexShaderSource } from "./shaders.js";
9
+ import { useWebGLResizeObserver } from "../../utils/webgl/useWebGLResizeObserver.js";
10
+ import { attachShader, bindQuadBuffer, compileShader, logWebGLErrors, uploadQuadBuffer } from "./utils.js";
11
+ import { useHeatmapPlotData } from "./useHeatmapPlotData.js";
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ export function HeatmapWebGLPlot({
14
+ borderRadius
15
+ }) {
16
+ const gl = useWebGLContext();
17
+ const series = useHeatmapSeriesContext();
18
+ const seriesToDisplay = series?.series[series.seriesOrder[0]];
19
+ if (!gl || !seriesToDisplay) {
20
+ return null;
21
+ }
22
+ return /*#__PURE__*/_jsx(HeatmapWebGLPlotImpl, {
23
+ gl: gl,
24
+ borderRadius: borderRadius ?? 0,
25
+ series: seriesToDisplay
26
+ });
27
+ }
28
+ function HeatmapWebGLPlotImpl(props) {
29
+ const {
30
+ gl,
31
+ borderRadius,
32
+ series
33
+ } = props;
34
+ const drawingArea = useDrawingArea();
35
+ const xScale = useXScale();
36
+ const yScale = useYScale();
37
+ const [vertexShader] = React.useState(() => compileShader(gl, heatmapVertexShaderSource, gl.VERTEX_SHADER));
38
+ const [program] = React.useState(() => {
39
+ const p = gl.createProgram();
40
+ gl.attachShader(p, vertexShader);
41
+ return p;
42
+ });
43
+ const [quadBuffer] = React.useState(() => uploadQuadBuffer(gl));
44
+ const dataLength = series.data.length;
45
+ const renderScheduledRef = React.useRef(false);
46
+ const render = React.useCallback(() => {
47
+ renderScheduledRef.current = false;
48
+
49
+ // Clear and draw
50
+ gl.clearColor(0, 0, 0, 0.0);
51
+ gl.clear(gl.COLOR_BUFFER_BIT);
52
+ gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, 4, dataLength);
53
+ }, [dataLength, gl]);
54
+ const scheduleRender = React.useCallback(() => {
55
+ renderScheduledRef.current = true;
56
+ }, []);
57
+
58
+ // On resize render directly to avoid a frame where the canvas is blank
59
+ useWebGLResizeObserver(render);
60
+ React.useEffect(() => {
61
+ /* Enable blending for transparency
62
+ * These are global to the WebGL context and need to be set only once */
63
+ gl.enable(gl.BLEND);
64
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
65
+ }, [gl]);
66
+ const width = xScale.bandwidth();
67
+ const height = yScale.bandwidth();
68
+
69
+ // A border radius cannot be larger than half the width or height of the rectangle
70
+ const seriesBorderRadius = Math.min(borderRadius ?? 0, width / 2, height / 2);
71
+ const lastSeriesBorderRadiusRef = React.useRef(seriesBorderRadius > 0 ? 0 : 1);
72
+ const setupResolutionUniform = React.useCallback(() => {
73
+ gl.uniform2f(gl.getUniformLocation(program, 'u_resolution'), drawingArea.width, drawingArea.height);
74
+ }, [drawingArea.height, drawingArea.width, gl, program]);
75
+ const setupBorderRadiusUniform = React.useCallback(() => {
76
+ gl.uniform1f(gl.getUniformLocation(program, 'u_borderRadius'), seriesBorderRadius);
77
+ }, [gl, program, seriesBorderRadius]);
78
+ const setupRectDimensionsUniform = React.useCallback(() => {
79
+ gl.uniform2f(gl.getUniformLocation(program, 'u_dimensions'), width, height);
80
+ }, [gl, height, program, width]);
81
+ const setupUniformsEvent = useEventCallback(() => {
82
+ bindQuadBuffer(gl, program, quadBuffer);
83
+ setupBorderRadiusUniform();
84
+ setupResolutionUniform();
85
+ setupRectDimensionsUniform();
86
+ });
87
+ const plotData = useHeatmapPlotData(drawingArea, series, xScale, yScale);
88
+ const setupAttributes = React.useCallback(() => {
89
+ const {
90
+ centers,
91
+ colors,
92
+ saturations
93
+ } = plotData;
94
+
95
+ // Upload rectangle centers
96
+ const centerBuffer = gl.createBuffer();
97
+ gl.bindBuffer(gl.ARRAY_BUFFER, centerBuffer);
98
+ gl.bufferData(gl.ARRAY_BUFFER, centers, gl.STATIC_DRAW);
99
+ const aCenter = gl.getAttribLocation(program, 'a_center');
100
+ gl.enableVertexAttribArray(aCenter);
101
+ gl.vertexAttribPointer(aCenter, 2, gl.FLOAT, false, 0, 0);
102
+
103
+ // This makes the attribute instanced (one value per rectangle, not per vertex)
104
+ gl.vertexAttribDivisor(aCenter, 1);
105
+
106
+ // Upload colors
107
+ const colorBuffer = gl.createBuffer();
108
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
109
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
110
+ const aColor = gl.getAttribLocation(program, 'a_color');
111
+ gl.enableVertexAttribArray(aColor);
112
+ gl.vertexAttribPointer(aColor, 4, gl.FLOAT, false, 0, 0);
113
+ gl.vertexAttribDivisor(aColor, 1);
114
+
115
+ // Upload saturations
116
+ const saturationBuffer = gl.createBuffer();
117
+ gl.bindBuffer(gl.ARRAY_BUFFER, saturationBuffer);
118
+ gl.bufferData(gl.ARRAY_BUFFER, saturations, gl.STATIC_DRAW);
119
+ const aSaturation = gl.getAttribLocation(program, 'a_saturation');
120
+ gl.enableVertexAttribArray(aSaturation);
121
+ gl.vertexAttribPointer(aSaturation, 1, gl.FLOAT, false, 0, 0);
122
+ gl.vertexAttribDivisor(aSaturation, 1);
123
+ }, [gl, plotData, program]);
124
+ const setupAttributesEvent = useEventCallback(() => setupAttributes());
125
+ React.useEffect(() => {
126
+ const shouldAttachNewShader = lastSeriesBorderRadiusRef.current > 0 !== seriesBorderRadius > 0;
127
+ lastSeriesBorderRadiusRef.current = seriesBorderRadius;
128
+ if (shouldAttachNewShader) {
129
+ const shaderSource = seriesBorderRadius > 0 ? heatmapFragmentShaderSourceWithBorderRadius : heatmapFragmentShaderSourceNoBorderRadius;
130
+ gl.getAttachedShaders(program)?.forEach(shader => {
131
+ const shaderType = gl.getShaderParameter(shader, gl.SHADER_TYPE);
132
+ if (shaderType === gl.FRAGMENT_SHADER) {
133
+ gl.detachShader(program, shader);
134
+ gl.deleteShader(shader);
135
+ }
136
+ });
137
+ const fragmentShader = attachShader(gl, program, shaderSource, gl.FRAGMENT_SHADER);
138
+ gl.linkProgram(program);
139
+
140
+ // https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices#dont_check_shader_compile_status_unless_linking_fails
141
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
142
+ console.error(`Program linking failed: ${gl.getProgramInfoLog(program)}`);
143
+ console.error(`Vertex shader info-log: ${gl.getShaderInfoLog(vertexShader)}`);
144
+ console.error(`Fragment shader info-log: ${gl.getShaderInfoLog(fragmentShader)}`);
145
+ }
146
+
147
+ // Not a hook
148
+ // eslint-disable-next-line react-compiler/react-compiler
149
+ gl.useProgram(program);
150
+ logWebGLErrors(gl);
151
+ setupUniformsEvent();
152
+ setupAttributesEvent();
153
+ } else {
154
+ setupBorderRadiusUniform();
155
+ }
156
+ scheduleRender();
157
+ }, [gl, program, scheduleRender, seriesBorderRadius, setupBorderRadiusUniform,
158
+ // We use the event callback versions here because we only want this effect to trigger when the border radius changes
159
+ setupAttributesEvent, setupUniformsEvent, vertexShader]);
160
+ React.useEffect(() => {
161
+ setupResolutionUniform();
162
+ scheduleRender();
163
+ }, [setupResolutionUniform, scheduleRender]);
164
+ React.useEffect(() => {
165
+ setupRectDimensionsUniform();
166
+ scheduleRender();
167
+ }, [setupRectDimensionsUniform, scheduleRender]);
168
+ React.useEffect(() => {
169
+ setupAttributes();
170
+ scheduleRender();
171
+ }, [scheduleRender, setupAttributes]);
172
+ React.useEffect(() => {
173
+ if (renderScheduledRef.current) {
174
+ render();
175
+ }
176
+ });
177
+ return null;
178
+ }
@@ -0,0 +1,4 @@
1
+ import { type HeatmapRendererPlotProps } from '@mui/x-charts-pro/internals';
2
+ export declare function HeatmapWebGLRenderer({
3
+ borderRadius
4
+ }: HeatmapRendererPlotProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,17 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { useRegisterPointerInteractions, WebGLProvider } from '@mui/x-charts/internals';
5
+ import { selectorHeatmapItemAtPosition } from '@mui/x-charts-pro/internals';
6
+ import { HeatmapWebGLPlot } from "./HeatmapWebGLPlot.js";
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ export function HeatmapWebGLRenderer({
9
+ borderRadius
10
+ }) {
11
+ useRegisterPointerInteractions(selectorHeatmapItemAtPosition);
12
+ return /*#__PURE__*/_jsx(WebGLProvider, {
13
+ children: /*#__PURE__*/_jsx(HeatmapWebGLPlot, {
14
+ borderRadius: borderRadius
15
+ })
16
+ });
17
+ }
@@ -0,0 +1,3 @@
1
+ export declare const heatmapVertexShaderSource = "\n precision mediump float;\n \n attribute vec2 a_position;\n attribute vec2 a_center;\n attribute vec4 a_color;\n attribute float a_saturation;\n \n varying vec4 v_color;\n varying vec2 v_pos;\n \n uniform vec2 u_dimensions;\n uniform vec2 u_resolution;\n \n // https://tsev.dev/posts/2020-06-19-colour-correction-with-webgl/\n vec3 adjust_saturation(vec3 color, float value) {\n // https://www.w3.org/TR/WCAG21/#dfn-relative-luminance\n const vec3 luminosityFactor = vec3(0.2126, 0.7152, 0.0722);\n vec3 grayscale = vec3(dot(color, luminosityFactor));\n \n return mix(grayscale, color, 1.0 + value);\n }\n \n void main() {\n // Convert from pixels to clip space (-1 to 1)\n vec2 position = a_center + a_position * u_dimensions / 2.0;\n vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0;\n gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);\n \n v_color = vec4(adjust_saturation(a_color.rgb, a_saturation), 1.0);\n v_pos = a_position * u_dimensions / 2.0;\n }\n ";
2
+ export declare const heatmapFragmentShaderSourceNoBorderRadius = "\n precision mediump float;\n \n varying vec4 v_color;\n \n void main() {\n gl_FragColor = v_color;\n }\n ";
3
+ export declare const heatmapFragmentShaderSourceWithBorderRadius = "\n precision mediump float;\n\n varying vec4 v_color;\n varying vec2 v_pos;\n\n uniform vec2 u_dimensions;\n uniform float u_borderRadius;\n\n float roundedBoxSDF(vec2 pos, vec2 half_size, float radius) {\n vec2 q = abs(pos) - half_size + radius;\n return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius;\n }\n\n void main() {\n // Calculate distance from rounded rectangle edge\n float dist = roundedBoxSDF(v_pos, u_dimensions / 2.0, u_borderRadius);\n \n // Create smooth alpha based on distance\n float alpha = 1.0 - smoothstep(-0.5, 0.5, dist);\n \n gl_FragColor = vec4(v_color.rgb, v_color.a * alpha);\n }\n ";
@@ -0,0 +1,71 @@
1
+ // language=Glsl
2
+ export const heatmapVertexShaderSource = /* glsl */`
3
+ precision mediump float;
4
+
5
+ attribute vec2 a_position;
6
+ attribute vec2 a_center;
7
+ attribute vec4 a_color;
8
+ attribute float a_saturation;
9
+
10
+ varying vec4 v_color;
11
+ varying vec2 v_pos;
12
+
13
+ uniform vec2 u_dimensions;
14
+ uniform vec2 u_resolution;
15
+
16
+ // https://tsev.dev/posts/2020-06-19-colour-correction-with-webgl/
17
+ vec3 adjust_saturation(vec3 color, float value) {
18
+ // https://www.w3.org/TR/WCAG21/#dfn-relative-luminance
19
+ const vec3 luminosityFactor = vec3(0.2126, 0.7152, 0.0722);
20
+ vec3 grayscale = vec3(dot(color, luminosityFactor));
21
+
22
+ return mix(grayscale, color, 1.0 + value);
23
+ }
24
+
25
+ void main() {
26
+ // Convert from pixels to clip space (-1 to 1)
27
+ vec2 position = a_center + a_position * u_dimensions / 2.0;
28
+ vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0;
29
+ gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
30
+
31
+ v_color = vec4(adjust_saturation(a_color.rgb, a_saturation), 1.0);
32
+ v_pos = a_position * u_dimensions / 2.0;
33
+ }
34
+ `;
35
+
36
+ // language=Glsl
37
+ export const heatmapFragmentShaderSourceNoBorderRadius = /* glsl */`
38
+ precision mediump float;
39
+
40
+ varying vec4 v_color;
41
+
42
+ void main() {
43
+ gl_FragColor = v_color;
44
+ }
45
+ `;
46
+
47
+ // language=Glsl
48
+ export const heatmapFragmentShaderSourceWithBorderRadius = /* glsl */`
49
+ precision mediump float;
50
+
51
+ varying vec4 v_color;
52
+ varying vec2 v_pos;
53
+
54
+ uniform vec2 u_dimensions;
55
+ uniform float u_borderRadius;
56
+
57
+ float roundedBoxSDF(vec2 pos, vec2 half_size, float radius) {
58
+ vec2 q = abs(pos) - half_size + radius;
59
+ return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius;
60
+ }
61
+
62
+ void main() {
63
+ // Calculate distance from rounded rectangle edge
64
+ float dist = roundedBoxSDF(v_pos, u_dimensions / 2.0, u_borderRadius);
65
+
66
+ // Create smooth alpha based on distance
67
+ float alpha = 1.0 - smoothstep(-0.5, 0.5, dist);
68
+
69
+ gl_FragColor = vec4(v_color.rgb, v_color.a * alpha);
70
+ }
71
+ `;
@@ -0,0 +1,12 @@
1
+ import { type ScaleBand } from '@mui/x-charts-vendor/d3-scale';
2
+ import { type DefaultizedHeatmapSeriesType } from '@mui/x-charts-pro/models';
3
+ import { type ChartDrawingArea } from '@mui/x-charts/hooks';
4
+ export declare function useHeatmapPlotData(drawingArea: ChartDrawingArea, series: DefaultizedHeatmapSeriesType, xScale: ScaleBand<{
5
+ toString(): string;
6
+ }>, yScale: ScaleBand<{
7
+ toString(): string;
8
+ }>): {
9
+ centers: Float32Array<ArrayBuffer>;
10
+ colors: Float32Array<ArrayBuffer>;
11
+ saturations: Float32Array<ArrayBuffer>;
12
+ };
@@ -0,0 +1,51 @@
1
+ import * as React from 'react';
2
+ import { useZColorScale } from '@mui/x-charts/hooks';
3
+ import { selectorChartsIsFadedCallback, selectorChartsIsHighlightedCallback, useStore } from '@mui/x-charts/internals';
4
+ import { parseColor } from "../../utils/webgl/parseColor.js";
5
+ export function useHeatmapPlotData(drawingArea, series, xScale, yScale) {
6
+ const width = xScale.bandwidth();
7
+ const height = yScale.bandwidth();
8
+ const colorScale = useZColorScale();
9
+ const store = useStore();
10
+ const isHighlighted = store.use(selectorChartsIsHighlightedCallback);
11
+ const isFaded = store.use(selectorChartsIsFadedCallback);
12
+ return React.useMemo(() => {
13
+ const centers = new Float32Array(series.data.length * 2);
14
+ const colors = new Float32Array(series.data.length * 4);
15
+ const saturations = new Float32Array(series.data.length);
16
+ const xDomain = xScale.domain();
17
+ const yDomain = yScale.domain();
18
+ for (let dataIndex = 0; dataIndex < series.data.length; dataIndex += 1) {
19
+ const [xIndex, yIndex, value] = series.data[dataIndex];
20
+ const x = xScale(xDomain[xIndex]);
21
+ const y = yScale(yDomain[yIndex]);
22
+ const color = colorScale?.(value);
23
+ if (x === undefined || y === undefined || !color) {
24
+ continue;
25
+ }
26
+ centers[dataIndex * 2] = x + width / 2 - drawingArea.left;
27
+ centers[dataIndex * 2 + 1] = y + height / 2 - drawingArea.top;
28
+ const rgbColor = parseColor(color);
29
+ colors[dataIndex * 4] = rgbColor[0];
30
+ colors[dataIndex * 4 + 1] = rgbColor[1];
31
+ colors[dataIndex * 4 + 2] = rgbColor[2];
32
+ colors[dataIndex * 4 + 3] = 1.0;
33
+ if (isHighlighted({
34
+ seriesId: series.id,
35
+ dataIndex
36
+ })) {
37
+ saturations[dataIndex] = 0.2;
38
+ } else if (isFaded({
39
+ seriesId: series.id,
40
+ dataIndex
41
+ })) {
42
+ saturations[dataIndex] = -0.2;
43
+ }
44
+ }
45
+ return {
46
+ centers,
47
+ colors,
48
+ saturations
49
+ };
50
+ }, [colorScale, drawingArea.left, drawingArea.top, height, isFaded, isHighlighted, series.data, series.id, width, xScale, yScale]);
51
+ }
@@ -0,0 +1,8 @@
1
+ export declare function compileShader(gl: WebGL2RenderingContext, shaderSource: string, shaderType: WebGL2RenderingContext['FRAGMENT_SHADER'] | WebGL2RenderingContext['VERTEX_SHADER']): WebGLShader;
2
+ export declare function uploadQuadBuffer(gl: WebGL2RenderingContext): WebGLBuffer;
3
+ export declare function bindQuadBuffer(gl: WebGL2RenderingContext, program: WebGLProgram, quadBuffer: WebGLBuffer): void;
4
+ export declare function attachShader(gl: WebGL2RenderingContext, program: WebGLProgram, shaderSource: string, shaderType: WebGL2RenderingContext['FRAGMENT_SHADER'] | WebGL2RenderingContext['VERTEX_SHADER']): WebGLShader;
5
+ /**
6
+ * Logs WebGL errors to the console in development mode.
7
+ */
8
+ export declare function logWebGLErrors(gl: WebGL2RenderingContext): void;
@@ -0,0 +1,41 @@
1
+ export function compileShader(gl, shaderSource, shaderType) {
2
+ const shader = gl.createShader(shaderType);
3
+ gl.shaderSource(shader, shaderSource);
4
+ gl.compileShader(shader);
5
+ return shader;
6
+ }
7
+ export function uploadQuadBuffer(gl) {
8
+ const quadVertices = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);
9
+ const buffer = gl.createBuffer();
10
+ gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
11
+ gl.bufferData(gl.ARRAY_BUFFER, quadVertices, gl.STATIC_DRAW);
12
+ return buffer;
13
+ }
14
+ export function bindQuadBuffer(gl, program, quadBuffer) {
15
+ gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
16
+ const aPosition = gl.getAttribLocation(program, 'a_position');
17
+ gl.enableVertexAttribArray(aPosition);
18
+ gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);
19
+ }
20
+ export function attachShader(gl, program, shaderSource, shaderType) {
21
+ const shader = gl.createShader(shaderType);
22
+ gl.shaderSource(shader, shaderSource);
23
+ gl.compileShader(shader);
24
+ gl.attachShader(program, shader);
25
+ return shader;
26
+ }
27
+
28
+ /**
29
+ * Logs WebGL errors to the console in development mode.
30
+ */
31
+ export function logWebGLErrors(gl) {
32
+ /* Only log errors in dev because it has a performance cost:
33
+ * https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices#avoid_blocking_api_calls_in_production */
34
+ if (process.env.NODE_ENV !== 'production') {
35
+ let error = gl.getError();
36
+ while (error !== gl.NO_ERROR) {
37
+ console.error('WebGL error:', error);
38
+ error = gl.getError();
39
+ }
40
+ }
41
+ }
package/esm/index.d.ts CHANGED
@@ -22,6 +22,8 @@ export * from '@mui/x-charts/ChartsSurface';
22
22
  export * from '@mui/x-charts/ChartDataProvider';
23
23
  export * from '@mui/x-charts/ChartsLabel';
24
24
  export * from '@mui/x-charts-pro/Heatmap';
25
+ export { ChartsContainerPro } from '@mui/x-charts-pro/ChartsContainerPro';
26
+ export type { ChartsContainerProProps } from '@mui/x-charts-pro/ChartsContainerPro';
25
27
  export { ChartContainerPro } from '@mui/x-charts-pro/ChartContainerPro';
26
28
  export type { ChartContainerProProps } from '@mui/x-charts-pro/ChartContainerPro';
27
29
  export * from '@mui/x-charts-pro/ChartDataProviderPro';
@@ -41,5 +43,7 @@ export * from "./models/index.js";
41
43
  export * from "./plugins/index.js";
42
44
  export * from "./ChartsRenderer/index.js";
43
45
  export * from "./ChartDataProviderPremium/index.js";
46
+ export * from "./ChartsContainerPremium/index.js";
44
47
  export * from "./ChartContainerPremium/index.js";
45
- export * from "./BarChartPremium/index.js";
48
+ export * from "./BarChartPremium/index.js";
49
+ export * from "./HeatmapPremium/index.js";
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-charts-premium v8.26.0
2
+ * @mui/x-charts-premium v9.0.0-alpha.0
3
3
  *
4
4
  * @license SEE LICENSE IN LICENSE
5
5
  * This source code is licensed under the SEE LICENSE IN LICENSE license found in the
@@ -33,6 +33,7 @@ export * from '@mui/x-charts/ChartsLabel';
33
33
 
34
34
  // Pro components
35
35
  export * from '@mui/x-charts-pro/Heatmap';
36
+ export { ChartsContainerPro } from '@mui/x-charts-pro/ChartsContainerPro';
36
37
  export { ChartContainerPro } from '@mui/x-charts-pro/ChartContainerPro';
37
38
  export * from '@mui/x-charts-pro/ChartDataProviderPro';
38
39
  export * from '@mui/x-charts-pro/ScatterChartPro';
@@ -57,5 +58,7 @@ export * from "./plugins/index.js";
57
58
  // Premium components
58
59
  export * from "./ChartsRenderer/index.js";
59
60
  export * from "./ChartDataProviderPremium/index.js";
61
+ export * from "./ChartsContainerPremium/index.js";
60
62
  export * from "./ChartContainerPremium/index.js";
61
- export * from "./BarChartPremium/index.js";
63
+ export * from "./BarChartPremium/index.js";
64
+ export * from "./HeatmapPremium/index.js";
@@ -1,6 +1,6 @@
1
1
  import { type ChartSeriesType, type ConvertSignaturesIntoPlugins, type UseChartCartesianAxisSignature, type UseChartTooltipSignature, type UseChartInteractionSignature, type UseChartZAxisSignature, type UseChartHighlightSignature, type UseChartPolarAxisSignature, type UseChartBrushSignature, type UseChartVisibilityManagerSignature } from '@mui/x-charts/internals';
2
2
  import { type UseChartProExportSignature, type UseChartProZoomSignature } from '@mui/x-charts-pro/plugins';
3
- export type AllPluginSignatures<TSeries extends ChartSeriesType = ChartSeriesType> = [UseChartZAxisSignature, UseChartBrushSignature, UseChartTooltipSignature, UseChartInteractionSignature, UseChartCartesianAxisSignature<TSeries>, UseChartPolarAxisSignature<TSeries>, UseChartHighlightSignature, UseChartVisibilityManagerSignature<TSeries>, UseChartProZoomSignature, UseChartProExportSignature];
3
+ export type AllPluginSignatures<TSeries extends ChartSeriesType = ChartSeriesType> = [UseChartZAxisSignature, UseChartBrushSignature, UseChartTooltipSignature<TSeries>, UseChartInteractionSignature, UseChartCartesianAxisSignature<TSeries>, UseChartPolarAxisSignature<TSeries>, UseChartHighlightSignature, UseChartVisibilityManagerSignature<TSeries>, UseChartProZoomSignature, UseChartProExportSignature];
4
4
  export type AllPluginsType<TSeries extends ChartSeriesType = ChartSeriesType> = ConvertSignaturesIntoPlugins<AllPluginSignatures<TSeries>>;
5
5
  export declare const ALL_PLUGINS: (import("@mui/x-charts/internals").ChartPlugin<UseChartZAxisSignature> | import("@mui/x-charts/internals").ChartPlugin<UseChartBrushSignature> | import("@mui/x-charts/internals").ChartPlugin<UseChartInteractionSignature> | import("@mui/x-charts/internals").ChartPlugin<UseChartHighlightSignature> | import("@mui/x-charts/internals").ChartPlugin<UseChartProZoomSignature> | import("@mui/x-charts/internals").ChartPlugin<UseChartProExportSignature> | import("@mui/x-charts/internals").ChartPlugin<UseChartTooltipSignature<any>> | import("@mui/x-charts/internals").ChartPlugin<UseChartCartesianAxisSignature<any>> | import("@mui/x-charts/internals").ChartPlugin<UseChartPolarAxisSignature<any>> | import("@mui/x-charts/internals").ChartPlugin<UseChartVisibilityManagerSignature<any>>)[];
6
6
  export type DefaultPluginSignatures<TSeries extends ChartSeriesType = ChartSeriesType> = [UseChartZAxisSignature, UseChartBrushSignature, UseChartTooltipSignature, UseChartInteractionSignature, UseChartCartesianAxisSignature<TSeries>, UseChartPolarAxisSignature<TSeries>, UseChartHighlightSignature, UseChartVisibilityManagerSignature<TSeries>, UseChartProZoomSignature, UseChartProExportSignature];
@@ -2,7 +2,7 @@ import { type CartesianSeriesType, type CommonDefaultizedProps, type CommonSerie
2
2
  import { type DefaultizedProps } from '@mui/x-internals/types';
3
3
  /** [start, end] */
4
4
  export type RangeBarValueType = [number, number];
5
- export interface RangeBarSeriesType extends CommonSeriesType<RangeBarValueType | null>, CartesianSeriesType {
5
+ export interface RangeBarSeriesType extends CommonSeriesType<RangeBarValueType | null, 'rangeBar'>, CartesianSeriesType {
6
6
  type: 'rangeBar';
7
7
  /**
8
8
  * Data associated to each range bar.
@@ -1,5 +1,5 @@
1
1
  import type { DefaultizedProps, MakeRequired } from '@mui/x-internals/types';
2
- import type { SeriesColor } from '@mui/x-charts/internals';
2
+ import type { CommonHighlightScope, SeriesColor } from '@mui/x-charts/internals';
3
3
  import type { RangeBarValueType, RangeBarSeriesType } from "../models/index.js";
4
4
  import type { DefaultizedRangeBarSeriesType, RangeBarItemIdentifier } from "../models/seriesType/rangeBar.js";
5
5
  import type { BarSeries } from "../BarChart/index.js";
@@ -17,6 +17,7 @@ declare module '@mui/x-charts/internals' {
17
17
  itemIdentifierWithData: RangeBarItemIdentifier;
18
18
  valueType: RangeBarValueType | null;
19
19
  axisType: 'cartesian';
20
+ highlightScope: CommonHighlightScope;
20
21
  };
21
22
  }
22
23
  }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Parse color string to RGBA object. Each channel is normalized to [0, 1].
3
+ * This function does not work in SSR.
4
+ */
5
+ export declare function parseColor(color: string): [number, number, number, number];
@@ -0,0 +1,78 @@
1
+ const colorCache = new Map();
2
+
3
+ /**
4
+ * Parse color string to RGBA object. Each channel is normalized to [0, 1].
5
+ * This function does not work in SSR.
6
+ */
7
+ export function parseColor(color) {
8
+ const cached = colorCache.get(color);
9
+ if (cached) {
10
+ return cached;
11
+ }
12
+ let result = parseColorUsingRegex(color);
13
+ if (result == null) {
14
+ result = parseRgbaColor(color);
15
+ }
16
+ if (result == null) {
17
+ result = parseColorUsingCanvas(color);
18
+ }
19
+ colorCache.set(color, result);
20
+ return result;
21
+ }
22
+
23
+ // Validates hex color formats (#RGB, #RRGGBB, #RRGGBBAA)
24
+ const hexRegex = /^[0-9A-Fa-f]{3}$|^[0-9A-Fa-f]{6}$|^[0-9A-Fa-f]{8}$/;
25
+ function parseColorUsingRegex(color) {
26
+ if (color.startsWith('#')) {
27
+ color = color.slice(1);
28
+ }
29
+ if (!hexRegex.test(color)) {
30
+ return null; // Invalid hex color
31
+ }
32
+ if (color.length === 3) {
33
+ color = color.split('').map(char => char + char).join('');
34
+ }
35
+ const r = parseInt(color.slice(0, 2), 16) / 255;
36
+ const g = parseInt(color.slice(2, 4), 16) / 255;
37
+ const b = parseInt(color.slice(4, 6), 16) / 255;
38
+ const a = color.length === 8 ? parseInt(color.substring(6, 8), 16) / 255 : 1;
39
+ return [r, g, b, a];
40
+ }
41
+
42
+ // Parses rgb() and rgba() formats
43
+ const rgbaRegex = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+)\s*)?\)$/i;
44
+ function parseRgbaColor(color) {
45
+ const match = color.match(rgbaRegex);
46
+ if (!match) {
47
+ return null;
48
+ }
49
+ const r = parseInt(match[1], 10);
50
+ const g = parseInt(match[2], 10);
51
+ const b = parseInt(match[3], 10);
52
+ const a = match[4] !== undefined ? parseFloat(match[4]) : 1;
53
+ if (r > 255 || g > 255 || b > 255) {
54
+ return null;
55
+ }
56
+ if (a < 0 || a > 1) {
57
+ return null;
58
+ }
59
+ return [r / 255, g / 255, b / 255, a];
60
+ }
61
+ let canvas;
62
+ function parseColorUsingCanvas(color) {
63
+ if (!canvas) {
64
+ if ('OffscreenCanvas' in window) {
65
+ canvas = new OffscreenCanvas(1, 1);
66
+ } else {
67
+ canvas = document.createElement('canvas');
68
+ canvas.width = 1;
69
+ canvas.height = 1;
70
+ }
71
+ }
72
+ const ctx = canvas.getContext('2d');
73
+ ctx.fillStyle = color;
74
+ ctx.fillRect(0, 0, 1, 1);
75
+ const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;
76
+ const result = [r / 255, g / 255, b / 255, a / 255];
77
+ return result;
78
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * This hook calls the provided `onResize` callback whenever the WebGL canvas is resized.
3
+ * It detects size changes when the element is resized, the browser zoom updates or the device pixel ratio changes.
4
+ * These last two conditions aren't supported by Safari, so `onResize` won't be called in these cases on Safari.
5
+ * @param onResize
6
+ */
7
+ export declare function useWebGLResizeObserver(onResize: () => void): void;
@@ -0,0 +1,64 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { useWebGLContext } from '@mui/x-charts/internals';
5
+ function getDevicePixelContentBoxSize(entry) {
6
+ // Safari does not support devicePixelContentBoxSize
7
+ if (entry.devicePixelContentBoxSize) {
8
+ return {
9
+ width: entry.devicePixelContentBoxSize[0].inlineSize,
10
+ height: entry.devicePixelContentBoxSize[0].blockSize
11
+ };
12
+ }
13
+ // These values not correct, but they're as close as you can get in Safari
14
+ return {
15
+ width: entry.contentBoxSize[0].inlineSize * devicePixelRatio,
16
+ height: entry.contentBoxSize[0].blockSize * devicePixelRatio
17
+ };
18
+ }
19
+
20
+ /**
21
+ * This hook calls the provided `onResize` callback whenever the WebGL canvas is resized.
22
+ * It detects size changes when the element is resized, the browser zoom updates or the device pixel ratio changes.
23
+ * These last two conditions aren't supported by Safari, so `onResize` won't be called in these cases on Safari.
24
+ * @param onResize
25
+ */
26
+ export function useWebGLResizeObserver(onResize) {
27
+ const gl = useWebGLContext();
28
+ React.useEffect(() => {
29
+ const canvas = gl?.canvas;
30
+ if (!(canvas instanceof HTMLCanvasElement)) {
31
+ return undefined;
32
+ }
33
+ const observer = new ResizeObserver(entries => {
34
+ for (const entry of entries) {
35
+ const {
36
+ width,
37
+ height
38
+ } = getDevicePixelContentBoxSize(entry);
39
+ canvas.width = Math.max(1, width);
40
+ canvas.height = Math.max(1, height);
41
+
42
+ // Update WebGL viewport
43
+ gl?.viewport(0, 0, width, height);
44
+ onResize();
45
+ }
46
+ });
47
+ try {
48
+ /* We use 'device-pixel-content-box' to observe the size of the canvas in device pixels, rather than CSS pixels.
49
+ * This ensures that we correctly handle high-DPI displays and browser zoom.
50
+ * However, this is not supported in Safari, which throws, so we fall back to 'content-box'.
51
+ * WebKit Bug: https://www2.webkit.org/show_bug.cgi?id=219005 */
52
+ observer.observe(canvas, {
53
+ box: 'device-pixel-content-box'
54
+ });
55
+ } catch {
56
+ observer.observe(canvas, {
57
+ box: 'content-box'
58
+ });
59
+ }
60
+ return () => {
61
+ observer.disconnect();
62
+ };
63
+ }, [gl, gl?.canvas, onResize]);
64
+ }