From 5950fcc5fb37172bfd286fa55bd28060ef5e7b12 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Wed, 1 Jun 2022 12:09:09 +0700 Subject: [PATCH 01/11] allow state prefix to be configurable --- .../generateUtilityClass.test.ts | 4 +++ .../generateUtilityClass.ts | 31 ++++++++++++------- .../generateUtilityClasses.ts | 3 +- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.test.ts b/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.test.ts index ec4a28cb0b510b..acf655563d8925 100644 --- a/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.test.ts +++ b/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.test.ts @@ -48,4 +48,8 @@ describe('generateUtilityClass', () => { expect(generateUtilityClass('MuiTest', 'selected')).to.equal('Mui-selected'); }); }); + + it('custom state prefix', () => { + expect(generateUtilityClass('JoyButton', 'focusVisible', 'Joy')).to.equal('Joy-focusVisible'); + }); }); diff --git a/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts b/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts index 711436453acfe3..ed6f509677753d 100644 --- a/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts +++ b/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts @@ -13,19 +13,26 @@ export type GlobalStateSlot = | 'selected'; const globalStateClassesMapping: Record = { - active: 'Mui-active', - checked: 'Mui-checked', - completed: 'Mui-completed', - disabled: 'Mui-disabled', - error: 'Mui-error', - expanded: 'Mui-expanded', - focused: 'Mui-focused', - focusVisible: 'Mui-focusVisible', - required: 'Mui-required', - selected: 'Mui-selected', + active: 'active', + checked: 'checked', + completed: 'completed', + disabled: 'disabled', + error: 'error', + expanded: 'expanded', + focused: 'focused', + focusVisible: 'focusVisible', + required: 'required', + selected: 'selected', }; -export default function generateUtilityClass(componentName: string, slot: string): string { +export default function generateUtilityClass( + componentName: string, + slot: string, + globalStatePrefix = 'Mui', +): string { const globalStateClass = globalStateClassesMapping[slot as GlobalStateSlot]; - return globalStateClass || `${ClassNameGenerator.generate(componentName)}-${slot}`; + return ( + `${globalStatePrefix}-${globalStateClass}` || + `${ClassNameGenerator.generate(componentName)}-${slot}` + ); } diff --git a/packages/mui-utils/src/generateUtilityClasses/generateUtilityClasses.ts b/packages/mui-utils/src/generateUtilityClasses/generateUtilityClasses.ts index 61973f3aa9a26c..235916d2ea8f1e 100644 --- a/packages/mui-utils/src/generateUtilityClasses/generateUtilityClasses.ts +++ b/packages/mui-utils/src/generateUtilityClasses/generateUtilityClasses.ts @@ -3,11 +3,12 @@ import generateUtilityClass from '../generateUtilityClass'; export default function generateUtilityClasses( componentName: string, slots: T[], + globalStatePrefix = 'Mui', ): Record { const result: Record = {}; slots.forEach((slot) => { - result[slot] = generateUtilityClass(componentName, slot); + result[slot] = generateUtilityClass(componentName, slot, globalStatePrefix); }); return result; From 3c398acee3e990ef4d621cbe4a62e1b58e02c8ad Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Wed, 1 Jun 2022 18:27:46 +0700 Subject: [PATCH 02/11] fix condition --- .../src/generateUtilityClass/generateUtilityClass.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts b/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts index ed6f509677753d..4d5def219b690c 100644 --- a/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts +++ b/packages/mui-utils/src/generateUtilityClass/generateUtilityClass.ts @@ -31,8 +31,7 @@ export default function generateUtilityClass( globalStatePrefix = 'Mui', ): string { const globalStateClass = globalStateClassesMapping[slot as GlobalStateSlot]; - return ( - `${globalStatePrefix}-${globalStateClass}` || - `${ClassNameGenerator.generate(componentName)}-${slot}` - ); + return globalStateClass + ? `${globalStatePrefix}-${globalStateClass}` + : `${ClassNameGenerator.generate(componentName)}-${slot}`; } From b85ef77f226574fb3f9eb625a463c2f58fe993af Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Fri, 3 Jun 2022 22:35:14 +0700 Subject: [PATCH 03/11] add Joy generate utility class --- packages/mui-joy/src/className/index.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/mui-joy/src/className/index.ts b/packages/mui-joy/src/className/index.ts index ac4bb27c3b0d48..913fdef9925639 100644 --- a/packages/mui-joy/src/className/index.ts +++ b/packages/mui-joy/src/className/index.ts @@ -1,3 +1,5 @@ +import { unstable_generateUtilityClass, unstable_generateUtilityClasses } from '@mui/utils'; + /** * Caution! this module must not include unstyled components import from `@mui/base`, otherwise, it will break the ClassNameGenerator. * ❌ import { ... } from '@mui/base'; @@ -8,3 +10,9 @@ // eslint-disable-next-line import/prefer-default-export export { unstable_ClassNameGenerator } from '@mui/base/className'; + +export const generateUtilityClass = (componentName: string, slot: string) => + unstable_generateUtilityClass(componentName, slot, 'Joy'); + +export const generateUtilityClasses = (componentName: string, slots: Array) => + unstable_generateUtilityClasses(componentName, slots, 'Joy'); From 643c93f6f8d852f9fc021a87415b19f2bbdd650b Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Fri, 3 Jun 2022 22:35:26 +0700 Subject: [PATCH 04/11] use for focusVisible selector --- packages/mui-joy/src/styles/extendTheme.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/mui-joy/src/styles/extendTheme.ts b/packages/mui-joy/src/styles/extendTheme.ts index 598a9990bf6107..4212fc8fd14379 100644 --- a/packages/mui-joy/src/styles/extendTheme.ts +++ b/packages/mui-joy/src/styles/extendTheme.ts @@ -16,6 +16,7 @@ import { TypographySystem, FontSize } from './types/typography'; import { Variants } from './types/variants'; import { Theme, ThemeCSSVar, ThemeScales } from './types'; import { Components } from './components'; +import { generateUtilityClass } from '../className'; type CSSProperties = CSS.Properties; @@ -303,7 +304,7 @@ export default function extendTheme(themeInput?: ThemeInput): Theme { xl: 800, }, focus: { - selector: '&.Mui-focusVisible, &:focus-visible', + selector: `&.${generateUtilityClass('', 'focusVisible')}, &:focus-visible`, default: { outlineOffset: 'var(--joy-focus-outlineOffset, 0px)', // reset user agent stylesheet outline: '4px solid var(--joy-palette-focusVisible)', From c87334f2e4b4862828132f7e3e9f266e85d28ed4 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Fri, 3 Jun 2022 22:46:21 +0700 Subject: [PATCH 05/11] fix all components --- packages/mui-joy/src/AspectRatio/aspectRatioClasses.ts | 2 +- packages/mui-joy/src/Avatar/avatarClasses.ts | 2 +- packages/mui-joy/src/AvatarGroup/avatarGroupClasses.ts | 2 +- packages/mui-joy/src/Badge/badgeClasses.ts | 2 +- packages/mui-joy/src/Button/buttonClasses.ts | 2 +- packages/mui-joy/src/Card/cardClasses.ts | 2 +- packages/mui-joy/src/CardContent/cardContentClasses.ts | 2 +- packages/mui-joy/src/CardCover/cardCoverClasses.ts | 2 +- packages/mui-joy/src/CardOverflow/cardOverflowClasses.ts | 2 +- packages/mui-joy/src/Checkbox/Checkbox.tsx | 4 ++-- packages/mui-joy/src/Checkbox/checkboxClasses.ts | 2 +- packages/mui-joy/src/Chip/chipClasses.ts | 2 +- packages/mui-joy/src/ChipDelete/chipDeleteClasses.ts | 2 +- packages/mui-joy/src/Container/containerClasses.ts | 2 +- packages/mui-joy/src/FormHelperText/formHelperTextClasses.ts | 2 +- packages/mui-joy/src/FormLabel/formLabelClasses.ts | 2 +- packages/mui-joy/src/IconButton/iconButtonClasses.ts | 2 +- packages/mui-joy/src/Input/inputClasses.ts | 2 +- packages/mui-joy/src/Link/linkClasses.ts | 2 +- packages/mui-joy/src/List/listClasses.ts | 2 +- packages/mui-joy/src/ListDivider/listDividerClasses.ts | 2 +- packages/mui-joy/src/ListItem/listItemClasses.ts | 2 +- packages/mui-joy/src/ListItemButton/listItemButtonClasses.ts | 2 +- .../mui-joy/src/ListItemContent/listItemContentClasses.ts | 2 +- .../mui-joy/src/ListItemDecorator/listItemDecoratorClasses.ts | 2 +- packages/mui-joy/src/Radio/Radio.tsx | 4 ++-- packages/mui-joy/src/Radio/radioClasses.ts | 2 +- packages/mui-joy/src/RadioGroup/radioGroupClasses.ts | 2 +- packages/mui-joy/src/Sheet/sheetClasses.ts | 2 +- packages/mui-joy/src/SvgIcon/svgIconClasses.ts | 2 +- packages/mui-joy/src/Switch/switchClasses.ts | 2 +- packages/mui-joy/src/TextField/textFieldClasses.ts | 2 +- packages/mui-joy/src/Typography/typographyClasses.ts | 2 +- 33 files changed, 35 insertions(+), 35 deletions(-) diff --git a/packages/mui-joy/src/AspectRatio/aspectRatioClasses.ts b/packages/mui-joy/src/AspectRatio/aspectRatioClasses.ts index 72118bcdac3cc5..e1b1034503222d 100644 --- a/packages/mui-joy/src/AspectRatio/aspectRatioClasses.ts +++ b/packages/mui-joy/src/AspectRatio/aspectRatioClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface AspectRatioClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Avatar/avatarClasses.ts b/packages/mui-joy/src/Avatar/avatarClasses.ts index d4ce28452fb641..4d42d4c9d2d8ea 100644 --- a/packages/mui-joy/src/Avatar/avatarClasses.ts +++ b/packages/mui-joy/src/Avatar/avatarClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface AvatarClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/AvatarGroup/avatarGroupClasses.ts b/packages/mui-joy/src/AvatarGroup/avatarGroupClasses.ts index bd724ea5924659..3ac0acdd62d454 100644 --- a/packages/mui-joy/src/AvatarGroup/avatarGroupClasses.ts +++ b/packages/mui-joy/src/AvatarGroup/avatarGroupClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface AvatarGroupClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Badge/badgeClasses.ts b/packages/mui-joy/src/Badge/badgeClasses.ts index 6dc62ce22a71ae..aba4663a19aba5 100644 --- a/packages/mui-joy/src/Badge/badgeClasses.ts +++ b/packages/mui-joy/src/Badge/badgeClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface BadgeClasses { /** Class name applied to the root element. */ diff --git a/packages/mui-joy/src/Button/buttonClasses.ts b/packages/mui-joy/src/Button/buttonClasses.ts index 5ef5369398782b..6f72ab08ef4961 100644 --- a/packages/mui-joy/src/Button/buttonClasses.ts +++ b/packages/mui-joy/src/Button/buttonClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ButtonClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Card/cardClasses.ts b/packages/mui-joy/src/Card/cardClasses.ts index 85daa83d8e466d..687062fdf18d50 100644 --- a/packages/mui-joy/src/Card/cardClasses.ts +++ b/packages/mui-joy/src/Card/cardClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface CardClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/CardContent/cardContentClasses.ts b/packages/mui-joy/src/CardContent/cardContentClasses.ts index 467c0cb3c648bd..0cda1a38dd9bd9 100644 --- a/packages/mui-joy/src/CardContent/cardContentClasses.ts +++ b/packages/mui-joy/src/CardContent/cardContentClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface CardContentClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/CardCover/cardCoverClasses.ts b/packages/mui-joy/src/CardCover/cardCoverClasses.ts index 391abcadc19e3c..382f467d22b39b 100644 --- a/packages/mui-joy/src/CardCover/cardCoverClasses.ts +++ b/packages/mui-joy/src/CardCover/cardCoverClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface CardCoverClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/CardOverflow/cardOverflowClasses.ts b/packages/mui-joy/src/CardOverflow/cardOverflowClasses.ts index 173a0cae896add..dd445e4e83e4d2 100644 --- a/packages/mui-joy/src/CardOverflow/cardOverflowClasses.ts +++ b/packages/mui-joy/src/CardOverflow/cardOverflowClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface CardOverflowClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Checkbox/Checkbox.tsx b/packages/mui-joy/src/Checkbox/Checkbox.tsx index f4a5c764ae9462..47a3fa04bb5294 100644 --- a/packages/mui-joy/src/Checkbox/Checkbox.tsx +++ b/packages/mui-joy/src/Checkbox/Checkbox.tsx @@ -64,12 +64,12 @@ const CheckboxRoot = styled('span', { display: 'inline-flex', fontFamily: theme.vars.fontFamily.body, lineHeight: 'var(--Checkbox-size)', // prevent label from having larger height than the checkbox - '&.Mui-disabled': { + [`&.${checkboxClasses.disabled}`]: { color: theme.vars.palette[ownerState.color!]?.plainDisabledColor, }, ...(ownerState.disableIcon && { color: theme.vars.palette[ownerState.color!]?.[`${ownerState.variant!}Color`], - '&.Mui-disabled': { + [`&.${checkboxClasses.disabled}`]: { color: theme.vars.palette[ownerState.color!]?.[`${ownerState.variant!}DisabledColor`], }, }), diff --git a/packages/mui-joy/src/Checkbox/checkboxClasses.ts b/packages/mui-joy/src/Checkbox/checkboxClasses.ts index 30a940f8bcf900..7e33cdfe4a1137 100644 --- a/packages/mui-joy/src/Checkbox/checkboxClasses.ts +++ b/packages/mui-joy/src/Checkbox/checkboxClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface CheckboxClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Chip/chipClasses.ts b/packages/mui-joy/src/Chip/chipClasses.ts index 4619b7ffa4c3de..ef79e47e44af79 100644 --- a/packages/mui-joy/src/Chip/chipClasses.ts +++ b/packages/mui-joy/src/Chip/chipClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ChipClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ChipDelete/chipDeleteClasses.ts b/packages/mui-joy/src/ChipDelete/chipDeleteClasses.ts index fce130dbc7652b..6b44ed513cc84e 100644 --- a/packages/mui-joy/src/ChipDelete/chipDeleteClasses.ts +++ b/packages/mui-joy/src/ChipDelete/chipDeleteClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ChipDeleteClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Container/containerClasses.ts b/packages/mui-joy/src/Container/containerClasses.ts index df3cff6f60208a..cc6ae505c27b0f 100644 --- a/packages/mui-joy/src/Container/containerClasses.ts +++ b/packages/mui-joy/src/Container/containerClasses.ts @@ -1,5 +1,5 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; import { ContainerClasses } from '@mui/system'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export type { ContainerClassKey } from '@mui/system'; export type { ContainerClasses }; diff --git a/packages/mui-joy/src/FormHelperText/formHelperTextClasses.ts b/packages/mui-joy/src/FormHelperText/formHelperTextClasses.ts index bd61b0ae42fd1c..c9a2e633615d08 100644 --- a/packages/mui-joy/src/FormHelperText/formHelperTextClasses.ts +++ b/packages/mui-joy/src/FormHelperText/formHelperTextClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface FormHelperTextClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/FormLabel/formLabelClasses.ts b/packages/mui-joy/src/FormLabel/formLabelClasses.ts index 1b5a13c5cfe680..b2624a7ef4c39a 100644 --- a/packages/mui-joy/src/FormLabel/formLabelClasses.ts +++ b/packages/mui-joy/src/FormLabel/formLabelClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface FormLabelClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/IconButton/iconButtonClasses.ts b/packages/mui-joy/src/IconButton/iconButtonClasses.ts index 72722ead0e3191..2d89f71fc67376 100644 --- a/packages/mui-joy/src/IconButton/iconButtonClasses.ts +++ b/packages/mui-joy/src/IconButton/iconButtonClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface IconButtonClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Input/inputClasses.ts b/packages/mui-joy/src/Input/inputClasses.ts index 1e378534359e7d..6f853d154ba8ee 100644 --- a/packages/mui-joy/src/Input/inputClasses.ts +++ b/packages/mui-joy/src/Input/inputClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface InputClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Link/linkClasses.ts b/packages/mui-joy/src/Link/linkClasses.ts index ec49fc9537c79a..0fa388bdc91d78 100644 --- a/packages/mui-joy/src/Link/linkClasses.ts +++ b/packages/mui-joy/src/Link/linkClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface LinkClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/List/listClasses.ts b/packages/mui-joy/src/List/listClasses.ts index bbcf666f3a341f..399e317311e005 100644 --- a/packages/mui-joy/src/List/listClasses.ts +++ b/packages/mui-joy/src/List/listClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ListDivider/listDividerClasses.ts b/packages/mui-joy/src/ListDivider/listDividerClasses.ts index cbec7d500527c6..7ed0ad0b202fd6 100644 --- a/packages/mui-joy/src/ListDivider/listDividerClasses.ts +++ b/packages/mui-joy/src/ListDivider/listDividerClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListDividerClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ListItem/listItemClasses.ts b/packages/mui-joy/src/ListItem/listItemClasses.ts index 9e338b56a97ba9..77abb6ac6892b7 100644 --- a/packages/mui-joy/src/ListItem/listItemClasses.ts +++ b/packages/mui-joy/src/ListItem/listItemClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListItemClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ListItemButton/listItemButtonClasses.ts b/packages/mui-joy/src/ListItemButton/listItemButtonClasses.ts index d870153e5e1860..639cf7a5b1ce5a 100644 --- a/packages/mui-joy/src/ListItemButton/listItemButtonClasses.ts +++ b/packages/mui-joy/src/ListItemButton/listItemButtonClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListItemButtonClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ListItemContent/listItemContentClasses.ts b/packages/mui-joy/src/ListItemContent/listItemContentClasses.ts index 8788b63ba39f78..02ce494988f50f 100644 --- a/packages/mui-joy/src/ListItemContent/listItemContentClasses.ts +++ b/packages/mui-joy/src/ListItemContent/listItemContentClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListItemContentClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/ListItemDecorator/listItemDecoratorClasses.ts b/packages/mui-joy/src/ListItemDecorator/listItemDecoratorClasses.ts index 41e15419519f66..3a06f107e9c91c 100644 --- a/packages/mui-joy/src/ListItemDecorator/listItemDecoratorClasses.ts +++ b/packages/mui-joy/src/ListItemDecorator/listItemDecoratorClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface ListItemDecoratorClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Radio/Radio.tsx b/packages/mui-joy/src/Radio/Radio.tsx index 5baeabb4872e9b..013f4d311c1f53 100644 --- a/packages/mui-joy/src/Radio/Radio.tsx +++ b/packages/mui-joy/src/Radio/Radio.tsx @@ -76,12 +76,12 @@ const RadioRoot = styled('span', { minWidth: 0, fontFamily: theme.vars.fontFamily.body, lineHeight: 'var(--Radio-size)', // prevent label from having larger height than the checkbox - '&.Mui-disabled': { + [`&.${radioClasses.disabled}`]: { color: theme.vars.palette[ownerState.color!]?.plainDisabledColor, }, ...(ownerState.disableIcon && { color: theme.vars.palette[ownerState.color!]?.[`${ownerState.variant!}Color`], - '&.Mui-disabled': { + [`&.${radioClasses.disabled}`]: { color: theme.vars.palette[ownerState.color!]?.[`${ownerState.variant!}DisabledColor`], }, }), diff --git a/packages/mui-joy/src/Radio/radioClasses.ts b/packages/mui-joy/src/Radio/radioClasses.ts index fe7ca089d90bae..6e26201525ea6a 100644 --- a/packages/mui-joy/src/Radio/radioClasses.ts +++ b/packages/mui-joy/src/Radio/radioClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface RadioClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/RadioGroup/radioGroupClasses.ts b/packages/mui-joy/src/RadioGroup/radioGroupClasses.ts index d490e4a587493c..55c9494c11f7be 100644 --- a/packages/mui-joy/src/RadioGroup/radioGroupClasses.ts +++ b/packages/mui-joy/src/RadioGroup/radioGroupClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface RadioGroupClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Sheet/sheetClasses.ts b/packages/mui-joy/src/Sheet/sheetClasses.ts index a4f7d8cb2839f6..8618b303dd4e29 100644 --- a/packages/mui-joy/src/Sheet/sheetClasses.ts +++ b/packages/mui-joy/src/Sheet/sheetClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface SheetClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/SvgIcon/svgIconClasses.ts b/packages/mui-joy/src/SvgIcon/svgIconClasses.ts index 903da31cc73940..69a3ac7895e944 100644 --- a/packages/mui-joy/src/SvgIcon/svgIconClasses.ts +++ b/packages/mui-joy/src/SvgIcon/svgIconClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface SvgIconClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Switch/switchClasses.ts b/packages/mui-joy/src/Switch/switchClasses.ts index ddf8a57f112596..3593ae58fa310c 100644 --- a/packages/mui-joy/src/Switch/switchClasses.ts +++ b/packages/mui-joy/src/Switch/switchClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface SwitchClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/TextField/textFieldClasses.ts b/packages/mui-joy/src/TextField/textFieldClasses.ts index 2d07bb289a5136..018c4fe5aaca91 100644 --- a/packages/mui-joy/src/TextField/textFieldClasses.ts +++ b/packages/mui-joy/src/TextField/textFieldClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface TextFieldClasses { /** Styles applied to the root element. */ diff --git a/packages/mui-joy/src/Typography/typographyClasses.ts b/packages/mui-joy/src/Typography/typographyClasses.ts index e007d51c4d8e8e..57edadf5315222 100644 --- a/packages/mui-joy/src/Typography/typographyClasses.ts +++ b/packages/mui-joy/src/Typography/typographyClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface TypographyClasses { /** Styles applied to the root element. */ From 29c749f6c7ab7c82ac9ef9c16654dd3d5a3fa54b Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Sat, 4 Jun 2022 07:41:33 +0700 Subject: [PATCH 06/11] fix lint and remove hard-coded class --- packages/mui-joy/src/Link/Link.tsx | 4 ++-- packages/mui-joy/src/className/index.ts | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/mui-joy/src/Link/Link.tsx b/packages/mui-joy/src/Link/Link.tsx index 79edd8c72ece7d..72c2b4a4d5c010 100644 --- a/packages/mui-joy/src/Link/Link.tsx +++ b/packages/mui-joy/src/Link/Link.tsx @@ -11,7 +11,7 @@ import { import { unstable_extendSxProp as extendSxProp } from '@mui/system'; import styled from '../styles/styled'; import useThemeProps from '../styles/useThemeProps'; -import { getLinkUtilityClass } from './linkClasses'; +import linkClasses, { getLinkUtilityClass } from './linkClasses'; import { LinkProps, LinkTypeMap } from './LinkProps'; import { TypographyContext } from '../Typography/Typography'; @@ -103,7 +103,7 @@ const LinkRoot = styled('a', { : { color: theme.vars.palette[ownerState.color!]?.plainColor, cursor: 'pointer', - '&.Mui-disabled': { + [`&.${linkClasses.disabled}`]: { pointerEvents: 'none', color: theme.vars.palette[ownerState.color!]?.plainDisabledColor, }, diff --git a/packages/mui-joy/src/className/index.ts b/packages/mui-joy/src/className/index.ts index 913fdef9925639..ae3933e409f997 100644 --- a/packages/mui-joy/src/className/index.ts +++ b/packages/mui-joy/src/className/index.ts @@ -8,7 +8,6 @@ import { unstable_generateUtilityClass, unstable_generateUtilityClasses } from ' * Issue: https://github.com/mui/material-ui/issues/30011#issuecomment-1024993401 */ -// eslint-disable-next-line import/prefer-default-export export { unstable_ClassNameGenerator } from '@mui/base/className'; export const generateUtilityClass = (componentName: string, slot: string) => From b85d40c8cc3d1e9fc4b1e1dcf5834aa9c2f2f577 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Sun, 5 Jun 2022 20:09:13 +0700 Subject: [PATCH 07/11] temp --- .../mui-base/src/SliderUnstyled/useSlider.ts | 4 +- packages/mui-joy/src/Slider/Slider2.tsx | 256 ++++++++++++++++++ 2 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 packages/mui-joy/src/Slider/Slider2.tsx diff --git a/packages/mui-base/src/SliderUnstyled/useSlider.ts b/packages/mui-base/src/SliderUnstyled/useSlider.ts index 0e57074be29cbd..05d69860eb2e19 100644 --- a/packages/mui-base/src/SliderUnstyled/useSlider.ts +++ b/packages/mui-base/src/SliderUnstyled/useSlider.ts @@ -681,14 +681,14 @@ export default function useSlider(parameters: UseSliderParameters) { return { active, - axis, + axis: axis as keyof typeof axisProps, axisProps, dragging, focusVisible, getHiddenInputProps, getRootProps, getThumbProps, - marks, + marks: marks as boolean | Mark[], open, range, trackLeap, diff --git a/packages/mui-joy/src/Slider/Slider2.tsx b/packages/mui-joy/src/Slider/Slider2.tsx new file mode 100644 index 00000000000000..61791437efc8f1 --- /dev/null +++ b/packages/mui-joy/src/Slider/Slider2.tsx @@ -0,0 +1,256 @@ +import * as React from 'react'; +import PropTypes from 'prop-types'; +import clsx from 'clsx'; +import { chainPropTypes } from '@mui/utils'; +import { OverridableComponent } from '@mui/types'; +import composeClasses from '@mui/base/composeClasses'; +import { useSlider, valueToPercent } from '@mui/base/SliderUnstyled'; +import { useThemeProps } from '../styles'; +import { getSliderUtilityClass } from './sliderClasses'; +import { SliderProps, SliderTypeMap } from './SliderProps'; + +type OwnerState = SliderProps & { + dragging: boolean; + marked: boolean; +}; + +const Identity = (x: any) => x; + +const useUtilityClasses = (ownerState: OwnerState) => { + const { disabled, dragging, marked, orientation, track, classes } = ownerState; + + const slots = { + root: [ + 'root', + disabled && 'disabled', + dragging && 'dragging', + marked && 'marked', + orientation === 'vertical' && 'vertical', + track === 'inverted' && 'trackInverted', + track === false && 'trackFalse', + ], + rail: ['rail'], + track: ['track'], + mark: ['mark'], + markActive: ['markActive'], + markLabel: ['markLabel'], + markLabelActive: ['markLabelActive'], + valueLabel: ['valueLabel'], + thumb: ['thumb', disabled && 'disabled'], + active: ['active'], + disabled: ['disabled'], + focusVisible: ['focusVisible'], + }; + + return composeClasses(slots, getSliderUtilityClass, classes); +}; + +const Slider = React.forwardRef(function Slider(inProps, ref) { + const props = useThemeProps({ props: inProps, name: 'JoySlider' }); + const { + 'aria-label': ariaLabel, + 'aria-valuetext': ariaValuetext, + className, + component, + componentsProps = {}, + classes: classesProp, + disableSwap = false, + disabled = false, + getAriaLabel, + getAriaValueText, + marks: marksProp = false, + max = 100, + min = 0, + name, + onChange, + onChangeCommitted, + onMouseDown, + orientation = 'horizontal', + scale = Identity, + step = 1, + tabIndex, + track = 'normal', + value: valueProp, + valueLabelDisplay = 'off', + valueLabelFormat = Identity, + isRtl = false, + ...other + } = props; + + const ownerState = { + ...props, + marks: marksProp, + classes: classesProp, + disabled, + isRtl, + max, + min, + orientation, + scale, + step, + track, + valueLabelDisplay, + valueLabelFormat, + } as OwnerState; + + const { + axisProps, + getRootProps, + getHiddenInputProps, + getThumbProps, + open, + active, + axis, + range, + focusVisible, + dragging, + marks, + values, + trackOffset, + trackLeap, + } = useSlider({ ...ownerState, ref }); + + ownerState.marked = + marks === true || + (Array.isArray(marks) && marks.length > 0 && marks.some((mark) => mark.label)); + ownerState.dragging = dragging; + + const trackStyle = { + ...axisProps[axis].offset(trackOffset), + ...axisProps[axis].leap(trackLeap), + }; + + const hiddenInputProps = getHiddenInputProps(); + + const classes = useUtilityClasses(ownerState); + + return ( + + + + {marks + .filter((mark) => mark.value >= min && mark.value <= max) + .map((mark, index) => { + const percent = valueToPercent(mark.value, min, max); + const style = axisProps[axis].offset(percent); + + let markActive; + if (track === false) { + markActive = values.indexOf(mark.value) !== -1; + } else { + markActive = + (track === 'normal' && + (range + ? mark.value >= values[0] && mark.value <= values[values.length - 1] + : mark.value <= values[0])) || + (track === 'inverted' && + (range + ? mark.value <= values[0] || mark.value >= values[values.length - 1] + : mark.value >= values[0])); + } + + return ( + + + {mark.label != null ? ( + + {mark.label} + + ) : null} + + ); + })} + {values.map((value, index) => { + const percent = valueToPercent(value, min, max); + const style = axisProps[axis].offset(percent); + + const ValueLabelComponent = valueLabelDisplay === 'off' ? Forward : ValueLabel; + + return ( + + + + + + + + ); + })} + + ); +}) as OverridableComponent; + +export default Slider; From 5c82d29e55c69418a8531e821d381bdfec75de38 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Sun, 5 Jun 2022 22:23:26 +0700 Subject: [PATCH 08/11] fix types --- packages/mui-base/src/SliderUnstyled/useSlider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mui-base/src/SliderUnstyled/useSlider.ts b/packages/mui-base/src/SliderUnstyled/useSlider.ts index 05d69860eb2e19..6622a043d93282 100644 --- a/packages/mui-base/src/SliderUnstyled/useSlider.ts +++ b/packages/mui-base/src/SliderUnstyled/useSlider.ts @@ -688,7 +688,7 @@ export default function useSlider(parameters: UseSliderParameters) { getHiddenInputProps, getRootProps, getThumbProps, - marks: marks as boolean | Mark[], + marks: marks as Mark[], open, range, trackLeap, From 7074e5093811002216680a535b29a926cb7447f9 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Sun, 5 Jun 2022 22:24:39 +0700 Subject: [PATCH 09/11] fix slider to use joy related classnames --- packages/mui-joy/src/Slider/Slider.tsx | 378 +++++++++++-------- packages/mui-joy/src/Slider/Slider2.tsx | 256 ------------- packages/mui-joy/src/Slider/SliderProps.ts | 23 +- packages/mui-joy/src/Slider/sliderClasses.ts | 12 +- 4 files changed, 243 insertions(+), 426 deletions(-) delete mode 100644 packages/mui-joy/src/Slider/Slider2.tsx diff --git a/packages/mui-joy/src/Slider/Slider.tsx b/packages/mui-joy/src/Slider/Slider.tsx index 0c8a74c0afacb8..5131b822412ec7 100644 --- a/packages/mui-joy/src/Slider/Slider.tsx +++ b/packages/mui-joy/src/Slider/Slider.tsx @@ -1,41 +1,50 @@ -import PropTypes from 'prop-types'; import * as React from 'react'; +import clsx from 'clsx'; +import { unstable_composeClasses as composeClasses } from '@mui/utils'; import { OverridableComponent } from '@mui/types'; -import { unstable_capitalize as capitalize } from '@mui/utils'; import { shouldForwardProp } from '@mui/system'; -import { - SliderUnstyled, - SliderValueLabelUnstyled, - unstable_composeClasses as composeClasses, -} from '@mui/base'; -import { Theme, useThemeProps } from '../styles'; -import styled from '../styles/styled'; -import shouldSpreadAdditionalProps from '../utils/shouldSpreadAdditionalProps'; +import { useSlider } from '@mui/base/SliderUnstyled'; +import { useThemeProps, styled, Theme } from '../styles'; import sliderClasses, { getSliderUtilityClass } from './sliderClasses'; import { SliderProps, SliderTypeMap } from './SliderProps'; -const useUtilityClasses = (ownerState: SliderProps) => { - const { disabled, orientation, track, size, color } = ownerState; +type OwnerState = SliderProps & { + dragging: boolean; + marked: boolean; +}; + +const valueToPercent = (value: number, min: number, max: number) => + ((value - min) * 100) / (max - min); + +const Identity = (x: any) => x; + +const useUtilityClasses = (ownerState: OwnerState) => { + const { disabled, dragging, marked, orientation, track, classes } = ownerState; const slots = { root: [ 'root', disabled && 'disabled', + dragging && 'dragging', + marked && 'marked', orientation === 'vertical' && 'vertical', track === 'inverted' && 'trackInverted', track === false && 'trackFalse', - color && `color${capitalize(color)}`, - size && `size${capitalize(size)}`, ], rail: ['rail'], track: ['track'], mark: ['mark'], + markActive: ['markActive'], markLabel: ['markLabel'], + markLabelActive: ['markLabelActive'], valueLabel: ['valueLabel'], + valueLabelOpen: ['valueLabelOpen'], thumb: ['thumb', disabled && 'disabled'], + active: ['active'], + focusVisible: ['focusVisible'], }; - return composeClasses(slots, getSliderUtilityClass, {}); + return composeClasses(slots, getSliderUtilityClass, classes); }; const sliderColorVariables = @@ -231,7 +240,7 @@ const SliderMark = styled('span', { // `markActive` is injected by SliderUnstyled, should not spread to DOM shouldForwardProp: (prop) => shouldForwardProp(prop) && prop !== 'markActive', overridesResolver: (props, styles) => styles.mark, -})<{ ownerState: SliderProps; 'data-index': number; style: React.CSSProperties }>( +})<{ ownerState: SliderProps & { markActive: boolean }; 'data-index': number }>( ({ ownerState, ...props }) => { return { position: 'absolute', @@ -256,18 +265,18 @@ const SliderMark = styled('span', { transform: 'translate(-50%, calc(var(--Slider-mark-size) / 2))', ...(props['data-index'] === 0 && { // data-index is from SliderUnstyled - transform: `translate(-50%, min(var(--Slider-mark-size), 3px))`, + transform: `translate(-50%, calc(min(var(--Slider-mark-size), 3px) * -1))`, }), - ...(props.style?.left === '100%' && { + ...(props.style?.bottom === '100%' && { // workaround for detecting last mark - transform: `translate(-50%, calc(var(--Slider-mark-size) * -1 - min(var(--Slider-mark-size), 3px)))`, + transform: `translate(-50%, calc(var(--Slider-mark-size) * 1 + min(var(--Slider-mark-size), 3px)))`, }), }), }; }, ); -const SliderValueLabel = styled(SliderValueLabelUnstyled, { +const SliderValueLabel = styled('span', { name: 'JoySlider', slot: 'ValueLabel', overridesResolver: (props, styles) => styles.valueLabel, @@ -321,8 +330,9 @@ const SliderValueLabel = styled(SliderValueLabelUnstyled, { transform: 'translateY(calc((var(--Slider-thumb-size) + var(--Slider-valueLabel-arrowSize)) * -1)) scale(1)', }, - [`& .${sliderClasses.valueLabelCircle}`]: { - display: 'inline-flex', + '& > span': { + display: 'flex', + alignItems: 'center', zIndex: 1, }, })); @@ -348,21 +358,54 @@ const SliderMarkLabel = styled('span', { position: 'absolute', whiteSpace: 'nowrap', ...(ownerState.orientation === 'horizontal' && { - top: 'calc(50% + (max(var(--Slider-track-size), var(--Slider-thumb-size)) / 2))', + top: 'calc(50% + 4px + (max(var(--Slider-track-size), var(--Slider-thumb-size)) / 2))', transform: 'translateX(-50%)', }), ...(ownerState.orientation === 'vertical' && { - left: 36, + left: 'calc(50% + 8px + (max(var(--Slider-track-size), var(--Slider-thumb-size)) / 2))', transform: 'translateY(50%)', }), })); +const SliderInput = styled('input', { + name: 'JoySlider', + slot: 'Input', + overridesResolver: (props, styles) => styles.input, +})<{ ownerState: SliderProps }>({}); + const Slider = React.forwardRef(function Slider(inProps, ref) { - const props = useThemeProps({ props: inProps, name: 'JoySlider' }); + const props = useThemeProps({ + props: inProps, + name: 'JoySlider', + }); const { - component = 'span', - components = {}, + 'aria-label': ariaLabel, + 'aria-valuetext': ariaValuetext, + className, + component, componentsProps = {}, + classes: classesProp, + disableSwap = false, + disabled = false, + defaultValue, + getAriaLabel, + getAriaValueText, + marks: marksProp = false, + max = 100, + min = 0, + name, + onChange, + onChangeCommitted, + onMouseDown, + orientation = 'horizontal', + scale = Identity, + step = 1, + tabIndex, + track = 'normal', + value: valueProp, + valueLabelDisplay = 'off', + valueLabelFormat = Identity, + isRtl = false, color = 'primary', size = 'md', ...other @@ -370,135 +413,174 @@ const Slider = React.forwardRef(function Slider(inProps, ref) { const ownerState = { ...props, - size, + marks: marksProp, + classes: classesProp, + disabled, + defaultValue, + isRtl, + max, + min, + orientation, + scale, + step, + track, + valueLabelDisplay, + valueLabelFormat, color, + size, + } as OwnerState; + + const { + axisProps, + getRootProps, + getHiddenInputProps, + getThumbProps, + open, + active, + axis, + range, + focusVisible, + dragging, + marks, + values, + trackOffset, + trackLeap, + } = useSlider({ ...ownerState, ref }); + + ownerState.marked = marks.length > 0 && marks.some((mark) => mark.label); + ownerState.dragging = dragging; + + const trackStyle = { + ...axisProps[axis].offset(trackOffset), + ...axisProps[axis].leap(trackLeap), }; + const hiddenInputProps = getHiddenInputProps(); + const classes = useUtilityClasses(ownerState); return ( - + {...getRootProps(onMouseDown ? { onMouseDown } : {})} + as={component} + ownerState={ownerState} + className={clsx(classes.root, className)} + > + + + {marks + .filter((mark) => mark.value >= min && mark.value <= max) + .map((mark, index) => { + const percent = valueToPercent(mark.value, min, max); + const style = axisProps[axis].offset(percent); + + let markActive; + if (track === false) { + markActive = values.indexOf(mark.value) !== -1; + } else { + markActive = + (track === 'normal' && + (range + ? mark.value >= values[0] && mark.value <= values[values.length - 1] + : mark.value <= values[0])) || + (track === 'inverted' && + (range + ? mark.value <= values[0] || mark.value >= values[values.length - 1] + : mark.value >= values[0])); + } + + return ( + + + {mark.label != null ? ( + + {mark.label} + + ) : null} + + ); + })} + {values.map((value, index) => { + const percent = valueToPercent(value, min, max); + const style = axisProps[axis].offset(percent); + return ( + + {/* @ts-expect-error TODO: revisit the null type in useSlider */} + + {valueLabelDisplay !== 'off' ? ( + + {value} + + ) : null} + + ); + })} + ); }) as OverridableComponent; -Slider.propTypes /* remove-proptypes */ = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit TypeScript types and run "yarn proptypes" | - // ---------------------------------------------------------------------- - /** - * @ignore - */ - children: PropTypes.node, - /** - * The color of the component. It supports those theme colors that make sense for this component. - * @default 'primary' - */ - color: PropTypes.oneOf(['danger', 'info', 'neutral', 'primary', 'success', 'warning']), - /** - * The component used for the root node. - * Either a string to use a HTML element or a component. - */ - component: PropTypes.elementType, - /** - * The components used for each slot inside the Slider. - * Either a string to use a HTML element or a component. - * @default {} - */ - components: PropTypes.shape({ - Input: PropTypes.elementType, - Mark: PropTypes.elementType, - MarkLabel: PropTypes.elementType, - Rail: PropTypes.elementType, - Root: PropTypes.elementType, - Thumb: PropTypes.elementType, - Track: PropTypes.elementType, - ValueLabel: PropTypes.elementType, - }), - /** - * The props used for each slot inside the Slider. - * @default {} - */ - componentsProps: PropTypes.shape({ - input: PropTypes.object, - mark: PropTypes.object, - markLabel: PropTypes.object, - rail: PropTypes.object, - root: PropTypes.object, - thumb: PropTypes.object, - track: PropTypes.object, - valueLabel: PropTypes.shape({ - className: PropTypes.string, - components: PropTypes.shape({ - Root: PropTypes.elementType, - }), - style: PropTypes.object, - value: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), - valueLabelDisplay: PropTypes.oneOf(['auto', 'off', 'on']), - }), - }), - /** - * The size of the component. - * It accepts theme values between 'sm' and 'lg'. - * @default 'md' - */ - size: PropTypes.oneOf(['sm', 'md', 'lg']), - /** - * The system prop that allows defining system overrides as well as additional CSS styles. - */ - sx: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), - PropTypes.func, - PropTypes.object, - ]), -} as any; - export default Slider; diff --git a/packages/mui-joy/src/Slider/Slider2.tsx b/packages/mui-joy/src/Slider/Slider2.tsx deleted file mode 100644 index 61791437efc8f1..00000000000000 --- a/packages/mui-joy/src/Slider/Slider2.tsx +++ /dev/null @@ -1,256 +0,0 @@ -import * as React from 'react'; -import PropTypes from 'prop-types'; -import clsx from 'clsx'; -import { chainPropTypes } from '@mui/utils'; -import { OverridableComponent } from '@mui/types'; -import composeClasses from '@mui/base/composeClasses'; -import { useSlider, valueToPercent } from '@mui/base/SliderUnstyled'; -import { useThemeProps } from '../styles'; -import { getSliderUtilityClass } from './sliderClasses'; -import { SliderProps, SliderTypeMap } from './SliderProps'; - -type OwnerState = SliderProps & { - dragging: boolean; - marked: boolean; -}; - -const Identity = (x: any) => x; - -const useUtilityClasses = (ownerState: OwnerState) => { - const { disabled, dragging, marked, orientation, track, classes } = ownerState; - - const slots = { - root: [ - 'root', - disabled && 'disabled', - dragging && 'dragging', - marked && 'marked', - orientation === 'vertical' && 'vertical', - track === 'inverted' && 'trackInverted', - track === false && 'trackFalse', - ], - rail: ['rail'], - track: ['track'], - mark: ['mark'], - markActive: ['markActive'], - markLabel: ['markLabel'], - markLabelActive: ['markLabelActive'], - valueLabel: ['valueLabel'], - thumb: ['thumb', disabled && 'disabled'], - active: ['active'], - disabled: ['disabled'], - focusVisible: ['focusVisible'], - }; - - return composeClasses(slots, getSliderUtilityClass, classes); -}; - -const Slider = React.forwardRef(function Slider(inProps, ref) { - const props = useThemeProps({ props: inProps, name: 'JoySlider' }); - const { - 'aria-label': ariaLabel, - 'aria-valuetext': ariaValuetext, - className, - component, - componentsProps = {}, - classes: classesProp, - disableSwap = false, - disabled = false, - getAriaLabel, - getAriaValueText, - marks: marksProp = false, - max = 100, - min = 0, - name, - onChange, - onChangeCommitted, - onMouseDown, - orientation = 'horizontal', - scale = Identity, - step = 1, - tabIndex, - track = 'normal', - value: valueProp, - valueLabelDisplay = 'off', - valueLabelFormat = Identity, - isRtl = false, - ...other - } = props; - - const ownerState = { - ...props, - marks: marksProp, - classes: classesProp, - disabled, - isRtl, - max, - min, - orientation, - scale, - step, - track, - valueLabelDisplay, - valueLabelFormat, - } as OwnerState; - - const { - axisProps, - getRootProps, - getHiddenInputProps, - getThumbProps, - open, - active, - axis, - range, - focusVisible, - dragging, - marks, - values, - trackOffset, - trackLeap, - } = useSlider({ ...ownerState, ref }); - - ownerState.marked = - marks === true || - (Array.isArray(marks) && marks.length > 0 && marks.some((mark) => mark.label)); - ownerState.dragging = dragging; - - const trackStyle = { - ...axisProps[axis].offset(trackOffset), - ...axisProps[axis].leap(trackLeap), - }; - - const hiddenInputProps = getHiddenInputProps(); - - const classes = useUtilityClasses(ownerState); - - return ( - - - - {marks - .filter((mark) => mark.value >= min && mark.value <= max) - .map((mark, index) => { - const percent = valueToPercent(mark.value, min, max); - const style = axisProps[axis].offset(percent); - - let markActive; - if (track === false) { - markActive = values.indexOf(mark.value) !== -1; - } else { - markActive = - (track === 'normal' && - (range - ? mark.value >= values[0] && mark.value <= values[values.length - 1] - : mark.value <= values[0])) || - (track === 'inverted' && - (range - ? mark.value <= values[0] || mark.value >= values[values.length - 1] - : mark.value >= values[0])); - } - - return ( - - - {mark.label != null ? ( - - {mark.label} - - ) : null} - - ); - })} - {values.map((value, index) => { - const percent = valueToPercent(value, min, max); - const style = axisProps[axis].offset(percent); - - const ValueLabelComponent = valueLabelDisplay === 'off' ? Forward : ValueLabel; - - return ( - - - - - - - - ); - })} - - ); -}) as OverridableComponent; - -export default Slider; diff --git a/packages/mui-joy/src/Slider/SliderProps.ts b/packages/mui-joy/src/Slider/SliderProps.ts index 8c40676b12b84b..105f297a06df03 100644 --- a/packages/mui-joy/src/Slider/SliderProps.ts +++ b/packages/mui-joy/src/Slider/SliderProps.ts @@ -3,9 +3,18 @@ import { OverridableStringUnion, OverrideProps } from '@mui/types'; import * as React from 'react'; import { ColorPaletteProp, SxProps } from '../styles/types'; -export type SliderSlot = 'root' | 'mark' | 'markLabel' | 'rail' | 'track' | 'thumb' | 'valueLabel'; +export type SliderSlot = + | 'root' + | 'mark' + | 'markLabel' + | 'rail' + | 'track' + | 'thumb' + | 'valueLabel' + | 'input'; export interface SliderPropsColorOverrides {} + export interface SliderPropsSizeOverrides {} export type SliderTypeMap< @@ -32,18 +41,6 @@ export type SliderTypeMap< defaultComponent: D; }>; -export type SliderRootProps = NonNullable['root']; -export type SliderMarkProps = NonNullable['mark']; -export type SliderMarkLabelProps = NonNullable< - SliderTypeMap['props']['componentsProps'] ->['markLabel']; -export type SliderRailProps = NonNullable['rail']; -export type SliderTrackProps = NonNullable['track']; -export type SliderThumbProps = NonNullable['thumb']; -export type SliderValueLabelProps = NonNullable< - SliderTypeMap['props']['componentsProps'] ->['valueLabel']; - export type SliderProps< D extends React.ElementType = SliderTypeMap['defaultComponent'], P = { component?: React.ElementType }, diff --git a/packages/mui-joy/src/Slider/sliderClasses.ts b/packages/mui-joy/src/Slider/sliderClasses.ts index cf16691afb96e7..59faaa155be846 100644 --- a/packages/mui-joy/src/Slider/sliderClasses.ts +++ b/packages/mui-joy/src/Slider/sliderClasses.ts @@ -1,4 +1,4 @@ -import { generateUtilityClass, generateUtilityClasses } from '@mui/base'; +import { generateUtilityClass, generateUtilityClasses } from '../className'; export interface SliderClasses { /** Class name applied to the root element. */ @@ -25,10 +25,6 @@ export interface SliderClasses { valueLabel: string; /** Class name applied to the thumb label element if it's open. */ valueLabelOpen: string; - /** Class name applied to the thumb label's circle element. */ - valueLabelCircle: string; - /** Class name applied to the thumb label's label element. */ - valueLabelLabel: string; /** Class name applied to the mark element. */ mark: string; /** Class name applied to the mark element when it is active. */ @@ -58,10 +54,10 @@ export interface SliderClasses { export type SliderClassKey = keyof SliderClasses; export function getSliderUtilityClass(slot: string): string { - return generateUtilityClass('MuiSlider', slot); + return generateUtilityClass('JoySlider', slot); } -const sliderClasses: SliderClasses = generateUtilityClasses('MuiSlider', [ +const sliderClasses: SliderClasses = generateUtilityClasses('JoySlider', [ 'root', 'disabled', 'dragging', @@ -77,8 +73,6 @@ const sliderClasses: SliderClasses = generateUtilityClasses('MuiSlider', [ 'thumb', 'valueLabel', 'valueLabelOpen', - 'valueLabelCircle', - 'valueLabelLabel', 'colorPrimary', 'colorNeutral', 'colorDanger', From b4e2c852de458dadc69e8046f8fb9f1676f3b64c Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Sun, 5 Jun 2022 22:59:48 +0700 Subject: [PATCH 10/11] run proptypes --- packages/mui-joy/src/Slider/Slider.tsx | 223 +++++++++++++++++++++++++ 1 file changed, 223 insertions(+) diff --git a/packages/mui-joy/src/Slider/Slider.tsx b/packages/mui-joy/src/Slider/Slider.tsx index 5131b822412ec7..252815aa6a2654 100644 --- a/packages/mui-joy/src/Slider/Slider.tsx +++ b/packages/mui-joy/src/Slider/Slider.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import PropTypes from 'prop-types'; import clsx from 'clsx'; import { unstable_composeClasses as composeClasses } from '@mui/utils'; import { OverridableComponent } from '@mui/types'; @@ -378,6 +379,7 @@ const Slider = React.forwardRef(function Slider(inProps, ref) { props: inProps, name: 'JoySlider', }); + const { 'aria-label': ariaLabel, 'aria-valuetext': ariaValuetext, @@ -583,4 +585,225 @@ const Slider = React.forwardRef(function Slider(inProps, ref) { ); }) as OverridableComponent; +Slider.propTypes /* remove-proptypes */ = { + // ----------------------------- Warning -------------------------------- + // | These PropTypes are generated from the TypeScript type definitions | + // | To update them edit TypeScript types and run "yarn proptypes" | + // ---------------------------------------------------------------------- + /** + * The label of the slider. + */ + 'aria-label': PropTypes.string, + /** + * A string value that provides a user-friendly name for the current value of the slider. + */ + 'aria-valuetext': PropTypes.string, + /** + * @ignore + */ + children: PropTypes.node, + /** + * Override or extend the styles applied to the component. + */ + classes: PropTypes.object, + /** + * @ignore + */ + className: PropTypes.string, + /** + * The color of the component. It supports those theme colors that make sense for this component. + * @default 'primary' + */ + color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf(['danger', 'info', 'neutral', 'primary', 'success', 'warning']), + PropTypes.string, + ]), + /** + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, + /** + * The props used for each slot inside the Slider. + * @default {} + */ + componentsProps: PropTypes.shape({ + input: PropTypes.object, + mark: PropTypes.object, + markLabel: PropTypes.object, + rail: PropTypes.object, + root: PropTypes.object, + thumb: PropTypes.object, + track: PropTypes.object, + valueLabel: PropTypes.shape({ + className: PropTypes.string, + components: PropTypes.shape({ + Root: PropTypes.elementType, + }), + style: PropTypes.object, + value: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), + valueLabelDisplay: PropTypes.oneOf(['auto', 'off', 'on']), + }), + }), + /** + * The default value. Use when the component is not controlled. + */ + defaultValue: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), + /** + * If `true`, the component is disabled. + * @default false + */ + disabled: PropTypes.bool, + /** + * If `true`, the active thumb doesn't swap when moving pointer over a thumb while dragging another thumb. + * @default false + */ + disableSwap: PropTypes.bool, + /** + * Accepts a function which returns a string value that provides a user-friendly name for the thumb labels of the slider. + * This is important for screen reader users. + * @param {number} index The thumb label's index to format. + * @returns {string} + */ + getAriaLabel: PropTypes.func, + /** + * Accepts a function which returns a string value that provides a user-friendly name for the current value of the slider. + * This is important for screen reader users. + * @param {number} value The thumb label's value to format. + * @param {number} index The thumb label's index to format. + * @returns {string} + */ + getAriaValueText: PropTypes.func, + /** + * Indicates whether the theme context has rtl direction. It is set automatically. + * @default false + */ + isRtl: PropTypes.bool, + /** + * Marks indicate predetermined values to which the user can move the slider. + * If `true` the marks are spaced according the value of the `step` prop. + * If an array, it should contain objects with `value` and an optional `label` keys. + * @default false + */ + marks: PropTypes.oneOfType([ + PropTypes.arrayOf( + PropTypes.shape({ + label: PropTypes.node, + value: PropTypes.number.isRequired, + }), + ), + PropTypes.bool, + ]), + /** + * The maximum allowed value of the slider. + * Should not be equal to min. + * @default 100 + */ + max: PropTypes.number, + /** + * The minimum allowed value of the slider. + * Should not be equal to max. + * @default 0 + */ + min: PropTypes.number, + /** + * Name attribute of the hidden `input` element. + */ + name: PropTypes.string, + /** + * Callback function that is fired when the slider's value changed. + * + * @param {Event} event The event source of the callback. + * You can pull out the new value by accessing `event.target.value` (any). + * **Warning**: This is a generic event not a change event. + * @param {number | number[]} value The new value. + * @param {number} activeThumb Index of the currently moved thumb. + */ + onChange: PropTypes.func, + /** + * Callback function that is fired when the `mouseup` is triggered. + * + * @param {React.SyntheticEvent | Event} event The event source of the callback. **Warning**: This is a generic event not a change event. + * @param {number | number[]} value The new value. + */ + onChangeCommitted: PropTypes.func, + /** + * @ignore + */ + onMouseDown: PropTypes.func, + /** + * The component orientation. + * @default 'horizontal' + */ + orientation: PropTypes.oneOf(['horizontal', 'vertical']), + /** + * A transformation function, to change the scale of the slider. + * @default (x) => x + */ + scale: PropTypes.func, + /** + * The size of the component. + * It accepts theme values between 'sm' and 'lg'. + * @default 'md' + */ + size: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([ + PropTypes.oneOf(['sm', 'md', 'lg']), + PropTypes.string, + ]), + /** + * The granularity with which the slider can step through values. (A "discrete" slider.) + * The `min` prop serves as the origin for the valid values. + * We recommend (max - min) to be evenly divisible by the step. + * + * When step is `null`, the thumb can only be slid onto marks provided with the `marks` prop. + * @default 1 + */ + step: PropTypes.number, + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + /** + * Tab index attribute of the hidden `input` element. + */ + tabIndex: PropTypes.number, + /** + * The track presentation: + * + * - `normal` the track will render a bar representing the slider value. + * - `inverted` the track will render a bar representing the remaining slider value. + * - `false` the track will render without a bar. + * @default 'normal' + */ + track: PropTypes.oneOf(['inverted', 'normal', false]), + /** + * The value of the slider. + * For ranged sliders, provide an array with two values. + */ + value: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.number]), + /** + * Controls when the value label is displayed: + * + * - `auto` the value label will display when the thumb is hovered or focused. + * - `on` will display persistently. + * - `off` will never display. + * @default 'off' + */ + valueLabelDisplay: PropTypes.oneOf(['auto', 'off', 'on']), + /** + * The format function the value label's value. + * + * When a function is provided, it should have the following signature: + * + * - {number} value The value label's value to format + * - {number} index The value label's index to format + * @default (x) => x + */ + valueLabelFormat: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), +} as any; + export default Slider; From 9404b2d4c52819789cd082751d2bc073393aa483 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Wed, 15 Jun 2022 12:57:16 +0700 Subject: [PATCH 11/11] remove base related --- packages/mui-joy/src/className/index.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/packages/mui-joy/src/className/index.ts b/packages/mui-joy/src/className/index.ts index ae3933e409f997..1d47a7d752fa78 100644 --- a/packages/mui-joy/src/className/index.ts +++ b/packages/mui-joy/src/className/index.ts @@ -1,14 +1,6 @@ import { unstable_generateUtilityClass, unstable_generateUtilityClasses } from '@mui/utils'; -/** - * Caution! this module must not include unstyled components import from `@mui/base`, otherwise, it will break the ClassNameGenerator. - * ❌ import { ... } from '@mui/base'; - * ✅ import { ... } from '@mui/base/utils'; // must be specific base module - * - * Issue: https://github.com/mui/material-ui/issues/30011#issuecomment-1024993401 - */ - -export { unstable_ClassNameGenerator } from '@mui/base/className'; +export { unstable_ClassNameGenerator } from '@mui/utils'; export const generateUtilityClass = (componentName: string, slot: string) => unstable_generateUtilityClass(componentName, slot, 'Joy');