Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,022 changes: 590 additions & 432 deletions src/modules/Dropdown/Dropdown.js

Large diffs are not rendered by default.

19 changes: 6 additions & 13 deletions src/modules/Dropdown/DropdownDivider.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,22 @@
/* eslint-disable react-hooks/static-components */
import cx from 'clsx'
import PropTypes from 'prop-types'
import * as React from 'react'

import { getComponentType, getUnhandledProps } from '../../lib'
import { getComponentType, getUnhandledProps } from './lib'

/**
* A dropdown menu can contain dividers to separate related content.
*/
const DropdownDivider = React.forwardRef(function (props, ref) {
function DropdownDivider(props) {
const { ref } = props
const { className } = props

const classes = cx('divider', className)

const rest = getUnhandledProps(DropdownDivider, props)
const ElementType = getComponentType(props)

return <ElementType {...rest} className={classes} ref={ref} />
})

DropdownDivider.displayName = 'DropdownDivider'
DropdownDivider.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,

/** Additional classes. */
className: PropTypes.string,
}

DropdownDivider.displayName = 'DropdownDivider'
export default DropdownDivider
39 changes: 11 additions & 28 deletions src/modules/Dropdown/DropdownHeader.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
/* eslint-disable react-hooks/static-components */
import cx from 'clsx'
import PropTypes from 'prop-types'
import * as React from 'react'

import {
childrenUtils,
createShorthandFactory,
customPropTypes,
getComponentType,
getUnhandledProps,
} from '../../lib'
import Icon from '../../elements/Icon'
} from './lib'

/**
* A dropdown menu can contain a header.
*/
const DropdownHeader = React.forwardRef(function (props, ref) {
function DropdownHeader(props) {
const { ref } = props
const { children, className, content, icon } = props

const classes = cx('header', className)
const rest = getUnhandledProps(DropdownHeader, props)
const ElementType = getComponentType(props)

if (!childrenUtils.isNil(children)) {
if (children != null) {
return (
<ElementType {...rest} className={classes} ref={ref}>
{children}
Expand All @@ -31,30 +28,16 @@ const DropdownHeader = React.forwardRef(function (props, ref) {

return (
<ElementType {...rest} className={classes} ref={ref}>
{Icon.create(icon, { autoGenerateKey: false })}
{icon && <i className={`${icon} icon`} aria-hidden="true" />}

{content}
</ElementType>
)
})

DropdownHeader.displayName = 'DropdownHeader'
DropdownHeader.propTypes = {
/** An element type to render as (string or function) */
as: PropTypes.elementType,

/** Primary content. */
children: PropTypes.node,

/** Additional classes. */
className: PropTypes.string,

/** Shorthand for primary content. */
content: customPropTypes.contentShorthand,

/** Shorthand for Icon. */
icon: customPropTypes.itemShorthand,
}

DropdownHeader.create = createShorthandFactory(DropdownHeader, (content) => ({ content }))
DropdownHeader.displayName = 'DropdownHeader'
DropdownHeader.create = createShorthandFactory(DropdownHeader, (content) => {
return { content }
})

export default DropdownHeader
170 changes: 81 additions & 89 deletions src/modules/Dropdown/DropdownItem.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
/* eslint-disable react-hooks/static-components */
import cx from 'clsx'
import _ from 'lodash'
import PropTypes from 'prop-types'
import * as React from 'react'

import {
childrenUtils,
createShorthand,
createShorthandFactory,
customPropTypes,
getComponentType,
getUnhandledProps,
getKeyOnly,
} from '../../lib'
import Flag from '../../elements/Flag'
import Icon from '../../elements/Icon'
import Image from '../../elements/Image'
import Label from '../../elements/Label'

} from './lib'
/**
* An item sub-component for Dropdown component.
*/
const DropdownItem = React.forwardRef(function (props, ref) {
function DropdownItem(props) {
const {
active,
children,
Expand All @@ -32,26 +24,30 @@ const DropdownItem = React.forwardRef(function (props, ref) {
icon,
image,
label,
onClick,
selected,
text,
//value,
ref,
...rest
} = props

const handleClick = (e) => {
_.invoke(props, 'onClick', e, props)
}
const handleClick = React.useCallback(
(e) => {
onClick?.(e, props)
},
[onClick, props]
)

const classes = cx(
getKeyOnly(active, 'active'),
getKeyOnly(disabled, 'disabled'),
getKeyOnly(selected, 'selected'),
'item',
className,
className
)
// add default dropdown icon if item contains another menu
const iconName = _.isNil(icon)
? childrenUtils.someByType(children, 'DropdownMenu') && 'dropdown'
: icon
const rest = getUnhandledProps(DropdownItem, props)

//const rest = getUnhandledProps(DropdownItem, props);
const ElementType = getComponentType(props)
const ariaOptions = {
role: 'option',
Expand All @@ -62,29 +58,78 @@ const DropdownItem = React.forwardRef(function (props, ref) {

if (!childrenUtils.isNil(children)) {
return (
<ElementType {...rest} {...ariaOptions} className={classes} onClick={handleClick} ref={ref}>
<ElementType
{...rest}
{...ariaOptions}
className={classes}
onClick={handleClick}
ref={ref}
>
{children}
</ElementType>
)
}

const flagElement = Flag.create(flag, { autoGenerateKey: false })
const iconElement = Icon.create(iconName, { autoGenerateKey: false })
const imageElement = Image.create(image, { autoGenerateKey: false })
const labelElement = Label.create(label, { autoGenerateKey: false })
const descriptionElement = createShorthand('span', (val) => ({ children: val }), description, {
defaultProps: { className: 'description' },
autoGenerateKey: false,
})
const flagElement = flag && (
<i className={`${flag} flag`} aria-hidden="true" />
)

const iconElement = icon && (
<i className={`${icon} icon`} aria-hidden="true" />
)

const imageElement =
image &&
(() => {
const raw = typeof image === 'object' ? image : { src: image }
const alt = typeof image === 'object' ? image.alt || '' : ''
const imgProps = Object.fromEntries(
Object.entries(raw).filter(([k]) => k !== 'avatar' && k !== 'alt')
)
return <img {...imgProps} alt={alt} className="ui mini avatar image" />
})()

const labelElement = createShorthand(
'div',
(val) => {
return { children: val }
},
label,
{
defaultProps: { className: 'ui label' },
autoGenerateKey: false,
}
)

const descriptionElement = createShorthand(
'span',
(val) => {
return { children: val }
},
description,
{
defaultProps: { className: 'description' },
autoGenerateKey: false,
}
)

const textElement = createShorthand(
'span',
(val) => ({ children: val }),
(val) => {
return { children: val }
},
childrenUtils.isNil(content) ? text : content,
{ defaultProps: { className: 'text' }, autoGenerateKey: false },
{ defaultProps: { className: 'text' }, autoGenerateKey: false }
)

return (
<ElementType {...rest} {...ariaOptions} className={classes} onClick={handleClick} ref={ref}>
<ElementType
{...rest}
{...ariaOptions}
className={classes}
onClick={handleClick}
ref={ref}
>
{imageElement}
{iconElement}
{flagElement}
Expand All @@ -93,64 +138,11 @@ const DropdownItem = React.forwardRef(function (props, ref) {
{textElement}
</ElementType>
)
})

DropdownItem.displayName = 'DropdownItem'
DropdownItem.propTypes = {
/** An element type to render as (string or function). */
as: PropTypes.elementType,

/** Style as the currently chosen item. */
active: PropTypes.bool,

/** Primary content. */
children: PropTypes.node,

/** Additional classes. */
className: PropTypes.string,

/** Shorthand for primary content. */
content: customPropTypes.contentShorthand,

/** Additional text with less emphasis. */
description: customPropTypes.itemShorthand,

/** A dropdown item can be disabled. */
disabled: PropTypes.bool,

/** Shorthand for Flag. */
flag: customPropTypes.itemShorthand,

/** Shorthand for Icon. */
icon: customPropTypes.itemShorthand,

/** Shorthand for Image. */
image: customPropTypes.itemShorthand,

/** Shorthand for Label. */
label: customPropTypes.itemShorthand,

/**
* Called on click.
*
* @param {SyntheticEvent} event - React's original SyntheticEvent.
* @param {object} data - All props.
*/
onClick: PropTypes.func,

/**
* The item currently selected by keyboard shortcut.
* This is not the active item.
*/
selected: PropTypes.bool,

/** Display text. */
text: customPropTypes.contentShorthand,

/** Stored value. */
value: PropTypes.oneOfType([PropTypes.bool, PropTypes.number, PropTypes.string]),
}

DropdownItem.create = createShorthandFactory(DropdownItem, (opts) => opts)
DropdownItem.displayName = 'DropdownItem'
DropdownItem.create = createShorthandFactory(DropdownItem, (opts) => {
return opts
})

export default DropdownItem
Loading