Browse Source

style: affix & util

feat-css-var
tangjinzhou 3 years ago
parent
commit
60e2597f7f
  1. 8
      components/_util/__tests__/unreachableException.test.js
  2. 23
      components/_util/styleChecker.ts
  3. 7
      components/_util/unreachableException.ts
  4. 6
      components/_util/wave.tsx
  5. 14
      components/affix/index.en-US.md
  6. 5
      components/affix/index.tsx
  7. 16
      components/affix/index.zh-CN.md
  8. 17
      components/affix/utils.ts

8
components/_util/__tests__/unreachableException.test.js

@ -0,0 +1,8 @@
import UnreachableException from '../unreachableException';
describe('UnreachableException', () => {
it('error thrown matches snapshot', () => {
const exception = new UnreachableException('some value');
expect(exception.error.message).toMatchInlineSnapshot(`"unreachable case: \\"some value\\""`);
});
});

23
components/_util/styleChecker.ts

@ -2,8 +2,8 @@ import canUseDom from './canUseDom';
export const canUseDocElement = () => canUseDom() && window.document.documentElement;
export const isStyleSupport = (styleName: string | Array<string>): boolean => {
if (canUseDocElement()) {
const isStyleNameSupport = (styleName: string | string[]): boolean => {
if (canUseDom() && window.document.documentElement) {
const styleNameList = Array.isArray(styleName) ? styleName : [styleName];
const { documentElement } = window.document;
@ -12,6 +12,25 @@ export const isStyleSupport = (styleName: string | Array<string>): boolean => {
return false;
};
const isStyleValueSupport = (styleName: string, value: any) => {
if (!isStyleNameSupport(styleName)) {
return false;
}
const ele = document.createElement('div');
const origin = ele.style[styleName];
ele.style[styleName] = value;
return ele.style[styleName] !== origin;
};
export function isStyleSupport(styleName: string | string[], styleValue?: any) {
if (!Array.isArray(styleName) && styleValue !== undefined) {
return isStyleValueSupport(styleName, styleValue);
}
return isStyleNameSupport(styleName);
}
let flexGapSupported: boolean | undefined;
export const detectFlexGapSupported = () => {
if (!canUseDocElement()) {

7
components/_util/unreachableException.ts

@ -0,0 +1,7 @@
export default class UnreachableException {
error: Error;
constructor(value: never) {
this.error = new Error(`unreachable case: ${JSON.stringify(value)}`);
}
}

6
components/_util/wave.tsx

@ -24,6 +24,7 @@ export default defineComponent({
name: 'Wave',
props: {
insertExtraNode: Boolean,
disabled: Boolean,
},
setup(props, { slots, expose }) {
const instance = getCurrentInstance();
@ -60,10 +61,11 @@ export default defineComponent({
return insertExtraNode ? 'ant-click-animating' : 'ant-click-animating-without-extra-node';
};
const onClick = (node: HTMLElement, waveColor: string) => {
if (!node || isHidden(node) || node.className.indexOf('-leave') >= 0) {
const { insertExtraNode, disabled } = props;
if (disabled || !node || isHidden(node) || node.className.indexOf('-leave') >= 0) {
return;
}
const { insertExtraNode } = props;
extraNode = document.createElement('div');
extraNode.className = 'ant-click-animating-node';
const attributeName = getAttributeName();

14
components/affix/index.en-US.md

@ -23,9 +23,9 @@ Please note that Affix should not cover other content on the page, especially wh
### events
| Events Name | Description | Arguments | Version |
| ----------- | ---------------------------------------- | ----------------- | ------- |
| change | Callback for when Affix state is changed | Function(affixed) |
| Events Name | Description | Arguments | Version |
| ----------- | ---------------------------------------- | --------------------------- | ------- |
| change | Callback for when Affix state is changed | (affixed?: boolean) => void | |
**Note:** Children of `Affix` must not have the property `position: absolute`, but you can set `position: absolute` on `Affix` itself:
@ -35,8 +35,12 @@ Please note that Affix should not cover other content on the page, especially wh
## FAQ
### Affix bind container with `target`, sometime move out of container.
### When binding container with `target` in Affix, elements sometimes move out of the container.
We don't listen window scroll for performance consideration.
We only listen to container scroll events for performance consideration. You can add custom listeners if you still want to, like react demo <https://codesandbox.io/s/2xyj5zr85p>
Related issues:[#3938](https://github.com/ant-design/ant-design/issues/3938) [#5642](https://github.com/ant-design/ant-design/issues/5642) [#16120](https://github.com/ant-design/ant-design/issues/16120)
### When Affix is used in a horizontal scroll container, the position of the element `left` is incorrect.
Affix is generally only applicable to areas with one-way scrolling, and only supports usage in vertical scrolling containers. If you want to use it in a horizontal container, you can consider implementing with the native `position: sticky` property.

5
components/affix/index.tsx

@ -179,10 +179,7 @@ const Affix = defineComponent({
watch(
() => props.target,
val => {
let newTarget = null;
if (val) {
newTarget = val() || null;
}
const newTarget = val?.() || null;
if (state.prevTarget !== newTarget) {
removeObserveTarget(currentInstance);
if (newTarget) {

16
components/affix/index.zh-CN.md

@ -19,14 +19,14 @@ cover: https://gw.alipayobjects.com/zos/alicdn/tX6-md4H6/Affix.svg
| 成员 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| offsetBottom | 距离窗口底部达到指定偏移量后触发 | number | | |
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | | |
| offsetTop | 距离窗口顶部达到指定偏移量后触发 | number | 0 | |
| target | 设置 `Affix` 需要监听其滚动事件的元素,值为一个返回对应 DOM 元素的函数 | () => HTMLElement | () => window | |
### 事件
| 事件名称 | 说明 | 回调参数 | 版本 |
| -------- | ---------------------------- | ----------------- | ---- | --- |
| change | 固定状态改变时触发的回调函数 | Function(affixed) | 无 | |
| 事件名称 | 说明 | 回调参数 | 版本 |
| -------- | ---------------------------- | --------------------------- | ---- | --- |
| change | 固定状态改变时触发的回调函数 | (affixed?: boolean) => void | - | |
**注意:**`Affix` 内的元素不要使用绝对定位,如需要绝对定位的效果,可以直接设置 `Affix` 为绝对定位:
@ -38,6 +38,12 @@ cover: https://gw.alipayobjects.com/zos/alicdn/tX6-md4H6/Affix.svg
### Affix 使用 `target` 绑定容器时,元素会跑到容器外。
从性能角度考虑,我们只监听容器滚动事件。
从性能角度考虑,我们只监听容器滚动事件。如果希望任意滚动,你可以在窗体添加滚动监听, 参考 react 版本示例 <https://codesandbox.io/s/2xyj5zr85p>
相关 issue:[#3938](https://github.com/ant-design/ant-design/issues/3938) [#5642](https://github.com/ant-design/ant-design/issues/5642) [#16120](https://github.com/ant-design/ant-design/issues/16120)
### Affix 在水平滚动容器中使用时, 元素 `left` 位置不正确。
Affix 一般只适用于单向滚动的区域,只支持在垂直滚动容器中使用。如果希望在水平容器中使用,你可以考虑使用 原生 `position: sticky` 实现。
相关 issue: [#29108](https://github.com/ant-design/ant-design/issues/29108)

17
components/affix/utils.ts

@ -3,19 +3,14 @@ import type { ComponentPublicInstance } from 'vue';
import supportsPassive from '../_util/supportsPassive';
export type BindElement = HTMLElement | Window | null | undefined;
export type Rect = ClientRect | DOMRect;
export function getTargetRect(target: BindElement): ClientRect {
export function getTargetRect(target: BindElement): DOMRect {
return target !== window
? (target as HTMLElement).getBoundingClientRect()
: ({ top: 0, bottom: window.innerHeight } as ClientRect);
: ({ top: 0, bottom: window.innerHeight } as DOMRect);
}
export function getFixedTop(
placeholderReact: Rect,
targetRect: Rect,
offsetTop: number | undefined,
) {
export function getFixedTop(placeholderReact: DOMRect, targetRect: DOMRect, offsetTop: number) {
if (offsetTop !== undefined && targetRect.top > placeholderReact.top - offsetTop) {
return `${offsetTop + targetRect.top}px`;
}
@ -23,9 +18,9 @@ export function getFixedTop(
}
export function getFixedBottom(
placeholderReact: Rect,
targetRect: Rect,
offsetBottom: number | undefined,
placeholderReact: DOMRect,
targetRect: DOMRect,
offsetBottom: number,
) {
if (offsetBottom !== undefined && targetRect.bottom < placeholderReact.bottom + offsetBottom) {
const targetBottomOffset = window.innerHeight - targetRect.bottom;

Loading…
Cancel
Save