@talend/react-components
Version:
Set of react components.
298 lines (294 loc) • 9.37 kB
JavaScript
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
import PropTypes from 'prop-types';
import { Component, createElement as _createElement } from 'react';
import classNames from 'classnames';
import TooltipTrigger from '../../TooltipTrigger';
import { Action } from '../../Actions';
import Icon from '../../Icon';
import Badge from '../../Badge';
import css from './TreeViewItem.module.scss';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
const BASE_PADDING = 30;
const CARET_WIDTH = 12;
const PADDING = 20;
/**
* return the default open or closed folder icon if non is specified on item
* or if it is specified return the specified icon with `-closed` append if not opened
* @param {String} iconName - icon name
* @param {Boolean} isOpened - state of the item
* @return {String}
*/
export function getItemIcon(iconName = 'talend-folder', isOpened) {
return isOpened ? iconName : `${iconName}-closed`;
}
/**
* Internal: you should not use it
* Instantiate an icon based on the icon config
*
* @param icon The icon name of the Icon props
* @param isOpened if the treeview is opened
*/
function TreeViewIcon({
icon,
isOpened
}) {
if (typeof icon === 'object') {
return icon.tooltipLabel ? /*#__PURE__*/_jsx(TooltipTrigger, {
label: icon.tooltipLabel,
tooltipPlacement: icon.tooltipPlacement || 'top',
children: /*#__PURE__*/_jsx("span", {
children: /*#__PURE__*/_jsx(Icon, {
name: icon.name,
className: classNames(css['tc-treeview-img'], icon.className)
})
})
}) : /*#__PURE__*/_jsx(Icon, {
...icon,
className: classNames(css['tc-treeview-img'], icon.className)
});
}
return /*#__PURE__*/_jsx(Icon, {
name: getItemIcon(icon, isOpened),
className: classNames(css['tc-treeview-folder'])
});
}
TreeViewIcon.propTypes = {
icon: PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.shape(Icon.propTypes)]),
isOpened: PropTypes.bool
};
/**
* Internal: you should not use it
* Single item of TreeView component
*
* @param id, for qa purposes
* @param item required, item to display
* item.actions optional, array with actions' to be displayed meta-info
* @param onSelect required, callback function to trigger once item was clicked
* @param onClick required, callback function to trigger once item was clicked
*
* @returns XML, jsx to display
*/
class TreeViewItem extends Component {
constructor(props) {
super(props);
this.renderIconAction = this.renderIconAction.bind(this);
this.renderTreeViewChildren = this.renderTreeViewChildren.bind(this);
this.onMouseLeave = this.onMouseLeave.bind(this);
this.onMouseEnter = this.onMouseEnter.bind(this);
this.state = {
hovered: false
};
}
onMouseEnter() {
this.setState({
hovered: true
});
}
onMouseLeave() {
this.setState({
hovered: false
});
}
getTabIndex() {
let shouldBeFocusable;
if (this.props.selectedId === undefined) {
shouldBeFocusable = this.props.level === 1 && this.props.index === 1;
} else {
shouldBeFocusable = this.isSelected();
}
return shouldBeFocusable ? 0 : -1;
}
hasChildren() {
return this.props.item.children && this.props.item.children.length;
}
isSelected() {
const {
item,
selectedId
} = this.props;
if (selectedId === undefined) {
return false;
}
if (Array.isArray(selectedId)) {
return selectedId.includes(item.id);
}
return item.id === selectedId;
}
isOpened() {
const {
children = [],
isOpened = false
} = this.props.item;
if (!children.length) {
return undefined;
}
return isOpened;
}
renderTreeViewChildren() {
if (!this.isOpened()) {
return null;
}
const {
children
} = this.props.item;
return /*#__PURE__*/_jsx("ul", {
role: "group",
className: css['tc-treeview-ul'],
children: children.map((child, i) => /*#__PURE__*/_jsx(TreeViewItem, {
id: this.props.id && `${this.props.id}-${i}`,
item: child,
siblings: children,
onKeyDown: this.props.onKeyDown,
onSelect: this.props.onSelect,
onToggle: this.props.onToggle,
index: i + 1,
selectedId: this.props.selectedId,
level: this.props.level + 1
}, i))
}, "children");
}
renderIconAction({
action,
id,
...actionProps
}) {
let safeId = id;
if (!id && this.props.id) {
safeId = `${this.props.id}-${actionProps.icon}`;
}
return /*#__PURE__*/_createElement(Action, {
...actionProps,
onClick: event => {
event.stopPropagation();
action(this.props.item);
},
tooltipPlacement: "right",
hideLabel: true,
key: actionProps.label,
id: safeId,
link: true
});
}
render() {
const {
id,
index,
item,
level,
onKeyDown,
onSelect,
onToggle,
siblings
} = this.props;
const {
isOpened = false,
hidden,
name,
children = [],
showCounter,
actions,
icon,
counter = children.length,
disabled,
className
} = item;
const paddingLeft = `${(level - 1) * (PADDING + CARET_WIDTH) + BASE_PADDING}px`;
const showOpenedFolder = !!(children.length && (isOpened || this.state.hovered));
return /*#__PURE__*/_jsxs("li", {
// eslint-disable-line jsx-a11y/no-static-element-interactions
id: id,
role: "treeitem",
tabIndex: this.getTabIndex(),
"aria-expanded": this.isOpened(),
"aria-level": level,
"aria-posinset": index,
"aria-setsize": siblings.length,
"aria-selected": this.isSelected(),
"aria-disabled": disabled,
className: classNames('tc-treeview-item-li', css['tc-treeview-li'], className),
onClick: e => {
e.stopPropagation();
return !disabled && onSelect(e, item);
},
onKeyDown: e => !disabled && onKeyDown(e, this.containerRef, {
...item,
hasChildren: children.length,
isOpened,
siblings
}),
"data-hidden": hidden,
onMouseEnter: this.onMouseEnter,
onMouseLeave: this.onMouseLeave,
ref: ref => {
this.containerRef = ref;
},
children: [/*#__PURE__*/_jsxs("div", {
className: classNames('tc-treeview-item', css['tc-treeview-item'], {
[css.disabled]: disabled,
disabled
}),
style: {
paddingLeft
},
children: [children.length ? /*#__PURE__*/_jsx(Action, {
className: css['tc-treeview-toggle'],
icon: "talend-caret-down",
iconTransform: isOpened ? undefined : 'rotate-270',
id: id && `${id}-toggle`,
onClick: e => {
e.stopPropagation();
return onToggle(e, item);
},
label: "",
"aria-hidden": true,
tabIndex: "-1",
link: true
}) : null, icon !== false && /*#__PURE__*/_jsx(TreeViewIcon, {
icon: icon,
isOpened: showOpenedFolder
}, "icon"), /*#__PURE__*/_jsx("span", {
className: classNames('tc-treeview-item-name', css['tc-treeview-item-name']),
children: name
}, "label"), /*#__PURE__*/_jsxs("div", {
className: css['tc-treeview-item-ctrl'],
children: [showCounter && /*#__PURE__*/_jsx(Badge, {
label: counter.toString()
}, "badge"), actions && actions.map(this.renderIconAction)]
}, "actions")]
}), this.renderTreeViewChildren()]
});
}
}
_defineProperty(TreeViewItem, "propTypes", {
id: PropTypes.string.isRequired,
index: PropTypes.number.isRequired,
item: PropTypes.shape({
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
name: PropTypes.string.isRequired,
disabled: PropTypes.bool,
isOpened: PropTypes.bool,
className: PropTypes.string,
children: PropTypes.arrayOf(PropTypes.object),
icon: PropTypes.oneOfType([PropTypes.bool, PropTypes.string, PropTypes.object]),
actions: PropTypes.arrayOf(PropTypes.shape({
action: PropTypes.func,
label: PropTypes.string,
icon: PropTypes.string
})),
counter: PropTypes.number,
showCounter: PropTypes.bool
}).isRequired,
siblings: PropTypes.array,
level: PropTypes.number.isRequired,
onKeyDown: PropTypes.func.isRequired,
onToggle: PropTypes.func.isRequired,
onSelect: PropTypes.func.isRequired,
selectedId: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array])
});
_defineProperty(TreeViewItem, "defaultProps", {
level: 1
});
export default TreeViewItem;
//# sourceMappingURL=TreeViewItem.component.js.map