diff --git a/app/client/.eslintrc.base.json b/app/client/.eslintrc.base.json index 65a20d8f27..6826984d32 100644 --- a/app/client/.eslintrc.base.json +++ b/app/client/.eslintrc.base.json @@ -54,7 +54,27 @@ { "caseSensitive": false } ], "no-console": "warn", - "no-debugger": "warn" + "no-debugger": "warn", + "@typescript-eslint/no-restricted-imports": [ + "error", + { + "patterns": [ + { + "group": ["@blueprintjs/core/lib/esnext/*"], + "message": "Reason: @blueprintjs/core has both lib/esnext and lib/esm directories which export the same components. To avoid duplicating components in the bundle, please import only from the lib/esm directory." + }, + { + "group": ["*.svg"], + "importNames": ["ReactComponent"], + "message": "Reason: Please don’t import SVG icons statically. (They won’t always be needed, but they *will* always be present in the bundle and will increase the bundle size.) Instead, please either import them as SVG paths (e.g. import starIconUrl from './star.svg'), or use the importSvg wrapper from design-system-old (e.g. const StarIcon = importSvg(() => import('./star.svg')))." + }, + { + "group": ["remixicon-react/*"], + "message": "Reason: Please don’t import Remix icons statically. (They won’t always be needed, but they *will* always be present in the bundle and will increase the bundle size.) Instead, please use the importRemixIcon wrapper from design-system-old (e.g. const StarIcon = importRemixIcon(() => import('remixicon-react/Star')))." + } + ] + } + ] }, "settings": { "import/resolver": { diff --git a/app/client/.eslintrc.js b/app/client/.eslintrc.js index 7db2dd3ebe..45bc21c710 100644 --- a/app/client/.eslintrc.js +++ b/app/client/.eslintrc.js @@ -1,5 +1,15 @@ // The `@type` comment improves auto-completion for VS Code users: https://github.com/appsmithorg/appsmith/pull/21602#discussion_r1144528505 /** @type {import('eslint').Linter.Config} */ +const fs = require("fs"); +const path = require("path"); +const JSON5 = require("json5"); + +const baseEslintConfig = JSON5.parse( + fs.readFileSync(path.join(__dirname, "./.eslintrc.base.json"), "utf8"), +); +const baseNoRestrictedImports = + baseEslintConfig.rules["@typescript-eslint/no-restricted-imports"][1]; + const eslintConfig = { extends: ["./.eslintrc.base.json"], rules: { @@ -10,6 +20,7 @@ const eslintConfig = { "error", { paths: [ + ...(baseNoRestrictedImports.paths ?? []), { name: "codemirror", message: @@ -26,22 +37,7 @@ const eslintConfig = { }, ], patterns: [ - { - group: ["@blueprintjs/core/lib/esnext/*"], - message: - "Reason: @blueprintjs/core has both lib/esnext and lib/esm directories which export the same components. To avoid duplicating components in the bundle, please import only from the lib/esm directory.", - }, - { - group: ["*.svg"], - importNames: ["ReactComponent"], - message: - "Reason: Please don’t import SVG icons statically. (They won’t always be needed, but they *will* always be present in the bundle and will increase the bundle size.) Instead, please either import them as SVG paths (e.g. import starIconUrl from './star.svg'), or use the importSvg wrapper from design-system-old (e.g. const StarIcon = importSvg(() => import('./star.svg'))).", - }, - { - group: ["remixicon-react/*"], - message: - "Reason: Please don’t import Remix icons statically. (They won’t always be needed, but they *will* always be present in the bundle and will increase the bundle size.) Instead, please use the importRemixIcon wrapper from design-system-old (e.g. const StarIcon = importRemixIcon(() => import('remixicon-react/Star'))).", - }, + ...(baseNoRestrictedImports.patterns ?? []), { group: ["**/ce/*"], message: "Reason: Please use @appsmith import instead.", diff --git a/app/client/package.json b/app/client/package.json index 880f437fca..fe38d8c380 100644 --- a/app/client/package.json +++ b/app/client/package.json @@ -306,6 +306,7 @@ "jest-canvas-mock": "^2.3.1", "jest-environment-jsdom": "^27.4.1", "jest-styled-components": "^7.0.8", + "json5": "^2.2.3", "lint-staged": "^13.2.0", "msw": "^0.28.0", "plop": "^3.1.1", diff --git a/app/client/packages/design-system/headless/src/components/Checkbox/Checkbox.tsx b/app/client/packages/design-system/headless/src/components/Checkbox/Checkbox.tsx index ae7ab969fc..7bb5a7e064 100644 --- a/app/client/packages/design-system/headless/src/components/Checkbox/Checkbox.tsx +++ b/app/client/packages/design-system/headless/src/components/Checkbox/Checkbox.tsx @@ -1,18 +1,33 @@ import { mergeProps } from "@react-aria/utils"; import { useFocusRing } from "@react-aria/focus"; import { useHover } from "@react-aria/interactions"; -import CheckIcon from "remixicon-react/CheckLineIcon"; import { useToggleState } from "@react-stately/toggle"; import { useFocusableRef } from "@react-spectrum/utils"; -import SubtractIcon from "remixicon-react/SubtractLineIcon"; import React, { forwardRef, useContext, useRef } from "react"; import { useVisuallyHidden } from "@react-aria/visually-hidden"; import type { SpectrumCheckboxProps } from "@react-types/checkbox"; import type { FocusableRef, StyleProps } from "@react-types/shared"; import { useCheckbox, useCheckboxGroupItem } from "@react-aria/checkbox"; - import { CheckboxGroupContext } from "./context"; +// Adapted from remixicon-react/CheckLineIcon (https://github.com/Remix-Design/RemixIcon/blob/f88a51b6402562c6c2465f61a3e845115992e4c6/icons/System/check-line.svg) +const CheckIcon = ({ size }: { size: number }) => { + return ( + + + + ); +}; + +// Adapted from remixicon-react/SubtractLineIcon (https://github.com/Remix-Design/RemixIcon/blob/f88a51b6402562c6c2465f61a3e845115992e4c6/icons/System/subtract-line.svg) +const SubtractIcon = ({ size }: { size: number }) => { + return ( + + + + ); +}; + export interface CheckboxProps extends Omit { icon?: React.ReactNode; diff --git a/app/client/packages/design-system/headless/src/components/Field/ErrorText.tsx b/app/client/packages/design-system/headless/src/components/Field/ErrorText.tsx index 34d89074ba..27212c2028 100644 --- a/app/client/packages/design-system/headless/src/components/Field/ErrorText.tsx +++ b/app/client/packages/design-system/headless/src/components/Field/ErrorText.tsx @@ -1,9 +1,17 @@ import React, { forwardRef } from "react"; import type { HTMLAttributes } from "react"; import { useDOMRef } from "@react-spectrum/utils"; -import AlertIcon from "remixicon-react/AlertFillIcon"; import type { DOMRef, SpectrumHelpTextProps } from "@react-types/shared"; +// Adapted from remixicon-react/AlertFillIcon (https://github.com/Remix-Design/RemixIcon/blob/f88a51b6402562c6c2465f61a3e845115992e4c6/icons/System/alert-fill.svg) +const AlertIcon = () => { + return ( + + + + ); +}; + interface HelpTextProps extends SpectrumHelpTextProps { errorMessageProps?: HTMLAttributes; } diff --git a/app/client/packages/design-system/headless/src/components/Field/Label.tsx b/app/client/packages/design-system/headless/src/components/Field/Label.tsx index 06b7573c99..fc0b359531 100644 --- a/app/client/packages/design-system/headless/src/components/Field/Label.tsx +++ b/app/client/packages/design-system/headless/src/components/Field/Label.tsx @@ -2,9 +2,23 @@ import React, { forwardRef } from "react"; import { useDOMRef } from "@react-spectrum/utils"; import type { DOMRef } from "@react-types/shared"; import { filterDOMProps } from "@react-aria/utils"; -import AsteriskIcon from "remixicon-react/AsteriskIcon"; import type { SpectrumLabelProps } from "@react-types/label"; +// Adapted from remixicon-react/AsteriskIcon (https://github.com/Remix-Design/RemixIcon/blob/f88a51b6402562c6c2465f61a3e845115992e4c6/icons/Editor/asterisk.svg) +const AsteriskIcon = (props: { [key: string]: string | undefined }) => { + return ( + + + + ); +}; + export interface LabelProps extends SpectrumLabelProps { isEmphasized?: boolean; } diff --git a/app/client/packages/design-system/widgets/src/components/Button/Button.test.tsx b/app/client/packages/design-system/widgets/src/components/Button/Button.test.tsx index 558aa676aa..3eba6bca2b 100644 --- a/app/client/packages/design-system/widgets/src/components/Button/Button.test.tsx +++ b/app/client/packages/design-system/widgets/src/components/Button/Button.test.tsx @@ -2,10 +2,24 @@ import React from "react"; import "@testing-library/jest-dom"; import { Icon } from "@design-system/headless"; import { render, screen } from "@testing-library/react"; -import EmotionHappyLineIcon from "remixicon-react/EmotionHappyLineIcon"; import { Button } from "./"; +// Adapted from remixicon-react/EmotionHappyLineIcon (https://github.com/Remix-Design/RemixIcon/blob/f88a51b6402562c6c2465f61a3e845115992e4c6/icons/User%20%26%20Faces/emotion-happy-line.svg) +const EmotionHappyLineIcon = ({ ...props }: Record) => { + return ( + + + + ); +}; + describe("@design-system/widgets/Button", () => { it("renders children when passed", () => { render(); diff --git a/app/client/packages/design-system/widgets/src/components/Checkbox/Checkbox.test.tsx b/app/client/packages/design-system/widgets/src/components/Checkbox/Checkbox.test.tsx index 97b965fc9b..91f6b3d874 100644 --- a/app/client/packages/design-system/widgets/src/components/Checkbox/Checkbox.test.tsx +++ b/app/client/packages/design-system/widgets/src/components/Checkbox/Checkbox.test.tsx @@ -3,10 +3,24 @@ import "@testing-library/jest-dom"; import { Icon } from "@design-system/headless"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import EmotionHappyLineIcon from "remixicon-react/EmotionHappyLineIcon"; import { Checkbox } from "./Checkbox"; +// Adapted from remixicon-react/EmotionHappyLineIcon (https://github.com/Remix-Design/RemixIcon/blob/f88a51b6402562c6c2465f61a3e845115992e4c6/icons/User%20%26%20Faces/emotion-happy-line.svg) +const EmotionHappyLineIcon = ({ ...props }: Record) => { + return ( + + + + ); +}; + describe("@design-system/widgets/Checkbox", () => { const onChangeSpy = jest.fn(); diff --git a/app/client/packages/design-system/widgets/src/components/Spinner/index.styled.tsx b/app/client/packages/design-system/widgets/src/components/Spinner/index.styled.tsx index 59c2a0bc20..b7fbe84fe6 100644 --- a/app/client/packages/design-system/widgets/src/components/Spinner/index.styled.tsx +++ b/app/client/packages/design-system/widgets/src/components/Spinner/index.styled.tsx @@ -1,5 +1,27 @@ +import React from "react"; import styled from "styled-components"; -import LoaderIcon from "remixicon-react/Loader2FillIcon"; + +// Adapted from remixicon-react/Loader2FillIcon (https://github.com/Remix-Design/RemixIcon/blob/f88a51b6402562c6c2465f61a3e845115992e4c6/icons/System/loader-2-fill.svg) +function LoaderIcon({ + className, + ...props +}: { + className?: string; + [key: string]: any; +}) { + return ( + + + + ); +} export const StyledSpinner = styled(LoaderIcon)` animation: spin 1s linear infinite; diff --git a/app/client/src/workers/Evaluation/fns/__tests__/interval.test.ts b/app/client/src/workers/Evaluation/fns/__tests__/interval.test.ts index d474dd928e..42963e86d4 100644 --- a/app/client/src/workers/Evaluation/fns/__tests__/interval.test.ts +++ b/app/client/src/workers/Evaluation/fns/__tests__/interval.test.ts @@ -80,7 +80,7 @@ describe("Tests for interval functions", () => { // eslint-disable-next-line jest/no-disabled-tests it.skip("Callback should have access to outer scope variables", async () => { const stalker = jest.fn(); - function test() { + function runTest() { let count = 0; const interval = evalContext.setInterval(() => { count++; @@ -88,7 +88,7 @@ describe("Tests for interval functions", () => { }, 100); return interval; } - const interval = test(); + const interval = runTest(); await new Promise((resolve) => setTimeout(resolve, 300)); clearInterval(interval); expect(stalker).toBeCalledTimes(2); diff --git a/app/client/yarn.lock b/app/client/yarn.lock index 79dcc13bbc..36c5184222 100644 --- a/app/client/yarn.lock +++ b/app/client/yarn.lock @@ -9679,6 +9679,7 @@ __metadata: js-regex-pl: ^1.0.1 js-sha256: ^0.9.0 jshint: ^2.13.4 + json5: ^2.2.3 klona: ^2.0.5 libphonenumber-js: ^1.9.44 linkedom: ^0.14.20