diff --git a/package.json b/package.json index da7bd4dfc0..944e210a3b 100644 --- a/package.json +++ b/package.json @@ -44,15 +44,16 @@ "run:example": "tsx -r dotenv/config -r tsconfig-paths/register ./examples/index.ts" }, "resolutions": { - "@types/react": "^17.0.0", - "@types/react-dom": "^17.0.0", + "@types/react": "18.3.18", + "@types/react-dom": "^18.0.0", "@typescript-eslint/parser": "^6.2.0", "react-router-dom": "^6.11.2", "react-router": "^6.11.2", "react": "^18.0.0", "react-dom": "^18.0.0", "nwsapi": "2.2.7", - "antd": "5.12.8" + "antd": "5.12.8", + "@ant-design/icons": "^5.6.1" }, "config": { "ghooks": { @@ -72,13 +73,14 @@ "@commitlint/cli": "^16.1.0", "@commitlint/config-conventional": "^16.0.0", "@commitlint/prompt-cli": "^16.1.0", - "@types/react": "^17.0.0", - "@types/react-dom": "^17.0.0", + "@types/react": "18.3.18", + "@types/react-dom": "^18.0.0", "auto-changelog": "^2.4.0", "eslint-plugin-jest-dom": "^5.0.1", "eslint-plugin-testing-library": "^5.11.0", "ghooks": "^2.0.4", "lint-staged": "^13.2.3", + "patch-package": "^8.0.0", "pretty-format": "^24.0.0", "pretty-quick": "^3.1.0", "react": "^18.0.0", diff --git a/packages/core/cli/src/commands/postinstall.js b/packages/core/cli/src/commands/postinstall.js index 202fb6656c..be0a53f997 100644 --- a/packages/core/cli/src/commands/postinstall.js +++ b/packages/core/cli/src/commands/postinstall.js @@ -14,6 +14,14 @@ const { existsSync, mkdirSync, readFileSync, appendFileSync } = require('fs'); const { readFile, writeFile } = require('fs').promises; const { createStoragePluginsSymlink, createDevPluginsSymlink } = require('@nocobase/utils/plugin-symlink'); +function runPatchPackage() { + // run yarn patch-package + // console.log('patching third party packages...'); + run('yarn', ['patch-package'], { + stdio: 'pipe', + }); +} + function writeToExclude() { const excludePath = resolve(process.cwd(), '.git', 'info', 'exclude'); const content = 'packages/pro-plugins/\n'; @@ -47,6 +55,7 @@ module.exports = (cli) => { .allowUnknownOption() .option('--skip-umi') .action(async (options) => { + runPatchPackage(); writeToExclude(); generatePlugins(); generatePlaywrightPath(true); diff --git a/packages/core/client/package.json b/packages/core/client/package.json index 888a97060e..2969f67358 100644 --- a/packages/core/client/package.json +++ b/packages/core/client/package.json @@ -8,7 +8,7 @@ "dependencies": { "@ahooksjs/use-url-state": "3.5.1", "@ant-design/cssinjs": "^1.11.1", - "@ant-design/icons": "^5.1.4", + "@ant-design/icons": "^5.6.1", "@ant-design/pro-layout": "^7.16.11", "@antv/g2plot": "^2.4.18", "@budibase/handlebars-helpers": "^0.14.0", diff --git a/packages/core/client/src/application/Application.tsx b/packages/core/client/src/application/Application.tsx index 0e6035f1b2..c41299d41f 100644 --- a/packages/core/client/src/application/Application.tsx +++ b/packages/core/client/src/application/Application.tsx @@ -235,7 +235,7 @@ export class Application { this.addComponents({ Link, Navigate: Navigate as ComponentType, - NavLink, + NavLink: NavLink as ComponentType, }); } diff --git a/packages/core/client/src/data-source/collection-template/CollectionTemplate.ts b/packages/core/client/src/data-source/collection-template/CollectionTemplate.ts index a25e386271..4f6e81f189 100644 --- a/packages/core/client/src/data-source/collection-template/CollectionTemplate.ts +++ b/packages/core/client/src/data-source/collection-template/CollectionTemplate.ts @@ -63,7 +63,7 @@ export abstract class CollectionTemplate { /** UI configurable CollectionOptions parameters (fields for adding or editing Collection forms) */ configurableProperties?: Record; /** Available field types for the current template */ - availableFieldInterfaces?: AvailableFieldInterfacesInclude | AvailableFieldInterfacesExclude; + availableFieldInterfaces?: AvailableFieldInterfacesInclude & AvailableFieldInterfacesExclude; /** Whether it is a divider */ divider?: boolean; /** Template description */ diff --git a/packages/core/client/src/hooks/useMenuItem.tsx b/packages/core/client/src/hooks/useMenuItem.tsx index 02274aa0ce..bdc2de58f4 100644 --- a/packages/core/client/src/hooks/useMenuItem.tsx +++ b/packages/core/client/src/hooks/useMenuItem.tsx @@ -44,7 +44,7 @@ export const useMenuItem = () => { const renderItems = useRef<() => JSX.Element>(null); const shouldRerender = useRef(false); - const Component = useCallback(({ limitCount }) => { + const Component = useCallback(({ limitCount }: { limitCount?: number }) => { if (!shouldRerender.current) { return null; } diff --git a/packages/core/client/src/lazy-helper/index.tsx b/packages/core/client/src/lazy-helper/index.tsx index 71c3cf2e76..a02ebfd059 100644 --- a/packages/core/client/src/lazy-helper/index.tsx +++ b/packages/core/client/src/lazy-helper/index.tsx @@ -7,13 +7,17 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import React, { ComponentType, lazy as ReactLazy } from 'react'; +import React, { lazy as ReactLazy } from 'react'; import { Spin } from 'antd'; import { get } from 'lodash'; import { useImported, loadableResource } from 'react-imported-component'; export const LAZY_COMPONENT_KEY = Symbol('LAZY_COMPONENT_KEY'); +type LazyComponentType, K extends keyof M> = { + [P in K]: M[P]; +}; + /** * Lazily loads a React component or multiple components. * @@ -31,16 +35,14 @@ export const LAZY_COMPONENT_KEY = Symbol('LAZY_COMPONENT_KEY'); * @param {...K[]} componentNames - The names of the components to be lazy-loaded from the module. * @returns {Record>} An object containing the lazy-loaded components. */ -export function lazy>( - factory: () => Promise<{ default: M }>, -): React.LazyExoticComponent; +export function lazy>(factory: () => Promise): M['default']; -export function lazy, K extends keyof M & string>( +export function lazy, K extends keyof M = keyof M>( factory: () => Promise, ...componentNames: K[] -): Record>; +): LazyComponentType; -export function lazy, K extends keyof M & string>( +export function lazy, K extends keyof M>( factory: () => Promise, ...componentNames: K[] ) { @@ -73,14 +75,14 @@ export function lazy, K extends keyof M & string>( }; }), ); - acc[name] = (props) => ( + acc[name] = ((props) => ( }> - ); + )) as M[K]; return acc; }, - {} as Record>, + {} as LazyComponentType, ); } diff --git a/packages/core/client/src/route-switch/antd/admin-layout/index.tsx b/packages/core/client/src/route-switch/antd/admin-layout/index.tsx index 545a712480..316acd15d2 100644 --- a/packages/core/client/src/route-switch/antd/admin-layout/index.tsx +++ b/packages/core/client/src/route-switch/antd/admin-layout/index.tsx @@ -14,7 +14,6 @@ import React, { createContext, FC, memo, - // @ts-ignore startTransition, useCallback, useContext, diff --git a/packages/core/client/src/schema-component/antd/__builtins__/portal.tsx b/packages/core/client/src/schema-component/antd/__builtins__/portal.tsx index 296a1ed9a3..701fd4fd6f 100644 --- a/packages/core/client/src/schema-component/antd/__builtins__/portal.tsx +++ b/packages/core/client/src/schema-component/antd/__builtins__/portal.tsx @@ -28,12 +28,14 @@ export const createPortalProvider = (id: string | symbol) => { {props.children} - {() => { - if (!props.id) return <>; - const portal = PortalMap.get(props.id); - if (portal) return createPortal(portal, document.body); - return <>; - }} + { + (() => { + if (!props.id) return <>; + const portal = PortalMap.get(props.id); + if (portal) return createPortal(portal, document.body); + return <>; + }) as unknown as React.ReactNode + } ); diff --git a/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx b/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx index 0df450ce92..0566eef305 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.Drawer.tsx @@ -10,7 +10,6 @@ import { observer, RecursionField, useField, useFieldSchema } from '@formily/react'; import { Drawer } from 'antd'; import classNames from 'classnames'; -// @ts-ignore import React, { FC, startTransition, useCallback, useEffect, useMemo, useState } from 'react'; import { ErrorBoundary, FallbackProps } from 'react-error-boundary'; import { NocoBaseRecursionField } from '../../../formily/NocoBaseRecursionField'; diff --git a/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx b/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx index e23d79031b..496a91ec20 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.Modal.tsx @@ -12,7 +12,6 @@ import { observer, useField, useFieldSchema } from '@formily/react'; import { Modal, ModalProps } from 'antd'; import classNames from 'classnames'; import { ErrorBoundary, FallbackProps } from 'react-error-boundary'; -// @ts-ignore import React, { FC, startTransition, useEffect, useMemo, useState } from 'react'; import { NocoBaseRecursionField } from '../../../formily/NocoBaseRecursionField'; import { useToken } from '../../../style'; diff --git a/packages/core/client/src/schema-component/antd/action/Action.Page.tsx b/packages/core/client/src/schema-component/antd/action/Action.Page.tsx index 8726edbc20..3853779f40 100644 --- a/packages/core/client/src/schema-component/antd/action/Action.Page.tsx +++ b/packages/core/client/src/schema-component/antd/action/Action.Page.tsx @@ -8,7 +8,6 @@ */ import { observer, useFieldSchema } from '@formily/react'; -// @ts-ignore import React, { FC, startTransition, useEffect, useMemo, useState } from 'react'; import { createPortal } from 'react-dom'; import { ActionContextNoRerender, useActionContext } from '.'; diff --git a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.tsx b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.tsx index 2714432cce..c439277ae6 100644 --- a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.tsx +++ b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.tsx @@ -48,7 +48,7 @@ export const AssociationFilterItem = withDynamicSchemaProps( const [searchVisible, setSearchVisible] = useState(false); - const defaultActiveKeyCollapse = useMemo( + const defaultActiveKeyCollapse = useMemo( () => (defaultCollapse && collectionField?.name ? [collectionField.name] : []), [collectionField?.name, defaultCollapse], ); diff --git a/packages/core/client/src/schema-component/antd/icon-picker/__tests__/icon-picker.test.tsx b/packages/core/client/src/schema-component/antd/icon-picker/__tests__/icon-picker.test.tsx index 57738bc9a2..cdc7676e91 100644 --- a/packages/core/client/src/schema-component/antd/icon-picker/__tests__/icon-picker.test.tsx +++ b/packages/core/client/src/schema-component/antd/icon-picker/__tests__/icon-picker.test.tsx @@ -18,7 +18,7 @@ describe('IconPicker', () => { const button = container.querySelector('button') as HTMLButtonElement; await userEvent.click(button); - expect(screen.queryAllByRole('img').length).toBe(422); + expect(screen.queryAllByRole('img').length).toBe(448); }); it('should display the selected icon', async () => { @@ -50,9 +50,9 @@ describe('IconPicker', () => { const searchInput = screen.queryByRole('search') as HTMLInputElement; await waitFor(() => expect(searchInput).toBeInTheDocument()); - expect(screen.queryAllByRole('img').length).toBe(422); + expect(screen.queryAllByRole('img').length).toBe(448); await userEvent.type(searchInput, 'left'); - await waitFor(() => expect(screen.queryAllByRole('img').length).toBeLessThan(422)); + await waitFor(() => expect(screen.queryAllByRole('img').length).toBeLessThan(448)); await userEvent.clear(searchInput); await userEvent.type(searchInput, 'abcd'); await waitFor(() => { diff --git a/packages/core/client/src/schema-component/antd/menu/Menu.tsx b/packages/core/client/src/schema-component/antd/menu/Menu.tsx index 5cf6b963c0..4659cdec34 100644 --- a/packages/core/client/src/schema-component/antd/menu/Menu.tsx +++ b/packages/core/client/src/schema-component/antd/menu/Menu.tsx @@ -398,7 +398,12 @@ const HeaderMenu = React.memo<{ }, ); -const SideMenu = React.memo( +type SideMenuProps = Omit & { + mode: 'mix' | MenuProps['mode']; + [key: string]: any; +}; + +const SideMenu = React.memo( ({ mode, sideMenuSchema, diff --git a/packages/core/client/src/schema-component/antd/table-v2/DelayRender.tsx b/packages/core/client/src/schema-component/antd/table-v2/DelayRender.tsx index 0cc5d4f5b3..1885badc52 100644 --- a/packages/core/client/src/schema-component/antd/table-v2/DelayRender.tsx +++ b/packages/core/client/src/schema-component/antd/table-v2/DelayRender.tsx @@ -8,7 +8,6 @@ */ import _ from 'lodash'; -// @ts-ignore import React, { FC, startTransition, useEffect, useState } from 'react'; import { useKeepAlive } from '../../../route-switch/antd/admin-layout/KeepAlive'; diff --git a/packages/core/client/src/schema-component/antd/tabs/Tabs.tsx b/packages/core/client/src/schema-component/antd/tabs/Tabs.tsx index fc3d9395dc..4a8c5fa6fd 100644 --- a/packages/core/client/src/schema-component/antd/tabs/Tabs.tsx +++ b/packages/core/client/src/schema-component/antd/tabs/Tabs.tsx @@ -52,7 +52,7 @@ export const Tabs: any = React.memo((props: TabsProps) => { const tabBarExtraContent = useMemo( () => ({ right: render(), - left: contextProps?.tabBarExtraContent, + left: contextProps?.tabBarExtraContent as React.ReactNode, }), [contextProps?.tabBarExtraContent, render], ); diff --git a/packages/core/client/src/schema-component/antd/variable/TextArea.tsx b/packages/core/client/src/schema-component/antd/variable/TextArea.tsx index ad242524ed..53656f75e5 100644 --- a/packages/core/client/src/schema-component/antd/variable/TextArea.tsx +++ b/packages/core/client/src/schema-component/antd/variable/TextArea.tsx @@ -447,6 +447,8 @@ export function TextArea(props) { onPaste={onPaste} onCompositionStart={onCompositionStart} onCompositionEnd={onCompositionEnd} + // should use data-placeholder here, but not sure if it is safe to make the change, so add ignore here + // @ts-ignore placeholder={props.placeholder} style={style} className={cx( diff --git a/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx b/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx index de3db9d2de..8762a557ec 100644 --- a/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx +++ b/packages/core/client/src/schema-initializer/items/DataBlockInitializer.tsx @@ -395,7 +395,7 @@ export const DataBlockInitializer: FC = (props) => { }, children, }, - ]; + ] as MenuProps['items']; }, [searchedChildren, hideChildrenIfSingleCollection, name, compile, title, icon, onClick, props]); if (childItems.length > 1 || (childItems.length === 1 && childItems[0].children?.length > 0)) { diff --git a/packages/core/client/src/schema-settings/GeneralSchemaDesigner.tsx b/packages/core/client/src/schema-settings/GeneralSchemaDesigner.tsx index 8cea71914d..3f41bf55ec 100644 --- a/packages/core/client/src/schema-settings/GeneralSchemaDesigner.tsx +++ b/packages/core/client/src/schema-settings/GeneralSchemaDesigner.tsx @@ -15,7 +15,6 @@ import classNames from 'classnames'; import React, { createContext, FC, - //@ts-ignore startTransition, useCallback, useEffect, diff --git a/packages/core/client/src/schema-settings/SchemaSettings.tsx b/packages/core/client/src/schema-settings/SchemaSettings.tsx index be9a281da0..68c9399eba 100644 --- a/packages/core/client/src/schema-settings/SchemaSettings.tsx +++ b/packages/core/client/src/schema-settings/SchemaSettings.tsx @@ -35,7 +35,6 @@ import React, { FC, ReactNode, createContext, - // @ts-ignore startTransition, useCallback, useContext, diff --git a/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/bulkEditFormItemSettings.ts b/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/bulkEditFormItemSettings.ts index b37491008b..98e9fba32a 100644 --- a/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/bulkEditFormItemSettings.ts +++ b/packages/plugins/@nocobase/plugin-action-bulk-edit/src/client/bulkEditFormItemSettings.ts @@ -201,7 +201,7 @@ export const bulkEditFormItemSettings = new SchemaSettings({ const { form } = useFormBlockContext(); const isFormReadPretty = useIsFormReadPretty(); const validateSchema = useValidateSchema(); - return form && !isFormReadPretty && validateSchema; + return form && !isFormReadPretty && Boolean(validateSchema); }, }, fieldComponentSettingsItem, diff --git a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/CollectionsManager/EditCollectionAction.tsx b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/CollectionsManager/EditCollectionAction.tsx index b2fc5ec706..41509b8159 100644 --- a/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/CollectionsManager/EditCollectionAction.tsx +++ b/packages/plugins/@nocobase/plugin-data-source-manager/src/client/component/CollectionsManager/EditCollectionAction.tsx @@ -191,7 +191,7 @@ const EditCollectionAction = (props) => { const schema = getSchema( { ...templateConf, - }, + } as unknown as IField, record, compile, getContainer, diff --git a/packages/plugins/@nocobase/plugin-graph-collection-manager/src/client/components/Entity.tsx b/packages/plugins/@nocobase/plugin-graph-collection-manager/src/client/components/Entity.tsx index 7da5289d20..fdfc2aee8a 100644 --- a/packages/plugins/@nocobase/plugin-graph-collection-manager/src/client/components/Entity.tsx +++ b/packages/plugins/@nocobase/plugin-graph-collection-manager/src/client/components/Entity.tsx @@ -297,7 +297,15 @@ const PopoverContent = React.forwardRef((props: any, ref) => { }); PopoverContent.displayName = 'PopoverContent'; -const PortsCom = React.memo(({ targetGraph, collectionData, setTargetNode, node, loadCollections }) => { +type PortsComProps = { + targetGraph: any; + collectionData: any; + setTargetNode: any; + node: any; + loadCollections: any; +}; + +const PortsCom = React.memo(({ targetGraph, collectionData, setTargetNode, node, loadCollections }) => { const { store: { data: { item, ports, data }, diff --git a/packages/plugins/@nocobase/plugin-map/package.json b/packages/plugins/@nocobase/plugin-map/package.json index 54a2772a96..40295e4a3f 100644 --- a/packages/plugins/@nocobase/plugin-map/package.json +++ b/packages/plugins/@nocobase/plugin-map/package.json @@ -19,8 +19,8 @@ "@formily/shared": "2.x", "@googlemaps/js-api-loader": "^1.16.1", "@types/google.maps": "^3.53.4", - "@types/react": "^17.0.0", - "@types/react-dom": "^17.0.0", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", "ahooks": "^3.7.2", "antd": "5.x", "react": "18.x", diff --git a/packages/plugins/@nocobase/plugin-mobile-client/package.json b/packages/plugins/@nocobase/plugin-mobile-client/package.json index f0579c0be5..4f2d44ccee 100644 --- a/packages/plugins/@nocobase/plugin-mobile-client/package.json +++ b/packages/plugins/@nocobase/plugin-mobile-client/package.json @@ -14,8 +14,8 @@ "@formily/antd-v5": "1.x", "@formily/react": "2.x", "@formily/shared": "2.x", - "@types/react": "17.x", - "@types/react-dom": "17.x", + "@types/react": "18.x", + "@types/react-dom": "18.x", "ahooks": "3.x", "antd": "5.x", "antd-mobile": "^5.38", diff --git a/packages/plugins/@nocobase/plugin-mobile/package.json b/packages/plugins/@nocobase/plugin-mobile/package.json index 3ce0b9173c..5eaec347b8 100644 --- a/packages/plugins/@nocobase/plugin-mobile/package.json +++ b/packages/plugins/@nocobase/plugin-mobile/package.json @@ -23,8 +23,8 @@ "@formily/core": "2.x", "@formily/react": "2.x", "@formily/shared": "2.x", - "@types/react": "17.x", - "@types/react-dom": "17.x", + "@types/react": "18.x", + "@types/react-dom": "18.x", "ahooks": "3.x", "antd": "5.x", "antd-mobile": "^5.38", diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/SchemaConfig.tsx b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/SchemaConfig.tsx index edb5f885d5..6a77c7bde3 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/SchemaConfig.tsx +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/client/instruction/SchemaConfig.tsx @@ -566,8 +566,8 @@ export function SchemaConfigButton(props) { const msg = validateForms(values.forms); if (msg) { message.error({ - // eslint-disable-next-line react-hooks/rules-of-hooks - title: t('Validation failed'), + // message.error does not support title, and it will cause error, so comment it + // title: t('Validation failed'), content: t(msg), }); return; diff --git a/patches/@types+react+18.3.18.patch b/patches/@types+react+18.3.18.patch new file mode 100644 index 0000000000..57e7c26a34 --- /dev/null +++ b/patches/@types+react+18.3.18.patch @@ -0,0 +1,22 @@ +diff --git a/node_modules/@types/react/index.d.ts b/node_modules/@types/react/index.d.ts +index 6ea73ef..c835599 100644 +--- a/node_modules/@types/react/index.d.ts ++++ b/node_modules/@types/react/index.d.ts +@@ -1030,7 +1030,7 @@ declare namespace React { + forceUpdate(callback?: () => void): void; + render(): ReactNode; + +- readonly props: Readonly

; ++ readonly props: Readonly

; + state: Readonly; + /** + * @deprecated +@@ -1125,7 +1125,7 @@ declare namespace React { + */ + interface FunctionComponent

{ + ( +- props: P, ++ props: P & { children?: P extends { children: infer C } ? C : any }, + /** + * @deprecated + *