dbl-components
Version:
Framework based on bootstrap 5
156 lines (140 loc) • 4.47 kB
JavaScript
import PropTypes from "prop-types";
import { resolveRefs, eventHandler } from "dbl-utils";
import { ptClasses } from "../prop-types";
import JsonRender from "../json-render";
import Component from "../component";
export default class ActionComponent extends Component {
static jsClass = 'Action';
static propTypes = {
...Component.propTypes,
classButton: PropTypes.bool,
close: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
disabled: PropTypes.bool,
form: PropTypes.string,
icon: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
iconClasses: ptClasses,
iconProps: PropTypes.object,
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
open: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
status: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
statusClasses: PropTypes.objectOf(ptClasses),
statusIcons: PropTypes.objectOf(PropTypes.string),
to: PropTypes.string,
type: PropTypes.string,
value: PropTypes.any,
justifyContent: PropTypes.oneOf(['start', 'center', 'end'])
}
static defaultProps = {
...Component.defaultProps,
type: 'button',
classButton: true,
open: false,
close: false,
statusIcons: {
success: 'check',
error: 'x',
warning: 'exclamation',
loading: 'spinner'
},
statusClasses: {
success: 'text-bold text-success',
error: 'text-bold text-danger',
warning: 'text-bold text-warning',
loading: 'spinner'
},
iconClasses: '',
iconProps: {},
justifyContent: 'center'
};
static schemaContent = {
actionIcon: {
name: ["$props/name", "actionIcon"],
component: "Icons",
icon: "$props/icon",
style: {
width: "var(--bs-btn-font-size)"
}
},
actionContent: {
name: ["$props/name", "actionContent"],
tag: 'span'
},
actionStatus: {
name: ["$props/name", "actionStatus"],
component: 'Icons',
icon: "$state/status",
classes: "float-end"
}
};
tag = 'button';
classes = 'd-inline-flex align-items-center';
constructor(props) {
super(props);
this.classes += ' justify-content-' + props.justifyContent;
this.state.localClasses = props.classButton ? 'btn' : '';
this.onClick = this.onClick.bind(this);
this.eventHandlers.onClick = this.onClick;
this.schema = resolveRefs(ActionComponent.schemaContent, { props });
this.jsonRender = new JsonRender({
...props
}, this.mutations.bind(this));
}
onClick(e) {
e.stopPropagation();
const { navigate, to, type, open, close, value, name, id } = this.props;
if (type === 'link' && to) {
navigate(to);
}
if (open) {
eventHandler.dispatch('update.' + open, { open: true });
}
if (close) {
eventHandler.dispatch('update.' + close, { open: false });
}
let dispatch = name;
if (value || id) {
dispatch = { [name]: value, id };
}
eventHandler.dispatch(name, dispatch);
}
get componentProps() {
const { type: prevType, disabled, form, _props = {} } = this.props;
const type = prevType === 'link' ? 'button' : prevType;
return { type, disabled, ..._props, form: form ? form + '-form' : undefined };
}
content() {
return this.jsonRender.buildContent(this.schema);
}
mutations(name, config) {
const search = name.replace(this.props.name + '-', '');
switch (search) {
case "actionIcon": {
const cn = [];
if (this.props.children) cn.push('me-2');
return {
...this.props.iconProps,
active: !!this.props.icon,
icon: this.props.icon,
classes: [cn, this.props.iconClasses].flat().join(' ')
}
}
case 'actionStatus': {
const classes = [config.classes, this.props.statusClasses[this.props.status]];
if (this.props.icon || this.props.children) classes.push('ms-2');
return {
active: !!this.props.status,
icon: this.props.statusIcons[this.props.status],
classes,
}
}
case "actionContent": {
return {
active: !!this.props.children,
content: this.props.children,
}
}
default:
break;
}
}
}