You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.6 KiB
JavaScript

"use strict";
const React = require("react");
const asExpression = require("as-expression");
const defaultStyle = require("./style.css");
const useTheme = require("../../util/themeable");
const ListItemContext = require("../../contexts/list-item");
const comparePath = require("../../util/compare-path");
const useClickTimer = require("../../util/use-click-timer");
function Expander({ expanded, onClick }) {
let { withTheme } = useTheme({ control: "list", defaultStyle });
return (
<div className={withTheme("expander")} onClick={onClick}>
{(expanded === true)
? "▼"
: "▶"}
</div>
);
}
function ExpanderPlaceholder() {
let { withTheme } = useTheme({ control: "list", defaultStyle });
return <div className={withTheme("expanderPlaceholder")} />;
}
module.exports = function ListItem({ label, id, children }) {
let { onClick, onDoubleClick, path, selectedPath } = React.useContext(ListItemContext);
let [ expanded, setExpanded ] = React.useState(true);
let { withTheme } = useTheme({ control: "list", defaultStyle });
let doubleClickTimer = useClickTimer(500);
let depth = path.length;
let indent = depth * 11; // FIXME: Figure out a way to do this with CSS instead, eg. via value exports?
let ownPath = path.concat([ id ]);
let isSelected = comparePath(selectedPath, ownPath);
function handleClick() {
if (doubleClickTimer.click()) {
if (onDoubleClick != null) {
onDoubleClick(ownPath);
} else if (children != null) {
// TODO: Check whether we really only want to do this when no onDoubleClick handler is specified, ie. only as a default behaviour
toggleExpanded();
}
}
}
function handleMouseDown() {
if (doubleClickTimer.mouseDown()) {
onClick(ownPath);
}
}
function toggleExpanded() {
setExpanded((expanded) => !expanded);
}
let style = {
paddingLeft: `${indent}px`
};
return (
<React.Fragment>
{/* FIXME: item_selected capitalization */}
<div className={withTheme(["item", { item_selected: isSelected }])} style={style} onMouseDown={handleMouseDown} onClick={handleClick}>
{(children != null)
? <Expander expanded={expanded} onClick={toggleExpanded} />
: <ExpanderPlaceholder />}
<div className={withTheme("label")}>
{label}
</div>
</div>
{(children != null && expanded === true)
? asExpression(() => {
let itemContext = {
path: ownPath,
selectedPath: selectedPath,
onClick: onClick,
onDoubleClick: onDoubleClick
};
return (
<ListItemContext.Provider value={itemContext}>
{children}
</ListItemContext.Provider>
);
})
: null}
</React.Fragment>
);
};