Skip to content
This repository has been archived by the owner on Mar 1, 2024. It is now read-only.

Commit

Permalink
Merge pull request #251 from MrJarv1s/TagEvents
Browse files Browse the repository at this point in the history
Tag and Icon Event Handling
  • Loading branch information
jonthomp authored Jun 29, 2018
2 parents af28b80 + f1f860c commit fa84100
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 65 deletions.
26 changes: 24 additions & 2 deletions src/components/Icon/Icon.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
import * as React from "react";
import cn from "classnames";

import type { MouseEvents, PointerEvents, FocusEvents } from "../../";

type Props = {|
...MouseEvents,
...PointerEvents,
...FocusEvents,
+className?: string,
/**
* Should this icon be rendered within an <a> tag
Expand Down Expand Up @@ -40,6 +45,13 @@ function Icon({
isAriaHidden,
payment,
flag,
onClick,
onMouseEnter,
onMouseLeave,
onPointerEnter,
onPointerLeave,
onFocus,
onBlur,
}: Props): React.Node {
const prefix = (payment && "payment") || (flag && "flag") || prefixFromProps;
const classes = cn(
Expand All @@ -55,10 +67,20 @@ function Icon({
}
: null;

const eventProps = {
onClick,
onMouseEnter,
onMouseLeave,
onPointerEnter,
onPointerLeave,
onFocus,
onBlur,
};

return !link ? (
<i className={classes} />
<i className={classes} {...eventProps} />
) : (
<a className="icon" {...extraProps}>
<a className="icon" {...extraProps} {...eventProps}>
<i className={classes} />
</a>
);
Expand Down
170 changes: 113 additions & 57 deletions src/components/Tag/Tag.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,23 @@ import cn from "classnames";
import TagList from "./TagList.react";
import TagAddOn from "./TagAddOn.react";

import type { MouseEvents, PointerEvents, FocusEvents } from "../../";

type PropsForAll = {|
...MouseEvents,
...PointerEvents,
...FocusEvents,
+children?: React.Node,
+className?: string,
+rounded?: boolean,
+color?: string,
+avatar?: string,
+remove?: boolean,
+onRemoveClick?: Function,
+addOn?: React.Node,
+addOnIcon?: string,
+addOnColor?: string,
+onAddOnClick?: Function,
|};

type DefaultProps = {|
Expand All @@ -35,69 +42,118 @@ type ReactRouterProps = {|

type Props = DefaultProps | LinkComponentProps | ReactRouterProps;

function Tag(props: Props): React.Node {
const {
children,
className,
rounded,
color = "",
avatar,
remove,
addOn,
addOnIcon,
addOnColor,
} = props;
const classes = cn(
{
tag: true,
expanded: true,
"tag-rounded": rounded,
[`tag-${color}`]: color,
},
className
);
const childrenForAll = (
<React.Fragment>
{avatar && (
<span
class="tag-avatar avatar"
style={{ backgroundImage: `url(${avatar})` }}
/>
)}
{children}
{(addOn || addOnIcon) && (
<TagAddOn icon={addOnIcon} color={addOnColor}>
{addOn}
</TagAddOn>
)}
{remove && <TagAddOn link icon="x" />}
</React.Fragment>
);

if (props.RootComponent) {
const { RootComponent: Component, to } = props;
return (
<Component className={classes} to={to}>
{childrenForAll}
</Component>
type State = {|
isDeleted: boolean,
|};

class Tag extends React.Component<Props, State> {
state = {
isDeleted: false,
};

static List = TagList;
static AddOn = TagAddOn;

handleOnRemoveClick = (): void => {
this.setState(s => ({
isDeleted: true,
}));
};

render(): React.Node {
const {
children,
className,
rounded,
color = "",
avatar,
remove,
addOn,
addOnIcon,
addOnColor,
onClick,
onMouseEnter,
onMouseLeave,
onPointerEnter,
onPointerLeave,
onFocus,
onBlur,
onRemoveClick,
onAddOnClick,
} = this.props;

const classes = cn(
{
tag: true,
expanded: true,
"tag-rounded": rounded,
[`tag-${color}`]: color,
},
className
);
}

if (props.link) {
const { href } = props;
const eventProps = {
onClick,
onMouseEnter,
onMouseLeave,
onPointerEnter,
onPointerLeave,
onFocus,
onBlur,
};

if (this.state.isDeleted) {
return null;
}

const childrenForAll = (
<React.Fragment>
{avatar && (
<span
class="tag-avatar avatar"
style={{ backgroundImage: `url(${avatar})` }}
/>
)}
{children}
{(addOn || addOnIcon) && (
<TagAddOn icon={addOnIcon} color={addOnColor} onClick={onAddOnClick}>
{addOn}
</TagAddOn>
)}
{remove && onRemoveClick ? (
<TagAddOn onClick={onRemoveClick} link icon="x" />
) : (
remove && (
<TagAddOn onClick={this.handleOnRemoveClick} link icon="x" />
)
)}
</React.Fragment>
);

if (this.props.RootComponent) {
const { to } = this.props;
return (
<React.Component className={classes} to={to} {...eventProps}>
{childrenForAll}
</React.Component>
);
}

if (this.props.link) {
const { href } = this.props;
return (
<a className={classes} href={href} {...eventProps}>
{childrenForAll}
</a>
);
}

return (
<a className={classes} href={href}>
<span className={classes} {...eventProps}>
{childrenForAll}
</a>
</span>
);
}

return <span className={classes}>{childrenForAll}</span>;
}

Tag.displayName = "Tag";

Tag.List = TagList;
Tag.AddOn = TagAddOn;

export default Tag;
47 changes: 41 additions & 6 deletions src/components/Tag/TagAddOn.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import * as React from "react";
import cn from "classnames";
import { Icon } from "../";

import type { MouseEvents, PointerEvents, FocusEvents } from "../../";

type PropsForAll = {|
...MouseEvents,
...PointerEvents,
...FocusEvents,
+children?: React.Node,
+className?: string,
+icon?: string,
Expand All @@ -17,7 +22,6 @@ type PropsForLink = {|
...PropsForAll,
link: true,
+href?: string,
+onClick?: (event: SyntheticMouseEvent<HTMLLinkElement>) => mixed,
|};

type PropsForReactRouter = {|
Expand All @@ -29,9 +33,32 @@ type PropsForReactRouter = {|
type Props = DefaultProps | PropsForLink | PropsForReactRouter;

function TagAddOn(props: Props): React.Node {
const { children, className, icon, color = "" } = props;
const {
children,
className,
icon,
color = "",
onClick,
onMouseEnter,
onMouseLeave,
onPointerEnter,
onPointerLeave,
onFocus,
onBlur,
} = props;

const classes = cn("tag-addon", { [`tag-${color}`]: color }, className);

const eventProps = {
onClick,
onMouseEnter,
onMouseLeave,
onPointerEnter,
onPointerLeave,
onFocus,
onBlur,
};

const childrenForAll = (
<React.Fragment>
{icon && <Icon name={icon} />}
Expand All @@ -40,20 +67,28 @@ function TagAddOn(props: Props): React.Node {
);

if (props.link) {
const { href, onClick } = props;
const { href } = props;
return (
<a className={classes} href={href} onClick={onClick}>
<a className={classes} href={href} {...eventProps}>
{childrenForAll}
</a>
);
}

if (props.RootComponent) {
const { RootComponent: Component, to } = props;
return <Component to={to}>{childrenForAll}</Component>;
return (
<Component to={to} {...eventProps}>
{childrenForAll}
</Component>
);
}

return <span className={classes}>{childrenForAll}</span>;
return (
<span className={classes} {...eventProps}>
{childrenForAll}
</span>
);
}

TagAddOn.displayName = "Tag.AddOn";
Expand Down

0 comments on commit fa84100

Please sign in to comment.