From b636e5cbec7ce2725af0f82cd8fd182272e01418 Mon Sep 17 00:00:00 2001 From: plouc Date: Fri, 7 Jan 2022 07:02:28 +0900 Subject: [PATCH] feat(heatmap): update the website documentation according to API changes and additions --- .../src/data/components/heatmap/mapper.tsx | 3 +- website/src/data/components/heatmap/props.ts | 426 +++++++++++----- .../pages/heatmap/{canvas.js => canvas.tsx} | 0 website/src/pages/heatmap/index.js | 167 ------- website/src/pages/heatmap/index.tsx | 464 ++++++++++++++++++ 5 files changed, 760 insertions(+), 300 deletions(-) rename website/src/pages/heatmap/{canvas.js => canvas.tsx} (100%) delete mode 100644 website/src/pages/heatmap/index.js create mode 100644 website/src/pages/heatmap/index.tsx diff --git a/website/src/data/components/heatmap/mapper.tsx b/website/src/data/components/heatmap/mapper.tsx index 9c343af3c5..006de5c795 100644 --- a/website/src/data/components/heatmap/mapper.tsx +++ b/website/src/data/components/heatmap/mapper.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { settingsMapper, mapAxis } from '../../../lib/settings' +import { settingsMapper, mapAxis, mapFormat } from '../../../lib/settings' const CustomCell = ({ value, @@ -40,6 +40,7 @@ const CustomCell = ({ export default settingsMapper( { + valueFormat: mapFormat, cellShape: value => { if (value === `Custom(props) => (…)`) return CustomCell return value diff --git a/website/src/data/components/heatmap/props.ts b/website/src/data/components/heatmap/props.ts index 977d2acb2d..d2db49b846 100644 --- a/website/src/data/components/heatmap/props.ts +++ b/website/src/data/components/heatmap/props.ts @@ -1,7 +1,12 @@ -// @ts-ignore -import { HeatMapDefaultProps as defaults } from '@nivo/heatmap' +import { commonDefaultProps as defaults, svgDefaultProps as svgDefaults } from '@nivo/heatmap' import { themeProperty, motionProperties, groupProperties } from '../../../lib/componentProperties' -import { chartDimensions, chartGrid, axes, isInteractive } from '../../../lib/chart-properties' +import { + chartDimensions, + chartGrid, + axes, + isInteractive, + commonAccessibilityProps, +} from '../../../lib/chart-properties' import { ChartProperty, Flavor } from '../../../types' const allFlavors: Flavor[] = ['svg', 'canvas', 'api'] @@ -10,48 +15,18 @@ const props: ChartProperty[] = [ { key: 'data', group: 'Base', - flavors: allFlavors, help: 'Chart data.', - type: 'object[]', + type: 'HeatMapSerie[]', required: true, }, - { - key: 'indexBy', - group: 'Base', - flavors: allFlavors, - help: 'Key to use to index the data.', - description: ` - Key to use to index the data, - this key must exist in each data item. - You can also provide a function which will - receive the data item and must return - the desired index - `, - type: 'string | Function', - required: false, - defaultValue: defaults.indexBy, - }, - { - key: 'keys', - group: 'Base', - flavors: allFlavors, - help: 'Keys to use to determine each serie.', - type: 'string[]', - required: false, - defaultValue: defaults.keys, - }, { key: 'minValue', - help: 'Minimum value.', - flavors: allFlavors, description: ` - Minimum value. If 'auto', will pick the lowest value in the provided data set. Should be overriden if your data set does not contain desired lower bound value. `, - required: false, defaultValue: defaults.minValue, type: `number | 'auto'`, group: 'Base', @@ -65,15 +40,13 @@ const props: ChartProperty[] = [ }, { key: 'maxValue', - help: 'Maximum value.', flavors: allFlavors, description: ` - Maximum value. If 'auto', will pick the highest value + If 'auto', will pick the highest value in the provided data set. Should be overriden if your data set does not contain desired higher bound value. `, - required: false, defaultValue: defaults.maxValue, type: `number | 'auto'`, group: 'Base', @@ -85,149 +58,176 @@ const props: ChartProperty[] = [ max: 100, }, }, + { + key: 'valueFormat', + group: 'Base', + help: 'Optional formatter for values.', + description: ` + The formatted value can then be used for labels & tooltips. + + Under the hood, nivo uses [d3-format](https://github.com/d3/d3-format), + please have a look at it for available formats, you can also pass a function + which will receive the raw value and should return the formatted one. + `, + type: 'string | (value: number) => string | number', + control: { type: 'valueFormat' }, + }, + ...chartDimensions(allFlavors), { key: 'forceSquare', help: 'Force square cells (width = height).', - flavors: allFlavors, - required: false, defaultValue: defaults.forceSquare, type: 'boolean', control: { type: 'switch' }, group: 'Base', }, { - key: 'sizeVariation', - help: 'Cell size variation.', - flavors: allFlavors, - description: `Size variation (0~1), if value is 0 size won't be affected. If you use for example the value 0.3, cell width/height will vary between 0.7~1 according to its corresponding value.`, - required: false, - defaultValue: defaults.sizeVariation, + key: 'xOuterPadding', + defaultValue: defaults.xOuterPadding, type: 'number', group: 'Base', control: { type: 'range', min: 0, max: 1, - step: 0.02, + step: 0.05, }, }, { - key: 'padding', - help: 'Padding.', - flavors: allFlavors, - required: false, - defaultValue: defaults.padding, + key: 'xInnerPadding', + defaultValue: defaults.xInnerPadding, type: 'number', group: 'Base', control: { type: 'range', min: 0, - max: 36, - unit: 'px', + max: 1, + step: 0.05, }, }, - ...chartDimensions(allFlavors), - themeProperty(['svg', 'canvas', 'api']), { - key: 'cellShape', - help: `Cell shape/component.`, + key: 'yOuterPadding', flavors: allFlavors, - description: ` - Cell shape, can be one of: \`'rect'\`, \`'circle'\`, - if a function is provided, it must return - a valid SVG element and will receive - the following props: - \`\`\` - { - value: number, - x: number, - y: number, - width: number, - height: number, - color: string, - opacity: number, - borderWidth: number, - borderColor: string, - textColor: string, - } - \`\`\` - `, - type: 'string | Function', - required: false, - defaultValue: defaults.cellShape, - group: 'Style', + defaultValue: defaults.yOuterPadding, + type: 'number', + group: 'Base', control: { - type: 'choices', - choices: ['rect', 'circle', 'Custom(props) => (…)'].map(key => ({ - label: key, - value: key, - })), + type: 'range', + min: 0, + max: 1, + step: 0.05, + }, + }, + { + key: 'yInnerPadding', + defaultValue: defaults.yInnerPadding, + type: 'number', + group: 'Base', + control: { + type: 'range', + min: 0, + max: 1, + step: 0.05, }, }, + { + key: 'sizeVariation', + help: 'Cell size variation.', + description: `Size variation (0~1), if value is 0 size won't be affected. If you use for example the value 0.3, cell width/height will vary between 0.7~1 according to its corresponding value.`, + defaultValue: defaults.sizeVariation, + type: 'number', + group: 'Base', + control: { + type: 'range', + min: 0, + max: 1, + step: 0.02, + }, + }, + themeProperty(allFlavors), { key: 'colors', - help: 'Defines color range.', - flavors: allFlavors, - type: 'string | Function | string[]', - required: false, - defaultValue: 'nivo', - control: { type: 'quantizeColors' }, group: 'Style', + type: 'ContinuousColorScaleConfig | ((datum) => string)', + control: { + type: 'continuous_colors', + }, }, { key: 'cellOpacity', - help: 'Cell opacity (0~1).', - flavors: allFlavors, - required: false, + group: 'Style', + defaultValue: defaults.cellOpacity, + type: 'number', + control: { type: 'opacity' }, + }, + { + key: 'activeCellOpacity', + group: 'Style', + flavors: ['svg', 'canvas'], + defaultValue: defaults.cellOpacity, + type: 'number', + control: { type: 'opacity' }, + }, + { + key: 'inactiveCellOpacity', + group: 'Style', + flavors: ['svg', 'canvas'], defaultValue: defaults.cellOpacity, type: 'number', control: { type: 'opacity' }, + }, + { + key: 'borderRadius', group: 'Style', + help: 'Cell border radius, when using `rect`.', + flavors: ['svg', 'api'], + defaultValue: svgDefaults.borderRadius, + type: 'number', + control: { type: 'range', min: 0, max: 16 }, }, { - key: 'cellBorderWidth', + key: 'borderWidth', + group: 'Style', help: 'Cell border width.', - flavors: allFlavors, - required: false, - defaultValue: defaults.cellBorderWidth, + defaultValue: defaults.borderWidth, type: 'number', control: { type: 'lineWidth' }, - group: 'Style', }, { - key: 'cellBorderColor', + key: 'borderColor', + group: 'Style', help: 'Method to compute cell border color.', - flavors: allFlavors, description: ` how to compute cell border color, [see dedicated documentation](self:/guides/colors). `, - type: 'string | object | Function', - required: false, - defaultValue: defaults.cellBorderColor, + type: 'InheritedColorConfig', + defaultValue: defaults.borderColor, control: { type: 'inheritedColor' }, - group: 'Style', }, { key: 'enableLabels', help: 'Enable/disable labels.', - flavors: allFlavors, type: 'boolean', - required: false, defaultValue: defaults.enableLabels, control: { type: 'switch' }, group: 'Labels', }, + { + key: 'label', + help: 'Define what to use as a label.', + type: 'PropertyAccessor', + defaultValue: defaults.label, + group: 'Labels', + }, { key: 'labelTextColor', help: 'Method to compute label text color.', - flavors: allFlavors, description: ` how to compute label text color, [see dedicated documentation](self:/guides/colors). `, type: 'string | object | Function', - required: false, defaultValue: defaults.labelTextColor, control: { type: 'inheritedColor' }, group: 'Labels', @@ -238,6 +238,189 @@ const props: ChartProperty[] = [ yDefault: defaults.enableGridY, }), ...axes({ flavors: allFlavors }), + { + key: 'legends', + group: 'Legends', + type: `ContinuousColorsLegendProps[]`, + control: { + type: 'array', + shouldCreate: true, + shouldRemove: true, + props: [ + { + key: 'anchor', + type: 'LegendAnchor', + control: { type: 'boxAnchor' }, + }, + { + key: 'translateX', + type: 'number', + control: { + type: 'range', + min: -200, + max: 200, + }, + }, + { + key: 'translateY', + type: 'number', + control: { + type: 'range', + min: -200, + max: 200, + }, + }, + { + key: 'length', + type: 'number', + control: { + type: 'range', + min: 60, + max: 500, + }, + }, + { + key: 'thickness', + type: 'number', + control: { + type: 'range', + min: 6, + max: 32, + }, + }, + { + key: 'direction', + type: `'row' | 'column'`, + control: { + type: 'radio', + choices: [ + { + label: 'row', + value: 'row', + }, + { + label: 'column', + value: 'column', + }, + ], + }, + }, + { + key: 'tickPosition', + type: `'before' | 'after'`, + control: { + type: 'radio', + choices: [ + { + label: 'before', + value: 'before', + }, + { + label: 'after', + value: 'after', + }, + ], + }, + }, + { + key: 'tickSize', + type: 'number', + control: { + type: 'range', + min: 0, + max: 12, + }, + }, + { + key: 'tickSpacing', + type: 'number', + control: { + type: 'range', + min: 0, + max: 12, + }, + }, + { + key: 'tickOverlap', + type: 'boolean', + control: { type: 'switch' }, + }, + { + key: 'title', + type: 'string', + control: { type: 'text' }, + }, + { + key: 'titleAlign', + type: `'start' | 'middle' | 'end'`, + control: { + type: 'radio', + choices: [ + { + label: 'start', + value: 'start', + }, + { + label: 'middle', + value: 'middle', + }, + { + label: 'end', + value: 'end', + }, + ], + }, + }, + { + key: 'titleOffset', + type: 'number', + control: { + type: 'range', + min: 0, + max: 12, + }, + }, + ], + }, + }, + { + key: 'layers', + type: `('grid' | 'axes' | 'cells' | CustomLayer | CustomCanvasLayer)[]`, + group: 'Customization', + help: 'Defines the order of layers and add custom layers, please use the appropriate variant for custom layers.', + defaultValue: defaults.layers, + flavors: ['svg', 'canvas'], + }, + { + key: 'cellComponent', + group: 'Customization', + type: `'rect' | 'circle' | CellComponent`, + help: 'Cell component, the API does not support `CellComponent`.', + flavors: ['svg', 'api'], + defaultValue: 'rect', + control: { + type: 'choices', + choices: ['rect', 'circle', 'CustomCell'].map(key => ({ + label: key, + value: key, + })), + }, + }, + { + key: 'renderCell', + group: 'Customization', + type: `'rect' | 'circle' | CellCanvasRenderer`, + help: 'Cell renderer for canvas implementation.', + flavors: ['canvas'], + defaultValue: 'rect', + control: { + type: 'choices', + choices: ['rect', 'circle', 'customRenderCell'].map(key => ({ + label: key, + value: key, + })), + }, + }, isInteractive({ flavors: ['svg', 'canvas'], defaultValue: defaults.isInteractive, @@ -247,7 +430,6 @@ const props: ChartProperty[] = [ flavors: ['svg', 'canvas'], group: 'Interactivity', type: '(cell, event) => void', - required: false, help: 'onClick handler.', description: ` onClick handler, will receive node data @@ -280,7 +462,6 @@ const props: ChartProperty[] = [ - **column**: highlight the current cell's column - **rowColumn**: highlight the current cell's row & column `, - required: false, defaultValue: defaults.hoverTarget, type: 'string', group: 'Interactivity', @@ -292,26 +473,7 @@ const props: ChartProperty[] = [ })), }, }, - { - key: 'cellHoverOpacity', - flavors: ['svg', 'canvas'], - help: 'Cell opacity on hover.', - required: false, - defaultValue: defaults.cellHoverOpacity, - type: 'number', - control: { type: 'opacity' }, - group: 'Interactivity', - }, - { - key: 'cellHoverOthersOpacity', - flavors: ['svg', 'canvas'], - help: 'Cell opacity when not hovered.', - required: false, - defaultValue: defaults.cellHoverOthersOpacity, - type: 'number', - control: { type: 'opacity' }, - group: 'Interactivity', - }, + ...commonAccessibilityProps(allFlavors), ...motionProperties(['svg'], defaults, 'react-spring'), ] diff --git a/website/src/pages/heatmap/canvas.js b/website/src/pages/heatmap/canvas.tsx similarity index 100% rename from website/src/pages/heatmap/canvas.js rename to website/src/pages/heatmap/canvas.tsx diff --git a/website/src/pages/heatmap/index.js b/website/src/pages/heatmap/index.js deleted file mode 100644 index ea13a2d537..0000000000 --- a/website/src/pages/heatmap/index.js +++ /dev/null @@ -1,167 +0,0 @@ -import React from 'react' -import { ResponsiveHeatMap, HeatMapDefaultProps } from '@nivo/heatmap' -import { patternLinesDef } from '@nivo/core' -import isFunction from 'lodash/isFunction' -import { ComponentTemplate } from '../../components/components/ComponentTemplate' -import meta from '../../data/components/heatmap/meta.yml' -import mapper from '../../data/components/heatmap/mapper' -import { groups } from '../../data/components/heatmap/props' -import { generateLightDataSet } from '../../data/components/heatmap/generator' -import { graphql, useStaticQuery } from 'gatsby' - -const initialProperties = { - indexBy: 'country', - - margin: { - top: 100, - right: 60, - bottom: 60, - left: 60, - }, - - minValue: 'auto', - maxValue: 'auto', - forceSquare: true, - sizeVariation: 0, - padding: 0, - colors: 'nivo', - - axisTop: { - enable: true, - orient: 'top', - tickSize: 5, - tickPadding: 5, - tickRotation: -90, - legend: '', - legendOffset: 36, - }, - axisRight: { - enable: false, - orient: 'right', - tickSize: 5, - tickPadding: 5, - tickRotation: 0, - legend: 'country', - legendPosition: 'middle', - legendOffset: 40, - }, - axisBottom: { - enable: false, - orient: 'bottom', - tickSize: 5, - tickPadding: 5, - tickRotation: -90, - legend: '', - legendPosition: 'middle', - legendOffset: 36, - }, - axisLeft: { - enable: true, - orient: 'left', - tickSize: 5, - tickPadding: 5, - tickRotation: 0, - legend: 'country', - legendPosition: 'middle', - legendOffset: -40, - }, - - enableGridX: false, - enableGridY: false, - - cellShape: 'rect', - cellOpacity: 1, - cellBorderWidth: 0, - cellBorderColor: { - from: 'color', - modifiers: [['darker', 0.4]], - }, - - enableLabels: true, - labelTextColor: { - from: 'color', - modifiers: [['darker', 1.8]], - }, - - defs: [ - patternLinesDef('lines', { - background: 'inherit', - color: 'rgba(0, 0, 0, 0.1)', - rotation: -45, - lineWidth: 4, - spacing: 7, - }), - ], - fill: [{ match: d => false && d.value < 30, id: 'lines' }], - - animate: true, - motionConfig: 'wobbly', - motionStiffness: 80, - motionDamping: 9, - - isInteractive: true, - hoverTarget: 'cell', - cellHoverOpacity: 1, - cellHoverOthersOpacity: 0.25, -} - -const HeatMap = () => { - const { - image: { - childImageSharp: { gatsbyImageData: image }, - }, - } = useStaticQuery(graphql` - query { - image: file(absolutePath: { glob: "**/src/assets/captures/heatmap.png" }) { - childImageSharp { - gatsbyImageData(layout: FIXED, width: 700, quality: 100) - } - } - } - `) - - return ( - ({ - keys: data.keys, - ...properties, - cellShape: isFunction(properties.cellShape) - ? 'Custom(props) => (…)' - : properties.cellShape, - })} - generateData={generateLightDataSet} - getTabData={data => data.data} - image={image} - > - {(properties, data, theme, logAction) => { - return ( - { - logAction({ - type: 'click', - label: `[cell] ${cell.yKey}.${cell.xKey}: ${cell.value}`, - color: cell.color, - data: cell, - }) - }} - /> - ) - }} - - ) -} - -export default HeatMap diff --git a/website/src/pages/heatmap/index.tsx b/website/src/pages/heatmap/index.tsx new file mode 100644 index 0000000000..3742d9ba6f --- /dev/null +++ b/website/src/pages/heatmap/index.tsx @@ -0,0 +1,464 @@ +import React from 'react' +import { + ResponsiveHeatMap, + svgDefaultProps as defaults, +} from '../../../../packages/heatmap/dist/nivo-heatmap.cjs' +import { patternLinesDef } from '@nivo/core' +import isFunction from 'lodash/isFunction' +import { ComponentTemplate } from '../../components/components/ComponentTemplate' +import meta from '../../data/components/heatmap/meta.yml' +import mapper from '../../data/components/heatmap/mapper' +import { groups } from '../../data/components/heatmap/props' +import { generateLightDataSet } from '../../data/components/heatmap/generator' +import { graphql, useStaticQuery } from 'gatsby' + +const getRandomValue = () => -100 + Math.random() * 200 + +const getData = () => [ + { + id: 'japan', + data: [ + { + x: 'plane', + y: getRandomValue(), + }, + { + x: 'helicopter', + y: getRandomValue(), + }, + { + x: 'boat', + y: getRandomValue(), + }, + { + x: 'train', + y: getRandomValue(), + }, + { + x: 'subway', + y: getRandomValue(), + }, + { + x: 'bus', + y: getRandomValue(), + }, + { + x: 'car', + y: getRandomValue(), + }, + { + x: 'moto', + y: getRandomValue(), + }, + { + x: 'bicycle', + y: getRandomValue(), + }, + { + x: 'horse', + y: getRandomValue(), + }, + { + x: 'skateboard', + y: getRandomValue(), + }, + { + x: 'others', + y: getRandomValue(), + }, + ], + }, + { + id: 'france', + data: [ + { + x: 'plane', + y: getRandomValue(), + }, + { + x: 'helicopter', + y: getRandomValue(), + }, + { + x: 'boat', + y: getRandomValue(), + }, + { + x: 'train', + y: getRandomValue(), + }, + { + x: 'subway', + y: getRandomValue(), + }, + { + x: 'bus', + y: getRandomValue(), + }, + { + x: 'car', + y: getRandomValue(), + }, + { + x: 'moto', + y: getRandomValue(), + }, + { + x: 'bicycle', + y: getRandomValue(), + }, + { + x: 'horse', + y: getRandomValue(), + }, + { + x: 'skateboard', + y: getRandomValue(), + }, + { + x: 'others', + y: getRandomValue(), + }, + ], + }, + { + id: 'us', + data: [ + { + x: 'plane', + y: getRandomValue(), + }, + { + x: 'helicopter', + y: getRandomValue(), + }, + { + x: 'boat', + y: getRandomValue(), + }, + { + x: 'train', + y: getRandomValue(), + }, + { + x: 'subway', + y: getRandomValue(), + }, + { + x: 'bus', + y: getRandomValue(), + }, + { + x: 'car', + y: getRandomValue(), + }, + { + x: 'moto', + y: getRandomValue(), + }, + { + x: 'bicycle', + y: getRandomValue(), + }, + { + x: 'horse', + y: getRandomValue(), + }, + { + x: 'skateboard', + y: getRandomValue(), + }, + { + x: 'others', + y: getRandomValue(), + }, + ], + }, + { + id: 'germany', + data: [ + { + x: 'plane', + y: getRandomValue(), + }, + { + x: 'helicopter', + y: getRandomValue(), + }, + { + x: 'boat', + y: getRandomValue(), + }, + { + x: 'train', + y: getRandomValue(), + }, + { + x: 'subway', + y: getRandomValue(), + }, + { + x: 'bus', + y: getRandomValue(), + }, + { + x: 'car', + y: getRandomValue(), + }, + { + x: 'moto', + y: getRandomValue(), + }, + { + x: 'bicycle', + y: getRandomValue(), + }, + { + x: 'horse', + y: getRandomValue(), + }, + { + x: 'skateboard', + y: getRandomValue(), + }, + { + x: 'others', + y: getRandomValue(), + }, + ], + }, + { + id: 'norway', + data: [ + { + x: 'plane', + y: getRandomValue(), + }, + { + x: 'helicopter', + y: getRandomValue(), + }, + { + x: 'boat', + y: getRandomValue(), + }, + { + x: 'train', + y: getRandomValue(), + }, + { + x: 'subway', + y: getRandomValue(), + }, + { + x: 'bus', + y: getRandomValue(), + }, + { + x: 'car', + y: getRandomValue(), + }, + { + x: 'moto', + y: getRandomValue(), + }, + { + x: 'bicycle', + y: getRandomValue(), + }, + { + x: 'horse', + y: getRandomValue(), + }, + { + x: 'skateboard', + y: getRandomValue(), + }, + { + x: 'others', + y: getRandomValue(), + }, + ], + }, +] + +const initialProperties = { + margin: { + top: 90, + right: 90, + bottom: 60, + left: 90, + }, + + minValue: defaults.minValue, + maxValue: defaults.maxValue, + valueFormat: { format: '>-d', enabled: true }, + + forceSquare: defaults.forceSquare, + sizeVariation: 0, + xOuterPadding: defaults.xOuterPadding, + xInnerPadding: 0.05, + yOuterPadding: defaults.yOuterPadding, + yInnerPadding: 0.05, + + enableGridX: defaults.enableGridX, + enableGridY: defaults.enableGridY, + axisTop: { + enable: true, + orient: 'top', + tickSize: 5, + tickPadding: 5, + tickRotation: -90, + legend: '', + legendOffset: 46, + }, + axisRight: { + enable: true, + orient: 'right', + tickSize: 5, + tickPadding: 5, + tickRotation: 0, + legend: 'country', + legendPosition: 'middle', + legendOffset: 64, + }, + axisBottom: { + enable: false, + orient: 'bottom', + tickSize: 5, + tickPadding: 5, + tickRotation: -90, + legend: '', + legendPosition: 'middle', + legendOffset: 36, + }, + axisLeft: { + enable: true, + orient: 'left', + tickSize: 5, + tickPadding: 5, + tickRotation: 0, + legend: 'country', + legendPosition: 'middle', + legendOffset: -64, + }, + + colors: { + type: 'diverging', + scheme: 'red_yellow_blue', + divergeAt: 0.5, + minValue: -100, + maxValue: 100, + }, + cellComponent: 'rect', + cellOpacity: 1, + activeCellOpacity: 1, + inactiveCellOpacity: 1, + borderRadius: 2, + borderWidth: 1, + borderColor: { + from: 'color', + modifiers: [['darker', 0.6]], + }, + + enableLabels: true, + labelTextColor: { + from: 'color', + modifiers: [['darker', 2]], + }, + + defs: [ + patternLinesDef('lines', { + background: 'inherit', + color: 'rgba(0, 0, 0, 0.1)', + rotation: -45, + lineWidth: 4, + spacing: 7, + }), + ], + fill: [{ match: d => false && d.value < 30, id: 'lines' }], + + legends: [ + { + anchor: 'bottom', + translateX: 0, + translateY: 30, + length: 400, + thickness: 8, + direction: 'row', + tickPosition: 'after', + tickSize: 3, + tickSpacing: 4, + tickOverlap: false, + tickFormat: Math.round, + title: 'Value →', + titleAlign: 'start', + titleOffset: 4, + }, + ], + + animate: defaults.animate, + motionConfig: defaults.motionConfig, + + isInteractive: defaults.isInteractive, + hoverTarget: 'cell', +} + +const HeatMap = () => { + const { + image: { + childImageSharp: { gatsbyImageData: image }, + }, + } = useStaticQuery(graphql` + query { + image: file(absolutePath: { glob: "**/src/assets/captures/heatmap.png" }) { + childImageSharp { + gatsbyImageData(layout: FIXED, width: 700, quality: 100) + } + } + } + `) + + return ( + ({ + ...properties, + cellShape: isFunction(properties.cellShape) + ? 'Custom(props) => (…)' + : properties.cellShape, + })} + generateData={getData} + // getTabData={data => data.data} + image={image} + > + {(properties, data, theme, logAction) => { + return ( + { + logAction({ + type: 'click', + label: `${cell.serieId} ${cell.data.x}: ${cell.formattedValue}`, + color: cell.color, + data: cell, + }) + }} + /> + ) + }} + + ) +} + +export default HeatMap