Browse Source

chore: init wrapper

happy
二货机器人 2 years ago
parent
commit
7e4139815e
  1. 15
      .dumi/theme/layouts/GlobalLayout.tsx
  2. 21
      components/_util/wave/WaveEffect.tsx
  3. 6
      components/_util/wave/index.ts
  4. 7
      components/_util/wave/style.ts
  5. 11
      components/_util/wave/useWave.ts
  6. 2
      components/button/demo/basic.tsx
  7. 27
      components/config-provider/context.ts
  8. 5
      components/config-provider/index.tsx
  9. 2
      components/theme/index.ts
  10. 6
      components/theme/internal.ts
  11. 11
      components/theme/themesToken/happy/index.tsx
  12. 32
      components/theme/themesToken/happy/style/wave.ts
  13. 53
      components/theme/themesToken/happy/wave.tsx

15
.dumi/theme/layouts/GlobalLayout.tsx

@ -36,14 +36,6 @@ const getAlgorithm = (themes: ThemeName[] = []) =>
})
.filter((algorithm) => algorithm);
const getComponents = (themes: ThemeName[] = []): OverrideToken => {
if (themes.includes('happy')) {
return antdTheme.happyThemeToken;
}
return null;
};
const GlobalLayout: React.FC = () => {
const outlet = useOutlet();
const { pathname } = useLocation();
@ -115,14 +107,19 @@ const GlobalLayout: React.FC = () => {
[isMobile, direction, updateSiteConfig, theme],
);
// Happy Work Theme
const components = theme.includes('happy') ? antdTheme.happyThemeToken.token : null;
const wave = theme.includes('happy') ? antdTheme.happyThemeToken.wave : null;
return (
<StyleProvider cache={styleCache} linters={[logicalPropertiesLinter]}>
<SiteContext.Provider value={siteContextValue}>
<ConfigProvider
theme={{
algorithm: getAlgorithm(theme),
components: getComponents(theme),
components,
}}
wave={wave}
>
{outlet}
{!pathname.startsWith('/~demos') && (

21
components/_util/wave/WaveEffect.tsx

@ -4,7 +4,8 @@ import raf from 'rc-util/lib/raf';
import { render, unmount } from 'rc-util/lib/React/render';
import classNames from 'classnames';
import { getTargetWaveColor } from './util';
import type { GlobalToken } from '../../theme/interface';
import type { ConfigProviderProps } from '../../config-provider';
import type { useToken } from '../../theme/internal';
function validateNum(value: number) {
return Number.isNaN(value) ? 0 : value;
@ -123,20 +124,26 @@ const WaveEffect: React.FC<WaveEffectProps> = (props) => {
export interface WaveWrapperProps {
className: string;
target: HTMLElement;
token: GlobalToken;
token: ReturnType<typeof useToken>;
wave: ConfigProviderProps['wave'];
}
function WaveWrapper(props: WaveWrapperProps) {
const { token, target } = props;
const { token, target, wave } = props;
if (token?.Wave?.render) {
return token?.Wave?.render(target, token);
if (wave?.render) {
return wave?.render(target, token) as React.ReactElement;
}
return <WaveEffect {...props} />;
}
export default function showWaveEffect(node: HTMLElement, className: string, token: GlobalToken) {
export default function showWaveEffect(
node: HTMLElement,
className: string,
token: ReturnType<typeof useToken>,
wave: ConfigProviderProps['wave'],
) {
// Create holder
const holder = document.createElement('div');
holder.style.position = 'absolute';
@ -144,5 +151,5 @@ export default function showWaveEffect(node: HTMLElement, className: string, tok
holder.style.top = `0px`;
node.parentElement?.appendChild(holder);
render(<WaveWrapper target={node} className={className} token={token} />, holder);
render(<WaveWrapper target={node} className={className} token={token} wave={wave} />, holder);
}

6
components/_util/wave/index.ts

@ -16,16 +16,16 @@ export interface WaveProps {
const Wave: React.FC<WaveProps> = (props) => {
const { children, disabled } = props;
const { getPrefixCls } = useContext<ConfigConsumerProps>(ConfigContext);
const { getPrefixCls, wave } = useContext<ConfigConsumerProps>(ConfigContext);
const containerRef = useRef<HTMLElement>(null);
// ============================== Style ===============================
const prefixCls = getPrefixCls('wave');
const [, hashId] = useStyle(prefixCls);
const [, token] = useToken();
const token = useToken();
// =============================== Wave ===============================
const showWave = useWave(containerRef, classNames(prefixCls, hashId), token);
const showWave = useWave(containerRef, classNames(prefixCls, hashId), token, wave);
// ============================== Effect ==============================
React.useEffect(() => {

7
components/_util/wave/style.ts

@ -1,10 +1,7 @@
import { genComponentStyleHook } from '../../theme/internal';
import type { AliasToken, FullToken, GenerateStyle } from '../../theme/internal';
import type { FullToken, GenerateStyle } from '../../theme/internal';
export interface ComponentToken {
/** @deprecated Dev only. Do not use. */
render?: (target: HTMLElement, token: AliasToken) => React.ReactElement;
}
export interface ComponentToken {}
export interface WaveToken extends FullToken<'Wave'> {}

11
components/_util/wave/useWave.ts

@ -1,16 +1,19 @@
import type { ComponentToken } from './style';
import useEvent from 'rc-util/lib/hooks/useEvent';
import type { ConfigProviderProps } from '../../config-provider';
import showWaveEffect from './WaveEffect';
import type { useToken } from '../../theme/internal';
export default function useWave(
nodeRef: React.RefObject<HTMLElement>,
className: string,
waveToken?: ComponentToken,
token: ReturnType<typeof useToken>,
wave: ConfigProviderProps['wave'],
): VoidFunction {
function showWave() {
const node = nodeRef.current!;
showWaveEffect(node, className, waveToken);
showWaveEffect(node, className, token, wave);
}
return showWave;
return useEvent(showWave);
}

2
components/button/demo/basic.tsx

@ -2,7 +2,7 @@ import React from 'react';
import { Button, Space } from 'antd';
const App: React.FC = () => (
<Space wrap>
<Space wrap style={{ margin: 32 }}>
<Button type="primary">Primary Button</Button>
<Button>Default Button</Button>
<Button type="dashed">Dashed Button</Button>

27
components/config-provider/context.ts

@ -6,6 +6,7 @@ import type { Locale } from '../locale';
import type { AliasToken, MapToken, OverrideToken, SeedToken } from '../theme/interface';
import type { RenderEmptyHandler } from './defaultRenderEmpty';
import type { SizeType } from './SizeContext';
import type { ConfigProviderProps } from '.';
export const defaultIconPrefixCls = 'anticon';
@ -34,7 +35,11 @@ export interface ThemeConfig {
inherit?: boolean;
}
export interface ConfigConsumerProps {
export interface ConfigConsumerProps
extends Pick<
ConfigProviderProps,
'input' | 'pagination' | 'space' | 'form' | 'select' | 'pageHeader' | 'wave'
> {
getTargetContainer?: () => HTMLElement;
getPopupContainer?: (triggerNode?: HTMLElement) => HTMLElement;
rootPrefixCls?: string;
@ -43,31 +48,11 @@ export interface ConfigConsumerProps {
renderEmpty?: RenderEmptyHandler;
csp?: CSPConfig;
autoInsertSpaceInButton?: boolean;
input?: {
autoComplete?: string;
};
pagination?: {
showSizeChanger?: boolean;
};
locale?: Locale;
pageHeader?: {
ghost: boolean;
};
direction?: DirectionType;
space?: {
size?: SizeType | number;
};
virtual?: boolean;
dropdownMatchSelectWidth?: boolean;
form?: {
requiredMark?: RequiredMark;
colon?: boolean;
scrollToFirstError?: Options | boolean;
};
theme?: ThemeConfig;
select?: {
showSearch?: boolean;
};
}
const defaultGetPrefixCls = (suffixCls?: string, customizePrefixCls?: string) => {

5
components/config-provider/index.tsx

@ -12,6 +12,7 @@ import LocaleProvider, { ANT_MARK } from '../locale';
import LocaleReceiver from '../locale/LocaleReceiver';
import defaultLocale from '../locale/en_US';
import { DesignTokenContext } from '../theme/internal';
import type { useToken } from '../theme/internal';
import defaultSeedToken from '../theme/themes/seed';
import type { ConfigConsumerProps, CSPConfig, DirectionType, Theme, ThemeConfig } from './context';
import { ConfigConsumer, ConfigContext, defaultIconPrefixCls } from './context';
@ -55,6 +56,7 @@ const PASSED_PROPS: Exclude<keyof ConfigConsumerProps, 'rootPrefixCls' | 'getPre
'pagination',
'form',
'select',
'wave',
];
export interface ConfigProviderProps {
@ -81,6 +83,9 @@ export interface ConfigProviderProps {
pagination?: {
showSizeChanger?: boolean;
};
wave?: {
render?: (target: HTMLElement, token: ReturnType<typeof useToken>) => React.ReactNode;
};
locale?: Locale;
pageHeader?: {
ghost: boolean;

2
components/theme/index.ts

@ -26,5 +26,7 @@ export default {
defaultAlgorithm,
darkAlgorithm,
compactAlgorithm,
// TODO: Remove this after to be third part package
happyThemeToken,
};

6
components/theme/internal.ts

@ -57,7 +57,11 @@ export const DesignTokenContext = React.createContext<{
}>(defaultConfig);
// ================================== Hook ==================================
export function useToken(): [Theme<SeedToken, MapToken>, GlobalToken, string] {
export function useToken(): [
theme: Theme<SeedToken, MapToken>,
globalToken: GlobalToken,
hashId: string,
] {
const {
token: rootDesignToken,
hashed,

11
components/theme/themesToken/happy/index.tsx

@ -1,8 +1,9 @@
import type { OverrideToken } from '../../interface';
import Wave from './wave';
import wave from './wave';
const token: OverrideToken = {
Wave,
};
const token: OverrideToken = {};
export default token;
export default {
token,
wave,
};

32
components/theme/themesToken/happy/style/wave.ts

@ -0,0 +1,32 @@
import { useStyleRegister } from '@ant-design/cssinjs';
import type { UseTokenType } from '../wave';
export default function useStyle(tokenConfig: UseTokenType) {
const [theme, token, hashId] = tokenConfig;
useStyleRegister({ theme, token, hashId, path: ['Customize', 'Wave', 'Effect'] }, () => {
const prefixCls = '.happy-wave';
return [
{
[prefixCls]: {
position: 'fixed',
left: 0,
top: 0,
width: 20,
height: 20,
background: 'green',
[`${prefixCls}-dot`]: {
position: 'absolute',
left: 0,
top: 0,
width: 10,
height: 10,
background: 'red',
},
},
},
];
});
}

53
components/theme/themesToken/happy/wave.tsx

@ -1,23 +1,58 @@
import classNames from 'classnames';
import CSSMotion from 'rc-motion';
import * as React from 'react';
import type { GlobalToken, OverrideToken } from '../../interface';
import type { ComponentToken } from '../../../_util/wave/style';
import type { ConfigProviderProps } from '../../../config-provider';
import useWaveStyle from './style/wave';
export type WaveRender = Required<Required<ConfigProviderProps>['wave']>['render'];
export type UseTokenType = Parameters<WaveRender>[1];
interface HappyWaveProps {
target: HTMLElement;
token: GlobalToken;
token: UseTokenType;
}
function HappyWave({ target, token }: HappyWaveProps) {
React.useEffect(() => {}, []);
const prefixCls = 'happy-wave';
const dotPrefixCls = `${prefixCls}-dot`;
const [left, setLeft] = React.useState(0);
const [top, setTop] = React.useState(0);
const [, , hashId] = token;
useWaveStyle(token);
React.useEffect(() => {
const rect = target.getBoundingClientRect();
setLeft(rect.left + rect.width / 2);
setTop(rect.top + rect.height / 2);
}, []);
return (
<div
className={classNames(prefixCls, hashId)}
style={{
left,
top,
}}
>
{new Array(7).fill(null).map((_, index) => {
const name = `${dotPrefixCls}-${index}`;
return <div style={{ position: 'fixed' }}>2333</div>;
return (
<CSSMotion key={name}>
{() => <div className={classNames(dotPrefixCls, name)} />}
</CSSMotion>
);
})}
</div>
);
}
const renderWave: ComponentToken['render'] = (target, token) => (
<HappyWave target={target} token={token} />
);
const renderWave: WaveRender = (target, token) => <HappyWave target={target} token={token} />;
const Wave: OverrideToken['Wave'] = {
const Wave: ConfigProviderProps['wave'] = {
render: renderWave,
};

Loading…
Cancel
Save