Skip to content

Commit

Permalink
Merge branch 'next' into typo-grid
Browse files Browse the repository at this point in the history
  • Loading branch information
cherniavskii committed Dec 20, 2023
2 parents 9bcc91a + 671f66f commit fece5cb
Show file tree
Hide file tree
Showing 11 changed files with 250 additions and 157 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/cherry-pick-next-to-master.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
name: Cherry pick next to master

on:
pull_request_target:
branches:
Expand All @@ -23,6 +25,7 @@ jobs:
branch: master
body: 'Cherry-pick of #{old_pull_request_id}'
cherry-pick-branch: ${{ format('cherry-pick-{0}', github.event.number) }}
title: '{old_title} (@${{ github.event.pull_request.user.login }})'
labels: |
cherry-pick
env:
Expand Down
6 changes: 3 additions & 3 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@
"react": "^18.2.0",
"react-docgen": "^5.4.3",
"react-dom": "^18.2.0",
"react-hook-form": "^7.49.0",
"react-hook-form": "^7.49.2",
"react-is": "^18.2.0",
"react-router": "^6.20.1",
"react-router-dom": "^6.20.1",
"react-router": "^6.21.0",
"react-router-dom": "^6.21.0",
"react-runner": "^1.0.3",
"react-simple-code-editor": "^0.13.1",
"recast": "^0.23.4",
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@
"@types/requestidlecallback": "^0.3.7",
"@types/sinon": "^10.0.20",
"@types/yargs": "^17.0.32",
"@typescript-eslint/eslint-plugin": "^6.13.2",
"@typescript-eslint/parser": "^6.13.2",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"@typescript-eslint/parser": "^6.15.0",
"axe-core": "4.8.2",
"babel-loader": "^9.1.3",
"babel-plugin-istanbul": "^6.1.1",
Expand All @@ -122,14 +122,14 @@
"cross-env": "^7.0.3",
"danger": "^11.3.1",
"enzyme": "^3.11.0",
"eslint": "^8.55.0",
"eslint": "^8.56.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.1.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-webpack": "^0.13.8",
"eslint-plugin-filenames": "^1.3.2",
"eslint-plugin-import": "^2.29.0",
"eslint-plugin-jsdoc": "^46.9.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsdoc": "^46.9.1",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-mocha": "^10.2.0",
"eslint-plugin-prettier": "^5.0.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/eslint-plugin-material-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"description": "Custom eslint rules for MUI X.",
"main": "src/index.js",
"devDependencies": {
"@types/eslint": "^8.44.8",
"@types/eslint": "^8.44.9",
"@typescript-eslint/experimental-utils": "^5.62.0",
"@typescript-eslint/parser": "^6.13.2"
"@typescript-eslint/parser": "^6.15.0"
},
"scripts": {
"test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/eslint-plugin-material-ui/**/*.test.js' --timeout 3000"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ describe('<DateField /> - Editing', () => {
);

describeAdapters('Pasting', DateField, ({ adapter, render, renderWithProps, clickOnInput }) => {
const firePasteEvent = (input: HTMLInputElement, pastedValue: string) => {
const firePasteEvent = (input: HTMLInputElement, pastedValue?: string, rawValue?: string) => {
act(() => {
const clipboardEvent = new window.Event('paste', {
bubbles: true,
Expand All @@ -755,14 +755,18 @@ describe('<DateField /> - Editing', () => {

// @ts-ignore
clipboardEvent.clipboardData = {
getData: () => pastedValue,
getData: () => pastedValue ?? rawValue ?? '',
};
// canContinue is `false` if default have been prevented
const canContinue = input.dispatchEvent(clipboardEvent);
if (!canContinue) {
return;
}

if (!pastedValue) {
return;
}

const prevValue = input.value;
const nextValue = `${prevValue.slice(
0,
Expand Down Expand Up @@ -927,6 +931,24 @@ describe('<DateField /> - Editing', () => {
fireEvent.change(input, { target: { value: '09/2/2022' } }); // Press 2
expectInputValue(input, '09/02/2022'); // If internal state is not reset it would be 22 instead of 02
});

it('should allow pasting a section', () => {
const { input, selectSection } = renderWithProps({
defaultValue: adapter.date('2018-12-05'),
});

selectSection('month');

fireEvent.change(input, { target: { value: '1/05/2018' } }); // initiate search query on month section
expectInputValue(input, '01/05/2018');

firePasteEvent(input, undefined, '05');
expectInputValue(input, '05/05/2018');

selectSection('month'); // move back to month section
fireEvent.change(input, { target: { value: '2/05/2018' } }); // check that the search query has been cleared after pasting
expectInputValue(input, '02/05/2018'); // If internal state is not reset it would be 12 instead of 02
});
});

describeAdapters(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,50 +130,36 @@ const PickersSectionList = React.forwardRef(function PickersSectionList(
const rootRef = React.useRef<HTMLDivElement>(null);
const handleRootRef = useForkRef(ref, rootRef);

const getRoot = (methodName: string) => {
if (!rootRef.current) {
throw new Error(
`MUI: Cannot call sectionListRef.${methodName} before the mount of the component`,
);
}

return rootRef.current;
};

React.useImperativeHandle(sectionListRef, () => ({
getRoot() {
if (!rootRef.current) {
throw new Error(
'MUI: Cannot call sectionListRef.getRoot before the mount of the component',
);
}

return rootRef.current;
return getRoot('getRoot');
},
getSectionContainer(index) {
if (!rootRef.current) {
throw new Error(
'MUI: Cannot call sectionListRef.getSectionContainer before the mount of the component',
);
}

return rootRef.current.querySelector<HTMLSpanElement>(
const root = getRoot('getSectionContainer');
return root.querySelector<HTMLSpanElement>(
`.${pickersSectionListClasses.section}[data-sectionindex="${index}"]`,
)!;
},
getSectionContent(index) {
if (!rootRef.current) {
throw new Error(
'MUI: Cannot call sectionListRef.getSectionContent before the mount of the component',
);
}

return rootRef.current.querySelector<HTMLSpanElement>(
const root = getRoot('getSectionContent');
return root.querySelector<HTMLSpanElement>(
`.${pickersSectionListClasses.section}[data-sectionindex="${index}"] .${pickersSectionListClasses.sectionContent}`,
)!;
},
getSectionIndexFromDOMElement(element) {
if (!rootRef.current) {
throw new Error(
'MUI: Cannot call sectionListRef.getSectionIndexFromDOMElement before the mount of the component',
);
}

if (element == null) {
return null;
}
const root = getRoot('getSectionIndexFromDOMElement');

if (!rootRef.current.contains(element)) {
if (element == null || !root.contains(element)) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
Unstable_PickersSectionListSectionContent as PickersSectionListSectionContent,
} from '../../../PickersSectionList';

const round = (value) => Math.round(value * 1e5) / 1e5;

const PickersInputRoot = styled(Box, {
name: 'MuiPickersInput',
slot: 'Root',
Expand All @@ -25,14 +27,19 @@ const PickersInputRoot = styled(Box, {
const borderColor =
theme.palette.mode === 'light' ? 'rgba(0, 0, 0, 0.23)' : 'rgba(255, 255, 255, 0.23)';
return {
...theme.typography.body1,
color: (theme.vars || theme).palette.text.primary,

cursor: 'text',
padding: '16.5px 14px',
padding: '0 14px',
display: 'flex',
justifyContent: 'flex-start',
alignItems: 'center',
width: ownerState.fullWidth ? '100%' : '25ch',
position: 'relative',
borderRadius: (theme.vars || theme).shape.borderRadius,
boxSizing: 'border-box', // Prevent padding issue with fullWidth.
letterSpacing: `${round(0.15 / 16)}em`,

[`&:hover .${pickersInputClasses.notchedOutline}`]: {
borderColor: (theme.vars || theme).palette.text.primary,
},
Expand Down Expand Up @@ -65,10 +72,6 @@ const PickersInputRoot = styled(Box, {
[`&.${pickersInputClasses.error} .${pickersInputClasses.notchedOutline}`]: {
borderColor: (theme.vars || theme).palette.error.main,
},

...(ownerState.size === 'small' && {
padding: '8.5px 14px',
}),
};
});

Expand All @@ -80,7 +83,19 @@ const PickersInputSectionsContainer = styled(PickersSectionListRoot, {
fontFamily: theme.typography.fontFamily,
fontSize: 'inherit',
lineHeight: '1.4375em', // 23px
outline: 'none',
display: 'flex',
flexWrap: 'nowrap',
padding: '16.5px 0',
flexGrow: 1,
overflow: 'hidden',
letterSpacing: 'inherit',
// Chrome behavior
width: '182px',

...(ownerState.size === 'small' && {
padding: '8.5px 0',
}),
...(theme.direction === 'rtl' && { textAlign: 'right /*! @noflip */' as any }),
...(!(ownerState.adornedStart || ownerState.focused || ownerState.filled) && {
color: 'currentColor',
Expand All @@ -103,8 +118,9 @@ const PickersInputSection = styled(PickersSectionListSection, {
})(({ theme }) => ({
fontFamily: theme.typography.fontFamily,
fontSize: 'inherit',
letterSpacing: 'inherit',
lineHeight: '1.4375em', // 23px
flexGrow: 1,
display: 'flex',
}));

const PickersInputSectionContent = styled(PickersSectionListSectionContent, {
Expand All @@ -123,7 +139,10 @@ const PickersInputSeparator = styled(PickersSectionListSectionSeparator, {
name: 'MuiPickersInput',
slot: 'Separator',
overridesResolver: (props, styles) => styles.separator,
})(() => ({}));
})(() => ({
whiteSpace: 'pre',
letterSpacing: 'inherit',
}));

const PickersInputInput = styled('input', {
name: 'MuiPickersInput',
Expand Down Expand Up @@ -257,6 +276,7 @@ export const PickersInput = React.forwardRef(function PickersInput(

const ownerState: OwnerStateType = {
...(props as Omit<PickersInputProps, keyof FormControlState>),

...muiFormControl,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,14 @@ export const useField = <
(activeSection.contentType === 'digit' && digitsOnly) ||
(activeSection.contentType === 'digit-with-letter' && digitsAndLetterOnly);
if (isValidPastedValue) {
// Early return to let the paste update section, value
resetCharacterQuery();
updateSectionValue({
activeSection,
newSectionValue: pastedValue,
shouldGoToNextSection: true,
});
// prevent default to avoid the input change handler being called
event.preventDefault();
return;
}
if (lettersOnly || digitsOnly) {
Expand Down
37 changes: 36 additions & 1 deletion test/e2e/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { platform } from 'node:os';
import { expect } from 'chai';
import {
chromium,
Expand Down Expand Up @@ -547,10 +548,44 @@ async function initializeEnvironment(
const input = page.getByRole('textbox');

await input.focus();
await input.type('04/11/2022');
await input.fill('04/11/2022');

expect(await input.inputValue()).to.equal('04/11/2022');
});

it('should allow pasting a section', async () => {
// Only firefox is capable of reliably running this test in CI and headless browsers
if (browserType.name() !== 'firefox' && process.env.CIRCLECI) {
return;
}
await renderFixture('DatePicker/BasicDesktopDatePicker');
const input = page.getByRole('textbox');

const isMac = platform() === 'darwin';
const modifier = isMac ? 'Meta' : 'Control';

await input.focus();
// ensure that the focus is moved to the end section by typing naturally - with a timeout
await input.pressSequentially('04/11/2022');
// move to day section
await input.press('ArrowLeft');
// copy day section value
await input.press(`${modifier}+KeyC`);
// move to month section
await input.press('ArrowLeft');
// initiate search query on month section
await input.press('1');
// paste day section value to month section
await input.press(`${modifier}+KeyV`);

expect(await input.inputValue()).to.equal('11/11/2022');

// move back to month section
await input.press('ArrowLeft');
// check that the search query has been cleared after pasting
await input.press('2');
expect(await input.inputValue()).to.equal('02/11/2022');
});
});
describe('<MobileDatePicker />', () => {
it('should allow selecting a value', async () => {
Expand Down
26 changes: 19 additions & 7 deletions test/regressions/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ async function main() {
// prepare screenshots
await fse.emptyDir(screenshotDir);

function navigateToTest(testIndex) {
// Use client-side routing which is much faster than full page navigation via page.goto().
// Could become an issue with test isolation.
// If tests are flaky due to global pollution switch to page.goto(route);
// puppeteers built-in click() times out
return page.$eval(`#tests li:nth-of-type(${testIndex}) a`, (link) => {
link.click();
});
}

describe('visual regressions', () => {
after(async () => {
await browser.close();
Expand All @@ -91,13 +101,15 @@ async function main() {
this.timeout(6000);
}

// Use client-side routing which is much faster than full page navigation via page.goto().
// Could become an issue with test isolation.
// If tests are flaky due to global pollution switch to page.goto(route);
// puppeteers built-in click() times out
await page.$eval(`#tests li:nth-of-type(${index + 1}) a`, (link) => {
link.click();
});
try {
await navigateToTest(index + 1);
} catch (error) {
// When one demo crashes, the page becomes empty and there are no links to demos,
// so navigation to the next demo throws an error.
// Reloading the page fixes this.
await page.reload();
await navigateToTest(index + 1);
}
// Move cursor offscreen to not trigger unwanted hover effects.
page.mouse.move(0, 0);

Expand Down
Loading

0 comments on commit fece5cb

Please sign in to comment.