Skip to content

Commit

Permalink
Refactor #1876
Browse files Browse the repository at this point in the history
  • Loading branch information
mertsincan committed Apr 14, 2021
1 parent fad9ae5 commit 761cad7
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 44 deletions.
18 changes: 13 additions & 5 deletions src/components/button/Button.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,29 @@ declare namespace Button {

type PositionType = 'top' | 'bottom' | 'left' | 'right';

type LoadingIconType = React.ReactNode | ((props: ButtonProps) => React.ReactNode);
type IconType = React.ReactNode | ((options: IconOptions) => React.ReactNode);

interface IconOptions {
className: string;
element: React.ReactNode;
props: ButtonProps;
}

interface LoadingOptions {
icon: LoadingIconType,
position: PositionType
icon: IconType;
position: PositionType;
disabled: boolean;
}

interface ButtonProps extends React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
interface ButtonProps extends Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, 'disabled'> {
label?: string;
icon?: string;
icon?: IconType;
iconPos?: PositionType;
badge?: string;
badgeClassName?: string;
tooltip?: string;
tooltipOptions?: TooltipOptions;
disabled?: boolean;
loading?: boolean;
loadingOptions?: LoadingOptions;
}
Expand Down
96 changes: 65 additions & 31 deletions src/components/button/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,21 @@ export class ButtonComponent extends Component {
tooltip: null,
tooltipOptions: null,
forwardRef: null,
disabled: false,
loading: false,
loadingOptions: null
}

static propTypes = {
label: PropTypes.string,
icon: PropTypes.string,
icon: PropTypes.any,
iconPos: PropTypes.string,
badge: PropTypes.string,
badgeClassName: PropTypes.string,
tooltip: PropTypes.string,
tooltipOptions: PropTypes.object,
forwardRef: PropTypes.any,
disabled: PropTypes.bool,
loading: PropTypes.bool,
loadingOptions: PropTypes.any
};
Expand Down Expand Up @@ -70,6 +72,40 @@ export class ButtonComponent extends Component {
}
}

getOptions(loadingOptions) {
let disabled = this.isDisabled(loadingOptions);
let vertical = this.isVertical(loadingOptions);
let iconOnly = this.isIconOnly(loadingOptions);

return { disabled, vertical, iconOnly };
}

getLoadingOptions() {
if (this.props.loading) {
let defaultOptions = { icon: 'pi pi-spin pi-spinner', position: 'left', disabled: true };
let options = { ...defaultOptions, ...(this.props.loadingOptions || {}) };

return options;
}

return null;
}

isDisabled(loadingOptions) {
return this.props.disabled || (loadingOptions && loadingOptions.disabled);
}

isIconOnly(loadingOptions) {
return !this.props.label && (this.props.icon || (loadingOptions && loadingOptions.icon))
}

isVertical(loadingOptions) {
return this.props.label && (
(this.props.iconPos === 'top' || this.props.iconPos === 'bottom') ||
(loadingOptions && (loadingOptions.position === 'top' || loadingOptions.position === 'bottom'))
);
}

renderTooltip() {
this.tooltip = tip({
target: this.element,
Expand All @@ -79,24 +115,31 @@ export class ButtonComponent extends Component {
}

renderIcon(icon, position) {
let content = null;

if (icon) {
if (typeof icon === 'string') {
let className = classNames(icon, 'p-c', {
'p-button-icon-left': position === 'left' && this.props.label,
'p-button-icon-right': position === 'right' && this.props.label,
'p-button-icon-top': position === 'top' && this.props.label,
'p-button-icon-bottom': position === 'bottom' && this.props.label
});

return (
<span className={className}></span>
);
let iconType = typeof icon;
let className = classNames('p-c', {
[`${icon}`]: iconType === 'string',
'p-button-icon-left': position === 'left' && this.props.label,
'p-button-icon-right': position === 'right' && this.props.label,
'p-button-icon-top': position === 'top' && this.props.label,
'p-button-icon-bottom': position === 'bottom' && this.props.label
});
content = <span className={className}></span>;

if (iconType !== 'string') {
const defaultContentOptions = {
className,
element: content,
props: this.props
};

content = ObjectUtils.getJSXElement(icon, defaultContentOptions);
}

return ObjectUtils.getJSXElement(icon, this.props);
}

return null;
return content;
}

renderLabel() {
Expand All @@ -117,32 +160,23 @@ export class ButtonComponent extends Component {
return null;
}

renderLoadingIcon() {
if (this.props.loading) {
let icon = (this.props.loadingOptions && this.loadingOptions.icon) || 'pi pi-spin pi-spinner';
let position = this.props.loadingOptions && this.props.loadingOptions.position;

return this.renderIcon(icon, position);
}

return null;
}

render() {
let loadingOptions = this.getLoadingOptions();
let { disabled, vertical, iconOnly } = this.getOptions(loadingOptions);
let className = classNames('p-button p-component', this.props.className, {
'p-button-icon-only': this.props.icon && !this.props.label,
'p-button-vertical': (this.props.iconPos === 'top' || this.props.iconPos === 'bottom') && this.label,
'p-disabled': this.props.disabled
'p-button-icon-only': iconOnly,
'p-button-vertical': vertical,
'p-disabled': disabled
});
let loading = this.props.loading && this.renderIcon(loadingOptions.icon, loadingOptions.position);
let icon = this.renderIcon(this.props.icon, this.props.iconPos);
let label = this.renderLabel();
let badge = this.renderBadge();
let loading = this.renderLoadingIcon();

let buttonProps = ObjectUtils.findDiffKeys(this.props, ButtonComponent.defaultProps);

return (
<button ref={(el) => this.getElementRef(el)} {...buttonProps} className={className}>
<button ref={(el) => this.getElementRef(el)} {...buttonProps} className={className} disabled={disabled}>
{loading}
{icon}
{label}
Expand Down
20 changes: 12 additions & 8 deletions src/showcase/button/ButtonDemo.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ export class ButtonDemo extends Component {
super(props)
this.state = {
loading: false,
check: false,
disabled: false
done: false
}
this.onClick = this.onClick.bind(this);

this.onLoadingClick = this.onLoadingClick.bind(this);
}

onClick() {
this.setState({ check: false, loading: true, disabled: true })
onLoadingClick() {
this.setState({ loading: true, done: false });
setTimeout(() => {
this.setState({ loading: false, check: true, disabled: false })
}, 2000)
this.setState({ loading: false, done: true });
}, 2000);
}

render() {
Expand All @@ -32,6 +32,7 @@ export class ButtonDemo extends Component {
<h1>Button</h1>
<p>Button is an extension to standard input element with icons and theming.</p>
</AppInlineHeader>

<AppDemoActions github="button/ButtonDemo.js" />
</div>

Expand All @@ -48,7 +49,10 @@ export class ButtonDemo extends Component {
<Button label="Submit" icon="pi pi-check" iconPos="right" />

<h5>Loading</h5>
<Button label="Submit" disabled={this.state.disabled} onClick={this.onClick} loading={this.state.loading} icon={this.state.check ? 'pi pi-check' : null} iconPos="right" />
<Button loading />
<Button label="Submit" loading />
<Button label="Submit" icon="pi pi-check" loading loadingOptions={{ position: 'right' }} />
<Button label="Submit" icon={this.state.done && 'pi pi-check'} loading={this.state.loading} onClick={this.onLoadingClick} />

<h5>Severities</h5>
<Button label="Primary" />
Expand Down

0 comments on commit 761cad7

Please sign in to comment.