chore: use ads icons (#35633)
## Description Why did this PR appear? I wanted to replace the icons from `ads-old` with the icons from `ads`. After that, I had to fix some affected components in `ads-old` and in the main app. In the process, I discovered that a large amount of code is simply not being used. ## Automation /ok-to-test tags="@tag.All" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/10419944222> > Commit: 86491f43aff37e34468fb7dc32722b9ef2ec60c9 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=10419944222&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.All` > Spec: > <hr>Fri, 16 Aug 2024 13:28:03 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Improved precision in UI element targeting for enhanced test reliability. - Broadened icon options within the FilePickerComponent for greater flexibility. - **Improvements** - Shifted component imports to a centralized design system for better consistency. - Simplified prop structures for the Button component to enhance clarity. - Enhanced validation utilities available for form handling and input validation. - **Bug Fixes** - Enhanced robustness of element locators, reducing potential UI interaction issues. - **Refactor** - Adjusted component properties to align with updated design guidelines, promoting semantic usage. - Consolidated exports to emphasize type definitions and utility functions for better maintainability. - **Chores** - Cleaned up imports and updated code structure for improved maintainability. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
4a902483df
commit
c1c196efbd
|
|
@ -86,7 +86,7 @@ export default {
|
|||
shareUserIcons: ".t--workspace-share-user-icons",
|
||||
toastMessage: "div.Toastify__toast",
|
||||
uploadLogo: "//div/form/input",
|
||||
removeLogo: ".remove-button a span",
|
||||
removeLogo: "[data-testid=t--remove-logo]",
|
||||
generalTab: "//li//span[text()='General']",
|
||||
membersTab: "//li//span[text()='Members']",
|
||||
cancelBtn: "//span[text()='Cancel']",
|
||||
|
|
@ -105,5 +105,5 @@ export default {
|
|||
noEntityFound:".no-search-results",
|
||||
initialWorkspace:"[data-testid^='Untitled workspace']",
|
||||
initialApplication:"[data-testid^='Untitled application']",
|
||||
_entitySearchBar:"[data-testid='t--application-search-input']";
|
||||
_entitySearchBar:"[data-testid='t--application-search-input']"
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
# usage ./create_story.sh -f <Folder name under src fodler>
|
||||
while getopts f: flag
|
||||
do
|
||||
case "${flag}" in
|
||||
f) folder=${OPTARG};;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "Creating story for folder: $folder"
|
||||
cat story_template.txt >> src/$folder/$folder.stories.tsx
|
||||
|
|
@ -5,10 +5,8 @@
|
|||
"main": "src/index.ts",
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"create-story": "./create_story.sh",
|
||||
"lint": "yarn g:lint",
|
||||
"prettier": "yarn g:prettier",
|
||||
"test:unit": "yarn g:jest"
|
||||
"prettier": "yarn g:prettier"
|
||||
},
|
||||
"contributors": [
|
||||
"Albin <albin@appsmith.com>",
|
||||
|
|
|
|||
|
|
@ -272,7 +272,7 @@ const ServerLineIcon = importRemixIcon(
|
|||
async () => import("remixicon-react/ServerLineIcon"),
|
||||
);
|
||||
|
||||
enum Size {
|
||||
export enum Size {
|
||||
xxs = "xxs",
|
||||
xs = "xs",
|
||||
small = "small",
|
||||
|
|
|
|||
|
|
@ -1,118 +0,0 @@
|
|||
// TODO: In Phase 2, add a warn when this component doesn't have a <Router> component in it's ancestors
|
||||
import type { ReactNode } from "react";
|
||||
import React from "react";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import Icon from "../Icon";
|
||||
|
||||
export interface BreadcrumbsProps {
|
||||
items: {
|
||||
href: string;
|
||||
text: string;
|
||||
}[];
|
||||
}
|
||||
export interface BreadcrumbProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export const StyledBreadcrumbList = styled.ol`
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
color: var(--ads-breadcrumbs-list-text-color);
|
||||
margin-bottom: 23px;
|
||||
|
||||
.breadcrumb-separator {
|
||||
color: var(--ads-breadcrumbs-separator-text-color);
|
||||
margin: auto 6px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.t--breadcrumb-item {
|
||||
&.active {
|
||||
color: var(--ads-breadcrumbs-active-text-color);
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
function BreadcrumbSeparator({ children, ...props }: { children: ReactNode }) {
|
||||
return (
|
||||
<li className="breadcrumb-separator" {...props}>
|
||||
{children}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
function BreadcrumbItem({ children, ...props }: { children: ReactNode }) {
|
||||
return (
|
||||
<li className="breadcrumb-item" {...props}>
|
||||
{children}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
function BreadcrumbList(props: BreadcrumbProps) {
|
||||
let children = React.Children.toArray(props.children);
|
||||
|
||||
children = children.map((child, index) => (
|
||||
<BreadcrumbItem key={`breadcrumb_item${index}`}>{child}</BreadcrumbItem>
|
||||
));
|
||||
|
||||
const lastIndex = children.length - 1;
|
||||
|
||||
const childrenNew = children.reduce((acc: ReactNode[], child, index) => {
|
||||
const notLast = index < lastIndex;
|
||||
|
||||
if (notLast) {
|
||||
acc.push(
|
||||
child,
|
||||
<BreadcrumbSeparator key={`breadcrumb_sep${index}`}>
|
||||
<Icon name="right-arrow-2" />
|
||||
</BreadcrumbSeparator>,
|
||||
);
|
||||
} else {
|
||||
acc.push(child);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<StyledBreadcrumbList className="t--breadcrumb-list">
|
||||
{childrenNew}
|
||||
</StyledBreadcrumbList>
|
||||
);
|
||||
}
|
||||
|
||||
function Breadcrumbs(props: BreadcrumbsProps) {
|
||||
const { pathname } = useLocation();
|
||||
return (
|
||||
<BreadcrumbList>
|
||||
{props.items.map(({ href, text }) =>
|
||||
href === pathname ? (
|
||||
<span
|
||||
className={`t--breadcrumb-item ${
|
||||
href === pathname ? `active` : ``
|
||||
}`}
|
||||
key={href}
|
||||
>
|
||||
{text}
|
||||
</span>
|
||||
) : (
|
||||
<Link
|
||||
className={`t--breadcrumb-item ${
|
||||
href === pathname ? `active` : ``
|
||||
}`}
|
||||
key={href}
|
||||
to={href}
|
||||
>
|
||||
{text}
|
||||
</Link>
|
||||
),
|
||||
)}
|
||||
</BreadcrumbList>
|
||||
);
|
||||
}
|
||||
|
||||
export default Breadcrumbs;
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
import React from "react";
|
||||
import "@testing-library/jest-dom";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import Button, { Size } from "./index";
|
||||
import { create } from "react-test-renderer";
|
||||
|
||||
describe("<Button /> component - render", () => {
|
||||
it("renders the button component with text passed as input", () => {
|
||||
render(<Button size={Size.medium} tag="button" text="Run" />);
|
||||
expect(screen.getByRole("button")).toHaveTextContent("Run");
|
||||
});
|
||||
});
|
||||
|
||||
describe("<Button /> component - loading behaviour", () => {
|
||||
it("calls the onclick handler when not in loading state", () => {
|
||||
const fn = jest.fn();
|
||||
const tree = create(
|
||||
<Button
|
||||
isLoading={false}
|
||||
onClick={fn}
|
||||
size={Size.medium}
|
||||
tag="button"
|
||||
text="Run"
|
||||
/>,
|
||||
);
|
||||
const button = tree.root.findByType("button");
|
||||
button.props.onClick();
|
||||
expect(fn.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it("does not call the onclick handler when in loading state", () => {
|
||||
const fn = jest.fn();
|
||||
const tree = create(
|
||||
<Button
|
||||
isLoading
|
||||
onClick={fn}
|
||||
size={Size.medium}
|
||||
tag="button"
|
||||
text="Run"
|
||||
/>,
|
||||
);
|
||||
const button = tree.root.findByType("button");
|
||||
button.props.onClick();
|
||||
expect(fn.mock.calls.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,581 +0,0 @@
|
|||
import React from "react";
|
||||
import _ from "lodash";
|
||||
import styled, { css } from "styled-components";
|
||||
import { Variant } from "../constants/variants";
|
||||
import type { CommonComponentProps } from "../types/common";
|
||||
import { Classes } from "../constants/classes";
|
||||
import type { IconName } from "../Icon";
|
||||
import Icon, { IconSize } from "../Icon";
|
||||
import Spinner from "../Spinner";
|
||||
import { typography } from "../constants/typography";
|
||||
|
||||
const smallButton = css`
|
||||
font-size: ${typography.btnSmall.fontSize}px;
|
||||
font-weight: ${typography.btnSmall.fontWeight};
|
||||
line-height: ${typography.btnSmall.lineHeight}px;
|
||||
letter-spacing: ${typography.btnSmall.letterSpacing}px;
|
||||
`;
|
||||
|
||||
const mediumButton = css`
|
||||
font-size: ${typography.btnMedium.fontSize}px;
|
||||
font-weight: ${typography.btnMedium.fontWeight};
|
||||
line-height: ${typography.btnMedium.lineHeight}px;
|
||||
letter-spacing: ${typography.btnMedium.letterSpacing}px;
|
||||
`;
|
||||
|
||||
const largeButton = css`
|
||||
font-size: ${typography.btnLarge.fontSize}px;
|
||||
font-weight: ${typography.btnLarge.fontWeight};
|
||||
line-height: ${typography.btnLarge.lineHeight}px;
|
||||
letter-spacing: ${typography.btnLarge.letterSpacing}px;
|
||||
`;
|
||||
|
||||
export enum Category {
|
||||
primary = "primary",
|
||||
secondary = "secondary",
|
||||
tertiary = "tertiary",
|
||||
}
|
||||
|
||||
export enum Size {
|
||||
xxs = "xxs",
|
||||
xs = "xs",
|
||||
small = "small",
|
||||
medium = "medium",
|
||||
large = "large",
|
||||
}
|
||||
|
||||
interface stateStyleType {
|
||||
bgColorPrimary: string;
|
||||
borderColorPrimary: string;
|
||||
txtColorPrimary: string;
|
||||
bgColorSecondary: string;
|
||||
borderColorSecondary: string;
|
||||
txtColorSecondary: string;
|
||||
bgColorTertiary: string;
|
||||
borderColorTertiary: string;
|
||||
txtColorTertiary: string;
|
||||
}
|
||||
|
||||
interface BtnColorType {
|
||||
bgColor: string;
|
||||
txtColor: string;
|
||||
border: string;
|
||||
outline: string;
|
||||
}
|
||||
|
||||
interface BtnFontType {
|
||||
buttonFont: any;
|
||||
padding: string;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export enum IconPositions {
|
||||
left = "left",
|
||||
right = "right",
|
||||
}
|
||||
|
||||
export type ButtonProps = CommonComponentProps & {
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
text?: string;
|
||||
category?: Category;
|
||||
variant?: Variant;
|
||||
className?: string;
|
||||
icon?: IconName;
|
||||
size?: Size;
|
||||
fill?: boolean;
|
||||
href?: string;
|
||||
tabIndex?: number;
|
||||
tag?: "a" | "button";
|
||||
type?: "submit" | "reset" | "button";
|
||||
target?: string;
|
||||
height?: string;
|
||||
width?: string;
|
||||
iconPosition?: IconPositions;
|
||||
};
|
||||
|
||||
const defaultProps = {
|
||||
category: Category.primary,
|
||||
variant: Variant.info,
|
||||
size: Size.small,
|
||||
isLoading: false,
|
||||
disabled: false,
|
||||
fill: undefined,
|
||||
tag: "a",
|
||||
};
|
||||
|
||||
interface buttonVariant {
|
||||
main: string;
|
||||
light: string;
|
||||
dark: string;
|
||||
darker: string;
|
||||
darkest: string;
|
||||
}
|
||||
|
||||
interface ButtonColorType {
|
||||
[index: string]: buttonVariant;
|
||||
}
|
||||
|
||||
const ButtonColors: ButtonColorType = {
|
||||
info: {
|
||||
main: "var(--ads-color-brand)",
|
||||
light: "var(--ads-old-color-hot-cinnamon)",
|
||||
dark: "var(--ads-color-brand-hover)",
|
||||
darker: "var(--ads-color-brand-disabled)",
|
||||
darkest: "var(--ads-old-color-pot-pourri)",
|
||||
},
|
||||
success: {
|
||||
main: "var(--ads-old-color-jade)",
|
||||
light: "var(--ads-old-color-fun-green)",
|
||||
dark: "var(--ads-old-color-fun-green-2)",
|
||||
darker: "var(--ads-old-color-granny-apple)",
|
||||
darkest: "var(--ads-old-color-foam)",
|
||||
},
|
||||
warning: {
|
||||
main: "var(--ads-old-color-sun)",
|
||||
light: "var(--ads-old-color-yellow-sea)",
|
||||
dark: "var(--ads-old-color-yellow-sea)",
|
||||
darker: "var(--ads-old-color-champagne)",
|
||||
darkest: "var(--ads-old-color-early-dawn)",
|
||||
},
|
||||
danger: {
|
||||
main: "var(--ads-old-color-pomegranate)",
|
||||
light: "var(--ads-old-color-milano-red)",
|
||||
dark: "var(--ads-old-color-milano-red-2)",
|
||||
darker: "var(--ads-old-color-cinderella)",
|
||||
darkest: "var(--ads-old-color-fair-pink)",
|
||||
},
|
||||
secondary: {
|
||||
main: "var(--ads-old-color-mid-gray)",
|
||||
light: "var(--ads-old-color-gray-10)",
|
||||
dark: "var(--ads-color-black-5)",
|
||||
darker: "var(--ads-old-color-gallery)",
|
||||
darkest: "var(--ads-color-black-450)",
|
||||
},
|
||||
tertiary: {
|
||||
main: "var(--ads-old-color-mid-gray)",
|
||||
light: "var(--ads-old-color-gray-10)",
|
||||
dark: "var(--ads-color-black-5)",
|
||||
darker: "var(--ads-old-color-gallery)",
|
||||
darkest: "var(--ads-color-black-450)",
|
||||
},
|
||||
};
|
||||
|
||||
const WhiteTextVariants = [Variant.danger, Variant.warning, Variant.success];
|
||||
|
||||
const getDisabledStyles = (props: ButtonProps) => {
|
||||
const variant = props.variant ?? defaultProps.variant;
|
||||
const category = props.category ?? defaultProps.category;
|
||||
|
||||
const stylesByCategory = {
|
||||
[Category.primary]: {
|
||||
txtColorPrimary: "var(--ads-old-color-gray-7)",
|
||||
bgColorPrimary: ButtonColors[variant].darker,
|
||||
borderColorPrimary: ButtonColors[variant].darker,
|
||||
},
|
||||
[Category.secondary]: {
|
||||
txtColorSecondary: "var(--ads-color-black-500)",
|
||||
bgColorSecondary: "var(--ads-color-black-50)",
|
||||
borderColorSecondary: "var(--ads-color-black-300)",
|
||||
},
|
||||
[Category.tertiary]: {
|
||||
txtColorTertiary: "var(--ads-color-black-500)",
|
||||
bgColorTertiary: "var(--ads-color-black-0)",
|
||||
borderColorTertiary: "transparent",
|
||||
},
|
||||
};
|
||||
|
||||
return stylesByCategory[category];
|
||||
};
|
||||
|
||||
const getMainStateStyles = (props: ButtonProps) => {
|
||||
const variant = props.variant ?? defaultProps.variant;
|
||||
const category = props.category ?? defaultProps.category;
|
||||
|
||||
const stylesByCategory = {
|
||||
[Category.primary]: {
|
||||
bgColorPrimary: ButtonColors[variant].main,
|
||||
borderColorPrimary: ButtonColors[variant].main,
|
||||
txtColorPrimary:
|
||||
WhiteTextVariants.indexOf(variant) === -1
|
||||
? "var(--ads-color-brand-text)"
|
||||
: "var(--ads-color-black-0)",
|
||||
},
|
||||
[Category.secondary]: {
|
||||
bgColorSecondary: "var(--ads-color-black-0)",
|
||||
borderColorSecondary: "var(--ads-color-black-300)",
|
||||
txtColorSecondary: "var(--ads-color-black-700)",
|
||||
},
|
||||
[Category.tertiary]: {
|
||||
bgColorTertiary: "var(--ads-color-black-0)",
|
||||
borderColorTertiary: "transparent",
|
||||
txtColorTertiary: "var(--ads-color-black-700)",
|
||||
},
|
||||
};
|
||||
|
||||
return stylesByCategory[category];
|
||||
};
|
||||
|
||||
const getHoverStateStyles = (props: ButtonProps) => {
|
||||
const variant = props.variant ?? defaultProps.variant;
|
||||
const category = props.category ?? defaultProps.category;
|
||||
|
||||
const stylesByCategory = {
|
||||
[Category.primary]: {
|
||||
bgColorPrimary: ButtonColors[variant].dark,
|
||||
txtColorPrimary:
|
||||
WhiteTextVariants.indexOf(variant) === -1
|
||||
? "var(--ads-color-brand-text)"
|
||||
: "var(--ads-color-black-0)",
|
||||
borderColorPrimary: ButtonColors[variant].dark,
|
||||
},
|
||||
[Category.secondary]: {
|
||||
bgColorSecondary: "var(--ads-color-black-50)",
|
||||
txtColorSecondary: "var(--ads-color-black-700)",
|
||||
borderColorSecondary: "var(--ads-color-black-300)",
|
||||
},
|
||||
[Category.tertiary]: {
|
||||
bgColorTertiary: "var(--ads-color-black-100)",
|
||||
txtColorTertiary: "var(--ads-color-black-700)",
|
||||
borderColorTertiary: "transparent",
|
||||
},
|
||||
};
|
||||
|
||||
return stylesByCategory[category];
|
||||
};
|
||||
|
||||
const getActiveStateStyles = (props: ButtonProps) => {
|
||||
const variant = props.variant ?? defaultProps.variant;
|
||||
const category = props.category ?? defaultProps.category;
|
||||
|
||||
const stylesByCategory = {
|
||||
[Category.primary]: {
|
||||
bgColorPrimary: ButtonColors[variant].dark,
|
||||
borderColorPrimary: ButtonColors[variant].main,
|
||||
txtColorPrimary:
|
||||
WhiteTextVariants.indexOf(variant) === -1
|
||||
? "var(--ads-color-brand-text)"
|
||||
: "var(--ads-color-black-0)",
|
||||
},
|
||||
[Category.secondary]: {
|
||||
bgColorSecondary: "var(--ads-color-black-100)",
|
||||
borderColorSecondary: "var(--ads-color-black-600)",
|
||||
txtColorSecondary: "var(--ads-color-black-800)",
|
||||
},
|
||||
[Category.tertiary]: {
|
||||
bgColorTertiary: "var(--ads-color-black-200)",
|
||||
borderColorTertiary: "transparent",
|
||||
txtColorTertiary: "var(--ads-color-black-800)",
|
||||
},
|
||||
};
|
||||
|
||||
return stylesByCategory[category];
|
||||
};
|
||||
|
||||
const stateStyles = (props: ButtonProps, stateArg: string): stateStyleType => {
|
||||
const styles = {
|
||||
bgColorPrimary: "",
|
||||
borderColorPrimary: "",
|
||||
txtColorPrimary: "",
|
||||
bgColorSecondary: "",
|
||||
borderColorSecondary: "",
|
||||
txtColorSecondary: "",
|
||||
bgColorTertiary: "",
|
||||
borderColorTertiary: "",
|
||||
txtColorTertiary: "",
|
||||
};
|
||||
const state =
|
||||
props.isLoading || props.disabled
|
||||
? "disabled"
|
||||
: (stateArg as keyof typeof stylesByState);
|
||||
const stylesByState = {
|
||||
disabled: getDisabledStyles(props),
|
||||
main: getMainStateStyles(props),
|
||||
hover: getHoverStateStyles(props),
|
||||
active: getActiveStateStyles(props),
|
||||
};
|
||||
|
||||
return {
|
||||
...styles,
|
||||
...stylesByState[state],
|
||||
};
|
||||
};
|
||||
|
||||
const btnColorStyles = (props: ButtonProps, state: string): BtnColorType => {
|
||||
let bgColor = "",
|
||||
txtColor = "",
|
||||
border = "",
|
||||
outline = "";
|
||||
switch (props.category) {
|
||||
case Category.primary:
|
||||
bgColor = stateStyles(props, state).bgColorPrimary;
|
||||
txtColor = stateStyles(props, state).txtColorPrimary;
|
||||
border = `1.2px solid ${stateStyles(props, state).borderColorPrimary}`;
|
||||
break;
|
||||
case Category.secondary:
|
||||
bgColor = stateStyles(props, state).bgColorSecondary;
|
||||
txtColor = stateStyles(props, state).txtColorSecondary;
|
||||
border = `1.2px solid ${stateStyles(props, state).borderColorSecondary}`;
|
||||
outline = "2px solid var(--ads-color-blue-150)";
|
||||
break;
|
||||
case Category.tertiary:
|
||||
bgColor = stateStyles(props, state).bgColorTertiary;
|
||||
txtColor = stateStyles(props, state).txtColorTertiary;
|
||||
border = `1.2px solid ${stateStyles(props, state).borderColorTertiary}`;
|
||||
outline = "2px solid var(--ads-color-blue-150)";
|
||||
break;
|
||||
}
|
||||
return { bgColor, txtColor, border, outline };
|
||||
};
|
||||
|
||||
const getPaddingBySize = (props: ButtonProps) => {
|
||||
const paddingBySize = {
|
||||
[Size.small]: `0px var(--ads-spaces-3)`,
|
||||
[Size.medium]: `0px var(--ads-spaces-7)`,
|
||||
[Size.large]: `0px 26px`,
|
||||
};
|
||||
const paddingBySizeForJustIcon = {
|
||||
[Size.small]: `0px var(--ads-spaces-1)`,
|
||||
[Size.medium]: `0px var(--ads-spaces-2)`,
|
||||
[Size.large]: `0px var(--ads-spaces-3)`,
|
||||
};
|
||||
|
||||
const isIconOnly = !props.text && props.icon;
|
||||
const paddingConfig = isIconOnly ? paddingBySizeForJustIcon : paddingBySize;
|
||||
|
||||
const iSizeInConfig =
|
||||
// @ts-expect-error fix this the next time the file is edited
|
||||
Object.keys(paddingConfig).indexOf(props.size != null || "") !== -1;
|
||||
const size: any =
|
||||
props.size != null && iSizeInConfig ? props.size : Size.small;
|
||||
|
||||
return paddingConfig[size as keyof typeof paddingConfig];
|
||||
};
|
||||
|
||||
const getHeightBySize = (props: ButtonProps) => {
|
||||
const heightBySize = {
|
||||
[Size.small]: 20,
|
||||
[Size.medium]: 30,
|
||||
[Size.large]: 38,
|
||||
};
|
||||
|
||||
const iSizeInConfig =
|
||||
// @ts-expect-error fix this the next time the file is edited
|
||||
Object.keys(heightBySize).indexOf(props.size != null || "") !== -1;
|
||||
const size: any =
|
||||
props.size != null && iSizeInConfig ? props.size : Size.small;
|
||||
|
||||
return heightBySize[size as keyof typeof heightBySize];
|
||||
};
|
||||
|
||||
const getBtnFontBySize = (props: ButtonProps) => {
|
||||
const fontBySize = {
|
||||
[Size.small]: smallButton,
|
||||
[Size.medium]: mediumButton,
|
||||
[Size.large]: largeButton,
|
||||
};
|
||||
|
||||
const iSizeInConfig =
|
||||
// @ts-expect-error fix this the next time the file is edited
|
||||
Object.keys(fontBySize).indexOf(props.size != null || "") !== -1;
|
||||
const size: any =
|
||||
props.size != null && iSizeInConfig ? props.size : Size.small;
|
||||
|
||||
return fontBySize[size as keyof typeof fontBySize];
|
||||
};
|
||||
|
||||
const btnFontStyles = (props: ButtonProps): BtnFontType => {
|
||||
const padding = getPaddingBySize(props);
|
||||
const height = getHeightBySize(props);
|
||||
const buttonFont = getBtnFontBySize(props);
|
||||
|
||||
return { buttonFont, padding, height };
|
||||
};
|
||||
|
||||
const ButtonStyles = css<ButtonProps>`
|
||||
user-select: none;
|
||||
width: ${(props) =>
|
||||
props.width ? props.width : props.fill ? "100%" : "auto"};
|
||||
height: ${(props) => props.height || btnFontStyles(props).height}px;
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
text-transform: uppercase;
|
||||
background-color: ${(props) => btnColorStyles(props, "main").bgColor};
|
||||
color: ${(props) => btnColorStyles(props, "main").txtColor};
|
||||
border: ${(props) => btnColorStyles(props, "main").border};
|
||||
border-radius: 0;
|
||||
${(props) => btnFontStyles(props).buttonFont};
|
||||
padding: ${(props: ButtonProps) => btnFontStyles(props).padding};
|
||||
.${Classes.ICON}:not([name="no-response"]) {
|
||||
svg {
|
||||
fill: ${(props: ButtonProps) => btnColorStyles(props, "main").txtColor};
|
||||
}
|
||||
}
|
||||
&,
|
||||
& * {
|
||||
cursor: ${(props) =>
|
||||
props.isLoading || props.disabled ? `not-allowed` : `pointer`};
|
||||
}
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
background-color: ${(props: ButtonProps) =>
|
||||
btnColorStyles(props, "hover").bgColor};
|
||||
color: ${(props: ButtonProps) => btnColorStyles(props, "hover").txtColor};
|
||||
border: ${(props: ButtonProps) => btnColorStyles(props, "hover").border};
|
||||
.${Classes.ICON} {
|
||||
fill: ${(props: ButtonProps) => btnColorStyles(props, "hover").txtColor};
|
||||
}
|
||||
}
|
||||
&:focus-visible {
|
||||
outline: ${(props: ButtonProps) => btnColorStyles(props, "active").outline};
|
||||
outline-offset: 0px;
|
||||
}
|
||||
font-style: normal;
|
||||
&:active {
|
||||
background-color: ${(props: ButtonProps) =>
|
||||
btnColorStyles(props, "active").bgColor};
|
||||
color: ${(props: ButtonProps) => btnColorStyles(props, "active").txtColor};
|
||||
border: ${(props: ButtonProps) => btnColorStyles(props, "active").border};
|
||||
.${Classes.ICON} {
|
||||
fill: ${(props: ButtonProps) => btnColorStyles(props, "active").txtColor};
|
||||
}
|
||||
}
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
.${Classes.SPINNER} {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
circle {
|
||||
stroke: var(--ads-old-color-gray-7);
|
||||
}
|
||||
}
|
||||
.t--right-icon {
|
||||
margin-left: var(--ads-spaces-1);
|
||||
}
|
||||
.t--left-icon {
|
||||
margin-right: var(--ads-spaces-1);
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledButton = styled("button")`
|
||||
${ButtonStyles}
|
||||
`;
|
||||
|
||||
const StyledLinkButton = styled("a")`
|
||||
${ButtonStyles}
|
||||
`;
|
||||
|
||||
export const VisibilityWrapper = styled.div`
|
||||
visibility: hidden;
|
||||
`;
|
||||
|
||||
const IconSizeProp = (size?: Size) => {
|
||||
const sizeMapping = {
|
||||
[Size.xxs]: IconSize.XXS,
|
||||
[Size.xs]: IconSize.XS,
|
||||
[Size.small]: IconSize.SMALL,
|
||||
[Size.medium]: IconSize.MEDIUM,
|
||||
[Size.large]: IconSize.LARGE,
|
||||
};
|
||||
|
||||
return size != null ? sizeMapping[size] : IconSize.SMALL;
|
||||
};
|
||||
|
||||
function TextLoadingState({ text }: { text?: string }) {
|
||||
return <VisibilityWrapper>{text}</VisibilityWrapper>;
|
||||
}
|
||||
|
||||
function IconLoadingState({ icon, size }: { size?: Size; icon?: IconName }) {
|
||||
return <Icon invisible name={icon} size={IconSizeProp(size)} />;
|
||||
}
|
||||
|
||||
const getIconContent = (props: ButtonProps, rightPosFlag = false) =>
|
||||
props.icon ? (
|
||||
props.isLoading ? (
|
||||
<IconLoadingState {...props} />
|
||||
) : (
|
||||
<Icon
|
||||
className={rightPosFlag ? "t--right-icon" : "t--left-icon"}
|
||||
name={props.icon}
|
||||
size={IconSizeProp(props.size)}
|
||||
/>
|
||||
)
|
||||
) : null;
|
||||
|
||||
const getTextContent = (props: ButtonProps) =>
|
||||
props.text ? (
|
||||
props.isLoading ? (
|
||||
<TextLoadingState text={props.text} />
|
||||
) : (
|
||||
props.text
|
||||
)
|
||||
) : null;
|
||||
|
||||
const getButtonContent = (props: ButtonProps) => {
|
||||
const iconPos =
|
||||
props.iconPosition != null
|
||||
? props.iconPosition
|
||||
: props.tag === "a"
|
||||
? IconPositions.right
|
||||
: IconPositions.left;
|
||||
return (
|
||||
<>
|
||||
{iconPos === IconPositions.left && getIconContent(props)}
|
||||
<span>{getTextContent(props)}</span>
|
||||
{iconPos === IconPositions.right && getIconContent(props, true)}
|
||||
{props.isLoading ? <Spinner size={IconSizeProp(props.size)} /> : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
function ButtonComponent(props: ButtonProps) {
|
||||
const { className, cypressSelector, isLoading, onClick } = props;
|
||||
const filteredProps = _.omit(props, ["fill"]);
|
||||
return (
|
||||
<StyledButton
|
||||
className={className}
|
||||
data-cy={cypressSelector}
|
||||
{...filteredProps}
|
||||
onClick={(e: React.MouseEvent<HTMLElement>) =>
|
||||
onClick && !isLoading && onClick(e)
|
||||
}
|
||||
>
|
||||
{getButtonContent(props)}
|
||||
</StyledButton>
|
||||
);
|
||||
}
|
||||
|
||||
function LinkButtonComponent(props: ButtonProps) {
|
||||
const { className, cypressSelector, href, onClick } = props;
|
||||
const filteredProps = _.omit(props, ["fill"]);
|
||||
return (
|
||||
<StyledLinkButton
|
||||
className={className}
|
||||
data-cy={cypressSelector}
|
||||
href={href}
|
||||
{...filteredProps}
|
||||
onClick={(e: React.MouseEvent<HTMLElement>) =>
|
||||
!props.disabled && onClick && onClick(e)
|
||||
}
|
||||
>
|
||||
{getButtonContent(props)}
|
||||
</StyledLinkButton>
|
||||
);
|
||||
}
|
||||
|
||||
function Button(props: ButtonProps) {
|
||||
return props.tag === "button" ? (
|
||||
<ButtonComponent {...props} />
|
||||
) : (
|
||||
<LinkButtonComponent {...props} />
|
||||
);
|
||||
}
|
||||
|
||||
export default Button;
|
||||
|
||||
Button.defaultProps = defaultProps;
|
||||
|
|
@ -2,8 +2,8 @@ import type { ReactNode, PropsWithChildren } from "react";
|
|||
import React, { useState, useEffect } from "react";
|
||||
import styled from "styled-components";
|
||||
import { Dialog, Classes } from "@blueprintjs/core";
|
||||
import type { IconName } from "../Icon";
|
||||
import Icon, { IconSize } from "../Icon";
|
||||
import type { IconNames } from "@appsmith/ads";
|
||||
import { Icon } from "@appsmith/ads";
|
||||
import { typography } from "../constants/typography";
|
||||
|
||||
type DialogProps = PropsWithChildren<{
|
||||
|
|
@ -115,7 +115,7 @@ interface DialogComponentProps {
|
|||
title?: string;
|
||||
headerIcon?: {
|
||||
clickable?: boolean;
|
||||
name: IconName;
|
||||
name: IconNames;
|
||||
fillColor?: string;
|
||||
hoverColor?: string;
|
||||
bgColor?: string;
|
||||
|
|
@ -156,11 +156,9 @@ export function DialogComponent(props: DialogComponentProps) {
|
|||
const headerIcon = props.headerIcon ? (
|
||||
<HeaderIconWrapper bgColor={props.headerIcon.bgColor}>
|
||||
<Icon
|
||||
clickable={props.headerIcon?.clickable}
|
||||
fillColor={props.headerIcon.fillColor}
|
||||
hoverFillColor={props.headerIcon.hoverColor}
|
||||
color={props.headerIcon.fillColor}
|
||||
name={props.headerIcon.name}
|
||||
size={IconSize.XL}
|
||||
size="lg"
|
||||
/>
|
||||
</HeaderIconWrapper>
|
||||
) : null;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { getTypographyByKey } from "../constants/typography";
|
|||
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||
import { ReactComponent as ProfileImagePlaceholder } from "../assets/icons/others/profile-placeholder.svg";
|
||||
import Icon, { IconSize } from "../Icon";
|
||||
import { Spinner } from "@appsmith/ads";
|
||||
|
||||
interface Props {
|
||||
onChange: (file: File) => void;
|
||||
|
|
@ -241,7 +241,7 @@ export default function DisplayImageUpload({
|
|||
<Suspense
|
||||
fallback={
|
||||
<SpinnerContainer>
|
||||
<Icon name={"loader"} size={IconSize.XL} />
|
||||
<Spinner size="lg" />
|
||||
</SpinnerContainer>
|
||||
}
|
||||
>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -5,7 +5,8 @@ import {
|
|||
} from "@blueprintjs/core";
|
||||
import styled from "styled-components";
|
||||
import type { noop } from "lodash";
|
||||
import { Icon, IconSize, Text, TextType } from "../index";
|
||||
import { Spinner } from "@appsmith/ads";
|
||||
import { Text, TextType } from "../index";
|
||||
import type { CommonComponentProps } from "../types/common";
|
||||
|
||||
export enum EditInteractionKind {
|
||||
|
|
@ -116,14 +117,6 @@ const TextContainer = styled.div<{
|
|||
}
|
||||
`;
|
||||
|
||||
const IconWrapper = styled.div`
|
||||
width: var(--ads-spaces-15);
|
||||
padding-right: var(--ads-spaces-5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
`;
|
||||
|
||||
export const EditableTextSubComponent = React.forwardRef(
|
||||
(props: EditableTextSubComponentProps, ref: any) => {
|
||||
const {
|
||||
|
|
@ -224,17 +217,6 @@ export const EditableTextSubComponent = React.forwardRef(
|
|||
[inputValidation, onTextChanged],
|
||||
);
|
||||
|
||||
const iconName =
|
||||
!isEditing &&
|
||||
savingState === SavingState.NOT_STARTED &&
|
||||
!props.hideEditIcon
|
||||
? "pencil-line"
|
||||
: !isEditing && savingState === SavingState.SUCCESS
|
||||
? "success"
|
||||
: savingState === SavingState.ERROR || (isEditing && !!isInvalid)
|
||||
? "error"
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<>
|
||||
<TextContainer
|
||||
|
|
@ -258,19 +240,7 @@ export const EditableTextSubComponent = React.forwardRef(
|
|||
value={value}
|
||||
/>
|
||||
|
||||
{savingState === SavingState.STARTED ? (
|
||||
<IconWrapper className="icon-wrapper">
|
||||
<Icon name={"loader"} size={IconSize.XL} />
|
||||
</IconWrapper>
|
||||
) : value && !props.hideEditIcon ? (
|
||||
<IconWrapper className="icon-wrapper">
|
||||
<Icon
|
||||
fillColor="var(--ads-v2-color-fg)"
|
||||
name={iconName}
|
||||
size={IconSize.XL}
|
||||
/>
|
||||
</IconWrapper>
|
||||
) : null}
|
||||
{savingState === SavingState.STARTED ? <Spinner size="md" /> : null}
|
||||
</TextContainer>
|
||||
{isEditing && !!isInvalid ? (
|
||||
<Text className="error-message" type={TextType.P2}>
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import styled from "styled-components";
|
|||
import type { DropTargetMonitor } from "react-dnd";
|
||||
import { DndProvider, useDrop } from "react-dnd";
|
||||
import HTML5Backend, { NativeTypes } from "react-dnd-html5-backend";
|
||||
import Button, { Category, IconPositions, Size } from "../Button";
|
||||
import type { IconName } from "../Icon";
|
||||
import Icon, { IconSize } from "../Icon";
|
||||
import { Button } from "@appsmith/ads";
|
||||
import type { IconNames } from "@appsmith/ads";
|
||||
import { Icon } from "@appsmith/ads";
|
||||
import Text, { TextType } from "../Text";
|
||||
import { toast } from "@appsmith/ads";
|
||||
import TooltipComponent from "../Tooltip";
|
||||
|
|
@ -14,7 +14,6 @@ import {
|
|||
ERROR_FILE_TOO_LARGE,
|
||||
REMOVE_FILE_TOOL_TIP,
|
||||
} from "../constants/messages";
|
||||
import { Classes } from "../constants/classes";
|
||||
import { importSvg } from "../utils/icon-loadables";
|
||||
|
||||
const UploadSuccessIcon = importSvg(
|
||||
|
|
@ -51,7 +50,7 @@ export interface FilePickerProps {
|
|||
logoUploadError?: string;
|
||||
fileType: FileType;
|
||||
delayedUpload?: boolean;
|
||||
uploadIcon?: IconName;
|
||||
uploadIcon?: IconNames;
|
||||
title?: string;
|
||||
description?: string;
|
||||
containerClickable?: boolean; // when container is clicked, it'll work as button
|
||||
|
|
@ -172,20 +171,10 @@ export const ContainerDiv = styled.div<{
|
|||
bottom: 0;
|
||||
border-radius: 0 0 var(--ads-v2-border-radius) var(--ads-v2-border-radius);
|
||||
}
|
||||
a {
|
||||
.ads-v2-button {
|
||||
width: 110px;
|
||||
margin: var(--ads-spaces-13) var(--ads-spaces-3) var(--ads-spaces-3) auto;
|
||||
color: var(--ads-v2-color-fg);
|
||||
border-radius: var(--ads-v2-border-radius);
|
||||
border-color: var(--ads-v2-color-border);
|
||||
text-transform: capitalize;
|
||||
background: var(--ads-v2-color-bg);
|
||||
.${Classes.ICON} {
|
||||
margin-right: calc(var(--ads-spaces-2) - 1px);
|
||||
}
|
||||
&:hover {
|
||||
background: var(--ads-v2-color-bg-subtle);
|
||||
}
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -407,7 +396,7 @@ function FilePickerComponent(props: FilePickerProps) {
|
|||
<div className="button-wrapper" ref={fileContainerRef}>
|
||||
<UploadIconWrapper>
|
||||
<Icon
|
||||
fillColor={
|
||||
color={
|
||||
props.iconFillColor ||
|
||||
"var(--ads-file-picker-v2-upload-icon-fill-color)"
|
||||
}
|
||||
|
|
@ -434,12 +423,13 @@ function FilePickerComponent(props: FilePickerProps) {
|
|||
/>
|
||||
{!props.containerClickable && (
|
||||
<Button
|
||||
category={Category.secondary}
|
||||
className="browse-button"
|
||||
kind="secondary"
|
||||
onClick={(el: React.MouseEvent<HTMLElement>) => ButtonClick(el)}
|
||||
size={Size.medium}
|
||||
text="Browse"
|
||||
/>
|
||||
size="sm"
|
||||
>
|
||||
Browse
|
||||
</Button>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -466,13 +456,14 @@ function FilePickerComponent(props: FilePickerProps) {
|
|||
<div className="remove-button">
|
||||
<div className="overlay" />
|
||||
<Button
|
||||
category={Category.secondary}
|
||||
icon="delete"
|
||||
iconPosition={IconPositions.left}
|
||||
data-testid="t--remove-logo"
|
||||
kind="secondary"
|
||||
onClick={() => removeFile()}
|
||||
size={Size.medium}
|
||||
text="Remove"
|
||||
/>
|
||||
size="sm"
|
||||
startIcon="delete"
|
||||
>
|
||||
Remove
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
@ -493,7 +484,7 @@ function FilePickerComponent(props: FilePickerProps) {
|
|||
</Text>
|
||||
<TooltipComponent content={REMOVE_FILE_TOOL_TIP()} position="top">
|
||||
<IconWrapper className="icon-wrapper" onClick={() => removeFile()}>
|
||||
<Icon name="close" size={IconSize.XL} />
|
||||
<Icon name="close" size="lg" />
|
||||
</IconWrapper>
|
||||
</TooltipComponent>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import Icon, { IconSize } from "../Icon";
|
||||
import { Icon } from "@appsmith/ads";
|
||||
import Text, { TextType } from "../Text";
|
||||
import { Classes } from "../constants/classes";
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ function GifPlayer(props: GifPlayerProps) {
|
|||
<Overlay />
|
||||
<img src={props.thumbnail} />
|
||||
<PlayButton>
|
||||
<Icon name="play" size={IconSize.XXXL} />
|
||||
<Icon name="play" size="lg" />
|
||||
<Text color={"var(--ads-v2-color-fg)"} type={TextType.P3}>
|
||||
Click to play
|
||||
</Text>
|
||||
|
|
|
|||
|
|
@ -1,982 +0,0 @@
|
|||
import type { Ref } from "react";
|
||||
import React, { forwardRef } from "react";
|
||||
import styled from "styled-components";
|
||||
import type { CommonComponentProps } from "../types/common";
|
||||
import { Classes } from "../constants/classes";
|
||||
import { noop } from "lodash";
|
||||
import Spinner from "../Spinner";
|
||||
import { ControlIcons } from "../ControlIcons";
|
||||
import { importRemixIcon, importSvg } from "../utils/icon-loadables";
|
||||
const ClearInterval = importSvg(
|
||||
async () => import("../assets/icons/action/clearInterval.svg"),
|
||||
);
|
||||
const ClearStore = importSvg(
|
||||
async () => import("../assets/icons/action/clearStore.svg"),
|
||||
);
|
||||
const CopyToClipboard = importSvg(
|
||||
async () => import("../assets/icons/action/copyToClipboard.svg"),
|
||||
);
|
||||
const DownloadAction = importSvg(
|
||||
async () => import("../assets/icons/action/download.svg"),
|
||||
);
|
||||
const ExecuteJs = importSvg(
|
||||
async () => import("../assets/icons/action/executeJs.svg"),
|
||||
);
|
||||
const ExecuteQuery = importSvg(
|
||||
async () => import("../assets/icons/action/executeQuery.svg"),
|
||||
);
|
||||
const GetGeolocation = importSvg(
|
||||
async () => import("../assets/icons/action/getGeolocation.svg"),
|
||||
);
|
||||
const Modal = importSvg(async () => import("../assets/icons/action/modal.svg"));
|
||||
const NavigateTo = importSvg(
|
||||
async () => import("../assets/icons/action/navigateTo.svg"),
|
||||
);
|
||||
const RemoveStore = importSvg(
|
||||
async () => import("../assets/icons/action/removeStore.svg"),
|
||||
);
|
||||
const ResetWidget = importSvg(
|
||||
async () => import("../assets/icons/action/resetWidget.svg"),
|
||||
);
|
||||
const SetInterval = importSvg(
|
||||
async () => import("../assets/icons/action/setInterval.svg"),
|
||||
);
|
||||
const ShowAlert = importSvg(
|
||||
async () => import("../assets/icons/action/showAlert.svg"),
|
||||
);
|
||||
const StopWatchGeolocation = importSvg(
|
||||
async () => import("../assets/icons/action/stopWatchGeolocation.svg"),
|
||||
);
|
||||
const StoreValue = importSvg(
|
||||
async () => import("../assets/icons/action/storeValue.svg"),
|
||||
);
|
||||
const WatchGeolocation = importSvg(
|
||||
async () => import("../assets/icons/action/watchGeolocation.svg"),
|
||||
);
|
||||
const RunAPI = importSvg(
|
||||
async () => import("../assets/icons/action/runApi.svg"),
|
||||
);
|
||||
const PostMessage = importSvg(
|
||||
async () => import("../assets/icons/action/postMessage.svg"),
|
||||
);
|
||||
const NoAction = importSvg(
|
||||
async () => import("../assets/icons/action/noAction.svg"),
|
||||
);
|
||||
const BookLineIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/book-open-line.svg"),
|
||||
);
|
||||
const BugIcon = importSvg(async () => import("../assets/icons/ads/bug.svg"));
|
||||
const CancelIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/cancel.svg"),
|
||||
);
|
||||
const CrossIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/cross.svg"),
|
||||
);
|
||||
const Fork2Icon = importSvg(
|
||||
async () => import("../assets/icons/ads/fork-2.svg"),
|
||||
);
|
||||
const OpenIcon = importSvg(async () => import("../assets/icons/ads/open.svg"));
|
||||
const UserIcon = importSvg(async () => import("../assets/icons/ads/user.svg"));
|
||||
const GeneralIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/general.svg"),
|
||||
);
|
||||
const BillingIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/billing.svg"),
|
||||
);
|
||||
const ErrorIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/error.svg"),
|
||||
);
|
||||
const ShineIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/shine.svg"),
|
||||
);
|
||||
const SuccessIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/success.svg"),
|
||||
);
|
||||
const CloseIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/close.svg"),
|
||||
);
|
||||
const WarningTriangleIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/warning-triangle.svg"),
|
||||
);
|
||||
const ShareIcon2 = importSvg(
|
||||
async () => import("../assets/icons/ads/share-2.svg"),
|
||||
);
|
||||
const InviteUserIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/invite-users.svg"),
|
||||
);
|
||||
const ManageIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/manage.svg"),
|
||||
);
|
||||
const ArrowLeft = importSvg(
|
||||
async () => import("../assets/icons/ads/arrow-left.svg"),
|
||||
);
|
||||
const ChevronLeft = importSvg(
|
||||
async () => import("../assets/icons/ads/chevron_left.svg"),
|
||||
);
|
||||
const LinkIcon = importSvg(async () => import("../assets/icons/ads/link.svg"));
|
||||
const NoResponseIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/no-response.svg"),
|
||||
);
|
||||
const LightningIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/lightning.svg"),
|
||||
);
|
||||
const TrendingFlat = importSvg(
|
||||
async () => import("../assets/icons/ads/trending-flat.svg"),
|
||||
);
|
||||
const PlayIcon = importSvg(async () => import("../assets/icons/ads/play.svg"));
|
||||
const DesktopIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/desktop.svg"),
|
||||
);
|
||||
const WandIcon = importSvg(async () => import("../assets/icons/ads/wand.svg"));
|
||||
const MobileIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/mobile.svg"),
|
||||
);
|
||||
const TabletIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/tablet.svg"),
|
||||
);
|
||||
const TabletLandscapeIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/tablet-landscape.svg"),
|
||||
);
|
||||
const FluidIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/fluid.svg"),
|
||||
);
|
||||
const CardContextMenu = importSvg(
|
||||
async () => import("../assets/icons/ads/card-context-menu.svg"),
|
||||
);
|
||||
const SendButton = importSvg(
|
||||
async () => import("../assets/icons/comments/send-button.svg"),
|
||||
);
|
||||
const Pin = importSvg(async () => import("../assets/icons/comments/pin.svg"));
|
||||
const TrashOutline = importSvg(
|
||||
async () => import("../assets/icons/form/trash.svg"),
|
||||
);
|
||||
const ReadPin = importSvg(
|
||||
async () => import("../assets/icons/comments/read-pin.svg"),
|
||||
);
|
||||
const UnreadPin = importSvg(
|
||||
async () => import("../assets/icons/comments/unread-pin.svg"),
|
||||
);
|
||||
const Chat = importSvg(async () => import("../assets/icons/comments/chat.svg"));
|
||||
const Unpin = importSvg(
|
||||
async () => import("../assets/icons/comments/unpinIcon.svg"),
|
||||
);
|
||||
const Reaction = importSvg(
|
||||
async () => import("../assets/icons/comments/reaction.svg"),
|
||||
);
|
||||
const Reaction2 = importSvg(
|
||||
async () => import("../assets/icons/comments/reaction-2.svg"),
|
||||
);
|
||||
const Upload = importSvg(async () => import("../assets/icons/ads/upload.svg"));
|
||||
const ArrowForwardIcon = importSvg(
|
||||
async () => import("../assets/icons/control/arrow_forward.svg"),
|
||||
);
|
||||
const DoubleArrowRightIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/double-arrow-right.svg"),
|
||||
);
|
||||
const CapSolidIcon = importSvg(
|
||||
async () => import("../assets/icons/control/cap_solid.svg"),
|
||||
);
|
||||
const CapDotIcon = importSvg(
|
||||
async () => import("../assets/icons/control/cap_dot.svg"),
|
||||
);
|
||||
const LineDottedIcon = importSvg(
|
||||
async () => import("../assets/icons/control/line_dotted.svg"),
|
||||
);
|
||||
const LineDashedIcon = importSvg(
|
||||
async () => import("../assets/icons/control/line_dashed.svg"),
|
||||
);
|
||||
const TableIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/tables.svg"),
|
||||
);
|
||||
const ColumnIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/column.svg"),
|
||||
);
|
||||
const GearIcon = importSvg(async () => import("../assets/icons/ads/gear.svg"));
|
||||
const UserV2Icon = importSvg(
|
||||
async () => import("../assets/icons/ads/user-v2.svg"),
|
||||
);
|
||||
const SupportIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/support.svg"),
|
||||
);
|
||||
const Snippet = importSvg(
|
||||
async () => import("../assets/icons/ads/snippet.svg"),
|
||||
);
|
||||
const WorkspaceIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/workspaceIcon.svg"),
|
||||
);
|
||||
const SettingIcon = importSvg(
|
||||
async () => import("../assets/icons/control/settings.svg"),
|
||||
);
|
||||
const DropdownIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/dropdown.svg"),
|
||||
);
|
||||
const ChatIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/app-icons/chat.svg"),
|
||||
);
|
||||
const JsIcon = importSvg(async () => import("../assets/icons/ads/js.svg"));
|
||||
const ExecuteIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/execute.svg"),
|
||||
);
|
||||
const PackageIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/package.svg"),
|
||||
);
|
||||
|
||||
const DevicesIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/devices.svg"),
|
||||
);
|
||||
const GridIcon = importSvg(async () => import("../assets/icons/ads/grid.svg"));
|
||||
const HistoryLineIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/history-line.svg"),
|
||||
);
|
||||
const SuccessLineIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/success-line.svg"),
|
||||
);
|
||||
const ErrorLineIcon = importSvg(
|
||||
async () => import("../assets/icons/ads/error-line.svg"),
|
||||
);
|
||||
const UpdatesIcon = importSvg(
|
||||
async () => import("../assets/icons/help/updates.svg"),
|
||||
);
|
||||
|
||||
// remix icons
|
||||
const AddMoreIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/AddCircleLineIcon"),
|
||||
);
|
||||
const AddMoreFillIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/AddCircleFillIcon"),
|
||||
);
|
||||
const ArrowLeftRightIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowLeftRightLineIcon"),
|
||||
);
|
||||
const ArrowDownLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowDownLineIcon"),
|
||||
);
|
||||
const BookIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/BookOpenLineIcon"),
|
||||
);
|
||||
const BugLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/BugLineIcon"),
|
||||
);
|
||||
const ChevronRight = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowRightSFillIcon"),
|
||||
);
|
||||
const CheckLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/CheckLineIcon"),
|
||||
);
|
||||
const CloseLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/CloseLineIcon"),
|
||||
);
|
||||
const CloseCircleIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/CloseCircleFillIcon"),
|
||||
);
|
||||
const CloseCircleLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/CloseCircleLineIcon"),
|
||||
);
|
||||
const CloudOfflineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/CloudOffLineIcon"),
|
||||
);
|
||||
const CommentContextMenu = importRemixIcon(
|
||||
async () => import("remixicon-react/More2FillIcon"),
|
||||
);
|
||||
const More2FillIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/More2FillIcon"),
|
||||
);
|
||||
const CompassesLine = importRemixIcon(
|
||||
async () => import("remixicon-react/CompassesLineIcon"),
|
||||
);
|
||||
const ContextMenuIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/MoreFillIcon"),
|
||||
);
|
||||
const CreateNewIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/AddLineIcon"),
|
||||
);
|
||||
const Database2Line = importRemixIcon(
|
||||
async () => import("remixicon-react/Database2LineIcon"),
|
||||
);
|
||||
const DatasourceIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/CloudFillIcon"),
|
||||
);
|
||||
const DeleteBin7 = importRemixIcon(
|
||||
async () => import("remixicon-react/DeleteBin7LineIcon"),
|
||||
);
|
||||
const DiscordIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/DiscordLineIcon"),
|
||||
);
|
||||
const DownArrow = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowDownSFillIcon"),
|
||||
);
|
||||
const Download = importRemixIcon(
|
||||
async () => import("remixicon-react/DownloadCloud2LineIcon"),
|
||||
);
|
||||
const DuplicateIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/FileCopyLineIcon"),
|
||||
);
|
||||
const EditIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/PencilFillIcon"),
|
||||
);
|
||||
const EditLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/EditLineIcon"),
|
||||
);
|
||||
const EditUnderlineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/EditLineIcon"),
|
||||
);
|
||||
const Emoji = importRemixIcon(
|
||||
async () => import("remixicon-react/EmotionLineIcon"),
|
||||
);
|
||||
const ExpandMore = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowDownSLineIcon"),
|
||||
);
|
||||
const DownArrowIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowDownSLineIcon"),
|
||||
);
|
||||
const ExpandLess = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowUpSLineIcon"),
|
||||
);
|
||||
const EyeOn = importRemixIcon(
|
||||
async () => import("remixicon-react/EyeLineIcon"),
|
||||
);
|
||||
const EyeOff = importRemixIcon(
|
||||
async () => import("remixicon-react/EyeOffLineIcon"),
|
||||
);
|
||||
const FileTransfer = importRemixIcon(
|
||||
async () => import("remixicon-react/FileTransferLineIcon"),
|
||||
);
|
||||
const FileLine = importRemixIcon(
|
||||
async () => import("remixicon-react/FileLineIcon"),
|
||||
);
|
||||
const Filter = importRemixIcon(
|
||||
async () => import("remixicon-react/Filter2FillIcon"),
|
||||
);
|
||||
const ForbidLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ForbidLineIcon"),
|
||||
);
|
||||
const GitMerge = importRemixIcon(
|
||||
async () => import("remixicon-react/GitMergeLineIcon"),
|
||||
);
|
||||
const GitCommit = importRemixIcon(
|
||||
async () => import("remixicon-react/GitCommitLineIcon"),
|
||||
);
|
||||
const GitPullRequst = importRemixIcon(
|
||||
async () => import("remixicon-react/GitPullRequestLineIcon"),
|
||||
);
|
||||
const GlobalLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/GlobalLineIcon"),
|
||||
);
|
||||
const GuideIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/GuideFillIcon"),
|
||||
);
|
||||
const HelpIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/QuestionMarkIcon"),
|
||||
);
|
||||
const LightbulbFlashLine = importRemixIcon(
|
||||
async () => import("remixicon-react/LightbulbFlashLineIcon"),
|
||||
);
|
||||
const LinksLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/LinksLineIcon"),
|
||||
);
|
||||
const InfoIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/InformationLineIcon"),
|
||||
);
|
||||
const KeyIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/Key2LineIcon"),
|
||||
);
|
||||
const LeftArrowIcon2 = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowLeftSLineIcon"),
|
||||
);
|
||||
const Link2 = importRemixIcon(async () => import("remixicon-react/LinkIcon"));
|
||||
const LeftArrowIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowLeftLineIcon"),
|
||||
);
|
||||
const NewsPaperLine = importRemixIcon(
|
||||
async () => import("remixicon-react/NewspaperLineIcon"),
|
||||
);
|
||||
const OvalCheck = importRemixIcon(
|
||||
async () => import("remixicon-react/CheckboxCircleLineIcon"),
|
||||
);
|
||||
const OvalCheckFill = importRemixIcon(
|
||||
async () => import("remixicon-react/CheckboxCircleFillIcon"),
|
||||
);
|
||||
const Pin3 = importRemixIcon(
|
||||
async () => import("remixicon-react/Pushpin2FillIcon"),
|
||||
);
|
||||
const PlayCircleLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/PlayCircleLineIcon"),
|
||||
);
|
||||
const QueryIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/CodeSSlashLineIcon"),
|
||||
);
|
||||
const RemoveIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/SubtractLineIcon"),
|
||||
);
|
||||
const RightArrowIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowRightLineIcon"),
|
||||
);
|
||||
const RightArrowIcon2 = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowRightSLineIcon"),
|
||||
);
|
||||
const RocketIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/RocketLineIcon"),
|
||||
);
|
||||
const SearchIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/SearchLineIcon"),
|
||||
);
|
||||
const SortAscIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/SortAscIcon"),
|
||||
);
|
||||
const SortDescIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/SortDescIcon"),
|
||||
);
|
||||
const ShareBoxLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ShareBoxLineIcon"),
|
||||
);
|
||||
const ShareBoxFillIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ShareBoxFillIcon"),
|
||||
);
|
||||
const ShareForwardIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ShareForwardFillIcon"),
|
||||
);
|
||||
const Trash = importRemixIcon(
|
||||
async () => import("remixicon-react/DeleteBinLineIcon"),
|
||||
);
|
||||
const UpArrow = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowUpSFillIcon"),
|
||||
);
|
||||
const WarningIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ErrorWarningFillIcon"),
|
||||
);
|
||||
const WarningLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ErrorWarningLineIcon"),
|
||||
);
|
||||
const LoginIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/LoginBoxLineIcon"),
|
||||
);
|
||||
const LogoutIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/LogoutBoxRLineIcon"),
|
||||
);
|
||||
const ShareLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ShareLineIcon"),
|
||||
);
|
||||
const LoaderLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/LoaderLineIcon"),
|
||||
);
|
||||
const WidgetIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/FunctionLineIcon"),
|
||||
);
|
||||
const RefreshLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/RefreshLineIcon"),
|
||||
);
|
||||
const GitBranchLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/GitBranchLineIcon"),
|
||||
);
|
||||
const EditBoxLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/EditBoxLineIcon"),
|
||||
);
|
||||
const StarLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/StarLineIcon"),
|
||||
);
|
||||
const StarFillIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/StarFillIcon"),
|
||||
);
|
||||
const Settings2LineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/Settings2LineIcon"),
|
||||
);
|
||||
const DownloadIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/DownloadLineIcon"),
|
||||
);
|
||||
const UploadCloud2LineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/UploadCloud2LineIcon"),
|
||||
);
|
||||
const DownloadLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/DownloadLineIcon"),
|
||||
);
|
||||
const UploadLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/UploadLineIcon"),
|
||||
);
|
||||
const FileListLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/FileListLineIcon"),
|
||||
);
|
||||
const HamburgerIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/MenuLineIcon"),
|
||||
);
|
||||
const MagicLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/MagicLineIcon"),
|
||||
);
|
||||
const UserHeartLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/UserHeartLineIcon"),
|
||||
);
|
||||
const DvdLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/DvdLineIcon"),
|
||||
);
|
||||
const Group2LineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/Group2LineIcon"),
|
||||
);
|
||||
const CodeViewIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/CodeViewIcon"),
|
||||
);
|
||||
const GroupLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/GroupLineIcon"),
|
||||
);
|
||||
const ArrowRightUpLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowRightUpLineIcon"),
|
||||
);
|
||||
const MailCheckLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/MailCheckLineIcon"),
|
||||
);
|
||||
const UserFollowLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/UserFollowLineIcon"),
|
||||
);
|
||||
const AddBoxLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/AddBoxLineIcon"),
|
||||
);
|
||||
const ArrowRightSFillIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowRightSFillIcon"),
|
||||
);
|
||||
const ArrowDownSFillIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowDownSFillIcon"),
|
||||
);
|
||||
const MailLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/MailLineIcon"),
|
||||
);
|
||||
const LockPasswordLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/LockPasswordLineIcon"),
|
||||
);
|
||||
const Timer2LineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/Timer2LineIcon"),
|
||||
);
|
||||
const MapPin2LineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/MapPin2LineIcon"),
|
||||
);
|
||||
const User3LineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/User3LineIcon"),
|
||||
);
|
||||
const User2LineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/User2LineIcon"),
|
||||
);
|
||||
const Key2LineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/Key2LineIcon"),
|
||||
);
|
||||
const FileList2LineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/FileList2LineIcon"),
|
||||
);
|
||||
const Lock2LineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/Lock2LineIcon"),
|
||||
);
|
||||
const SearchEyeLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/SearchEyeLineIcon"),
|
||||
);
|
||||
const AlertLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/AlertLineIcon"),
|
||||
);
|
||||
const SettingsLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/SettingsLineIcon"),
|
||||
);
|
||||
const LockUnlockLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/LockUnlockLineIcon"),
|
||||
);
|
||||
const PantoneLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/PantoneLineIcon"),
|
||||
);
|
||||
const QuestionFillIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/QuestionFillIcon"),
|
||||
);
|
||||
const QuestionLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/QuestionLineIcon"),
|
||||
);
|
||||
const UserSharedLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/UserSharedLineIcon"),
|
||||
);
|
||||
const UserReceived2LineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/UserReceived2LineIcon"),
|
||||
);
|
||||
const UserAddLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/UserAddLineIcon"),
|
||||
);
|
||||
const UserUnfollowLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/UserUnfollowLineIcon"),
|
||||
);
|
||||
const DeleteRowIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/DeleteRowIcon"),
|
||||
);
|
||||
const ArrowUpLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ArrowUpLineIcon"),
|
||||
);
|
||||
const MoneyDollarCircleLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/MoneyDollarCircleLineIcon"),
|
||||
);
|
||||
const ExternalLinkLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/ExternalLinkLineIcon"),
|
||||
);
|
||||
const PencilLineIcon = importRemixIcon(
|
||||
async () => import("remixicon-react/PencilLineIcon"),
|
||||
);
|
||||
|
||||
export enum IconSize {
|
||||
XXS = "extraExtraSmall",
|
||||
XS = "extraSmall",
|
||||
SMALL = "small",
|
||||
MEDIUM = "medium",
|
||||
LARGE = "large",
|
||||
XL = "extraLarge",
|
||||
XXL = "extraExtraLarge",
|
||||
XXXL = "extraExtraExtraLarge",
|
||||
XXXXL = "extraExtraExtraExtraLarge",
|
||||
}
|
||||
|
||||
const ICON_SIZE_LOOKUP = {
|
||||
[IconSize.XXS]: 8,
|
||||
[IconSize.XS]: 10,
|
||||
[IconSize.SMALL]: 12,
|
||||
[IconSize.MEDIUM]: 14,
|
||||
[IconSize.LARGE]: 15,
|
||||
[IconSize.XL]: 16,
|
||||
[IconSize.XXL]: 18,
|
||||
[IconSize.XXXL]: 20,
|
||||
[IconSize.XXXXL]: 22,
|
||||
undefined: 12,
|
||||
};
|
||||
|
||||
export const sizeHandler = (size?: IconSize): number => {
|
||||
return (
|
||||
ICON_SIZE_LOOKUP[size as keyof typeof ICON_SIZE_LOOKUP] ||
|
||||
ICON_SIZE_LOOKUP[IconSize.SMALL]
|
||||
);
|
||||
};
|
||||
|
||||
export const IconWrapper = styled.span<IconProps>`
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: ${(props) =>
|
||||
props.disabled ? "not-allowed" : props.clickable ? "pointer" : "default"};
|
||||
${(props) =>
|
||||
props.withWrapper &&
|
||||
`
|
||||
min-width: ${sizeHandler(props.size) * 2}px;
|
||||
height: ${sizeHandler(props.size) * 2}px;
|
||||
border-radius: 9999px;
|
||||
justify-content: center;
|
||||
background-color: ${props.wrapperColor || "rgba(0, 0, 0, 0.1)"};
|
||||
`}
|
||||
svg {
|
||||
width: ${(props) => sizeHandler(props.size)}px;
|
||||
height: ${(props) => sizeHandler(props.size)}px;
|
||||
${(props) =>
|
||||
!props.keepColors
|
||||
? `
|
||||
fill: ${props.fillColor || ""};
|
||||
circle {
|
||||
fill: ${props.fillColor || ""};
|
||||
}
|
||||
path {
|
||||
fill: ${props.fillColor || ""};
|
||||
}
|
||||
`
|
||||
: ""};
|
||||
${(props) => (props.invisible ? `visibility: hidden;` : null)};
|
||||
|
||||
&:hover {
|
||||
${(props) =>
|
||||
!props.keepColors
|
||||
? `
|
||||
fill: ${props.hoverFillColor || ""};
|
||||
path {
|
||||
fill: ${props.hoverFillColor || ""};
|
||||
}
|
||||
`
|
||||
: ""}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
function getControlIcon(iconName: string) {
|
||||
const ControlIcon = ControlIcons[iconName];
|
||||
return <ControlIcon height={24} width={24} />;
|
||||
}
|
||||
|
||||
const ICON_LOOKUP = {
|
||||
undefined: null,
|
||||
HEADING_ONE: getControlIcon("HEADING_ONE"),
|
||||
HEADING_THREE: getControlIcon("HEADING_THREE"),
|
||||
HEADING_TWO: getControlIcon("HEADING_TWO"),
|
||||
PARAGRAPH: getControlIcon("PARAGRAPH"),
|
||||
PARAGRAPH_TWO: getControlIcon("PARAGRAPH_TWO"),
|
||||
"add-box-line": <AddBoxLineIcon />,
|
||||
"add-more": <AddMoreIcon />,
|
||||
"add-more-fill": <AddMoreFillIcon />,
|
||||
"alert-line": <AlertLineIcon />,
|
||||
"arrow-down-s-fill": <ArrowDownSFillIcon />,
|
||||
"arrow-forward": <ArrowForwardIcon />,
|
||||
"arrow-left": <ArrowLeft />,
|
||||
"arrow-right-s-fill": <ArrowRightSFillIcon />,
|
||||
"arrow-right-up-line": <ArrowRightUpLineIcon />,
|
||||
"arrow-up-line": <ArrowUpLineIcon />,
|
||||
"book-line": <BookLineIcon />,
|
||||
"bug-line": <BugLineIcon />,
|
||||
"cap-dot": <CapDotIcon />,
|
||||
"cap-solid": <CapSolidIcon />,
|
||||
"card-context-menu": <CardContextMenu />,
|
||||
"chat-help": <ChatIcon />,
|
||||
"check-line": <CheckLineIcon />,
|
||||
"chevron-left": <ChevronLeft />,
|
||||
"chevron-right": <ChevronRight />,
|
||||
"close-circle": <CloseCircleIcon />,
|
||||
"close-circle-line": <CloseCircleLineIcon />,
|
||||
"close-modal": <CloseLineIcon />,
|
||||
"close-x": <CloseLineIcon />,
|
||||
"cloud-off-line": <CloudOfflineIcon />,
|
||||
"comment-context-menu": <CommentContextMenu />,
|
||||
"compasses-line": <CompassesLine />,
|
||||
"context-menu": <ContextMenuIcon />,
|
||||
"database-2-line": <Database2Line />,
|
||||
"delete-blank": <DeleteBin7 />,
|
||||
"delete-row": <DeleteRowIcon />,
|
||||
"double-arrow-right": <DoubleArrowRightIcon />,
|
||||
"down-arrow": <DownArrowIcon />,
|
||||
"down-arrow-2": <ArrowDownLineIcon />,
|
||||
"download-line": <DownloadLineIcon />,
|
||||
"edit-box-line": <EditBoxLineIcon />,
|
||||
"edit-line": <EditLineIcon />,
|
||||
"edit-underline": <EditUnderlineIcon />,
|
||||
"expand-less": <ExpandLess />,
|
||||
"expand-more": <ExpandMore />,
|
||||
"external-link-line": <ExternalLinkLineIcon />,
|
||||
"eye-off": <EyeOff />,
|
||||
"eye-on": <EyeOn />,
|
||||
"file-line": <FileLine />,
|
||||
"file-list-2-line": <FileList2LineIcon />,
|
||||
"file-list-line": <FileListLineIcon />,
|
||||
"file-transfer": <FileTransfer />,
|
||||
"fork-2": <Fork2Icon />,
|
||||
"forbid-line": <ForbidLineIcon />,
|
||||
"git-branch": <GitBranchLineIcon />,
|
||||
"git-commit": <GitCommit />,
|
||||
"git-pull-request": <GitPullRequst />,
|
||||
"global-line": <GlobalLineIcon />,
|
||||
"group-2-line": <Group2LineIcon />,
|
||||
"group-line": <GroupLineIcon />,
|
||||
"invite-user": <InviteUserIcon />,
|
||||
"key-2-line": <Key2LineIcon />,
|
||||
"left-arrow-2": <LeftArrowIcon2 />,
|
||||
"lightbulb-flash-line": <LightbulbFlashLine />,
|
||||
"line-dashed": <LineDashedIcon />,
|
||||
"line-dotted": <LineDottedIcon />,
|
||||
"link-2": <Link2 />,
|
||||
"links-line": <LinksLineIcon />,
|
||||
"lock-2-line": <Lock2LineIcon />,
|
||||
"lock-password-line": <LockPasswordLineIcon />,
|
||||
"lock-unlock-line": <LockUnlockLineIcon />,
|
||||
"magic-line": <MagicLineIcon />,
|
||||
"mail-check-line": <MailCheckLineIcon />,
|
||||
"mail-line": <MailLineIcon />,
|
||||
"map-pin-2-line": <MapPin2LineIcon />,
|
||||
"more-2-fill": <More2FillIcon />,
|
||||
"news-paper": <NewsPaperLine />,
|
||||
"no-response": <NoResponseIcon />,
|
||||
"oval-check": <OvalCheck />,
|
||||
"oval-check-fill": <OvalCheckFill />,
|
||||
"pin-3": <Pin3 />,
|
||||
"play-circle-line": <PlayCircleLineIcon />,
|
||||
"question-fill": <QuestionFillIcon />,
|
||||
"question-line": <QuestionLineIcon />,
|
||||
"reaction-2": <Reaction2 />,
|
||||
"read-pin": <ReadPin />,
|
||||
"right-arrow": <RightArrowIcon />,
|
||||
"right-arrow-2": <RightArrowIcon2 />,
|
||||
"search-eye-line": <SearchEyeLineIcon />,
|
||||
"send-button": <SendButton />,
|
||||
"settings-2-line": <Settings2LineIcon />,
|
||||
"settings-line": <SettingsLineIcon />,
|
||||
"share-2": <ShareIcon2 />,
|
||||
"share-box": <ShareBoxFillIcon />,
|
||||
"share-box-line": <ShareBoxLineIcon />,
|
||||
"share-line": <ShareLineIcon />,
|
||||
"sort-asc": <SortAscIcon />,
|
||||
"sort-desc": <SortDescIcon />,
|
||||
"star-fill": <StarFillIcon />,
|
||||
"star-line": <StarLineIcon />,
|
||||
"swap-horizontal": <ArrowLeftRightIcon />,
|
||||
"timer-2-line": <Timer2LineIcon />,
|
||||
"trash-outline": <TrashOutline />,
|
||||
"trending-flat": <TrendingFlat />,
|
||||
"unread-pin": <UnreadPin />,
|
||||
"upload-cloud": <UploadCloud2LineIcon />,
|
||||
"upload-line": <UploadLineIcon />,
|
||||
"user-2": <UserV2Icon />,
|
||||
"user-2-line": <User2LineIcon />,
|
||||
"user-3-line": <User3LineIcon />,
|
||||
"user-add-line": <UserAddLineIcon />,
|
||||
"user-follow-line": <UserFollowLineIcon />,
|
||||
"user-heart-line": <UserHeartLineIcon />,
|
||||
"user-received-2-line": <UserReceived2LineIcon />,
|
||||
"user-shared-line": <UserSharedLineIcon />,
|
||||
"user-unfollow-line": <UserUnfollowLineIcon />,
|
||||
"view-all": <RightArrowIcon />,
|
||||
"view-less": <LeftArrowIcon />,
|
||||
"warning-line": <WarningLineIcon />,
|
||||
"warning-triangle": <WarningTriangleIcon />,
|
||||
"money-dollar-circle-line": <MoneyDollarCircleLineIcon />,
|
||||
"success-line": <SuccessLineIcon />,
|
||||
"error-line": <ErrorLineIcon />,
|
||||
"history-line": <HistoryLineIcon />,
|
||||
billing: <BillingIcon />,
|
||||
book: <BookIcon />,
|
||||
bug: <BugIcon />,
|
||||
cancel: <CancelIcon />,
|
||||
chat: <Chat />,
|
||||
close: <CloseIcon />,
|
||||
code: <CodeViewIcon />,
|
||||
column: <ColumnIcon />,
|
||||
cross: <CrossIcon />,
|
||||
danger: <ErrorIcon />,
|
||||
datasource: <DatasourceIcon />,
|
||||
delete: <Trash />,
|
||||
desktop: <DesktopIcon />,
|
||||
discord: <DiscordIcon />,
|
||||
downArrow: <DownArrow />,
|
||||
download2: <DownloadIcon />,
|
||||
download: <Download />,
|
||||
dropdown: <DropdownIcon />,
|
||||
duplicate: <DuplicateIcon />,
|
||||
edit: <EditIcon />,
|
||||
emoji: <Emoji />,
|
||||
enterprise: <MagicLineIcon />,
|
||||
error: <ErrorIcon />,
|
||||
execute: <ExecuteIcon />,
|
||||
filter: <Filter />,
|
||||
fluid: <FluidIcon />,
|
||||
fork: <GitMerge />,
|
||||
gear: <GearIcon />,
|
||||
general: <GeneralIcon />,
|
||||
guide: <GuideIcon />,
|
||||
hamburger: <HamburgerIcon />,
|
||||
help: <HelpIcon />,
|
||||
info: <InfoIcon />,
|
||||
js: <JsIcon />,
|
||||
key: <KeyIcon />,
|
||||
lightning: <LightningIcon />,
|
||||
link: <LinkIcon />,
|
||||
loader: <LoaderLineIcon />,
|
||||
login: <LoginIcon />,
|
||||
logout: <LogoutIcon />,
|
||||
manage: <ManageIcon />,
|
||||
member: <UserHeartLineIcon />,
|
||||
minus: <RemoveIcon />,
|
||||
mobile: <MobileIcon />,
|
||||
open: <OpenIcon />,
|
||||
pantone: <PantoneLineIcon />,
|
||||
pin: <Pin />,
|
||||
play: <PlayIcon />,
|
||||
plus: <CreateNewIcon />,
|
||||
query: <QueryIcon />,
|
||||
reaction: <Reaction />,
|
||||
refresh: <RefreshLineIcon />,
|
||||
rocket: <RocketIcon />,
|
||||
search: <SearchIcon />,
|
||||
setting: <SettingIcon />,
|
||||
share: <ShareForwardIcon />,
|
||||
shine: <ShineIcon />,
|
||||
snippet: <Snippet />,
|
||||
success: <SuccessIcon />,
|
||||
support: <SupportIcon />,
|
||||
tables: <TableIcon />,
|
||||
tablet: <TabletIcon />,
|
||||
tabletLandscape: <TabletLandscapeIcon />,
|
||||
trash: <Trash />,
|
||||
unpin: <Unpin />,
|
||||
upArrow: <UpArrow />,
|
||||
upgrade: <DvdLineIcon />,
|
||||
upload: <Upload />,
|
||||
user: <UserIcon />,
|
||||
wand: <WandIcon />,
|
||||
warning: <WarningIcon />,
|
||||
widget: <WidgetIcon />,
|
||||
workspace: <WorkspaceIcon />,
|
||||
"clear-interval": <ClearInterval />,
|
||||
"clear-store": <ClearStore />,
|
||||
"copy-to-clipboard": <CopyToClipboard />,
|
||||
"download-action": <DownloadAction />,
|
||||
"execute-js": <ExecuteJs />,
|
||||
"execute-query": <ExecuteQuery />,
|
||||
"get-geolocation": <GetGeolocation />,
|
||||
modal: <Modal />,
|
||||
"navigate-to": <NavigateTo />,
|
||||
"remove-store": <RemoveStore />,
|
||||
"reset-widget": <ResetWidget />,
|
||||
"set-interval": <SetInterval />,
|
||||
"show-alert": <ShowAlert />,
|
||||
"stop-watch-geolocation": <StopWatchGeolocation />,
|
||||
"store-value": <StoreValue />,
|
||||
"watch-geolocation": <WatchGeolocation />,
|
||||
"run-api": <RunAPI />,
|
||||
"post-message": <PostMessage />,
|
||||
"no-action": <NoAction />,
|
||||
package: <PackageIcon />,
|
||||
devices: <DevicesIcon />,
|
||||
grid: <GridIcon />,
|
||||
updates: <UpdatesIcon />,
|
||||
"pencil-line": <PencilLineIcon />,
|
||||
};
|
||||
|
||||
export const IconCollection = Object.keys(ICON_LOOKUP);
|
||||
|
||||
export type IconName = (typeof IconCollection)[number];
|
||||
|
||||
export interface IconProps {
|
||||
size?: IconSize;
|
||||
name?: IconName;
|
||||
invisible?: boolean;
|
||||
className?: string;
|
||||
onClick?: (e: React.MouseEvent) => void;
|
||||
fillColor?: string;
|
||||
hoverFillColor?: string;
|
||||
keepColors?: boolean;
|
||||
loaderWithIconWrapper?: boolean;
|
||||
clickable?: boolean;
|
||||
disabled?: boolean;
|
||||
withWrapper?: boolean;
|
||||
wrapperColor?: string;
|
||||
}
|
||||
|
||||
const Icon = forwardRef(
|
||||
(
|
||||
{ onClick, ...props }: IconProps & CommonComponentProps,
|
||||
ref: Ref<HTMLSpanElement>,
|
||||
) => {
|
||||
const iconName = props.name;
|
||||
const returnIcon =
|
||||
ICON_LOOKUP[iconName as keyof typeof ICON_LOOKUP] || null;
|
||||
|
||||
const clickable = props.clickable === undefined ? true : props.clickable;
|
||||
|
||||
let loader = <Spinner size={props.size} />;
|
||||
if (props.loaderWithIconWrapper) {
|
||||
loader = (
|
||||
<IconWrapper className={Classes.ICON} clickable={clickable} {...props}>
|
||||
<Spinner size={props.size} />
|
||||
</IconWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return returnIcon && !props.isLoading ? (
|
||||
<IconWrapper
|
||||
className={`${Classes.ICON} ${props.className}`}
|
||||
clickable={clickable}
|
||||
data-cy={props.cypressSelector}
|
||||
onClick={props.disabled ? noop : onClick}
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
{returnIcon}
|
||||
</IconWrapper>
|
||||
) : props.isLoading ? (
|
||||
loader
|
||||
) : null;
|
||||
},
|
||||
);
|
||||
|
||||
Icon.displayName = "Icon";
|
||||
|
||||
export default React.memo(Icon);
|
||||
|
|
@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from "react";
|
|||
import styled from "styled-components";
|
||||
import type { AppIconName } from "../AppIcon";
|
||||
import AppIcon, { AppIconCollection } from "../AppIcon";
|
||||
import { Size } from "../Button";
|
||||
import { Size } from "../AppIcon";
|
||||
import type { CommonComponentProps } from "../types/common";
|
||||
import { Classes } from "../constants/classes";
|
||||
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@ import React, { forwardRef } from "react";
|
|||
import type { CommonComponentProps } from "../types/common";
|
||||
import { Classes } from "../constants/classes";
|
||||
import styled from "styled-components";
|
||||
import type { IconName } from "../Icon";
|
||||
import Icon, { IconSize } from "../Icon";
|
||||
import type { IconNames } from "@appsmith/ads";
|
||||
import { Icon } from "@appsmith/ads";
|
||||
import TooltipComponent from "../Tooltip";
|
||||
import Text, { TextType, FontWeight } from "../Text";
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||
import type { PopoverPosition } from "@blueprintjs/core/lib/esnext/components/popover/popoverSharedProps";
|
||||
|
||||
export type MenuItemProps = CommonComponentProps & {
|
||||
icon?: IconName;
|
||||
icon?: IconNames;
|
||||
text: string;
|
||||
label?: ReactNode;
|
||||
href?: string;
|
||||
|
|
@ -98,14 +98,7 @@ const MenuItemContent = forwardRef(
|
|||
type={props.type}
|
||||
>
|
||||
<IconContainer className={props.containerClassName}>
|
||||
{props.icon ? (
|
||||
<Icon
|
||||
isLoading={props.isLoading}
|
||||
loaderWithIconWrapper
|
||||
name={props.icon}
|
||||
size={IconSize.LARGE}
|
||||
/>
|
||||
) : null}
|
||||
{props.icon ? <Icon name={props.icon} size="md" /> : null}
|
||||
{props.text && (
|
||||
<Text type={TextType.H5} weight={FontWeight.NORMAL}>
|
||||
{props.ellipsize
|
||||
|
|
|
|||
|
|
@ -1,59 +0,0 @@
|
|||
import React from "react";
|
||||
import styled, { keyframes } from "styled-components";
|
||||
import type { IconSize } from "../Icon";
|
||||
import { sizeHandler } from "../Icon";
|
||||
import { Classes } from "../constants/classes";
|
||||
|
||||
const rotate = keyframes`
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
`;
|
||||
|
||||
const dash = keyframes`
|
||||
0% {
|
||||
stroke-dasharray: 1, 150;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
50% {
|
||||
stroke-dasharray: 90, 150;
|
||||
stroke-dashoffset: -35;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 90, 150;
|
||||
stroke-dashoffset: -124;
|
||||
}
|
||||
`;
|
||||
|
||||
const SvgContainer = styled.svg<SpinnerProp>`
|
||||
animation: ${rotate} 2s linear infinite;
|
||||
width: ${(props) => sizeHandler(props.size)}px;
|
||||
height: ${(props) => sizeHandler(props.size)}px;
|
||||
`;
|
||||
|
||||
const SvgCircle = styled.circle`
|
||||
stroke: var(--ads-v2-color-fg-subtle);
|
||||
stroke-linecap: round;
|
||||
animation: ${dash} 1.5s ease-in-out infinite;
|
||||
stroke-width: var(--ads-spaces-1);
|
||||
`;
|
||||
|
||||
export interface SpinnerProp {
|
||||
size?: IconSize;
|
||||
}
|
||||
|
||||
Spinner.defaultProp = {
|
||||
size: "small",
|
||||
};
|
||||
|
||||
export default function Spinner(props: SpinnerProp) {
|
||||
return (
|
||||
<SvgContainer
|
||||
className={Classes.SPINNER}
|
||||
size={props.size}
|
||||
viewBox="0 0 50 50"
|
||||
>
|
||||
<SvgCircle cx="25" cy="25" fill="none" r="20" />
|
||||
</SvgContainer>
|
||||
);
|
||||
}
|
||||
|
|
@ -3,8 +3,7 @@ import React from "react";
|
|||
import styled from "styled-components";
|
||||
import { Classes } from "../constants/classes";
|
||||
import { typography } from "../constants/typography";
|
||||
import Spinner from "../Spinner";
|
||||
import { IconSize } from "../Icon";
|
||||
import { Spinner } from "@appsmith/ads";
|
||||
import { importSvg } from "../utils/icon-loadables";
|
||||
|
||||
const DownArrow = importSvg(
|
||||
|
|
@ -192,11 +191,7 @@ function Table(props: TableProps) {
|
|||
<tr className="no-hover">
|
||||
<td className="no-border" colSpan={columns?.length}>
|
||||
<CentralizedWrapper>
|
||||
{loaderComponent ? (
|
||||
loaderComponent
|
||||
) : (
|
||||
<Spinner size={IconSize.XXL} />
|
||||
)}
|
||||
{loaderComponent ? loaderComponent : <Spinner size="lg" />}
|
||||
</CentralizedWrapper>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -1,426 +0,0 @@
|
|||
import type { RefObject } from "react";
|
||||
import React, { useCallback, useState, useEffect } from "react";
|
||||
import { Tab, Tabs, TabList, TabPanel } from "react-tabs";
|
||||
import "react-tabs/style/react-tabs.css";
|
||||
import styled from "styled-components";
|
||||
import type { IconName } from "../Icon";
|
||||
import Icon, { IconSize } from "../Icon";
|
||||
import { useResizeObserver } from "../hooks";
|
||||
import { Classes } from "../constants/classes";
|
||||
import type { CommonComponentProps } from "../types/common";
|
||||
import { typography } from "../constants/typography";
|
||||
|
||||
export const TAB_MIN_HEIGHT = `36px`;
|
||||
|
||||
export interface TabProp {
|
||||
key: string;
|
||||
title: string;
|
||||
count?: number;
|
||||
panelComponent?: JSX.Element;
|
||||
icon?: IconName;
|
||||
iconSize?: IconSize;
|
||||
}
|
||||
|
||||
const TabsWrapper = styled.div<{
|
||||
shouldOverflow?: boolean;
|
||||
vertical?: boolean;
|
||||
responseViewer?: boolean;
|
||||
}>`
|
||||
border-radius: 0px;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
.react-tabs {
|
||||
height: 100%;
|
||||
}
|
||||
.react-tabs__tab-panel {
|
||||
height: calc(100% - ${TAB_MIN_HEIGHT});
|
||||
overflow: auto;
|
||||
}
|
||||
.react-tabs__tab-list {
|
||||
margin: 0px;
|
||||
display: flex;
|
||||
flex-direction: ${(props) => (!!props.vertical ? "column" : "row")};
|
||||
align-items: ${(props) => (!!props.vertical ? "stretch" : "center")};
|
||||
border-bottom: none;
|
||||
color: var(--ads-tabs-default-tab-list-text-color);
|
||||
path {
|
||||
fill: var(--ads-tabs-default-tab-list-svg-fill-color);
|
||||
}
|
||||
${(props) =>
|
||||
props.shouldOverflow &&
|
||||
`
|
||||
overflow-y: hidden;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.responseViewer &&
|
||||
`
|
||||
margin-left: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 24px;
|
||||
background-color: var(--ads-tabs-default-tab-list-response-viewer-background-color) !important;
|
||||
width: fit-content;
|
||||
padding-left: 1px;
|
||||
margin-top: 10px !important;
|
||||
margin-bottom: 10px !important;
|
||||
`}
|
||||
}
|
||||
.react-tabs__tab {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
border-color: transparent;
|
||||
position: relative;
|
||||
|
||||
padding: 0px 3px;
|
||||
margin-right: ${(props) =>
|
||||
!props.vertical ? `calc(var(--ads-spaces-12) - 3px)` : 0};
|
||||
}
|
||||
|
||||
.react-tabs__tab,
|
||||
.react-tabs__tab:focus {
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
&:after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.responseViewer &&
|
||||
`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
height: 22px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid var(--ads-tabs-default-tab-focus-response-viewer-border-color);
|
||||
margin-right: -1px;
|
||||
margin-left: -1px;
|
||||
margin-top: -2px;
|
||||
height: 100%;
|
||||
`}
|
||||
}
|
||||
|
||||
.react-tabs__tab--selected {
|
||||
background-color: transparent;
|
||||
path {
|
||||
fill: var(--ads-tabs-tab-selected-svg-fill-color);
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.responseViewer &&
|
||||
`
|
||||
background-color: var(--ads-tabs-tab-selected-response-viewer-background-color);
|
||||
border: 1px solid var(--ads-tabs-tab-selected-response-viewer-border-color);
|
||||
border-radius: 0px;
|
||||
font-weight: normal;
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
export const TabTitle = styled.span<{ responseViewer?: boolean }>`
|
||||
font-size: ${typography.h5.fontSize}px;
|
||||
font-weight: var(--ads-font-weight-bold);
|
||||
line-height: var(--ads-spaces-6);
|
||||
letter-spacing: ${typography.h5.letterSpacing}px;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
${(props) =>
|
||||
props.responseViewer &&
|
||||
`
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
line-height: 16px;
|
||||
letter-spacing: normal;
|
||||
text-transform: uppercase;
|
||||
color: var(--ads-tabs-tab-title-response-viewer-text-color);
|
||||
`}
|
||||
`;
|
||||
|
||||
export const TabCount = styled.div`
|
||||
background-color: var(--ads-tabs-count-background-color);
|
||||
border-radius: 8px;
|
||||
min-width: 17px;
|
||||
height: 17px;
|
||||
font-size: 9px;
|
||||
margin-left: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 2px;
|
||||
`;
|
||||
|
||||
const TabTitleWrapper = styled.div<{
|
||||
selected: boolean;
|
||||
vertical: boolean;
|
||||
responseViewer?: boolean;
|
||||
}>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
padding: calc(var(--ads-spaces-3) - 1px)
|
||||
${(props) => (props.vertical ? `calc(var(--ads-spaces-4) - 1px)` : 0)}
|
||||
calc(var(--ads-spaces-4) - 1px)
|
||||
${(props) => (props.vertical ? `calc(var(--ads-spaces-4) - 1px)` : 0)};
|
||||
color: var(--ads-tabs-title-wrapper-text-color);
|
||||
&:hover {
|
||||
color: var(--ads-tabs-title-wrapper-hover-text-color);
|
||||
.${Classes.ICON} {
|
||||
svg {
|
||||
fill: var(--ads-tabs-title-wrapper-hover-text-color);
|
||||
path {
|
||||
fill: var(--ads-tabs-title-wrapper-hover-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.responseViewer &&
|
||||
`
|
||||
padding: 0px;
|
||||
`}
|
||||
|
||||
.${Classes.ICON} {
|
||||
margin-right: var(--ads-spaces-1);
|
||||
border-radius: 50%;
|
||||
svg {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: auto;
|
||||
fill: var(--ads-tabs-title-wrapper-icon-fill-color);
|
||||
path {
|
||||
fill: var(--ads-tabs-title-wrapper-icon-fill-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
props.selected
|
||||
? `
|
||||
background-color: transparent;
|
||||
color: var(--ads-color-black-900);
|
||||
.${Classes.ICON} {
|
||||
svg {
|
||||
path {
|
||||
fill: var(--ads-color-black-900)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-title {
|
||||
${
|
||||
props.responseViewer &&
|
||||
`
|
||||
font-weight: normal;
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: ${props.vertical ? `calc(var(--ads-spaces-1) - 2px)` : "100%"};
|
||||
bottom: ${props.vertical ? "0%" : `calc(var(--ads-spaces-0) - 1px)`};
|
||||
top: ${
|
||||
props.vertical ? `calc(var(--ads-spaces-0) - 1px)` : "calc(100% - 2px)"
|
||||
};
|
||||
left: var(--ads-spaces-0);
|
||||
height: ${props.vertical ? "100%" : `calc(var(--ads-spaces-1) - 2px)`};
|
||||
background-color: var(--ads-color-brand);
|
||||
z-index: var(--ads-z-index-3);
|
||||
|
||||
${
|
||||
props.responseViewer &&
|
||||
`
|
||||
display: none;
|
||||
`
|
||||
}
|
||||
}
|
||||
`
|
||||
: ""}
|
||||
`;
|
||||
|
||||
const CollapseIconWrapper = styled.div`
|
||||
position: absolute;
|
||||
right: 14px;
|
||||
top: calc(var(--ads-spaces-3) - 1px);
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
export interface TabItemProps {
|
||||
tab: TabProp;
|
||||
selected: boolean;
|
||||
vertical: boolean;
|
||||
responseViewer?: boolean;
|
||||
}
|
||||
|
||||
function DefaultTabItem(props: TabItemProps) {
|
||||
const { responseViewer, selected, tab, vertical } = props;
|
||||
return (
|
||||
<TabTitleWrapper
|
||||
responseViewer={responseViewer}
|
||||
selected={selected}
|
||||
vertical={vertical}
|
||||
>
|
||||
{tab.icon ? (
|
||||
<Icon
|
||||
name={tab.icon}
|
||||
size={tab.iconSize != null ? tab.iconSize : IconSize.XXXL}
|
||||
/>
|
||||
) : null}
|
||||
<TabTitle className="tab-title" responseViewer={responseViewer}>
|
||||
{tab.title}
|
||||
</TabTitle>
|
||||
{tab.count && tab.count > 0 ? (
|
||||
<TabCount data-testid="t--tab-count">{tab.count}</TabCount>
|
||||
) : null}
|
||||
</TabTitleWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
export type TabbedViewComponentType = CommonComponentProps & {
|
||||
tabs: Array<TabProp>;
|
||||
selectedIndex?: number;
|
||||
onSelect?: (tabIndex: number) => void;
|
||||
overflow?: boolean;
|
||||
vertical?: boolean;
|
||||
tabItemComponent?: (props: TabItemProps) => JSX.Element;
|
||||
responseViewer?: boolean;
|
||||
canCollapse?: boolean;
|
||||
// Reference to container for collapsing or expanding content
|
||||
containerRef?: RefObject<HTMLElement>;
|
||||
// height of container when expanded
|
||||
expandedHeight?: string;
|
||||
};
|
||||
|
||||
// Props required to support a collapsible (foldable) tab component
|
||||
export interface CollapsibleTabProps {
|
||||
// Reference to container for collapsing or expanding content
|
||||
containerRef: RefObject<HTMLDivElement>;
|
||||
// height of container when expanded( usually the default height of the tab component)
|
||||
expandedHeight: string;
|
||||
}
|
||||
|
||||
export type CollapsibleTabbedViewComponentType = TabbedViewComponentType &
|
||||
CollapsibleTabProps;
|
||||
|
||||
export const collapsibleTabRequiredPropKeys: Array<keyof CollapsibleTabProps> =
|
||||
["containerRef", "expandedHeight"];
|
||||
|
||||
// Tab is considered collapsible only when all required collapsible props are present
|
||||
export const isCollapsibleTabComponent = (
|
||||
props: TabbedViewComponentType | CollapsibleTabbedViewComponentType,
|
||||
): props is CollapsibleTabbedViewComponentType =>
|
||||
collapsibleTabRequiredPropKeys.every((key) => key in props);
|
||||
|
||||
export function TabComponent(
|
||||
props: TabbedViewComponentType | CollapsibleTabbedViewComponentType,
|
||||
) {
|
||||
const { onSelect, tabItemComponent } = props;
|
||||
const TabItem = tabItemComponent || DefaultTabItem;
|
||||
// for setting selected state of an uncontrolled component
|
||||
const [selectedIndex, setSelectedIndex] = useState(props.selectedIndex || 0);
|
||||
const [isExpanded, setIsExpanded] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof props.selectedIndex === "number")
|
||||
setSelectedIndex(props.selectedIndex);
|
||||
}, [props.selectedIndex]);
|
||||
|
||||
const toggleCollapse = () => {
|
||||
if (!isCollapsibleTabComponent(props)) return;
|
||||
const { containerRef, expandedHeight } = props;
|
||||
if (containerRef?.current && expandedHeight) {
|
||||
containerRef.current.style.height = isExpanded
|
||||
? TAB_MIN_HEIGHT
|
||||
: expandedHeight;
|
||||
}
|
||||
setIsExpanded((prev) => !prev);
|
||||
};
|
||||
|
||||
const resizeCallback = useCallback(
|
||||
(entries: ResizeObserverEntry[]) => {
|
||||
if (entries && entries.length) {
|
||||
const {
|
||||
contentRect: { height },
|
||||
} = entries[0];
|
||||
if (height > Number(TAB_MIN_HEIGHT.replace("px", "")) + 6) {
|
||||
!isExpanded && setIsExpanded(true);
|
||||
} else {
|
||||
isExpanded && setIsExpanded(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
[isExpanded],
|
||||
);
|
||||
|
||||
useResizeObserver(
|
||||
isCollapsibleTabComponent(props) ? props.containerRef?.current : null,
|
||||
resizeCallback,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isCollapsibleTabComponent(props)) return;
|
||||
const { containerRef } = props;
|
||||
if (!isExpanded && containerRef.current) {
|
||||
containerRef.current.style.height = TAB_MIN_HEIGHT;
|
||||
}
|
||||
}, [isExpanded]);
|
||||
|
||||
return (
|
||||
<TabsWrapper
|
||||
className={props.className}
|
||||
data-cy={props.cypressSelector}
|
||||
responseViewer={props.responseViewer}
|
||||
shouldOverflow={props.overflow}
|
||||
vertical={props.vertical}
|
||||
>
|
||||
{isCollapsibleTabComponent(props) && (
|
||||
<CollapseIconWrapper className="t--tabs-collapse-icon">
|
||||
<Icon
|
||||
name={isExpanded ? "expand-more" : "expand-less"}
|
||||
onClick={toggleCollapse}
|
||||
size={IconSize.XXXXL}
|
||||
/>
|
||||
</CollapseIconWrapper>
|
||||
)}
|
||||
|
||||
<Tabs
|
||||
onSelect={(index: number) => {
|
||||
onSelect ? onSelect(index) : setSelectedIndex(index);
|
||||
!isExpanded && toggleCollapse();
|
||||
}}
|
||||
selectedIndex={props.selectedIndex}
|
||||
>
|
||||
<TabList>
|
||||
{props.tabs.map((tab, index) => (
|
||||
<Tab
|
||||
data-cy={`t--tab-${tab.key}`}
|
||||
data-replay-id={tab.key}
|
||||
key={tab.key}
|
||||
>
|
||||
<TabItem
|
||||
responseViewer={props.responseViewer}
|
||||
selected={
|
||||
index === props.selectedIndex || index === selectedIndex
|
||||
}
|
||||
tab={tab}
|
||||
vertical={!!props.vertical}
|
||||
/>
|
||||
</Tab>
|
||||
))}
|
||||
</TabList>
|
||||
{props.tabs.map((tab) => (
|
||||
<TabPanel key={tab.key}>{tab.panelComponent}</TabPanel>
|
||||
))}
|
||||
</Tabs>
|
||||
</TabsWrapper>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,475 +0,0 @@
|
|||
import type { EventHandler, FocusEvent, Ref } from "react";
|
||||
import React, {
|
||||
forwardRef,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from "react";
|
||||
import type { CommonComponentProps } from "../types/common";
|
||||
import { Classes } from "../constants/classes";
|
||||
import { typography } from "../constants/typography";
|
||||
import { Classes as BlueprintClasses } from "@blueprintjs/core";
|
||||
import styled from "styled-components";
|
||||
import Text, { TextType } from "../Text";
|
||||
import {
|
||||
ERROR_MESSAGE_NAME_EMPTY,
|
||||
createMessage,
|
||||
FORM_VALIDATION_INVALID_EMAIL,
|
||||
} from "../constants/messages";
|
||||
import type { IconName } from "../Icon";
|
||||
import Icon, { IconCollection, IconSize } from "../Icon";
|
||||
import { AsyncControllableInput } from "@blueprintjs/core/lib/esm/components/forms/asyncControllableInput";
|
||||
import _ from "lodash";
|
||||
import { replayHighlightClass } from "../constants/classes";
|
||||
import { hexToRgba } from "../utils/colors";
|
||||
|
||||
export type InputType = "text" | "password" | "number" | "email" | "tel";
|
||||
|
||||
export type Validator = (value: string) => {
|
||||
isValid: boolean;
|
||||
message: string;
|
||||
};
|
||||
|
||||
// TODO (abhinav): Use a regex which adheres to standards RFC5322
|
||||
const isEmail = (value: string) => {
|
||||
const re =
|
||||
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
return re.test(value);
|
||||
};
|
||||
|
||||
export function emailValidator(email: string) {
|
||||
let isValid = true;
|
||||
if (email) {
|
||||
isValid = isEmail(email);
|
||||
}
|
||||
return {
|
||||
isValid: isValid,
|
||||
message: !isValid ? createMessage(FORM_VALIDATION_INVALID_EMAIL) : "",
|
||||
};
|
||||
}
|
||||
|
||||
export function notEmptyValidator(value: string) {
|
||||
const isValid = !!value;
|
||||
return {
|
||||
isValid: isValid,
|
||||
message: !isValid ? createMessage(ERROR_MESSAGE_NAME_EMPTY) : "",
|
||||
};
|
||||
}
|
||||
|
||||
export type TextInputProps = CommonComponentProps & {
|
||||
autoFocus?: boolean;
|
||||
placeholder?: string;
|
||||
fill?: boolean;
|
||||
defaultValue?: string;
|
||||
value?: string;
|
||||
validator?: (value: string) => { isValid: boolean; message: string };
|
||||
onChange?: (value: string) => void;
|
||||
readOnly?: boolean;
|
||||
dataType?: string;
|
||||
leftIcon?: IconName;
|
||||
prefix?: string;
|
||||
helperText?: string;
|
||||
rightSideComponent?: React.ReactNode;
|
||||
width?: string;
|
||||
height?: string;
|
||||
noBorder?: boolean;
|
||||
noCaret?: boolean;
|
||||
onBlur?: EventHandler<FocusEvent<any>>;
|
||||
onFocus?: EventHandler<FocusEvent<any>>;
|
||||
errorMsg?: string;
|
||||
trimValue?: boolean;
|
||||
$padding?: string;
|
||||
useTextArea?: boolean;
|
||||
isCopy?: boolean;
|
||||
border?: boolean;
|
||||
style?: any;
|
||||
tabIndex?: number;
|
||||
};
|
||||
|
||||
interface boxReturnType {
|
||||
bgColor: string;
|
||||
color: string;
|
||||
borderColor: string;
|
||||
}
|
||||
|
||||
const boxStyles = (props: TextInputProps, isValid: boolean): boxReturnType => {
|
||||
let bgColor = "var(--ads-text-input-text-box-default-background-color)";
|
||||
let color = "var(--ads-text-input-text-box-default-text-color)";
|
||||
let borderColor = "var(--ads-text-input-text-box-default-border-color)";
|
||||
|
||||
if (props.disabled) {
|
||||
bgColor = "var(--ads-text-input-text-box-disabled-background-color)";
|
||||
color = "var(--ads-text-input-text-box-disabled-text-color)";
|
||||
borderColor = "var(--ads-text-input-text-box-disabled-border-color)";
|
||||
}
|
||||
if (props.readOnly) {
|
||||
bgColor = "var(--ads-text-input-text-box-read-only-background-color)";
|
||||
color = "var(--ads-text-input-text-box-read-only-text-color)";
|
||||
borderColor = "var(--ads-text-input-text-box-read-only-border-color)";
|
||||
}
|
||||
if (!isValid) {
|
||||
bgColor = hexToRgba("var(--ads-danger-main)", 0.1);
|
||||
color = "var(--ads-danger-main)";
|
||||
borderColor = "var(--ads-danger-main)";
|
||||
}
|
||||
return { bgColor, color, borderColor };
|
||||
};
|
||||
|
||||
const InputLoader = styled.div<{
|
||||
$value?: string;
|
||||
$noBorder?: boolean;
|
||||
$isFocused?: boolean;
|
||||
$isLoading?: boolean;
|
||||
$height?: string;
|
||||
}>`
|
||||
display: ${(props) => (props.$isLoading ? "static" : "none")};
|
||||
border-radius: 0;
|
||||
width: ${(props) =>
|
||||
props.$value && !props.$noBorder && props.$isFocused
|
||||
? "calc(100% - 50px)"
|
||||
: "100%"};
|
||||
|
||||
height: ${(props) => props.$height || "36px"};
|
||||
`;
|
||||
|
||||
const StyledInput = styled((props) => {
|
||||
// we are removing non input related props before passing them in the components
|
||||
// eslint-disable @typescript-eslint/no-unused-vars
|
||||
const { dataType, inputRef, ...inputProps } = props;
|
||||
|
||||
const omitProps = [
|
||||
"hasLeftIcon",
|
||||
"inputStyle",
|
||||
"rightSideComponentWidth",
|
||||
"validator",
|
||||
"isValid",
|
||||
"cypressSelector",
|
||||
"leftIcon",
|
||||
"helperText",
|
||||
"rightSideComponent",
|
||||
"noBorder",
|
||||
"isLoading",
|
||||
"noCaret",
|
||||
"fill",
|
||||
"errorMsg",
|
||||
"useTextArea",
|
||||
"border",
|
||||
"asyncControl",
|
||||
"handleCopy",
|
||||
"prefix",
|
||||
];
|
||||
|
||||
const HtmlTag = props.useTextArea ? "textarea" : "input";
|
||||
|
||||
return props.asyncControl ? (
|
||||
<AsyncControllableInput
|
||||
{..._.omit(inputProps, omitProps)}
|
||||
datatype={dataType}
|
||||
inputRef={inputRef}
|
||||
/>
|
||||
) : (
|
||||
<HtmlTag ref={inputRef} {..._.omit(inputProps, omitProps)} />
|
||||
);
|
||||
})<
|
||||
TextInputProps & {
|
||||
inputStyle: boxReturnType;
|
||||
isValid: boolean;
|
||||
rightSideComponentWidth: number;
|
||||
hasLeftIcon: boolean;
|
||||
$isLoading?: boolean;
|
||||
}
|
||||
>`
|
||||
display: ${(props) => (props.$isLoading ? "none" : "static")};
|
||||
${(props) => (props.noCaret ? "caret-color: white;" : null)};
|
||||
color: ${(props) => props.inputStyle.color};
|
||||
width: ${(props) =>
|
||||
props.value && !props.noBorder && props.isFocused
|
||||
? "calc(100% - 50px)"
|
||||
: "100%"};
|
||||
border-radius: 0;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
padding: 0px var(--ads-spaces-6);
|
||||
${(props) => (props.$padding ? `padding: ${props.$padding}` : "")};
|
||||
padding-right: ${(props) =>
|
||||
`calc(${props.rightSideComponentWidth}px + var(--ads-spaces-6))`};
|
||||
background-color: transparent;
|
||||
font-size: ${typography.p1.fontSize}px;
|
||||
font-weight: ${typography.p1.fontWeight};
|
||||
line-height: ${typography.p1.lineHeight}px;
|
||||
letter-spacing: ${typography.p1.letterSpacing}px;
|
||||
text-overflow: ellipsis;
|
||||
height: 100%;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--ads-text-input-placeholder-text-color);
|
||||
}
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
`;
|
||||
|
||||
export const InputWrapper = styled.div<{
|
||||
value?: string;
|
||||
isFocused: boolean;
|
||||
fill?: number;
|
||||
noBorder?: boolean;
|
||||
height?: string;
|
||||
width?: string;
|
||||
inputStyle: boxReturnType;
|
||||
isValid?: boolean;
|
||||
disabled?: boolean;
|
||||
$isLoading?: boolean;
|
||||
readOnly?: boolean;
|
||||
}>`
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: ${(props) =>
|
||||
props.fill ? "100%" : props.width ? props.width : "260px"};
|
||||
height: ${(props) => props.height || "36px"};
|
||||
border: 1.2px solid
|
||||
${(props) =>
|
||||
props.noBorder ? "transparent" : props.inputStyle.borderColor};
|
||||
background-color: ${(props) => props.inputStyle.bgColor};
|
||||
color: ${(props) => props.inputStyle.color};
|
||||
${(props) =>
|
||||
props.isFocused && !props.noBorder && !props.disabled && !props.readOnly
|
||||
? `
|
||||
border: 1.2px solid
|
||||
${
|
||||
props.isValid
|
||||
? "var(--appsmith-input-focus-border-color)"
|
||||
: "var(--ads-danger-main)"
|
||||
};
|
||||
`
|
||||
: null}
|
||||
|
||||
.${Classes.TEXT} {
|
||||
color: var(--ads-danger-main);
|
||||
}
|
||||
.helper {
|
||||
.${Classes.TEXT} {
|
||||
color: var(--ads-text-input-helper-text-text-color);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: ${(props) =>
|
||||
props.disabled || props.readOnly
|
||||
? props.inputStyle.bgColor
|
||||
: "var(--ads-text-input-text-box-hover-background-color)"};
|
||||
}
|
||||
${(props) => (props.disabled ? "cursor: not-allowed;" : null)}
|
||||
`;
|
||||
|
||||
const MsgWrapper = styled.div`
|
||||
position: absolute;
|
||||
bottom: -20px;
|
||||
left: 0px;
|
||||
&.helper {
|
||||
.${Classes.TEXT} {
|
||||
color: var(--ads-text-input-helper-text-text-color);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const RightSideContainer = styled.div`
|
||||
position: absolute;
|
||||
right: var(--ads-spaces-6);
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const IconWrapper = styled.div`
|
||||
.${Classes.ICON} {
|
||||
margin-right: var(--ads-spaces-5);
|
||||
}
|
||||
`;
|
||||
|
||||
const PrefixWrapper = styled.div`
|
||||
.${Classes.TEXT} {
|
||||
padding-left: var(--ads-spaces-2);
|
||||
color: var(--ads-color-black-400);
|
||||
}
|
||||
`;
|
||||
|
||||
const initialValidation = (props: TextInputProps) => {
|
||||
let validationObj = { isValid: true, message: "" };
|
||||
if (props.defaultValue && props.validator) {
|
||||
validationObj = props.validator(props.defaultValue);
|
||||
}
|
||||
return validationObj;
|
||||
};
|
||||
|
||||
const TextInput = forwardRef(
|
||||
(props: TextInputProps, ref: Ref<HTMLInputElement>) => {
|
||||
//
|
||||
const [validation, setValidation] = useState<{
|
||||
isValid: boolean;
|
||||
message: string;
|
||||
}>(initialValidation(props));
|
||||
|
||||
const [rightSideComponentWidth, setRightSideComponentWidth] = useState(0);
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
const [inputValue, setInputValue] = useState(props.defaultValue);
|
||||
|
||||
const { trimValue = false } = props;
|
||||
|
||||
const setRightSideRef = useCallback((ref: HTMLDivElement) => {
|
||||
if (ref) {
|
||||
const { width } = ref.getBoundingClientRect();
|
||||
setRightSideComponentWidth(width);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const inputStyle = useMemo(
|
||||
() => boxStyles(props, validation?.isValid),
|
||||
[props, validation?.isValid],
|
||||
);
|
||||
|
||||
// set the default value
|
||||
useEffect(() => {
|
||||
if (props.defaultValue) {
|
||||
const inputValue = props.defaultValue;
|
||||
setInputValue(inputValue);
|
||||
checkValidator(inputValue);
|
||||
props.onChange && props.onChange(inputValue);
|
||||
}
|
||||
}, [props.defaultValue]);
|
||||
|
||||
const checkValidator = (inputValue: string) => {
|
||||
const inputValueValidation =
|
||||
props.validator && props.validator(inputValue);
|
||||
if (inputValueValidation) {
|
||||
props.validator && setValidation(inputValueValidation);
|
||||
}
|
||||
};
|
||||
|
||||
const memoizedChangeHandler = useCallback(
|
||||
(el) => {
|
||||
const inputValue: string = trimValue
|
||||
? el.target.value.trim()
|
||||
: el.target.value;
|
||||
setInputValue(inputValue);
|
||||
checkValidator(inputValue);
|
||||
return props.onChange && props.onChange(inputValue);
|
||||
},
|
||||
[props.onChange, setValidation, trimValue],
|
||||
);
|
||||
|
||||
const onBlurHandler = useCallback(
|
||||
(e: React.FocusEvent<any>) => {
|
||||
setIsFocused(false);
|
||||
if (props.onBlur) props.onBlur(e);
|
||||
},
|
||||
[setIsFocused, props.onBlur],
|
||||
);
|
||||
|
||||
const onFocusHandler = useCallback((e: React.FocusEvent<any>) => {
|
||||
setIsFocused(true);
|
||||
if (props.onFocus) props.onFocus(e);
|
||||
}, []);
|
||||
|
||||
const ErrorMessage = (
|
||||
<MsgWrapper>
|
||||
<Text type={TextType.P3}>
|
||||
{props.errorMsg ? props.errorMsg : validation?.message}
|
||||
</Text>
|
||||
</MsgWrapper>
|
||||
);
|
||||
|
||||
const HelperMessage = (
|
||||
<MsgWrapper className="helper">
|
||||
<Text type={TextType.P3}>* {props.helperText}</Text>
|
||||
</MsgWrapper>
|
||||
);
|
||||
|
||||
const iconColor = !validation?.isValid
|
||||
? "var(--ads-danger-main)"
|
||||
: "var(--ads-text-input-icon-path-color)";
|
||||
|
||||
const hasLeftIcon = props.leftIcon
|
||||
? IconCollection.includes(props.leftIcon)
|
||||
: false;
|
||||
|
||||
return (
|
||||
<InputWrapper
|
||||
$isLoading={props.isLoading}
|
||||
className={replayHighlightClass}
|
||||
disabled={props.disabled}
|
||||
fill={props.fill ? 1 : 0}
|
||||
height={props.height || undefined}
|
||||
inputStyle={inputStyle}
|
||||
isFocused={isFocused}
|
||||
isValid={validation?.isValid}
|
||||
noBorder={props.noBorder}
|
||||
readOnly={props.readOnly}
|
||||
value={inputValue}
|
||||
width={props.width || undefined}
|
||||
>
|
||||
{props.leftIcon && (
|
||||
<IconWrapper className="left-icon">
|
||||
<Icon
|
||||
fillColor={iconColor}
|
||||
name={props.leftIcon}
|
||||
size={IconSize.MEDIUM}
|
||||
/>
|
||||
</IconWrapper>
|
||||
)}
|
||||
|
||||
{props.prefix && (
|
||||
<PrefixWrapper className="prefix">
|
||||
<Text type={TextType.P1}>{props.prefix}</Text>
|
||||
</PrefixWrapper>
|
||||
)}
|
||||
|
||||
<InputLoader
|
||||
$height={props.height}
|
||||
$isFocused={isFocused}
|
||||
$isLoading={props.isLoading}
|
||||
$noBorder={props.noBorder}
|
||||
$value={props.value}
|
||||
className={BlueprintClasses.SKELETON}
|
||||
/>
|
||||
|
||||
<StyledInput
|
||||
$isLoading={props.isLoading}
|
||||
autoFocus={props.autoFocus}
|
||||
defaultValue={props.defaultValue}
|
||||
inputStyle={inputStyle}
|
||||
isValid={validation?.isValid}
|
||||
ref={ref}
|
||||
type={props.dataType || "text"}
|
||||
{...props}
|
||||
data-cy={props.cypressSelector}
|
||||
hasLeftIcon={hasLeftIcon}
|
||||
inputRef={ref}
|
||||
name={props?.name}
|
||||
onBlur={onBlurHandler}
|
||||
onChange={memoizedChangeHandler}
|
||||
onFocus={onFocusHandler}
|
||||
placeholder={props.placeholder}
|
||||
readOnly={props.readOnly}
|
||||
rightSideComponentWidth={rightSideComponentWidth}
|
||||
tabIndex={props.tabIndex ?? 0}
|
||||
/>
|
||||
{validation?.isValid &&
|
||||
props.helperText &&
|
||||
props.helperText.length > 0 &&
|
||||
HelperMessage}
|
||||
{ErrorMessage}
|
||||
<RightSideContainer className="right-icon" ref={setRightSideRef}>
|
||||
{props.rightSideComponent}
|
||||
</RightSideContainer>
|
||||
</InputWrapper>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
TextInput.displayName = "TextInput";
|
||||
|
||||
export default TextInput;
|
||||
|
|
@ -18,7 +18,7 @@ import {
|
|||
Classes,
|
||||
} from "@blueprintjs/core";
|
||||
import styled from "styled-components";
|
||||
import Icon, { IconSize } from "../Icon";
|
||||
import { Icon } from "@appsmith/ads";
|
||||
import { replayHighlightClass } from "../constants/classes";
|
||||
import useDSEvent from "../hooks/useDSEvent";
|
||||
import { DSEventTypes } from "../types/common";
|
||||
|
|
@ -626,7 +626,7 @@ function TreeDropdown(props: TreeDropdownProps) {
|
|||
}`}
|
||||
elementRef={buttonRef}
|
||||
onKeyDown={handleKeydown}
|
||||
rightIcon={<Icon name="down-arrow" size={IconSize.XXL} />}
|
||||
rightIcon={<Icon name="down-arrow" size="md" />}
|
||||
text={
|
||||
selectedLabelModifier
|
||||
? selectedLabelModifier(selectedOptionFromProps, displayValue)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
export enum Classes {
|
||||
ICON = "cs-icon",
|
||||
ICON = "ads-v2-icon",
|
||||
APP_ICON = "cs-app-icon",
|
||||
TEXT = "cs-text",
|
||||
BP3_POPOVER_ARROW_BORDER = "bp3-popover-arrow-border",
|
||||
|
|
|
|||
|
|
@ -3,12 +3,6 @@
|
|||
export { default as AppIcon } from "./AppIcon";
|
||||
export * from "./AppIcon";
|
||||
|
||||
export { default as Breadcrumbs } from "./Breadcrumbs";
|
||||
export * from "./Breadcrumbs";
|
||||
|
||||
export { default as Button } from "./Button";
|
||||
export * from "./Button";
|
||||
|
||||
export { default as Checkbox } from "./Checkbox";
|
||||
export * from "./Checkbox";
|
||||
|
||||
|
|
@ -26,8 +20,11 @@ export * from "./DisplayImageUpload";
|
|||
export { default as DraggableList } from "./DraggableList";
|
||||
export * from "./DraggableList";
|
||||
|
||||
export { default as Dropdown } from "./Dropdown";
|
||||
export * from "./Dropdown";
|
||||
export type {
|
||||
DropdownOption,
|
||||
DropdownOnSelect,
|
||||
RenderDropdownOptionType,
|
||||
} from "./Dropdown";
|
||||
|
||||
export { default as EditableText } from "./EditableText";
|
||||
export * from "./EditableText";
|
||||
|
|
@ -48,9 +45,6 @@ export * from "./GifPlayer";
|
|||
|
||||
export * from "./HighlightText";
|
||||
|
||||
export { default as Icon } from "./Icon";
|
||||
export * from "./Icon";
|
||||
|
||||
export { default as IconSelector } from "./IconSelector";
|
||||
export * from "./IconSelector";
|
||||
|
||||
|
|
@ -69,9 +63,6 @@ export * from "./RectangularSwitcher";
|
|||
export { default as SearchComponent } from "./SearchComponent";
|
||||
export * from "./SearchComponent";
|
||||
|
||||
export { default as Spinner } from "./Spinner";
|
||||
export * from "./Spinner";
|
||||
|
||||
export { default as Statusbar } from "./Statusbar";
|
||||
export * from "./Statusbar";
|
||||
|
||||
|
|
@ -81,8 +72,6 @@ export * from "./Switch";
|
|||
export { default as Switcher } from "./Switcher";
|
||||
export * from "./Switcher";
|
||||
|
||||
export * from "./Tabs";
|
||||
|
||||
export { default as Table } from "./Table";
|
||||
export * from "./Table";
|
||||
|
||||
|
|
@ -92,9 +81,6 @@ export * from "./TagInput";
|
|||
export { default as Text } from "./Text";
|
||||
export * from "./Text";
|
||||
|
||||
export { default as TextInput } from "./TextInput";
|
||||
export * from "./TextInput";
|
||||
|
||||
export { default as TooltipComponent } from "./Tooltip";
|
||||
export * from "./Tooltip";
|
||||
|
||||
|
|
@ -108,3 +94,5 @@ export * from "./constants/variants";
|
|||
export * from "./types/common";
|
||||
export * from "./utils/colors";
|
||||
export * from "./utils/icon-loadables";
|
||||
export * from "./utils/emailValidator";
|
||||
export * from "./utils/notEmptyValidator";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
import {
|
||||
createMessage,
|
||||
FORM_VALIDATION_INVALID_EMAIL,
|
||||
} from "../constants/messages";
|
||||
|
||||
const isEmail = (value: string) => {
|
||||
const re =
|
||||
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
return re.test(value);
|
||||
};
|
||||
|
||||
export function emailValidator(email: string) {
|
||||
let isValid = true;
|
||||
if (email) {
|
||||
isValid = isEmail(email);
|
||||
}
|
||||
return {
|
||||
isValid: isValid,
|
||||
message: !isValid ? createMessage(FORM_VALIDATION_INVALID_EMAIL) : "",
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import { createMessage, ERROR_MESSAGE_NAME_EMPTY } from "../constants/messages";
|
||||
|
||||
export function notEmptyValidator(value: string) {
|
||||
const isValid = !!value;
|
||||
return {
|
||||
isValid: isValid,
|
||||
message: !isValid ? createMessage(ERROR_MESSAGE_NAME_EMPTY) : "",
|
||||
};
|
||||
}
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
export * from "./Icon";
|
||||
export * from "./Icon.types";
|
||||
export { IconCollection } from "./Icon.provider";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import type { TabProp } from "@appsmith/ads-old";
|
||||
import { getTypographyByKey } from "@appsmith/ads-old";
|
||||
import type { Theme } from "constants/DefaultTheme";
|
||||
|
||||
|
|
@ -40,7 +39,9 @@ const Wrapper = styled.div<WrapperProps>`
|
|||
`;
|
||||
|
||||
export default function TabItemBackgroundFill(props: {
|
||||
tab: TabProp;
|
||||
tab: {
|
||||
title: string;
|
||||
};
|
||||
selected: boolean;
|
||||
vertical: boolean;
|
||||
}) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import type {
|
||||
SwitcherProps,
|
||||
TreeDropdownOption,
|
||||
IconName,
|
||||
} from "@appsmith/ads-old";
|
||||
import type { SwitcherProps, TreeDropdownOption } from "@appsmith/ads-old";
|
||||
import type { IconNames } from "@appsmith/ads";
|
||||
import type { EntityTypeValue, MetaArgs } from "ee/entities/DataTree/types";
|
||||
import type React from "react";
|
||||
import type { AdditionalDynamicDataTree } from "utils/autocomplete/customTreeTypeDefCreator";
|
||||
|
|
@ -177,7 +174,7 @@ export interface FieldGroupValueType {
|
|||
defaultParams: string;
|
||||
value?: string;
|
||||
children?: TreeDropdownOption[];
|
||||
icon?: IconName;
|
||||
icon?: IconNames;
|
||||
}
|
||||
|
||||
export interface FieldGroupConfig {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import React from "react";
|
||||
import type { CollapsibleTabProps } from "@appsmith/ads-old";
|
||||
import AnalyticsUtil from "ee/utils/AnalyticsUtil";
|
||||
import { DEBUGGER_TAB_KEYS } from "./Debugger/helpers";
|
||||
import { Tab, TabPanel, Tabs, TabsList } from "@appsmith/ads";
|
||||
import styled from "styled-components";
|
||||
import { LIST_HEADER_HEIGHT, FOOTER_MARGIN } from "./Debugger/DebuggerLogs";
|
||||
import type { RefObject } from "react";
|
||||
|
||||
const TabPanelWrapper = styled(TabPanel)`
|
||||
margin-top: 0;
|
||||
|
|
@ -40,8 +40,12 @@ interface EntityBottomTabsProps {
|
|||
isCollapsed?: boolean;
|
||||
}
|
||||
|
||||
type CollapsibleEntityBottomTabsProps = EntityBottomTabsProps &
|
||||
CollapsibleTabProps;
|
||||
type CollapsibleEntityBottomTabsProps = EntityBottomTabsProps & {
|
||||
// Reference to container for collapsing or expanding content
|
||||
containerRef: RefObject<HTMLDivElement>;
|
||||
// height of container when expanded( usually the default height of the tab component)
|
||||
expandedHeight: string;
|
||||
};
|
||||
|
||||
// Using this if there are debugger related tabs
|
||||
function EntityBottomTabs(
|
||||
|
|
@ -60,23 +64,6 @@ function EntityBottomTabs(
|
|||
}
|
||||
};
|
||||
|
||||
// if (props.isCollapsed) {
|
||||
// return (
|
||||
// <Flex alignItems="center" gap="spaces-3" height="100%" pl="spaces-5">
|
||||
// {props.tabs.map((tab) => (
|
||||
// <Button
|
||||
// key={tab.key}
|
||||
// kind="tertiary"
|
||||
// onClick={() => onTabSelect(tab.key)}
|
||||
// size="md"
|
||||
// >
|
||||
// {tab.title}
|
||||
// </Button>
|
||||
// ))}
|
||||
// </Flex>
|
||||
// );
|
||||
// }
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
className="h-full"
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ const FileImportCard = styled.div<{ fillCardWidth: boolean }>`
|
|||
height: 100%;
|
||||
justify-content: flex-start;
|
||||
|
||||
.cs-icon {
|
||||
.ads-v2-icon {
|
||||
border-radius: 50%;
|
||||
width: ${(props) => props.theme.spaces[12] + 2}px;
|
||||
height: ${(props) => props.theme.spaces[12] + 2}px;
|
||||
|
|
@ -113,7 +113,7 @@ const StatusbarWrapper = styled.div`
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.cs-icon {
|
||||
.ads-v2-icon {
|
||||
margin: auto;
|
||||
border-radius: var(--ads-v2-border-radius-circle);
|
||||
width: 32px;
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
import React from "react";
|
||||
import type { BaseFieldProps } from "redux-form";
|
||||
import { Field } from "redux-form";
|
||||
import type { TextInputProps } from "@appsmith/ads-old";
|
||||
import { TextInput } from "@appsmith/ads-old";
|
||||
|
||||
type RenderComponentProps = TextInputProps & {
|
||||
input?: {
|
||||
onChange?: (value: number) => void;
|
||||
value?: number;
|
||||
};
|
||||
};
|
||||
|
||||
function RenderComponent(props: RenderComponentProps) {
|
||||
const onChangeHandler = (value: number) => {
|
||||
props.input && props.input.onChange && props.input.onChange(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<TextInput
|
||||
dataType={props.dataType}
|
||||
defaultValue={props.input?.value?.toString()}
|
||||
onChange={(value: string) => onChangeHandler(Number(value))}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
class NumberField extends React.Component<BaseFieldProps & TextInputProps> {
|
||||
render() {
|
||||
return (
|
||||
<Field
|
||||
component={RenderComponent}
|
||||
{...this.props}
|
||||
disabled={this.props.disabled}
|
||||
noValidate
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default NumberField;
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
import React from "react";
|
||||
import type { ControlProps } from "./BaseControl";
|
||||
import BaseControl from "./BaseControl";
|
||||
import type { ControlType } from "constants/PropertyControlConstants";
|
||||
import NumberField from "components/editorComponents/form/fields/NumberField";
|
||||
import { Classes, Text, TextType } from "@appsmith/ads-old";
|
||||
import styled from "styled-components";
|
||||
|
||||
const FormGroup = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.${Classes.TEXT} {
|
||||
color: ${(props) => props.theme.colors.apiPane.settings.textColor};
|
||||
margin-right: ${(props) => props.theme.spaces[12]}px;
|
||||
}
|
||||
`;
|
||||
|
||||
export function InputText(props: {
|
||||
label: string;
|
||||
value: string;
|
||||
placeholder?: string;
|
||||
dataType?: string;
|
||||
name: string;
|
||||
}) {
|
||||
const { dataType, label, name, placeholder } = props;
|
||||
|
||||
return (
|
||||
<FormGroup data-testid={name}>
|
||||
<Text type={TextType.P1}>{label}</Text>
|
||||
<NumberField dataType={dataType} name={name} placeholder={placeholder} />
|
||||
</FormGroup>
|
||||
);
|
||||
}
|
||||
|
||||
class InputNumberControl extends BaseControl<InputControlProps> {
|
||||
render() {
|
||||
const { configProperty, dataType, label, placeholderText, propertyValue } =
|
||||
this.props;
|
||||
|
||||
return (
|
||||
<InputText
|
||||
dataType={dataType}
|
||||
label={label}
|
||||
name={configProperty}
|
||||
placeholder={placeholderText}
|
||||
value={propertyValue}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
getControlType(): ControlType {
|
||||
return "NUMBER_INPUT";
|
||||
}
|
||||
}
|
||||
|
||||
export interface InputControlProps extends ControlProps {
|
||||
placeholderText: string;
|
||||
}
|
||||
|
||||
export default InputNumberControl;
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import * as React from "react";
|
||||
import styled from "styled-components";
|
||||
import type { TextInputProps } from "@appsmith/ads-old";
|
||||
import type { ContainerOrientation } from "constants/WidgetConstants";
|
||||
import { Input, Icon } from "@appsmith/ads";
|
||||
import useInteractionAnalyticsEvent from "utils/hooks/useInteractionAnalyticsEvent";
|
||||
|
|
@ -90,7 +89,21 @@ export const StyledNavigateToFieldsContainer = styled.div`
|
|||
width: 95%;
|
||||
`;
|
||||
|
||||
export const InputGroup = React.forwardRef((props: TextInputProps, ref) => {
|
||||
interface InputGroupProps {
|
||||
autoFocus?: boolean;
|
||||
className?: string;
|
||||
dataType?: string;
|
||||
onBlur?: () => void;
|
||||
onFocus?: () => void;
|
||||
placeholder?: string;
|
||||
value?: string;
|
||||
width?: string;
|
||||
onChange?: (value: string) => void;
|
||||
defaultValue?: string;
|
||||
tabIndex?: number;
|
||||
}
|
||||
|
||||
export const InputGroup = React.forwardRef((props: InputGroupProps, ref) => {
|
||||
let inputRef = React.useRef<HTMLInputElement>(null);
|
||||
const wrapperRef = React.useRef<HTMLInputElement>(null);
|
||||
const { dispatchInteractionAnalyticsEvent } =
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import React from "react";
|
||||
import type { WrappedFieldMetaProps, WrappedFieldInputProps } from "redux-form";
|
||||
import { Field } from "redux-form";
|
||||
import type { InputType } from "@appsmith/ads-old";
|
||||
import { Input, NumberInput } from "@appsmith/ads";
|
||||
|
||||
import type { Intent } from "constants/DefaultTheme";
|
||||
|
|
@ -48,7 +47,7 @@ export interface FormTextFieldProps {
|
|||
name: string;
|
||||
placeholder: string;
|
||||
description?: string;
|
||||
type?: InputType;
|
||||
type?: "text" | "password" | "number" | "email" | "tel";
|
||||
label?: React.ReactNode;
|
||||
intent?: Intent;
|
||||
disabled?: boolean;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { Link, Text } from "@appsmith/ads";
|
|||
export const HelpPopoverStyle = createGlobalStyle`
|
||||
.bp3-portal {
|
||||
.delete-menu-item {
|
||||
.cs-icon, .cs-text {
|
||||
.ads-v2-icon, .cs-text {
|
||||
color: var(--appsmith-color-red-500) !important;
|
||||
svg {
|
||||
path {
|
||||
|
|
|
|||
|
|
@ -2,14 +2,10 @@ import localStorage from "utils/localStorage";
|
|||
import { GridDefaults } from "./WidgetConstants";
|
||||
import { APP_MAX_WIDTH, type AppMaxWidth } from "@appsmith/wds-theming";
|
||||
|
||||
export const CANVAS_DEFAULT_HEIGHT_PX = 1292;
|
||||
export const CANVAS_DEFAULT_MIN_HEIGHT_PX = 380;
|
||||
export const CANVAS_DEFAULT_GRID_HEIGHT_PX = 1;
|
||||
export const CANVAS_DEFAULT_GRID_WIDTH_PX = 1;
|
||||
export const CANVAS_DEFAULT_MIN_ROWS = Math.ceil(
|
||||
CANVAS_DEFAULT_MIN_HEIGHT_PX / GridDefaults.DEFAULT_GRID_ROW_HEIGHT,
|
||||
);
|
||||
export const CANVAS_BACKGROUND_COLOR = "#FFFFFF";
|
||||
export const DEFAULT_ENTITY_EXPLORER_WIDTH = 256;
|
||||
export const DEFAULT_PROPERTY_PANE_WIDTH = 288;
|
||||
export const APP_SETTINGS_PANE_WIDTH = 525;
|
||||
|
|
@ -40,7 +36,6 @@ export const getPersistentAppStore = (appId: string, branch?: string) => {
|
|||
return store;
|
||||
};
|
||||
|
||||
export const TOOLTIP_HOVER_ON_DELAY = 1000;
|
||||
export const TOOLTIP_HOVER_ON_DELAY_IN_S = 1;
|
||||
|
||||
export const MOBILE_MAX_WIDTH = 767;
|
||||
|
|
@ -63,11 +58,6 @@ export const NAVIGATION_SETTINGS = {
|
|||
STATIC: "static",
|
||||
STICKY: "sticky",
|
||||
},
|
||||
ITEM_STYLE: {
|
||||
TEXT_ICON: "textIcon",
|
||||
TEXT: "text",
|
||||
ICON: "icon",
|
||||
},
|
||||
COLOR_STYLE: {
|
||||
LIGHT: "light",
|
||||
THEME: "theme",
|
||||
|
|
@ -87,7 +77,6 @@ export interface NavigationSetting {
|
|||
orientation: (typeof NAVIGATION_SETTINGS.ORIENTATION)[keyof typeof NAVIGATION_SETTINGS.ORIENTATION];
|
||||
navStyle: (typeof NAVIGATION_SETTINGS.NAV_STYLE)[keyof typeof NAVIGATION_SETTINGS.NAV_STYLE];
|
||||
position: (typeof NAVIGATION_SETTINGS.POSITION)[keyof typeof NAVIGATION_SETTINGS.POSITION];
|
||||
itemStyle: (typeof NAVIGATION_SETTINGS.ITEM_STYLE)[keyof typeof NAVIGATION_SETTINGS.ITEM_STYLE];
|
||||
colorStyle: (typeof NAVIGATION_SETTINGS.COLOR_STYLE)[keyof typeof NAVIGATION_SETTINGS.COLOR_STYLE];
|
||||
logoAssetId: string;
|
||||
logoConfiguration: (typeof NAVIGATION_SETTINGS.LOGO_CONFIGURATION)[keyof typeof NAVIGATION_SETTINGS.LOGO_CONFIGURATION];
|
||||
|
|
@ -127,7 +116,6 @@ export const defaultNavigationSetting = {
|
|||
orientation: NAVIGATION_SETTINGS.ORIENTATION.TOP,
|
||||
navStyle: NAVIGATION_SETTINGS.NAV_STYLE.STACKED,
|
||||
position: NAVIGATION_SETTINGS.POSITION.STATIC,
|
||||
itemStyle: NAVIGATION_SETTINGS.ITEM_STYLE.TEXT,
|
||||
colorStyle: NAVIGATION_SETTINGS.COLOR_STYLE.LIGHT,
|
||||
logoAssetId: NAVIGATION_SETTINGS.LOGO_ASSET_ID,
|
||||
logoConfiguration:
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
import React from "react";
|
||||
import { Breadcrumbs } from "@appsmith/ads-old";
|
||||
import { BreadcrumbCategories } from "ee/pages/AdminSettings/BreadcrumbCategories";
|
||||
|
||||
export const getBreadcrumbList = (category: string, subCategory?: string) => {
|
||||
const breadcrumbList = [
|
||||
BreadcrumbCategories.HOMEPAGE,
|
||||
...(subCategory
|
||||
? [BreadcrumbCategories[category], BreadcrumbCategories[subCategory]]
|
||||
: [BreadcrumbCategories[category]]),
|
||||
];
|
||||
|
||||
return breadcrumbList;
|
||||
};
|
||||
|
||||
function SettingsBreadcrumbs({
|
||||
category,
|
||||
subCategory,
|
||||
}: {
|
||||
category: string;
|
||||
subCategory?: string;
|
||||
}) {
|
||||
return <Breadcrumbs items={getBreadcrumbList(category, subCategory)} />;
|
||||
}
|
||||
|
||||
export default SettingsBreadcrumbs;
|
||||
|
|
@ -197,7 +197,6 @@ export function Sidebar(props: SidebarProps) {
|
|||
key={page.pageId}
|
||||
>
|
||||
<MenuItem
|
||||
isMinimal={isMinimal}
|
||||
key={page.pageId}
|
||||
navigationSetting={
|
||||
currentApplicationDetails?.applicationDetail
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
import { useLocation } from "react-router-dom";
|
||||
import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
|
||||
// import { get } from "lodash";
|
||||
// import { useSelector } from "react-redux";
|
||||
import type {
|
||||
ApplicationPayload,
|
||||
Page,
|
||||
} from "ee/constants/ReduxActionConstants";
|
||||
// import { NAVIGATION_SETTINGS } from "constants/AppConstants";
|
||||
import { useWindowSizeHooks } from "utils/hooks/dragResizeHooks";
|
||||
// import { getSelectedAppTheme } from "selectors/appThemingSelectors";
|
||||
import MenuItem from "./components/MenuItem";
|
||||
import { Container } from "./TopInline.styled";
|
||||
import MenuItemContainer from "./components/MenuItemContainer";
|
||||
|
|
@ -21,9 +17,6 @@ import { useSelector } from "react-redux";
|
|||
import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
|
||||
import { throttle } from "lodash";
|
||||
|
||||
// TODO - @Dhruvik - ImprovedAppNav
|
||||
// Replace with NavigationProps if nothing changes
|
||||
// appsmith/app/client/src/pages/AppViewer/Navigation/constants.ts
|
||||
interface TopInlineProps {
|
||||
currentApplicationDetails?: ApplicationPayload;
|
||||
pages: Page[];
|
||||
|
|
@ -31,15 +24,6 @@ interface TopInlineProps {
|
|||
|
||||
export function TopInline(props: TopInlineProps) {
|
||||
const { currentApplicationDetails, pages } = props;
|
||||
// const selectedTheme = useSelector(getSelectedAppTheme);
|
||||
// const navColorStyle =
|
||||
// currentApplicationDetails?.applicationDetail?.navigationSetting?.colorStyle ||
|
||||
// NAVIGATION_SETTINGS.COLOR_STYLE.LIGHT;
|
||||
// const primaryColor = get(
|
||||
// selectedTheme,
|
||||
// "properties.colors.primaryColor",
|
||||
// "inherit",
|
||||
// );
|
||||
const location = useLocation();
|
||||
const { pathname } = location;
|
||||
const [query, setQuery] = useState("");
|
||||
|
|
|
|||
|
|
@ -10,9 +10,7 @@ import { builderURL, viewerURL } from "ee/RouteBuilder";
|
|||
import { getAppMode } from "ee/selectors/applicationSelectors";
|
||||
import { getSelectedAppTheme } from "selectors/appThemingSelectors";
|
||||
import { trimQueryString } from "utils/helpers";
|
||||
import { Icon } from "@appsmith/ads-old";
|
||||
import MenuText from "./MenuText";
|
||||
import classNames from "classnames";
|
||||
import { StyledMenuItem } from "./MenuItem.styled";
|
||||
import { NavigationMethod } from "utils/history";
|
||||
|
||||
|
|
@ -20,15 +18,9 @@ interface MenuItemProps {
|
|||
page: Page;
|
||||
query: string;
|
||||
navigationSetting?: NavigationSetting;
|
||||
isMinimal?: boolean;
|
||||
}
|
||||
|
||||
const MenuItem = ({
|
||||
isMinimal,
|
||||
navigationSetting,
|
||||
page,
|
||||
query,
|
||||
}: MenuItemProps) => {
|
||||
const MenuItem = ({ navigationSetting, page, query }: MenuItemProps) => {
|
||||
const appMode = useSelector(getAppMode);
|
||||
const pageURL = useHref(
|
||||
appMode === APP_MODE.PUBLISHED ? viewerURL : builderURL,
|
||||
|
|
@ -61,28 +53,11 @@ const MenuItem = ({
|
|||
state: { invokedBy: NavigationMethod.AppNavigation },
|
||||
}}
|
||||
>
|
||||
{navigationSetting?.itemStyle !== NAVIGATION_SETTINGS.ITEM_STYLE.TEXT && (
|
||||
<Icon
|
||||
className={classNames({
|
||||
"page-icon": true,
|
||||
"mr-2":
|
||||
navigationSetting?.itemStyle ===
|
||||
NAVIGATION_SETTINGS.ITEM_STYLE.TEXT_ICON && !isMinimal,
|
||||
"mx-auto": isMinimal,
|
||||
})}
|
||||
name="file-line"
|
||||
// @ts-expect-error Fix this the next time the file is edited
|
||||
size="large"
|
||||
/>
|
||||
)}
|
||||
{navigationSetting?.itemStyle !== NAVIGATION_SETTINGS.ITEM_STYLE.ICON &&
|
||||
!isMinimal && (
|
||||
<MenuText
|
||||
name={page.pageName}
|
||||
navColorStyle={navColorStyle}
|
||||
primaryColor={primaryColor}
|
||||
/>
|
||||
)}
|
||||
<MenuText
|
||||
name={page.pageName}
|
||||
navColorStyle={navColorStyle}
|
||||
primaryColor={primaryColor}
|
||||
/>
|
||||
</StyledMenuItem>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import { useSelector } from "react-redux";
|
|||
import { getSelectedAppTheme } from "selectors/appThemingSelectors";
|
||||
import { Icon } from "@appsmith/ads";
|
||||
import MenuText from "./MenuText";
|
||||
import classNames from "classnames";
|
||||
import {
|
||||
StyledMenuDropdownContainer,
|
||||
StyledMenuItemInDropdown,
|
||||
|
|
@ -57,32 +56,14 @@ const MoreDropdownButton = ({
|
|||
}}
|
||||
primaryColor={primaryColor}
|
||||
>
|
||||
{navigationSetting?.itemStyle !==
|
||||
NAVIGATION_SETTINGS.ITEM_STYLE.TEXT && (
|
||||
<Icon
|
||||
className={classNames({
|
||||
"page-icon": true,
|
||||
"mr-2":
|
||||
navigationSetting?.itemStyle ===
|
||||
NAVIGATION_SETTINGS.ITEM_STYLE.TEXT_ICON,
|
||||
})}
|
||||
name="context-menu"
|
||||
size="md"
|
||||
<>
|
||||
<MenuText
|
||||
name="More"
|
||||
navColorStyle={navColorStyle}
|
||||
primaryColor={primaryColor}
|
||||
/>
|
||||
)}
|
||||
|
||||
{navigationSetting?.itemStyle !==
|
||||
NAVIGATION_SETTINGS.ITEM_STYLE.ICON && (
|
||||
<>
|
||||
<MenuText
|
||||
name="More"
|
||||
navColorStyle={navColorStyle}
|
||||
primaryColor={primaryColor}
|
||||
/>
|
||||
{/*@ts-expect-error Fix this the next time the file is edited*/}
|
||||
<Icon className="page-icon ml-2" name="expand-more" size="large" />
|
||||
</>
|
||||
)}
|
||||
<Icon className="page-icon ml-2" name="expand-more" size="md" />
|
||||
</>
|
||||
</StyleMoreDropdownButton>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -124,25 +105,11 @@ const MoreDropdownButton = ({
|
|||
state: { invokedBy: NavigationMethod.AppNavigation },
|
||||
}}
|
||||
>
|
||||
{navigationSetting?.itemStyle !==
|
||||
NAVIGATION_SETTINGS.ITEM_STYLE.TEXT && (
|
||||
<Icon
|
||||
className={classNames({
|
||||
"page-icon mr-2": true,
|
||||
})}
|
||||
name="file-line"
|
||||
// @ts-expect-error Fix this the next time the file is edited
|
||||
size="large"
|
||||
/>
|
||||
)}
|
||||
{navigationSetting?.itemStyle !==
|
||||
NAVIGATION_SETTINGS.ITEM_STYLE.ICON && (
|
||||
<MenuText
|
||||
name={page.pageName}
|
||||
navColorStyle={navColorStyle}
|
||||
primaryColor={primaryColor}
|
||||
/>
|
||||
)}
|
||||
<MenuText
|
||||
name={page.pageName}
|
||||
navColorStyle={navColorStyle}
|
||||
primaryColor={primaryColor}
|
||||
/>
|
||||
</StyledMenuItemInDropdown>
|
||||
);
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ const DatasourceCard = styled.div`
|
|||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
.cs-icon {
|
||||
.ads-v2-icon {
|
||||
opacity: 0;
|
||||
transition: 0.3s all ease;
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ const DatasourceCard = styled.div`
|
|||
}
|
||||
&:hover {
|
||||
background-color: var(--ads-v2-color-bg-subtle);
|
||||
.cs-icon {
|
||||
.ads-v2-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,6 @@ import React, { useCallback, useEffect, useState } from "react";
|
|||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { getCurrentApplication } from "ee/selectors/applicationSelectors";
|
||||
import { APP_NAVIGATION_SETTING, createMessage } from "ee/constants/messages";
|
||||
// import { ReactComponent as NavOrientationTopIcon } from "assets/icons/settings/nav-orientation-top.svg";
|
||||
// import { ReactComponent as NavOrientationSideIcon } from "assets/icons/settings/nav-orientation-side.svg";
|
||||
// import { ReactComponent as NavStyleInlineIcon } from "assets/icons/settings/nav-style-inline.svg";
|
||||
// import { ReactComponent as NavStyleStackedIcon } from "assets/icons/settings/nav-style-stacked.svg";
|
||||
// import { ReactComponent as NavStyleSidebarIcon } from "assets/icons/settings/nav-style-sidebar.svg";
|
||||
import type { NavigationSetting } from "constants/AppConstants";
|
||||
import { NAVIGATION_SETTINGS } from "constants/AppConstants";
|
||||
import _, { debounce, isEmpty, isPlainObject } from "lodash";
|
||||
|
|
@ -22,15 +17,6 @@ import LogoInput from "pages/Editor/NavigationSettings/LogoInput";
|
|||
import SwitchSettingForLogoConfiguration from "./SwitchSettingForLogoConfiguration";
|
||||
import { selectFeatureFlags } from "ee/selectors/featureFlagsSelectors";
|
||||
|
||||
/**
|
||||
* TODO - @Dhruvik - ImprovedAppNav
|
||||
* Revisit these imports in v1.1
|
||||
* https://www.notion.so/appsmith/Ship-Faster-33b32ed5b6334810a0b4f42e03db4a5b?pvs=4
|
||||
*/
|
||||
// import { ReactComponent as NavPositionStickyIcon } from "assets/icons/settings/nav-position-sticky.svg";
|
||||
// import { ReactComponent as NavPositionStaticIcon } from "assets/icons/settings/nav-position-static.svg";
|
||||
// import { ReactComponent as NavStyleMinimalIcon } from "assets/icons/settings/nav-style-minimal.svg";
|
||||
|
||||
export type UpdateSetting = (
|
||||
key: keyof NavigationSetting,
|
||||
value: NavigationSetting[keyof NavigationSetting],
|
||||
|
|
@ -158,32 +144,6 @@ function NavigationSettings() {
|
|||
: NAVIGATION_SETTINGS.NAV_STYLE.SIDEBAR;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO - @Dhruvik - ImprovedAppNav
|
||||
* Uncomment to change these settings automatically in v1.1
|
||||
* https://www.notion.so/appsmith/Ship-Faster-33b32ed5b6334810a0b4f42e03db4a5b
|
||||
*
|
||||
* When the orientation is side and nav style changes -
|
||||
* 1. to minimal, change the item style to icon
|
||||
* 1. to sidebar, change the item style to text + icon
|
||||
*/
|
||||
// if (
|
||||
// newSettings.orientation ===
|
||||
// NAVIGATION_SETTINGS.ORIENTATION.SIDE &&
|
||||
// navigationSetting.navStyle !== newSettings.navStyle
|
||||
// ) {
|
||||
// if (
|
||||
// newSettings.navStyle === NAVIGATION_SETTINGS.NAV_STYLE.MINIMAL
|
||||
// ) {
|
||||
// newSettings.itemStyle = NAVIGATION_SETTINGS.ITEM_STYLE.ICON;
|
||||
// } else if (
|
||||
// newSettings.navStyle === NAVIGATION_SETTINGS.NAV_STYLE.SIDEBAR
|
||||
// ) {
|
||||
// newSettings.itemStyle =
|
||||
// NAVIGATION_SETTINGS.ITEM_STYLE.TEXT_ICON;
|
||||
// }
|
||||
// }
|
||||
|
||||
payload.applicationDetail = {
|
||||
navigationSetting: newSettings,
|
||||
};
|
||||
|
|
@ -225,23 +185,15 @@ function NavigationSettings() {
|
|||
{
|
||||
label: _.startCase(NAVIGATION_SETTINGS.ORIENTATION.TOP),
|
||||
value: NAVIGATION_SETTINGS.ORIENTATION.TOP,
|
||||
// startIcon:<NavOrientationTopIcon />,
|
||||
},
|
||||
{
|
||||
label: _.startCase(NAVIGATION_SETTINGS.ORIENTATION.SIDE),
|
||||
value: NAVIGATION_SETTINGS.ORIENTATION.SIDE,
|
||||
// startIcon:<NavOrientationSideIcon />,
|
||||
},
|
||||
]}
|
||||
updateSetting={updateSetting}
|
||||
/>
|
||||
|
||||
{/**
|
||||
* TODO - @Dhruvik - ImprovedAppNav
|
||||
* Remove check for orientation = top when adding sidebar minimal to show sidebar
|
||||
* variants as well.
|
||||
* https://www.notion.so/appsmith/Ship-Faster-33b32ed5b6334810a0b4f42e03db4a5b
|
||||
*/}
|
||||
{navigationSetting?.orientation ===
|
||||
NAVIGATION_SETTINGS.ORIENTATION.TOP && (
|
||||
<ButtonGroupSetting
|
||||
|
|
@ -252,7 +204,6 @@ function NavigationSettings() {
|
|||
{
|
||||
label: _.startCase(NAVIGATION_SETTINGS.NAV_STYLE.STACKED),
|
||||
value: NAVIGATION_SETTINGS.NAV_STYLE.STACKED,
|
||||
// startIcon:<NavStyleStackedIcon />,
|
||||
hidden:
|
||||
navigationSetting?.orientation ===
|
||||
NAVIGATION_SETTINGS.ORIENTATION.SIDE,
|
||||
|
|
@ -260,7 +211,6 @@ function NavigationSettings() {
|
|||
{
|
||||
label: _.startCase(NAVIGATION_SETTINGS.NAV_STYLE.INLINE),
|
||||
value: NAVIGATION_SETTINGS.NAV_STYLE.INLINE,
|
||||
// startIcon:<NavStyleInlineIcon />,
|
||||
hidden:
|
||||
navigationSetting?.orientation ===
|
||||
NAVIGATION_SETTINGS.ORIENTATION.SIDE,
|
||||
|
|
@ -268,90 +218,15 @@ function NavigationSettings() {
|
|||
{
|
||||
label: _.startCase(NAVIGATION_SETTINGS.NAV_STYLE.SIDEBAR),
|
||||
value: NAVIGATION_SETTINGS.NAV_STYLE.SIDEBAR,
|
||||
// startIcon:<NavStyleSidebarIcon />,
|
||||
hidden:
|
||||
navigationSetting?.orientation ===
|
||||
NAVIGATION_SETTINGS.ORIENTATION.TOP,
|
||||
},
|
||||
/**
|
||||
* TODO - @Dhruvik - ImprovedAppNav
|
||||
* Hiding minimal sidebar for v1
|
||||
* https://www.notion.so/appsmith/Ship-Faster-33b32ed5b6334810a0b4f42e03db4a5b
|
||||
*/
|
||||
// {
|
||||
// label: _.startCase(NAVIGATION_SETTINGS.NAV_STYLE.MINIMAL),
|
||||
// value: NAVIGATION_SETTINGS.NAV_STYLE.MINIMAL,
|
||||
// startIcon:<NavStyleMinimalIcon />,
|
||||
// hidden:
|
||||
// navigationSetting?.orientation ===
|
||||
// NAVIGATION_SETTINGS.ORIENTATION.TOP,
|
||||
// },
|
||||
]}
|
||||
updateSetting={updateSetting}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/**
|
||||
* TODO - @Dhruvik - ImprovedAppNav
|
||||
* Hiding position for v1
|
||||
* https://www.notion.so/appsmith/Logo-configuration-option-can-be-multiselect-2a436598539c4db99d1f030850fd8918?pvs=4
|
||||
*/}
|
||||
{/* <ButtonGroupSetting
|
||||
heading={createMessage(APP_NAVIGATION_SETTING.positionLabel)}
|
||||
keyName="position"
|
||||
navigationSetting={navigationSetting}
|
||||
options={[
|
||||
{
|
||||
label: _.startCase(NAVIGATION_SETTINGS.POSITION.STATIC),
|
||||
value: NAVIGATION_SETTINGS.POSITION.STATIC,
|
||||
startIcon:<NavPositionStaticIcon />,
|
||||
},
|
||||
{
|
||||
label: _.startCase(NAVIGATION_SETTINGS.POSITION.STICKY),
|
||||
value: NAVIGATION_SETTINGS.POSITION.STICKY,
|
||||
startIcon:<NavPositionStickyIcon />,
|
||||
},
|
||||
]}
|
||||
updateSetting={updateSetting}
|
||||
/> */}
|
||||
|
||||
{/**
|
||||
* TODO - @Dhruvik - ImprovedAppNav
|
||||
* Hiding item style for v1
|
||||
* https://www.notion.so/appsmith/Logo-configuration-option-can-be-multiselect-2a436598539c4db99d1f030850fd8918?pvs=4
|
||||
*/}
|
||||
{/* <ButtonGroupSetting
|
||||
heading={createMessage(APP_NAVIGATION_SETTING.itemStyleLabel)}
|
||||
keyName="itemStyle"
|
||||
navigationSetting={navigationSetting}
|
||||
options={[
|
||||
{
|
||||
label: "Text + Icon",
|
||||
value: NAVIGATION_SETTINGS.ITEM_STYLE.TEXT_ICON,
|
||||
hidden:
|
||||
navigationSetting?.navStyle ===
|
||||
NAVIGATION_SETTINGS.NAV_STYLE.MINIMAL,
|
||||
},
|
||||
{
|
||||
label: _.startCase(NAVIGATION_SETTINGS.ITEM_STYLE.TEXT),
|
||||
value: NAVIGATION_SETTINGS.ITEM_STYLE.TEXT,
|
||||
hidden:
|
||||
navigationSetting?.navStyle ===
|
||||
NAVIGATION_SETTINGS.NAV_STYLE.MINIMAL,
|
||||
},
|
||||
{
|
||||
label: _.startCase(NAVIGATION_SETTINGS.ITEM_STYLE.ICON),
|
||||
value: NAVIGATION_SETTINGS.ITEM_STYLE.ICON,
|
||||
hidden:
|
||||
navigationSetting?.orientation ===
|
||||
NAVIGATION_SETTINGS.ORIENTATION.SIDE &&
|
||||
navigationSetting?.navStyle ===
|
||||
NAVIGATION_SETTINGS.NAV_STYLE.SIDEBAR,
|
||||
},
|
||||
]}
|
||||
updateSetting={updateSetting}
|
||||
/> */}
|
||||
|
||||
<ButtonGroupSetting
|
||||
heading={createMessage(APP_NAVIGATION_SETTING.colorStyleLabel)}
|
||||
keyName="colorStyle"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const SectionLabel = styled.div`
|
|||
letter-spacing: -0.17px;
|
||||
color: var(--ads-v2-color-fg);
|
||||
display: flex;
|
||||
.cs-icon {
|
||||
.ads-v2-icon {
|
||||
margin-left: ${(props) => props.theme.spaces[2]}px;
|
||||
}
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ export type EditableAppNameProps = CommonComponentProps & {
|
|||
onBlur?: (value: string) => void;
|
||||
isEditingDefault?: boolean;
|
||||
inputValidation?: (value: string) => string | boolean;
|
||||
hideEditIcon?: boolean;
|
||||
fill?: boolean;
|
||||
isError?: boolean;
|
||||
isEditing: boolean;
|
||||
|
|
|
|||
|
|
@ -123,7 +123,6 @@ export function EditorName(props: EditorNameProps) {
|
|||
defaultValue={defaultValue}
|
||||
editInteractionKind={props.editInteractionKind}
|
||||
fill={props.fill}
|
||||
hideEditIcon
|
||||
inputValidation={inputValidation}
|
||||
isEditing={isEditing}
|
||||
isEditingDefault={isEditingDefault}
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ const Wrapper = styled.div`
|
|||
margin-bottom: 16px;
|
||||
.left-icon {
|
||||
margin-left: 14px;
|
||||
.cs-icon {
|
||||
.ads-v2-icon {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -372,7 +372,6 @@ function GeneratePageForm() {
|
|||
value: column.name,
|
||||
subText: column.type,
|
||||
icon: columnIcon,
|
||||
// @ts-expect-error Fix this the next time the file is edited
|
||||
iconSize: "md",
|
||||
iconColor: "var(--ads-v2-color-fg)",
|
||||
});
|
||||
|
|
@ -448,8 +447,7 @@ function GeneratePageForm() {
|
|||
iconSize: "md",
|
||||
iconColor: "var(--ads-v2-color-fg)",
|
||||
}));
|
||||
// @ts-expect-error Fix this the next time the file is edited
|
||||
setSelectedDatasourceTableOptions(tables);
|
||||
setSelectedDatasourceTableOptions(tables as DropdownOptions);
|
||||
}
|
||||
}, [bucketList, isS3Plugin, setSelectedDatasourceTableOptions]);
|
||||
|
||||
|
|
@ -482,8 +480,7 @@ function GeneratePageForm() {
|
|||
columns,
|
||||
},
|
||||
}));
|
||||
// @ts-expect-error Fix this the next time the file is edited
|
||||
setSelectedDatasourceTableOptions(newTables);
|
||||
setSelectedDatasourceTableOptions(newTables as DropdownOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -774,9 +771,7 @@ function GeneratePageForm() {
|
|||
<StyledIconWrapper>
|
||||
<Icon
|
||||
color={table?.iconColor}
|
||||
// @ts-expect-error Fix this the next time the file is edited
|
||||
name={table.icon}
|
||||
// @ts-expect-error Fix this the next time the file is edited
|
||||
name={table.icon as string}
|
||||
size={table.iconSize}
|
||||
/>
|
||||
</StyledIconWrapper>
|
||||
|
|
@ -849,9 +844,7 @@ function GeneratePageForm() {
|
|||
<StyledIconWrapper>
|
||||
<Icon
|
||||
color={column?.iconColor}
|
||||
// @ts-expect-error Fix this the next time the file is edited
|
||||
name={column.icon}
|
||||
// @ts-expect-error Fix this the next time the file is edited
|
||||
name={column.icon as string}
|
||||
size={column.iconSize}
|
||||
/>
|
||||
</StyledIconWrapper>
|
||||
|
|
|
|||
|
|
@ -1,403 +0,0 @@
|
|||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import type { InjectedFormProps } from "redux-form";
|
||||
import { reduxForm } from "redux-form";
|
||||
import styled from "styled-components";
|
||||
import type { AppState } from "ee/reducers";
|
||||
import { API_HOME_SCREEN_FORM } from "ee/constants/forms";
|
||||
import ActiveDataSources from "./ActiveDataSources";
|
||||
import {
|
||||
getDatasources,
|
||||
getMockDatasources,
|
||||
} from "ee/selectors/entitiesSelector";
|
||||
import type { Datasource, MockDatasource } from "entities/Datasource";
|
||||
import type { TabProp } from "@appsmith/ads-old";
|
||||
import { IconSize } from "@appsmith/ads-old";
|
||||
import { INTEGRATION_TABS, INTEGRATION_EDITOR_MODES } from "constants/routes";
|
||||
import BackButton from "../DataSourceEditor/BackButton";
|
||||
import UnsupportedPluginDialog from "./UnsupportedPluginDialog";
|
||||
import { getQueryParams } from "utils/URLUtils";
|
||||
import { getIsGeneratePageInitiator } from "utils/GenerateCrudUtil";
|
||||
import { getCurrentApplicationId } from "selectors/editorSelectors";
|
||||
import { integrationEditorURL } from "ee/RouteBuilder";
|
||||
import { getCurrentAppWorkspace } from "ee/selectors/selectedWorkspaceSelectors";
|
||||
|
||||
import { Tab, TabPanel, Tabs, TabsList } from "@appsmith/ads";
|
||||
import Debugger, {
|
||||
ResizerContentContainer,
|
||||
ResizerMainContainer,
|
||||
} from "../DataSourceEditor/Debugger";
|
||||
import { showDebuggerFlag } from "selectors/debuggerSelectors";
|
||||
import AnalyticsUtil from "ee/utils/AnalyticsUtil";
|
||||
import { DatasourceCreateEntryPoints } from "constants/Datasource";
|
||||
import { selectFeatureFlags } from "ee/selectors/featureFlagsSelectors";
|
||||
import { isGACEnabled } from "ee/utils/planHelpers";
|
||||
import { getHasCreateDatasourcePermission } from "ee/utils/BusinessFeatures/permissionPageHelpers";
|
||||
import CreateNewDatasourceTab from "./CreateNewDatasourceTab";
|
||||
|
||||
const HeaderFlex = styled.div`
|
||||
font-size: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: var(--ads-v2-color-fg-emphasis-plus);
|
||||
padding: 0 var(--ads-v2-spaces-7);
|
||||
`;
|
||||
|
||||
const ApiHomePage = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
padding-top: 20px;
|
||||
/* margin-left: 10px; */
|
||||
flex: 1;
|
||||
overflow: hidden !important;
|
||||
.closeBtn {
|
||||
position: absolute;
|
||||
left: 70%;
|
||||
}
|
||||
.fontSize16 {
|
||||
font-size: 16px;
|
||||
}
|
||||
.integrations-content-container {
|
||||
padding: 0 var(--ads-v2-spaces-7);
|
||||
}
|
||||
.t--vertical-menu {
|
||||
overflow: auto;
|
||||
}
|
||||
`;
|
||||
|
||||
const MainTabsContainer = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 var(--ads-v2-spaces-7);
|
||||
/* .react-tabs__tab-list {
|
||||
margin: 2px;
|
||||
} */
|
||||
`;
|
||||
|
||||
const SectionGrid = styled.div<{ isActiveTab?: boolean }>`
|
||||
margin-top: 16px;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
gap: 10px 16px;
|
||||
flex: 1;
|
||||
min-height: 100%;
|
||||
`;
|
||||
|
||||
interface IntegrationsHomeScreenProps {
|
||||
basePageId: string;
|
||||
selectedTab: string;
|
||||
location: {
|
||||
search: string;
|
||||
pathname: string;
|
||||
};
|
||||
history: {
|
||||
replace: (data: string) => void;
|
||||
push: (data: string) => void;
|
||||
};
|
||||
isCreating: boolean;
|
||||
dataSources: Datasource[];
|
||||
mockDatasources: MockDatasource[];
|
||||
applicationId: string;
|
||||
canCreateDatasource?: boolean;
|
||||
showDebugger: boolean;
|
||||
}
|
||||
|
||||
interface IntegrationsHomeScreenState {
|
||||
page: number;
|
||||
activePrimaryMenuId: string;
|
||||
activeSecondaryMenuId: number;
|
||||
unsupportedPluginDialogVisible: boolean;
|
||||
}
|
||||
|
||||
type Props = IntegrationsHomeScreenProps &
|
||||
InjectedFormProps<{ category: string }, IntegrationsHomeScreenProps>;
|
||||
|
||||
const PRIMARY_MENU_IDS = {
|
||||
ACTIVE: "ACTIVE",
|
||||
CREATE_NEW: "CREATE_NEW",
|
||||
};
|
||||
|
||||
const getSecondaryMenuIds = (hasActiveSources = false) => {
|
||||
return {
|
||||
API: 0 + (hasActiveSources ? 0 : 1),
|
||||
DATABASE: 1 + (hasActiveSources ? 0 : 1),
|
||||
MOCK_DATABASE: 2 - (hasActiveSources ? 0 : 2),
|
||||
};
|
||||
};
|
||||
|
||||
const TERTIARY_MENU_IDS = {
|
||||
ACTIVE_CONNECTIONS: 0,
|
||||
MOCK_DATABASE: 1,
|
||||
};
|
||||
|
||||
class IntegrationsHomeScreen extends React.Component<
|
||||
Props,
|
||||
IntegrationsHomeScreenState
|
||||
> {
|
||||
unsupportedPluginContinueAction: () => void;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.unsupportedPluginContinueAction = () => null;
|
||||
this.state = {
|
||||
page: 1,
|
||||
activePrimaryMenuId: PRIMARY_MENU_IDS.CREATE_NEW,
|
||||
activeSecondaryMenuId: getSecondaryMenuIds(
|
||||
props.mockDatasources.length > 0,
|
||||
).API,
|
||||
unsupportedPluginDialogVisible: false,
|
||||
};
|
||||
}
|
||||
|
||||
syncActivePrimaryMenu = () => {
|
||||
// on mount/update if syncing the primary active menu.
|
||||
const { selectedTab } = this.props;
|
||||
if (
|
||||
(selectedTab === INTEGRATION_TABS.NEW &&
|
||||
this.state.activePrimaryMenuId !== PRIMARY_MENU_IDS.CREATE_NEW) ||
|
||||
(selectedTab === INTEGRATION_TABS.ACTIVE &&
|
||||
this.state.activePrimaryMenuId !== PRIMARY_MENU_IDS.ACTIVE)
|
||||
) {
|
||||
this.setState({
|
||||
activePrimaryMenuId:
|
||||
selectedTab === INTEGRATION_TABS.NEW
|
||||
? PRIMARY_MENU_IDS.CREATE_NEW
|
||||
: PRIMARY_MENU_IDS.ACTIVE,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { basePageId, dataSources, history } = this.props;
|
||||
|
||||
const queryParams = getQueryParams();
|
||||
const redirectMode = queryParams.mode;
|
||||
const isGeneratePageInitiator = getIsGeneratePageInitiator();
|
||||
if (isGeneratePageInitiator) {
|
||||
if (redirectMode === INTEGRATION_EDITOR_MODES.AUTO) {
|
||||
delete queryParams.mode;
|
||||
delete queryParams.from;
|
||||
history.replace(
|
||||
integrationEditorURL({
|
||||
basePageId,
|
||||
selectedTab: INTEGRATION_TABS.NEW,
|
||||
params: queryParams,
|
||||
}),
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
dataSources.length > 0 &&
|
||||
redirectMode === INTEGRATION_EDITOR_MODES.AUTO
|
||||
) {
|
||||
// User will be taken to active tab if there are datasources
|
||||
history.replace(
|
||||
integrationEditorURL({
|
||||
basePageId,
|
||||
selectedTab: INTEGRATION_TABS.ACTIVE,
|
||||
}),
|
||||
);
|
||||
} else if (redirectMode === INTEGRATION_EDITOR_MODES.MOCK) {
|
||||
// If there are no datasources -> new user
|
||||
history.replace(
|
||||
integrationEditorURL({
|
||||
basePageId,
|
||||
selectedTab: INTEGRATION_TABS.NEW,
|
||||
}),
|
||||
);
|
||||
this.onSelectSecondaryMenu(
|
||||
getSecondaryMenuIds(dataSources.length > 0).MOCK_DATABASE,
|
||||
);
|
||||
} else {
|
||||
this.syncActivePrimaryMenu();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
this.syncActivePrimaryMenu();
|
||||
const { basePageId, dataSources, history } = this.props;
|
||||
if (dataSources.length === 0 && prevProps.dataSources.length > 0) {
|
||||
history.replace(
|
||||
integrationEditorURL({
|
||||
basePageId,
|
||||
selectedTab: INTEGRATION_TABS.NEW,
|
||||
}),
|
||||
);
|
||||
this.onSelectSecondaryMenu(
|
||||
getSecondaryMenuIds(dataSources.length > 0).MOCK_DATABASE,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
onSelectPrimaryMenu = (activePrimaryMenuId: string) => {
|
||||
const { basePageId, dataSources, history } = this.props;
|
||||
if (activePrimaryMenuId === this.state.activePrimaryMenuId) {
|
||||
return;
|
||||
}
|
||||
history.push(
|
||||
integrationEditorURL({
|
||||
basePageId,
|
||||
selectedTab:
|
||||
activePrimaryMenuId === PRIMARY_MENU_IDS.ACTIVE
|
||||
? INTEGRATION_TABS.ACTIVE
|
||||
: INTEGRATION_TABS.NEW,
|
||||
}),
|
||||
);
|
||||
this.setState({
|
||||
activeSecondaryMenuId:
|
||||
activePrimaryMenuId === PRIMARY_MENU_IDS.ACTIVE
|
||||
? TERTIARY_MENU_IDS.ACTIVE_CONNECTIONS
|
||||
: getSecondaryMenuIds(dataSources.length > 0).API,
|
||||
});
|
||||
};
|
||||
|
||||
onSelectSecondaryMenu = (activeSecondaryMenuId: number) => {
|
||||
this.setState({ activeSecondaryMenuId });
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
basePageId,
|
||||
canCreateDatasource = false,
|
||||
dataSources,
|
||||
location,
|
||||
showDebugger,
|
||||
} = this.props;
|
||||
const { unsupportedPluginDialogVisible } = this.state;
|
||||
let currentScreen;
|
||||
const { activePrimaryMenuId } = this.state;
|
||||
|
||||
const PRIMARY_MENU: TabProp[] = [
|
||||
{
|
||||
key: "ACTIVE",
|
||||
title: "Active",
|
||||
panelComponent: <div />,
|
||||
},
|
||||
...(canCreateDatasource
|
||||
? [
|
||||
{
|
||||
key: "CREATE_NEW",
|
||||
title: "Create new",
|
||||
panelComponent: <div />,
|
||||
icon: "plus",
|
||||
iconSize: IconSize.XS,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
].filter(Boolean);
|
||||
|
||||
const isGeneratePageInitiator = getIsGeneratePageInitiator();
|
||||
// Avoid user to switch tabs when in generate page flow by hiding the tabs itself.
|
||||
const showTabs = !isGeneratePageInitiator;
|
||||
|
||||
if (activePrimaryMenuId === PRIMARY_MENU_IDS.CREATE_NEW) {
|
||||
currentScreen = <CreateNewDatasourceTab />;
|
||||
} else {
|
||||
currentScreen = (
|
||||
<ActiveDataSources
|
||||
basePageId={basePageId}
|
||||
dataSources={dataSources}
|
||||
history={this.props.history}
|
||||
location={location}
|
||||
onCreateNew={() => {
|
||||
this.onSelectPrimaryMenu(PRIMARY_MENU_IDS.CREATE_NEW);
|
||||
// Event for datasource creation click
|
||||
const entryPoint = DatasourceCreateEntryPoints.ACTIVE_DATASOURCE;
|
||||
AnalyticsUtil.logEvent("NAVIGATE_TO_CREATE_NEW_DATASOURCE_PAGE", {
|
||||
entryPoint,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<BackButton />
|
||||
<UnsupportedPluginDialog
|
||||
isModalOpen={unsupportedPluginDialogVisible}
|
||||
onClose={() =>
|
||||
this.setState({ unsupportedPluginDialogVisible: false })
|
||||
}
|
||||
onContinue={this.unsupportedPluginContinueAction}
|
||||
/>
|
||||
<ApiHomePage
|
||||
className="t--integrationsHomePage"
|
||||
style={{ overflow: "auto" }}
|
||||
>
|
||||
<HeaderFlex>
|
||||
<p className="sectionHeadings">Datasources in your workspace</p>
|
||||
</HeaderFlex>
|
||||
<SectionGrid
|
||||
isActiveTab={
|
||||
this.state.activePrimaryMenuId !== PRIMARY_MENU_IDS.ACTIVE
|
||||
}
|
||||
>
|
||||
<MainTabsContainer>
|
||||
{showTabs && (
|
||||
<Tabs
|
||||
data-testid="t--datasource-tab"
|
||||
onValueChange={this.onSelectPrimaryMenu}
|
||||
value={this.state.activePrimaryMenuId}
|
||||
>
|
||||
<TabsList>
|
||||
{PRIMARY_MENU.map((tab: TabProp) => (
|
||||
<Tab
|
||||
data-testid={`t--tab-${tab.key}`}
|
||||
key={tab.key}
|
||||
value={tab.key}
|
||||
>
|
||||
{tab.title}
|
||||
</Tab>
|
||||
))}
|
||||
</TabsList>
|
||||
{PRIMARY_MENU.map((tab: TabProp) => (
|
||||
<TabPanel key={tab.key} value={tab.key}>
|
||||
{tab.panelComponent}
|
||||
</TabPanel>
|
||||
))}
|
||||
</Tabs>
|
||||
)}
|
||||
</MainTabsContainer>
|
||||
<ResizerMainContainer>
|
||||
<ResizerContentContainer className="integrations-content-container">
|
||||
{currentScreen}
|
||||
</ResizerContentContainer>
|
||||
{showDebugger && <Debugger />}
|
||||
</ResizerMainContainer>
|
||||
</SectionGrid>
|
||||
</ApiHomePage>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
// Debugger render flag
|
||||
const showDebugger = showDebuggerFlag(state);
|
||||
|
||||
const userWorkspacePermissions =
|
||||
getCurrentAppWorkspace(state).userPermissions ?? [];
|
||||
|
||||
const featureFlags = selectFeatureFlags(state);
|
||||
const isFeatureEnabled = isGACEnabled(featureFlags);
|
||||
|
||||
const canCreateDatasource = getHasCreateDatasourcePermission(
|
||||
isFeatureEnabled,
|
||||
userWorkspacePermissions,
|
||||
);
|
||||
return {
|
||||
dataSources: getDatasources(state),
|
||||
mockDatasources: getMockDatasources(state),
|
||||
isCreating: state.ui.apiPane.isCreating,
|
||||
applicationId: getCurrentApplicationId(state),
|
||||
canCreateDatasource,
|
||||
showDebugger,
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(
|
||||
reduxForm<{ category: string }, IntegrationsHomeScreenProps>({
|
||||
form: API_HOME_SCREEN_FORM,
|
||||
})(IntegrationsHomeScreen),
|
||||
);
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
import React from "react";
|
||||
import IntegrationsHomeScreen from "./IntegrationsHomeScreen";
|
||||
import type { RouteComponentProps } from "react-router";
|
||||
import * as Sentry from "@sentry/react";
|
||||
|
||||
type Props = RouteComponentProps<{
|
||||
basePageId: string;
|
||||
selectedTab: string;
|
||||
}>;
|
||||
|
||||
const integrationsEditor = (props: Props) => {
|
||||
const { history, location, match } = props;
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
position: "relative",
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<IntegrationsHomeScreen
|
||||
basePageId={match.params.basePageId}
|
||||
history={history}
|
||||
location={location}
|
||||
selectedTab={match.params.selectedTab}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sentry.withProfiler(integrationsEditor);
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
import styled from "styled-components";
|
||||
import { MenuItem } from "@appsmith/ads-old";
|
||||
import { Colors } from "constants/Colors";
|
||||
|
||||
const DangerMenuItem = styled(MenuItem)`
|
||||
&&,
|
||||
&& .cs-text {
|
||||
color: ${Colors.DANGER_SOLID};
|
||||
}
|
||||
|
||||
&&,
|
||||
&&:hover {
|
||||
svg,
|
||||
svg path {
|
||||
fill: ${Colors.DANGER_SOLID};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default DangerMenuItem;
|
||||
|
|
@ -50,7 +50,7 @@ const DsTitle = styled.div`
|
|||
text-overflow: ellipsis;
|
||||
padding-right: 4px;
|
||||
}
|
||||
.cs-icon {
|
||||
.ads-v2-icon {
|
||||
margin-left: ${(props) => props.theme.spaces[2]}px;
|
||||
}
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
import React from "react";
|
||||
import type {
|
||||
DefaultDropDownValueNodeProps,
|
||||
DropdownOption,
|
||||
} from "@appsmith/ads-old";
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownWrapper,
|
||||
DropdownContainer as DropdownComponentContainer,
|
||||
} from "@appsmith/ads-old";
|
||||
import { Colors } from "constants/Colors";
|
||||
import styled from "styled-components";
|
||||
import { Classes as GitSyncClasses } from "pages/Editor/gitSync/constants";
|
||||
import { importSvg } from "@appsmith/ads-old";
|
||||
|
||||
const ChevronDown = importSvg(
|
||||
async () => import("assets/icons/ads/chevron-down.svg"),
|
||||
);
|
||||
|
||||
const SelectedValueNodeContainer = styled.div`
|
||||
color: ${Colors.CRUSTA};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
& .label {
|
||||
margin-right: ${(props) => props.theme.spaces[2]}px;
|
||||
}
|
||||
`;
|
||||
|
||||
function SelectedValueNode(props: DefaultDropDownValueNodeProps) {
|
||||
const { selected } = props;
|
||||
return (
|
||||
<SelectedValueNodeContainer>
|
||||
<span className="label">{(selected as DropdownOption).label}</span>
|
||||
<ChevronDown />
|
||||
</SelectedValueNodeContainer>
|
||||
);
|
||||
}
|
||||
|
||||
const DropdownContainer = styled.div`
|
||||
& ${DropdownComponentContainer} {
|
||||
width: max-content;
|
||||
}
|
||||
&&&& ${DropdownWrapper} {
|
||||
padding: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
interface OptionSelectorProps {
|
||||
options: DropdownOption[];
|
||||
selected: DropdownOption;
|
||||
// TODO: Fix this the next time the file is edited
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
onSelect?: (value?: string, dropdownOption?: any) => void;
|
||||
}
|
||||
|
||||
function OptionSelector({ onSelect, options, selected }: OptionSelectorProps) {
|
||||
return (
|
||||
<DropdownContainer className={GitSyncClasses.OPTION_SELECTOR_WRAPPER}>
|
||||
<Dropdown
|
||||
SelectedValueNode={SelectedValueNode}
|
||||
bgColor={"transparent"}
|
||||
className="auth-type-dropdown"
|
||||
onSelect={onSelect}
|
||||
options={options}
|
||||
selected={selected}
|
||||
showDropIcon={false}
|
||||
showLabelOnly
|
||||
/>
|
||||
</DropdownContainer>
|
||||
);
|
||||
}
|
||||
|
||||
export default OptionSelector;
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import type { Theme } from "constants/DefaultTheme";
|
||||
import type { TabProp } from "@appsmith/ads-old";
|
||||
import { getTypographyByKey } from "@appsmith/ads-old";
|
||||
import { Colors } from "constants/Colors";
|
||||
|
||||
|
|
@ -40,7 +39,10 @@ const Wrapper = styled.div<WrapperProps>`
|
|||
`;
|
||||
|
||||
export default function TabItem(props: {
|
||||
tab: TabProp;
|
||||
tab: {
|
||||
key: string;
|
||||
title: string;
|
||||
};
|
||||
selected: boolean;
|
||||
vertical: boolean;
|
||||
}) {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ const FileImportCard = styled.div<{ fillCardWidth: boolean }>`
|
|||
height: 100%;
|
||||
justify-content: flex-start;
|
||||
|
||||
.cs-icon {
|
||||
.ads-v2-icon {
|
||||
border-radius: 50%;
|
||||
width: ${(props) => props.theme.spaces[12] + 2}px;
|
||||
height: ${(props) => props.theme.spaces[12] + 2}px;
|
||||
|
|
@ -146,7 +146,7 @@ const StatusbarWrapper = styled.div`
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.cs-icon {
|
||||
.ads-v2-icon {
|
||||
margin: auto;
|
||||
border-radius: var(--ads-v2-border-radius-circle);
|
||||
width: 32px;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ const UserNameSection = styled.div`
|
|||
|
||||
const StyledMenuItem = styled(MenuItem)`
|
||||
svg,
|
||||
.cs-icon svg path {
|
||||
.ads-v2-icon svg path {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
fill: var(--ads-v2-color-fg);
|
||||
|
|
|
|||
|
|
@ -40,11 +40,9 @@ const ApplicationSearchItem = (props: Props) => {
|
|||
>
|
||||
<CircleAppIcon
|
||||
className="!mr-1"
|
||||
color="var(--ads-v2-color-fg)"
|
||||
// @ts-expect-error Fix this the next time the file is edited
|
||||
name={
|
||||
application?.icon ||
|
||||
(getApplicationIcon(application.id) as AppIconName)
|
||||
(application?.icon ||
|
||||
getApplicationIcon(application.id)) as AppIconName
|
||||
}
|
||||
size={Size.xxs}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
import React, { useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { setThemeMode } from "actions/themeActions";
|
||||
import { MenuItem, RectangularSwitcher } from "@appsmith/ads-old";
|
||||
import { getCurrentThemeMode, ThemeMode } from "selectors/themeSelectors";
|
||||
|
||||
export default function ThemeSwitcher(props: { className?: string }) {
|
||||
const dispatch = useDispatch();
|
||||
const themeMode = useSelector(getCurrentThemeMode);
|
||||
const [switchedOn, setSwitchOn] = useState(themeMode === ThemeMode.DARK);
|
||||
|
||||
return (
|
||||
<MenuItem
|
||||
label={
|
||||
<RectangularSwitcher
|
||||
className={props.className}
|
||||
onSwitch={(value: boolean) => {
|
||||
setSwitchOn(value);
|
||||
dispatch(setThemeMode(value ? ThemeMode.DARK : ThemeMode.LIGHT));
|
||||
}}
|
||||
value={switchedOn}
|
||||
/>
|
||||
}
|
||||
text="Theme"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
// import React, { JSXElementConstructor } from "react";
|
||||
// import { IconProps, IconWrapper } from "constants/IconConstants";
|
||||
import type React from "react";
|
||||
import { Alignment, Classes } from "@blueprintjs/core";
|
||||
import { Classes as DTClasses } from "@blueprintjs/datetime";
|
||||
|
|
@ -112,7 +110,6 @@ export const hexToRgba = (color: string, alpha: number) => {
|
|||
};
|
||||
|
||||
const ALPHANUMERIC = "1234567890abcdefghijklmnopqrstuvwxyz";
|
||||
// const ALPHABET = "abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
export const generateReactKey = ({
|
||||
prefix = "",
|
||||
|
|
|
|||
Loading…
Reference in New Issue