diff --git a/components/doc/common/apidoc/index.json b/components/doc/common/apidoc/index.json index 8d6100e338..268826a009 100644 --- a/components/doc/common/apidoc/index.json +++ b/components/doc/common/apidoc/index.json @@ -30405,6 +30405,14 @@ "type": "ReactNode", "default": "", "description": "Used to get the child elements of the component." + }, + { + "name": "pt", + "optional": true, + "readonly": false, + "type": "StepsPassThroughOptions", + "default": "", + "description": "Uses to pass attributes to DOM elements inside the component." } ] }, @@ -30459,6 +30467,88 @@ ] } } + }, + "interfaces": { + "description": "Defines the custom interfaces used by the module.", + "values": { + "StepsThroughMethodOptions": { + "description": "Custom passthrough(pt) option method.", + "relatedProp": "", + "props": [ + { + "name": "props", + "optional": false, + "readonly": false, + "type": "StepsProps" + } + ], + "callbacks": [] + }, + "StepsPassThroughOptions": { + "description": "Custom passthrough(pt) options.", + "relatedProp": "pt", + "props": [ + { + "name": "root", + "optional": true, + "readonly": false, + "type": "StepsPassThroughType>", + "description": "Uses to pass attributes to the root's DOM element." + }, + { + "name": "menu", + "optional": true, + "readonly": false, + "type": "StepsPassThroughType>", + "description": "Uses to pass attributes to the list's DOM element." + }, + { + "name": "menuitem", + "optional": true, + "readonly": false, + "type": "StepsPassThroughType>", + "description": "Uses to pass attributes to the list item's DOM element." + }, + { + "name": "action", + "optional": true, + "readonly": false, + "type": "StepsPassThroughType>", + "description": "Uses to pass attributes to the action's DOM element." + }, + { + "name": "step", + "optional": true, + "readonly": false, + "type": "StepsPassThroughType>", + "description": "Uses to pass attributes to the step's DOM element." + }, + { + "name": "label", + "optional": true, + "readonly": false, + "type": "StepsPassThroughType>", + "description": "Uses to pass attributes to the label's DOM element." + }, + { + "name": "icon", + "optional": true, + "readonly": false, + "type": "StepsPassThroughType | HTMLAttributes>", + "description": "Uses to pass attributes to the icon's DOM element." + } + ], + "callbacks": [] + } + } + }, + "types": { + "description": "Defines the custom types used by the module.", + "values": { + "StepsPassThroughType": { + "values": "PassThroughType" + } + } } }, "styleclass": { diff --git a/components/doc/steps/pt/ptdoc.js b/components/doc/steps/pt/ptdoc.js new file mode 100644 index 0000000000..4d321057c3 --- /dev/null +++ b/components/doc/steps/pt/ptdoc.js @@ -0,0 +1,111 @@ +import { DocSectionText } from '../../common/docsectiontext'; +import { DocSectionCode } from '../../common/docsectioncode'; +import { Steps } from '../../../lib/steps/Steps'; + +export function PTDoc(props) { + const items = [ + { + label: 'Personal' + }, + { + label: 'Seat' + }, + { + label: 'Payment' + }, + { + label: 'Confirmation' + } + ]; + + const code = { + basic: ` + + `, + javascript: ` +import React from 'react'; +import { Steps } from 'primereact/steps'; + +export default function PTDemo() { + const items = [ + { + label: 'Personal' + }, + { + label: 'Seat' + }, + { + label: 'Payment' + }, + { + label: 'Confirmation' + } + ]; + + return ( +
+ +
+ ) +} + `, + typescript: ` +import React from 'react'; +import { Steps } 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/steps/pt/wireframe.js b/components/doc/steps/pt/wireframe.js new file mode 100644 index 0000000000..2d8fd264f1 --- /dev/null +++ b/components/doc/steps/pt/wireframe.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { DocSectionText } from '../../common/docsectiontext'; + +export const Wireframe = (props) => { + return ( + <> + +
+ steps +
+ + ); +}; diff --git a/components/lib/steps/Steps.js b/components/lib/steps/Steps.js index 00e42f5ac1..d5571f324e 100644 --- a/components/lib/steps/Steps.js +++ b/components/lib/steps/Steps.js @@ -1,5 +1,5 @@ import * as React from 'react'; -import { classNames, IconUtils, ObjectUtils } from '../utils/Utils'; +import { classNames, IconUtils, ObjectUtils, mergeProps } from '../utils/Utils'; import { StepsBase } from './StepsBase'; export const Steps = React.memo( @@ -8,6 +8,10 @@ export const Steps = React.memo( const elementRef = React.useRef(null); + const { ptm } = StepsBase.setMetaData({ + props + }); + const itemClick = (event, item, index) => { if (props.readOnly || item.disabled) { event.preventDefault(); @@ -49,12 +53,48 @@ export const Steps = React.memo( 'p-highlight p-steps-current': active, 'p-disabled': disabled }); + const iconClassName = classNames('p-menuitem-icon', item.icon); - const icon = IconUtils.getJSXIcon(item.icon, { className: 'p-menuitem-icon' }, { props }); - const label = item.label && {item.label}; + const iconProps = mergeProps( + { + className: iconClassName + }, + ptm('icon') + ); + + const icon = IconUtils.getJSXIcon(item.icon, { ...iconProps }, { props }); + + const labelProps = mergeProps( + { + className: 'p-steps-title' + }, + ptm('label') + ); + + const label = item.label && {item.label}; + + const stepProps = mergeProps( + { + className: 'p-steps-number' + }, + ptm('step') + ); + + const actionProps = mergeProps( + { + href: item.url || '#', + className: 'p-menuitem-link', + role: 'presentation', + target: item.target, + onClick: (event) => itemClick(event, item, index), + tabIndex + }, + ptm('action') + ); + let content = ( - itemClick(event, item, index)} tabIndex={tabIndex}> - {index + 1} + + {index + 1} {icon} {label} @@ -77,18 +117,34 @@ export const Steps = React.memo( content = ObjectUtils.getJSXElement(item.template, item, defaultContentOptions); } - return ( - + const menuItemProps = mergeProps( + { + key: key, + id: item.id, + className: className, + style: item.style, + role: 'tab', + 'aria-selected': active, + 'aria-expanded': active + }, + ptm('menuitem') ); + + return
  • {content}
  • ; }; const createItems = () => { + const menuProps = mergeProps( + { + role: 'tablist' + }, + ptm('menu') + ); + if (props.model) { const items = props.model.map(createItem); - return
      {items}
    ; + return
      {items}
    ; } return null; @@ -99,7 +155,6 @@ export const Steps = React.memo( getElement: () => elementRef.current })); - const otherProps = StepsBase.getOtherProps(props); const className = classNames( 'p-steps p-component', { @@ -107,13 +162,21 @@ export const Steps = React.memo( }, props.className ); - const items = createItems(); - return ( -
    - {items} -
    + const rootProps = mergeProps( + { + id: props.id, + ref: elementRef, + className, + style: props.style + }, + StepsBase.getOtherProps(props), + ptm('root') ); + + const items = createItems(); + + return
    {items}
    ; }) ); diff --git a/components/lib/steps/StepsBase.js b/components/lib/steps/StepsBase.js index 1f1473f755..d2b98dff8e 100644 --- a/components/lib/steps/StepsBase.js +++ b/components/lib/steps/StepsBase.js @@ -1,6 +1,6 @@ -import { ObjectUtils } from '../utils/Utils'; +import { ComponentBase } from '../componentbase/ComponentBase'; -export const StepsBase = { +export const StepsBase = ComponentBase.extend({ defaultProps: { __TYPE: 'Steps', id: null, @@ -11,7 +11,5 @@ export const StepsBase = { className: null, onSelect: null, children: undefined - }, - getProps: (props) => ObjectUtils.getMergedProps(props, StepsBase.defaultProps), - getOtherProps: (props) => ObjectUtils.getDiffProps(props, StepsBase.defaultProps) -}; + } +}); diff --git a/components/lib/steps/steps.d.ts b/components/lib/steps/steps.d.ts index 1fddc2e3a6..02ba2342eb 100644 --- a/components/lib/steps/steps.d.ts +++ b/components/lib/steps/steps.d.ts @@ -9,6 +9,51 @@ */ import * as React from 'react'; import { MenuItem } from '../menuitem'; +import { PassThroughType } from '../utils/utils'; + +export declare type StepsPassThroughType = PassThroughType; + +/** + * Custom passthrough(pt) option method. + */ +export interface StepsThroughMethodOptions { + props: StepsProps; +} + +/** + * Custom passthrough(pt) options. + * @see {@link StepsProps.pt} + */ +export interface StepsPassThroughOptions { + /** + * Uses to pass attributes to the root's DOM element. + */ + root?: StepsPassThroughType>; + /** + * Uses to pass attributes to the list's DOM element. + */ + menu?: StepsPassThroughType>; + /** + * Uses to pass attributes to the list item's DOM element. + */ + menuitem?: StepsPassThroughType>; + /** + * Uses to pass attributes to the action's DOM element. + */ + action?: StepsPassThroughType>; + /** + * Uses to pass attributes to the step's DOM element. + */ + step?: StepsPassThroughType>; + /** + * Uses to pass attributes to the label's DOM element. + */ + label?: StepsPassThroughType>; + /** + * Uses to pass attributes to the icon's DOM element. + */ + icon?: StepsPassThroughType | React.HTMLAttributes>; +} /** * Custom select event @@ -59,6 +104,11 @@ export interface StepsProps extends Omit { @@ -34,6 +37,24 @@ const StepsDemo = () => { } ]; + const ptDocs = [ + { + id: 'pt.wireframe', + label: 'Wireframe', + component: Wireframe + }, + { + id: 'pt.steps.options', + label: 'Steps PT Options', + component: DocApiTable + }, + { + id: 'pt.demo', + label: 'Example', + component: PTDoc + } + ]; + return ( { componentDocs={docs} apiDocs={['Steps', 'MenuItem']} className="steps-demo" + ptDocs={ptDocs} /> ); };