diff --git a/components/doc/common/apidoc/index.json b/components/doc/common/apidoc/index.json index 636b7b2c00..e488e224ee 100644 --- a/components/doc/common/apidoc/index.json +++ b/components/doc/common/apidoc/index.json @@ -30923,6 +30923,14 @@ "type": "ReactNode", "default": "", "description": "Used to get the child elements of the component." + }, + { + "name": "pt", + "optional": true, + "readonly": false, + "type": "TabMenuPassThroughOptions", + "default": "", + "description": "Uses to pass attributes to DOM elements inside the component." } ] }, @@ -30977,6 +30985,108 @@ ] } } + }, + "interfaces": { + "description": "Defines the custom interfaces used by the module.", + "values": { + "TabMenuThroughMethodOptions": { + "description": "Custom passthrough(pt) option method.", + "relatedProp": "", + "props": [ + { + "name": "props", + "optional": false, + "readonly": false, + "type": "TabMenuProps" + }, + { + "name": "state", + "optional": false, + "readonly": false, + "type": "TabMenuState" + } + ], + "callbacks": [] + }, + "TabMenuPassThroughOptions": { + "description": "Custom passthrough(pt) options.", + "relatedProp": "pt", + "props": [ + { + "name": "root", + "optional": true, + "readonly": false, + "type": "TabMenuPassThroughType>", + "description": "Uses to pass attributes to the root's DOM element." + }, + { + "name": "menu", + "optional": true, + "readonly": false, + "type": "TabMenuPassThroughType>", + "description": "Uses to pass attributes to the list's DOM element." + }, + { + "name": "menuitem", + "optional": true, + "readonly": false, + "type": "TabMenuPassThroughType>", + "description": "Uses to pass attributes to the list item's DOM element." + }, + { + "name": "action", + "optional": true, + "readonly": false, + "type": "TabMenuPassThroughType>", + "description": "Uses to pass attributes to the action's DOM element." + }, + { + "name": "icon", + "optional": true, + "readonly": false, + "type": "TabMenuPassThroughType | HTMLAttributes>", + "description": "Uses to pass attributes to the icon's DOM element." + }, + { + "name": "label", + "optional": true, + "readonly": false, + "type": "TabMenuPassThroughType>", + "description": "Uses to pass attributes to the label's DOM element." + }, + { + "name": "inkbar", + "optional": true, + "readonly": false, + "type": "TabMenuPassThroughType>", + "description": "Uses to pass attributes to the inkbar's DOM element." + } + ], + "callbacks": [] + }, + "TabMenuState": { + "description": "Defines current inline state in TabMenu component.", + "relatedProp": "", + "props": [ + { + "name": "activeIndex", + "optional": false, + "readonly": false, + "type": "number", + "description": "Current active index state as a number." + } + ], + "callbacks": [] + } + } + }, + "types": { + "description": "Defines the custom types used by the module.", + "values": { + "TabMenuPassThroughType": { + "values": "PassThroughType" + } + } } }, "tabview": { diff --git a/components/doc/dock/pt/ptdoc.js b/components/doc/dock/pt/ptdoc.js index efadc294c1..a4f042f45b 100644 --- a/components/doc/dock/pt/ptdoc.js +++ b/components/doc/dock/pt/ptdoc.js @@ -167,7 +167,7 @@ export default function PTDemo() {
{ - return ( <> diff --git a/components/doc/steps/pt/ptdoc.js b/components/doc/steps/pt/ptdoc.js index 4d321057c3..39dc810290 100644 --- a/components/doc/steps/pt/ptdoc.js +++ b/components/doc/steps/pt/ptdoc.js @@ -48,7 +48,7 @@ export default function PTDemo() { ]; return ( -
+
+
-
+
+ `, + javascript: ` +import React from 'react'; +import { TabMenu } from 'primereact/tabmenu'; + +export default function PTDemo() { + const items = [ + { + label: 'Personal' + }, + { + label: 'Seat' + }, + { + label: 'Payment' + }, + { + label: 'Confirmation' + } + ]; + + return ( +
+ +
+ ) +} + `, + typescript: ` +import React from 'react'; +import { TabMenu } from 'primereact/steps'; +import { MenuItem } from 'primereact/menuitem'; + +export default function PTDemo() { + const items: MenuItem[] = [ + { + label: 'Personal' + }, + { + label: 'Seat' + }, + { + label: 'Payment' + }, + { + label: 'Confirmation' + } + ]; + + return ( +
+ +
+ ) +} + ` + }; + + return ( + <> + +
+ +
+ + + ); +} diff --git a/components/doc/tabmenu/pt/wireframe.js b/components/doc/tabmenu/pt/wireframe.js new file mode 100644 index 0000000000..e09daea3ac --- /dev/null +++ b/components/doc/tabmenu/pt/wireframe.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { DocSectionText } from '../../common/docsectiontext'; + +export const Wireframe = (props) => { + return ( + <> + +
+ tabmenu +
+ + ); +}; diff --git a/components/lib/dock/Dock.js b/components/lib/dock/Dock.js index c0f55d17c4..893608693e 100644 --- a/components/lib/dock/Dock.js +++ b/components/lib/dock/Dock.js @@ -57,7 +57,7 @@ export const Dock = React.memo( const actionProps = mergeProps( { href: url || '#', - role: "menuitem", + role: 'menuitem', className: contentClassName, target, 'data-pr-tooltip': label, @@ -90,17 +90,13 @@ export const Dock = React.memo( { key: index, className, - role: "none", + role: 'none', onMouseEnter: () => onItemMouseEnter(index) }, ptm('menuitem') - ) - - return ( -
  • - {content} -
  • ); + + return
  • {content}
  • ; }; const createItems = () => { @@ -112,7 +108,7 @@ export const Dock = React.memo( const header = ObjectUtils.getJSXElement(props.header, { props }); const headerProps = mergeProps( { - className: "p-dock-header" + className: 'p-dock-header' }, ptm('header') ); @@ -127,18 +123,14 @@ export const Dock = React.memo( const items = createItems(); const menuProps = mergeProps( { - className: "p-dock-list", - role: "menu", + className: 'p-dock-list', + role: 'menu', onMouseLeave: onListMouseLeave }, ptm('menu') - ) - - return ( -
      - {items} -
    ); + + return
      {items}
    ; }; const createFooter = () => { @@ -146,10 +138,10 @@ export const Dock = React.memo( const footer = ObjectUtils.getJSXElement(props.footer, { props }); const footerProps = mergeProps( { - className: "p-dock-footer" + className: 'p-dock-footer' }, ptm('footer') - ) + ); return
    {footer}
    ; } @@ -185,7 +177,7 @@ export const Dock = React.memo( const containerProps = mergeProps( { - className: "p-dock-container" + className: 'p-dock-container' }, ptm('container') ); diff --git a/components/lib/tabmenu/TabMenu.js b/components/lib/tabmenu/TabMenu.js index 888b3033da..cba2b82868 100644 --- a/components/lib/tabmenu/TabMenu.js +++ b/components/lib/tabmenu/TabMenu.js @@ -1,6 +1,6 @@ import * as React from 'react'; import { Ripple } from '../ripple/Ripple'; -import { classNames, DomHandler, IconUtils, ObjectUtils } from '../utils/Utils'; +import { classNames, DomHandler, IconUtils, ObjectUtils, mergeProps } from '../utils/Utils'; import { TabMenuBase } from './TabMenuBase'; export const TabMenu = React.memo( @@ -14,6 +14,13 @@ export const TabMenu = React.memo( const tabsRef = React.useRef({}); const activeIndex = props.onTabChange ? props.activeIndex : activeIndexState; + const { ptm } = TabMenuBase.setMetaData({ + props, + state: { + activeIndex: activeIndexState + } + }); + const itemClick = (event, item, index) => { if (item.disabled) { event.preventDefault(); @@ -82,10 +89,37 @@ export const TabMenu = React.memo( _className ); const iconClassName = classNames('p-menuitem-icon', _icon); - const icon = IconUtils.getJSXIcon(_icon, { className: 'p-menuitem-icon' }, { props }); - const label = _label && {_label}; + const iconProps = mergeProps( + { + className: iconClassName + }, + ptm('icon') + ); + + const icon = IconUtils.getJSXIcon(_icon, { ...iconProps }, { props }); + + const labelProps = mergeProps( + { + className: 'p-menuitem-text' + }, + ptm('label') + ); + + const label = _label && {_label}; + + const actionProps = mergeProps( + { + href: url || '#', + className: 'p-menuitem-link', + target: target, + onClick: (event) => itemClick(event, item, index), + role: 'presentation' + }, + ptm('action') + ); + let content = ( - itemClick(event, item, index)} role="presentation"> + {icon} {label} @@ -108,11 +142,21 @@ export const TabMenu = React.memo( content = ObjectUtils.getJSXElement(template, item, defaultContentOptions); } - return ( -
  • - {content} -
  • + const menuItemProps = mergeProps( + { + ref: tabsRef.current[`tab_${index}`], + key, + className: className, + style: style, + role: 'tab', + 'aria-selected': active, + 'aria-expanded': active, + 'aria-disabled': disabled + }, + ptm('menuitem') ); + + return
  • {content}
  • ; }; const createItems = () => { @@ -120,15 +164,41 @@ export const TabMenu = React.memo( }; if (props.model) { - const otherProps = TabMenuBase.getOtherProps(props); const className = classNames('p-tabmenu p-component', props.className); const items = createItems(); + const inkbarProps = mergeProps( + { + ref: inkbarRef, + className: 'p-tabmenu-ink-bar' + }, + ptm('inkbar') + ); + const menuProps = mergeProps( + { + ref: navRef, + className: 'p-tabmenu-nav p-reset', + role: 'tablist' + }, + ptm('menu') + ); + + const rootProps = mergeProps( + { + id: props.id, + ref: elementRef, + className, + style: props.style + }, + TabMenuBase.getOtherProps(props), + ptm('root') + ); + return ( -
    -
      +
      +
        {items} -
      • +
      ); diff --git a/components/lib/tabmenu/TabMenuBase.js b/components/lib/tabmenu/TabMenuBase.js index 2dfc5adf2d..ff1e0653e9 100644 --- a/components/lib/tabmenu/TabMenuBase.js +++ b/components/lib/tabmenu/TabMenuBase.js @@ -1,6 +1,6 @@ -import { ObjectUtils } from '../utils/Utils'; +import { ComponentBase } from '../componentbase/ComponentBase'; -export const TabMenuBase = { +export const TabMenuBase = ComponentBase.extend({ defaultProps: { __TYPE: 'TabMenu', id: null, @@ -10,7 +10,5 @@ export const TabMenuBase = { className: null, onTabChange: null, children: undefined - }, - getProps: (props) => ObjectUtils.getMergedProps(props, TabMenuBase.defaultProps), - getOtherProps: (props) => ObjectUtils.getDiffProps(props, TabMenuBase.defaultProps) -}; + } +}); diff --git a/components/lib/tabmenu/tabmenu.d.ts b/components/lib/tabmenu/tabmenu.d.ts index a578ac45c6..3559d8c929 100644 --- a/components/lib/tabmenu/tabmenu.d.ts +++ b/components/lib/tabmenu/tabmenu.d.ts @@ -9,6 +9,63 @@ */ import * as React from 'react'; import { MenuItem } from '../menuitem'; +import { PassThroughType } from '../utils/utils'; + +export declare type TabMenuPassThroughType = PassThroughType; + +/** + * Custom passthrough(pt) option method. + */ +export interface TabMenuThroughMethodOptions { + props: TabMenuProps; + state: TabMenuState; +} + +/** + * Custom passthrough(pt) options. + * @see {@link TabMenuProps.pt} + */ +export interface TabMenuPassThroughOptions { + /** + * Uses to pass attributes to the root's DOM element. + */ + root?: TabMenuPassThroughType>; + /** + * Uses to pass attributes to the list's DOM element. + */ + menu?: TabMenuPassThroughType>; + /** + * Uses to pass attributes to the list item's DOM element. + */ + menuitem?: TabMenuPassThroughType>; + /** + * Uses to pass attributes to the action's DOM element. + */ + action?: TabMenuPassThroughType>; + /** + * Uses to pass attributes to the icon's DOM element. + */ + icon?: TabMenuPassThroughType | React.HTMLAttributes>; + /** + * Uses to pass attributes to the label's DOM element. + */ + label?: TabMenuPassThroughType>; + /** + * Uses to pass attributes to the inkbar's DOM element. + */ + inkbar?: TabMenuPassThroughType>; +} + +/** + * Defines current inline state in TabMenu component. + */ +export interface TabMenuState { + /** + * Current active index state as a number. + * @defaulValue 0 + */ + activeIndex: number; +} /** * Custom tab change event. @@ -54,6 +111,11 @@ export interface TabMenuProps extends Omit { } ]; - return ; }; diff --git a/pages/tabmenu/index.js b/pages/tabmenu/index.js index 46f64b5511..23b380cb35 100644 --- a/pages/tabmenu/index.js +++ b/pages/tabmenu/index.js @@ -1,9 +1,12 @@ +import { Wireframe } from '../../components/doc/tabmenu/pt/wireframe'; import { DocComponent } from '../../components/doc/common/doccomponent'; import { AccessibilityDoc } from '../../components/doc/tabmenu/accessibilitydoc'; import { BasicDoc } from '../../components/doc/tabmenu/basicdoc'; import { ControlledDoc } from '../../components/doc/tabmenu/controlleddoc'; import { ImportDoc } from '../../components/doc/tabmenu/importdoc'; +import { PTDoc } from '../../components/doc/tabmenu/pt/ptdoc'; import { StyleDoc } from '../../components/doc/tabmenu/styledoc'; +import DocApiTable from '../../components/doc/common/docapitable'; const TabMenuDemo = () => { const docs = [ @@ -34,7 +37,25 @@ const TabMenuDemo = () => { } ]; - return ; + const ptDocs = [ + { + id: 'pt.wireframe', + label: 'Wireframe', + component: Wireframe + }, + { + id: 'pt.tabmenu.options', + label: 'TabMenu PT Options', + component: DocApiTable + }, + { + id: 'pt.demo', + label: 'Example', + component: PTDoc + } + ]; + + return ; }; export default TabMenuDemo;