From eec10dfc754394afa44e985bd3ed919f05157837 Mon Sep 17 00:00:00 2001 From: AdriSolid Date: Tue, 16 Mar 2021 17:28:50 +0100 Subject: [PATCH] feat: add react-widget to storybook (#120) --- CHANGELOG.md | 1 + packages/react-ui/package.json | 2 + .../react-ui/storybook/.storybook/preview.js | 12 ++- .../stories/Introduction.stories.mdx | 29 +++--- .../stories/common/Palette.stories.js | 2 +- .../stories/common/Typography.stories.js | 2 +- .../stories/widgets/CategoryWidget.stories.js | 93 +++++++++++++++++++ .../stories/widgets/FormulaWidget.stories.js | 76 +++++++++++++++ .../widgets/HistogramWidget.stories.js | 81 ++++++++++++++++ .../stories/widgets/PieWidget.stories.js | 87 +++++++++++++++++ .../storybook/stories/widgets/utils.js | 45 +++++++++ .../CategoryWidgetUI.stories.js | 40 ++++---- .../FormulaWidgetUI.stories.js | 15 +-- .../HistogramWidgetUI.stories.js | 47 +++++----- .../PieWidgetUI.stories.js | 3 +- .../WrapperWidgetUI.stories.js | 2 +- packages/react-widgets/reference.md | 1 + .../src/widgets/CategoryWidget.js | 6 +- .../src/widgets/FormulaWidget.js | 3 +- .../src/widgets/HistogramWidget.js | 3 +- .../react-widgets/src/widgets/PieWidget.js | 3 +- 21 files changed, 478 insertions(+), 75 deletions(-) create mode 100644 packages/react-ui/storybook/stories/widgets/CategoryWidget.stories.js create mode 100644 packages/react-ui/storybook/stories/widgets/FormulaWidget.stories.js create mode 100644 packages/react-ui/storybook/stories/widgets/HistogramWidget.stories.js create mode 100644 packages/react-ui/storybook/stories/widgets/PieWidget.stories.js create mode 100644 packages/react-ui/storybook/stories/widgets/utils.js rename packages/react-ui/storybook/stories/{widgets => widgetsUI}/CategoryWidgetUI.stories.js (56%) rename packages/react-ui/storybook/stories/{widgets => widgetsUI}/FormulaWidgetUI.stories.js (72%) rename packages/react-ui/storybook/stories/{widgets => widgetsUI}/HistogramWidgetUI.stories.js (52%) rename packages/react-ui/storybook/stories/{widgets => widgetsUI}/PieWidgetUI.stories.js (93%) rename packages/react-ui/storybook/stories/{widgets => widgetsUI}/WrapperWidgetUI.stories.js (98%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c7ed66d6..8a65d853c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - Fix histogram operations with values equal to zero [#113](https://github.com/CartoDB/carto-react/pull/113) - Return uniqueIdProperty from useCartoLayerProps hook [#113](https://github.com/CartoDB/carto-react/pull/113) - Fix lint-staged for multi package [#117](https://github.com/CartoDB/carto-react/pull/117) +- Add Widgets from @carto/react-widgets to StoryBook [#120](https://github.com/CartoDB/carto-react/pull/120) ## 1.0.0-beta14 (2021-02-08) diff --git a/packages/react-ui/package.json b/packages/react-ui/package.json index 19d60c62d..3c5b08818 100644 --- a/packages/react-ui/package.json +++ b/packages/react-ui/package.json @@ -58,6 +58,8 @@ "eslint-plugin-react-hooks": "^4.2.0", "firebase-tools": "^8.17.0", "jest": "^26.6.3", + "react-redux": "^7.2.2", + "@reduxjs/toolkit": "^1.5.0", "webpack": "^5.24.2", "webpack-cli": "^4.5.0" }, diff --git a/packages/react-ui/storybook/.storybook/preview.js b/packages/react-ui/storybook/.storybook/preview.js index a89246b22..da40672bf 100644 --- a/packages/react-ui/storybook/.storybook/preview.js +++ b/packages/react-ui/storybook/.storybook/preview.js @@ -44,11 +44,19 @@ export const parameters = { storySort: { order: [ 'Introduction', - 'Getting Started', + 'CARTO Theme', ['Palette', 'Typography'], 'Common', 'Widgets', - ['WrapperWidgetUI', 'FormulaWidgetUI', 'CategoryWidgetUI'] + ['CategoryWidget', 'FormulaWidget', , 'HistogramWidget', 'PieWidget'], + 'Widgets UI', + [ + 'CategoryWidgetUI', + 'FormulaWidgetUI', + 'HistogramWidgetUI', + 'PieWidgetUI', + 'WrapperWidgetUI' + ] ] } } diff --git a/packages/react-ui/storybook/stories/Introduction.stories.mdx b/packages/react-ui/storybook/stories/Introduction.stories.mdx index 0e38f1ca4..6ec79cf9a 100644 --- a/packages/react-ui/storybook/stories/Introduction.stories.mdx +++ b/packages/react-ui/storybook/stories/Introduction.stories.mdx @@ -2,36 +2,43 @@ import { Meta, Description } from '@storybook/addon-docs/blocks'; -# CARTO for React - UI Components -This storybook includes the UI Components for CARTO for React (@carto/react-ui). +# CARTO for React - Widgets and UI Components +This storybook includes the UI Components (@carto/react-ui) and the powerful Widgets (@carto/react-widgets) for CARTO for React. They are based on [Material-UI](https://material-ui.com/), and they include a CARTO theme + custom widgets. ## Storybook Development ### How to add a new Story Put your `stories.js` files inside the `storybook/stories` folder following the same folder structure as the source files. For example: -`stories/widgets/FormulaWidgetUI.stories.js` for `src/ui/widgets/FormulaWidgetUI.js` component. +`stories/widgets/FormulaWidget.stories.js` for `react-widgets/src/widgets/FormulaWidget.js` component. As long as we are using a decorator to inject the MaterialUI theme, you just need to import and add your component to the `template` of your story. ```js import React from 'react'; -import FormulaWidgetUI from '../../../src/widgets/FormulaWidgetUI'; +import FormulaWidget from '../../../../react-widgets/src/widgets/FormulaWidget'; -const Template = (args) => ; +const Template = (args) => ; ``` Then, export your story and the different variations: ```js export default { - title: 'Widgets/FormulaWidgetUI', - component: FormulaWidgetUI, + title: 'Widgets/FormulaWidget', + component: FormulaWidget, + // We use a decorator for mocking the Redux store in Widgets + decorators: [(Story) => ] }; -export const Empty = Template.bind({}); -Empty.args = {}; +const DEFAULT_PROPS = { + id: 'sb-formula-id', + title: 'wrapper title', + dataSource: 'sb-data-source', + column: 'sb-column', + operation: 'sum' +}; -export const Text = Template.bind({}); -Text.args = { data: '$1000000'}; +export const Default = Template.bind({}); +Default.args = DEFAULT_PROPS; ``` Optionally, you can add some extra controls to your story, but by default Storybook will add automatic controls for your story arguments. diff --git a/packages/react-ui/storybook/stories/common/Palette.stories.js b/packages/react-ui/storybook/stories/common/Palette.stories.js index b5e41baf6..2ef72a34d 100644 --- a/packages/react-ui/storybook/stories/common/Palette.stories.js +++ b/packages/react-ui/storybook/stories/common/Palette.stories.js @@ -3,7 +3,7 @@ import { Box, Grid, Typography } from '@material-ui/core'; import { useTheme } from '@material-ui/core/styles'; const options = { - title: 'Getting Started/Palette', + title: 'CARTO Theme/Palette', component: Box, argTypes: { colorVariant: { diff --git a/packages/react-ui/storybook/stories/common/Typography.stories.js b/packages/react-ui/storybook/stories/common/Typography.stories.js index 9d6983bd1..d88112a42 100644 --- a/packages/react-ui/storybook/stories/common/Typography.stories.js +++ b/packages/react-ui/storybook/stories/common/Typography.stories.js @@ -2,7 +2,7 @@ import React from 'react'; import Typography from '@material-ui/core/Typography'; const options = { - title: 'Getting Started/Typography', + title: 'CARTO Theme/Typography', component: Typography, argTypes: { variant: { diff --git a/packages/react-ui/storybook/stories/widgets/CategoryWidget.stories.js b/packages/react-ui/storybook/stories/widgets/CategoryWidget.stories.js new file mode 100644 index 000000000..dc67e9626 --- /dev/null +++ b/packages/react-ui/storybook/stories/widgets/CategoryWidget.stories.js @@ -0,0 +1,93 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import { + Title, + Subtitle, + Primary, + ArgsTable, + Stories, + PRIMARY_STORY +} from '@storybook/addon-docs/blocks'; +import * as cartoSlice from '../../../../react-redux/src/slices/cartoSlice'; +import { AggregationTypes } from '../../../../react-core/src'; +import CategoryWidget from '../../../../react-widgets/src/widgets/CategoryWidget'; +import { mockAppStoreConfiguration } from './utils'; + +const store = mockAppStoreConfiguration(); +store.dispatch( + cartoSlice.setWidgetLoadingState({ widgetId: 'sb-category-id', isLoading: false }) +); + +const mockedData = [...Array(30)].map((_, idx) => ({ + 'sb-column': `Category ${ + idx < 5 ? '1' : idx < 10 ? '2' : idx < 15 ? '3' : idx < 20 ? '4' : '5' + }`, + 'sb-operation-column': idx * 100 +})); +store.dispatch( + cartoSlice.setViewportFeatures({ sourceId: 'sb-data-source', features: mockedData }) +); + +const options = { + title: 'Widgets/CategoryWidget', + component: CategoryWidget, + decorators: [ + (Story) => ( + + + + ) + ], + argTypes: { + operation: { + control: { + type: 'select', + options: Object.values(AggregationTypes) + } + } + }, + parameters: { + docs: { + page: () => ( + <> + + <Subtitle /> + <Primary /> + <ArgsTable story={PRIMARY_STORY} /> + <Stories /> + </> + ) + } + } +}; + +export default options; + +const Template = (args) => <CategoryWidget {...args} />; + +const DEFAULT_PROPS = { + id: 'sb-category-id', + title: 'wrapper title', + dataSource: 'sb-data-source', + column: 'sb-column', + operationColumn: 'sb-operation-column', + operation: 'sum' +}; + +export const Default = Template.bind({}); +Default.args = DEFAULT_PROPS; + +export const WithFormatter = Template.bind({}); +WithFormatter.args = { ...DEFAULT_PROPS, formatter: (v) => `$${v}` }; + +export const WithCustomLabels = Template.bind({}); +WithCustomLabels.args = { + ...DEFAULT_PROPS, + labels: { + 'Category 1': 'Cat. 1', + 'Category 2': 'Cat. 2', + 'Category 3': 'Cat. 3', + 'Category 4': 'Cat. 4', + 'Category 5': 'Cat. 5' + } +}; diff --git a/packages/react-ui/storybook/stories/widgets/FormulaWidget.stories.js b/packages/react-ui/storybook/stories/widgets/FormulaWidget.stories.js new file mode 100644 index 000000000..b0782fc95 --- /dev/null +++ b/packages/react-ui/storybook/stories/widgets/FormulaWidget.stories.js @@ -0,0 +1,76 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import { + Title, + Subtitle, + Primary, + ArgsTable, + Stories, + PRIMARY_STORY +} from '@storybook/addon-docs/blocks'; +import * as cartoSlice from '../../../../react-redux/src/slices/cartoSlice'; +import { AggregationTypes } from '../../../../react-core/src'; +import FormulaWidget from '../../../../react-widgets/src/widgets/FormulaWidget'; +import { mockAppStoreConfiguration } from './utils'; + +const store = mockAppStoreConfiguration(); +store.dispatch( + cartoSlice.setWidgetLoadingState({ widgetId: 'sb-formula-id', isLoading: false }) +); +store.dispatch( + cartoSlice.setViewportFeatures({ + sourceId: 'sb-data-source', + features: [{ 'sb-column': 5000 }, { 'sb-column': 5000 }] + }) +); + +const options = { + title: 'Widgets/FormulaWidget', + component: FormulaWidget, + decorators: [ + (Story) => ( + <Provider store={store}> + <Story /> + </Provider> + ) + ], + argTypes: { + operation: { + control: { + type: 'select', + options: Object.values(AggregationTypes) + } + } + }, + parameters: { + docs: { + page: () => ( + <> + <Title /> + <Subtitle /> + <Primary /> + <ArgsTable story={PRIMARY_STORY} /> + <Stories /> + </> + ) + } + } +}; + +export default options; + +const Template = (args) => <FormulaWidget {...args} />; + +const DEFAULT_PROPS = { + id: 'sb-formula-id', + title: 'wrapper title', + dataSource: 'sb-data-source', + column: 'sb-column', + operation: 'sum' +}; + +export const Default = Template.bind({}); +Default.args = DEFAULT_PROPS; + +export const WithFormatter = Template.bind({}); +WithFormatter.args = { ...DEFAULT_PROPS, formatter: (v) => `$${v}` }; diff --git a/packages/react-ui/storybook/stories/widgets/HistogramWidget.stories.js b/packages/react-ui/storybook/stories/widgets/HistogramWidget.stories.js new file mode 100644 index 000000000..9c8833fc4 --- /dev/null +++ b/packages/react-ui/storybook/stories/widgets/HistogramWidget.stories.js @@ -0,0 +1,81 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import { + Title, + Subtitle, + Primary, + ArgsTable, + Stories, + PRIMARY_STORY +} from '@storybook/addon-docs/blocks'; +import * as cartoSlice from '../../../../react-redux/src/slices/cartoSlice'; +import { AggregationTypes } from '../../../../react-core/src'; +import HistogramWidget from '../../../../react-widgets/src/widgets/HistogramWidget'; +import { mockAppStoreConfiguration } from './utils'; + +const store = mockAppStoreConfiguration(); +store.dispatch( + cartoSlice.setWidgetLoadingState({ widgetId: 'sb-histogram-id', isLoading: false }) +); + +const mockedData = [...Array(40)].map((_, idx) => ({ + 'sb-column': idx < 10 ? 100 : idx < 25 ? 200 : idx < 33 ? 300 : idx < 35 ? 400 : 500 +})); +store.dispatch( + cartoSlice.setViewportFeatures({ sourceId: 'sb-data-source', features: mockedData }) +); + +const options = { + title: 'Widgets/HistogramWidget', + component: HistogramWidget, + decorators: [ + (Story) => ( + <Provider store={store}> + <Story /> + </Provider> + ) + ], + argTypes: { + operation: { + control: { + type: 'select', + options: Object.values(AggregationTypes) + } + } + }, + parameters: { + docs: { + page: () => ( + <> + <Title /> + <Subtitle /> + <Primary /> + <ArgsTable story={PRIMARY_STORY} /> + <Stories /> + </> + ) + } + } +}; + +export default options; + +const Template = (args) => <HistogramWidget {...args} />; + +const DEFAULT_PROPS = { + id: 'sb-histogram-id', + title: 'wrapper title', + dataSource: 'sb-data-source', + column: 'sb-column', + ticks: [200, 300, 400, 500], + operation: 'count' +}; + +export const Default = Template.bind({}); +Default.args = DEFAULT_PROPS; + +export const xAxisFormatter = Template.bind({}); +xAxisFormatter.args = { ...DEFAULT_PROPS, xAxisFormatter: (v) => `${v}$` }; + +export const yAxisFormatter = Template.bind({}); +yAxisFormatter.args = { ...DEFAULT_PROPS, formatter: (v) => `$${v}` }; diff --git a/packages/react-ui/storybook/stories/widgets/PieWidget.stories.js b/packages/react-ui/storybook/stories/widgets/PieWidget.stories.js new file mode 100644 index 000000000..a3cc3738e --- /dev/null +++ b/packages/react-ui/storybook/stories/widgets/PieWidget.stories.js @@ -0,0 +1,87 @@ +import React from 'react'; +import { Provider } from 'react-redux'; +import { + Title, + Subtitle, + Primary, + ArgsTable, + Stories, + PRIMARY_STORY +} from '@storybook/addon-docs/blocks'; +import * as cartoSlice from '../../../../react-redux/src/slices/cartoSlice'; +import { AggregationTypes } from '../../../../react-core/src'; +import PieWidget from '../../../../react-widgets/src/widgets/PieWidget'; +import { mockAppStoreConfiguration } from './utils'; + +const store = mockAppStoreConfiguration(); +store.dispatch( + cartoSlice.setWidgetLoadingState({ widgetId: 'sb-pie-id', isLoading: false }) +); + +const mockedData = [...Array(10)].map((_, idx) => ({ + 'sb-column': `Category ${ + idx < 2 ? '1' : idx < 4 ? '2' : idx < 8 ? '3' : idx < 9 ? '4' : '5' + }`, + 'sb-operation-column': idx * 100 +})); +store.dispatch( + cartoSlice.setViewportFeatures({ sourceId: 'sb-data-source', features: mockedData }) +); + +const options = { + title: 'Widgets/PieWidget', + component: PieWidget, + decorators: [ + (Story) => ( + <Provider store={store}> + <Story /> + </Provider> + ) + ], + argTypes: { + operation: { + control: { + type: 'select', + options: Object.values(AggregationTypes) + } + } + }, + parameters: { + docs: { + page: () => ( + <> + <Title /> + <Subtitle /> + <Primary /> + <ArgsTable story={PRIMARY_STORY} /> + <Stories /> + </> + ) + } + } +}; + +export default options; + +const Template = (args) => <PieWidget {...args} />; + +const DEFAULT_PROPS = { + id: 'sb-pie-id', + title: 'wrapper title', + dataSource: 'sb-data-source', + column: 'sb-column', + operationColumn: 'sb-operation-column', + operation: 'sum' +}; + +export const Default = Template.bind({}); +Default.args = DEFAULT_PROPS; + +export const WithFormatter = Template.bind({}); +WithFormatter.args = { ...DEFAULT_PROPS, formatter: (v) => `$${v}` }; + +export const TooltipFormatter = Template.bind({}); +TooltipFormatter.args = { + ...DEFAULT_PROPS, + tooltipFormatter: (params) => `That's a custom tooltip for: ${params.name}` +}; diff --git a/packages/react-ui/storybook/stories/widgets/utils.js b/packages/react-ui/storybook/stories/widgets/utils.js new file mode 100644 index 000000000..33b71d895 --- /dev/null +++ b/packages/react-ui/storybook/stories/widgets/utils.js @@ -0,0 +1,45 @@ +import { combineReducers, configureStore } from '@reduxjs/toolkit'; +import * as cartoSlice from '../../../../react-redux/src/slices/cartoSlice'; + +const MOCKED_SOURCE = { + credentials: { + username: 'public', + apiKey: 'default_public' + }, + id: 'sb-data-source', + type: 'sql', + data: 'data' +} + +let mockedStore = {}; + +function mockReducerManagerCreation(initialReducers) { + const reducers = { ...initialReducers }; + let combinedReducer = Object.keys(reducers).length + ? combineReducers(reducers) + : () => {}; + + return { + reduce: (state, action) => { + return combinedReducer(state, action); + }, + add: (key, reducer) => { + reducers[key] = reducer; + combinedReducer = combineReducers(reducers); + mockedStore.replaceReducer(combinedReducer); + } + }; +} + +export function mockAppStoreConfiguration() { + const reducerManager = mockReducerManagerCreation(); + mockedStore = configureStore({ + reducer: reducerManager.reduce + }); + + mockedStore.reducerManager = reducerManager; + mockedStore.reducerManager.add('carto', cartoSlice.createCartoSlice({})); + mockedStore.dispatch(cartoSlice.addSource(MOCKED_SOURCE)); + + return mockedStore; +} diff --git a/packages/react-ui/storybook/stories/widgets/CategoryWidgetUI.stories.js b/packages/react-ui/storybook/stories/widgetsUI/CategoryWidgetUI.stories.js similarity index 56% rename from packages/react-ui/storybook/stories/widgets/CategoryWidgetUI.stories.js rename to packages/react-ui/storybook/stories/widgetsUI/CategoryWidgetUI.stories.js index e7c3f4d1d..8250872b3 100644 --- a/packages/react-ui/storybook/stories/widgets/CategoryWidgetUI.stories.js +++ b/packages/react-ui/storybook/stories/widgetsUI/CategoryWidgetUI.stories.js @@ -2,7 +2,7 @@ import React from 'react'; import CategoryWidgetUI from '../../../src/widgets/CategoryWidgetUI'; const options = { - title: 'Widgets/CategoryWidgetUI', + title: 'Widgets UI/CategoryWidgetUI', component: CategoryWidgetUI, argTypes: { selectedCategories: { @@ -20,25 +20,19 @@ const options = { } } }; + export default options; -const Template = (args) => <CategoryWidgetUI {...args}></CategoryWidgetUI>; -const data = [ - { name: 'categoryA', value: 100 }, - { name: 'categoryB', value: 120 }, - { name: 'categoryC', value: 150 }, - { name: 'categoryD', value: 90 }, - { name: 'categoryE', value: 200 }, - { name: 'categoryF', value: 20 }, - { name: 'categoryG', value: 90 } -]; +const Template = (args) => <CategoryWidgetUI {...args} />; + +const data = [...Array(7)].map((_, idx) => ({ + name: `Category ${idx + 1}`, + value: idx * 100 +})); -const dataFiltered = [ - { name: 'categoryA', value: null }, - { name: 'categoryB', value: 120 }, - { name: 'categoryC', value: 100 }, - { name: 'categoryD', value: null } -]; +const filteredData = data.slice(0, 4).map((cat, idx) => { + return { ...cat, value: idx % 2 === 0 ? null : cat.value }; +}); export const Default = Template.bind({}); Default.args = { data }; @@ -53,16 +47,16 @@ export const WithCustomLabels = Template.bind({}); WithCustomLabels.args = { data, labels: { - categoryA: 'Cat. A', - categoryB: 'Cat. B', - categoryC: 'Cat. C', - categoryD: 'Cat. D' + 'Category 1': 'Cat. 1', + 'Category 2': 'Cat. 2', + 'Category 3': 'Cat. 3', + 'Category 4': 'Cat. 4' } }; export const WithSelectedCategories = Template.bind({}); WithSelectedCategories.args = { - data: dataFiltered, - selectedCategories: ['categoryB', 'categoryC'], + data: filteredData, + selectedCategories: ['Category 2', 'Category 4'], onSelectedCategoriesChange: (categories) => console.log(categories) }; diff --git a/packages/react-ui/storybook/stories/widgets/FormulaWidgetUI.stories.js b/packages/react-ui/storybook/stories/widgetsUI/FormulaWidgetUI.stories.js similarity index 72% rename from packages/react-ui/storybook/stories/widgets/FormulaWidgetUI.stories.js rename to packages/react-ui/storybook/stories/widgetsUI/FormulaWidgetUI.stories.js index ae45b6ef7..40af786d3 100644 --- a/packages/react-ui/storybook/stories/widgets/FormulaWidgetUI.stories.js +++ b/packages/react-ui/storybook/stories/widgetsUI/FormulaWidgetUI.stories.js @@ -2,7 +2,7 @@ import React from 'react'; import FormulaWidgetUI from '../../../src/widgets/FormulaWidgetUI'; const options = { - title: 'Widgets/FormulaWidgetUI', + title: 'Widgets UI/FormulaWidgetUI', component: FormulaWidgetUI, argTypes: { formatter: { @@ -12,27 +12,30 @@ const options = { } } }; + export default options; const Template = (args) => <FormulaWidgetUI {...args} />; +const data = 10000; + export const Empty = Template.bind({}); Empty.args = {}; export const Text = Template.bind({}); -Text.args = { data: '$1000000' }; +Text.args = { data: `$${data}` }; export const ValueUnit = Template.bind({}); -ValueUnit.args = { data: { value: 1000000, unit: '$' } }; +ValueUnit.args = { data: { value: data, unit: '$' } }; export const FormatterText = Template.bind({}); -FormatterText.args = { data: 1000000, formatter: (v) => `$${v}` }; +FormatterText.args = { data, formatter: (v) => `$${v}` }; export const FormatterValueUnit = Template.bind({}); -FormatterValueUnit.args = { data: 1000000 }; +FormatterValueUnit.args = { data }; export const FormatterValueUnitBefore = Template.bind({}); FormatterValueUnitBefore.args = { - data: 1000000, + data, unitBefore: true }; diff --git a/packages/react-ui/storybook/stories/widgets/HistogramWidgetUI.stories.js b/packages/react-ui/storybook/stories/widgetsUI/HistogramWidgetUI.stories.js similarity index 52% rename from packages/react-ui/storybook/stories/widgets/HistogramWidgetUI.stories.js rename to packages/react-ui/storybook/stories/widgetsUI/HistogramWidgetUI.stories.js index dcaaa5e04..c53dedb3b 100644 --- a/packages/react-ui/storybook/stories/widgets/HistogramWidgetUI.stories.js +++ b/packages/react-ui/storybook/stories/widgetsUI/HistogramWidgetUI.stories.js @@ -1,65 +1,64 @@ import React from 'react'; import HistogramWidgetUI from '../../../src/widgets/HistogramWidgetUI'; -// This default export determines where your story goes in the story list const options = { - title: 'Widgets/HistogramWidgetUI', + title: 'Widgets UI/HistogramWidgetUI', component: HistogramWidgetUI }; + export default options; -const DATA = [220, 350, 1900, 900, 630, 100]; +const Template = (args) => <HistogramWidgetUI {...args} />; -const DATA_AXIS = ['1000', '2000', '3000', '4000', '5000', '6000']; +const data = [100, 300, 500, 250, 50, 200, 100]; -const Template = (args) => <HistogramWidgetUI {...args} />; +const dataAxis = [100, 200, 300, 400, 500, 600]; export const Empty = Template.bind({}); Empty.args = { name: 'STORE', - data: DATA, - dataAxis: DATA_AXIS, - selectedBars: [] + data, + dataAxis, + selectedBars: [], + tooltipFormatter: () => {} }; export const Simple = Template.bind({}); Simple.args = { name: 'STORE', - data: DATA, - onSelectedBarsChange: (event) => { - console.log(event); - }, + data, + onSelectedBarsChange: (evt) => console.log(evt), selectedBars: [], - dataAxis: DATA_AXIS, - tooltipFormatter: ([serie]) => serie.value + ' $' + dataAxis, + tooltipFormatter: ([{ value }]) => value + ' $' }; export const xAxisFormatter = Template.bind({}); xAxisFormatter.args = { name: 'STORE', - data: DATA, - dataAxis: DATA_AXIS, + data, + dataAxis, xAxisFormatter: (v) => `${v / 1000}k`, - tooltipFormatter: ([serie]) => serie.value + ' $' + tooltipFormatter: ([{ value }]) => value + ' $' }; export const yAxisFormatter = Template.bind({}); yAxisFormatter.args = { name: 'STORE', - data: DATA, - dataAxis: DATA_AXIS, + data, + dataAxis, yAxisFormatter: (v) => `${v / 1000}k`, - tooltipFormatter: ([serie]) => serie.value + ' $' + tooltipFormatter: ([{ value }]) => value + ' $' }; export const Filtered = Template.bind({}); Filtered.args = { name: 'STORE', - data: DATA, - dataAxis: DATA_AXIS, + data, + dataAxis, selectedBars: [1, 2], - tooltipFormatter: ([serie]) => serie.value + ' $', - onSelectedBarsChange: (event) => { + tooltipFormatter: ([{ value }]) => value + ' $', + onSelectedBarsChange: (evt) => { // Do nothing } }; diff --git a/packages/react-ui/storybook/stories/widgets/PieWidgetUI.stories.js b/packages/react-ui/storybook/stories/widgetsUI/PieWidgetUI.stories.js similarity index 93% rename from packages/react-ui/storybook/stories/widgets/PieWidgetUI.stories.js rename to packages/react-ui/storybook/stories/widgetsUI/PieWidgetUI.stories.js index 1fa7b7609..f28b13c68 100644 --- a/packages/react-ui/storybook/stories/widgets/PieWidgetUI.stories.js +++ b/packages/react-ui/storybook/stories/widgetsUI/PieWidgetUI.stories.js @@ -1,9 +1,8 @@ import React from 'react'; import PieWidgetUI from '../../../src/widgets/PieWidgetUI'; -// This default export determines where your story goes in the story list const options = { - title: 'Widgets/PieWidgetUI', + title: 'Widgets UI/PieWidgetUI', component: PieWidgetUI }; diff --git a/packages/react-ui/storybook/stories/widgets/WrapperWidgetUI.stories.js b/packages/react-ui/storybook/stories/widgetsUI/WrapperWidgetUI.stories.js similarity index 98% rename from packages/react-ui/storybook/stories/widgets/WrapperWidgetUI.stories.js rename to packages/react-ui/storybook/stories/widgetsUI/WrapperWidgetUI.stories.js index 5cd891dc8..cccd836b3 100644 --- a/packages/react-ui/storybook/stories/widgets/WrapperWidgetUI.stories.js +++ b/packages/react-ui/storybook/stories/widgetsUI/WrapperWidgetUI.stories.js @@ -6,7 +6,7 @@ import AddLocationIcon from '@material-ui/icons/AddLocation'; import WrapperWidgetUI from '.../../../src/widgets/WrapperWidgetUI'; const options = { - title: 'Widgets/WrapperWidgetUI', + title: 'Widgets UI/WrapperWidgetUI', component: WrapperWidgetUI, argTypes: { actions: { diff --git a/packages/react-widgets/reference.md b/packages/react-widgets/reference.md index 731f794d3..7a3a52486 100644 --- a/packages/react-widgets/reference.md +++ b/packages/react-widgets/reference.md @@ -14,6 +14,7 @@ Renders a `<CategoryWidget />` component | [props.operationColumn] | <code>string</code> | | Name of the data source's column to operate with. If not defined it will default to the one defined in `column`. | | props.operation | <code>string</code> | | Operation to apply to the operationColumn. Must be one of those defined in `AggregationTypes` object. | | [props.formatter] | [<code>formatterCallback</code>](#formatterCallback) | | Function to format each value returned. | +| [props.labels] | <code>Object</code> | <code>{}</code> | Overwrite category labels. | | [props.viewportFilter] | <code>boolean</code> | <code>true</code> | Defines whether filter by the viewport or globally. | | [props.onError] | [<code>errorCallback</code>](#errorCallback) | | Function to handle error messages from the widget. | | [props.wrapperProps] | <code>Object</code> | | Extra props to pass to [WrapperWidgetUI](https://storybook-react.carto.com/?path=/docs/widgets-wrapperwidgetui--default) | diff --git a/packages/react-widgets/src/widgets/CategoryWidget.js b/packages/react-widgets/src/widgets/CategoryWidget.js index d34d9a99b..31117d5d9 100644 --- a/packages/react-widgets/src/widgets/CategoryWidget.js +++ b/packages/react-widgets/src/widgets/CategoryWidget.js @@ -21,6 +21,7 @@ import useWidgetLoadingState from './useWidgetLoadingState'; * @param {string} [props.operationColumn] - Name of the data source's column to operate with. If not defined it will default to the one defined in `column`. * @param {string} props.operation - Operation to apply to the operationColumn. Must be one of those defined in `AggregationTypes` object. * @param {formatterCallback} [props.formatter] - Function to format each value returned. + * @param {Object} [props.labels] - Overwrite category labels * @param {boolean} [props.viewportFilter=true] - Defines whether filter by the viewport or globally. * @param {errorCallback} [props.onError] - Function to handle error messages from the widget. * @param {Object} [props.wrapperProps] - Extra props to pass to [WrapperWidgetUI](https://storybook-react.carto.com/?path=/docs/widgets-wrapperwidgetui--default) @@ -129,11 +130,14 @@ CategoryWidget.propTypes = { operationColumn: PropTypes.string, operation: PropTypes.oneOf(Object.values(AggregationTypes)).isRequired, formatter: PropTypes.func, + labels: PropTypes.object, viewportFilter: PropTypes.bool, - onError: PropTypes.func + onError: PropTypes.func, + wrapperProps: PropTypes.object }; CategoryWidget.defaultProps = { + labels: {}, viewportFilter: true, wrapperProps: {} }; diff --git a/packages/react-widgets/src/widgets/FormulaWidget.js b/packages/react-widgets/src/widgets/FormulaWidget.js index ab0e6ecc6..5f855aab9 100644 --- a/packages/react-widgets/src/widgets/FormulaWidget.js +++ b/packages/react-widgets/src/widgets/FormulaWidget.js @@ -89,7 +89,8 @@ FormulaWidget.propTypes = { operation: PropTypes.oneOf(Object.values(AggregationTypes)).isRequired, formatter: PropTypes.func, viewportFilter: PropTypes.bool, - onError: PropTypes.func + onError: PropTypes.func, + wrapperProps: PropTypes.object }; FormulaWidget.defaultProps = { diff --git a/packages/react-widgets/src/widgets/HistogramWidget.js b/packages/react-widgets/src/widgets/HistogramWidget.js index 7950ed598..0c8c3bd46 100644 --- a/packages/react-widgets/src/widgets/HistogramWidget.js +++ b/packages/react-widgets/src/widgets/HistogramWidget.js @@ -156,7 +156,8 @@ HistogramWidget.propTypes = { tooltip: PropTypes.bool, ticks: PropTypes.array.isRequired, viewportFilter: PropTypes.bool, - onError: PropTypes.func + onError: PropTypes.func, + wrapperProps: PropTypes.object }; HistogramWidget.defaultProps = { diff --git a/packages/react-widgets/src/widgets/PieWidget.js b/packages/react-widgets/src/widgets/PieWidget.js index 2609e19e7..cc0cff8e3 100644 --- a/packages/react-widgets/src/widgets/PieWidget.js +++ b/packages/react-widgets/src/widgets/PieWidget.js @@ -153,7 +153,8 @@ PieWidget.propTypes = { formatter: PropTypes.func, tooltipFormatter: PropTypes.func, viewportFilter: PropTypes.bool, - onError: PropTypes.func + onError: PropTypes.func, + wrapperProps: PropTypes.object }; PieWidget.defaultProps = {