chore: Removes hard-coded colors from the plugins - iteration 1 (#19923)

* chore: Removes hard-coded colors from the plugins - iteration 1

* Fixes lint errors

* Fixes tests
This commit is contained in:
Michael S. Molina 2022-05-09 10:44:13 -03:00 committed by GitHub
parent d0b8b1e97d
commit b7cff8335b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 409 additions and 324 deletions

View File

@ -18,17 +18,11 @@
*/
import React from 'react';
import { SupersetTheme } from '../../style';
import { FallbackPropsWithDimension } from './SuperChart';
export type Props = FallbackPropsWithDimension;
const CONTAINER_STYLE = {
backgroundColor: '#000',
color: '#fff',
overflow: 'auto',
padding: 32,
};
export default function FallbackComponent({
componentStack,
error,
@ -36,7 +30,15 @@ export default function FallbackComponent({
width,
}: Props) {
return (
<div style={{ ...CONTAINER_STYLE, height, width }}>
<div
css={(theme: SupersetTheme) => ({
backgroundColor: theme.colors.grayscale.dark2,
color: theme.colors.grayscale.light5,
overflow: 'auto',
padding: 32,
})}
style={{ height, width }}
>
<div>
<div>
<b>Oops! An error occured!</b>

View File

@ -19,7 +19,12 @@
/* eslint-disable max-classes-per-file */
import React from 'react';
import { QueryFormData, ChartMetadata, ChartPlugin } from '@superset-ui/core';
import {
QueryFormData,
ChartMetadata,
ChartPlugin,
useTheme,
} from '@superset-ui/core';
const DIMENSION_STYLE = {
fontSize: 36,
@ -39,31 +44,36 @@ export const TestComponent = ({
message?: string;
width?: number;
height?: number;
}) => (
<div
className="test-component"
style={{
width,
height,
backgroundColor: '#00d1c1',
color: '#fff',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
borderRadius: 8,
}}
>
<div className="message" style={{ padding: 10 }}>
{message ?? 'custom component'}
}) => {
const theme = useTheme();
return (
<div
className="test-component"
style={{
width,
height,
backgroundColor: theme.colors.primary.base,
color: theme.colors.grayscale.light5,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
borderRadius: 8,
}}
>
<div className="message" style={{ padding: 10 }}>
{message ?? 'custom component'}
</div>
<div className="dimension" style={DIMENSION_STYLE}>
{[width, height].join('x')}
</div>
<div className="formData" style={{ padding: 10 }}>
<code style={{ color: theme.colors.primary.light2 }}>
{JSON.stringify(formData)}
</code>
</div>
</div>
<div className="dimension" style={DIMENSION_STYLE}>
{[width, height].join('x')}
</div>
<div className="formData" style={{ padding: 10 }}>
<code style={{ color: '#D3F9F7' }}>{JSON.stringify(formData)}</code>
</div>
</div>
);
);
};
export const ChartKeys = {
DILIGENT: 'diligent-chart',

View File

@ -17,11 +17,16 @@
* under the License.
*/
import React from 'react';
import { mount, shallow } from 'enzyme';
import React, { ReactElement, ReactNode } from 'react';
import { mount } from 'enzyme';
import mockConsole, { RestoreConsole } from 'jest-mock-console';
import { ChartProps, promiseTimeout, supersetTheme } from '@superset-ui/core';
import {
ChartProps,
promiseTimeout,
supersetTheme,
SupersetTheme,
ThemeProvider,
} from '@superset-ui/core';
import SuperChartCore from '../../../src/chart/components/SuperChartCore';
import {
ChartKeys,
@ -30,6 +35,22 @@ import {
SlowChartPlugin,
} from './MockChartPlugins';
const Wrapper = ({
theme,
children,
}: {
theme: SupersetTheme;
children: ReactNode;
}) => <ThemeProvider theme={theme}>{children}</ThemeProvider>;
const styledMount = (component: ReactElement) =>
mount(component, {
wrappingComponent: Wrapper,
wrappingComponentProps: {
theme: supersetTheme,
},
});
describe('SuperChartCore', () => {
const chartProps = new ChartProps();
@ -63,7 +84,7 @@ describe('SuperChartCore', () => {
describe('registered charts', () => {
it('renders registered chart', () => {
const wrapper = shallow(
const wrapper = styledMount(
<SuperChartCore
chartType={ChartKeys.DILIGENT}
chartProps={chartProps}
@ -75,7 +96,9 @@ describe('SuperChartCore', () => {
});
});
it('renders registered chart with lazy loading', () => {
const wrapper = shallow(<SuperChartCore chartType={ChartKeys.LAZY} />);
const wrapper = styledMount(
<SuperChartCore chartType={ChartKeys.LAZY} />,
);
return promiseTimeout(() => {
expect(wrapper.render().find('div.test-component')).toHaveLength(1);
@ -84,14 +107,14 @@ describe('SuperChartCore', () => {
it('does not render if chartType is not set', () => {
// Suppress warning
// @ts-ignore chartType is required
const wrapper = shallow(<SuperChartCore />);
const wrapper = styledMount(<SuperChartCore />);
return promiseTimeout(() => {
expect(wrapper.render().children()).toHaveLength(0);
}, 5);
});
it('adds id to container if specified', () => {
const wrapper = shallow(
const wrapper = styledMount(
<SuperChartCore chartType={ChartKeys.DILIGENT} id="the-chart" />,
);
@ -100,7 +123,7 @@ describe('SuperChartCore', () => {
});
});
it('adds class to container if specified', () => {
const wrapper = shallow(
const wrapper = styledMount(
<SuperChartCore chartType={ChartKeys.DILIGENT} className="the-chart" />,
);
@ -109,7 +132,7 @@ describe('SuperChartCore', () => {
}, 0);
});
it('uses overrideTransformProps when specified', () => {
const wrapper = shallow(
const wrapper = styledMount(
<SuperChartCore
chartType={ChartKeys.DILIGENT}
overrideTransformProps={() => ({ message: 'hulk' })}
@ -125,7 +148,7 @@ describe('SuperChartCore', () => {
queriesData: [{ message: 'hulk' }],
theme: supersetTheme,
});
const wrapper = shallow(
const wrapper = styledMount(
<SuperChartCore
chartType={ChartKeys.DILIGENT}
preTransformProps={() => chartPropsWithPayload}
@ -138,7 +161,7 @@ describe('SuperChartCore', () => {
});
});
it('uses postTransformProps when specified', () => {
const wrapper = shallow(
const wrapper = styledMount(
<SuperChartCore
chartType={ChartKeys.DILIGENT}
postTransformProps={() => ({ message: 'hulk' })}
@ -150,7 +173,7 @@ describe('SuperChartCore', () => {
});
});
it('renders if chartProps is not specified', () => {
const wrapper = shallow(
const wrapper = styledMount(
<SuperChartCore chartType={ChartKeys.DILIGENT} />,
);
@ -159,7 +182,9 @@ describe('SuperChartCore', () => {
});
});
it('does not render anything while waiting for Chart code to load', () => {
const wrapper = shallow(<SuperChartCore chartType={ChartKeys.SLOW} />);
const wrapper = styledMount(
<SuperChartCore chartType={ChartKeys.SLOW} />,
);
return promiseTimeout(() => {
expect(wrapper.render().children()).toHaveLength(0);
@ -167,14 +192,16 @@ describe('SuperChartCore', () => {
});
it('eventually renders after Chart is loaded', () => {
// Suppress warning
const wrapper = mount(<SuperChartCore chartType={ChartKeys.SLOW} />);
const wrapper = styledMount(
<SuperChartCore chartType={ChartKeys.SLOW} />,
);
return promiseTimeout(() => {
expect(wrapper.render().find('div.test-component')).toHaveLength(1);
}, 1500);
});
it('does not render if chartProps is null', () => {
const wrapper = shallow(
const wrapper = styledMount(
<SuperChartCore chartType={ChartKeys.DILIGENT} chartProps={null} />,
);
@ -186,7 +213,7 @@ describe('SuperChartCore', () => {
describe('unregistered charts', () => {
it('renders error message', () => {
const wrapper = mount(
const wrapper = styledMount(
<SuperChartCore chartType="4d-pie-chart" chartProps={chartProps} />,
);

View File

@ -2,8 +2,8 @@
import React from 'react';
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
const ThemeDecorator = storyFn => (
<ThemeProvider theme={supersetTheme}>{storyFn()}</ThemeProvider>
const ThemeDecorator = Story => (
<ThemeProvider theme={supersetTheme}>{<Story />}</ThemeProvider>
);
export default ThemeDecorator;

View File

@ -23,7 +23,7 @@ import { DecoratorFunction } from '@storybook/addons';
import ResizablePanel, { Size } from './ResizablePanel';
export const SupersetBody = styled.div`
background: #f5f5f5;
background: ${({ theme }) => theme.colors.grayscale.light4};
padding: 16px;
min-height: 100%;

View File

@ -40,6 +40,8 @@ export const basic = () => (
cellSize: 10,
cellPadding: 2,
cellRadius: 0,
domainGranularity: 'month',
subdomainGranularity: 'day',
linearColorScheme: 'schemeRdYlBu',
steps: 10,
yAxisFormat: '.3s',

View File

@ -22,6 +22,7 @@ import {
seedRandom,
SuperChart,
SequentialD3,
useTheme,
} from '@superset-ui/core';
import CountryMapChartPlugin, {
countries,
@ -44,6 +45,7 @@ function generateData(geojson: JsonObject) {
}
export const basic = function BasicCountryMapStory({ width, height }) {
const theme = useTheme();
const country = select('Country', Object.keys(countries!), 'france');
const colorSchema = select<any>(
'Color schema',
@ -67,7 +69,13 @@ export const basic = function BasicCountryMapStory({ width, height }) {
if (!data) {
return (
<div style={{ color: '#aaa', textAlign: 'center', padding: 20 }}>
<div
style={{
color: theme.colors.grayscale.base,
textAlign: 'center',
padding: 20,
}}
>
Loading...
</div>
);

View File

@ -19,9 +19,9 @@
/* eslint-disable no-magic-numbers */
import React from 'react';
import { SuperChart } from '@superset-ui/core';
import { SuperChart, useTheme } from '@superset-ui/core';
import MapBoxChartPlugin from '@superset-ui/legacy-plugin-chart-map-box';
import data from './data';
import { generateData } from './data';
new MapBoxChartPlugin().configure({ key: 'map-box' }).register();
@ -29,27 +29,30 @@ export default {
title: 'Legacy Chart Plugins/legacy-plugin-chart-map-box',
};
export const basic = () => (
<SuperChart
chartType="map-box"
width={400}
height={400}
queriesData={[{ data }]}
formData={{
allColumnsX: 'LON',
allColumnsY: 'LAT',
clusteringRadius: '60',
globalOpacity: 1,
mapboxColor: 'rgb(0, 122, 135)',
mapboxLabel: [],
mapboxStyle: 'mapbox://styles/mapbox/light-v9',
pandasAggfunc: 'sum',
pointRadius: 'Auto',
pointRadiusUnit: 'Pixels',
renderWhileDragging: true,
viewportLatitude: 37.78711146014447,
viewportLongitude: -122.37633433151713,
viewportZoom: 10.026425338292782,
}}
/>
);
export const Basic = () => {
const theme = useTheme();
return (
<SuperChart
chartType="map-box"
width={400}
height={400}
queriesData={[{ data: generateData(theme) }]}
formData={{
allColumnsX: 'LON',
allColumnsY: 'LAT',
clusteringRadius: '60',
globalOpacity: 1,
mapboxColor: 'rgb(0, 122, 135)',
mapboxLabel: [],
mapboxStyle: 'mapbox://styles/mapbox/light-v9',
pandasAggfunc: 'sum',
pointRadius: 'Auto',
pointRadiusUnit: 'Pixels',
renderWhileDragging: true,
viewportLatitude: 37.78711146014447,
viewportLongitude: -122.37633433151713,
viewportZoom: 10.026425338292782,
}}
/>
);
};

View File

@ -16,9 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
import { SupersetTheme } from '@superset-ui/core';
/* eslint-disable sort-keys, no-magic-numbers */
export default {
export const generateData = (theme: SupersetTheme) => ({
geoJSON: {
type: 'FeatureCollection',
features: [
@ -5538,5 +5539,5 @@ export default {
],
renderWhileDragging: true,
tooltip: null,
color: 'rgb(0, 122, 135)',
};
color: theme.colors.primary.base,
});

View File

@ -38,6 +38,7 @@ export const basic = () => (
formData={{
maxBubbleSize: '25',
showBubbles: true,
colorPicker: {},
}}
/>
);

View File

@ -20,9 +20,9 @@
/* eslint-disable sort-keys */
/* eslint-disable no-magic-numbers */
import React from 'react';
import { SuperChart } from '@superset-ui/core';
import { SuperChart, useTheme } from '@superset-ui/core';
import { PathChartPlugin } from '@superset-ui/legacy-preset-chart-deckgl';
import payload from './payload';
import { payload } from './payload';
import dummyDatasource from '../../../../shared/dummyDatasource';
new PathChartPlugin().configure({ key: 'deck_path' }).register();
@ -31,51 +31,54 @@ export default {
title: 'Legacy Chart Plugins/legacy-preset-chart-deckgl/PathChartPlugin',
};
export const PathChartViz = () => (
<SuperChart
chartType="deck_path"
width={400}
height={400}
datasource={dummyDatasource}
queriesData={[payload]}
formData={{
datasource: '11__table',
viz_type: 'deck_path',
slice_id: 72,
url_params: {},
granularity_sqla: null,
time_grain_sqla: null,
time_range: '+:+',
line_column: 'path_json',
line_type: 'json',
row_limit: 5000,
filter_nulls: true,
adhoc_filters: [],
mapbox_style: 'mapbox://styles/mapbox/light-v9',
viewport: {
altitude: 1.5,
bearing: 0,
height: 1094,
latitude: 37.73671752604488,
longitude: -122.18885402582598,
maxLatitude: 85.05113,
maxPitch: 60,
maxZoom: 20,
minLatitude: -85.05113,
minPitch: 0,
minZoom: 0,
pitch: 0,
width: 669,
zoom: 9.51847667620428,
},
color_picker: { a: 1, b: 135, g: 122, r: 0 },
line_width: 150,
reverse_long_lat: false,
autozoom: true,
js_columns: ['color'],
js_data_mutator: '',
js_tooltip: '',
js_onclick_href: '',
}}
/>
);
export const PathChartViz = () => {
const theme = useTheme();
return (
<SuperChart
chartType="deck_path"
width={400}
height={400}
datasource={dummyDatasource}
queriesData={[payload(theme)]}
formData={{
datasource: '11__table',
viz_type: 'deck_path',
slice_id: 72,
url_params: {},
granularity_sqla: null,
time_grain_sqla: null,
time_range: '+:+',
line_column: 'path_json',
line_type: 'json',
row_limit: 5000,
filter_nulls: true,
adhoc_filters: [],
mapbox_style: 'mapbox://styles/mapbox/light-v9',
viewport: {
altitude: 1.5,
bearing: 0,
height: 1094,
latitude: 37.73671752604488,
longitude: -122.18885402582598,
maxLatitude: 85.05113,
maxPitch: 60,
maxZoom: 20,
minLatitude: -85.05113,
minPitch: 0,
minZoom: 0,
pitch: 0,
width: 669,
zoom: 9.51847667620428,
},
color_picker: { a: 1, b: 135, g: 122, r: 0 },
line_width: 150,
reverse_long_lat: false,
autozoom: true,
js_columns: ['color'],
js_data_mutator: '',
js_tooltip: '',
js_onclick_href: '',
}}
/>
);
};

View File

@ -19,7 +19,7 @@
/* eslint-disable sort-keys */
/* eslint-disable no-magic-numbers */
export default {
export const payload = theme => ({
cache_key: null,
cached_dttm: null,
cache_timeout: 86400,
@ -82,7 +82,7 @@ export default {
data: {
features: [
{
color: '#ed1c24',
color: theme.colors.primary.base,
path: [
[-122.3535851, 37.9360513],
[-122.3179784, 37.9249513],
@ -109,10 +109,10 @@ export default {
[-122.3876274, 37.5993171],
],
__timestamp: null,
extraProps: { color: '#ed1c24' },
extraProps: { color: theme.colors.primary.base },
},
{
color: '#faa61a',
color: theme.colors.warning.base,
path: [
[-122.353165, 37.936887],
[-122.317269, 37.925655],
@ -134,10 +134,10 @@ export default {
[-121.9772135, 37.5567286],
],
__timestamp: null,
extraProps: { color: '#faa61a' },
extraProps: { color: theme.colors.warning.base },
},
{
color: '#ffe800',
color: theme.colors.error.base,
path: [
[-121.945154, 38.018914],
[-122.024597, 38.003275],
@ -167,10 +167,10 @@ export default {
[-122.38666, 37.599787],
],
__timestamp: null,
extraProps: { color: '#ffe800' },
extraProps: { color: theme.colors.error.base },
},
{
color: '#00aeef',
color: theme.colors.success.base,
path: [
[-121.900367, 37.701695],
[-121.928099, 37.699759],
@ -192,10 +192,10 @@ export default {
[-122.469081, 37.706121],
],
__timestamp: null,
extraProps: { color: '#00aeef' },
extraProps: { color: theme.colors.success.base },
},
{
color: '#4db848',
color: theme.colors.warning.base,
path: [
[-121.9764, 37.557355],
[-122.017867, 37.591208],
@ -218,11 +218,11 @@ export default {
[-122.4683093, 37.705461],
],
__timestamp: null,
extraProps: { color: '#4db848' },
extraProps: { color: theme.colors.warning.base },
},
],
mapboxApiKey:
'pk.eyJ1Ijoia3Jpc3R3IiwiYSI6ImNqbGg1N242NTFlczczdnBhazViMjgzZ2sifQ.lUneM-o3NucXN189EYyXxQ',
metricLabels: [],
},
};
});

View File

@ -54,7 +54,7 @@ export const basic = ({ width, height }) => (
formData={{
encoding: {
color: {
value: '#0097e6',
field: 'name',
},
fontSize: {
field: 'sum__num',
@ -120,7 +120,7 @@ export const encodesFontByFirstLetter = ({ width, height }) => (
formData={{
encoding: {
color: {
value: '#8c7ae6',
field: 'name',
},
fontFamily: {
field: 'name[0]',

View File

@ -18,80 +18,83 @@
*/
import React from 'react';
import { SuperChart } from '@superset-ui/core';
import { SuperChart, useTheme } from '@superset-ui/core';
import data from '../data/data2';
import { LINE_PLUGIN_TYPE } from '../constants';
import dummyDatasource from '../../../../../shared/dummyDatasource';
export default () => (
<SuperChart
key="line1"
chartType={LINE_PLUGIN_TYPE}
width={400}
height={400}
datasource={dummyDatasource}
queriesData={[{ data }]}
formData={{
encoding: {
x: {
field: 'x',
type: 'temporal',
format: '%Y',
scale: {
type: 'time',
export default () => {
const theme = useTheme();
return (
<SuperChart
key="line1"
chartType={LINE_PLUGIN_TYPE}
width={400}
height={400}
datasource={dummyDatasource}
queriesData={[{ data }]}
formData={{
encoding: {
x: {
field: 'x',
type: 'temporal',
format: '%Y',
scale: {
type: 'time',
},
axis: {
orient: 'bottom',
title: 'Time',
},
},
axis: {
orient: 'bottom',
title: 'Time',
y: {
field: 'y',
type: 'quantitative',
scale: {
type: 'linear',
},
axis: {
orient: 'left',
title: 'Score',
},
},
stroke: {
value: theme.colors.success.base,
type: 'nominal',
scale: false,
},
fill: {
field: 'snapshot',
type: 'nominal',
scale: {
type: 'ordinal',
domain: ['Current', 'Last year'],
range: [true, false],
},
legend: false,
},
strokeDasharray: {
field: 'snapshot',
type: 'nominal',
scale: {
type: 'ordinal',
domain: ['Current', 'Last year'],
range: [null, '4 4'],
},
legend: false,
},
strokeWidth: {
field: 'snapshot',
type: 'nominal',
scale: {
type: 'ordinal',
domain: ['Current', 'Last year'],
range: [3, 1.5],
},
legend: false,
},
},
y: {
field: 'y',
type: 'quantitative',
scale: {
type: 'linear',
},
axis: {
orient: 'left',
title: 'Score',
},
},
stroke: {
value: '#1abc9c',
type: 'nominal',
scale: false,
},
fill: {
field: 'snapshot',
type: 'nominal',
scale: {
type: 'ordinal',
domain: ['Current', 'Last year'],
range: [true, false],
},
legend: false,
},
strokeDasharray: {
field: 'snapshot',
type: 'nominal',
scale: {
type: 'ordinal',
domain: ['Current', 'Last year'],
range: [null, '4 4'],
},
legend: false,
},
strokeWidth: {
field: 'snapshot',
type: 'nominal',
scale: {
type: 'ordinal',
domain: ['Current', 'Last year'],
range: [3, 1.5],
},
legend: false,
},
},
}}
/>
);
}}
/>
);
};

View File

@ -50,6 +50,7 @@ const propTypes = {
timeFormatter: PropTypes.func,
valueFormatter: PropTypes.func,
verboseMap: PropTypes.object,
theme: PropTypes.object,
};
function Calendar(element, props) {
@ -69,6 +70,7 @@ function Calendar(element, props) {
timeFormatter,
valueFormatter,
verboseMap,
theme,
} = props;
const container = d3Select(element)
@ -120,7 +122,7 @@ function Calendar(element, props) {
colorScale,
min: legendColors[0],
max: legendColors[legendColors.length - 1],
empty: 'white',
empty: theme.colors.grayscale.light5,
},
displayLegend: showLegend,
itemName: '',

View File

@ -18,83 +18,86 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
import { reactify, styled, css } from '@superset-ui/core';
import { reactify, styled, css, useTheme } from '@superset-ui/core';
import { Global } from '@emotion/react';
import Component from './Calendar';
const ReactComponent = reactify(Component);
const Calender = ({ className, ...otherProps }) => (
<div className={className}>
<Global
styles={theme => css`
.d3-tip {
line-height: 1;
padding: ${theme.gridUnit * 3}px;
background: ${theme.colors.grayscale.dark2};
color: ${theme.colors.grayscale.light5};
border-radius: 4px;
pointer-events: none;
z-index: 1000;
font-size: ${theme.typography.sizes.s}px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: ${theme.typography.sizes.xs};
width: 100%;
line-height: 1;
color: ${theme.colors.grayscale.dark2};
position: absolute;
pointer-events: none;
}
/* Northward tooltips */
.d3-tip.n:after {
content: '\\25BC';
margin: -${theme.gridUnit}px 0 0 0;
top: 100%;
left: 0;
text-align: center;
}
/* Eastward tooltips */
.d3-tip.e:after {
content: '\\25C0';
margin: -${theme.gridUnit}px 0 0 0;
top: 50%;
left: -${theme.gridUnit * 2}px;
}
/* Southward tooltips */
.d3-tip.s:after {
content: '\\25B2';
margin: 0;
top: -${theme.gridUnit * 2}px;
left: 0;
text-align: center;
}
/* Westward tooltips */
.d3-tip.w:after {
content: '\\25B6';
margin: -${theme.gridUnit}px 0 0 0px;
top: 50%;
left: 100%;
}
`}
/>
<ReactComponent {...otherProps} />
</div>
);
const Calendar = ({ className, ...otherProps }) => {
const theme = useTheme();
return (
<div className={className}>
<Global
styles={css`
.d3-tip {
line-height: 1;
padding: ${theme.gridUnit * 3}px;
background: ${theme.colors.grayscale.dark2};
color: ${theme.colors.grayscale.light5};
border-radius: 4px;
pointer-events: none;
z-index: 1000;
font-size: ${theme.typography.sizes.s}px;
}
/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
box-sizing: border-box;
display: inline;
font-size: ${theme.typography.sizes.xs};
width: 100%;
line-height: 1;
color: ${theme.colors.grayscale.dark2};
position: absolute;
pointer-events: none;
}
/* Northward tooltips */
.d3-tip.n:after {
content: '\\25BC';
margin: -${theme.gridUnit}px 0 0 0;
top: 100%;
left: 0;
text-align: center;
}
/* Eastward tooltips */
.d3-tip.e:after {
content: '\\25C0';
margin: -${theme.gridUnit}px 0 0 0;
top: 50%;
left: -${theme.gridUnit * 2}px;
}
/* Southward tooltips */
.d3-tip.s:after {
content: '\\25B2';
margin: 0;
top: -${theme.gridUnit * 2}px;
left: 0;
text-align: center;
}
/* Westward tooltips */
.d3-tip.w:after {
content: '\\25B6';
margin: -${theme.gridUnit}px 0 0 0px;
top: 50%;
left: 100%;
}
`}
/>
<ReactComponent {...otherProps} theme={theme} />
</div>
);
};
Calender.defaultProps = {
Calendar.defaultProps = {
otherProps: {},
};
Calender.propTypes = {
Calendar.propTypes = {
className: PropTypes.string.isRequired,
otherProps: PropTypes.objectOf(PropTypes.any),
};
export default styled(Calender)`
export default styled(Calendar)`
${({ theme }) => `
.superset-legacy-chart-calendar {
padding: ${theme.gridUnit * 3}px;

View File

@ -18,16 +18,19 @@
*/
import React from 'react';
import PropTypes from 'prop-types';
import { styled, reactify } from '@superset-ui/core';
import { styled, reactify, useTheme } from '@superset-ui/core';
import WorldMap from './WorldMap';
const ReactWorldMap = reactify(WorldMap);
const WorldMapComponent = ({ className, ...otherProps }) => (
<div className={className}>
<ReactWorldMap {...otherProps} />
</div>
);
const WorldMapComponent = ({ className, ...otherProps }) => {
const theme = useTheme();
return (
<div className={className}>
<ReactWorldMap {...otherProps} theme={theme} />
</div>
);
};
WorldMapComponent.propTypes = {
className: PropTypes.string.isRequired,

View File

@ -55,6 +55,7 @@ function WorldMap(element, props) {
showBubbles,
linearColorScheme,
color,
theme,
} = props;
const div = d3.select(element);
div.classed('superset-legacy-chart-world-map', true);
@ -90,14 +91,14 @@ function WorldMap(element, props) {
height,
data: processedData,
fills: {
defaultFill: '#eee',
defaultFill: theme.colors.grayscale.light2,
},
geographyConfig: {
popupOnHover: true,
highlightOnHover: true,
borderWidth: 1,
borderColor: '#feffff',
highlightBorderColor: '#feffff',
borderColor: theme.colors.grayscale.light5,
highlightBorderColor: theme.colors.grayscale.light5,
highlightFillColor: color,
highlightBorderWidth: 1,
popupTemplate: (geo, d) =>
@ -119,7 +120,7 @@ function WorldMap(element, props) {
animate: true,
highlightOnHover: true,
highlightFillColor: color,
highlightBorderColor: 'black',
highlightBorderColor: theme.colors.grayscale.dark2,
highlightBorderWidth: 2,
highlightBorderOpacity: 1,
highlightFillOpacity: 0.85,

View File

@ -17,7 +17,8 @@
* under the License.
*/
import React, { useMemo, CSSProperties } from 'react';
import { styled } from '@superset-ui/core';
import React, { useMemo } from 'react';
import { filterXSS } from 'xss';
export type TooltipProps = {
@ -31,6 +32,22 @@ export type TooltipProps = {
| undefined;
};
const StyledDiv = styled.div<{ top: number; left: number }>`
${({ theme, top, left }) => `
position: absolute;
top: ${top}px;
left: ${left}px;
padding: ${theme.gridUnit * 2}px;
margin: ${theme.gridUnit * 2}px;
background: ${theme.colors.grayscale.dark2};
color: ${theme.colors.grayscale.light5};
maxWidth: 300px;
fontSize: ${theme.typography.sizes.s}px;
zIndex: 9;
pointerEvents: none;
`}
`;
export default function Tooltip(props: TooltipProps) {
const { tooltip } = props;
if (typeof tooltip === 'undefined' || tooltip === null) {
@ -39,24 +56,6 @@ export default function Tooltip(props: TooltipProps) {
const { x, y, content } = tooltip;
// eslint-disable-next-line react-hooks/rules-of-hooks
const style: CSSProperties = useMemo(
() => ({
position: 'absolute',
top: `${y}px`,
left: `${x}px`,
padding: '8px',
margin: '8px',
background: 'rgba(0, 0, 0, 0.8)',
color: '#fff',
maxWidth: '300px',
fontSize: '12px',
zIndex: 9,
pointerEvents: 'none',
}),
[x, y],
);
if (typeof content === 'string') {
// eslint-disable-next-line react-hooks/rules-of-hooks
const contentHtml = useMemo(
@ -66,14 +65,18 @@ export default function Tooltip(props: TooltipProps) {
[content],
);
return (
<div style={style}>
<StyledDiv top={y} left={x}>
<div
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={contentHtml}
/>
</div>
</StyledDiv>
);
}
return <div style={style}>{content}</div>;
return (
<StyledDiv top={y} left={x}>
{content}
</StyledDiv>
);
}

View File

@ -55,9 +55,18 @@ const PivotTableWrapper = styled.div`
`;
const METRIC_KEY = 'metric';
const iconStyle = { stroke: 'black', strokeWidth: '16px' };
const vals = ['value'];
const StyledPlusSquareOutlined = styled(PlusSquareOutlined)`
stroke: ${({ theme }) => theme.colors.grayscale.light2};
stroke-width: 16px;
`;
const StyledMinusSquareOutlined = styled(MinusSquareOutlined)`
stroke: ${({ theme }) => theme.colors.grayscale.light2};
stroke-width: 16px;
`;
const aggregatorsFactory = (formatter: NumberFormatter) => ({
Count: aggregatorTemplates.count(formatter),
'Count Unique Values': aggregatorTemplates.countUnique(formatter),
@ -345,8 +354,8 @@ export default function PivotTableChart(props: PivotTableProps) {
() => ({
colSubtotalDisplay: { displayOnTop: colSubtotalPosition },
rowSubtotalDisplay: { displayOnTop: rowSubtotalPosition },
arrowCollapsed: <PlusSquareOutlined style={iconStyle} />,
arrowExpanded: <MinusSquareOutlined style={iconStyle} />,
arrowCollapsed: <StyledPlusSquareOutlined />,
arrowExpanded: <StyledMinusSquareOutlined />,
}),
[colSubtotalPosition, rowSubtotalPosition],
);

View File

@ -105,7 +105,7 @@ class WordCloud extends React.PureComponent<
text: 'Text',
},
defaultEncoding: {
color: { value: 'black' },
color: { value: this.props.theme.colors.grayscale.dark2 },
fontFamily: { value: this.props.theme.typography.families.sansSerif },
fontSize: { value: 20 },
fontWeight: { value: 'bold' },

View File

@ -68,7 +68,9 @@ type Props = {
Readonly<typeof defaultProps>;
export default class BoxPlot extends React.PureComponent<Props> {
private createEncoder = boxPlotEncoderFactory.createSelector();
private createEncoder = boxPlotEncoderFactory(
this.props.theme?.colors.darkGray,
).createSelector();
private createMargin = createMarginSelector();

View File

@ -25,7 +25,7 @@ export type BoxPlotEncodingConfig = {
color: ['Color', string];
};
export const boxPlotEncoderFactory =
export const boxPlotEncoderFactory = (darkGray: string) =>
createEncoderFactory<BoxPlotEncodingConfig>({
channelTypes: {
x: 'XBand',
@ -35,7 +35,7 @@ export const boxPlotEncoderFactory =
defaultEncoding: {
x: { field: 'x', type: 'nominal' },
y: { field: 'y', type: 'quantitative' },
color: { value: '#222' },
color: { value: darkGray },
},
});

View File

@ -34,7 +34,7 @@ export type ScatterPlotEncodingConfig = {
tooltip: ['Text', string, 'multiple'];
};
export const scatterPlotEncoderFactory =
export const scatterPlotEncoderFactory = (darkGray: string) =>
createEncoderFactory<ScatterPlotEncodingConfig>({
channelTypes: {
x: 'X',
@ -48,7 +48,7 @@ export const scatterPlotEncoderFactory =
defaultEncoding: {
x: { field: 'x', type: 'quantitative' },
y: { field: 'y', type: 'quantitative' },
fill: { value: '#222' },
fill: { value: darkGray },
group: [],
size: { value: 5 },
stroke: { value: 'none' },

View File

@ -67,7 +67,9 @@ type Props = {
Readonly<typeof defaultProps>;
export default class ScatterPlot extends PureComponent<Props> {
private createEncoder = scatterPlotEncoderFactory.createSelector();
private createEncoder = scatterPlotEncoderFactory(
this.props.theme?.colors.darkGray,
).createSelector();
private createMargin = createMarginSelector();