Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d6ec6bf

Browse files
feat: anchor support cssvar
1 parent 3375bd4 commit d6ec6bf

File tree

6 files changed

+99
-59
lines changed

6 files changed

+99
-59
lines changed

‎components/_util/getScroll.ts‎

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,31 @@ export function isWindow(obj: any): obj is Window {
22
return obj !== null && obj !== undefined && obj === obj.window;
33
}
44

5-
export default function getScroll(
6-
target: HTMLElement | Window | Document | null,
7-
top: boolean,
8-
): number {
5+
const getScroll = (target: HTMLElement | Window | Document | null): number => {
96
if (typeof window === 'undefined') {
107
return 0;
118
}
12-
const method = top ? 'scrollTop' : 'scrollLeft';
139
let result = 0;
1410
if (isWindow(target)) {
15-
result = target[top ? 'scrollY' : 'scrollX'];
11+
result = target.pageYOffset;
1612
} else if (target instanceof Document) {
17-
result = target.documentElement[method];
13+
result = target.documentElement.scrollTop;
1814
} else if (target instanceof HTMLElement) {
19-
result = target[method];
15+
result = target.scrollTop;
2016
} else if (target) {
2117
// According to the type inference, the `target` is `never` type.
2218
// Since we configured the loose mode type checking, and supports mocking the target with such shape below::
2319
// `{ documentElement: { scrollLeft: 200, scrollTop: 400 }}`,
2420
// the program may falls into this branch.
2521
// Check the corresponding tests for details. Don't sure what is the real scenario this happens.
26-
result = target[method];
22+
/* biome-ignore lint/complexity/useLiteralKeys: target is a never type */ /* eslint-disable-next-line dot-notation */
23+
result = target['scrollTop'];
2724
}
2825

2926
if (target && !isWindow(target) && typeof result !== 'number') {
30-
result = ((target.ownerDocument ?? target) as any).documentElement?.[method];
27+
result = (target.ownerDocument ?? (target as Document)).documentElement?.scrollTop;
3128
}
3229
return result;
33-
}
30+
};
31+
32+
export default getScroll;

‎components/_util/scrollTo.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ interface ScrollToOptions {
1414
export default function scrollTo(y: number, options: ScrollToOptions = {}) {
1515
const { getContainer = () => window, callback, duration = 450 } = options;
1616
const container = getContainer();
17-
const scrollTop = getScroll(container,true);
17+
const scrollTop = getScroll(container);
1818
const startTime = Date.now();
1919

2020
const frameFunc = () => {

‎components/anchor/Anchor.tsx‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import AnchorLink from './AnchorLink';
2323
import PropTypes from '../_util/vue-types';
2424
import devWarning from '../vc-util/devWarning';
2525
import { arrayType } from '../_util/type';
26+
import useCSSVarCls from '../config-provider/hooks/useCssVarCls';
2627

2728
export type AnchorDirection = 'vertical' | 'horizontal';
2829

@@ -39,8 +40,7 @@ function getOffsetTop(element: HTMLElement, container: AnchorContainer): number
3940

4041
if (rect.width || rect.height) {
4142
if (container === window) {
42-
container = element.ownerDocument!.documentElement!;
43-
return rect.top - container.clientTop;
43+
return rect.top - element.ownerDocument!.documentElement!.clientTop;
4444
}
4545
return rect.top - (container as HTMLElement).getBoundingClientRect().top;
4646
}
@@ -70,6 +70,7 @@ export const anchorProps = () => ({
7070
targetOffset: Number,
7171
items: arrayType<AnchorLinkItemProps[]>(),
7272
direction: PropTypes.oneOf(['vertical', 'horizontal'] as AnchorDirection[]).def('vertical'),
73+
replace: Boolean,
7374
onChange: Function as PropType<(currentActiveLink: string) => void>,
7475
onClick: Function as PropType<(e: MouseEvent, link: { title: any; href: string }) => void>,
7576
});
@@ -91,7 +92,7 @@ export default defineComponent({
9192
setup(props, { emit, attrs, slots, expose }) {
9293
const { prefixCls, getTargetContainer, direction } = useConfigInject('anchor', props);
9394
const anchorDirection = computed(() => props.direction ?? 'vertical');
94-
95+
constrootCls=useCSSVarCls(prefixCls);
9596
if (process.env.NODE_ENV !== 'production') {
9697
devWarning(
9798
props.items && typeof slots.default !== 'function',
@@ -133,7 +134,7 @@ export default defineComponent({
133134
const target = document.getElementById(sharpLinkMatch[1]);
134135
if (target) {
135136
const top = getOffsetTop(target, container);
136-
if (top < offsetTop + bounds) {
137+
if (top <= offsetTop + bounds) {
137138
linkSections.push({
138139
link,
139140
top,
@@ -170,7 +171,7 @@ export default defineComponent({
170171
}
171172

172173
const container = getContainer.value();
173-
const scrollTop = getScroll(container,true);
174+
const scrollTop = getScroll(container);
174175
const eleOffsetTop = getOffsetTop(targetElement, container);
175176
let y = scrollTop + eleOffsetTop;
176177
y -= targetOffset !== undefined ? targetOffset : offsetTop || 0;
@@ -277,14 +278,15 @@ export default defineComponent({
277278
title={title}
278279
customTitleProps={option}
279280
v-slots={{ customTitle: slots.customTitle }}
281+
replace={props.replace}
280282
>
281283
{anchorDirection.value === 'vertical' ? createNestedLink(children) : null}
282284
</AnchorLink>
283285
);
284286
})
285287
: null;
286288

287-
const [wrapSSR, hashId] = useStyle(prefixCls);
289+
const [wrapSSR, hashId,cssVarCls] = useStyle(prefixCls,rootCls);
288290

289291
return () => {
290292
const { offsetTop, affix, showInkInFixed } = props;
@@ -296,6 +298,8 @@ export default defineComponent({
296298
const wrapperClass = classNames(hashId.value, props.wrapperClass, `${pre}-wrapper`, {
297299
[`${pre}-wrapper-horizontal`]: anchorDirection.value === 'horizontal',
298300
[`${pre}-rtl`]: direction.value === 'rtl',
301+
[rootCls.value]: true,
302+
[cssVarCls.value]: true,
299303
});
300304

301305
const anchorClass = classNames(pre, {

‎components/anchor/AnchorLink.tsx‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const anchorLinkProps = () => ({
1313
href: String,
1414
title: anyType<VueNode | ((item: any) => VueNode)>(),
1515
target: String,
16+
replace: Boolean,
1617
/* private use */
1718
customTitleProps: objectType<AnchorLinkItemProps>(),
1819
});
@@ -53,6 +54,10 @@ export default defineComponent({
5354
const { href } = props;
5455
contextHandleClick(e, { title: mergedTitle, href });
5556
scrollTo(href);
57+
if (props.replace) {
58+
e.preventDefault();
59+
window.location.replace(href);
60+
}
5661
};
5762

5863
watch(

‎components/anchor/style/index.ts‎

Lines changed: 72 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,55 @@
1-
import type { CSSObject } from '../../_util/cssinjs';
2-
import type { FullToken, GenerateStyle } from '../../theme/internal';
3-
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
1+
import { unit } from '../../_util/cssinjs';
2+
import {
3+
FullToken,
4+
GenerateStyle,
5+
genStyleHooks,
6+
GetDefaultToken,
7+
mergeToken,
8+
} from '../../theme/internal';
49
import { resetComponent, textEllipsis } from '../../style';
510

6-
export interface ComponentToken {}
11+
export interface ComponentToken {
12+
/**
13+
* @desc 链接纵向内间距
14+
* @descEN Vertical padding of link
15+
*/
16+
linkPaddingBlock: number;
17+
/**
18+
* @desc 链接横向内间距
19+
* @descEN Horizontal padding of link
20+
*/
21+
linkPaddingInlineStart: number;
22+
}
723

24+
/**
25+
* @desc Anchor 组件的 Token
26+
* @descEN Token for Anchor component
27+
*/
828
interface AnchorToken extends FullToken<'Anchor'> {
29+
/**
30+
* @desc 容器块偏移量
31+
* @descEN Holder block offset
32+
*/
933
holderOffsetBlock: number;
10-
anchorPaddingBlock: number;
11-
anchorPaddingBlockSecondary: number;
12-
anchorPaddingInline: number;
13-
anchorBallSize: number;
14-
anchorTitleBlock: number;
34+
/**
35+
* @desc 次级锚点块内间距
36+
* @descEN Secondary anchor block padding
37+
*/
38+
anchorPaddingBlockSecondary: number | string;
39+
/**
40+
* @desc 锚点球大小
41+
* @descEN Anchor ball size
42+
*/
43+
anchorBallSize: number | string;
44+
/**
45+
* @desc 锚点标题块
46+
* @descEN Anchor title block
47+
*/
48+
anchorTitleBlock: number | string;
1549
}
1650

1751
// ============================== Shared ==============================
18-
const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
52+
const genSharedAnchorStyle: GenerateStyle<AnchorToken> = token => {
1953
const {
2054
componentCls,
2155
holderOffsetBlock,
@@ -24,26 +58,25 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
2458
colorPrimary,
2559
lineType,
2660
colorSplit,
61+
calc,
2762
} = token;
2863

2964
return {
3065
[`${componentCls}-wrapper`]: {
31-
marginBlockStart: -holderOffsetBlock,
66+
marginBlockStart: calc(holderOffsetBlock).mul(-1).equal(),
3267
paddingBlockStart: holderOffsetBlock,
3368

3469
// delete overflow: auto
3570
// overflow: 'auto',
3671

37-
backgroundColor: 'transparent',
38-
3972
[componentCls]: {
4073
...resetComponent(token),
4174
position: 'relative',
4275
paddingInlineStart: lineWidthBold,
4376

4477
[`${componentCls}-link`]: {
45-
paddingBlock: token.anchorPaddingBlock,
46-
paddingInline: `${token.anchorPaddingInline}px 0`,
78+
paddingBlock: token.linkPaddingBlock,
79+
paddingInline: `${unit(token.linkPaddingInlineStart)} 0`,
4780

4881
'&-title': {
4982
...textEllipsis,
@@ -73,28 +106,21 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
73106
[componentCls]: {
74107
'&::before': {
75108
position: 'absolute',
76-
left: {
77-
_skip_check_: true,
78-
value: 0,
79-
},
109+
insetInlineStart: 0,
80110
top: 0,
81111
height: '100%',
82-
borderInlineStart: `${lineWidthBold}px ${lineType} ${colorSplit}`,
112+
borderInlineStart: `${unit(lineWidthBold)} ${lineType} ${colorSplit}`,
83113
content: '" "',
84114
},
85115

86116
[`${componentCls}-ink`]: {
87117
position: 'absolute',
88-
left: {
89-
_skip_check_: true,
90-
value: 0,
91-
},
118+
insetInlineStart: 0,
92119
display: 'none',
93120
transform: 'translateY(-50%)',
94121
transition: `top ${motionDurationSlow} ease-in-out`,
95122
width: lineWidthBold,
96123
backgroundColor: colorPrimary,
97-
98124
[`&${componentCls}-ink-visible`]: {
99125
display: 'inline-block',
100126
},
@@ -109,7 +135,7 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
109135
};
110136
};
111137

112-
const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
138+
const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = token => {
113139
const { componentCls, motionDurationSlow, lineWidthBold, colorPrimary } = token;
114140

115141
return {
@@ -127,7 +153,7 @@ const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token): CSSO
127153
value: 0,
128154
},
129155
bottom: 0,
130-
borderBottom: `1px ${token.lineType} ${token.colorSplit}`,
156+
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
131157
content: '" "',
132158
},
133159

@@ -157,17 +183,23 @@ const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token): CSSO
157183
};
158184
};
159185

160-
// ============================== Export ==============================
161-
export default genComponentStyleHook('Anchor', token => {
162-
const { fontSize, fontSizeLG, padding, paddingXXS } = token;
163-
164-
const anchorToken = mergeToken<AnchorToken>(token, {
165-
holderOffsetBlock: paddingXXS,
166-
anchorPaddingBlock: paddingXXS,
167-
anchorPaddingBlockSecondary: paddingXXS / 2,
168-
anchorPaddingInline: padding,
169-
anchorTitleBlock: (fontSize / 14) * 3,
170-
anchorBallSize: fontSizeLG / 2,
171-
});
172-
return [genSharedAnchorStyle(anchorToken), genSharedAnchorHorizontalStyle(anchorToken)];
186+
export const prepareComponentToken: GetDefaultToken<'Anchor'> = token => ({
187+
linkPaddingBlock: token.paddingXXS,
188+
linkPaddingInlineStart: token.padding,
173189
});
190+
191+
// ============================== Export ==============================
192+
export default genStyleHooks(
193+
'Anchor',
194+
token => {
195+
const { fontSize, fontSizeLG, paddingXXS, calc } = token;
196+
const anchorToken = mergeToken<AnchorToken>(token, {
197+
holderOffsetBlock: paddingXXS,
198+
anchorPaddingBlockSecondary: calc(paddingXXS).div(2).equal(),
199+
anchorTitleBlock: calc(fontSize).div(14).mul(3).equal(),
200+
anchorBallSize: calc(fontSizeLG).div(2).equal(),
201+
});
202+
return [genSharedAnchorStyle(anchorToken), genSharedAnchorHorizontalStyle(anchorToken)];
203+
},
204+
prepareComponentToken,
205+
);

‎components/float-button/BackTop.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const BackTop = defineComponent({
6060

6161
const handleScroll = throttleByAnimationFrame((e: Event | { target: any }) => {
6262
const { visibilityHeight } = props;
63-
const scrollTop = getScroll(e.target,true);
63+
const scrollTop = getScroll(e.target);
6464
state.visible = scrollTop >= visibilityHeight;
6565
});
6666

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /