Skip to content

Commit

Permalink
[RtlProvider] Add component & hook (mui#41241)
Browse files Browse the repository at this point in the history
  • Loading branch information
mnajdova committed Mar 8, 2024
1 parent a3dbaaf commit c284879
Show file tree
Hide file tree
Showing 17 changed files with 116 additions and 60 deletions.
8 changes: 5 additions & 3 deletions packages/mui-material/src/Drawer/Drawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
import clsx from 'clsx';
import integerPropType from '@mui/utils/integerPropType';
import composeClasses from '@mui/utils/composeClasses';
import { useRtl } from '@mui/system/RtlProvider';
import Modal from '../Modal';
import Slide from '../Slide';
import Paper from '../Paper';
Expand Down Expand Up @@ -137,8 +138,8 @@ export function isHorizontal(anchor) {
return ['left', 'right'].indexOf(anchor) !== -1;
}

export function getAnchor(theme, anchor) {
return theme.direction === 'rtl' && isHorizontal(anchor) ? oppositeDirection[anchor] : anchor;
export function getAnchor({ direction }, anchor) {
return direction === 'rtl' && isHorizontal(anchor) ? oppositeDirection[anchor] : anchor;
}

/**
Expand All @@ -148,6 +149,7 @@ export function getAnchor(theme, anchor) {
const Drawer = React.forwardRef(function Drawer(inProps, ref) {
const props = useThemeProps({ props: inProps, name: 'MuiDrawer' });
const theme = useTheme();
const isRtl = useRtl();
const defaultTransitionDuration = {
enter: theme.transitions.duration.enteringScreen,
exit: theme.transitions.duration.leavingScreen,
Expand Down Expand Up @@ -180,7 +182,7 @@ const Drawer = React.forwardRef(function Drawer(inProps, ref) {
mounted.current = true;
}, []);

const anchorInvariant = getAnchor(theme, anchorProp);
const anchorInvariant = getAnchor({ direction: isRtl ? 'rtl' : 'ltr' }, anchorProp);
const anchor = anchorProp;

const ownerState = {
Expand Down
8 changes: 4 additions & 4 deletions packages/mui-material/src/LinearProgress/LinearProgress.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import clsx from 'clsx';
import composeClasses from '@mui/utils/composeClasses';
import { keyframes, css } from '@mui/system';
import { darken, lighten } from '@mui/system/colorManipulator';
import { useRtl } from '@mui/system/RtlProvider';
import capitalize from '../utils/capitalize';
import useTheme from '../styles/useTheme';
import styled from '../styles/styled';
import useThemeProps from '../styles/useThemeProps';
import { getLinearProgressUtilityClass } from './linearProgressClasses';
Expand Down Expand Up @@ -283,7 +283,7 @@ const LinearProgress = React.forwardRef(function LinearProgress(inProps, ref) {
};

const classes = useUtilityClasses(ownerState);
const theme = useTheme();
const isRtl = useRtl();

const rootProps = {};
const inlineStyles = { bar1: {}, bar2: {} };
Expand All @@ -294,7 +294,7 @@ const LinearProgress = React.forwardRef(function LinearProgress(inProps, ref) {
rootProps['aria-valuemin'] = 0;
rootProps['aria-valuemax'] = 100;
let transform = value - 100;
if (theme.direction === 'rtl') {
if (isRtl) {
transform = -transform;
}
inlineStyles.bar1.transform = `translateX(${transform}%)`;
Expand All @@ -308,7 +308,7 @@ const LinearProgress = React.forwardRef(function LinearProgress(inProps, ref) {
if (variant === 'buffer') {
if (valueBuffer !== undefined) {
let transform = (valueBuffer || 0) - 100;
if (theme.direction === 'rtl') {
if (isRtl) {
transform = -transform;
}
inlineStyles.bar2.transform = `translateX(${transform}%)`;
Expand Down
9 changes: 5 additions & 4 deletions packages/mui-material/src/Menu/Menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import clsx from 'clsx';
import composeClasses from '@mui/utils/composeClasses';
import { useSlotProps } from '@mui/base/utils';
import HTMLElementType from '@mui/utils/HTMLElementType';
import { useRtl } from '@mui/system/RtlProvider';
import MenuList from '../MenuList';
import Popover, { PopoverPaper } from '../Popover';
import styled, { rootShouldForwardProp } from '../styles/styled';
import useTheme from '../styles/useTheme';
import useThemeProps from '../styles/useThemeProps';
import { getMenuUtilityClass } from './menuClasses';

Expand Down Expand Up @@ -85,8 +85,7 @@ const Menu = React.forwardRef(function Menu(inProps, ref) {
...other
} = props;

const theme = useTheme();
const isRtl = theme.direction === 'rtl';
const isRtl = useRtl();

const ownerState = {
...props,
Expand All @@ -108,7 +107,9 @@ const Menu = React.forwardRef(function Menu(inProps, ref) {

const handleEntering = (element, isAppearing) => {
if (menuListActionsRef.current) {
menuListActionsRef.current.adjustStyleForScrollbar(element, theme);
menuListActionsRef.current.adjustStyleForScrollbar(element, {
direction: isRtl ? 'rtl' : 'ltr',
});
}

if (onEntering) {
Expand Down
4 changes: 2 additions & 2 deletions packages/mui-material/src/MenuList/MenuList.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,13 @@ const MenuList = React.forwardRef(function MenuList(props, ref) {
React.useImperativeHandle(
actions,
() => ({
adjustStyleForScrollbar: (containerElement, theme) => {
adjustStyleForScrollbar: (containerElement, { direction }) => {
// Let's ignore that piece of logic if users are already overriding the width
// of the menu.
const noExplicitWidth = !listRef.current.style.width;
if (containerElement.clientHeight < listRef.current.clientHeight && noExplicitWidth) {
const scrollbarSize = `${getScrollbarSize(ownerDocument(containerElement))}px`;
listRef.current.style[theme.direction === 'rtl' ? 'paddingLeft' : 'paddingRight'] =
listRef.current.style[direction === 'rtl' ? 'paddingLeft' : 'paddingRight'] =
scrollbarSize;
listRef.current.style.width = `calc(100% + ${scrollbarSize})`;
}
Expand Down
31 changes: 15 additions & 16 deletions packages/mui-material/src/PaginationItem/PaginationItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import PropTypes from 'prop-types';
import clsx from 'clsx';
import composeClasses from '@mui/utils/composeClasses';
import { alpha } from '@mui/system/colorManipulator';
import { useRtl } from '@mui/system/RtlProvider';
import useThemeProps from '../styles/useThemeProps';
import paginationItemClasses, { getPaginationItemUtilityClass } from './paginationItemClasses';
import useTheme from '../styles/useTheme';
import ButtonBase from '../ButtonBase';
import capitalize from '../utils/capitalize';
import FirstPageIcon from '../internal/svg-icons/FirstPage';
Expand Down Expand Up @@ -288,23 +288,22 @@ const PaginationItem = React.forwardRef(function PaginationItem(inProps, ref) {
variant,
};

const theme = useTheme();
const isRtl = useRtl();
const classes = useUtilityClasses(ownerState);

const normalizedIcons =
theme.direction === 'rtl'
? {
previous: slots.next || components.next || NavigateNextIcon,
next: slots.previous || components.previous || NavigateBeforeIcon,
last: slots.first || components.first || FirstPageIcon,
first: slots.last || components.last || LastPageIcon,
}
: {
previous: slots.previous || components.previous || NavigateBeforeIcon,
next: slots.next || components.next || NavigateNextIcon,
first: slots.first || components.first || FirstPageIcon,
last: slots.last || components.last || LastPageIcon,
};
const normalizedIcons = isRtl
? {
previous: slots.next || components.next || NavigateNextIcon,
next: slots.previous || components.previous || NavigateBeforeIcon,
last: slots.first || components.first || FirstPageIcon,
first: slots.last || components.last || LastPageIcon,
}
: {
previous: slots.previous || components.previous || NavigateBeforeIcon,
next: slots.next || components.next || NavigateNextIcon,
first: slots.first || components.first || FirstPageIcon,
last: slots.last || components.last || LastPageIcon,
};

const Icon = normalizedIcons[type];

Expand Down
6 changes: 3 additions & 3 deletions packages/mui-material/src/Rating/Rating.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import clamp from '@mui/utils/clamp';
import visuallyHidden from '@mui/utils/visuallyHidden';
import chainPropTypes from '@mui/utils/chainPropTypes';
import composeClasses from '@mui/utils/composeClasses';
import useTheme from '../styles/useTheme';
import { useRtl } from '@mui/system/RtlProvider';
import {
capitalize,
useForkRef,
Expand Down Expand Up @@ -329,7 +329,7 @@ const Rating = React.forwardRef(function Rating(inProps, ref) {
});

const valueRounded = roundValueToPrecision(valueDerived, precision);
const theme = useTheme();
const isRtl = useRtl();
const [{ hover, focus }, setState] = React.useState({
hover: -1,
focus: -1,
Expand Down Expand Up @@ -364,7 +364,7 @@ const Rating = React.forwardRef(function Rating(inProps, ref) {

let percent;

if (theme.direction === 'rtl') {
if (isRtl) {
percent = (right - event.clientX) / containerWidth;
} else {
percent = (event.clientX - left) / containerWidth;
Expand Down
5 changes: 2 additions & 3 deletions packages/mui-material/src/Slider/Slider.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { isHostComponent, useSlotProps } from '@mui/base/utils';
import composeClasses from '@mui/utils/composeClasses';
import { useSlider, valueToPercent } from '@mui/base/useSlider';
import { alpha, lighten, darken } from '@mui/system/colorManipulator';
import { useRtl } from '@mui/system/RtlProvider';
import useThemeProps from '../styles/useThemeProps';
import styled, { slotShouldForwardProp } from '../styles/styled';
import useTheme from '../styles/useTheme';
import shouldSpreadAdditionalProps from '../utils/shouldSpreadAdditionalProps';
import capitalize from '../utils/capitalize';
import BaseSliderValueLabel from './SliderValueLabel';
Expand Down Expand Up @@ -404,8 +404,7 @@ const Forward = ({ children }) => children;
const Slider = React.forwardRef(function Slider(inputProps, ref) {
const props = useThemeProps({ props: inputProps, name: 'MuiSlider' });

const theme = useTheme();
const isRtl = theme.direction === 'rtl';
const isRtl = useRtl();

const {
'aria-label': ariaLabel,
Expand Down
5 changes: 2 additions & 3 deletions packages/mui-material/src/TabScrollButton/TabScrollButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import PropTypes from 'prop-types';
import clsx from 'clsx';
import { useSlotProps } from '@mui/base/utils';
import composeClasses from '@mui/utils/composeClasses';
import { useRtl } from '@mui/system/RtlProvider';
import KeyboardArrowLeft from '../internal/svg-icons/KeyboardArrowLeft';
import KeyboardArrowRight from '../internal/svg-icons/KeyboardArrowRight';
import ButtonBase from '../ButtonBase';
import useTheme from '../styles/useTheme';
import useThemeProps from '../styles/useThemeProps';
import styled from '../styles/styled';
import tabScrollButtonClasses, { getTabScrollButtonUtilityClass } from './tabScrollButtonClasses';
Expand Down Expand Up @@ -59,8 +59,7 @@ const TabScrollButton = React.forwardRef(function TabScrollButton(inProps, ref)
...other
} = props;

const theme = useTheme();
const isRtl = theme.direction === 'rtl';
const isRtl = useRtl();

const ownerState = { isRtl, ...props };

Expand Down
32 changes: 14 additions & 18 deletions packages/mui-material/src/TablePagination/TablePaginationActions.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
'use client';
import * as React from 'react';
import PropTypes from 'prop-types';
import { useRtl } from '@mui/system/RtlProvider';
import KeyboardArrowLeft from '../internal/svg-icons/KeyboardArrowLeft';
import KeyboardArrowRight from '../internal/svg-icons/KeyboardArrowRight';
import useTheme from '../styles/useTheme';
import IconButton from '../IconButton';
import LastPageIconDefault from '../internal/svg-icons/LastPage';
import FirstPageIconDefault from '../internal/svg-icons/FirstPage';
Expand All @@ -28,7 +28,7 @@ const TablePaginationActions = React.forwardRef(function TablePaginationActions(
...other
} = props;

const theme = useTheme();
const isRtl = useRtl();

const handleFirstPageButtonClick = (event) => {
onPageChange(event, 0);
Expand All @@ -55,19 +55,15 @@ const TablePaginationActions = React.forwardRef(function TablePaginationActions(
const NextButtonIcon = slots.nextButtonIcon ?? KeyboardArrowRight;
const PreviousButtonIcon = slots.previousButtonIcon ?? KeyboardArrowLeft;

const FirstButtonSlot = theme.direction === 'rtl' ? LastButton : FirstButton;
const PreviousButtonSlot = theme.direction === 'rtl' ? NextButton : PreviousButton;
const NextButtonSlot = theme.direction === 'rtl' ? PreviousButton : NextButton;
const LastButtonSlot = theme.direction === 'rtl' ? FirstButton : LastButton;
const FirstButtonSlot = isRtl ? LastButton : FirstButton;
const PreviousButtonSlot = isRtl ? NextButton : PreviousButton;
const NextButtonSlot = isRtl ? PreviousButton : NextButton;
const LastButtonSlot = isRtl ? FirstButton : LastButton;

const firstButtonSlotProps =
theme.direction === 'rtl' ? slotProps.lastButton : slotProps.firstButton;
const previousButtonSlotProps =
theme.direction === 'rtl' ? slotProps.nextButton : slotProps.previousButton;
const nextButtonSlotProps =
theme.direction === 'rtl' ? slotProps.previousButton : slotProps.nextButton;
const lastButtonSlotProps =
theme.direction === 'rtl' ? slotProps.firstButton : slotProps.lastButton;
const firstButtonSlotProps = isRtl ? slotProps.lastButton : slotProps.firstButton;
const previousButtonSlotProps = isRtl ? slotProps.nextButton : slotProps.previousButton;
const nextButtonSlotProps = isRtl ? slotProps.previousButton : slotProps.nextButton;
const lastButtonSlotProps = isRtl ? slotProps.firstButton : slotProps.lastButton;

return (
<div ref={ref} {...other}>
Expand All @@ -79,7 +75,7 @@ const TablePaginationActions = React.forwardRef(function TablePaginationActions(
title={getItemAriaLabel('first', page)}
{...firstButtonSlotProps}
>
{theme.direction === 'rtl' ? (
{isRtl ? (
<LastButtonIcon {...slotProps.lastButtonIcon} />
) : (
<FirstButtonIcon {...slotProps.firstButtonIcon} />
Expand All @@ -94,7 +90,7 @@ const TablePaginationActions = React.forwardRef(function TablePaginationActions(
title={getItemAriaLabel('previous', page)}
{...(previousButtonSlotProps ?? backIconButtonProps)}
>
{theme.direction === 'rtl' ? (
{isRtl ? (
<NextButtonIcon {...slotProps.nextButtonIcon} />
) : (
<PreviousButtonIcon {...slotProps.previousButtonIcon} />
Expand All @@ -108,7 +104,7 @@ const TablePaginationActions = React.forwardRef(function TablePaginationActions(
title={getItemAriaLabel('next', page)}
{...(nextButtonSlotProps ?? nextIconButtonProps)}
>
{theme.direction === 'rtl' ? (
{isRtl ? (
<PreviousButtonIcon {...slotProps.previousButtonIcon} />
) : (
<NextButtonIcon {...slotProps.nextButtonIcon} />
Expand All @@ -122,7 +118,7 @@ const TablePaginationActions = React.forwardRef(function TablePaginationActions(
title={getItemAriaLabel('last', page)}
{...lastButtonSlotProps}
>
{theme.direction === 'rtl' ? (
{isRtl ? (
<FirstButtonIcon {...slotProps.firstButtonIcon} />
) : (
<LastButtonIcon {...slotProps.lastButtonIcon} />
Expand Down
5 changes: 3 additions & 2 deletions packages/mui-material/src/Tabs/Tabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import clsx from 'clsx';
import refType from '@mui/utils/refType';
import { useSlotProps } from '@mui/base/utils';
import composeClasses from '@mui/utils/composeClasses';
import { useRtl } from '@mui/system/RtlProvider';
import styled from '../styles/styled';
import useThemeProps from '../styles/useThemeProps';
import useTheme from '../styles/useTheme';
Expand Down Expand Up @@ -231,7 +232,7 @@ let warnedOnceTabPresent = false;
const Tabs = React.forwardRef(function Tabs(inProps, ref) {
const props = useThemeProps({ props: inProps, name: 'MuiTabs' });
const theme = useTheme();
const isRtl = theme.direction === 'rtl';
const isRtl = useRtl();
const {
'aria-label': ariaLabel,
'aria-labelledby': ariaLabelledBy,
Expand Down Expand Up @@ -333,7 +334,7 @@ const Tabs = React.forwardRef(function Tabs(inProps, ref) {
clientWidth: tabsNode.clientWidth,
scrollLeft: tabsNode.scrollLeft,
scrollTop: tabsNode.scrollTop,
scrollLeftNormalized: getNormalizedScrollLeft(tabsNode, theme.direction),
scrollLeftNormalized: getNormalizedScrollLeft(tabsNode, isRtl ? 'rtl' : 'ltr'),
scrollWidth: tabsNode.scrollWidth,
top: rect.top,
bottom: rect.bottom,
Expand Down
3 changes: 2 additions & 1 deletion packages/mui-material/src/Tooltip/Tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import elementAcceptingRef from '@mui/utils/elementAcceptingRef';
import { appendOwnerState } from '@mui/base/utils';
import composeClasses from '@mui/utils/composeClasses';
import { alpha } from '@mui/system/colorManipulator';
import { useRtl } from '@mui/system/RtlProvider';
import styled from '../styles/styled';
import useTheme from '../styles/useTheme';
import useThemeProps from '../styles/useThemeProps';
Expand Down Expand Up @@ -270,7 +271,7 @@ const Tooltip = React.forwardRef(function Tooltip(inProps, ref) {
const children = React.isValidElement(childrenProp) ? childrenProp : <span>{childrenProp}</span>;

const theme = useTheme();
const isRtl = theme.direction === 'rtl';
const isRtl = useRtl();

const [childNode, setChildNode] = React.useState();
const [arrowRef, setArrowRef] = React.useState(null);
Expand Down
11 changes: 11 additions & 0 deletions packages/mui-system/src/RtlProvider/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as React from 'react';

interface RtlProviderProps {
children?: React.ReactNode;
value?: boolean;
}

declare const RtlProvider: React.FC<RtlProviderProps>;
export const useRtl: () => boolean;

export default RtlProvider;
Loading

0 comments on commit c284879

Please sign in to comment.