From 61e816f947218161dd4c080a36c347aa1f25d053 Mon Sep 17 00:00:00 2001
From: dengfuping <fuping.dfp@antgroup.com>
Date: Thu, 21 Sep 2023 20:10:08 +0800
Subject: [PATCH] fix(design): spin and theme should inherit from parent
 context for ConfigProvider

---
 .../config-provider/__tests__/theme.test.tsx  | 40 +++++++++++++
 packages/design/src/config-provider/index.tsx | 56 ++++++++++---------
 .../design/src/config-provider/navigate.ts    |  4 +-
 3 files changed, 71 insertions(+), 29 deletions(-)
 create mode 100644 packages/design/src/config-provider/__tests__/theme.test.tsx

diff --git a/packages/design/src/config-provider/__tests__/theme.test.tsx b/packages/design/src/config-provider/__tests__/theme.test.tsx
new file mode 100644
index 000000000..c145d7751
--- /dev/null
+++ b/packages/design/src/config-provider/__tests__/theme.test.tsx
@@ -0,0 +1,40 @@
+import React from 'react';
+import { render } from '@testing-library/react';
+import { ConfigProvider, useToken } from '@oceanbase/design';
+
+describe('ConfigProvider theme', () => {
+  it('ConfigProvider theme token', () => {
+    const Child1 = () => {
+      const { token } = useToken();
+      expect(token.colorBgLayout).toBe('#F5F8FE');
+      return <div />;
+    };
+    const Child2 = () => {
+      const { token } = useToken();
+      expect(token.colorBgLayout).toBe('#ff0000');
+      return <div />;
+    };
+    const Child3 = () => {
+      const { token } = useToken();
+      expect(token.colorBgLayout).toBe('#ff0000');
+      return <div />;
+    };
+    render(
+      <ConfigProvider>
+        <Child1 />
+        <ConfigProvider
+          theme={{
+            token: {
+              colorBgLayout: '#ff0000',
+            },
+          }}
+        >
+          <Child2 />
+          <ConfigProvider>
+            <Child3 />
+          </ConfigProvider>
+        </ConfigProvider>
+      </ConfigProvider>
+    );
+  });
+});
diff --git a/packages/design/src/config-provider/index.tsx b/packages/design/src/config-provider/index.tsx
index 446504002..466e4e433 100644
--- a/packages/design/src/config-provider/index.tsx
+++ b/packages/design/src/config-provider/index.tsx
@@ -7,6 +7,7 @@ import type {
 } from 'antd/es/config-provider';
 import type { ComponentStyleConfig } from 'antd/es/config-provider/context';
 import type { SpinIndicator } from 'antd/es/spin';
+import { merge } from 'lodash';
 import StaticFunction from '../static-function';
 import defaultTheme from '../theme';
 import defaultThemeToken from '../theme/default';
@@ -46,44 +47,45 @@ const ExtendedConfigContext = React.createContext<ExtendedConfigConsumerProps>({
 
 const { defaultSeed, components } = defaultTheme;
 
-// ConfigProvider 默认设置主题和内嵌 App,支持 message, notification 和 Modal 等静态方法消费 ConfigProvider 配置
-// ref: https://ant.design/components/app-cn
 const ConfigProvider = ({ children, theme, navigate, spin, ...restProps }: ConfigProviderProps) => {
   // inherit from parent ConfigProvider
-  const parentContext = React.useContext<ExtendedConfigConsumerProps>(ExtendedConfigContext);
+  const parentContext = React.useContext<ConfigConsumerProps>(AntConfigProvider.ConfigContext);
+  const parentExtendedContext =
+    React.useContext<ExtendedConfigConsumerProps>(ExtendedConfigContext);
   return (
     <AntConfigProvider
-      spin={spin}
-      theme={{
-        ...theme,
-        // Only set seed token for dark theme
-        // Because defaultThemeToken is designed for light theme
-        token: theme?.isDark
-          ? {
-            ...defaultSeed,
-            ...theme?.token,
-          }
-          : {
-            ...defaultSeed,
-            ...defaultThemeToken,
-            ...theme?.token,
-          },
-        components: {
-          ...components,
-          ...theme?.components,
-          InputNumber: {
-            ...components?.InputNumber,
-            ...theme?.components?.InputNumber,
+      spin={merge(parentContext.spin, spin)}
+      theme={merge(
+        {
+          // Only set seed token for dark theme
+          // Because defaultThemeToken is designed for light theme
+          token: theme?.isDark
+            ? {
+                ...defaultSeed,
+              }
+            : {
+                ...defaultSeed,
+                ...defaultThemeToken,
+              },
+          components: {
+            ...components,
+            InputNumber: {
+              ...components?.InputNumber,
+            },
           },
         },
-      }}
+        parentContext.theme,
+        theme
+      )}
       {...restProps}
     >
       <ExtendedConfigContext.Provider
         value={{
-          navigate: navigate === undefined ? parentContext.navigate : navigate,
+          navigate: navigate === undefined ? parentExtendedContext.navigate : navigate,
         }}
       >
+        {/* Nested App component for static function of message, notification and Modal to consume ConfigProvider config */}
+        {/* ref: https://ant.design/components/app */}
         <App>
           {children}
           <StaticFunction />
@@ -96,7 +98,7 @@ const ConfigProvider = ({ children, theme, navigate, spin, ...restProps }: Confi
 ConfigProvider.ConfigContext =
   AntConfigProvider.ConfigContext as React.Context<ConfigConsumerProps>;
 ConfigProvider.ExtendedConfigContext = ExtendedConfigContext;
-// “SizeContext”已弃用。ts(6385)
+// SizeContext is deprecated
 // ConfigProvider.SizeContext = AntConfigProvider.SizeContext;
 ConfigProvider.config = AntConfigProvider.config;
 ConfigProvider.useConfig = AntConfigProvider.useConfig;
diff --git a/packages/design/src/config-provider/navigate.ts b/packages/design/src/config-provider/navigate.ts
index 113b32035..7a36d41a8 100644
--- a/packages/design/src/config-provider/navigate.ts
+++ b/packages/design/src/config-provider/navigate.ts
@@ -20,7 +20,7 @@ export interface Path {
   hash: string;
 }
 
-export type To = string | Partial<Path>;
+export type To = string | Partial<Path> | any;
 
 export type RelativeRoutingType = 'route' | 'path';
 
@@ -33,5 +33,5 @@ export interface NavigateOptions {
 
 export interface NavigateFunction {
   (to: To, options?: NavigateOptions): void;
-  (delta: number): void;
+  (delta: number | any): void;
 }