UNPKG

molstar

Version:

A comprehensive macromolecular library.

246 lines 13.6 kB
import { __assign, __extends } from "tslib"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; /** * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal <david.sehnal@gmail.com> * @author Alexander Rose <alexander.rose@weirdbyte.de> */ import * as React from 'react'; import { Button, ControlGroup } from './common'; import { CloseSvg, ArrowDropDownSvg, ArrowRightSvg, CheckSvg } from './icons'; var ActionMenu = /** @class */ (function (_super) { __extends(ActionMenu, _super); function ActionMenu() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.hide = function () { return _this.props.onSelect(void 0); }; return _this; } ActionMenu.prototype.render = function () { var cmd = this.props; var section = _jsx(Section, { items: cmd.items, onSelect: cmd.onSelect, current: cmd.current, multiselect: this.props.multiselect, noOffset: this.props.noOffset, noAccent: this.props.noAccent }, void 0); return _jsxs("div", __assign({ className: "msp-action-menu-options" + (cmd.header ? '' : ' msp-action-menu-options-no-header') }, { children: [cmd.header && _jsx(ControlGroup, __assign({ header: cmd.header, title: cmd.title, initialExpanded: true, hideExpander: true, hideOffset: true, onHeaderClick: this.hide, topRightIcon: CloseSvg }, { children: section }), void 0), !cmd.header && section] }), void 0); }; return ActionMenu; }(React.PureComponent)); export { ActionMenu }; (function (ActionMenu) { function Header(label, options) { return options ? __assign({ kind: 'header', label: label }, options) : { kind: 'header', label: label }; } ActionMenu.Header = Header; function Item(label, value, options) { return __assign({ kind: 'item', label: label, value: value }, options); } ActionMenu.Item = Item; function createItems(xs, params) { var _a = params || {}, label = _a.label, value = _a.value, category = _a.category, selected = _a.selected, icon = _a.icon, addOn = _a.addOn, description = _a.description; var cats = void 0; var items = []; for (var i = 0; i < xs.length; i++) { var x = xs[i]; if ((params === null || params === void 0 ? void 0 : params.filter) && !params.filter(x)) continue; var catName = category === null || category === void 0 ? void 0 : category(x); var l = label ? label(x) : '' + x; var v = value ? value(x) : x; var d = description ? description(x) : typeof x === 'string' ? x : undefined; var cat = void 0; if (!!catName) { if (!cats) cats = new Map(); cat = cats.get(catName); if (!cat) { cat = [ActionMenu.Header(catName, { description: catName })]; cats.set(catName, cat); items.push(cat); } } else { cat = items; } var ao = addOn === null || addOn === void 0 ? void 0 : addOn(x); cat.push({ kind: 'item', label: l, value: v, icon: icon ? icon(x) : void 0, selected: selected ? selected(x) : void 0, addOn: ao, description: d }); } return items; } ActionMenu.createItems = createItems; var _selectOptions = { value: function (o) { return o[0]; }, label: function (o) { return o[1]; }, category: function (o) { return o[2]; } }; function createItemsFromSelectOptions(options, params) { return createItems(options, params ? __assign(__assign({}, _selectOptions), params) : _selectOptions); } ActionMenu.createItemsFromSelectOptions = createItemsFromSelectOptions; function hasSelectedItem(items) { if (isHeader(items)) return false; if (isItem(items)) return !!items.selected; for (var _i = 0, items_1 = items; _i < items_1.length; _i++) { var s = items_1[_i]; var found = hasSelectedItem(s); if (found) return true; } return false; } ActionMenu.hasSelectedItem = hasSelectedItem; function findItem(items, value) { if (isHeader(items)) return; if (isItem(items)) return items.value === value ? items : void 0; for (var _i = 0, items_2 = items; _i < items_2.length; _i++) { var s = items_2[_i]; var found = findItem(s, value); if (found) return found; } } ActionMenu.findItem = findItem; function getFirstItem(items) { if (isHeader(items)) return; if (isItem(items)) return items; for (var _i = 0, items_3 = items; _i < items_3.length; _i++) { var s = items_3[_i]; var found = getFirstItem(s); if (found) return found; } } ActionMenu.getFirstItem = getFirstItem; // export type SelectProps<T> = { // items: Items, // onSelect: (item: Item) => void, // disabled?: boolean, // label?: string, // current?: Item, // style?: React.CSSProperties // } // export class Select<T> extends React.PureComponent<SelectProps<T>, { isExpanded: boolean }> { // state = { isExpanded: false }; // toggleExpanded = () => this.setState({ isExpanded: !this.state.isExpanded }) // onSelect: OnSelect = (item) => { // this.setState({ isExpanded: false }); // if (!item) return; // this.onSelect(item); // } // render() { // const current = this.props.current; // const label = this.props.label || current?.label || ''; // return <div className='msp-action-menu-select' style={this.props.style}> // <ToggleButton disabled={this.props.disabled} style={{ textAlign: 'left' }} className='msp-no-overflow' // label={label} title={label as string} toggle={this.toggleExpanded} isSelected={this.state.isExpanded} /> // {this.state.isExpanded && <ActionMenu items={this.props.items} current={this.props.current} onSelect={this.onSelect} />} // </div> // } // } })(ActionMenu || (ActionMenu = {})); var Section = /** @class */ (function (_super) { __extends(Section, _super); function Section() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.state = Section.createState(_this.props); _this.toggleExpanded = function (e) { _this.setState({ isExpanded: !_this.state.isExpanded }); e.currentTarget.blur(); }; _this.selectAll = function () { var items = collectItems(_this.props.items, []).filter(function (i) { return !i.selected; }); _this.props.onSelect(items); }; _this.selectNone = function () { var items = collectItems(_this.props.items, []).filter(function (i) { return !!i.selected; }); _this.props.onSelect(items); }; return _this; } Section.createState = function (props, isExpanded) { var header = isItems(props.items) && isHeader(props.items[0]) ? props.items[0] : void 0; var hasCurrent = (header === null || header === void 0 ? void 0 : header.isIndependent) ? false : props.multiselect ? ActionMenu.hasSelectedItem(props.items) : (!!props.current && !!ActionMenu.findItem(props.items, props.current.value)) || ActionMenu.hasSelectedItem(props.items); return { header: header, hasCurrent: hasCurrent, isExpanded: hasCurrent || (isExpanded !== null && isExpanded !== void 0 ? isExpanded : !!(header === null || header === void 0 ? void 0 : header.initiallyExpanded)) }; }; Section.prototype.componentDidUpdate = function (prevProps) { if (this.props.items !== prevProps.items || this.props.current !== prevProps.current) { // keep previously expanded section if the header label is the same var isExpanded = (isItems(this.props.items) && isItems(prevProps.items) && isHeader(this.props.items[0]) && isHeader(prevProps.items[0]) && this.props.items[0].label === prevProps.items[0].label) ? this.state.isExpanded : undefined; this.setState(Section.createState(this.props, isExpanded)); } }; Object.defineProperty(Section.prototype, "multiselectHeader", { get: function () { var _a = this.state, header = _a.header, hasCurrent = _a.hasCurrent; return _jsxs("div", __assign({ className: 'msp-flex-row msp-control-group-header' }, { children: [_jsx(Button, __assign({ icon: this.state.isExpanded ? ArrowDropDownSvg : ArrowRightSvg, flex: true, noOverflow: true, onClick: this.toggleExpanded, title: "Click to " + (this.state.isExpanded ? 'collapse' : 'expand') + "." + ((header === null || header === void 0 ? void 0 : header.description) ? " " + (header === null || header === void 0 ? void 0 : header.description) : '') }, { children: hasCurrent ? _jsx("b", { children: header === null || header === void 0 ? void 0 : header.label }, void 0) : header === null || header === void 0 ? void 0 : header.label }), void 0), _jsx(Button, __assign({ icon: CheckSvg, flex: true, onClick: this.selectAll, style: { flex: '0 0 50px', textAlign: 'right' } }, { children: "All" }), void 0), _jsx(Button, __assign({ icon: CloseSvg, flex: true, onClick: this.selectNone, style: { flex: '0 0 50px', textAlign: 'right' } }, { children: "None" }), void 0)] }), void 0); }, enumerable: false, configurable: true }); Object.defineProperty(Section.prototype, "basicHeader", { get: function () { var _a = this.state, header = _a.header, hasCurrent = _a.hasCurrent; return _jsx("div", __assign({ className: 'msp-control-group-header', style: { marginTop: '1px' } }, { children: _jsx(Button, __assign({ noOverflow: true, icon: this.state.isExpanded ? ArrowDropDownSvg : ArrowRightSvg, onClick: this.toggleExpanded, title: "Click to " + (this.state.isExpanded ? 'collapse' : 'expand') + ". " + ((header === null || header === void 0 ? void 0 : header.description) ? header === null || header === void 0 ? void 0 : header.description : '') }, { children: hasCurrent ? _jsx("b", { children: header === null || header === void 0 ? void 0 : header.label }, void 0) : header === null || header === void 0 ? void 0 : header.label }), void 0) }), void 0); }, enumerable: false, configurable: true }); Section.prototype.render = function () { var _this = this; var _a = this.props, items = _a.items, onSelect = _a.onSelect, current = _a.current; if (isHeader(items)) return null; if (isItem(items)) return _jsx(Action, { item: items, onSelect: onSelect, current: current, multiselect: this.props.multiselect }, void 0); var header = this.state.header; return _jsxs(_Fragment, { children: [header && (this.props.multiselect && this.state.isExpanded ? this.multiselectHeader : this.basicHeader), _jsx("div", __assign({ className: this.props.noOffset ? void 0 : this.props.noAccent ? 'msp-control-offset' : 'msp-accent-offset' }, { children: (!header || this.state.isExpanded) && items.map(function (x, i) { if (isHeader(x)) return null; if (isItem(x)) return _jsx(Action, { item: x, onSelect: onSelect, current: current, multiselect: _this.props.multiselect }, i); return _jsx(Section, { items: x, onSelect: onSelect, current: current, multiselect: _this.props.multiselect, noAccent: true }, i); }) }), void 0)] }, void 0); }; return Section; }(React.PureComponent)); var Action = function (_a) { var item = _a.item, onSelect = _a.onSelect, current = _a.current, multiselect = _a.multiselect; var isCurrent = current === item; var style = item.addOn ? { position: 'relative' } : void 0; return _jsxs(Button, __assign({ icon: item.icon, noOverflow: true, className: 'msp-action-menu-button', onClick: function (e) { return onSelect(multiselect ? [item] : item, e); }, disabled: item.disabled, style: style, title: item.description }, { children: [isCurrent || item.selected ? _jsx("b", { children: item.label }, void 0) : item.label, item.addOn] }), void 0); }; function isItems(x) { return !!x && Array.isArray(x); } function isItem(x) { var v = x; return v && v.kind === 'item'; } function isHeader(x) { var v = x; return v && v.kind === 'header'; } function collectItems(items, target) { if (isHeader(items)) return target; if (isItem(items)) { target.push(items); return target; } for (var _i = 0, items_4 = items; _i < items_4.length; _i++) { var i = items_4[_i]; collectItems(i, target); } return target; } //# sourceMappingURL=action-menu.js.map