Merge branch 'release' of https://github.com/appsmithorg/appsmith into release
This commit is contained in:
commit
b8d1d56310
|
|
@ -1,108 +1,3 @@
|
|||
import React from "react";
|
||||
import { Tab, Tabs, TabList, TabPanel } from "react-tabs";
|
||||
import "react-tabs/style/react-tabs.css";
|
||||
import styled from "styled-components";
|
||||
import { Icon, IconName } from "./Icon";
|
||||
import { Size } from "./Button";
|
||||
import { CommonComponentProps } from "./common";
|
||||
|
||||
const TabsWrapper = styled.div<{ shouldOverflow?: boolean }>`
|
||||
font-family: ${props => props.theme.fonts.main};
|
||||
user-select: none;
|
||||
border-radius: 0px;
|
||||
height: 100%;
|
||||
span {
|
||||
margin-right: ${props => props.theme.spaces[2] - 1}px;
|
||||
}
|
||||
.react-tabs {
|
||||
height: 100%;
|
||||
}
|
||||
.react-tabs__tab-panel {
|
||||
height: calc(100% - 32px);
|
||||
overflow: scroll;
|
||||
}
|
||||
.react-tabs__tab-list {
|
||||
border-bottom: 2px solid ${props => props.theme.colors.blackShades[3]};
|
||||
color: ${props => props.theme.colors.blackShades[6]};
|
||||
${props =>
|
||||
props.shouldOverflow &&
|
||||
`
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
`}
|
||||
}
|
||||
.react-tabs__tab {
|
||||
padding: ${props => props.theme.space[7]}px 0;
|
||||
margin-right: ${props => props.theme.space[15]}px;
|
||||
text-align: center;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.react-tabs__tab:hover {
|
||||
color: ${props => props.theme.colors.blackShades[9]};
|
||||
path {
|
||||
fill: ${props => props.theme.colors.blackShades[9]};
|
||||
}
|
||||
}
|
||||
.react-tabs__tab:focus {
|
||||
box-shadow: none;
|
||||
border-bottom: ${props => props.theme.colors.info.main}
|
||||
${props => props.theme.space[16]}px solid;
|
||||
path {
|
||||
fill: ${props => props.theme.colors.blackShades[9]};
|
||||
}
|
||||
}
|
||||
.react-tabs__tab--selected {
|
||||
color: ${props => props.theme.colors.blackShades[9]};
|
||||
border: 0px solid;
|
||||
border-bottom: ${props => props.theme.colors.info.main}
|
||||
${props => props.theme.space[16]}px solid;
|
||||
background-color: transparent;
|
||||
path {
|
||||
fill: ${props => props.theme.colors.blackShades[9]};
|
||||
}
|
||||
}
|
||||
.react-tabs__tab:focus:after {
|
||||
content: none;
|
||||
height: ${props => props.theme.space[16]}px;
|
||||
background: ${props => props.theme.colors.info.main};
|
||||
}
|
||||
`;
|
||||
|
||||
type TabbedViewComponentType = {
|
||||
tabs: Array<{
|
||||
key: string;
|
||||
title: string;
|
||||
panelComponent: JSX.Element;
|
||||
icon?: IconName;
|
||||
}>;
|
||||
selectedIndex?: number;
|
||||
setSelectedIndex?: Function;
|
||||
overflow?: boolean;
|
||||
};
|
||||
|
||||
export const AdsTabComponent = (props: TabbedViewComponentType) => {
|
||||
return (
|
||||
<TabsWrapper shouldOverflow={props.overflow}>
|
||||
<Tabs
|
||||
selectedIndex={props.selectedIndex}
|
||||
onSelect={(index: number) => {
|
||||
props.setSelectedIndex && props.setSelectedIndex(index);
|
||||
}}
|
||||
>
|
||||
<TabList>
|
||||
{props.tabs.map(tab => (
|
||||
<Tab key={tab.key}>
|
||||
{tab.icon ? <Icon name={tab.icon} size={Size.large} /> : null}
|
||||
{tab.title}
|
||||
</Tab>
|
||||
))}
|
||||
</TabList>
|
||||
{props.tabs.map(tab => (
|
||||
<TabPanel key={tab.key}>{tab.panelComponent}</TabPanel>
|
||||
))}
|
||||
</Tabs>
|
||||
</TabsWrapper>
|
||||
);
|
||||
};
|
||||
// Create a wrapper around react-tabs
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ const StyledText = styled.div<TabProps>`
|
|||
`;
|
||||
|
||||
const TabsComponent = (props: TabsComponentProps) => {
|
||||
const { onTabChange, ...remainingProps } = props;
|
||||
const tabContainerRef: RefObject<HTMLDivElement> = useRef<HTMLDivElement>(
|
||||
null,
|
||||
);
|
||||
|
|
@ -135,7 +136,7 @@ const TabsComponent = (props: TabsComponentProps) => {
|
|||
)}
|
||||
<ChildrenWrapper>
|
||||
<ScrollableCanvasWrapper
|
||||
{...props}
|
||||
{...remainingProps}
|
||||
className={`${
|
||||
props.shouldScrollContents ? getCanvasClassName() : ""
|
||||
} ${generateClassName(props.widgetId)}`}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { ControlIcons } from "icons/ControlIcons";
|
|||
import { AnyStyledComponent } from "styled-components";
|
||||
import { generateReactKey } from "utils/generators";
|
||||
import { DroppableComponent } from "../designSystems/appsmith/DraggableListComponent";
|
||||
import { getNextEntityName } from "utils/AppsmithUtils";
|
||||
import _ from "lodash";
|
||||
|
||||
const StyledDeleteIcon = styled(FormIcons.DELETE_ICON as AnyStyledComponent)`
|
||||
|
|
@ -161,7 +162,11 @@ class TabControl extends BaseControl<ControlProps> {
|
|||
? JSON.parse(this.props.propertyValue)
|
||||
: this.props.propertyValue;
|
||||
const newTabId = generateReactKey({ prefix: "tab" });
|
||||
tabs.push({ id: newTabId, label: `Tab ${tabs.length + 1}` });
|
||||
const newTabLabel = getNextEntityName(
|
||||
"Tab ",
|
||||
tabs.map(tab => tab.label),
|
||||
);
|
||||
tabs.push({ id: newTabId, label: newTabLabel });
|
||||
this.updateProperty(this.props.propertyName, JSON.stringify(tabs));
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,68 +0,0 @@
|
|||
import React from "react";
|
||||
import { AdsTabComponent } from "components/ads/Tabs";
|
||||
import { withKnobs } from "@storybook/addon-knobs";
|
||||
import { withDesign } from "storybook-addon-designs";
|
||||
import { ThemeProvider } from "styled-components";
|
||||
import { adsTheme } from "../ads/baseTheme";
|
||||
import { IconName } from "../ads/Icon";
|
||||
|
||||
export default {
|
||||
title: "tabs",
|
||||
component: AdsTabComponent,
|
||||
decorators: [withKnobs, withDesign],
|
||||
};
|
||||
|
||||
type tabSingle = {
|
||||
key: string;
|
||||
title: string;
|
||||
panelComponent: JSX.Element;
|
||||
icon: IconName;
|
||||
};
|
||||
|
||||
const tabArr: tabSingle[] = [
|
||||
{
|
||||
key: "r",
|
||||
title: "Tab one",
|
||||
panelComponent: (
|
||||
<div
|
||||
style={{ backgroundColor: "#CB4810", width: "100%", height: "100%" }}
|
||||
></div>
|
||||
),
|
||||
icon: "delete",
|
||||
},
|
||||
{
|
||||
key: "r",
|
||||
title: "Tab two",
|
||||
panelComponent: (
|
||||
<div
|
||||
style={{ backgroundColor: "#218358", width: "100%", height: "100%" }}
|
||||
></div>
|
||||
),
|
||||
icon: "delete",
|
||||
},
|
||||
{
|
||||
key: "r",
|
||||
title: "Tab three",
|
||||
panelComponent: (
|
||||
<div
|
||||
style={{ backgroundColor: "#457AE6", width: "100%", height: "100%" }}
|
||||
></div>
|
||||
),
|
||||
icon: "delete",
|
||||
},
|
||||
];
|
||||
|
||||
export const withDynamicProps = () => (
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "600px",
|
||||
backgroundColor: "#1A191C",
|
||||
padding: "100px",
|
||||
}}
|
||||
>
|
||||
<ThemeProvider theme={adsTheme}>
|
||||
<AdsTabComponent tabs={tabArr}></AdsTabComponent>
|
||||
</ThemeProvider>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -8,6 +8,7 @@ import { WidgetPropertyValidationType } from "utils/ValidationFactory";
|
|||
import { VALIDATION_TYPES } from "constants/WidgetValidation";
|
||||
import _ from "lodash";
|
||||
import { EventType } from "constants/ActionConstants";
|
||||
import { WidgetOperations } from "widgets/BaseWidget";
|
||||
|
||||
class TabsWidget extends BaseWidget<
|
||||
TabsWidgetProps<TabContainerWidgetProps>,
|
||||
|
|
@ -60,21 +61,26 @@ class TabsWidget extends BaseWidget<
|
|||
|
||||
renderComponent = () => {
|
||||
const selectedTabId = this.props.selectedTabId;
|
||||
const children = this.props.children.filter(item => {
|
||||
return selectedTabId === item.tabId;
|
||||
})[0];
|
||||
const childWidgetData: TabContainerWidgetProps = children;
|
||||
const childWidgetData: TabContainerWidgetProps = this.props.children.filter(
|
||||
item => {
|
||||
return selectedTabId === item.tabId;
|
||||
},
|
||||
)[0];
|
||||
|
||||
if (!childWidgetData) {
|
||||
return <div></div>;
|
||||
return null;
|
||||
}
|
||||
childWidgetData.shouldScrollContents = false;
|
||||
childWidgetData.canExtend = this.props.shouldScrollContents;
|
||||
const { componentWidth, componentHeight } = this.getComponentDimensions();
|
||||
childWidgetData.rightColumn = componentWidth;
|
||||
childWidgetData.isVisible = this.props.isVisible;
|
||||
childWidgetData.bottomRow = this.props.shouldScrollContents
|
||||
? (this.props.bottomRow - this.props.topRow - 1) *
|
||||
this.props.parentRowSpace
|
||||
: componentHeight;
|
||||
? childWidgetData.bottomRow
|
||||
: componentHeight - 1;
|
||||
childWidgetData.parentId = this.props.widgetId;
|
||||
childWidgetData.minHeight = componentHeight;
|
||||
|
||||
return WidgetFactory.createWidget(childWidgetData, this.props.renderMode);
|
||||
};
|
||||
|
||||
|
|
@ -117,11 +123,12 @@ class TabsWidget extends BaseWidget<
|
|||
children: [],
|
||||
},
|
||||
};
|
||||
this.updateWidget("ADD_CHILD", this.props.widgetId, config);
|
||||
this.updateWidget(WidgetOperations.ADD_CHILD, this.props.widgetId, config);
|
||||
};
|
||||
|
||||
removeTabContainer = () => {
|
||||
let removedContainerWidgetId = "";
|
||||
let removedTabId = "";
|
||||
const tabIds: string[] = this.props.tabs.map(tab => {
|
||||
return tab.id;
|
||||
});
|
||||
|
|
@ -129,9 +136,22 @@ class TabsWidget extends BaseWidget<
|
|||
const children = this.props.children[index];
|
||||
if (!tabIds.includes(children.tabId)) {
|
||||
removedContainerWidgetId = children.widgetId;
|
||||
removedTabId = children.tabId;
|
||||
}
|
||||
}
|
||||
this.updateWidget("REMOVE_CHILD", removedContainerWidgetId, {
|
||||
/* Selecting first tab as default tab when no tab is selected */
|
||||
if (
|
||||
this.props.tabs.length > 1 &&
|
||||
removedTabId === this.props.selectedTabId
|
||||
) {
|
||||
setTimeout(() => {
|
||||
this.updateWidgetProperty(
|
||||
"defaultTab",
|
||||
this.props.tabs.filter(tab => tab.id !== removedTabId)[0].label,
|
||||
);
|
||||
}, 0);
|
||||
}
|
||||
this.updateWidget(WidgetOperations.DELETE, removedContainerWidgetId, {
|
||||
parentId: this.props.widgetId,
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user