Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merging master in release #124

Merged
merged 16 commits into from
Jul 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ jobs:
- run:
name: Should not have any git not staged
command: git diff --exit-code
- run:
name: Check for duplicated packages
command: yarn deduplicate
- save_cache:
key: v2-yarn-sha-{{ checksum "yarn.lock" }}
paths:
Expand All @@ -59,8 +62,11 @@ jobs:
name: '`yarn prettier` changes committed?'
command: yarn prettier check-changed
- run:
name: Lint
command: yarn lint:ci
name: Eslint
command: yarn eslint:ci
- run:
name: Lint JSON
command: yarn jsonlint
workflows:
version: 2
pipeline:
Expand Down
16 changes: 7 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
{
"name": "material-ui-x",
"version": "0.1.0",
"description": "Material-UI X Monorepo",
"author": "Material-UI Team",
"private": true,
"devDependencies": {
"@material-ui/core": "^4.9.12",
Expand Down Expand Up @@ -45,20 +42,21 @@
"stylelint-config-standard": "^20.0.0",
"stylelint-config-styled-components": "^0.1.1",
"stylelint-processor-styled-components": "^1.10.0",
"ts-jest": "^25.2.0"
"ts-jest": "^25.2.0",
"yarn-deduplicate": "^2.1.1"
},
"scripts": {
"deduplicate": "node scripts/deduplicate.js",
"jsonlint": "node scripts/jsonlint.js",
"hoist": "lerna bootstrap --hoist",
"bootstrap": "lerna bootstrap",
"build": "lerna run build --stream",
"start": "lerna run start --parallel",
"prettier": "node ./scripts/prettier.js",
"test": "lerna run test --parallel",
"lint": "eslint . --cache --report-unused-disable-directives --ext .js,.ts,.tsx",
"lint:ci": "eslint . --report-unused-disable-directives --ext .js,.ts,.tsx"
},
"eslintConfig": {
"extends": "react-app"
"lint": "yarn eslint && yarn jsonlint",
"eslint": "eslint . --cache --report-unused-disable-directives --ext .js,.ts,.tsx",
"eslint:ci": "eslint . --report-unused-disable-directives --ext .js,.ts,.tsx"
},
"setupFiles": [
"<rootDir>/src/setupTests.js"
Expand Down
3 changes: 2 additions & 1 deletion packages/grid/x-grid-modules/src/components/row-cells.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { buildCellParams } from '../utils/paramsUtils';

function applyCssClassRules(cellClassRules: CellClassRules, params: CellClassParams) {
return Object.entries(cellClassRules).reduce((appliedCss, entry) => {
const shouldApplyCss: boolean = entry[1](params);
const shouldApplyCss: boolean = isFunction(entry[1]) ? entry[1](params) : entry[1];
appliedCss += shouldApplyCss ? `${entry[0]} ` : '';
return appliedCss;
}, '');
Expand Down Expand Up @@ -60,6 +60,7 @@ export const RowCells: React.FC<RowCellsProps> = React.memo((props) => {
if (column.valueGetter) {
// Value getter override the original value
value = column.valueGetter(cellParams);
cellParams.value = value;
}

let formattedValueProp = {};
Expand Down
2 changes: 1 addition & 1 deletion packages/grid/x-grid-modules/src/gridComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import { mergeOptions } from './utils/mergeOptions';
*/
export const GridComponent: React.FC<GridComponentProps> = React.memo(
({ rows, columns, options, apiRef, loading, licenseStatus, className, components }) => {
useLoggerFactory(options?.logger, options?.logLevel);
useLoggerFactory(options?.logger, options?.logLevel || DEFAULT_GRID_OPTIONS.logLevel);
const logger = useLogger('Grid');
const rootContainerRef: RootContainerRef = React.useRef<HTMLDivElement>(null);
const footerRef = React.useRef<HTMLDivElement>(null);
Expand Down
13 changes: 11 additions & 2 deletions packages/grid/x-grid-modules/src/hooks/features/usePagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,21 @@ export const usePagination = (
logger.info(`Options or rows change, recalculating pageCount and rowCount`);
const newPageCount = getPageCount(state.pageSize, rowCount);

updateState({ pageCount: newPageCount, rowCount: rows.length });
updateState({ pageCount: newPageCount, rowCount });
if (state.page > newPageCount) {
setPage(newPageCount);
}
}
}, [rows.length, logger, updateState, state.rowCount, state.pageSize, setPage, state.page]);
}, [
rows.length,
options.rowCount,
logger,
updateState,
state.rowCount,
state.pageSize,
setPage,
state.page,
]);

React.useEffect(() => {
if (
Expand Down
8 changes: 4 additions & 4 deletions packages/grid/x-grid-modules/src/hooks/root/useApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export function useApi(
}
return eventParams;
},
[emitEvent, apiRef],
[apiRef],
);

const onClickHandler = React.useCallback(
Expand All @@ -158,7 +158,7 @@ export function useApi(
emitEvent(COLUMN_HEADER_CLICK, eventParams.header);
}
},
[emitEvent, apiRef],
[emitEvent, getEventParams],
);

const onHoverHandler = React.useCallback(
Expand All @@ -179,7 +179,7 @@ export function useApi(
emitEvent(COLUMN_HEADER_HOVER, eventParams.header);
}
},
[emitEvent, apiRef],
[emitEvent, getEventParams],
);

const registerEvent = React.useCallback(
Expand Down Expand Up @@ -237,7 +237,7 @@ export function useApi(
}

return undefined;
}, [gridRootRef, isApiInitialised, getHandler, logger, onClickHandler, apiRef]);
}, [gridRootRef, isApiInitialised, getHandler, logger, onClickHandler, onHoverHandler, apiRef]);

useApiEventHandler(apiRef, COL_RESIZE_START, handleResizeStart);
useApiEventHandler(apiRef, COL_RESIZE_STOP, handleResizeStop);
Expand Down
30 changes: 21 additions & 9 deletions packages/grid/x-grid-modules/src/hooks/root/useKeyboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
KEYDOWN_EVENT,
KEYUP_EVENT,
MULTIPLE_KEY_PRESS_CHANGED,
SCROLLING,
} from '../../constants/eventsConstants';
import {
findGridRootFromCurrent,
Expand Down Expand Up @@ -45,6 +46,7 @@ const getNextCellIndexes = (code: string, indexes: CellIndexCoordinates) => {
export const useKeyboard = (options: GridOptions, initialised: boolean, apiRef: ApiRef): void => {
const logger = useLogger('useKeyboard');
const isMultipleKeyPressed = React.useRef(false);
const rafFocusOnCellRef = React.useRef(0);

const onMultipleKeyChange = React.useCallback(
(isPressed: boolean) => {
Expand Down Expand Up @@ -106,19 +108,29 @@ export const useKeyboard = (options: GridOptions, initialised: boolean, apiRef:
nextCellIndexes.colIndex =
nextCellIndexes.colIndex >= colCount ? colCount - 1 : nextCellIndexes.colIndex;

apiRef.current!.scrollToIndexes(nextCellIndexes);
setTimeout(() => {
const nextCell = getCellElementFromIndexes(root, nextCellIndexes);
if (rafFocusOnCellRef.current) {
cancelAnimationFrame(rafFocusOnCellRef.current);
}

if (nextCell) {
nextCell.tabIndex = 0;
(nextCell as HTMLDivElement).focus();
}
}, 100);
apiRef.current!.once(SCROLLING, () => {
rafFocusOnCellRef.current = requestAnimationFrame(() => {
const nextCell = getCellElementFromIndexes(root, nextCellIndexes);

if (nextCell) {
logger.debug(
`Focusing on cell with index ${nextCellIndexes.rowIndex} - ${nextCellIndexes.colIndex} `,
);
nextCell.tabIndex = 0;
(nextCell as HTMLDivElement).focus();
}
});
});

apiRef.current!.scrollToIndexes(nextCellIndexes);

return nextCellIndexes;
},
[apiRef, options.pagination, options.pageSize],
[apiRef, options.pagination, options.pageSize, logger],
);

const selectActiveRow = React.useCallback(() => {
Expand Down
4 changes: 3 additions & 1 deletion packages/grid/x-grid-modules/src/models/cellClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ export type CellClassNamePropType = string | string[] | CellClassFn;
/**
* An object representing the cell class rules.
*/
export type CellClassRules = { [cssClass: string]: (params: CellClassParams) => boolean };
export type CellClassRules = {
[cssClass: string]: ((params: CellClassParams) => boolean) | boolean;
};
1 change: 1 addition & 0 deletions packages/grid/x-grid-modules/src/models/gridOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ export const DEFAULT_GRID_OPTIONS: GridOptions = {
paginationMode: FeatureMode.client,
extendRowFullWidth: true,
sortingOrder: ['asc', 'desc', null],
logLevel: 'warn',
columnTypes: DEFAULT_COLUMN_TYPES,
icons: {
columnSortedAscending: () => <ArrowUpward className="icon" />,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 9 additions & 1 deletion packages/storybook/integration/staticStories.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ const stories = [
await page.click('#action-btn');
},
},
{
path: '/story/x-grid-tests-selection--multiple-select-with-checkbox-no-click',
beforeTest: async (page) => {
await page.click(
'.grid-root .window .material-row:first-child .material-cell.checkbox-selection-cell .checkbox-input',
);
},
},
'/story/x-grid-tests-columns--header-component',
'/story/x-grid-tests-columns--new-column-types',
'/story/x-grid-tests-dataset--no-rows',
Expand Down Expand Up @@ -82,7 +90,7 @@ const stories = [
'/story/x-grid-tests-styling--column-cell-renderer',
];

describe.only('snapshotTest', () => {
describe('snapshotTest', () => {
stories.forEach((config: any) => {
const path = typeof config === 'string' ? config : config.path;
const beforeTest = typeof config === 'string' ? undefined : config.beforeTest;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { XGrid } from '@material-ui/x-grid';

<Meta title="1. Docs/12. Accessibility" component={XGrid} />

# Accessibility

Throughout our journey, accessibility has always been one of the core value of Material-UI components.
Hence the data-grid has no less than 70 accessibility standards implemented in our first beta version.

## Keyboard navigation

| Keys | Description |
| ---------------------------------------: | :------------------------------------------------ |
| <kbd>Tab</kbd> | Navigate between selectable elements |
| <kbd>Arrow Left</kbd> | Navigate between cell elements |
| <kbd>Arrow Bottom</kbd> | Navigate between cell elements |
| <kbd>Arrow Right</kbd> | Navigate between cell elements |
| <kbd>Arrow Up</kbd> | Navigate between cell elements |
| <kbd>Home</kbd> | Navigate to the first cell of the current row |
| <kbd>End</kbd> | Navigate to the last cell of the current row |
| <kbd>CMD/CTRL + Home</kbd> | Navigate to the first cell of the first row |
| <kbd>CMD/CTRL + End</kbd> | Navigate to the last cell of the last row |
| <kbd>Shift + Space</kbd> | Select the current row |
| <kbd>Shift + Space + Arrow Up/Down</kbd> | Select the current row and the row above or below |
| <kbd>Space</kbd> | Navigate to the next scrollable page |
| <kbd>Page Up</kbd> | Navigate to the next scrollable page |
| <kbd>Page Down</kbd> | Navigate to the previous scrollable page |
| <kbd>CMD/CTRL + A</kbd> | Select all rows |
| <kbd>CMD/CTRL + C</kbd> | Copy the currently selected row |
8 changes: 8 additions & 0 deletions packages/storybook/src/stories/grid-selection.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ export const MultipleSelect = () => {
return <XGrid rows={data.rows} columns={data.columns} options={options} />;
};
export const MultipleSelectWithCheckbox = () => {
const data = useData(200, 200);
const options: GridOptionsProp = {
checkboxSelection: true,
};

return <XGrid rows={data.rows} columns={data.columns} options={options} />;
};
export const MultipleSelectWithCheckboxNoClick = () => {
const data = useData(200, 200);
const options: GridOptionsProp = {
checkboxSelection: true,
Expand Down
1 change: 1 addition & 0 deletions packages/storybook/src/stories/grid-style.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export const ColumnCellClassRules = () => {
cols[4].cellClassRules = {
common: (params) => params.data.lastName === 'Smith',
unknown: (params) => !params.data.lastName,
border: true,
};

return (
Expand Down
3 changes: 3 additions & 0 deletions packages/storybook/src/style/grid-stories.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
.unknown {
background: coral;
}
.border {
border: 1px solid orangered;
}
#root {
top:0;
left: 0;
Expand Down
41 changes: 41 additions & 0 deletions scripts/deduplicate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* eslint-disable no-console */
const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');
const deduplicate = require('yarn-deduplicate');

const lockFile = path.resolve(__dirname, '../yarn.lock');
const yarnlock = fs.readFileSync(lockFile, 'utf8');

const duplicates = deduplicate.listDuplicates(yarnlock);
if (duplicates.length === 0) {
console.log('No duplicated packages found');
process.exit(0);
}

console.log(
`${duplicates.length} duplicated package(s) found\n${duplicates.map((x) => ` ${x}`).join('\n')}`,
);

if (process.env.CI) {
console.error(
[
`Error: There are currently ${duplicates.length} duplicated package(s).`,
`To deduplicate run "yarn deduplicate"`,
].join('\n'),
);
process.exit(1);
}

console.log('Deduplicating package(s)');
fs.writeFileSync(lockFile, deduplicate.fixDuplicates(yarnlock));

const yarn = spawn('yarn', {
shell: true,
stdio: 'inherit',
cwd: path.resolve(__dirname, '..'),
});

yarn.on('close', (code) => {
process.exit(code);
});
44 changes: 44 additions & 0 deletions scripts/jsonlint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* eslint-disable no-console */
const chalk = require('chalk');
const fse = require('fs-extra');
const glob = require('glob-gitignore');
const path = require('path');

const passMessage = (message) => `✓ ${chalk.gray(message)}`;
const failMessage = (message) => `✗ ${chalk.whiteBright(message)}`;

async function run() {
const workspaceRoot = path.resolve(__dirname, '..');

const eslintignoreContent = await fse.readFile(path.join(workspaceRoot, '.eslintignore'), {
encoding: 'utf8',
});
const eslintignore = eslintignoreContent.split(/\r?\n/).slice(0, -1);

const filenames = glob.sync('**/*.json', {
cwd: workspaceRoot,
ignore: [...eslintignore, 'tsconfig*.json', 'tslint.json'],
});

let passed = true;
const checks = filenames.map(async (filename) => {
const content = await fse.readFile(path.join(workspaceRoot, filename), { encoding: 'utf8' });
try {
JSON.parse(content);
console.log(passMessage(filename));
} catch (error) {
passed = false;
console.error(failMessage(`Error parsing ${filename}:\n\n${String(error)}`));
}
});

await Promise.all(checks);
if (passed === false) {
throw new Error('At least one file did not pass. Check the console output');
}
}

run().catch((error) => {
console.error(error);
process.exit(1);
});
Loading