diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml
index 9636917058..d8ab62c542 100644
--- a/.github/workflows/ci_tests.yml
+++ b/.github/workflows/ci_tests.yml
@@ -10,7 +10,7 @@ on:
jobs:
build:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
name: Build, Lint & Jest Test
steps:
- name: Get sources
@@ -47,7 +47,7 @@ jobs:
retention-days: 1
test_cafe:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
needs: build
strategy:
matrix:
@@ -79,7 +79,7 @@ jobs:
run: yarn testcafe:ci:${{ matrix.component }}
site:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
needs: build
name: Site
steps:
diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml
index e515299635..056665a03c 100644
--- a/.github/workflows/lint-pr.yml
+++ b/.github/workflows/lint-pr.yml
@@ -10,7 +10,7 @@ on:
jobs:
main:
name: Validate PR title
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
steps:
- uses: amannn/action-semantic-pull-request@v4
env:
diff --git a/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/custom-easing.jsx b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/custom-easing.jsx
new file mode 100644
index 0000000000..4fd3e04fdf
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/custom-easing.jsx
@@ -0,0 +1,50 @@
+export default () => {
+ const [currentData, setCurrentData] = useState(data[2017]);
+
+ const changeData = useCallback(e => {
+ setCurrentData(data[e.target.value]);
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/simple-animation.jsx b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/simple-animation.jsx
new file mode 100644
index 0000000000..f9af7c2a9b
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/simple-animation.jsx
@@ -0,0 +1,30 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/with-transition.jsx b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/with-transition.jsx
new file mode 100644
index 0000000000..bb7c3082e0
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/animation/$migration/with-transition.jsx
@@ -0,0 +1,67 @@
+const option = [2017, 2018, 2019];
+
+export default () => {
+ const [currentData, setCurrentData] = useState(data[2017]);
+ const id = useRef(undefined);
+ const index = useRef(1);
+ const selectRef = useRef(null);
+
+ useEffect(() => {
+ id.current = setInterval(() => {
+ selectRef.selectedIndex = index.current;
+ setCurrentData(data[option[index.current]]);
+
+ if (index.current === 2) {
+ index.current = 0;
+ } else {
+ index.current += 1;
+ }
+ }, 4000);
+
+ return () => clearTimeout(id.current);
+ }, []);
+
+ const changeData = useCallback(e => {
+ setCurrentData(data[e.target.value]);
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/bar-chart/$migration/rotated-bar.jsx b/packages/dx-react-chart-demos/src/demo-sources/bar-chart/$migration/rotated-bar.jsx
new file mode 100644
index 0000000000..c72599c91d
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/bar-chart/$migration/rotated-bar.jsx
@@ -0,0 +1,17 @@
+export default () => {
+ return (
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/area.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/area.jsx
new file mode 100644
index 0000000000..bb47950a11
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/area.jsx
@@ -0,0 +1,12 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/band-axis.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/band-axis.jsx
new file mode 100644
index 0000000000..d9dd82213b
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/band-axis.jsx
@@ -0,0 +1,12 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar-line.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar-line.jsx
new file mode 100644
index 0000000000..c64a7f2f12
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar-line.jsx
@@ -0,0 +1,51 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar.jsx
new file mode 100644
index 0000000000..bd48ea995e
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/bar.jsx
@@ -0,0 +1,13 @@
+export default () => {
+ return (
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/basic-legend.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/basic-legend.jsx
new file mode 100644
index 0000000000..666649f07f
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/basic-legend.jsx
@@ -0,0 +1,16 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/default-axis.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/default-axis.jsx
new file mode 100644
index 0000000000..4df8082b6c
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/default-axis.jsx
@@ -0,0 +1,11 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/legend-customization.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/legend-customization.jsx
new file mode 100644
index 0000000000..f78d02beda
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/legend-customization.jsx
@@ -0,0 +1,40 @@
+const markerPath = {
+ 'Original Signal': 'M 0 8 C 2 4 7 4 9.5 8 C 11 12 16 12 18 8 L 18 10 C 16 14 11 14 8.5 10 C 7 6 2 6 0 10 Z',
+ 'Noisy Signal': 'M 18 8 L 12 12 L 7 3 L 0 7.4 L 0 10 L 6 6 L 11 15 L 18 10.6 Z',
+ };
+
+ const markerRender = ({ series, marker: { fill } }) => {
+ return (
+
+ );
+ };
+
+ export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/line-spline.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/line-spline.jsx
new file mode 100644
index 0000000000..eb6f3cd10e
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/line-spline.jsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import {
+ Chart,
+ Series,
+ CommonSeriesSettings,
+} from 'devextreme-react/chart';
+
+/* ... */
+
+export default () => {
+ return (
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/logarithm.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/logarithm.jsx
new file mode 100644
index 0000000000..74e4b2179f
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/logarithm.jsx
@@ -0,0 +1,24 @@
+const format = formatPrefix('.1', 1e24);
+
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/pie.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/pie.jsx
new file mode 100644
index 0000000000..d7d39ea8c9
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/pie.jsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import PieChart, {
+ Series,
+ Label,
+ Connector,
+ Size,
+ Export,
+ PieChartTypes,
+} from 'devextreme-react/pie-chart';
+
+export default () => {
+ return (
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/point-customization.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/point-customization.jsx
new file mode 100644
index 0000000000..838dc2fae1
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/point-customization.jsx
@@ -0,0 +1,22 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/scatter.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/scatter.jsx
new file mode 100644
index 0000000000..93df1fcf6c
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/scatter.jsx
@@ -0,0 +1,17 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/theme.jsx b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/theme.jsx
new file mode 100644
index 0000000000..3881b200ff
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/chart-basic/$migration/theme.jsx
@@ -0,0 +1,34 @@
+export const paletteCollection = ['Material', 'Soft Pastel', 'Harmony Light', 'Pastel', 'Bright', 'Soft', 'Ocean', 'Office', 'Vintage', 'Violet', 'Carmine', 'Dark Moon', 'Soft Blue', 'Dark Violet', 'Green Mist'];
+
+export default () => {
+ const [paletteName, setPaletteName] = useState('Material');
+
+ const changeScheme = useCallback(e => {
+ setPaletteName(paletteCollection[e.target.value]);
+ }, []);
+
+ return (
+
+
+
+
+
+ {getPalette(palette).simpleSet.map((color) =>
)}
+
+
+
Scheme
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover-controlled.jsx b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover-controlled.jsx
new file mode 100644
index 0000000000..e5911db2ff
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover-controlled.jsx
@@ -0,0 +1,29 @@
+export default () => {
+ const [hoveredSeries, setHoveredSeries] = useState(undefined);
+ const [hoveredPoint, setHoveredPoint] = useState(undefined);
+
+ const onSeriesHoverChanged = useCallback(({ target: series }) => {
+ setHoveredSeries(series.isHovered() ? series: null);
+ }, []);
+
+ const onPointHoverChanged = useCallback(({ target: point }) => {
+ setHoveredSeries(point.isHovered() ? point: null);
+ }, []);
+
+ return (
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover.jsx b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover.jsx
new file mode 100644
index 0000000000..102cc32a6f
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/hover.jsx
@@ -0,0 +1,14 @@
+export default () => {
+ return (
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/multiple-selection.jsx b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/multiple-selection.jsx
new file mode 100644
index 0000000000..593e75c4b6
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/multiple-selection.jsx
@@ -0,0 +1,37 @@
+export default () => {
+ const [selectedPoints, setSelectedPoints] = useState([]);
+
+ const onPointClick = useCallback(({ target: point }) => {
+ const isPointSelected = point.isSelected();
+
+ if (isPointSelected) {
+ point.clearSelection();
+ setSelectedPoints(points => points.filter(selectedPoint => selectedPoint !== point));
+ }
+ else {
+ point.select();
+ setSelectedPoints(selectedPoints => [...selectedPoints, point]);
+ }
+ }, []);
+
+ return (
+
+
+ Total bars selected:
+ {' '}
+ {selectedPoints.length}
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/selection.jsx b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/selection.jsx
new file mode 100644
index 0000000000..157bd91cb9
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/selection.jsx
@@ -0,0 +1,34 @@
+export default () => {
+ const [selectedPoint, setSelectedPoint] = useState(undefined);
+
+ const onPointClick = useCallback(({ target: point, component }) => {
+ if (point.isSelected()) {
+ component.clearSelection();
+ setSelectedPoint(undefined);
+ }
+ else {
+ point.select();
+ setSelectedPoint(point);
+ }
+ }, []);
+
+ return (
+
+
+ Selected value:
+ {' '}
+ {selectedPoint ? data[selectedPoint].population : undefined}
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/single-multiple-selection.jsx b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/single-multiple-selection.jsx
new file mode 100644
index 0000000000..0a122d12e0
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/interaction/$migration/single-multiple-selection.jsx
@@ -0,0 +1,59 @@
+export default () => {
+ const [selectedPoints, setSelectedPoints] = useState([]);
+
+ const clearSelection = useCallback((component) => {
+ component.clearSelection();
+ setSelectedPoints([]);
+ }, []);
+
+ const selectPoint = useCallback((point) => {
+ point.select();
+ setSelectedPoints(points => [...points, point]);
+ }, []);
+
+ const deselectPoint = useCallback((point) => {
+ point.clearSelection();
+ setSelectedPoints(points => points.filter(selectedPoint => selectedPoint !== point));
+ }, []);
+
+ const onPointClick = useCallback(({ target: point, event, component }) => {
+ const isPointSelected = point.isSelected();
+ const selectedPointsCount = selectedPoints.length;
+
+ if (!event.ctrlKey && !event.metaKey) {
+ clearSelection(component);
+ if (!isPointSelected || selectedPointsCount > 1) {
+ selectPoint(point);
+ }
+ return;
+ }
+
+ if (isPointSelected) {
+ deselectPoint(point)
+ }
+ else {
+ selectPoint(point)
+ }
+ }, [selectedPoints, clearSelection, selectPoint, deselectPoint]);
+
+ return (
+
+
+ Total bars selected:
+ {' '}
+ {selectedPoints.length}
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/legend.jsx b/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/legend.jsx
new file mode 100644
index 0000000000..b4909e4b91
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/legend.jsx
@@ -0,0 +1,35 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/title.jsx b/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/title.jsx
new file mode 100644
index 0000000000..3a99fda3fe
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/layout/$migration/title.jsx
@@ -0,0 +1,31 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/controlled.jsx b/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/controlled.jsx
new file mode 100644
index 0000000000..fd5046b62e
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/controlled.jsx
@@ -0,0 +1,31 @@
+export default () => {
+ const [tooltipTarget, setTooltipTarget] = useState(undefined);
+
+ const onPointHoverChanged = useCallback(({ target: point, component }) => {
+ setTooltipTarget(point);
+
+ if (point) {
+ point.showTooltip();
+ } else {
+ component.hideTooltip();
+ }
+ }, []);
+
+ return (
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/uncontrolled.jsx b/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/uncontrolled.jsx
new file mode 100644
index 0000000000..88d3ab8960
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/tooltip/$migration/uncontrolled.jsx
@@ -0,0 +1,19 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/controlled.jsx b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/controlled.jsx
new file mode 100644
index 0000000000..d08f971f95
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/controlled.jsx
@@ -0,0 +1,44 @@
+export default () => {
+ const [argumentVisualRange, setArgumentVisualRange] = useState([null, null]);
+ const [valueVisualRange, setValueVisualRange] = useState([null, null]);
+
+ const onZoomEnd = useCallback(({ axis, range }) => {
+ if (axis.isArgumentAxis) {
+ setArgumentVisualRange(range);
+ }
+ else {
+ setValueVisualRange(range);
+ }
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/datetime.jsx b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/datetime.jsx
new file mode 100644
index 0000000000..a0fffa87da
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/datetime.jsx
@@ -0,0 +1,47 @@
+export default () => {
+ const [zoomAndPanOptions, setZoomAndPanOptions] = useState({
+ zoomArgument: true,
+ panArgument: true,
+ zoomValue: false,
+ panValue: false,
+ });
+
+ const submit = useCallback(({ target }) => setZoomAndPanOptions(options => ({
+ ...options,
+ [target.id]: target.checked,
+ })), []);
+
+ const renderInput = useCallback((id, label) => {
+ const { [id]: checked } = zoomAndPanOptions;
+ return (
+
+
+
+
+ );
+ }, [zoomAndPanOptions, submit]);
+
+ return (
+
+
+
+
+
+
+ {renderInput('zoomArgument', 'Zoom argument')}
+ {renderInput('panArgument', 'Pan argument')}
+ {renderInput('zoomValue', 'Zoom value')}
+ {renderInput('panValue', 'Pan value')}
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/uncontrolled.jsx b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/uncontrolled.jsx
new file mode 100644
index 0000000000..fea1440439
--- /dev/null
+++ b/packages/dx-react-chart-demos/src/demo-sources/zoom-pan/$migration/uncontrolled.jsx
@@ -0,0 +1,17 @@
+export default () => {
+ return (
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/packages/dx-react-chart-demos/src/index.jsx b/packages/dx-react-chart-demos/src/index.jsx
index 20852d887c..5af2230779 100644
--- a/packages/dx-react-chart-demos/src/index.jsx
+++ b/packages/dx-react-chart-demos/src/index.jsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { initialize } from '@devexpress/dx-demo-shell';
import '@devexpress/dx-demo-shell/dist/index.css';
-import { demos } from './demo-registry.js';
+import { demos, migrationSamples } from './demo-registry.js';
import { themes } from './theme-registry.js';
import { themeComponents } from './theme-components-registry.js';
import { demoData } from './demo-data-registry.js';
@@ -10,6 +10,7 @@ import './index.css';
initialize({
demoSources: demos,
+ migrationSamples,
themeSources: themes,
themeComponents,
demoData,
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/basic.jsx
new file mode 100644
index 0000000000..121f294164
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/basic.jsx
@@ -0,0 +1,41 @@
+import React, { useState } from 'react';
+
+import {
+ DataGrid,
+ Column,
+} from 'devextreme-react/data-grid';
+
+import 'devextreme/dist/css/dx.light.css';
+
+import {
+ generateRows,
+ globalSalesValues,
+} from '../../../demo-data/generator';
+
+export default () => {
+ const [columns] = useState([
+ { name: 'region', title: 'Region' },
+ { name: 'sector', title: 'Sector' },
+ { name: 'customer', title: 'Customer' },
+ { name: 'product', title: 'Product' },
+ { name: 'amount', title: 'Sale Amount' },
+ ]);
+ const [rows] = useState(generateRows({ columnValues: globalSalesValues, length: 8 }));
+
+ return (
+
+
+ {
+ columns.map((column) => (
+
+
+ ))
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/cell-wordwrap.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/cell-wordwrap.jsx
new file mode 100644
index 0000000000..36b3fc0eed
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/cell-wordwrap.jsx
@@ -0,0 +1,29 @@
+// In CSS, add the following style:
+//
+// .word-wrap {
+// white-space: normal;
+// }
+
+export default () => {
+ const [columns] = useState([
+ {
+ dataField: "region",
+ caption: "Region",
+ cssClass: "word-wrap",
+ width: 100,
+ },
+ { dataField: "sector", caption: "Sector" },
+ { dataField: "customer", caption: "Customer" },
+ { dataField: "product", caption: "Product" },
+ { dataField: "amount", caption: "Sale Amount" },
+ ]);
+ const [rows] = useState(
+ generateRows({ columnValues: globalSalesValues, length: 8 })
+ );
+
+ return (
+
+
+
+ );
+ };
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/column-alignment.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/column-alignment.jsx
new file mode 100644
index 0000000000..48cb5b42dc
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/column-alignment.jsx
@@ -0,0 +1,19 @@
+export default () => {
+ const [columns] = useState([
+ { dataField: "region", caption: "Region" },
+ { dataField: "sector", caption: "Sector", alignment: "center" },
+ { dataField: "customer", caption: "Customer", alignment: "center" },
+ { dataField: "product", caption: "Product" },
+ { dataField: "amount", caption: "Sale Amount", alignment: "right" },
+ ]);
+
+ const [rows] = useState(
+ generateRows({ columnValues: globalSalesValues, length: 8 })
+ );
+
+ return (
+
+
+
+ );
+ };
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/static-column-width.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/static-column-width.jsx
new file mode 100644
index 0000000000..3ae83521b7
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/static-column-width.jsx
@@ -0,0 +1,19 @@
+export default () => {
+ const [columns] = useState([
+ { dataField: "region", caption: "Region", width: "20%" },
+ { dataField: "sector", caption: "Sector", width: "15%" },
+ { dataField: "customer", caption: "Customer", width: "auto" },
+ { dataField: "product", caption: "Product", width: "auto" },
+ { dataField: "amount", caption: "Sale Amount", width: 140 },
+ ]);
+
+ const [rows] = useState(
+ generateRows({ columnValues: globalSalesValues, length: 8 })
+ );
+
+ return (
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-cell-template.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-cell-template.jsx
new file mode 100644
index 0000000000..79c5ab6c91
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-cell-template.jsx
@@ -0,0 +1,37 @@
+const HighlightedCell = (cellData) => (
+
+
+ {cellData.value}
+
+
+ );
+
+ export default () => {
+ return (
+
+ {
+ columns.map(column => (
+
+
+ ));
+ }
+
+ );
+ };
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-header-content-template.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-header-content-template.jsx
new file mode 100644
index 0000000000..9eac090ae2
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-header-content-template.jsx
@@ -0,0 +1,46 @@
+import IconButton from "@mui/material/IconButton";
+import VisibilityOff from "@mui/icons-material/VisibilityOff";
+import { styled } from "@mui/material/styles";
+
+const PREFIX = "Demo";
+const classes = {
+ button: `${PREFIX}-button`,
+};
+const StyledIconButton = styled(IconButton)(({ theme }) => ({
+ [`&.${classes.button}`]: {
+ margin: theme.spacing(0, 1),
+ },
+}));
+
+const CustomHeaderCell = ({ column }) => (
+
+ {column.name}
+ alert("Custom action")}
+ size="large"
+ >
+
+
+
+);
+
+export default () => {
+ return (
+
+
+ {columns.map((column) => (
+
+ ))}
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-row-template.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-row-template.jsx
new file mode 100644
index 0000000000..72ce259ebb
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-row-template.jsx
@@ -0,0 +1,58 @@
+const styles = {
+ banking: {
+ backgroundColor: '#f5f5f5',
+ },
+ health: {
+ backgroundColor: '#a2e2a4',
+ },
+ telecom: {
+ backgroundColor: '#b3e5fc',
+ },
+ energy: {
+ backgroundColor: '#ffcdd2',
+ },
+ insurance: {
+ backgroundColor: '#f0f4c3',
+ },
+ };
+
+ const getSectorData = (gridData: DataGridTypes.ColumnCellTemplateData) => gridData.data['sector'];
+
+
+ const TableRow = (rowData: DataGridTypes.RowTemplateData) => (
+ alert(JSON.stringify(rowData.data))}
+ style={{
+ cursor: "pointer",
+ ...styles[getSectorData(rowData)],
+ }}
+ >
+ | {rowData.data.region} |
+ {rowData.data.sector} |
+ {rowData.data.customer} |
+ {rowData.data.product} |
+ {rowData.data.amount} |
+
+ );
+
+ export default () => {
+ return (
+
+ {
+ columns.map(column => (
+
+
+ ));
+ }
+
+ );
+ };
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-template.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-template.jsx
new file mode 100644
index 0000000000..cb7552f6aa
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-basic/$migration/table-template.jsx
@@ -0,0 +1,10 @@
+export default () => {
+ return (
+
+ /* columns */
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/controlled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/controlled.jsx
new file mode 100644
index 0000000000..db0aa906de
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/controlled.jsx
@@ -0,0 +1,43 @@
+export default () => {
+ const [columns] = useState([
+ { name: 'name', title: 'Name' },
+ { name: 'gender', title: 'Gender' },
+ { name: 'city', title: 'City' },
+ { name: 'car', title: 'Car' },
+ ]);
+
+ const [columnVisibility, setColumnVisibility] = useState({
+ '0': true,
+ '1': false,
+ '2': true,
+ '3': false
+ });
+
+ const onVisibleChanged = useCallback((columnIndex) => (visibility) => {
+ setColumnVisibility({
+ ...columnVisibility,
+ [columnIndex]: visibility
+ });
+ }, [columnVisibility]);
+
+ return (
+
+
+ {
+ columns.map((column, idx) => (
+
+
+ ));
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/disable-toggling-column-visibility.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/disable-toggling-column-visibility.jsx
new file mode 100644
index 0000000000..337088bf5d
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/disable-toggling-column-visibility.jsx
@@ -0,0 +1,33 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/uncontrolled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/uncontrolled.jsx
new file mode 100644
index 0000000000..eec17e34ae
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-chooser/$migration/uncontrolled.jsx
@@ -0,0 +1,32 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/controlled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/controlled.jsx
new file mode 100644
index 0000000000..bb40c03344
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/controlled.jsx
@@ -0,0 +1,44 @@
+export default () => {
+ const [columns] = useState([
+ { name: 'name', title: 'Name' },
+ { name: 'gender', title: 'Gender' },
+ { name: 'city', title: 'City' },
+ { name: 'car', title: 'Car' },
+ ]);
+
+ const [visibleIndexes, setVisibleIndexes] = useState({
+ '2': 0,
+ '1': 1,
+ '3': 2,
+ '0': 3,
+ });
+
+ const onVisibleIndexChanged = useCallback((columnIndex) => (columnVisibleIndex) => {
+ setVisibleIndexes({
+ ...visibleIndexes,
+ [columnIndex]: columnVisibleIndex
+ })
+ }, [visibleIndexes]);
+
+ return (
+
+
+ {
+ columns.map((column, idx) => (
+
+
+ ));
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/uncontrolled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/uncontrolled.jsx
new file mode 100644
index 0000000000..6b389a3232
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-reordering/$migration/uncontrolled.jsx
@@ -0,0 +1,28 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/controlled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/controlled.jsx
new file mode 100644
index 0000000000..38b4b7cac1
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/controlled.jsx
@@ -0,0 +1,44 @@
+export default () => {
+ const [columns] = useState([
+ { name: 'name', title: 'Name' },
+ { name: 'gender', title: 'Gender' },
+ { name: 'city', title: 'City' },
+ { name: 'car', title: 'Car' },
+ ]);
+
+ const [columnWidths, setColumnWidths] = useState({
+ '0': 180,
+ '1': 180,
+ '2': 180,
+ '3': 240
+ });
+
+ const onWidthChanged = useCallback((columnIndex) => (width) => {
+ setColumnWidths({
+ ...columnWidths,
+ [columnIndex]: width
+ })
+ }, [columnWidths]);
+
+ return (
+
+
+ {
+ columns.map((column, idx) => (
+
+
+ ));
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/resizing-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/resizing-mode.jsx
new file mode 100644
index 0000000000..23576b59bb
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/resizing-mode.jsx
@@ -0,0 +1,91 @@
+const ModeSelector = (props) => {
+ const { defaultValue, changeMode } = props;
+ return (
+
+ {'Column Resizing Mode:'}
+
+
+
+ );
+ };
+
+ const ResetWidthButton = (props) => {
+ const { resetWidths } = props;
+ return (
+
+ );
+ };
+
+ export default () => {
+ const [defaultColumnWidths] = useState({
+ '0': 180,
+ '1': 180,
+ '2': 180,
+ '3': 240
+ });
+
+ const [columnWidths, setColumnWidths] = useState(defaultColumnWidths);
+ const [resizingMode, setResizingMode] = useState('widget');
+
+ const onWidthChanged = useCallback((columnIndex) => (width) => {
+ setColumnWidths({
+ ...columnWidths,
+ [columnIndex]: width
+ })
+ }, [columnWidths]);
+
+ const resetColumnWidths = useCallback(() => {
+ setColumnWidths(defaultColumnWidths);
+ }, [defaultColumnWidths]);
+
+ return (
+
+
+
+
+ {
+ columns.map((column, idx) => (
+
+
+ ));
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/uncontrolled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/uncontrolled.jsx
new file mode 100644
index 0000000000..e0fc2ae064
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-column-resizing/$migration/uncontrolled.jsx
@@ -0,0 +1,31 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-getters.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-getters.jsx
new file mode 100644
index 0000000000..cf07956498
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-getters.jsx
@@ -0,0 +1,46 @@
+import DataSource from 'devextreme/data/data_source';
+import ArrayStore from 'devextreme/data/array_store';
+
+const dataSource = new DataSource({
+ store: new ArrayStore({
+ data: rows
+ }),
+ map: (dataItem) => ({
+ firstName: dataItem.user?.firstName,
+ lastName: dataItem.user?.lastName,
+ car: dataItem.car?.model,
+ position: dataItem.position,
+ city: dataItem.city,
+ })
+});
+
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-setters.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-setters.jsx
new file mode 100644
index 0000000000..ceb68db70f
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-data-accessors/$migration/value-setters.jsx
@@ -0,0 +1,63 @@
+export default () => {
+ const calculateFirstName = useCallback(row => (row.user ? row.user.firstName : undefined), []);
+ const calculateLastName = useCallback(row => (row.user ? row.user.lastName : undefined), []);
+ const calculateCarModel = useCallback(row => (row.car ? row.car.model : undefined), []);
+
+ const setFirstName = useCallback((newData, value, currentRowData) => {
+ newData.user = {
+ ...currentRowData.user,
+ firstName: value
+ };
+ }, []);
+ const setLastName = useCallback((newData, value, currentRowData) => {
+ newData.user = {
+ ...currentRowData.user,
+ lastName: value
+ };
+ }, []);
+ const setCarModel = useCallback((newData, value, currentRowData) => {
+ newData.car = {
+ model: value
+ };
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/editors.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/editors.jsx
new file mode 100644
index 0000000000..c03ecfe0c2
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/editors.jsx
@@ -0,0 +1,55 @@
+const booleanCellRender = ({ value }) => (
+
+ {value ? 'Yes' : 'No'}
+
+ );
+
+ const booleanEditCellRender = ({ value, setValue }) => (
+
+ );
+
+ export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/formatters.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/formatters.jsx
new file mode 100644
index 0000000000..78d5a6bcc3
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/formatters.jsx
@@ -0,0 +1,38 @@
+const formatCurrency = (value) => value.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
+
+const renderSaleAmount = (data) => (
+
+ {formatCurrency(data.value)}
+
+);
+
+const formatDate = (value) => value.replace(/(\d{4})-(\d{2})-(\d{2})/, '$3.$2.$1');
+
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/tooltip.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/tooltip.jsx
new file mode 100644
index 0000000000..90960d60af
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-data-types/$migration/tooltip.jsx
@@ -0,0 +1,55 @@
+const tooltipCellRender = ({
+ row: { data: { phone, birthDate } },
+ value,
+ columnIndex,
+ rowIndex
+ }) => {
+ return (
+
+
+ {value}
+
+
+ {`phone: ${phone}`}
+
+ {`birth date: ${birthDate}`}
+
+
+ );
+ };
+
+ export default () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-detail-row/$migration/simple-detail-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-detail-row/$migration/simple-detail-row.jsx
new file mode 100644
index 0000000000..e2d31e238f
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-detail-row/$migration/simple-detail-row.jsx
@@ -0,0 +1,52 @@
+const RowDetail = ({ data }) => (
+
+ Details for
+ {' '}
+ {data.name}
+ {' '}
+ from
+ {' '}
+ {data.city}
+
+ );
+
+ export default () => {
+ const [defaultExpandedRows, setDefaultExpandedRows] = useState([2, 5]);
+
+ const onContentReady = useCallback(e => {
+ if (defaultExpandedRows.length) {
+ defaultExpandedRows.forEach(key => e.component.expandRow(key));
+ setDefaultExpandedRows([]);
+ }
+ }, [defaultExpandedRows]);
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/disable-column-editing.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/disable-column-editing.jsx
new file mode 100644
index 0000000000..832d18e044
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/disable-column-editing.jsx
@@ -0,0 +1,34 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row-controlled.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row-controlled.jsx
new file mode 100644
index 0000000000..0c34dbd14e
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row-controlled.jsx
@@ -0,0 +1,39 @@
+export default () => {
+ const [editRowKey, setEditRowKey] = useState(null);
+ const [editChanges, setEditChanges] = useState([]);
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row.jsx
new file mode 100644
index 0000000000..68b45402b9
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/edit-row.jsx
@@ -0,0 +1,32 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/inline-cell-editing.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/inline-cell-editing.jsx
new file mode 100644
index 0000000000..530d072b1a
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/inline-cell-editing.jsx
@@ -0,0 +1,86 @@
+const StartEditActionSelector = (props) => {
+ const { defaultAction, changeAction } = props;
+ return (
+
+ {'Start Edit Action:'}
+
+
+
+ );
+ };
+
+ const SelectTextChecker = (props) => {
+ const { isSelectText, changeSelectText } = props;
+ return (
+
+
+
+ );
+ };
+
+ export default () => {
+ const [selectTextOnEditStart, setSelectTextOnEditStart] = useState(true);
+ const [startEditAction, setStartEditAction] = useState('click');
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/popup-editing.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/popup-editing.jsx
new file mode 100644
index 0000000000..0b91b31106
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/popup-editing.jsx
@@ -0,0 +1,56 @@
+export default () => {
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/validation-on-typing.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/validation-on-typing.jsx
new file mode 100644
index 0000000000..506bcf67c4
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-editing/$migration/validation-on-typing.jsx
@@ -0,0 +1,36 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/advanced-customization.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/advanced-customization.jsx
new file mode 100644
index 0000000000..002311354e
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/advanced-customization.jsx
@@ -0,0 +1,122 @@
+/* usual imports */
+import { Workbook } from 'exceljs';
+import { saveAs } from 'file-saver-es';
+import { exportDataGrid } from 'devextreme/excel_exporter';
+
+export default () => {
+ const onExporting = useCallback(e => {
+ const workbook = new Workbook();
+ const worksheet = workbook.addWorksheet('Main sheet');
+
+ exportDataGrid({
+ component: e.component,
+ worksheet,
+ autoFilterEnabled: true,
+ customizeCell: ({ gridCell, excelCell }) => {
+ if (gridCell.data.OrderDate < new Date(2014, 2, 3)) {
+ excelCell.font = { color: { argb: 'AAAAAA' } };
+ }
+ if (gridCell.data.SaleAmount > 15000) {
+ if (gridCell.column.name === 'SaleAmount') {
+ excelCell.font = { color: { argb: '000000' } };
+ excelCell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFBB00' } };
+ }
+ }
+ if (gridCell.column.name === 'SaleAmount') {
+ excelCell.numFmt = '$0';
+ }
+ if (!!gridCell.totalSummaryItemName) {
+ excelCell.font = { italic: true };
+ }
+ }
+ }).then(() => {
+ /* Customize the Header */
+ const generalStyles = {
+ font: { bold: true },
+ fill: {
+ type: 'pattern', pattern: 'solid', fgColor: { argb: 'D3D3D3' }, bgColor: { argb: 'D3D3D3' },
+ },
+ alignment: { horizontal: 'left' },
+ };
+ for (let rowIndex = 1; rowIndex < 6; rowIndex += 1) {
+ worksheet.mergeCells(rowIndex, 1, rowIndex, 3);
+ worksheet.mergeCells(rowIndex, 4, rowIndex, 6);
+ Object.assign(worksheet.getRow(rowIndex).getCell(1), generalStyles);
+ Object.assign(worksheet.getRow(rowIndex).getCell(3), generalStyles);
+ }
+ worksheet.getRow(1).height = 20;
+ worksheet.getRow(1).getCell(1).font = { bold: true, size: 16 };
+ worksheet.getRow(1).getCell(4).numFmt = 'd mmmm yyyy';
+ worksheet.getRow(1).getCell(4).font = { bold: true, size: 16 };
+ worksheet.getColumn(1).values = ['Sale Amounts:', 'Company Name:', 'Address:', 'Phone:', 'Website:'];
+ worksheet.getColumn(4).values = [new Date(), 'K&S Music', '1000 Nicllet Mall Minneapolis Minnesota', '(612) 304-6073', 'www.nowebsitemusic.com'];
+ worksheet.addRow({});
+
+ /* Customize the Footer */
+
+ const { lastRow } = worksheet;
+ let currentRowIndex = lastRow.number + 2;
+ for (let rowIndex = 0; rowIndex < 3; rowIndex += 1) {
+ worksheet.mergeCells(currentRowIndex + rowIndex, 1, currentRowIndex + rowIndex, 6);
+ Object.assign(worksheet.getRow(currentRowIndex + rowIndex).getCell(1), { font: { bold: true }, alignment: { horizontal: 'right' } });
+ }
+ worksheet.getRow(currentRowIndex).getCell(1).value = 'If you have any questions, please contact John Smith.';
+ currentRowIndex += 1;
+ worksheet.getRow(currentRowIndex).getCell(1).value = 'Phone: +111-111';
+ currentRowIndex += 1;
+ worksheet.getRow(currentRowIndex).getCell(1).value = 'For demonstration purposes only';
+ worksheet.getRow(currentRowIndex).getCell(1).font = { italic: true };
+
+ workbook.xlsx.writeBuffer().then((buffer) => {
+ saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx');
+ });
+ });
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/basic.jsx
new file mode 100644
index 0000000000..d60e9d4262
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/basic.jsx
@@ -0,0 +1,48 @@
+/* usual imports */
+import { Workbook } from 'exceljs';
+import { saveAs } from 'file-saver-es';
+import { exportDataGrid } from 'devextreme/excel_exporter';
+
+
+const onExporting = e => {
+ const workbook = new Workbook();
+ const worksheet = workbook.addWorksheet('Main sheet');
+
+ exportDataGrid({
+ component: e.component,
+ worksheet,
+ autoFilterEnabled: true,
+ }).then(() => {
+ workbook.xlsx.writeBuffer().then((buffer) => {
+ saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx');
+ });
+ });
+};
+
+export default () => (
+
+
+
+
+
+
+
+);
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/supported-grid-features.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/supported-grid-features.jsx
new file mode 100644
index 0000000000..40b82ddcef
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-export/$migration/supported-grid-features.jsx
@@ -0,0 +1,100 @@
+/* usual imports */
+import { Workbook } from 'exceljs';
+import { saveAs } from 'file-saver-es';
+import { exportDataGrid } from 'devextreme/excel_exporter';
+
+export default () => {
+ const onExporting = useCallback(e => {
+ const workbook = new Workbook();
+ const worksheet = workbook.addWorksheet('Main sheet');
+
+ exportDataGrid({
+ component: e.component,
+ worksheet,
+ autoFilterEnabled: true,
+ }).then(() => {
+ workbook.xlsx.writeBuffer().then((buffer) => {
+ saveAs(new Blob([buffer], { type: 'application/octet-stream' }), 'DataGrid.xlsx');
+ });
+ });
+ }, []);
+
+ const [defaultGroupsExpanded, setDefaultGroupsExpanded] = useState(false);
+ const [defaultSelection] = useState([14, 30, 38]);
+
+ const onContentReady = useCallback(e => {
+ if(!defaultGroupsExpanded) {
+ e.component.expandRow(['Todd Hoffman'])
+ .then(() => e.component.expandRow(['Todd Hoffman', 'Denver']))
+ .then(() => e.component.expandRow(['Todd Hoffman', 'Casper']));
+ setDefaultGroupsExpanded(true);
+ }
+ }), [defaultGroupsExpanded]);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/advanced-filter-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/advanced-filter-row.jsx
new file mode 100644
index 0000000000..ccaa98e456
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/advanced-filter-row.jsx
@@ -0,0 +1,69 @@
+const CurrencyEditor = ({ data: { value, setValue } } ) => {
+ const handleChange = (event) => {
+ const { value: targetValue } = event.target;
+ if (targetValue.trim() === '') {
+ setValue();
+ return;
+ }
+ setValue(parseInt(targetValue, 10));
+ };
+ return (
+
+ );
+ };
+
+ export default () => {
+ const calculateFilterExpression = useCallback((filterValue, selectedFilterOperation) => {
+ if (!!filterValue && selectedFilterOperation === 'month') {
+ const selector = (data) => {
+ return parseInt(data.saleDate.split('-')[1], 10);
+ };
+
+ return [selector, "=", parseInt(filterValue, 10)];
+ }
+
+ if(!this.defaultCalculateFilterExpression)
+ return [this.dataField, 'contains', filterValue];
+
+ return this.defaultCalculateFilterExpression.apply(this, arguments);
+ }, []);
+
+ return (
+
+
+
+
+
+
+ ', '>', '>=', '<', '<=']}
+ editCellComponent={CurrencyEditor}
+ />
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/controlled-mode.jsx
new file mode 100644
index 0000000000..cdd5027d3c
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/controlled-mode.jsx
@@ -0,0 +1,30 @@
+export default () => {
+ const [filterValue, setFilterValue] = useState({
+ ['car', '=', 'cruze']
+ });
+
+ return (
+
+
+
+ {
+ columns.map((column, idx) => (
+
+
+ ));
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/custom-filtering-algorithm.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/custom-filtering-algorithm.jsx
new file mode 100644
index 0000000000..affe08f86e
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/custom-filtering-algorithm.jsx
@@ -0,0 +1,42 @@
+const toLowerCase = value => String(value).toLowerCase();
+
+export default () => {
+ const calculateFilterExpression = useCallback((filterValue) => {
+ const selector = (data) => {
+ return toLowerCase(data.city);
+ };
+
+ return [selector, "startswith", toLowerCase(filterValue)];
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/disable-column-filtering.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/disable-column-filtering.jsx
new file mode 100644
index 0000000000..602b05e9ea
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/disable-column-filtering.jsx
@@ -0,0 +1,33 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/filter-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/filter-row.jsx
new file mode 100644
index 0000000000..ee73af2530
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/filter-row.jsx
@@ -0,0 +1,30 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/remote-filtering.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/remote-filtering.jsx
new file mode 100644
index 0000000000..142ec80857
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-filtering/$migration/remote-filtering.jsx
@@ -0,0 +1,73 @@
+function isNotEmpty(value: string | undefined | null) {
+ return value !== undefined && value !== null && value !== '';
+ }
+
+ const store = new CustomStore({
+ key: 'OrderNumber',
+ async load(loadOptions) {
+ const paramNames = [
+ 'skip', 'take', 'requireTotalCount', 'requireGroupCount',
+ 'sort', 'filter', 'totalSummary', 'group', 'groupSummary',
+ ];
+
+ const queryString = paramNames
+ .filter((paramName) => isNotEmpty(loadOptions[paramName]))
+ .map((paramName) => `${paramName}=${JSON.stringify(loadOptions[paramName])}`)
+ .join('&');
+
+ try {
+ const response = await fetch(`https://js.devexpress.com/Demos/WidgetsGalleryDataService/api/orders?${queryString}`);
+
+ const result = await response.json();
+
+ return {
+ data: result.data,
+ totalCount: result.totalCount,
+ summary: result.summary,
+ groupCount: result.groupCount,
+ };
+ } catch (err) {
+ throw new Error('Data Loading Error');
+ }
+ },
+ });
+
+ const remoteOperations = { filtering: true }
+
+ const App = () => (
+
+
+
+
+
+
+
+
+
+
+);
+
+export default App;
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-fixed-columns/$migration/basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-fixed-columns/$migration/basic.jsx
new file mode 100644
index 0000000000..33c3f54eae
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-fixed-columns/$migration/basic.jsx
@@ -0,0 +1,55 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/controlled-mode.jsx
new file mode 100644
index 0000000000..16c3d3a7d0
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/controlled-mode.jsx
@@ -0,0 +1,35 @@
+export default () => {
+ const [groupIndexes, setGroupIndexes] = useState({
+ '2': 0
+ });
+
+ const onGroupIndexChanged = useCallback((columnIndex) => (groupIndex) => {
+ setGroupIndexes({
+ ...groupIndexes,
+ [columnIndex]: groupIndex,
+ });
+ }, [groupIndexes]);
+
+ return (
+
+
+
+
+ {
+ columns.map((column, idx) => (
+
+
+ ));
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-advanced.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-advanced.jsx
new file mode 100644
index 0000000000..538815ff4d
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-advanced.jsx
@@ -0,0 +1,55 @@
+const groupCellRender = ({ value }) => (
+
+ from
+ {' '}
+ {value.from}
+ {' '}
+ to
+ {' '}
+ {value.to}
+
+ );
+
+ const nameGroupCriteria = rowData => {
+ const firstLetter = String(rowData.name).substr(0, 1).toLowerCase();
+ const groupValue = firstLetter < 'n'
+ ? { from: 'A', to: 'M' }
+ : { from: 'N', to: 'Z' };
+ return {
+ value: groupValue,
+ key: `${groupValue.from}-${groupValue.to}`,
+ };
+ };
+
+ export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-grouping-static.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-grouping-static.jsx
new file mode 100644
index 0000000000..82ee06404b
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom-grouping-static.jsx
@@ -0,0 +1,51 @@
+import DataSource from 'devextreme/data/data_source';
+import ArrayStore from 'devextreme/data/array_store';
+
+const dataSource = new DataSource({
+ store: new ArrayStore({
+ data
+ }),
+ postProcess: (hierarchicalData) => {
+ const flatData = hierarchicalData.reduce((acc, value) => {
+ const items = value.items.map((item) => ({
+ ...item,
+ 'gender': value.key,
+ }));
+
+ return [
+ ...acc,
+ ...items,
+ ];
+ }, []);
+
+ return flatData;
+ }
+});
+
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom.jsx
new file mode 100644
index 0000000000..acbbd0d1a9
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/custom.jsx
@@ -0,0 +1,50 @@
+const groupCellRender = ({ column, value }) => (
+
+ Group
+ {' '}
+
+ {column.caption}
+
+ {' '}
+ by first letter:
+ {' '}
+
+ {value}
+
+
+ );
+
+ const cityGroupCriteria = rowData => rowData.city.substr(0, 1);
+
+ export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/disable-column-grouping.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/disable-column-grouping.jsx
new file mode 100644
index 0000000000..9d6e481640
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/disable-column-grouping.jsx
@@ -0,0 +1,31 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/grouping-with-ui.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/grouping-with-ui.jsx
new file mode 100644
index 0000000000..327713c69f
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/grouping-with-ui.jsx
@@ -0,0 +1,29 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/remote-grouping-with-local-expanding.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/remote-grouping-with-local-expanding.jsx
new file mode 100644
index 0000000000..3f815e2ee2
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/remote-grouping-with-local-expanding.jsx
@@ -0,0 +1,74 @@
+function isNotEmpty(value: string | undefined | null) {
+ return value !== undefined && value !== null && value !== '';
+ }
+
+ const store = new CustomStore({
+ key: 'OrderNumber',
+ async load(loadOptions) {
+ const paramNames = [
+ 'skip', 'take', 'requireTotalCount', 'requireGroupCount',
+ 'sort', 'filter', 'totalSummary', 'group', 'groupSummary',
+ ];
+
+ const queryString = paramNames
+ .filter((paramName) => isNotEmpty(loadOptions[paramName]))
+ .map((paramName) => `${paramName}=${JSON.stringify(loadOptions[paramName])}`)
+ .join('&');
+
+ try {
+ const response = await fetch(`https://js.devexpress.com/Demos/WidgetsGalleryDataService/api/orders?${queryString}`);
+
+ const result = await response.json();
+
+ return {
+ data: result.data,
+ totalCount: result.totalCount,
+ summary: result.summary,
+ groupCount: result.groupCount,
+ };
+ } catch (err) {
+ throw new Error('Data Loading Error');
+ }
+ },
+ });
+
+ const remoteOperations = { grouping: true }
+
+
+ const App = () => (
+
+
+
+
+
+
+
+
+
+);
+
+export default App;
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/static.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/static.jsx
new file mode 100644
index 0000000000..50ebb9b695
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-grouping/$migration/static.jsx
@@ -0,0 +1,27 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/controlled-mode.jsx
new file mode 100644
index 0000000000..1cc9a9eb1b
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/controlled-mode.jsx
@@ -0,0 +1,33 @@
+export default () => {
+ const [focusedRowIndex, setFocusedRowIndex] = useState(-1);
+ const [focusedColumnIndex, setFocusedColumnIndex] = useState(-1);
+
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/focus-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/focus-row.jsx
new file mode 100644
index 0000000000..df878cbeeb
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/focus-row.jsx
@@ -0,0 +1,27 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/uncontrolled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/uncontrolled-mode.jsx
new file mode 100644
index 0000000000..373e917428
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-keyboard-navigation/$migration/uncontrolled-mode.jsx
@@ -0,0 +1,59 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/infinite-scrolling.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/infinite-scrolling.jsx
new file mode 100644
index 0000000000..6cb7bb7a31
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/infinite-scrolling.jsx
@@ -0,0 +1,27 @@
+const VIRTUAL_PAGE_SIZE = 50;
+
+export default () => {
+ const [columns] = useState([
+ { dataField: 'Id', caption: 'ID', width: 80 },
+ { dataField: 'ProductCategoryName', caption: 'Category', width: 220 },
+ { dataField: 'StoreName', caption: 'Store', width: 220 },
+ { dataField: 'ProductName', caption: 'Product' },
+ { dataField: 'SalesAmount', caption: 'Amount', width: 120 }
+ ]);
+
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/remote-data-basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/remote-data-basic.jsx
new file mode 100644
index 0000000000..910792ce9a
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-lazy-loading/$migration/remote-data-basic.jsx
@@ -0,0 +1,27 @@
+const VIRTUAL_PAGE_SIZE = 100;
+
+export default () => {
+ const [columns] = useState([
+ { dataField: 'Id', caption: 'ID', width: 80 },
+ { dataField: 'ProductCategoryName', caption: 'Category', width: 220 },
+ { dataField: 'StoreName', caption: 'Store', width: 220 },
+ { dataField: 'ProductName', caption: 'Product' },
+ { dataField: 'SalesAmount', caption: 'Amount', width: 120 }
+ ]);
+
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-localization/$migration/basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-localization/$migration/basic.jsx
new file mode 100644
index 0000000000..a723b5413a
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-localization/$migration/basic.jsx
@@ -0,0 +1,13 @@
+import deMessages from "devextreme/localization/messages/de.json";
+import { locale, loadMessages } from "devextreme/localization";
+
+loadMessages(deMessages);
+locale(navigator.language);
+
+export default () => (
+
+ {/* ... */}
+
+);
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/controlled-mode.jsx
new file mode 100644
index 0000000000..d941c12d8d
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/controlled-mode.jsx
@@ -0,0 +1,40 @@
+export default () => {
+ const [pageSizes] = useState([5, 10, 15]);
+ const [pageIndex, setPageIndex] = useState(0);
+ const [pageSize, setPageSize] = useState(5);
+
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/page-size-selector.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/page-size-selector.jsx
new file mode 100644
index 0000000000..b247a3d9f7
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/page-size-selector.jsx
@@ -0,0 +1,36 @@
+export default () => {
+ const [pageSizes] = useState([5, 10, 15, 'all']);
+
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/remote-paging.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/remote-paging.jsx
new file mode 100644
index 0000000000..f17c88549f
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/remote-paging.jsx
@@ -0,0 +1,78 @@
+function isNotEmpty(value: string | undefined | null) {
+ return value !== undefined && value !== null && value !== '';
+ }
+
+ const store = new CustomStore({
+ key: 'OrderNumber',
+ async load(loadOptions) {
+ const paramNames = [
+ 'skip', 'take', 'requireTotalCount', 'requireGroupCount',
+ 'sort', 'filter', 'totalSummary', 'group', 'groupSummary',
+ ];
+
+ const queryString = paramNames
+ .filter((paramName) => isNotEmpty(loadOptions[paramName]))
+ .map((paramName) => `${paramName}=${JSON.stringify(loadOptions[paramName])}`)
+ .join('&');
+
+ try {
+ const response = await fetch(`https://js.devexpress.com/Demos/WidgetsGalleryDataService/api/orders?${queryString}`);
+
+ const result = await response.json();
+
+ return {
+ data: result.data,
+ totalCount: result.totalCount,
+ summary: result.summary,
+ groupCount: result.groupCount,
+ };
+ } catch (err) {
+ throw new Error('Data Loading Error');
+ }
+ },
+ });
+
+ const remoteOperations = { paging: true }
+ const allowedPageSizes = [8, 12, 20];
+
+ const App = () => (
+
+
+
+
+
+
+
+
+
+
+);
+
+export default App;
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/uncontrolled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/uncontrolled-mode.jsx
new file mode 100644
index 0000000000..91746839cb
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-paging/$migration/uncontrolled-mode.jsx
@@ -0,0 +1,31 @@
+export default () => {
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/controlled-mode.jsx
new file mode 100644
index 0000000000..8cd938df80
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/controlled-mode.jsx
@@ -0,0 +1,33 @@
+export default () => {
+ const [searchPanelText, setSearchPanelText] = useState('Female');
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/remote-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/remote-mode.jsx
new file mode 100644
index 0000000000..e976b09abd
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/remote-mode.jsx
@@ -0,0 +1,72 @@
+function isNotEmpty(value: string | undefined | null) {
+ return value !== undefined && value !== null && value !== '';
+ }
+
+ const store = new CustomStore({
+ key: 'OrderNumber',
+ async load(loadOptions) {
+ const paramNames = [
+ 'skip', 'take', 'requireTotalCount', 'requireGroupCount',
+ 'sort', 'filter', 'totalSummary', 'group', 'groupSummary',
+ ];
+
+ const queryString = paramNames
+ .filter((paramName) => isNotEmpty(loadOptions[paramName]))
+ .map((paramName) => `${paramName}=${JSON.stringify(loadOptions[paramName])}`)
+ .join('&');
+
+ try {
+ const response = await fetch(`https://js.devexpress.com/Demos/WidgetsGalleryDataService/api/orders?${queryString}`);
+
+ const result = await response.json();
+
+ return {
+ data: result.data,
+ totalCount: result.totalCount,
+ summary: result.summary,
+ groupCount: result.groupCount,
+ };
+ } catch (err) {
+ throw new Error('Data Loading Error');
+ }
+ },
+ });
+
+ const remoteOperations = { filtering: true }
+
+ const App = () => (
+
+
+
+
+
+
+
+
+
+);
+
+export default App;
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/uncontrolled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/uncontrolled-mode.jsx
new file mode 100644
index 0000000000..fd9f86eb88
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/uncontrolled-mode.jsx
@@ -0,0 +1,30 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/visible-columns-searching.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/visible-columns-searching.jsx
new file mode 100644
index 0000000000..66a837b1fd
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-searching/$migration/visible-columns-searching.jsx
@@ -0,0 +1,31 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/basic.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/basic.jsx
new file mode 100644
index 0000000000..4cf89761a7
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/basic.jsx
@@ -0,0 +1,37 @@
+export default () => {
+ const [selectedRows, setSelectedRows] = useState([1]);
+ const onSelectionChanged = useCallback((e) => {
+ setSelectedRows(e.selectedRowKeys);
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/hidden-checkboxes.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/hidden-checkboxes.jsx
new file mode 100644
index 0000000000..7e6bb04abb
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/hidden-checkboxes.jsx
@@ -0,0 +1,38 @@
+export default () => {
+ const [selectedRows, setSelectedRows] = useState([1]);
+ const onSelectionChanged = useCallback((e) => {
+ setSelectedRows(e.selectedRowKeys);
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-all-pages.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-all-pages.jsx
new file mode 100644
index 0000000000..9a44f14b44
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-all-pages.jsx
@@ -0,0 +1,47 @@
+export default () => {
+ const [selectedRows, setSelectedRows] = useState([1]);
+ const onSelectionChanged = useCallback((e) => {
+ setSelectedRows(e.selectedRowKeys);
+ }, []);
+
+ return (
+
+
+ Total rows selected:
+ {' '}
+ {selectedRows.length}
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-page.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-page.jsx
new file mode 100644
index 0000000000..1eb8eeb5e3
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-by-page.jsx
@@ -0,0 +1,47 @@
+export default () => {
+ const [selectedRows, setSelectedRows] = useState([1]);
+ const onSelectionChanged = useCallback((e) => {
+ setSelectedRows(e.selectedRowKeys);
+ }, []);
+
+ return (
+
+
+ Total rows selected:
+ {' '}
+ {selectedRows.length}
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-virtual.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-virtual.jsx
new file mode 100644
index 0000000000..487e094618
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-all-virtual.jsx
@@ -0,0 +1,40 @@
+export default () => {
+ const [selectedRows, setSelectedRows] = useState([1]);
+ const onSelectionChanged = useCallback((e) => {
+ setSelectedRows(e.selectedRowKeys);
+ }, []);
+
+ return (
+
+
+ Total rows selected:
+ {' '}
+ {selectedRows.length}
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-by-row-click.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-by-row-click.jsx
new file mode 100644
index 0000000000..de8cbae074
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-selection/$migration/select-by-row-click.jsx
@@ -0,0 +1,38 @@
+export default () => {
+ const [selectedRows, setSelectedRows] = useState([1]);
+ const onSelectionChanged = useCallback((e) => {
+ setSelectedRows(e.selectedRowKeys);
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/controlled-mode.jsx
new file mode 100644
index 0000000000..2cfa033284
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/controlled-mode.jsx
@@ -0,0 +1,32 @@
+export default () => {
+ const [sorting, setSorting] = useState({
+ '2': 'asc'
+ });
+
+ const onSortOrderChanged = useCallback((columnIndex) => (columnSorting) => {
+ setSorting({
+ ...sorting,
+ [columnIndex]: columnSorting,
+ })
+ }, [sorting]);
+
+ return (
+
+ {
+ columns.map((column, idx) => (
+
+
+ ));
+ }
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sort-label.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sort-label.jsx
new file mode 100644
index 0000000000..7b40740eb2
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sort-label.jsx
@@ -0,0 +1,65 @@
+const SortingIcon = ({ sortOrder }) => (
+
+ );
+
+ const SortLabel = ({ toggleSort, text, sortOrder }) => (
+
+ );
+
+ export default () => {
+ const renderHeaderCell = useCallback(({ column, columnIndex, component }) => {
+ const sortOrder = component.columnOption(column.name, "sortOrder");
+
+ const toggleSort = useCallback(() => {
+ component.columnOption(column.name, "sortOrder", sortOrder === 'asc' ? 'desc' : 'asc');
+ }, [sortOrder, component, column]);
+
+ return (
+ ;
+ ), [])
+ };
+
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sorting.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sorting.jsx
new file mode 100644
index 0000000000..336d09856e
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/custom-sorting.jsx
@@ -0,0 +1,43 @@
+export default () => {
+ const priorityWeights = useMemo(() => ({
+ Low: 0,
+ Normal: 1,
+ High: 2,
+ }), []);
+
+ const comparePriority = useCallback((a, b) => {
+ const priorityA = priorityWeights[a];
+ const priorityB = priorityWeights[b];
+ if (priorityA === priorityB) {
+ return 0;
+ }
+ return (priorityA < priorityB) ? -1 : 1;
+ }, [priorityWeights]);
+
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/disable-column-sorting.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/disable-column-sorting.jsx
new file mode 100644
index 0000000000..a8ed373cb9
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/disable-column-sorting.jsx
@@ -0,0 +1,28 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/group-sorting.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/group-sorting.jsx
new file mode 100644
index 0000000000..ad1b596632
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/group-sorting.jsx
@@ -0,0 +1,31 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/header-sorting.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/header-sorting.jsx
new file mode 100644
index 0000000000..67c1756881
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/header-sorting.jsx
@@ -0,0 +1,21 @@
+export default () => {
+ return (
+
+ {
+ columns.map(column => (
+
+
+ ));
+ }
+
+ );
+};
+
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/remote-sorting.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/remote-sorting.jsx
new file mode 100644
index 0000000000..3f5a7516b4
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-sorting/$migration/remote-sorting.jsx
@@ -0,0 +1,78 @@
+function isNotEmpty(value: string | undefined | null) {
+ return value !== undefined && value !== null && value !== '';
+ }
+
+ const store = new CustomStore({
+ key: 'OrderNumber',
+ async load(loadOptions) {
+ const paramNames = [
+ 'skip', 'take', 'requireTotalCount', 'requireGroupCount',
+ 'sort', 'filter', 'totalSummary', 'group', 'groupSummary',
+ ];
+
+ const queryString = paramNames
+ .filter((paramName) => isNotEmpty(loadOptions[paramName]))
+ .map((paramName) => `${paramName}=${JSON.stringify(loadOptions[paramName])}`)
+ .join('&');
+
+ try {
+ const response = await fetch(`https://js.devexpress.com/Demos/WidgetsGalleryDataService/api/orders?${queryString}`);
+
+ const result = await response.json();
+
+ return {
+ data: result.data,
+ totalCount: result.totalCount,
+ summary: result.summary,
+ groupCount: result.groupCount,
+ };
+ } catch (err) {
+ throw new Error('Data Loading Error');
+ }
+ },
+ });
+
+ const remoteOperations = { sorting: true }
+
+ const App = () => (
+
+
+
+
+
+
+
+
+
+
+);
+
+export default App;
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-algorithm.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-algorithm.jsx
new file mode 100644
index 0000000000..df9423cbf6
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-algorithm.jsx
@@ -0,0 +1,70 @@
+export default () => {
+ const calculateCustomSummary = useCallback(options => {
+ if(options.name == 'SalesMedianSummary') {
+ switch(options.summaryProcess) {
+ case 'start':
+ options.totalValue = [];
+ break;
+ case 'calculate':
+ options.totalValue.push(options.value);
+ break;
+ case 'finalize':
+ if (!options.totalValue.length) {
+ options.totalValue = 0;
+ break;
+ }
+ const sortedValues = options.totalValue.sort((a, b) => a - b);
+ if (options.totalValue.length % 2 === 1) {
+ options.totalValue = sortedValues[(sortedValues.length + 1) / 2];
+ break;
+ }
+ const halfIndex = sortedValues.length / 2;
+ options.totalValue = (sortedValues[halfIndex] + sortedValues[halfIndex + 1]) / 2;
+ }
+ }
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-summary.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-summary.jsx
new file mode 100644
index 0000000000..f9b81e9bbf
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/custom-summary.jsx
@@ -0,0 +1,76 @@
+export default () => {
+ const onSelectionChanged = useCallback(e => e.component.refresh(true), []);
+
+ const calculateCustomSummary = useCallback(options => {
+ if (options.summaryProcess === 'start') {
+ options.totalValue = 0;
+ return;
+ }
+
+ const isRowSelected = options.component.isRowSelected(options.value?.ID);
+
+ if (options.summaryProcess !== 'calculate' || !isRowSelected) {
+ return;
+ }
+
+ switch(options.name) {
+ case 'SalesSumSummary':
+ options.totalValue += options.value.SaleAmount;
+ break;
+ case 'SalesMaxSummary':
+ options.totalValue = Math.max(options.totalValue, options.value.SaleAmount)
+ break;
+ case 'RegionCountSummary':
+ options.totalValue++;
+ }
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/formatless-custom-algorithm.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/formatless-custom-algorithm.jsx
new file mode 100644
index 0000000000..5ba8fa2940
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/formatless-custom-algorithm.jsx
@@ -0,0 +1,54 @@
+export default () => {
+ const calculateCustomSummary = useCallback(options => {
+ if(options.name == 'OverpricedCountSummary') {
+ switch(options.summaryProcess) {
+ case 'start':
+ options.totalValue = 0;
+ break;
+ case 'calculate':
+ options.totalValue += options.value > 6000 ? 1 : 0;
+ }
+ }
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/group-summary.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/group-summary.jsx
new file mode 100644
index 0000000000..c8df6e99fc
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/group-summary.jsx
@@ -0,0 +1,62 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/total-summary.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/total-summary.jsx
new file mode 100644
index 0000000000..ab48d5712f
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-summary/$migration/total-summary.jsx
@@ -0,0 +1,48 @@
+export default () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/controlled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/controlled-mode.jsx
new file mode 100644
index 0000000000..9b63eb31ee
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/controlled-mode.jsx
@@ -0,0 +1,35 @@
+export default () => {
+ const [expandedRowKeys, setExpandedRowKeys] = useState([0, 1]);
+
+ return (
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/hierarchical-tree.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/hierarchical-tree.jsx
new file mode 100644
index 0000000000..c6da68e79b
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/hierarchical-tree.jsx
@@ -0,0 +1,30 @@
+export default () => {
+ return (
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/plain-tree.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/plain-tree.jsx
new file mode 100644
index 0000000000..e2ea4b3142
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/plain-tree.jsx
@@ -0,0 +1,31 @@
+export default () => {
+ return (
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/remote.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/remote.jsx
new file mode 100644
index 0000000000..daabef13a6
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/remote.jsx
@@ -0,0 +1,46 @@
+const dataSource = {
+ async load(loadOptions) {
+ const parentIdsParam = loadOptions.parentIds;
+ const url = new URL('https://js.devexpress.com/Demos/Mvc/api/treeListData');
+ if (parentIdsParam) {
+ parentIdsParam.forEach((id: string) => {
+ url.searchParams.append('parentIds', id);
+ });
+ }
+
+ const result = await fetch(url.toString());
+
+ if (result.status === 200) {
+ return result.json();
+ }
+
+ throw new Error('Data Loading Error');
+ },
+ };
+
+ const customizeText = (e) => {
+ if (e.value !== null) {
+ return `${Math.ceil(e.value / 1024)} KB`;
+ }
+ return null;
+ };
+
+ export default () => {
+ return (
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/select-all.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/select-all.jsx
new file mode 100644
index 0000000000..fee8c5476e
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/select-all.jsx
@@ -0,0 +1,38 @@
+export default () => {
+ const [defaultExpandedRowIds] = useState([0]);
+
+ return (
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/selection-controls.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/selection-controls.jsx
new file mode 100644
index 0000000000..8b98c1c339
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/selection-controls.jsx
@@ -0,0 +1,39 @@
+export default () => {
+ const [defaultExpandedRowIds] = useState([0]);
+
+ return (
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/uncontrolled-mode.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/uncontrolled-mode.jsx
new file mode 100644
index 0000000000..6dbaf6218a
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-tree-data/$migration/uncontrolled-mode.jsx
@@ -0,0 +1,34 @@
+export default () => {
+ const [defaultExpandedRowIds] = useState([0, 1]);
+
+ return (
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/column-virtualization.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/column-virtualization.jsx
new file mode 100644
index 0000000000..ddde6161d7
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/column-virtualization.jsx
@@ -0,0 +1,26 @@
+export default () => {
+ return (
+
+
+
+ {
+ columns.map((column) => (
+
+
+ ));
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/row-virtualization.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/row-virtualization.jsx
new file mode 100644
index 0000000000..4c5f7b23ea
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/row-virtualization.jsx
@@ -0,0 +1,22 @@
+export default () => {
+ const [columns] = useState([
+ { dataField: 'Id', caption: 'ID' },
+ { dataField: 'name', caption: 'Name' },
+ { dataField: 'gender', caption: 'Gender' },
+ { dataField: 'city', caption: 'City' },
+ { dataField: 'car', caption: 'Car' }
+ ]);
+
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/scroll-to-row.jsx b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/scroll-to-row.jsx
new file mode 100644
index 0000000000..9d3393af51
--- /dev/null
+++ b/packages/dx-react-grid-demos/src/demo-sources/grid-virtual-scrolling/$migration/scroll-to-row.jsx
@@ -0,0 +1,31 @@
+export default () => {
+ const [columns] = useState([
+ { dataField: 'name', caption: 'Name', defaultSortOrder: 'asc' },
+ { dataField: 'gender', caption: 'Gender', allowSorting: false },
+ { dataField: 'city', caption: 'City', allowSorting: false },
+ { dataField: 'car', caption: 'Car', allowSorting: false }
+ ]);
+
+ const onRowInserted = useCallback((e) => {
+ e.component.navigateToRow(e.key);
+ }, []);
+
+ return (
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-all-day-panel/$migration/week-view.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-all-day-panel/$migration/week-view.jsx
new file mode 100644
index 0000000000..2993b0250c
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-all-day-panel/$migration/week-view.jsx
@@ -0,0 +1,13 @@
+const views = ['week'];
+
+export default () => (
+
+);
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/basic-setup.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/basic-setup.jsx
new file mode 100644
index 0000000000..e8a3cc55dd
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/basic-setup.jsx
@@ -0,0 +1,20 @@
+import Scheduler from 'devextreme-react/scheduler';
+
+const currentDate = '2018-11-01';
+const schedulerData = [
+ { startDate: '2018-11-01T09:45', endDate: '2018-11-01T11:00', title: 'Meeting' },
+ { startDate: '2018-11-01T12:00', endDate: '2018-11-01T13:30', title: 'Go to a gym' },
+];
+
+const views = ['day'];
+
+export default () => (
+
+);
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/custom-template.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/custom-template.jsx
new file mode 100644
index 0000000000..68f9ef1b11
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/custom-template.jsx
@@ -0,0 +1,66 @@
+const getDateCellClassName = (isToday, isWeekend) => {
+ if (isToday) {
+ return 'dark-blue-background';
+ }
+ if (isWeekend) {
+ return 'dark-gray-background';
+ }
+ };
+
+ const DateCell = ({ isToday, isWeekend, date }) => {
+ return (
+
+
+ { date.toLocaleString(window.navigator.language, { weekday: 'short' }) }
+
+
+ { date.getDate() }
+
+
+ );
+ };
+
+ const getDataCellClassName = (isToday, isWeekend) => {
+ if (isToday) {
+ return 'blue-background';
+ }
+ if (isWeekend) {
+ return 'gray-background';
+ }
+ };
+
+ const DataCell = ({ isToday, isWeekend }) => {
+ return (
+
+ );
+ };
+
+ const cellRender = (CellComponent, datePropName) => (props) => {
+ const cellDate = props[datePropName];
+ const date = new Date(cellDate);
+
+ if (date.getDate() === new Date().getDate()) {
+ return ;
+ }
+
+ if (date.getDay() === 0 || date.getDay() === 6) {
+ return ;
+ }
+
+ return ;
+ };
+
+ const views = ['week'];
+
+ export default () => (
+
+);
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/day.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/day.jsx
new file mode 100644
index 0000000000..88f0666a35
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/day.jsx
@@ -0,0 +1,11 @@
+const views = ['day'];
+
+export default () => (
+
+);
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/month.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/month.jsx
new file mode 100644
index 0000000000..5e0cc1694d
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/month.jsx
@@ -0,0 +1,11 @@
+const views = ['month'];
+const currentDate = '2018-07-17';
+
+export default () => (
+
+);
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/simple-template.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/simple-template.jsx
new file mode 100644
index 0000000000..4bb197acc2
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/simple-template.jsx
@@ -0,0 +1,29 @@
+const views = ['week'];
+
+const renderAppointment = ({ targetedAppointmentData }) => {
+ return (
+
+
{targetedAppointmentData.text}
+
+ {formatDate(targetedAppointmentData.displayStartDate, 'shortTime')}
+ {' - '}
+ {formatDate(targetedAppointmentData.displayEndDate, 'shortTime')}
+
+
+ );
+};
+
+export default () => (
+
+);
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/week.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/week.jsx
new file mode 100644
index 0000000000..cb3483e490
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-basic/$migration/week.jsx
@@ -0,0 +1,12 @@
+const views = ['week'];
+
+export default () => (
+
+);
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-current-time-indication/$migration/current-time-indicator.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-current-time-indication/$migration/current-time-indicator.jsx
new file mode 100644
index 0000000000..79da3345e4
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-current-time-indication/$migration/current-time-indicator.jsx
@@ -0,0 +1,54 @@
+/* ... */
+
+const CheckBoxContainer = (({
+ shadePreviousCells, handleCheckboxChange,
+ }) => (
+
+
+
+ ));
+
+ export default () => {
+ const [updateInterval, setUpdateInterval] = useState(10000);
+ const [shadePreviousCells, setShadePreviousCells] = useState(true);
+
+ const handleUpdateIntervalChange = useCallback((nextValue) => {
+ setUpdateInterval(nextValue * 1000);
+ }, [])
+
+ const handleCheckboxChange = useCallback(() => {
+ setShadePreviousCells(shadeCells => !shadeCells);
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/controlled.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/controlled.jsx
new file mode 100644
index 0000000000..35b7bf8dcd
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/controlled.jsx
@@ -0,0 +1,18 @@
+export default () => {
+ const [currentDate, setCurrentDate] = useState('2018-06-27');
+
+ return (
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/uncontrolled.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/uncontrolled.jsx
new file mode 100644
index 0000000000..9efe9e16f3
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-date-navigator/$migration/uncontrolled.jsx
@@ -0,0 +1,10 @@
+export default () => {
+ return (
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/copy-after-dragdrop.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/copy-after-dragdrop.jsx
new file mode 100644
index 0000000000..8def135c00
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/copy-after-dragdrop.jsx
@@ -0,0 +1,32 @@
+export default () => {
+ const shouldCopy = useRef(false);
+
+ const onDragEnd = useCallback(({ itemData, toItemData, event }) => {
+ shouldCopy.current = event.shiftKey && (itemData.startDate !== toItemData.startDate || itemData.endDate !== toItemData.endDate);
+ }, [shouldCopy.current]);
+
+ const onAppointmentUpdating = useCallback((e) => {
+ if (shouldCopy.current) {
+ e.cancel = true;
+ shouldCopy.current = false;
+ e.component.addAppointment(e.newData);
+ }
+ }, []);
+
+ return (
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/delete-confirmation.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/delete-confirmation.jsx
new file mode 100644
index 0000000000..98b67936b6
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/delete-confirmation.jsx
@@ -0,0 +1,24 @@
+export default () => {
+ const onAppointmentEditing = useCallback((e) => {
+ if(!window.confirm('Are you sure you want to edit/delete this appointment?')) {
+ e.cancel = true;
+ }
+ }, []);
+
+ return (
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/drag-drop.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/drag-drop.jsx
new file mode 100644
index 0000000000..30398bc911
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/drag-drop.jsx
@@ -0,0 +1,25 @@
+const dragDisableIds = new Set([3, 8, 10, 12]);
+
+export default () => {
+ const onDragStart = useCallback(e => {
+ if (dragDisableIds.has(e.itemData.id)) {
+ e.cancel = true;
+ }
+ }, []);
+
+ return (
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/editing-features.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/editing-features.jsx
new file mode 100644
index 0000000000..2cc7640218
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/editing-features.jsx
@@ -0,0 +1,52 @@
+export default () => {
+ const [editingOptions, setEditingOptions] = useState({
+ allowAdding: true,
+ allowDeleting: true,
+ allowUpdating: true,
+ allowDragging: true,
+ allowResizing: true,
+ });
+
+ const handleEditingOptionsChange = useCallback(({ target }) => {
+ const { value } = target;
+ const { [value]: checked } = editingOptions;
+ setEditingOptions({
+ ...editingOptions,
+ [value]: !checked,
+ });
+ });
+
+ const {
+ allowAdding, allowDeleting, allowUpdating, allowResizing, allowDragging,
+ } = editingOptions;
+
+ return (
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/form-customization.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/form-customization.jsx
new file mode 100644
index 0000000000..4162300db2
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/form-customization.jsx
@@ -0,0 +1,32 @@
+export default () => {
+ const onAppointmentFormOpening = useCallback(e => {
+ let formItems = e.form.option("items");
+
+ formItems.push({
+ colSpan: 2,
+ label: { text: "Custom Field" },
+ editorType: "dxTextBox",
+ dataField: "customField"
+ });
+
+ formItems = formItems.filter(item => item.label?.text !== 'More Information')
+
+ e.form.option("items", formItems);
+ }, []);
+
+ return (
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/uncontrolled.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/uncontrolled.jsx
new file mode 100644
index 0000000000..0b79a7ad74
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-editing/$migration/uncontrolled.jsx
@@ -0,0 +1,15 @@
+export default () => {
+ return (
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/basic.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/basic.jsx
new file mode 100644
index 0000000000..eb96f5777d
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/basic.jsx
@@ -0,0 +1,33 @@
+export default () => {
+ const [groups] = useState(['roomId', 'members']);
+
+ return (
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/custom.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/custom.jsx
new file mode 100644
index 0000000000..343d1856d6
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/custom.jsx
@@ -0,0 +1,65 @@
+const colors = ['rgba(102, 187, 106, 0.1)', 'rgba(255, 167, 38, 0.15)'];
+const iconClasses = ['low-priority-icon', 'high-priority-icon'];
+
+export default () => {
+ const dataCellRender = useCallback(({ groupIndex, text }) => {
+ return (
+
+ { text }
+
+ );
+ }, []);
+
+ const dateCellRender = useCallback(({ groupIndex, date }) => {
+ return (
+
+
+ { date.toLocaleString(window.navigator.language, { weekday: 'short' }) }
+
+
+ { date.getDate() }
+
+
+ );
+ }, []);
+
+ const resourceCellRender = useCallback(({ id, text }) => {
+ const Icon = getIconById(id);
+
+ return (
+
+ { text }
+
+
+ );
+ }, []);
+
+ const [groups] = useState(['priorityId']);
+ const [data] = useState(appointments.filter(appointment => appointment.priorityId < 3));
+
+ return (
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-by-dates.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-by-dates.jsx
new file mode 100644
index 0000000000..9266d24299
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-by-dates.jsx
@@ -0,0 +1,36 @@
+export default () => {
+ const [groups] = useState(['priorityId']);
+ const [groupByDate, setGroupByDate] = useState(true);
+
+ const onGroupOrderChange = useCallback(() => {
+ setGroupByDate(groupByDate => !groupByDate);
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-orientation.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-orientation.jsx
new file mode 100644
index 0000000000..f0213a2814
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-grouping/$migration/group-orientation.jsx
@@ -0,0 +1,41 @@
+export default () => {
+ const [priorityInstances] = useState([
+ { text: 'Low Priority', id: 1, color: blue },
+ { text: 'High Priority', id: 2, color: orange },
+ ]);
+
+ const [groups] = useState(['priorityId']);
+
+ return (
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/custom-formatting.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/custom-formatting.jsx
new file mode 100644
index 0000000000..2486f9a06d
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/custom-formatting.jsx
@@ -0,0 +1,47 @@
+export default () => {
+ const formatDayScaleDate = useCallback((date) => {
+ const momentDate = moment(date);
+ const weekday = momentDate.weekday();
+ return momentDate.format(weekday === 6 || weekday === 0 ? 'D' : 'dddd');
+ }, []);
+
+ const dateCellRender = useCallback(({ date }) => {
+ return (
+
+
+ { formatDayScaleDate(date) }
+
+
+ { date.getDate() }
+
+
+ );
+ }, []);
+
+ const timeCellRender = useCallback(({ date }) => {
+ return (
+
+ { formatTimeScaleDate(date) }
+
+ );
+ }, []);
+
+ return (
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/locale.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/locale.jsx
new file mode 100644
index 0000000000..dcfe0109c8
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-localization/$migration/locale.jsx
@@ -0,0 +1,43 @@
+import deMessages from 'devextreme/localization/messages/de.json';
+import frMessages from 'devextreme/localization/messages/fr.json';
+import { locale, loadMessages, formatMessage } from 'devextreme/localization';
+
+const DEFAULT_LOCALE = 'fr-FR';
+
+const getLocale = () => sessionStorage.getItem('locale') || DEFAULT_LOCALE;
+
+locale(getLocale());
+
+loadMessages(deMessages);
+loadMessages(frMessages);
+
+export default () => {
+ const [locale, setLocale] = useState(getLocale());
+
+ const onLocaleChange = useCallback(e => {
+ sessionStorage.setItem('locale', e.target.value);
+ setLocale(e.target.value);
+ document.location.reload();
+ }, []);
+
+ return (
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-recurrence/$migration/basic.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-recurrence/$migration/basic.jsx
new file mode 100644
index 0000000000..2ceff326b9
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-recurrence/$migration/basic.jsx
@@ -0,0 +1,22 @@
+const views = ['week', 'month'];
+
+export default () => (
+
+
+
+);
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/basic.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/basic.jsx
new file mode 100644
index 0000000000..b222f2df21
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/basic.jsx
@@ -0,0 +1,39 @@
+export default () => {
+ const [mainResourceName, setMainResourceName] = useState(resources[0]);
+
+ const changeMainResource = useCallback((mainResourceName) => {
+ setMainResourceName(mainResourceName);
+ }, []);
+
+ return (
+
+
+
+
+ {
+ resources.map(resource => (
+
+ ))
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/editing.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/editing.jsx
new file mode 100644
index 0000000000..3bfb6b5191
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-resources/$migration/editing.jsx
@@ -0,0 +1,26 @@
+export default () => {
+ return (
+
+
+
+ {
+ resources.map(resource => (
+
+ ))
+ }
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-tooltip/$migration/custom.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-tooltip/$migration/custom.jsx
new file mode 100644
index 0000000000..7721000cfb
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-tooltip/$migration/custom.jsx
@@ -0,0 +1,31 @@
+/* Lots of code here */
+
+const renderAppointmentTooltip = ({ appointmentData }) => {
+ return (
+
+
+
+
+
+
+
+
+ );
+ };
+
+ export default () => {
+ return (
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/controlled.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/controlled.jsx
new file mode 100644
index 0000000000..60ba3db474
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/controlled.jsx
@@ -0,0 +1,31 @@
+export default () => {
+ const [currentView, setCurrentView] = useState('workWeek');
+
+ return (
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/external-control.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/external-control.jsx
new file mode 100644
index 0000000000..908f61f593
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/external-control.jsx
@@ -0,0 +1,57 @@
+const ExternalViewSwitcher = ({
+ currentView,
+ onChange,
+ }) => (
+
+ } label="Week" />
+ } label="Work Week" />
+ } label="Month" />
+
+ );
+
+ export default () => {
+ const [currentView, setCurrentView] = useState('month');
+
+ const onOptionChanged = useCallback(e => {
+ if (e.fullName === 'currentView') {
+ setCurrentView(e.value);
+ }
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/uncontrolled.jsx b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/uncontrolled.jsx
new file mode 100644
index 0000000000..fa5f65458b
--- /dev/null
+++ b/packages/dx-react-scheduler-demos/src/demo-sources/scheduler-view-switcher/$migration/uncontrolled.jsx
@@ -0,0 +1,20 @@
+export default () => (
+
+
+
+
+);
\ No newline at end of file
diff --git a/packages/dx-react-scheduler-demos/src/index.jsx b/packages/dx-react-scheduler-demos/src/index.jsx
index a656a8d8ac..38c470cb2f 100644
--- a/packages/dx-react-scheduler-demos/src/index.jsx
+++ b/packages/dx-react-scheduler-demos/src/index.jsx
@@ -2,7 +2,7 @@ import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { initialize } from '@devexpress/dx-demo-shell';
import '@devexpress/dx-demo-shell/dist/index.css';
-import { demos } from './demo-registry';
+import { demos, migrationSamples } from './demo-registry';
import { themes } from './theme-registry';
import { themeComponents } from './theme-components-registry';
import { demoData } from './demo-data-registry';
@@ -10,6 +10,7 @@ import './index.css';
initialize({
demoSources: demos,
+ migrationSamples,
themeSources: themes,
themeComponents,
demoData,