From ea8c8b172be26e30645587416bedf822a7975390 Mon Sep 17 00:00:00 2001 From: habubey Date: Thu, 18 May 2023 19:10:34 +0300 Subject: [PATCH] Refactor #4391 - for MegaMenu --- components/doc/common/apidoc/index.json | 242 ++++++++++++++ components/doc/megamenu/pt/ptdoc.js | 408 ++++++++++++++++++++++++ components/doc/megamenu/pt/wireframe.js | 13 + components/lib/megamenu/MegaMenu.js | 230 ++++++++++--- components/lib/megamenu/MegaMenuBase.js | 10 +- components/lib/megamenu/megamenu.d.ts | 144 ++++++++- pages/megamenu/index.js | 22 +- 7 files changed, 1021 insertions(+), 48 deletions(-) create mode 100644 components/doc/megamenu/pt/ptdoc.js create mode 100644 components/doc/megamenu/pt/wireframe.js diff --git a/components/doc/common/apidoc/index.json b/components/doc/common/apidoc/index.json index 6d938deed0..b0eae36764 100644 --- a/components/doc/common/apidoc/index.json +++ b/components/doc/common/apidoc/index.json @@ -22648,6 +22648,14 @@ "type": "ReactNode", "default": "", "description": "Used to get the child elements of the component." + }, + { + "name": "pt", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughOptions", + "default": "", + "description": "Uses to pass attributes to DOM elements inside the component." } ] }, @@ -22656,6 +22664,240 @@ "values": [] } } + }, + "interfaces": { + "description": "Defines the custom interfaces used by the module.", + "values": { + "MegaMenuPassThroughMethodOptions": { + "description": "Custom passthrough(pt) option method.", + "relatedProp": "", + "props": [ + { + "name": "props", + "optional": false, + "readonly": false, + "type": "MegaMenuProps" + }, + { + "name": "state", + "optional": false, + "readonly": false, + "type": "MegaMenuState" + }, + { + "name": "context", + "optional": false, + "readonly": false, + "type": "MegaMenuContext" + } + ], + "callbacks": [] + }, + "MegaMenuPassThroughOptions": { + "description": "Custom passthrough(pt) options.", + "relatedProp": "pt", + "props": [ + { + "name": "root", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the root's DOM element." + }, + { + "name": "menu", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the list's DOM element." + }, + { + "name": "menuitem", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the list item's DOM element." + }, + { + "name": "headerAction", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the header action's DOM element." + }, + { + "name": "action", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the action's DOM element." + }, + { + "name": "icon", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType | SVGProps>", + "description": "Uses to pass attributes to the icon's DOM element." + }, + { + "name": "label", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the label's DOM element." + }, + { + "name": "submenuIcon", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType | SVGProps>", + "description": "Uses to pass attributes to the submenu icon's DOM element." + }, + { + "name": "panel", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the panel's DOM element." + }, + { + "name": "grid", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the grid's DOM element." + }, + { + "name": "column", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the column's DOM element." + }, + { + "name": "submenu", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the submenu's DOM element." + }, + { + "name": "submenuItem", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the submenu items's DOM element." + }, + { + "name": "submenuHeader", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the submenu header's DOM element." + }, + { + "name": "separator", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the separator's DOM element." + }, + { + "name": "start", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the start of the component." + }, + { + "name": "end", + "optional": true, + "readonly": false, + "type": "MegaMenuPassThroughType>", + "description": "Uses to pass attributes to the end of the component." + } + ], + "callbacks": [] + }, + "MegaMenuFocusedItemInfo": { + "description": "Defines focused item info", + "relatedProp": "", + "props": [ + { + "name": "index", + "optional": false, + "readonly": false, + "type": "number", + "description": "Active item index" + }, + { + "name": "level", + "optional": false, + "readonly": false, + "type": "number", + "description": "Active item level" + }, + { + "name": "parentKey", + "optional": false, + "readonly": false, + "type": "string", + "description": "Parent key info" + } + ], + "callbacks": [] + }, + "MegaMenuState": { + "description": "Defines current inline state in MegaMenu component.", + "relatedProp": "", + "props": [ + { + "name": "mobileActive", + "optional": false, + "readonly": false, + "type": "boolean", + "description": "Current mobileActive state as a boolean." + }, + { + "name": "attributeSelector", + "optional": false, + "readonly": false, + "type": "boolean", + "description": "Current attributeSelector visible state as a string." + }, + { + "name": "activeItem", + "optional": false, + "readonly": false, + "type": "MenuItem", + "description": "Active item path." + } + ], + "callbacks": [] + }, + "MegaMenuContext": { + "description": "Defines current options in MegaMenu component.", + "relatedProp": "", + "props": [ + { + "name": "active", + "optional": false, + "readonly": false, + "type": "boolean", + "description": "Current active state of menuitem as a boolean." + } + ], + "callbacks": [] + } + } + }, + "types": { + "description": "Defines the custom types used by the module.", + "values": { + "MegaMenuPassThroughType": { + "values": "PassThroughType" + } + } } }, "mention": { diff --git a/components/doc/megamenu/pt/ptdoc.js b/components/doc/megamenu/pt/ptdoc.js new file mode 100644 index 0000000000..fdbcdc96c7 --- /dev/null +++ b/components/doc/megamenu/pt/ptdoc.js @@ -0,0 +1,408 @@ +import { MegaMenu } from '../../../lib/megamenu/MegaMenu'; +import { DocSectionCode } from '../../common/docsectioncode'; +import { DocSectionText } from '../../common/docsectiontext'; + +export function PTDoc(props) { + const items = [ + { + label: 'Videos', + icon: 'pi pi-fw pi-video', + items: [ + [ + { + label: 'Video 1', + items: [{ label: 'Video 1.1' }, { label: 'Video 1.2' }] + }, + { + label: 'Video 2', + items: [{ label: 'Video 2.1' }, { label: 'Video 2.2' }] + } + ], + [ + { + label: 'Video 3', + items: [{ label: 'Video 3.1' }, { label: 'Video 3.2' }] + }, + { + label: 'Video 4', + items: [{ label: 'Video 4.1' }, { label: 'Video 4.2' }] + } + ] + ] + }, + { + label: 'Users', + icon: 'pi pi-fw pi-users', + items: [ + [ + { + label: 'User 1', + items: [{ label: 'User 1.1' }, { label: 'User 1.2' }] + }, + { + label: 'User 2', + items: [{ label: 'User 2.1' }, { label: 'User 2.2' }] + } + ], + [ + { + label: 'User 3', + items: [{ label: 'User 3.1' }, { label: 'User 3.2' }] + }, + { + label: 'User 4', + items: [{ label: 'User 4.1' }, { label: 'User 4.2' }] + } + ], + [ + { + label: 'User 5', + items: [{ label: 'User 5.1' }, { label: 'User 5.2' }] + }, + { + label: 'User 6', + items: [{ label: 'User 6.1' }, { label: 'User 6.2' }] + } + ] + ] + }, + { + label: 'Events', + icon: 'pi pi-fw pi-calendar', + items: [ + [ + { + label: 'Event 1', + items: [{ label: 'Event 1.1' }, { label: 'Event 1.2' }] + }, + { + label: 'Event 2', + items: [{ label: 'Event 2.1' }, { label: 'Event 2.2' }] + } + ], + [ + { + label: 'Event 3', + items: [{ label: 'Event 3.1' }, { label: 'Event 3.2' }] + }, + { + label: 'Event 4', + items: [{ label: 'Event 4.1' }, { label: 'Event 4.2' }] + } + ] + ] + }, + { + label: 'Settings', + icon: 'pi pi-fw pi-cog', + items: [ + [ + { + label: 'Setting 1', + items: [{ label: 'Setting 1.1' }, { label: 'Setting 1.2' }] + }, + { + label: 'Setting 2', + items: [{ label: 'Setting 2.1' }, { label: 'Setting 2.2' }] + }, + { + label: 'Setting 3', + items: [{ label: 'Setting 3.1' }, { label: 'Setting 3.2' }] + } + ], + [ + { + label: 'Technology 4', + items: [{ label: 'Setting 4.1' }, { label: 'Setting 4.2' }] + } + ] + ] + } + ]; + const code = { + basic: ` + ({ className: context.active ? 'bg-primary-200' : undefined }) + }} +/> +`, + javascript: ` +import React from 'react'; +import { MegaMenu } from 'primereact/megamenu'; + +export default function PTDemo() { + const items = [ + { + label: 'Videos', icon: 'pi pi-fw pi-video', + items: [ + [ + { + label: 'Video 1', + items: [{ label: 'Video 1.1' }, { label: 'Video 1.2' }] + }, + { + label: 'Video 2', + items: [{ label: 'Video 2.1' }, { label: 'Video 2.2' }] + } + ], + [ + { + label: 'Video 3', + items: [{ label: 'Video 3.1' }, { label: 'Video 3.2' }] + }, + { + label: 'Video 4', + items: [{ label: 'Video 4.1' }, { label: 'Video 4.2' }] + } + ] + ] + }, + { + label: 'Users', icon: 'pi pi-fw pi-users', + items: [ + [ + { + label: 'User 1', + items: [{ label: 'User 1.1' }, { label: 'User 1.2' }] + }, + { + label: 'User 2', + items: [{ label: 'User 2.1' }, { label: 'User 2.2' }] + }, + ], + [ + { + label: 'User 3', + items: [{ label: 'User 3.1' }, { label: 'User 3.2' }] + }, + { + label: 'User 4', + items: [{ label: 'User 4.1' }, { label: 'User 4.2' }] + } + ], + [ + { + label: 'User 5', + items: [{ label: 'User 5.1' }, { label: 'User 5.2' }] + }, + { + label: 'User 6', + items: [{ label: 'User 6.1' }, { label: 'User 6.2' }] + } + ] + ] + }, + { + label: 'Events', icon: 'pi pi-fw pi-calendar', + items: [ + [ + { + label: 'Event 1', + items: [{ label: 'Event 1.1' }, { label: 'Event 1.2' }] + }, + { + label: 'Event 2', + items: [{ label: 'Event 2.1' }, { label: 'Event 2.2' }] + } + ], + [ + { + label: 'Event 3', + items: [{ label: 'Event 3.1' }, { label: 'Event 3.2' }] + }, + { + label: 'Event 4', + items: [{ label: 'Event 4.1' }, { label: 'Event 4.2' }] + } + ] + ] + }, + { + label: 'Settings', icon: 'pi pi-fw pi-cog', + items: [ + [ + { + label: 'Setting 1', + items: [{ label: 'Setting 1.1' }, { label: 'Setting 1.2' }] + }, + { + label: 'Setting 2', + items: [{ label: 'Setting 2.1' }, { label: 'Setting 2.2' }] + }, + { + label: 'Setting 3', + items: [{ label: 'Setting 3.1' }, { label: 'Setting 3.2' }] + } + ], + [ + { + label: 'Technology 4', + items: [{ label: 'Setting 4.1' }, { label: 'Setting 4.2' }] + } + ] + ] + } + ]; + + return ( +
+ ({ className: context.active ? 'bg-primary-200' : undefined }) + }} + /> +
+ ) +} + `, + typescript: ` +import React from 'react'; +import { MegaMenu } from 'primereact/megamenu'; +import { MenuItem } from 'primereact/menuitem'; + +export default function PTDemo() { + const items: MenuItem[] = [ + { + label: 'Videos', icon: 'pi pi-fw pi-video', + items: [ + [ + { + label: 'Video 1', + items: [{ label: 'Video 1.1' }, { label: 'Video 1.2' }] + }, + { + label: 'Video 2', + items: [{ label: 'Video 2.1' }, { label: 'Video 2.2' }] + } + ], + [ + { + label: 'Video 3', + items: [{ label: 'Video 3.1' }, { label: 'Video 3.2' }] + }, + { + label: 'Video 4', + items: [{ label: 'Video 4.1' }, { label: 'Video 4.2' }] + } + ] + ] + }, + { + label: 'Users', icon: 'pi pi-fw pi-users', + items: [ + [ + { + label: 'User 1', + items: [{ label: 'User 1.1' }, { label: 'User 1.2' }] + }, + { + label: 'User 2', + items: [{ label: 'User 2.1' }, { label: 'User 2.2' }] + }, + ], + [ + { + label: 'User 3', + items: [{ label: 'User 3.1' }, { label: 'User 3.2' }] + }, + { + label: 'User 4', + items: [{ label: 'User 4.1' }, { label: 'User 4.2' }] + } + ], + [ + { + label: 'User 5', + items: [{ label: 'User 5.1' }, { label: 'User 5.2' }] + }, + { + label: 'User 6', + items: [{ label: 'User 6.1' }, { label: 'User 6.2' }] + } + ] + ] + }, + { + label: 'Events', icon: 'pi pi-fw pi-calendar', + items: [ + [ + { + label: 'Event 1', + items: [{ label: 'Event 1.1' }, { label: 'Event 1.2' }] + }, + { + label: 'Event 2', + items: [{ label: 'Event 2.1' }, { label: 'Event 2.2' }] + } + ], + [ + { + label: 'Event 3', + items: [{ label: 'Event 3.1' }, { label: 'Event 3.2' }] + }, + { + label: 'Event 4', + items: [{ label: 'Event 4.1' }, { label: 'Event 4.2' }] + } + ] + ] + }, + { + label: 'Settings', icon: 'pi pi-fw pi-cog', + items: [ + [ + { + label: 'Setting 1', + items: [{ label: 'Setting 1.1' }, { label: 'Setting 1.2' }] + }, + { + label: 'Setting 2', + items: [{ label: 'Setting 2.1' }, { label: 'Setting 2.2' }] + }, + { + label: 'Setting 3', + items: [{ label: 'Setting 3.1' }, { label: 'Setting 3.2' }] + } + ], + [ + { + label: 'Technology 4', + items: [{ label: 'Setting 4.1' }, { label: 'Setting 4.2' }] + } + ] + ] + } + ]; + + return ( +
+ ({ className: context.active ? 'bg-primary-200' : undefined }) + }} + /> +
+ ) +} + ` + }; + + return ( + <> + +
+ ({ className: context.active ? 'bg-primary-200' : undefined }) + }} + /> +
+ + + ); +} diff --git a/components/doc/megamenu/pt/wireframe.js b/components/doc/megamenu/pt/wireframe.js new file mode 100644 index 0000000000..9810be4468 --- /dev/null +++ b/components/doc/megamenu/pt/wireframe.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { DocSectionText } from '../../common/docsectiontext'; + +export const Wireframe = (props) => { + return ( + <> + +
+ megamenu +
+ + ); +}; diff --git a/components/lib/megamenu/MegaMenu.js b/components/lib/megamenu/MegaMenu.js index fa596de758..a54ac07776 100644 --- a/components/lib/megamenu/MegaMenu.js +++ b/components/lib/megamenu/MegaMenu.js @@ -1,12 +1,12 @@ import * as React from 'react'; import PrimeReact from '../api/Api'; import { useEventListener, useMatchMedia, useMountEffect, useResizeListener, useUpdateEffect } from '../hooks/Hooks'; -import { Ripple } from '../ripple/Ripple'; -import { DomHandler, IconUtils, ObjectUtils, UniqueComponentId, ZIndexUtils, classNames } from '../utils/Utils'; -import { MegaMenuBase } from './MegaMenuBase'; -import { AngleRightIcon } from '../icons/angleright'; import { AngleDownIcon } from '../icons/angledown'; +import { AngleRightIcon } from '../icons/angleright'; import { BarsIcon } from '../icons/bars'; +import { Ripple } from '../ripple/Ripple'; +import { DomHandler, IconUtils, ObjectUtils, UniqueComponentId, ZIndexUtils, classNames, mergeProps } from '../utils/Utils'; +import { MegaMenuBase } from './MegaMenuBase'; export const MegaMenu = React.memo( React.forwardRef((inProps, ref) => { @@ -22,6 +22,23 @@ export const MegaMenu = React.memo( const vertical = props.orientation === 'vertical'; const isMobileMode = useMatchMedia(`screen and (max-width: ${props.breakpoint})`, !!props.breakpoint); + const { ptm } = MegaMenuBase.setMetaData({ + props, + state: { + activeItem: activeItemState, + attributeSelector: attributeSelectorState, + mobileActive: mobileActiveState + } + }); + + const getPTOptions = (item, key) => { + return ptm(key, { + context: { + active: activeItemState === item + } + }); + }; + const [bindDocumentClickListener] = useEventListener({ type: 'click', listener: (event) => { @@ -240,14 +257,30 @@ export const MegaMenu = React.memo( const createSeparator = (index) => { const key = 'separator_' + index; - return
  • ; + const separatorProps = mergeProps( + { + key, + className: 'p-menu-separator', + role: 'separator' + }, + ptm('separator') + ); + + return
  • ; }; const createSubmenuIcon = (item) => { if (item.items) { const iconClassName = 'p-submenu-icon'; - const icon = vertical ? props.submenuIcon || : props.submenuIcon || ; - const submenuIcon = IconUtils.getJSXIcon(icon, { className: iconClassName }, { props }); + const submenuIconProps = mergeProps( + { + className: iconClassName + }, + ptm('submenuIcon') + ); + + const icon = vertical ? props.submenuIcon || : props.submenuIcon || ; + const submenuIcon = IconUtils.getJSXIcon(icon, { ...submenuIconProps }, { props }); return submenuIcon; } @@ -269,8 +302,32 @@ export const MegaMenu = React.memo( const iconClassName = classNames(item.icon, 'p-menuitem-icon'); const icon = IconUtils.getJSXIcon(item.icon, { className: 'p-menuitem-icon' }, { props }); const label = item.label && {item.label}; + + const actionProps = mergeProps( + { + href: item.url || '#', + className: linkClassName, + target: item.target, + onClick: (event) => onLeafClick(event, item), + role: 'menuitem', + 'aria-disabled': item.disabled + }, + getPTOptions(item, 'action') + ); + + const submenuItemProps = mergeProps( + { + key: key, + id: item.id, + className: className, + style: item.style, + role: 'none' + }, + getPTOptions(item, 'submenuItem') + ); + let content = ( - onLeafClick(event, item)} role="menuitem" aria-disabled={item.disabled}> + {icon} {label} @@ -290,11 +347,7 @@ export const MegaMenu = React.memo( content = ObjectUtils.getJSXElement(item.template, item, defaultContentOptions); } - return ( -
  • - {content} -
  • - ); + return
  • {content}
  • ; } }; @@ -312,11 +365,19 @@ export const MegaMenu = React.memo( ); const items = submenu.items.map(createSubmenuItem); + const submenuHeaderProps = mergeProps( + { + id: submenu.id, + className, + style: submenu.style, + role: 'presentation' + }, + ptm('submenuHeader') + ); + return ( - +
  • {submenu.label}
  • {items}
    ); @@ -330,11 +391,25 @@ export const MegaMenu = React.memo( const key = category.label + '_column_' + index; const submenus = createSubmenus(column); + const columnProps = mergeProps( + { + key: key, + className: columnClassName + }, + ptm('column') + ); + + const submenuProps = mergeProps( + { + className: 'p-megamenu-submenu', + role: 'menu' + }, + ptm('submenu') + ); + return ( -
    -
      - {submenus} -
    +
    +
      {submenus}
    ); }; @@ -355,9 +430,23 @@ export const MegaMenu = React.memo( if (category.items) { const columns = createColumns(category); + const panelProps = mergeProps( + { + className: 'p-megamenu-panel' + }, + ptm('panel') + ); + + const gridProps = mergeProps( + { + className: 'p-megamenu-grid' + }, + ptm('grid') + ); + return ( -
    -
    {columns}
    +
    +
    {columns}
    ); } @@ -477,23 +566,53 @@ export const MegaMenu = React.memo( const createCategory = (category, index) => { const className = classNames('p-menuitem', { 'p-menuitem-active': category === activeItemState }, category.className); const linkClassName = classNames('p-menuitem-link', { 'p-disabled': category.disabled }); - const icon = IconUtils.getJSXIcon(category.icon, { className: 'p-menuitem-icon' }, { props }); - const label = category.label && {category.label}; + const iconProps = mergeProps( + { + className: 'p-menuitem-icon' + }, + getPTOptions(category, 'icon') + ); + const icon = IconUtils.getJSXIcon(category.icon, { ...iconProps }, { props }); + + const labelProps = mergeProps( + { + className: 'p-menuitem-text' + }, + getPTOptions(category, 'label') + ); + const label = category.label && {category.label}; const itemContent = category.template ? ObjectUtils.getJSXElement(category.template, category) : null; const submenuIcon = createSubmenuIcon(category); const panel = createCategoryPanel(category); + const headerActionProps = mergeProps( + { + href: category.url || '#', + className: linkClassName, + target: category.target, + onClick: (e) => onCategoryClick(e, category), + onKeyDown: (e) => onCategoryKeyDown(e, category), + role: 'menuitem', + 'aria-haspopup': category.items != null + }, + getPTOptions(category, 'headerAction') + ); + + const menuItemProps = mergeProps( + { + key: category.label + '_' + index, + id: category.id, + className: className, + style: category.style, + onMouseEnter: (e) => onCategoryMouseEnter(e, category), + role: 'none' + }, + getPTOptions(category, 'menuitem') + ); + return ( -
  • onCategoryMouseEnter(e, category)} role="none"> - onCategoryClick(e, category)} - onKeyDown={(e) => onCategoryKeyDown(e, category)} - role="menuitem" - aria-haspopup={category.items != null} - > +
  • + {icon} {label} {itemContent} @@ -506,9 +625,17 @@ export const MegaMenu = React.memo( }; const createMenu = () => { + const menuProps = mergeProps( + { + className: 'p-megamenu-root-list', + role: 'menubar' + }, + ptm('menu') + ); + if (props.model) { return ( -
      +
        {props.model.map((item, index) => { return createCategory(item, index, true); })} @@ -520,20 +647,34 @@ export const MegaMenu = React.memo( }; const createStartContent = () => { + const startProps = mergeProps( + { + className: 'p-megamenu-start' + }, + ptm('start') + ); + if (props.start) { const start = ObjectUtils.getJSXElement(props.start, props); - return
        {start}
        ; + return
        {start}
        ; } return null; }; const createEndContent = () => { + const endProps = mergeProps( + { + className: 'p-megamenu-end' + }, + ptm('end') + ); + if (props.end) { const end = ObjectUtils.getJSXElement(props.end, props); - return
        {end}
        ; + return
        {end}
        ; } return null; @@ -557,7 +698,6 @@ export const MegaMenu = React.memo( return button; }; - const otherProps = MegaMenuBase.getOtherProps(props); const className = classNames( 'p-megamenu p-component', { @@ -567,13 +707,25 @@ export const MegaMenu = React.memo( }, props.className ); + + const rootProps = mergeProps( + { + ref: elementRef, + id: props.id, + className, + style: props.style + }, + MegaMenuBase.getOtherProps(props), + ptm('root') + ); + const menu = createMenu(); const start = createStartContent(); const end = createEndContent(); const menuButton = createMenuButton(); return ( -
        +
        {start} {menuButton} {menu} diff --git a/components/lib/megamenu/MegaMenuBase.js b/components/lib/megamenu/MegaMenuBase.js index 28f5d586ea..0e63bc0387 100644 --- a/components/lib/megamenu/MegaMenuBase.js +++ b/components/lib/megamenu/MegaMenuBase.js @@ -1,6 +1,6 @@ -import { ObjectUtils } from '../utils/Utils'; +import { ComponentBase } from '../componentbase/ComponentBase'; -export const MegaMenuBase = { +export const MegaMenuBase = ComponentBase.extend({ defaultProps: { __TYPE: 'MegaMenu', id: null, @@ -15,7 +15,5 @@ export const MegaMenuBase = { menuIcon: null, end: null, children: undefined - }, - getProps: (props) => ObjectUtils.getMergedProps(props, MegaMenuBase.defaultProps), - getOtherProps: (props) => ObjectUtils.getDiffProps(props, MegaMenuBase.defaultProps) -}; + } +}); diff --git a/components/lib/megamenu/megamenu.d.ts b/components/lib/megamenu/megamenu.d.ts index 12258a3962..0b947ae976 100644 --- a/components/lib/megamenu/megamenu.d.ts +++ b/components/lib/megamenu/megamenu.d.ts @@ -9,13 +9,148 @@ */ import * as React from 'react'; import { MenuItem } from '../menuitem'; -import { IconType } from '../utils/utils'; +import { IconType, PassThroughType } from '../utils/utils'; + +export declare type MegaMenuPassThroughType = PassThroughType; + +/** + * Custom passthrough(pt) option method. + */ +export interface MegaMenuPassThroughMethodOptions { + props: MegaMenuProps; + state: MegaMenuState; + context: MegaMenuContext; +} + +/** + * Custom passthrough(pt) options. + * @see {@link MegaMenuProps.pt} + */ +export interface MegaMenuPassThroughOptions { + /** + * Uses to pass attributes to the root's DOM element. + */ + root?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the list's DOM element. + */ + menu?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the list item's DOM element. + */ + menuitem?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the header action's DOM element. + */ + headerAction?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the action's DOM element. + */ + action?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the icon's DOM element. + */ + icon?: MegaMenuPassThroughType | React.HTMLAttributes>; + /** + * Uses to pass attributes to the label's DOM element. + */ + label?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the submenu icon's DOM element. + */ + submenuIcon?: MegaMenuPassThroughType | React.HTMLAttributes>; + /** + * Uses to pass attributes to the panel's DOM element. + */ + panel?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the grid's DOM element. + */ + grid?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the column's DOM element. + */ + column?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the submenu's DOM element. + */ + submenu?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the submenu items's DOM element. + */ + submenuItem?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the submenu header's DOM element. + */ + submenuHeader?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the separator's DOM element. + */ + separator?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the start of the component. + */ + start?: MegaMenuPassThroughType>; + /** + * Uses to pass attributes to the end of the component. + */ + end?: MegaMenuPassThroughType>; +} + +/** + * Defines focused item info + */ +export interface MegaMenuFocusedItemInfo { + /** + * Active item index + */ + index: number; + /** + * Active item level + */ + level: number; + /** + * Parent key info + */ + parentKey: string; +} + +/** + * Defines current inline state in MegaMenu component. + */ +export interface MegaMenuState { + /** + * Current mobileActive state as a boolean. + * @defaultValue false + */ + mobileActive: boolean; + /** + * Current attributeSelector visible state as a string. + */ + attributeSelector: boolean; + /** + * Active item path. + * @type {MenuItem} + */ + activeItem: MenuItem; +} + +/** + * Defines current options in MegaMenu component. + */ +export interface MegaMenuContext { + /** + * Current active state of menuitem as a boolean. + * @defaultValue false + */ + active: boolean; +} /** * Defines valid properties in MegaMenu component. In addition to these, all properties of HTMLDivElement can be used in this component. * @group Properties */ -export interface MegaMenuProps extends Omit, HTMLDivElement>, 'ref'> { +export interface MegaMenuProps extends Omit, HTMLDivElement>, 'ref' | 'pt'> { /** * An array of menuitems. */ @@ -55,6 +190,11 @@ export interface MegaMenuProps extends Omit { component: AccessibilityDoc } ]; + const ptDocs = [ + { + id: 'pt.wireframe', + label: 'Wireframe', + component: Wireframe + }, + { + id: 'pt.megamenu.options', + label: 'MegaMenu PT Options', + component: DocApiTable + }, + { + id: 'pt.demo', + label: 'Example', + component: PTDoc + } + ]; - return ; + return ; }; export default MegaMenuDemo;