import React, {ChangeEventHandler, DOMAttributes} from "react"; import {BPComponentProps, UiConfigRendererContextType} from "./BPComponent"; import { Button, Checkbox, Collapse, Divider, Icon, IconName, Intent, MaybeElement, Menu, MenuItem, Popover } from "@blueprintjs/core"; import {ConfigObject} from "../ConfigObject"; import {PanelActions} from "@blueprintjs/core/lib/esm/components/panel-stack2/panelTypes"; import {getOrCall, safeSetProperty} from 'ts-browser-helpers' import {BPContainerComponent, BPContainerComponentState, BPContainerComponentProps} from './BPContainerComponent' import classNames from "classnames"; import {Classes} from "@blueprintjs/core/src/common"; import {AnimationStates} from "@blueprintjs/core/lib/esm/components/collapse/collapse"; export type BPFolderComponentState = BPContainerComponentState & { } export type BPFolderComponentProps = BPContainerComponentProps & { icon?: IconName | MaybeElement } export class BPFolderComponent extends BPContainerComponent { constructor(props: BPComponentProps&PanelActions&BPFolderComponentProps, context: UiConfigRendererContextType) { super(props, context, {children: [], expanded: false, label: 'Folder'}); } render() { const { icon, config, level, filter, ...props } = this.props const setExpanded = (e: boolean) => { if (e === this.state.expanded) return this.setState({...this.state, expanded: e}) safeSetProperty(config, "expanded", e, true) // if (e) this.state.children.forEach(c => Array.isArray(c) ? null : c.uiRefresh?.("postFrame", true, 1)) // todo: handle array and functions } let children = this.state.children const enabledToggle = children[0] && this.context.methods.getBinding(children[0])[1] === 'enabled' ? children[0] : undefined if(enabledToggle) children = children.slice(1) const ctxMenuBtns = children.filter(c=>{ return c.type === 'button' && c.tags?.includes('context-menu') }) let endIcon: MaybeElement = undefined if(ctxMenuBtns.length > 0){ children = children.filter(c=>!ctxMenuBtns.includes(c)) endIcon = ( } placement="bottom-end" > */} {hasEnabled && e.stopPropagation()} />} {props.endIcon &&
{props.endIcon}
} {props.children} ) } export class Collapse2 extends Collapse{ private contentsRefHandler2 = (el: HTMLElement | null) => { // @ts-ignore this.contents = el; // @ts-ignore if (this.contents != null) { // @ts-ignore const height = this.contents.clientHeight; this.setState({ animationState: this.props.isOpen ? AnimationStates.OPEN : AnimationStates.CLOSED, height: height === 0 ? undefined : `${height}px`, heightWhenOpen: height === 0 ? undefined : height, }); } }; public render() { const isContentVisible = this.state.animationState !== AnimationStates.CLOSED; const shouldRenderChildren = isContentVisible || this.props.keepChildrenMounted; // const displayWithTransform = isContentVisible && this.state.animationState !== AnimationStates.CLOSING; const isAutoHeight = this.state.height === "auto"; const containerStyle = { height: isContentVisible ? this.state.height : undefined, overflowY: isAutoHeight ? "visible" : undefined, // transitions don't work with height: auto transition: isAutoHeight ? "none" : undefined, }; const contentsStyle = { // only use heightWhenOpen while closing // transform: displayWithTransform ? "translateY(0)" : `translateY(-${this.state.heightWhenOpen}px)`, // transitions don't work with height: auto // transition: isAutoHeight ? "none" : undefined, display: "block", // for opacity animation visibility: isContentVisible ? "visible" : "hidden", opacity: this.state.animationState === AnimationStates.CLOSING || this.state.animationState === AnimationStates.CLOSED ? 0.1 : 1, } as React.CSSProperties; // if(isContentVisible && !isAutoHeight && this.state.heightWhenOpen && this.state.height){ // const h = parseInt(this.state.height) // contentsStyle.opacity = h / this.state.heightWhenOpen; // console.log(contentsStyle.opacity) // } return React.createElement( this.props.component!, { className: classNames(Classes.COLLAPSE, this.props.className), style: containerStyle, },
{shouldRenderChildren ? this.props.children : null}
, ); } } export const ContextMenu: React.FC<{ buttons: any[]; context: UiConfigRendererContextType; }> = ({ buttons, context }) => { return ( {buttons.map((btn, i) => { const getProps = ()=>{ // todo use UiConfigMethods.getBaseProps const hidden = getOrCall(btn.hidden) ?? false const disabled = getOrCall(btn.disabled) ?? false const readOnly = getOrCall(btn.readOnly) ?? false return { hidden, disabled, readOnly } } const props = getProps() return props.hidden ? null : ( { e.stopPropagation(); const {hidden, disabled, readOnly} = getProps() if (hidden || disabled || readOnly) return; // todo loading state for promise context.methods.clickButton(btn, { args: [e] }); }} /> ); })} ); };