Skip to content

Commit

Permalink
refactor: use breakpoint by Copilot AI (ant-design#52870)
Browse files Browse the repository at this point in the history
* refactor: use breakpoint

* refactor: add hooks

* chore: clean up

* chore: fix logic

* chore: fix logic

* chore: fix ts

* chore: fix ts
  • Loading branch information
zombieJ authored Feb 18, 2025
1 parent a8f116f commit dd20460
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 69 deletions.
10 changes: 8 additions & 2 deletions components/grid/hooks/useBreakpoint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ import useForceUpdate from '../../_util/hooks/useForceUpdate';
import type { ScreenMap } from '../../_util/responsiveObserver';
import useResponsiveObserver from '../../_util/responsiveObserver';

function useBreakpoint(refreshOnChange = true): ScreenMap {
const screensRef = useRef<ScreenMap>({});
function useBreakpoint(refreshOnChange: boolean, defaultScreens: null): ScreenMap | null;
function useBreakpoint(refreshOnChange?: boolean, defaultScreens?: ScreenMap): ScreenMap;

function useBreakpoint(
refreshOnChange = true,
defaultScreens: ScreenMap | null = {} as ScreenMap,
): ScreenMap | null {
const screensRef = useRef<ScreenMap | null>(defaultScreens);
const forceUpdate = useForceUpdate();
const responsiveObserver = useResponsiveObserver();

Expand Down
38 changes: 38 additions & 0 deletions components/grid/hooks/useGutter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { Breakpoint, ScreenMap } from '../../_util/responsiveObserver';
import { responsiveArray } from '../../_util/responsiveObserver';
import type { RowProps } from '../row';

type Gap = number | undefined;

export default function useGutter(
gutter: RowProps['gutter'],
screens: ScreenMap | null,
): [Gap, Gap] {
const results: [number | undefined, number | undefined] = [undefined, undefined];
const normalizedGutter = Array.isArray(gutter) ? gutter : [gutter, undefined];

// By default use as `xs`
const mergedScreens = screens || {
xs: true,
sm: true,
md: true,
lg: true,
xl: true,
xxl: true,
};

normalizedGutter.forEach((g, index) => {
if (typeof g === 'object' && g !== null) {
for (let i = 0; i < responsiveArray.length; i++) {
const breakpoint: Breakpoint = responsiveArray[i];
if (mergedScreens[breakpoint] && g[breakpoint] !== undefined) {
results[index] = g[breakpoint] as number;
break;
}
}
} else {
results[index] = g;
}
});
return results;
}
77 changes: 10 additions & 67 deletions components/grid/row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import * as React from 'react';
import classNames from 'classnames';

import type { Breakpoint, ScreenMap } from '../_util/responsiveObserver';
import useResponsiveObserver, { responsiveArray } from '../_util/responsiveObserver';
import { responsiveArray } from '../_util/responsiveObserver';
import { ConfigContext } from '../config-provider';
import useBreakpoint from './hooks/useBreakpoint';
import useGutter from './hooks/useGutter';
import RowContext from './RowContext';
import type { RowContextState } from './RowContext';
import { useRowStyle } from './style';
Expand All @@ -23,7 +25,6 @@ type ResponsiveLike<T> = {
[key in Responsive]?: T;
};

type Gap = number | undefined;
export type Gutter = number | undefined | Partial<Record<Breakpoint, number>>;

type ResponsiveAligns = ResponsiveLike<(typeof _RowAligns)[number]>;
Expand All @@ -38,7 +39,7 @@ export interface RowProps extends React.HTMLAttributes<HTMLDivElement> {

function useMergedPropByScreen(
oriProp: RowProps['align'] | RowProps['justify'],
screen: ScreenMap,
screen: ScreenMap | null,
) {
const [prop, setProp] = React.useState(typeof oriProp === 'string' ? oriProp : '');

Expand All @@ -52,7 +53,7 @@ function useMergedPropByScreen(
for (let i = 0; i < responsiveArray.length; i++) {
const breakpoint: Breakpoint = responsiveArray[i];
// if do not match, do nothing
if (!screen[breakpoint]) {
if (!screen || !screen[breakpoint]) {
continue;
}
const curVal = oriProp[breakpoint];
Expand Down Expand Up @@ -85,74 +86,16 @@ const Row = React.forwardRef<HTMLDivElement, RowProps>((props, ref) => {

const { getPrefixCls, direction } = React.useContext(ConfigContext);

const [screens, setScreens] = React.useState<ScreenMap>({
xs: true,
sm: true,
md: true,
lg: true,
xl: true,
xxl: true,
});
// to save screens info when responsiveObserve callback had been call
const [curScreens, setCurScreens] = React.useState<ScreenMap>({
xs: false,
sm: false,
md: false,
lg: false,
xl: false,
xxl: false,
});

// ================================== calc responsive data ==================================
const mergedAlign = useMergedPropByScreen(align, curScreens);

const mergedJustify = useMergedPropByScreen(justify, curScreens);

const gutterRef = React.useRef<Gutter | [Gutter, Gutter]>(gutter);

const responsiveObserver = useResponsiveObserver();

// ================================== Effect ==================================
React.useEffect(() => {
const token = responsiveObserver.subscribe((screen) => {
setCurScreens(screen);
const currentGutter = gutterRef.current || 0;
if (
(!Array.isArray(currentGutter) && typeof currentGutter === 'object') ||
(Array.isArray(currentGutter) &&
(typeof currentGutter[0] === 'object' || typeof currentGutter[1] === 'object'))
) {
setScreens(screen);
}
});
return () => responsiveObserver.unsubscribe(token);
}, []);

// ================================== Render ==================================
const getGutter = (): [Gap, Gap] => {
const results: [Gap, Gap] = [undefined, undefined];
const normalizedGutter = Array.isArray(gutter) ? gutter : [gutter, undefined];
normalizedGutter.forEach((g, index) => {
if (typeof g === 'object') {
for (let i = 0; i < responsiveArray.length; i++) {
const breakpoint: Breakpoint = responsiveArray[i];
if (screens[breakpoint] && g[breakpoint] !== undefined) {
results[index] = g[breakpoint] as number;
break;
}
}
} else {
results[index] = g;
}
});
return results;
};
const screens = useBreakpoint(true, null);

const mergedAlign = useMergedPropByScreen(align, screens);
const mergedJustify = useMergedPropByScreen(justify, screens);

const prefixCls = getPrefixCls('row', customizePrefixCls);

const [wrapCSSVar, hashId, cssVarCls] = useRowStyle(prefixCls);

const gutters = getGutter();
const gutters = useGutter(gutter, screens);
const classes = classNames(
prefixCls,
{
Expand Down

0 comments on commit dd20460

Please sign in to comment.