From a2a0bfefc3bade5146b3ea7f04afcdaafd2459db Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Wed, 20 Nov 2024 18:47:10 +0800 Subject: [PATCH] Update proptypes and docs --- docs/data/api/tabs-root.json | 2 +- docs/data/translations/api-docs/tab/tab.json | 2 +- .../api-docs/tabs-root/tabs-root.json | 4 +- docs/reference/generated/tab.json | 2 +- docs/reference/generated/tabs-root.json | 5 +- .../src/Composite/List/CompositeList.tsx | 4 ++ .../src/Composite/Root/CompositeRoot.tsx | 8 +++ packages/mui-base/src/Tabs/Root/TabsRoot.tsx | 60 +++++++++++++++-- .../mui-base/src/Tabs/Root/TabsRootContext.ts | 27 ++++---- .../mui-base/src/Tabs/Root/useTabsRoot.ts | 64 ++++++++++--------- packages/mui-base/src/Tabs/Tab/Tab.tsx | 40 +++++++++++- packages/mui-base/src/Tabs/Tab/useTab.ts | 6 +- .../src/Tabs/TabIndicator/TabIndicator.tsx | 27 ++++++++ .../src/Tabs/TabIndicator/useTabIndicator.ts | 10 ++- .../mui-base/src/Tabs/TabPanel/TabPanel.tsx | 35 +++++++++- .../mui-base/src/Tabs/TabPanel/useTabPanel.ts | 20 +++--- .../mui-base/src/Tabs/TabsList/TabsList.tsx | 33 ++++++++++ .../mui-base/src/Tabs/TabsList/useTabsList.ts | 13 ++-- 18 files changed, 279 insertions(+), 83 deletions(-) diff --git a/docs/data/api/tabs-root.json b/docs/data/api/tabs-root.json index 4be24aeb81..346d8dcdb0 100644 --- a/docs/data/api/tabs-root.json +++ b/docs/data/api/tabs-root.json @@ -1,7 +1,7 @@ { "props": { "className": { "type": { "name": "union", "description": "func
| string" } }, - "defaultValue": { "type": { "name": "any" } }, + "defaultValue": { "type": { "name": "any" }, "default": "0" }, "direction": { "type": { "name": "enum", "description": "'ltr'
| 'rtl'" }, "default": "'ltr'" diff --git a/docs/data/translations/api-docs/tab/tab.json b/docs/data/translations/api-docs/tab/tab.json index d486100235..5eff531661 100644 --- a/docs/data/translations/api-docs/tab/tab.json +++ b/docs/data/translations/api-docs/tab/tab.json @@ -6,7 +6,7 @@ }, "render": { "description": "A function to customize rendering of the component." }, "value": { - "description": "You can provide your own value. Otherwise, it falls back to the child position index." + "description": "The value of the Tab. When not specified, the value is the child position index." } }, "classDescriptions": {} diff --git a/docs/data/translations/api-docs/tabs-root/tabs-root.json b/docs/data/translations/api-docs/tabs-root/tabs-root.json index 5800f4b6b4..27020d8d4f 100644 --- a/docs/data/translations/api-docs/tabs-root/tabs-root.json +++ b/docs/data/translations/api-docs/tabs-root/tabs-root.json @@ -5,14 +5,14 @@ "description": "Class names applied to the element or a function that returns them based on the component's state." }, "defaultValue": { - "description": "The default value. Use when the component is not controlled." + "description": "The default value. Use when the component is not controlled. When the value is null, no Tab will be selected." }, "direction": { "description": "The direction of the text." }, "onValueChange": { "description": "Callback invoked when new value is being set." }, "orientation": { "description": "The component orientation (layout flow direction)." }, "render": { "description": "A function to customize rendering of the component." }, "value": { - "description": "The value of the currently selected Tab. If you don't want any selected Tab, you can set this prop to null." + "description": "The value of the currently selected Tab. Use when the component is controlled. When the value is null, no Tab will be selected." } }, "classDescriptions": {} diff --git a/docs/reference/generated/tab.json b/docs/reference/generated/tab.json index 733e416638..bf941b933d 100644 --- a/docs/reference/generated/tab.json +++ b/docs/reference/generated/tab.json @@ -12,7 +12,7 @@ }, "value": { "type": "any", - "description": "You can provide your own value. Otherwise, it falls back to the child position index." + "description": "The value of the Tab.\nWhen not specified, the value is the child position index." } } } diff --git a/docs/reference/generated/tabs-root.json b/docs/reference/generated/tabs-root.json index fbef93c3f9..33998d6c74 100644 --- a/docs/reference/generated/tabs-root.json +++ b/docs/reference/generated/tabs-root.json @@ -8,7 +8,8 @@ }, "defaultValue": { "type": "any", - "description": "The default value. Use when the component is not controlled." + "default": "0", + "description": "The default value. Use when the component is not controlled.\nWhen the value is `null`, no Tab will be selected." }, "direction": { "type": "'ltr' | 'rtl'", @@ -30,7 +31,7 @@ }, "value": { "type": "any", - "description": "The value of the currently selected `Tab`.\nIf you don't want any selected `Tab`, you can set this prop to `null`." + "description": "The value of the currently selected `Tab`. Use when the component is controlled.\nWhen the value is `null`, no Tab will be selected." } } } diff --git a/packages/mui-base/src/Composite/List/CompositeList.tsx b/packages/mui-base/src/Composite/List/CompositeList.tsx index f4fae4da4a..f3eca29708 100644 --- a/packages/mui-base/src/Composite/List/CompositeList.tsx +++ b/packages/mui-base/src/Composite/List/CompositeList.tsx @@ -133,6 +133,10 @@ CompositeList.propTypes /* remove-proptypes */ = { labelsRef: PropTypes.shape({ current: PropTypes.arrayOf(PropTypes.string).isRequired, }), + /** + * @ignore + */ + onMapChange: PropTypes.func, } as any; export { CompositeList }; diff --git a/packages/mui-base/src/Composite/Root/CompositeRoot.tsx b/packages/mui-base/src/Composite/Root/CompositeRoot.tsx index c493631d2f..c8d3f4ae8e 100644 --- a/packages/mui-base/src/Composite/Root/CompositeRoot.tsx +++ b/packages/mui-base/src/Composite/Root/CompositeRoot.tsx @@ -133,6 +133,10 @@ CompositeRoot.propTypes /* remove-proptypes */ = { * @ignore */ onActiveIndexChange: PropTypes.func, + /** + * @ignore + */ + onMapChange: PropTypes.func, /** * @ignore */ @@ -141,6 +145,10 @@ CompositeRoot.propTypes /* remove-proptypes */ = { * A function to customize rendering of the component. */ render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), + /** + * @ignore + */ + stopEventPropagation: PropTypes.bool, } as any; export { CompositeRoot }; diff --git a/packages/mui-base/src/Tabs/Root/TabsRoot.tsx b/packages/mui-base/src/Tabs/Root/TabsRoot.tsx index 011d002975..d9ac62d08d 100644 --- a/packages/mui-base/src/Tabs/Root/TabsRoot.tsx +++ b/packages/mui-base/src/Tabs/Root/TabsRoot.tsx @@ -1,5 +1,6 @@ 'use client'; import * as React from 'react'; +import PropTypes from 'prop-types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; import type { BaseUIComponentProps } from '../../utils/types'; import { CompositeList } from '../../Composite/List/CompositeList'; @@ -102,11 +103,56 @@ const TabsRoot = React.forwardRef(function TabsRoot( ); }); +TabsRoot.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * @ignore + */ + children: PropTypes.node, + /** + * Class names applied to the element or a function that returns them based on the component's state. + */ + className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * The default value. Use when the component is not controlled. + * When the value is `null`, no Tab will be selected. + * @default 0 + */ + defaultValue: PropTypes.any, + /** + * The direction of the text. + * @default 'ltr' + */ + direction: PropTypes.oneOf(['ltr', 'rtl']), + /** + * Callback invoked when new value is being set. + */ + onValueChange: PropTypes.func, + /** + * The component orientation (layout flow direction). + * @default 'horizontal' + */ + orientation: PropTypes.oneOf(['horizontal', 'vertical']), + /** + * A function to customize rendering of the component. + */ + render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), + /** + * The value of the currently selected `Tab`. Use when the component is controlled. + * When the value is `null`, no Tab will be selected. + */ + value: PropTypes.any, +} as any; + export { TabsRoot }; export type TabsOrientation = 'horizontal' | 'vertical'; export type TabsDirection = 'ltr' | 'rtl'; export type TabActivationDirection = 'left' | 'right' | 'up' | 'down' | 'none'; +export type TabValue = any | null; namespace TabsRoot { export type OwnerState = { @@ -115,16 +161,18 @@ namespace TabsRoot { tabActivationDirection: TabActivationDirection; }; - export interface Props extends BaseUIComponentProps<'div', OwnerState> { + export interface Props extends Omit, 'defaultValue'> { /** - * The value of the currently selected `Tab`. - * If you don't want any selected `Tab`, you can set this prop to `null`. + * The value of the currently selected `Tab`. Use when the component is controlled. + * When the value is `null`, no Tab will be selected. */ - value?: any | null; + value?: TabValue; /** * The default value. Use when the component is not controlled. + * When the value is `null`, no Tab will be selected. + * @default 0 */ - defaultValue?: any | null; + defaultValue?: TabValue; /** * The component orientation (layout flow direction). * @default 'horizontal' @@ -138,6 +186,6 @@ namespace TabsRoot { /** * Callback invoked when new value is being set. */ - onValueChange?: (value: any | null, event?: Event) => void; + onValueChange?: (value: TabValue, event?: Event) => void; } } diff --git a/packages/mui-base/src/Tabs/Root/TabsRootContext.ts b/packages/mui-base/src/Tabs/Root/TabsRootContext.ts index b68d5f128e..5797e146d9 100644 --- a/packages/mui-base/src/Tabs/Root/TabsRootContext.ts +++ b/packages/mui-base/src/Tabs/Root/TabsRootContext.ts @@ -1,18 +1,18 @@ 'use client'; import * as React from 'react'; import { type TabMetadata } from '../Tab/useTab'; -import { type TabActivationDirection } from './TabsRoot'; +import type { TabActivationDirection, TabValue } from './TabsRoot'; export interface TabsRootContext { /** * The currently selected tab's value. */ - value: any | null; + value: TabValue; /** * Callback for setting new value. */ onValueChange: ( - value: any | null, + value: TabValue, activationDirection: TabActivationDirection, event: Event, ) => void; @@ -25,18 +25,23 @@ export interface TabsRootContext { */ direction: 'ltr' | 'rtl'; /** - * Registers a function that returns the id of the tab with the given value. + * Gets the element of the Tab with the given value. + * @param {any | undefined} value Value to find the tab for. */ - // registerGetTabIdByPanelValueOrIndexFn?: (lookupFunction: (id: any) => string | undefined) => void; - getTabElementBySelectedValue: (selectedValue: any | undefined) => HTMLElement | null; + getTabElementBySelectedValue: (selectedValue: TabValue | undefined) => HTMLElement | null; /** - * Gets the id of the tab with the given value. - * @param {any | undefined} value Value to find the tab for. + * Gets the `id` attribute of the Tab that corresponds to the given TabPanel value or index. + * @param (any | undefined) panelValue Value to find the Tab for. + * @param (number) index The index of the TabPanel to look for. */ - getTabIdByPanelValueOrIndex: (panelValue: any | undefined, index: number) => string | undefined; + getTabIdByPanelValueOrIndex: ( + panelValue: TabValue | undefined, + index: number, + ) => string | undefined; /** - * Gets the id of the tab panel with the given value. - * @param {any | undefined} value Value to find the tab panel for. + * Gets the `id` attribute of the TabPanel that corresponds to the given Tab value or index. + * @param (any | undefined) tabValue Value to find the Tab for. + * @param (number) index The index of the Tab to look for. */ getTabPanelIdByTabValueOrIndex: (tabValue: any, index: number) => string | undefined; setTabMap: (map: Map) => void; diff --git a/packages/mui-base/src/Tabs/Root/useTabsRoot.ts b/packages/mui-base/src/Tabs/Root/useTabsRoot.ts index 91f2c22814..1594ffb5dc 100644 --- a/packages/mui-base/src/Tabs/Root/useTabsRoot.ts +++ b/packages/mui-base/src/Tabs/Root/useTabsRoot.ts @@ -1,10 +1,12 @@ 'use client'; import * as React from 'react'; import { mergeReactProps } from '../../utils/mergeReactProps'; +import { GenericHTMLProps } from '../../utils/types'; import { useControlled } from '../../utils/useControlled'; +import type { CompositeMetadata } from '../../Composite/List/CompositeList'; import type { TabPanelMetadata } from '../TabPanel/useTabPanel'; import type { TabMetadata } from '../Tab/useTab'; -import type { TabActivationDirection } from './TabsRoot'; +import type { TabActivationDirection, TabValue } from './TabsRoot'; function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValue { const { @@ -24,21 +26,17 @@ function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValu }); const [tabPanelMap, setTabPanelMap] = React.useState( - () => new Map(), + () => new Map | null>(), ); const [tabMap, setTabMap] = React.useState( - () => new Map(), + () => new Map | null>(), ); const [tabActivationDirection, setTabActivationDirection] = React.useState('none'); const onValueChange = React.useCallback( - ( - newValue: any | null, - activationDirection: TabActivationDirection, - event: Event | undefined, - ) => { + (newValue: TabValue, activationDirection: TabActivationDirection, event: Event | undefined) => { setValue(newValue); setTabActivationDirection(activationDirection); onValueChangeProp?.(newValue, event); @@ -48,7 +46,7 @@ function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValu // get the `id` attribute of to set as the value of `aria-controls` on const getTabPanelIdByTabValueOrIndex = React.useCallback( - (tabValue: any | undefined, index: number) => { + (tabValue: TabValue | undefined, index: number) => { if (tabValue === undefined && index < 0) { return undefined; } @@ -76,7 +74,7 @@ function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValu // get the `id` attribute of to set as the value of `aria-labelledby` on const getTabIdByPanelValueOrIndex = React.useCallback( - (tabPanelValue: any | undefined, index: number) => { + (tabPanelValue: TabValue | undefined, index: number) => { if (tabPanelValue === undefined && index < 0) { return undefined; } @@ -88,7 +86,6 @@ function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValu index > -1 && tabPanelValue === (tabMetadata?.value ?? tabMetadata?.index ?? undefined) ) { - // console.log('found by tabPanelValue', tabMetadata?.id); return tabMetadata?.id; } @@ -98,7 +95,6 @@ function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValu index > -1 && index === (tabMetadata?.value ?? tabMetadata?.index ?? undefined) ) { - // console.log('found by tabPanel index', tabMetadata?.id); return tabMetadata?.id; } } @@ -110,7 +106,7 @@ function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValu // used in `useActivationDirectionDetector` for setting data-activation-direction const getTabElementBySelectedValue = React.useCallback( - (selectedValue: any | undefined): HTMLElement | null => { + (selectedValue: TabValue | undefined): HTMLElement | null => { if (selectedValue === undefined) { return null; } @@ -156,11 +152,11 @@ namespace useTabsRoot { * The value of the currently selected `Tab`. * If you don't want any selected `Tab`, you can set this prop to `false`. */ - value?: any | null; + value?: TabValue; /** * The default value. Use when the component is not controlled. */ - defaultValue?: any | null; + defaultValue?: TabValue; /** * The direction of the text. * @default 'ltr' @@ -169,56 +165,62 @@ namespace useTabsRoot { /** * Callback invoked when new value is being set. */ - onValueChange?: (value: any | null, event?: Event) => void; + onValueChange?: (value: TabValue, event?: Event) => void; } export interface ReturnValue { - getRootProps: ( - externalProps?: React.ComponentPropsWithRef<'div'>, - ) => React.ComponentPropsWithRef<'div'>; + /** + * Resolver for the Root component's props. + * @param externalProps additional props for Tabs.Root + * @returns props that should be spread on Tabs.Root + */ + getRootProps: (externalProps?: GenericHTMLProps) => GenericHTMLProps; /** * The direction of the text. */ direction: 'ltr' | 'rtl'; /** - * Gets the underlying element of the Tab with the given value. - * @param value Value to find the tab for. + * Gets the element of the Tab with the given value. + * @param {any | undefined} value Value to find the tab for. */ - getTabElementBySelectedValue: (panelValue: any | undefined) => HTMLElement | null; + getTabElementBySelectedValue: (panelValue: TabValue | undefined) => HTMLElement | null; /** - * Gets the `id` attribute of the Tab with the given value. + * Gets the `id` attribute of the Tab that corresponds to the given TabPanel value or index. * @param (any | undefined) panelValue Value to find the Tab for. * @param (number) index The index of the Tab to look for. */ - getTabIdByPanelValueOrIndex: (panelValue: any | undefined, index: number) => string | undefined; + getTabIdByPanelValueOrIndex: ( + panelValue: TabValue | undefined, + index: number, + ) => string | undefined; /** - * Gets the id of the tab panel with the given value. + * Gets the `id` attribute of the TabPanel that corresponds to the given Tab value or index. * @param value Value to find the tab panel for. */ getTabPanelIdByTabValueOrIndex: ( - tabValue: any | undefined, + tabValue: TabValue | undefined, index: number, ) => string | undefined; /** * Callback for setting new value. */ onValueChange: ( - value: any | null, + value: TabValue, activationDirection: TabActivationDirection, event: Event, ) => void; - setTabMap: (map: Map) => void; - setTabPanelMap: (map: Map) => void; + setTabMap: (map: Map | null>) => void; + setTabPanelMap: (map: Map | null>) => void; /** * The position of the active tab relative to the previously active tab. */ tabActivationDirection: TabActivationDirection; - tabMap: Map; + tabMap: Map | null>; tabPanelRefs: React.RefObject<(HTMLElement | null)[]>; /** * The currently selected tab's value. */ - value: any | null; + value: TabValue; } } diff --git a/packages/mui-base/src/Tabs/Tab/Tab.tsx b/packages/mui-base/src/Tabs/Tab/Tab.tsx index f16ecd3abe..87c7816528 100644 --- a/packages/mui-base/src/Tabs/Tab/Tab.tsx +++ b/packages/mui-base/src/Tabs/Tab/Tab.tsx @@ -1,9 +1,10 @@ 'use client'; import * as React from 'react'; +import PropTypes from 'prop-types'; import { useTab } from './useTab'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; import type { BaseUIComponentProps } from '../../utils/types'; -import type { TabsOrientation } from '../Root/TabsRoot'; +import type { TabsOrientation, TabValue } from '../Root/TabsRoot'; import { useTabsRootContext } from '../Root/TabsRootContext'; import { useTabsListContext } from '../TabsList/TabsListContext'; @@ -68,14 +69,47 @@ const Tab = React.forwardRef(function Tab( return renderElement(); }); +Tab.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * @ignore + */ + children: PropTypes.node, + /** + * Class names applied to the element or a function that returns them based on the component's state. + */ + className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * @ignore + */ + disabled: PropTypes.bool, + /** + * @ignore + */ + id: PropTypes.string, + /** + * A function to customize rendering of the component. + */ + render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), + /** + * The value of the Tab. + * When not specified, the value is the child position index. + */ + value: PropTypes.any, +} as any; + export { Tab }; namespace Tab { export interface Props extends BaseUIComponentProps<'button', Tab.OwnerState> { /** - * You can provide your own value. Otherwise, it falls back to the child position index. + * The value of the Tab. + * When not specified, the value is the child position index. */ - value?: any; + value?: TabValue; } export interface OwnerState { diff --git a/packages/mui-base/src/Tabs/Tab/useTab.ts b/packages/mui-base/src/Tabs/Tab/useTab.ts index 644d776074..27350e5e99 100644 --- a/packages/mui-base/src/Tabs/Tab/useTab.ts +++ b/packages/mui-base/src/Tabs/Tab/useTab.ts @@ -160,9 +160,9 @@ namespace useTab { export interface ReturnValue { /** - * Resolver for the root slot's props. - * @param externalProps props for the root slot - * @returns props that should be spread on the root slot + * Resolver for the Tab component's props. + * @param externalProps additional props for Tabs.Tab + * @returns props that should be spread on Tabs.Tab */ getRootProps: ( externalProps?: React.ComponentPropsWithRef<'button'>, diff --git a/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.tsx b/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.tsx index 9a12d65bc4..1cd3fb559f 100644 --- a/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.tsx +++ b/packages/mui-base/src/Tabs/TabIndicator/TabIndicator.tsx @@ -1,5 +1,6 @@ 'use client'; import * as React from 'react'; +import PropTypes from 'prop-types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; import { useOnMount } from '../../utils/useOnMount'; import type { BaseUIComponentProps } from '../../utils/types'; @@ -89,6 +90,32 @@ const TabIndicator = React.forwardRef( }, ); +TabIndicator.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * @ignore + */ + children: PropTypes.node, + /** + * Class names applied to the element or a function that returns them based on the component's state. + */ + className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * A function to customize rendering of the component. + */ + render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), + /** + * If `true`, the indicator will include code to render itself before React hydrates. + * This will minimize the time the indicator is not visible after the SSR-generated content is downloaded. + * + * @default false + */ + renderBeforeHydration: PropTypes.bool, +} as any; + export { TabIndicator }; namespace TabIndicator { diff --git a/packages/mui-base/src/Tabs/TabIndicator/useTabIndicator.ts b/packages/mui-base/src/Tabs/TabIndicator/useTabIndicator.ts index 8e0b45f981..73d6e1c28d 100644 --- a/packages/mui-base/src/Tabs/TabIndicator/useTabIndicator.ts +++ b/packages/mui-base/src/Tabs/TabIndicator/useTabIndicator.ts @@ -3,6 +3,7 @@ import * as React from 'react'; import type { TabsListContext } from '../TabsList/TabsListContext'; import type { TabsRootContext } from '../Root/TabsRootContext'; import { mergeReactProps } from '../../utils/mergeReactProps'; +import { GenericHTMLProps } from '../../utils/types'; import { useForcedRerendering } from '../../utils/useForcedRerendering'; function round(value: number) { @@ -125,9 +126,12 @@ export namespace useTabIndicator { Pick {} export interface ReturnValue { - getRootProps: ( - otherProps?: React.ComponentPropsWithRef<'span'>, - ) => React.ComponentPropsWithRef<'span'>; + /** + * Resolver for the TabIndicator component's props. + * @param externalProps additional props for Tabs.TabIndicator + * @returns props that should be spread on Tabs.TabIndicator + */ + getRootProps: (externalProps?: GenericHTMLProps) => GenericHTMLProps; activeTabPosition: ActiveTabPosition | null; } } diff --git a/packages/mui-base/src/Tabs/TabPanel/TabPanel.tsx b/packages/mui-base/src/Tabs/TabPanel/TabPanel.tsx index 47bd7582b8..e306403ef4 100644 --- a/packages/mui-base/src/Tabs/TabPanel/TabPanel.tsx +++ b/packages/mui-base/src/Tabs/TabPanel/TabPanel.tsx @@ -1,10 +1,11 @@ 'use client'; import * as React from 'react'; +import PropTypes from 'prop-types'; import { useTabPanel } from './useTabPanel'; import { tabsStyleHookMapping } from '../Root/styleHooks'; import { useTabsRootContext } from '../Root/TabsRootContext'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; -import { TabsRoot } from '../Root/TabsRoot'; +import { TabsRoot, type TabValue } from '../Root/TabsRoot'; import type { BaseUIComponentProps } from '../../utils/types'; /** @@ -60,6 +61,36 @@ const TabPanel = React.forwardRef(function TabPanel( return renderElement(); }); +TabPanel.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * @ignore + */ + children: PropTypes.node, + /** + * Class names applied to the element or a function that returns them based on the component's state. + */ + className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * If `true`, keeps the contents of the hidden TabPanel in the DOM. + * @default false + */ + keepMounted: PropTypes.bool, + /** + * A function to customize rendering of the component. + */ + render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), + /** + * The value of the TabPanel. It will be shown when the Tab with the corresponding value is selected. + * If not provided, it will fall back to the index of the panel. + * It is recommended to explicitly provide it, as it's required for the tab panel to be rendered on the server. + */ + value: PropTypes.any, +} as any; + export { TabPanel }; namespace TabPanel { @@ -73,7 +104,7 @@ namespace TabPanel { * If not provided, it will fall back to the index of the panel. * It is recommended to explicitly provide it, as it's required for the tab panel to be rendered on the server. */ - value?: any; + value?: TabValue; /** * If `true`, keeps the contents of the hidden TabPanel in the DOM. * @default false diff --git a/packages/mui-base/src/Tabs/TabPanel/useTabPanel.ts b/packages/mui-base/src/Tabs/TabPanel/useTabPanel.ts index f35be421a6..36212ca04e 100644 --- a/packages/mui-base/src/Tabs/TabPanel/useTabPanel.ts +++ b/packages/mui-base/src/Tabs/TabPanel/useTabPanel.ts @@ -1,10 +1,12 @@ 'use client'; import * as React from 'react'; -import type { TabsRootContext } from '../Root/TabsRootContext'; +import { mergeReactProps } from '../../utils/mergeReactProps'; +import { GenericHTMLProps } from '../../utils/types'; import { useId } from '../../utils/useId'; import { useForkRef } from '../../utils/useForkRef'; -import { mergeReactProps } from '../../utils/mergeReactProps'; import { useCompositeListItem } from '../../Composite/List/useCompositeListItem'; +import type { TabsRootContext } from '../Root/TabsRootContext'; +import type { TabValue } from '../Root/TabsRoot'; export interface TabPanelMetadata { id?: string; @@ -81,11 +83,11 @@ namespace useTabPanel { /** * The (context) value of the currently active/selected Tab. */ - selectedValue: TabsRootContext['value']; + selectedValue: TabValue; /** * The value of the TabPanel. It will be shown when the Tab with the corresponding value is selected. */ - value?: any; + value?: TabValue; } export interface ReturnValue { @@ -94,13 +96,11 @@ namespace useTabPanel { */ hidden: boolean; /** - * Resolver for the root slot's props. - * @param externalProps additional props for the root slot - * @returns props that should be spread on the root slot + * Resolver for the TabPanel component's props. + * @param externalProps additional props for Tabs.TabPanel + * @returns props that should be spread on Tabs.TabPanel */ - getRootProps: ( - externalProps?: React.ComponentPropsWithRef<'div'>, - ) => React.ComponentPropsWithRef<'div'>; + getRootProps: (externalProps?: GenericHTMLProps) => GenericHTMLProps; rootRef: React.RefCallback | null; } } diff --git a/packages/mui-base/src/Tabs/TabsList/TabsList.tsx b/packages/mui-base/src/Tabs/TabsList/TabsList.tsx index 02a29a04f1..ba978e74be 100644 --- a/packages/mui-base/src/Tabs/TabsList/TabsList.tsx +++ b/packages/mui-base/src/Tabs/TabsList/TabsList.tsx @@ -1,5 +1,6 @@ 'use client'; import * as React from 'react'; +import PropTypes from 'prop-types'; import { BaseUIComponentProps } from '../../utils/types'; import { useComponentRenderer } from '../../utils/useComponentRenderer'; import { CompositeRoot } from '../../Composite/Root/CompositeRoot'; @@ -101,6 +102,38 @@ const TabsList = React.forwardRef(function TabsList( ); }); +TabsList.propTypes /* remove-proptypes */ = { + // ┌────────────────────────────── Warning ──────────────────────────────┐ + // │ These PropTypes are generated from the TypeScript type definitions. │ + // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ + // └─────────────────────────────────────────────────────────────────────┘ + /** + * If `true`, the tab will be activated whenever it is focused. + * Otherwise, it has to be activated by clicking or pressing the Enter or Space key. + * + * @default true + */ + activateOnFocus: PropTypes.bool, + /** + * @ignore + */ + children: PropTypes.node, + /** + * Class names applied to the element or a function that returns them based on the component's state. + */ + className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + /** + * If `true`, using keyboard navigation will wrap focus to the other end of the list once the end is reached. + * + * @default true + */ + loop: PropTypes.bool, + /** + * A function to customize rendering of the component. + */ + render: PropTypes.oneOfType([PropTypes.element, PropTypes.func]), +} as any; + export { TabsList }; namespace TabsList { diff --git a/packages/mui-base/src/Tabs/TabsList/useTabsList.ts b/packages/mui-base/src/Tabs/TabsList/useTabsList.ts index f574cec7ca..87bd847ffa 100644 --- a/packages/mui-base/src/Tabs/TabsList/useTabsList.ts +++ b/packages/mui-base/src/Tabs/TabsList/useTabsList.ts @@ -2,9 +2,10 @@ import * as React from 'react'; import type { TabsRootContext } from '../Root/TabsRootContext'; import { type TabsOrientation, type TabActivationDirection } from '../Root/TabsRoot'; -import { useForkRef } from '../../utils/useForkRef'; import { mergeReactProps } from '../../utils/mergeReactProps'; +import { GenericHTMLProps } from '../../utils/types'; import { useEnhancedEffect } from '../../utils/useEnhancedEffect'; +import { useForkRef } from '../../utils/useForkRef'; import { useEventCallback } from '../../utils/useEventCallback'; function useTabsList(parameters: useTabsList.Parameters): useTabsList.ReturnValue { @@ -151,13 +152,11 @@ namespace useTabsList { export interface ReturnValue { /** - * Resolver for the root slot's props. - * @param externalProps props for the root slot - * @returns props that should be spread on the root slot + * Resolver for the TabsList component's props. + * @param externalProps additional props for Tabs.TabsList + * @returns props that should be spread on Tabs.TabsList */ - getRootProps: ( - externalProps?: React.ComponentPropsWithRef<'div'>, - ) => React.ComponentPropsWithRef<'div'>; + getRootProps: (externalProps?: GenericHTMLProps) => GenericHTMLProps; /** * Callback when a Tab is activated * @param {any | null} newValue The value of the newly activated tab.