diff --git a/.circleci/config.yml b/.circleci/config.yml index a13704284..8b3d78f44 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,7 +31,7 @@ jobs: python -m venv venv || virtualenv venv . venv/bin/activate pip install -r dev-requirements.txt --quiet - git clone --depth 1 git@github.com:plotly/dash.git dash-main + git clone --depth 1 -b exp-dynamic git@github.com:plotly/dash.git dash-main pip install -e ./dash-main[dev] --quiet - run: @@ -107,7 +107,7 @@ jobs: python -m venv venv || virtualenv venv . venv/bin/activate pip install -r dev-requirements.txt --quiet - git clone --depth 1 git@github.com:plotly/dash.git dash-main + git clone --depth 1 -b exp-dynamic git@github.com:plotly/dash.git dash-main pip install -e ./dash-main[dev] --quiet - run: @@ -212,7 +212,7 @@ jobs: name: Install dependencies (dash) command: | . venv/bin/activate - git clone --depth 1 git@github.com:plotly/dash.git dash-main + git clone --depth 1 -b exp-dynamic git@github.com:plotly/dash.git dash-main pip install -e ./dash-main[dev,testing] --quiet cd dash-main/dash-renderer && npm run build && pip install -e . && cd ../.. diff --git a/.config/webpack/base.js b/.config/webpack/base.js index 34e2f9887..ba471c134 100644 --- a/.config/webpack/base.js +++ b/.config/webpack/base.js @@ -1,12 +1,15 @@ - const path = require('path'); +const WebpackDashDynamicImport = require('@plotly/webpack-dash-dynamic-import'); + +const basePreprocessing = require('./base.preprocessing'); const packagejson = require('./../../package.json'); const dashLibraryName = packagejson.name.replace(/-/g, '_'); + module.exports = (options = {}) => { const babel = options.babel || undefined; - const preprocessor = options.preprocessor || {}; + const preprocessor = basePreprocessing(options.preprocessor); const mode = options.mode || 'development'; const ts = options.ts || {}; @@ -24,6 +27,7 @@ module.exports = (options = {}) => { mode: mode, output: { path: path.resolve(__dirname, `./../../${dashLibraryName}`), + chunkFilename: '[name].js', filename: '[name].js', library: dashLibraryName, libraryTarget: 'window' @@ -87,6 +91,20 @@ module.exports = (options = {}) => { tests: path.resolve('./tests') }, extensions: ['.js', '.ts', '.tsx'] - } + }, + optimization: { + splitChunks: { + chunks: 'async', + name: true, + cacheGroups: { + async: { + + } + } + } + }, + plugins: [ + new WebpackDashDynamicImport() + ] }; }; \ No newline at end of file diff --git a/.config/webpack/base.preprocessing.js b/.config/webpack/base.preprocessing.js new file mode 100644 index 000000000..84323524a --- /dev/null +++ b/.config/webpack/base.preprocessing.js @@ -0,0 +1,7 @@ +module.exports = ({ definitions, variables, ...options } = {}) => ({ + ...options, + definitions: definitions || [], + variables: Object.assign({ + mode: 'lazy' + }, variables || {}) +}); \ No newline at end of file diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js index 1da256ced..c9239abe9 100644 --- a/.storybook/webpack.config.js +++ b/.storybook/webpack.config.js @@ -1,8 +1,14 @@ let babel = require('./babel.config.js'); let config = require('./../.config/webpack/base.js')({ - babel + babel, + preprocessor: { + variables: { + mode: 'eager' + } + } }); config.externals = {}; +delete config.plugins; module.exports = config; \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d7385b9f..01778c50d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## Unreleased +### Changed +- [#554](https://github.com/plotly/dash-table/pull/554) Async loading of `xlsx` library on export + ## [4.4.1] - 2019-08-17 ### Fixed - [#618](https://github.com/plotly/dash-table/issues/618) Fix a bug with keyboard navigation not working correctly in certain circumstances when the table contains `readonly` columns. diff --git a/MANIFEST.in b/MANIFEST.in index efff6afda..3201355c4 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,7 @@ include dash_table/bundle.js include dash_table/bundle.js.map +include dash_table/async~*.js +include dash_table/async~*.js.map include dash_table/metadata.json include dash_table/package-info.json include LICENSE diff --git a/dash_table_base/__init__.py b/dash_table_base/__init__.py index 66baed638..7f4e7219b 100644 --- a/dash_table_base/__init__.py +++ b/dash_table_base/__init__.py @@ -44,6 +44,22 @@ ).format(__version__), 'namespace': package_name, 'dynamic': True + }, + { + 'relative_package_path': 'async~export.js', + 'external_url': ( + 'https://unpkg.com/dash-table@{}/dash_table/async~export.js' + ).format(__version__), + 'namespace': package_name, + 'async': True + }, + { + 'relative_package_path': 'async~export.js.map', + 'external_url': ( + 'https://unpkg.com/dash-table@{}/dash_table/async~export.js.map' + ).format(__version__), + 'namespace': package_name, + 'dynamic': True } ] diff --git a/package-lock.json b/package-lock.json index ae5a33e18..fc76a417c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2246,6 +2246,12 @@ } } }, + "@plotly/webpack-dash-dynamic-import": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@plotly/webpack-dash-dynamic-import/-/webpack-dash-dynamic-import-1.0.0.tgz", + "integrity": "sha512-ZkK0rwzAeKuYroBLWh7wHevWBG3Ljg2Tp9yrArXfxj75c2OlXpOlJEZgji9VHZZj0VvNEuBwxeG182fIK5FA4Q==", + "dev": true + }, "@reach/router": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@reach/router/-/router-1.2.1.tgz", diff --git a/package.json b/package.json index 8d00d722d..2dfa97972 100644 --- a/package.json +++ b/package.json @@ -15,11 +15,11 @@ "preprivate::opentests": "run-s private::wait*", "preprivate::test.server": "run-s private::wait_dash*", "preprivate::test.standalone": "run-s private::wait_js", - "pretest.standalone": "run-s private::build:js-test", + "pretest.standalone": "run-s private::build:js-test-standalone", "private::build": "node --max_old_space_size=4096 node_modules/webpack/bin/webpack --display-reasons --bail", "private::build:js": "run-s \"private::build -- --mode production\"", - "private::build:js-dev": "run-s \"private::build -- --mode development --config webpack.dev.config.js\"", "private::build:js-test": "run-s \"private::build -- --mode development --config webpack.test.config.js\"", + "private::build:js-test-standalone": "run-s \"private::build -- --mode development --config webpack.test.standalone.config.js\"", "private::build:js-test-watch": "run-s \"private::build -- --mode development --config webpack.test.config.js --watch\"", "private::build:py": "dash-generate-components src/dash-table/dash/DataTable.js dash_table -p package-info.json && cp dash_table_base/** dash_table/ && dash-generate-components src/dash-table/dash/DataTable.js dash_table -p package-info.json --r-prefix 'dash'", "private::host_dash8081": "python tests/cypress/dash/v_be_page.py", @@ -61,6 +61,7 @@ "devDependencies": { "@babel/cli": "^7.6.2", "@babel/core": "^7.6.2", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/polyfill": "^7.6.0", "@babel/preset-env": "^7.6.2", "@babel/preset-react": "^7.0.0", @@ -70,6 +71,7 @@ "@fortawesome/free-solid-svg-icons": "^5.11.2", "@fortawesome/react-fontawesome": "^0.1.4", "@percy/storybook": "^3.2.0", + "@plotly/webpack-dash-dynamic-import": "^1.0.0", "@storybook/cli": "^5.1.11", "@storybook/react": "^5.1.11", "@types/d3-format": "^1.3.1", diff --git a/src/dash-table/LazyLoader.ts b/src/dash-table/LazyLoader.ts new file mode 100644 index 000000000..a8d89e941 --- /dev/null +++ b/src/dash-table/LazyLoader.ts @@ -0,0 +1,5 @@ +export default class LazyLoader { + public static get xlsx() { + return import(/* webpackChunkName: "export", webpackMode: "$${{mode}}" */ 'xlsx'); + } +} \ No newline at end of file diff --git a/src/dash-table/components/Export/index.tsx b/src/dash-table/components/Export/index.tsx index 63a75fe6c..259b94f1d 100644 --- a/src/dash-table/components/Export/index.tsx +++ b/src/dash-table/components/Export/index.tsx @@ -1,7 +1,6 @@ -import XLSX from 'xlsx'; import React from 'react'; import { IDerivedData, Columns, ExportHeaders, ExportFormat, ExportColumns } from 'dash-table/components/Table/props'; -import { createWorkbook, createHeadings, createWorksheet } from './utils'; +import { createWorkbook, createHeadings, exportWorkbook } from './utils'; import getHeaderRows from 'dash-table/derived/header/headerRows'; interface IExportButtonProps { @@ -21,19 +20,16 @@ export default React.memo((props: IExportButtonProps) => { const exportedColumns = export_columns === ExportColumns.Visible ? visibleColumns : columns; - const handleExport = () => { + const handleExport = async () => { const columnID = exportedColumns.map(column => column.id); const columnHeaders = exportedColumns.map(column => column.name); const maxLength = getHeaderRows(columns); const heading = (export_headers !== ExportHeaders.None) ? createHeadings(columnHeaders, maxLength) : []; - const ws = createWorksheet(heading, virtual_data.data, columnID, export_headers, merge_duplicate_headers); - const wb = createWorkbook(ws); - if (export_format === ExportFormat.Xlsx) { - XLSX.writeFile(wb, 'Data.xlsx', {bookType: 'xlsx', type: 'buffer'}); - } else if (export_format === ExportFormat.Csv) { - XLSX.writeFile(wb, 'Data.csv', {bookType: 'csv', type: 'buffer'}); - } + + const wb = await createWorkbook(heading, virtual_data.data, columnID, export_headers, merge_duplicate_headers); + + await exportWorkbook(wb, export_format); }; return (
diff --git a/src/dash-table/components/Export/utils.tsx b/src/dash-table/components/Export/utils.tsx index c5c308ccc..a88bbbb5d 100644 --- a/src/dash-table/components/Export/utils.tsx +++ b/src/dash-table/components/Export/utils.tsx @@ -1,6 +1,8 @@ import * as R from 'ramda'; -import XLSX from 'xlsx'; +import { WorkBook } from 'xlsx/types'; + import { Data, ExportHeaders } from 'dash-table/components/Table/props'; +import LazyLoader from 'dash-table/LazyLoader'; interface IMergeObject { s: {r: number, c: number}; @@ -47,13 +49,9 @@ export function getMergeRanges(array: string[][]) { return R.filter((item: IMergeObject) => item.s.c !== item.e.c || item.s.r !== item.e.r, apiMergeArray); } -export function createWorkbook(ws: XLSX.WorkSheet) { - const wb = XLSX.utils.book_new(); - XLSX.utils.book_append_sheet(wb, ws, 'SheetJS'); - return wb; -} +export async function createWorkbook(heading: string[][], data: Data, columnID: string[], exportHeader: string, mergeDuplicateHeaders: boolean ) { + const XLSX = await LazyLoader.xlsx; -export function createWorksheet(heading: string[][], data: Data, columnID: string[], exportHeader: ExportHeaders, mergeDuplicateHeaders: boolean) { const ws = XLSX.utils.aoa_to_sheet([]); data = R.map(R.pick(columnID))(data); @@ -73,7 +71,20 @@ export function createWorksheet(heading: string[][], data: Data, columnID: strin } else if (exportHeader === ExportHeaders.Ids) { XLSX.utils.sheet_add_json(ws, data, { header: columnID }); } - return ws; + + const wb = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(wb, ws, 'SheetJS'); + return wb; +} + +export async function exportWorkbook (wb: WorkBook, format: string) { + const XLSX = await LazyLoader.xlsx; + + if (format === 'xlsx') { + XLSX.writeFile(wb, 'Data.xlsx', { bookType: 'xlsx', type: 'buffer' }); + } else if (format === 'csv') { + XLSX.writeFile(wb, 'Data.csv', { bookType: 'csv', type: 'buffer' }); + } } export function createHeadings(columnHeaders: (string | string[])[], maxLength: number) { diff --git a/src/dash-table/dash/DataTable.js b/src/dash-table/dash/DataTable.js index 67c225f66..41be99ea1 100644 --- a/src/dash-table/dash/DataTable.js +++ b/src/dash-table/dash/DataTable.js @@ -1307,4 +1307,4 @@ DataTable.persistenceTransforms = { }; DataTable.defaultProps = defaultProps; -DataTable.propTypes = propTypes; +DataTable.propTypes = propTypes; \ No newline at end of file diff --git a/tests/cypress/plugins/index.js b/tests/cypress/plugins/index.js index a943f34c3..9c2541b07 100644 --- a/tests/cypress/plugins/index.js +++ b/tests/cypress/plugins/index.js @@ -2,7 +2,7 @@ const wp = require('@cypress/webpack-preprocessor'); module.exports = on => { const options = { - webpackOptions: require('../../../webpack.test.config.js') + webpackOptions: require('../../../webpack.test.standalone.config.js') }; on('file:preprocessor', wp(options)); diff --git a/tests/cypress/tests/unit/exportUtils_tests.ts b/tests/cypress/tests/unit/exportUtils_tests.ts index d5600fb21..74c437e25 100644 --- a/tests/cypress/tests/unit/exportUtils_tests.ts +++ b/tests/cypress/tests/unit/exportUtils_tests.ts @@ -1,7 +1,8 @@ -import { transformMultiDimArray, getMergeRanges, createHeadings, createWorksheet } from 'dash-table/components/Export/utils'; import * as R from 'ramda'; import { ExportHeaders } from 'dash-table/components/Table/props'; +import { transformMultiDimArray, getMergeRanges, createHeadings, createWorkbook } from 'dash-table/components/Export/utils'; + describe('export', () => { describe('transformMultiDimArray', () => { @@ -225,10 +226,10 @@ describe('export', () => { ]; const columnID = ['col1', 'col2', 'col4']; - it('create sheet with column names as headers for name or display header mode', () => { - const wsName = createWorksheet(Headings, data, columnID, ExportHeaders.Names, true); - const wsDisplay = createWorksheet(Headings, data, columnID, ExportHeaders.Display, true); - const wsDisplayNoMerge = createWorksheet(Headings, data, columnID, ExportHeaders.Display, false); + it('create sheet with column names as headers for name or display header mode', async () => { + const wsName = await createWorkbook(Headings, data, columnID, ExportHeaders.Names, true); + const wsDisplay = await createWorkbook(Headings, data, columnID, ExportHeaders.Display, true); + const wsDisplayNoMerge = await createWorkbook(Headings, data, columnID, ExportHeaders.Display, false); const expectedWS = { A1: {t: 's', v: 'rows'}, A2: {t: 's', v: 'rows'}, @@ -256,12 +257,12 @@ describe('export', () => { expectedWSDisplay['!merges'] = [ {s: {r: 0, c: 0}, e: {r: 0, c: 1}}, {s: {r: 1, c: 1}, e: {r: 1, c: 2}}, {s: {r: 3, c: 0}, e: {r: 3, c: 2}} ]; - expect(wsName).to.deep.equal(expectedWS); - expect(wsDisplayNoMerge).to.deep.equal(expectedWS); - expect(wsDisplay).to.deep.equal(expectedWSDisplay); + expect(wsName.Sheets.SheetJS).to.deep.equal(expectedWS); + expect(wsDisplayNoMerge.Sheets.SheetJS).to.deep.equal(expectedWS); + expect(wsDisplay.Sheets.SheetJS).to.deep.equal(expectedWSDisplay); }); - it('create sheet with column ids as headers', () => { - const ws = createWorksheet(Headings, data, columnID, ExportHeaders.Ids, true); + it('create sheet with column ids as headers', async () => { + const ws = await createWorkbook(Headings, data, columnID, ExportHeaders.Ids, true); const expectedWS = { A1: {t: 's', v: 'col1'}, A2: {t: 'n', v: 1}, @@ -276,10 +277,10 @@ describe('export', () => { C3: {t: 'n', v: 4}, C4: {t: 'n', v: 3}}; expectedWS['!ref'] = 'A1:C4'; - expect(ws).to.deep.equal(expectedWS); + expect(ws.Sheets.SheetJS).to.deep.equal(expectedWS); }); - it('create sheet with no headers', () => { - const ws = createWorksheet([], data, columnID, ExportHeaders.None, true); + it('create sheet with no headers', async () => { + const ws = await createWorkbook([], data, columnID, ExportHeaders.None, true); const expectedWS = { A1: {t: 'n', v: 1}, A2: {t: 'n', v: 2}, @@ -291,15 +292,15 @@ describe('export', () => { C2: {t: 'n', v: 4}, C3: {t: 'n', v: 3}}; expectedWS['!ref'] = 'A1:C3'; - expect(ws).to.deep.equal(expectedWS); + expect(ws.Sheets.SheetJS).to.deep.equal(expectedWS); }); - it('create sheet with undefined column for clearable columns', () => { + it('create sheet with undefined column for clearable columns', async () => { const newData = [ {col2: 2, col4: 3}, {col2: 3, col4: 4}, {col2: 2, col4: 3} ]; - const ws = createWorksheet(Headings, newData, columnID, ExportHeaders.Display, false); + const ws = await createWorkbook(Headings, newData, columnID, ExportHeaders.Display, false); const expectedWS = {A1: {t: 's', v: 'rows'}, A2: {t: 's', v: 'rows'}, A3: {t: 's', v: 'rows'}, @@ -319,7 +320,7 @@ describe('export', () => { C6: {t: 'n', v: 4}, C7: {t: 'n', v: 3}}; expectedWS['!ref'] = 'A1:C7'; - expect(ws).to.deep.equal(expectedWS); + expect(ws.Sheets.SheetJS).to.deep.equal(expectedWS); }); }); diff --git a/tests/visual/percy-storybook/Border.defaults.percy.tsx b/tests/visual/percy-storybook/Border.defaults.percy.tsx index bf3e2998c..9d3a2888b 100644 --- a/tests/visual/percy-storybook/Border.defaults.percy.tsx +++ b/tests/visual/percy-storybook/Border.defaults.percy.tsx @@ -93,7 +93,7 @@ storiesOf('DashTable/Border (available space filled)', module) fixed_rows={{ headers: true }} />)) .add('with no frozen rows and frozen columns', () => ()) .add('with frozen rows and frozen columns', () => ( { // update active and selected cells for the new cell object format - const {data, columns, active_cell, selected_cells} = fixture.props; + const { data, columns, active_cell, selected_cells } = fixture.props; if (Array.isArray(active_cell)) { fixture.props.active_cell = makeCell( active_cell[0], active_cell[1], data as any[], columns as any[] @@ -309,7 +309,7 @@ storiesOf('DashTable/Without id', module) fixed_rows={{ headers: true }} row_deletable={true} row_selectable={true} - style_table={{height: 500, width: 200}} + style_table={{ height: 500, width: 200 }} style_data_conditional={style_data_conditional} />)) .add('with set height and width and colors', () => ()) @@ -335,7 +335,7 @@ storiesOf('DashTable/Without id', module) fixed_rows={{ headers: true }} row_deletable={true} row_selectable={true} - style_table={{height: 500, width: 400}} + style_table={{ height: 500, width: 400 }} css={[{ selector: '.dash-spreadsheet', rule: 'border: 4px solid hotpink' @@ -349,7 +349,7 @@ storiesOf('DashTable/Without id', module) fixed_rows={{ headers: true }} row_deletable={true} row_selectable={true} - style_table={{height: 500, width: 400}} + style_table={{ height: 500, width: 400 }} css={[{ selector: '.dash-spreadsheet', rule: 'border: 4px solid cyan' @@ -359,27 +359,27 @@ storiesOf('DashTable/Without id', module) ); storiesOf('DashTable/Export', module) - .add('Export Button for xlsx file', () => ()) - .add('Export Button for csv file', () => ()) - .add('No export Button for file formatted not supported', () => ()) - .add('No export Button', () => ()); + .add('Export Button for xlsx file', () => ()) + .add('Export Button for csv file', () => ()) + .add('No export Button for file formatted not supported', () => ()) + .add('No export Button', () => ()); diff --git a/tests/visual/percy-storybook/LoadingState.percy.tsx b/tests/visual/percy-storybook/LoadingState.percy.tsx index da8e5b3d5..96633cdb3 100644 --- a/tests/visual/percy-storybook/LoadingState.percy.tsx +++ b/tests/visual/percy-storybook/LoadingState.percy.tsx @@ -6,14 +6,12 @@ import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; - const data = [ { City: 'NYC', Neighborhood: 'Brooklyn', 'Temperature (F)': 70 }, { City: 'Montreal', Neighborhood: 'Mile End', 'Temperature (F)': 60 }, { City: 'Los Angeles', Neighborhood: 'Venice', 'Temperature (F)': 90 } ]; - const columns = R.map( i => ({ name: i, id: i, presentation: 'dropdown' }), ['City', 'Neighborhood', 'Temperature (F)'] diff --git a/tests/visual/percy-storybook/Style.percy.tsx b/tests/visual/percy-storybook/Style.percy.tsx index 0c76a64fb..6499c775c 100644 --- a/tests/visual/percy-storybook/Style.percy.tsx +++ b/tests/visual/percy-storybook/Style.percy.tsx @@ -136,8 +136,8 @@ storiesOf('DashTable/Style type condition', module) .add('single selected cells on dark themes', () => ( ({ name: i, id: i }), R.keysIn(data[0])) @@ -155,8 +155,8 @@ storiesOf('DashTable/Style type condition', module) .add('multiple selected cells on dark themes', () => ( ({ name: i, id: i }), R.keysIn(data[0])) @@ -356,8 +356,8 @@ storiesOf('DashTable/Style type condition', module) />)) .add('paging', () => ( R.merge(col, { + data={mock.data} + columns={mock.columns.map((col: any) => R.merge(col, { name: col.name, deletable: true }))} @@ -366,7 +366,7 @@ storiesOf('DashTable/Style type condition', module) }} row_deletable={true} row_selectable={true} - pagination_mode= {'fe'} + pagination_mode={'fe'} style_data_conditional={[{ if: { column_editable: true }, background_color: 'MediumPurple' }]} diff --git a/tests/visual/percy-storybook/Types.percy.tsx b/tests/visual/percy-storybook/Types.percy.tsx index 83d635ffb..5c957c6e5 100644 --- a/tests/visual/percy-storybook/Types.percy.tsx +++ b/tests/visual/percy-storybook/Types.percy.tsx @@ -5,14 +5,14 @@ import DataTable from 'dash-table/dash/DataTable'; const setProps = () => { }; const columns: { name: string[]; id: string; presentation?: string }[] = [ - { name: ['String'], id: 'string' }, - { name: ['Number'], id: 'number' }, - { name: ['Date'], id: 'date' }, - { name: ['Boolean'], id: 'boolean' }, - { name: ['Any'], id: 'any' }, + { name: ['String'], id: 'string' }, + { name: ['Number'], id: 'number' }, + { name: ['Date'], id: 'date' }, + { name: ['Boolean'], id: 'boolean' }, + { name: ['Any'], id: 'any' }, ]; -const columns_dd = columns.map(i => ({...i, presentation: 'dropdown'})); +const columns_dd = columns.map(i => ({ ...i, presentation: 'dropdown' })); storiesOf('DashTable/Types', module) .add('types input', () => ()) .add('types dropdown', () => ( ({ label: `label: ${i}`, value: i }), - ['Montreal', 'Vermont', 'New York City', 'Boston'] - ) - }, - number: { - options: R.map( - i => ({ label: `label: ${i}`, value: i }), - [1, 2, 3, 4] - ) - }, - date: { - options: R.map( - i => ({ label: `label: ${i}`, value: i }), - ['2015-01-01', '2015-10-24', '2016-05-10', '2017-11-11'] - ) - }, - boolean: { - options: R.map( - i => ({ label: `label: ${i}`, value: i }), - [true, false] - ) - }, - any: { - options: R.map( - i => ({ label: `label: ${i}`, value: i }), - ['Montreal', 1, '2015-01-01', true] - ) - } - }} - />)); \ No newline at end of file + setProps={setProps} + id='types dropdown' + data={[ + { string: 'Montreal', number: 1, date: '2015-01-01', boolean: true, any: 'Montreal' }, + { string: 'Vermont', number: 2, date: '2015-10-24', boolean: false, any: 1 }, + { string: 'New York City', number: 3, date: '2016-05-10', boolean: true, any: '2015-01-01' }, + { string: 'Boston', number: 4, date: '2017-11-11', boolean: false, any: true }, + ]} + columns={columns_dd} + editable={false} + dropdown={{ + string: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + ['Montreal', 'Vermont', 'New York City', 'Boston'] + ) + }, + number: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + [1, 2, 3, 4] + ) + }, + date: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + ['2015-01-01', '2015-10-24', '2016-05-10', '2017-11-11'] + ) + }, + boolean: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + [true, false] + ) + }, + any: { + options: R.map( + i => ({ label: `label: ${i}`, value: i }), + ['Montreal', 1, '2015-01-01', true] + ) + } + }} + />)); \ No newline at end of file diff --git a/tests/visual/percy-storybook/Width.percentages.percy.tsx b/tests/visual/percy-storybook/Width.percentages.percy.tsx index 609a4989c..f88c6633e 100644 --- a/tests/visual/percy-storybook/Width.percentages.percy.tsx +++ b/tests/visual/percy-storybook/Width.percentages.percy.tsx @@ -3,6 +3,7 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import random from 'core/math/random'; import DataTable from 'dash-table/dash/DataTable'; + const setProps = () => { }; const columns = ['a', 'b', 'c']; @@ -42,18 +43,18 @@ const props = Object.assign({}, baseProps, { storiesOf('DashTable/Width percentages', module) .add('without frozen columns or rows', () => ()) + {...props} + />)) .add('with frozen rows', () => ()) + />)) .add('with frozen columns', () => ()) .add('with frozen rows and frozen columns', () => ()); \ No newline at end of file diff --git a/tsconfig.base.json b/tsconfig.base.json index 9b6cfed5b..00915963c 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -5,7 +5,7 @@ "emitDecoratorMetadata": false, "experimentalDecorators": true, "jsx": "react", - "lib": ["esnext", "dom"], + "lib": ["esnext", "dom", "es2018.promise"], "module": "esnext", "moduleResolution": "node", "noImplicitAny": true, diff --git a/webpack.dev.config.js b/webpack.dev.config.js index 856ff0cb0..e9b24747f 100644 --- a/webpack.dev.config.js +++ b/webpack.dev.config.js @@ -5,4 +5,7 @@ const options = { mode: 'development' }; -module.exports = require('./.config/webpack/base.js')(options); \ No newline at end of file +let config = require('./.config/webpack/base.js')(options); +delete config.plugins; + +module.exports = config; \ No newline at end of file diff --git a/webpack.test.config.js b/webpack.test.config.js index cbd73489b..4d381c983 100644 --- a/webpack.test.config.js +++ b/webpack.test.config.js @@ -8,4 +8,6 @@ const options = { mode: 'development' }; -module.exports = require('./.config/webpack/base.js')(options); \ No newline at end of file +let config = require('./.config/webpack/base.js')(options); + +module.exports = config; \ No newline at end of file diff --git a/webpack.test.standalone.config.js b/webpack.test.standalone.config.js new file mode 100644 index 000000000..67f2d692d --- /dev/null +++ b/webpack.test.standalone.config.js @@ -0,0 +1,17 @@ +const options = { + ts: { + transpileOnly: true + }, + preprocessor: { + variables: { + mode: 'eager' + }, + definitions: ['TEST', 'TEST_COPY_PASTE'] + }, + mode: 'development' +}; + +let config = require('./.config/webpack/base.js')(options); +delete config.plugins; + +module.exports = config; \ No newline at end of file