-
-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Slider] restrict slider type #1241
base: master
Are you sure you want to change the base?
Conversation
|
||
/** | ||
* Groups all parts of the slider. | ||
* Renders a `<div>` element. | ||
* | ||
* Documentation: [Base UI Slider](https://base-ui.com/react/components/slider) | ||
*/ | ||
const SliderRoot = React.forwardRef(function SliderRoot( | ||
props: SliderRoot.Props, | ||
const SliderRoot = fixedForwardRef(function SliderRoot<TValue extends number | number[]>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReactForwardRef does not work well with generics.
So we need to create a wrapper function to apply the generic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seloner I think we can remove generic SliderRoot component by removing generic in Props interfacce.
Check https://github.com/mui/base-ui/pull/1241/files#r1899037802, please
@@ -157,28 +158,25 @@ export namespace SliderRoot { | |||
values: ReadonlyArray<number>; | |||
} | |||
|
|||
export interface Props | |||
export interface Props<TValue extends number | number[]> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My first approach here was to try to carry this generic all the way down in the slider components but it resulted to just pollute the code with generics.
Instead I simple just try to modify the top level component that the consumer will use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seloner
I believe we can define Props without using generics. By utilizing intersection types, we can potentially make the necessary changes internally without affecting the external API. This approach could simplify the type definitions and improve readability.
Here’s an example of how we can implement this:
@@ -158,7 +158,10 @@ export namespace SliderRoot {
values: ReadonlyArray<number>;
}
- export interface Props<TValue extends number | number[]>
+ export type Props = PropsTemplate<number> &
+ PropsTemplate<number[]> &
+ PropsTemplate<number | number[]>;
+ export interface PropsTemplate<TValue extends number | number[]>
extends Pick<
useSliderRoot.Parameters,
| 'disabled'
Please refer to mui/material-ui#44777 (comment)
Netlify deploy preview |
} | ||
} | ||
|
||
export { SliderRoot }; | ||
|
||
// @ts-expect-error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know how to handle this I am getting ts error for proptypes.
Tried the proptypes
script but no luck.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you remove fixedForwardRef and replace it with React.forwardRef
, then // @ts-expect-error
can be removed.
@@ -18,8 +18,8 @@ import { fixedForwardRef } from '../utils';
*
* Documentation: [Base UI Slider](https://base-ui.com/react/components/slider)
*/
-const SliderRoot = fixedForwardRef(function SliderRoot<TValue extends number | number[]>(
- props: SliderRoot.Props<TValue>,
+const SliderRoot = React.forwardRef(function SliderRoot(
+ props: SliderRoot.Props,
forwardedRef: React.ForwardedRef<HTMLDivElement>,
) {
const {
7f7d189
to
186397e
Compare
Nice work! @seloner This issue originated from mui/material-ui#44777. Therefore, referring to mui/material-ui#44777 might be helpful. IMHO, it would be better to run |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’d like to suggest the following tasks to address this issue:
- Convert
SliderRoot.Props
to an Intersection Type: Change the Props definition to use an intersection type, eliminating the need for generics.
@@ -158,7 +158,10 @@ export namespace SliderRoot {
values: ReadonlyArray<number>;
}
- export interface Props<TValue extends number | number[]>
+ export type Props = PropsTemplate<number> &
+ PropsTemplate<number[]> &
+ PropsTemplate<number | number[]>;
+ export interface PropsTemplate<TValue extends number | number[]>
extends Pick<
useSliderRoot.Parameters,
| 'disabled'
- Remove Generic Type from SliderRoot: Simplify SliderRoot by removing the generic type.
- Replace
fixedForwardRef
withReact.forwardRef
: Update the code to useReact.forwardRef
directly, which will allow us to remove the// @ts-expect-error
.
@@ -18,8 +18,8 @@ import { fixedForwardRef } from '../utils';
*
* Documentation: [Base UI Slider](https://base-ui.com/react/components/slider)
*/
-const SliderRoot = fixedForwardRef(function SliderRoot<TValue extends number | number[]>(
- props: SliderRoot.Props<TValue>,
+const SliderRoot = React.forwardRef(function SliderRoot(
+ props: SliderRoot.Props,
forwardedRef: React.ForwardedRef<HTMLDivElement>,
) {
const {
- Remove
// @ts-expect-error
: With the changes above, the TypeScript error should be resolved, making the// @ts-expect-error
unnecessary.
These changes should help resolve the type-related issues. Let me know your thoughts!
/** | ||
* The component orientation. | ||
* @default 'horizontal' | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seloner
It seems like this should be removed.
@@ -157,28 +158,25 @@ export namespace SliderRoot { | |||
values: ReadonlyArray<number>; | |||
} | |||
|
|||
export interface Props | |||
export interface Props<TValue extends number | number[]> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seloner
I believe we can define Props without using generics. By utilizing intersection types, we can potentially make the necessary changes internally without affecting the external API. This approach could simplify the type definitions and improve readability.
Here’s an example of how we can implement this:
@@ -158,7 +158,10 @@ export namespace SliderRoot {
values: ReadonlyArray<number>;
}
- export interface Props<TValue extends number | number[]>
+ export type Props = PropsTemplate<number> &
+ PropsTemplate<number[]> &
+ PropsTemplate<number | number[]>;
+ export interface PropsTemplate<TValue extends number | number[]>
extends Pick<
useSliderRoot.Parameters,
| 'disabled'
Please refer to mui/material-ui#44777 (comment)
@@ -49,7 +49,7 @@ function TestSlider(props: SliderRoot.Props) { | |||
); | |||
} | |||
|
|||
function TestRangeSlider(props: SliderRoot.Props) { | |||
function TestRangeSlider(props: SliderRoot.Props<number[]>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seloner I think we can define Props without using generics.
Check https://github.com/mui/base-ui/pull/1241/files#r1899037802, please
|
||
/** | ||
* Groups all parts of the slider. | ||
* Renders a `<div>` element. | ||
* | ||
* Documentation: [Base UI Slider](https://base-ui.com/react/components/slider) | ||
*/ | ||
const SliderRoot = React.forwardRef(function SliderRoot( | ||
props: SliderRoot.Props, | ||
const SliderRoot = fixedForwardRef(function SliderRoot<TValue extends number | number[]>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seloner I think we can remove generic SliderRoot component by removing generic in Props interfacce.
Check https://github.com/mui/base-ui/pull/1241/files#r1899037802, please
} | ||
} | ||
|
||
export { SliderRoot }; | ||
|
||
// @ts-expect-error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you remove fixedForwardRef and replace it with React.forwardRef
, then // @ts-expect-error
can be removed.
@@ -18,8 +18,8 @@ import { fixedForwardRef } from '../utils';
*
* Documentation: [Base UI Slider](https://base-ui.com/react/components/slider)
*/
-const SliderRoot = fixedForwardRef(function SliderRoot<TValue extends number | number[]>(
- props: SliderRoot.Props<TValue>,
+const SliderRoot = React.forwardRef(function SliderRoot(
+ props: SliderRoot.Props,
forwardedRef: React.ForwardedRef<HTMLDivElement>,
) {
const {
186397e
to
11792ab
Compare
@good-jinu |
@seloner My bad
So It seems like just a field like value doesn't work with it. For example: export type Props = PropsTemplate<number> |
PropsTemplate<number[]> |
PropsTemplate<number | number[]>; |
It does not work |
@seloner Thanks for working on this, I'm afraid this isn't an option though
@good-jinu Not sure if I understand you correctly, by "field like value" did you mean a single non-array value? |
We can still do the solution with the generics |
I think this is ok as long as it doesn't affect the public API, just wonder why @good-jinu is against generics (I prefer to avoid them too, but I'm just curious here) A while back we did decide that for components with values that could sometimes be an array (accordion, slider, toggle group), we'd make the value in callbacks always be an array so it's predictable, also curious to see what you all think about this! |
We could use a default value so it does no really affect the public API compared to now . type Props<T extends number | number[] = number | number[]> = {
value: T;
onValueChange: (value: T) => void;
};
const Component: <T extends number | number[]>(props: Props<T>) => {}; I like your suggestion to remove the number case and always go with an array. I am new to this project so I can't really answer though what is the best solution here. |
I actually agree with using generics; however, I wanted to avoid changing the public API. My main intention was to eliminate the I also think it's fine as long as it doesn't change the external API. |
Trying to fix
#1230