feat(core-blocks): CB-341 Tab Container's disabled & hidden states

This commit is contained in:
Wroud
2020-11-02 00:23:57 +03:00
parent 25ad09aac9
commit ecb53493a7
7 changed files with 28 additions and 7 deletions
@@ -23,6 +23,7 @@ interface Props<T = Record<string, any>> {
component?: React.FC<TabProps & T>;
className?: string;
style?: DynamicStyle[] | DynamicStyle;
disabled?: boolean;
onOpen?: (tabId: string) => void;
onClose?: (tabId: string) => void;
}
@@ -34,6 +35,7 @@ export function TabDefault<T = Record<string, any>>({
component,
className,
style,
disabled,
onOpen,
onClose,
...rest
@@ -48,6 +50,7 @@ export function TabDefault<T = Record<string, any>>({
className={className}
{...(rest as unknown as T)}
style={style}
disabled={disabled}
onOpen={onOpen}
onClose={onClose}
/>
@@ -55,7 +58,7 @@ export function TabDefault<T = Record<string, any>>({
}
return styled(styles)(
<Tab tabId={tabId} className={className} style={style} onOpen={onOpen} onClose={onClose}>
<Tab tabId={tabId} className={className} style={style} disabled={disabled} onOpen={onOpen} onClose={onClose}>
{icon && <TabIcon icon={icon} />}
{name && <TabTitle><Translate token={name} /></TabTitle>}
</Tab>
@@ -16,11 +16,13 @@ import { TabsContext } from './TabsContext';
type Props = React.PropsWithChildren<Omit<TabListOptions, keyof TabStateReturn>> & {
style?: DynamicStyle[] | DynamicStyle;
childrenFirst?: boolean;
};
export const TabList: React.FC<Props> = function TabList({
style,
children,
childrenFirst,
...props
}) {
const state = useContext(TabsContext);
@@ -30,9 +32,11 @@ export const TabList: React.FC<Props> = function TabList({
}
if (state.container) {
const displayed = state.container.getDisplayed(state.props);
return (
<BaseTabList {...props} {...state.state}>
{state.container.tabInfoList.map(tabInfo => (
{childrenFirst && children}
{displayed.map(tabInfo => (
<TabDefault
key={tabInfo.key}
tabId={tabInfo.key}
@@ -41,11 +45,12 @@ export const TabList: React.FC<Props> = function TabList({
component={tabInfo.tab?.()}
{...state.props}
style={style}
disabled={tabInfo.isDisabled?.(tabInfo.key, state.props)}
onOpen={tabInfo.onOpen}
onClose={tabInfo.onClose}
/>
))}
{children}
{!childrenFirst && children}
</BaseTabList>
);
}
@@ -39,9 +39,11 @@ export const TabPanelList: React.FC<Props> = function TabPanelList({
return <Panel tabId={tabInfo.key} {...state?.props} />;
}
const displayed = state.container.getDisplayed(state.props);
return styled(styles)(
<>
{state.container.tabInfoList.map(tabInfo => (
{displayed.map(tabInfo => (
<TabPanel
key={tabInfo.key}
tabId={tabInfo.key}
@@ -20,6 +20,9 @@ export interface ITabInfoOptions<TProps = Record<string, any>, TOptions extends
tab?: () => React.FC<TabProps & TProps>;
panel: () => React.FC<{ tabId: string } & TProps>;
isHidden?: (tabId: string, props?: TProps) => boolean;
isDisabled?: (tabId: string, props?: TProps) => boolean;
onClose?: (tabId: string) => void;
onOpen?: (tabId: string) => void;
}
@@ -36,13 +39,18 @@ export class TabsContainer<TProps = Record<string, any>, TOptions extends Record
readonly tabInfoMap: Map<string, ITabInfo<TProps, TOptions>>;
@computed get tabInfoList(): Array<ITabInfo<TProps, TOptions>> {
return Array.from(this.tabInfoMap.values()).sort((a, b) => a.order - b.order);
return Array.from(this.tabInfoMap.values())
.sort((a, b) => a.order - b.order);
}
constructor() {
this.tabInfoMap = new Map();
}
getDisplayed(props?: TProps): Array<ITabInfo<TProps, TOptions>> {
return this.tabInfoList.filter(tabInfo => !tabInfo.isHidden?.(tabInfo.key, props));
}
add(tabInfo: ITabInfoOptions<TProps, TOptions>): void {
if (this.tabInfoMap.has(tabInfo.key)) {
throw new Error('Tab with same key already exists');
@@ -33,7 +33,7 @@ export function TabsState<T = Record<string, any>>({
onChange,
...rest
}: Props<T>): React.ReactElement | null {
if (!currentTabId && container && container.tabInfoList.length > 0) {
if (!selectedId && !currentTabId && container && container.tabInfoList.length > 0) {
currentTabId = container.tabInfoList[0].key;
}
@@ -62,7 +62,8 @@ import {
CreateConnectionService,
ConnectionManualService,
ConnectionSearchService,
CreateConnectionBaseBootstrap
CreateConnectionBaseBootstrap,
ConnectionFormService
} from '@cloudbeaver/core-connections';
import { PluginManifest } from '@cloudbeaver/core-di';
import { CommonDialogService, ContextMenuService } from '@cloudbeaver/core-dialogs';
@@ -124,6 +125,7 @@ export const coreManifest: PluginManifest = {
SessionExpireService,
SessionExpiredDialogService,
ConnectionsLocaleService,
ConnectionFormService,
ConnectionDialogsService,
ConnectionSchemaManagerService,
ConnectionInfoResource,
@@ -1,3 +1,4 @@
export * from './Administration/Connections/ConnectionForm/ConnectionFormService';
export * from './Administration/Connections/ConnectionsAdministration';
export * from './Administration/Connections/ConnectionsAdministrationNavService';
export * from './Administration/Connections/ConnectionsAdministrationService';