diff --git a/components/affix/index.tsx b/components/affix/index.tsx index 8f4b37710..95155dd39 100644 --- a/components/affix/index.tsx +++ b/components/affix/index.tsx @@ -27,10 +27,11 @@ import useStyle from './style'; function getDefaultTarget() { return typeof window !== 'undefined' ? window : null; } -enum AffixStatus { - None, - Prepare, -} +const AFFIX_STATUS_NONE = 0; +const AFFIX_STATUS_PREPARE = 1; + +type AffixStatus = typeof AFFIX_STATUS_NONE | typeof AFFIX_STATUS_PREPARE; + export interface AffixState { affixStyle?: CSSProperties; placeholderStyle?: CSSProperties; @@ -82,7 +83,7 @@ const Affix = defineComponent({ const state = reactive({ affixStyle: undefined, placeholderStyle: undefined, - status: AffixStatus.None, + status: AFFIX_STATUS_NONE, lastAffix: false, prevTarget: null, timeout: null, @@ -98,7 +99,12 @@ const Affix = defineComponent({ const measure = () => { const { status, lastAffix } = state; const { target } = props; - if (status !== AffixStatus.Prepare || !fixedNode.value || !placeholderNode.value || !target) { + if ( + status !== AFFIX_STATUS_PREPARE || + !fixedNode.value || + !placeholderNode.value || + !target + ) { return; } @@ -108,7 +114,7 @@ const Affix = defineComponent({ } const newState = { - status: AffixStatus.None, + status: AFFIX_STATUS_NONE, } as AffixState; const placeholderRect = getTargetRect(placeholderNode.value as HTMLElement); @@ -172,7 +178,7 @@ const Affix = defineComponent({ }; const prepareMeasure = () => { Object.assign(state, { - status: AffixStatus.Prepare, + status: AFFIX_STATUS_PREPARE, affixStyle: undefined, placeholderStyle: undefined, }); @@ -253,12 +259,13 @@ const Affix = defineComponent({ }); const { prefixCls } = useConfigInject('affix', props); - const [wrapSSR, hashId] = useStyle(prefixCls); + const [wrapSSR, hashId, cssVarCls] = useStyle(prefixCls); return () => { const { affixStyle, placeholderStyle, status } = state; const className = classNames({ [prefixCls.value]: affixStyle, [hashId.value]: true, + [cssVarCls.value]: true, }); const restProps = omit(props, [ 'prefixCls', diff --git a/components/affix/style/index.ts b/components/affix/style/index.ts index f97731ae5..be895766d 100644 --- a/components/affix/style/index.ts +++ b/components/affix/style/index.ts @@ -1,17 +1,21 @@ import type { CSSObject } from '../../_util/cssinjs'; -import type { FullToken, GenerateStyle } from '../../theme/internal'; -import { genComponentStyleHook, mergeToken } from '../../theme/internal'; +import { FullToken, GenerateStyle, genStyleHooks, GetDefaultToken } from '../../theme/internal'; -export interface ComponentToken {} +export interface ComponentToken { + /** + * @desc 弹出层的 z-index + * @descEN z-index of popup + */ + zIndexPopup: number; +} interface AffixToken extends FullToken<'Affix'> { - zIndexPopup: number; + // } // ============================== Shared ============================== const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => { const { componentCls } = token; - return { [componentCls]: { position: 'fixed', @@ -20,10 +24,9 @@ const genSharedAffixStyle: GenerateStyle<AffixToken> = (token): CSSObject => { }; }; -// ============================== Export ============================== -export default genComponentStyleHook('Affix', token => { - const affixToken = mergeToken<AffixToken>(token, { - zIndexPopup: token.zIndexBase + 10, - }); - return [genSharedAffixStyle(affixToken)]; +export const prepareComponentToken: GetDefaultToken<'Affix'> = token => ({ + zIndexPopup: token.zIndexBase + 10, }); + +// ============================== Export ============================== +export default genStyleHooks('Affix', genSharedAffixStyle, prepareComponentToken); diff --git a/components/affix/utils.ts b/components/affix/utils.ts index 62ce50f27..08b46ea1e 100644 --- a/components/affix/utils.ts +++ b/components/affix/utils.ts @@ -9,8 +9,11 @@ export function getTargetRect(target: BindElement): DOMRect { : ({ top: 0, bottom: window.innerHeight } as DOMRect); } -export function getFixedTop(placeholderRect: DOMRect, targetRect: DOMRect, offsetTop: number) { - if (offsetTop !== undefined && targetRect.top > placeholderRect.top - offsetTop) { +export function getFixedTop(placeholderRect: DOMRect, targetRect: DOMRect, offsetTop?: number) { + if ( + offsetTop !== undefined && + Math.round(targetRect.top) > Math.round(placeholderRect.top) - offsetTop + ) { return `${offsetTop + targetRect.top}px`; } return undefined; @@ -19,9 +22,12 @@ export function getFixedTop(placeholderRect: DOMRect, targetRect: DOMRect, offse export function getFixedBottom( placeholderRect: DOMRect, targetRect: DOMRect, - offsetBottom: number, + offsetBottom?: number, ) { - if (offsetBottom !== undefined && targetRect.bottom < placeholderRect.bottom + offsetBottom) { + if ( + offsetBottom !== undefined && + Math.round(targetRect.bottom) < Math.round(placeholderRect.bottom) + offsetBottom + ) { const targetBottomOffset = window.innerHeight - targetRect.bottom; return `${offsetBottom + targetBottomOffset}px`; } @@ -29,7 +35,7 @@ export function getFixedBottom( } // ======================== Observer ======================== -const TRIGGER_EVENTS = [ +const TRIGGER_EVENTS: (keyof WindowEventMap)[] = [ 'resize', 'scroll', 'touchstart',