From 247888ae38e7f5451d7e54cd5aac27391f361c78 Mon Sep 17 00:00:00 2001 From: Lucas Di Pentima Date: Fri, 8 Oct 2021 15:49:15 -0300 Subject: [PATCH] 18128: Adds Multi Panel View (MPV for short) component family. MPVContainer aims to be a drop-in replacement for that will handle its children's visibility and pass to them additional props so they can optionally offer UI elements to the user. MPVPanelContent aims to be a drop-in replacement for in case there's a need for special layout inside a container. This component will forward the additional props to its children. Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima --- src/components/icon/icon.tsx | 1 + .../multi-panel-view/multi-panel-view.tsx | 104 ++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 src/components/multi-panel-view/multi-panel-view.tsx diff --git a/src/components/icon/icon.tsx b/src/components/icon/icon.tsx index 26ce4fea..05b94f7e 100644 --- a/src/components/icon/icon.tsx +++ b/src/components/icon/icon.tsx @@ -112,6 +112,7 @@ export const FileIcon: IconType = (props) => ; export const HelpIcon: IconType = (props) => ; export const HelpOutlineIcon: IconType = (props) => ; export const ImportContactsIcon: IconType = (props) => ; +export const InfoIcon: IconType = (props) => ; export const InputIcon: IconType = (props) => ; export const KeyIcon: IconType = (props) => ; export const LogIcon: IconType = (props) => ; diff --git a/src/components/multi-panel-view/multi-panel-view.tsx b/src/components/multi-panel-view/multi-panel-view.tsx new file mode 100644 index 00000000..54bea41d --- /dev/null +++ b/src/components/multi-panel-view/multi-panel-view.tsx @@ -0,0 +1,104 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +import React, { ReactElement, ReactNode, useState } from 'react'; +import { Button, Grid } from "@material-ui/core"; +import { GridProps } from '@material-ui/core/Grid'; +import { isArray } from 'lodash'; +import { DefaultView } from 'components/default-view/default-view'; +import { InfoIcon } from 'components/icon/icon'; +import { ReactNodeArray } from 'prop-types'; + +interface MPVHideablePanelDataProps { + name: string; + visible: boolean; + children: ReactNode; +} + +interface MPVHideablePanelActionProps { + doHidePanel: () => void; +} + +type MPVPanelProps = MPVHideablePanelDataProps & MPVHideablePanelActionProps; + +const MPVHideablePanel = ({doHidePanel, name, visible, ...props}: MPVPanelProps) => + visible + ? <> + {React.cloneElement((props.children as ReactElement), { doHidePanel, panelName: name })} + + : null; + +interface MPVPanelContentDataProps { + panelName?: string; + children: ReactElement; +} + +interface MPVPanelContentActionProps { + doHidePanel?: () => void; +} + +type MPVPanelContentProps = MPVPanelContentDataProps & MPVPanelContentActionProps & GridProps; + +// Grid item compatible component for layout and MPV props passing +export const MPVPanelContent = ({doHidePanel, panelName, ...props}: MPVPanelContentProps) => + + {React.cloneElement(props.children, { doHidePanel, panelName })} + ; + +export interface MPVContainerDataProps { + panelNames?: string[]; +} + +type MPVContainerProps = MPVContainerDataProps & GridProps; + +// Grid container compatible component that also handles panel toggling. +export const MPVContainer = ({children, panelNames, ...props}: MPVContainerProps) => { + if (children === undefined || children === null || children === {}) { + children = []; + } else if (!isArray(children)) { + children = [children]; + } + const visibility = (children as ReactNodeArray).map(() => true); + const [panelVisibility, setPanelVisibility] = useState(visibility); + + let panels: JSX.Element[] = []; + let toggles: JSX.Element[] = []; + + if (isArray(children)) { + for (let idx = 0; idx < children.length; idx++) { + const toggleFn = (idx: number) => () => { + setPanelVisibility([ + ...panelVisibility.slice(0, idx), + !panelVisibility[idx], + ...panelVisibility.slice(idx+1) + ]) + }; + const toggleLabel = panelVisibility[idx] ? 'Hide' : 'Show' + const panelName = panelNames === undefined + ? `Panel ${idx+1}` + : panelNames[idx] || `Panel ${idx+1}`; + + + toggles = [ + ...toggles, + + ]; + + const aPanel = + + {children[idx]} + ; + panels = [...panels, aPanel]; + }; + }; + + return + { toggles } + { panelVisibility.includes(true) + ? panels + : + + } + ; +}; -- 2.30.2