Skip to content

Commit

Permalink
feat(Toast): support attach props for ToastPlugin (#1555)
Browse files Browse the repository at this point in the history
* feat(Toast): support attach props for ToastPlugin

* test: update snapshots

* fix(DropdownMenu): resolved menuOpened and menuClosed events are invalid

* chore: update _common

* test: update snapshots

* chore(Toast): strip ToastPlugin from index file to plugin file

* fix: fix lint
  • Loading branch information
anlyyao authored Aug 29, 2024
1 parent 5033390 commit 84f2262
Show file tree
Hide file tree
Showing 39 changed files with 4,210 additions and 161 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"no-unused-expressions": "off",
"no-return-assign": "off",
"no-use-before-define": "off",
"no-bitwise": "off",
"func-names": "off",
"guard-for-in": "off",
"consistent-return": "off",
Expand Down
8 changes: 8 additions & 0 deletions src/_util/canUseDom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import isUndefined from 'lodash/isUndefined';

export const canUseDom = !!(
!isUndefined(window) &&
!isUndefined(document) &&
window.document &&
window.document.createElement
);
20 changes: 20 additions & 0 deletions src/_util/getScrollParent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
type ScrollElement = HTMLElement | Window;

const overflowScrollReg = /scroll|auto|overlay/i;

export default function getScrollParent(
el: Element | null | undefined,
root: ScrollElement | null | undefined = window,
): Window | Element | null | undefined {
let node = el;

while (node && node !== root && node.nodeType === 1) {
const { overflowY } = window.getComputedStyle(node);
if (overflowScrollReg.test(overflowY)) {
return node;
}
node = node.parentNode as Element;
}

return root;
}
19 changes: 19 additions & 0 deletions src/_util/supportsPassive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ref } from 'vue';
import { canUseDom } from './canUseDom';

export const supportsPassive = ref(false);

if (canUseDom) {
try {
const opts = {};
Object.defineProperty(opts, 'passive', {
get() {
supportsPassive.value = true;
return true; // 添加返回值
},
});
window.addEventListener('test-passive', null as any, opts);
} catch (e) {
//
}
}
72 changes: 72 additions & 0 deletions src/_util/useTouch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/* eslint-disable no-undef */

import { ref } from 'vue';

const MIN_DISTANCE = 10;

type Direction = '' | 'vertical' | 'horizontal';

function getDirection(x: number, y: number) {
if (x > y && x > MIN_DISTANCE) {
return 'horizontal';
}
if (y > x && y > MIN_DISTANCE) {
return 'vertical';
}
return '';
}

export function useTouch() {
const startX = ref(0);
const startY = ref(0);
const deltaX = ref(0);
const deltaY = ref(0);
const offsetX = ref(0);
const offsetY = ref(0);
const direction = ref<Direction>('');

const isVertical = () => direction.value === 'vertical';
const isHorizontal = () => direction.value === 'horizontal';

const reset = () => {
deltaX.value = 0;
deltaY.value = 0;
offsetX.value = 0;
offsetY.value = 0;
direction.value = '';
};

const start = ((event: TouchEvent) => {
reset();
startX.value = event.touches[0].clientX;
startY.value = event.touches[0].clientY;
}) as EventListener;

const move = ((event: TouchEvent) => {
const touch = event.touches[0];
// Fix: Safari back will set clientX to negative number
deltaX.value = touch.clientX < 0 ? 0 : touch.clientX - startX.value;
deltaY.value = touch.clientY - startY.value;
offsetX.value = Math.abs(deltaX.value);
offsetY.value = Math.abs(deltaY.value);

if (!direction.value) {
direction.value = getDirection(offsetX.value, offsetY.value);
}
}) as EventListener;

return {
move,
start,
reset,
startX,
startY,
deltaX,
deltaY,
offsetX,
offsetY,
direction,
isVertical,
isHorizontal,
};
}
2 changes: 1 addition & 1 deletion src/cascader/demos/lazy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

<script lang="ts" setup>
import { ref, computed } from 'vue';
import Toast from '../../toast/index';
import { Toast } from 'tdesign-mobile-vue';
const data = ref([
{
Expand Down
6 changes: 5 additions & 1 deletion src/dropdown-menu/dropdown-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ const name = `${prefix}-dropdown-menu`;
export default defineComponent({
name,
components: { CaretDownSmallIcon, CaretUpSmallIcon },
props: DropdownMenuProps,
props: {
onMenuOpened: Function,
onMenuClosed: Function,
...DropdownMenuProps,
},
emits: ['menuOpened', 'menuClosed'],
setup(props, { slots }) {
const renderContent = useContent();
Expand Down
83 changes: 83 additions & 0 deletions src/hooks/useLockScroll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { Ref, watch, onMounted, onActivated, onBeforeUnmount, onDeactivated, nextTick } from 'vue';
import { useTouch } from '../_util/useTouch';
import getScrollParent from '../_util/getScrollParent';
import { supportsPassive } from '../_util/supportsPassive';

let totalLockCount = 0;
let mounted: boolean = null;

// 移植自vant:https://github.com/youzan/vant/blob/HEAD/src/composables/use-lock-scroll.ts
export function useLockScroll(rootRef: Ref<HTMLElement | undefined>, shouldLock: () => boolean, componentName: string) {
const touch = useTouch();
const BODY_LOCK_CLASS = `${componentName}--lock`;

const onTouchMove = (event: TouchEvent) => {
touch.move(event);

const direction = touch.deltaY.value > 0 ? '10' : '01';
const el = getScrollParent(event.target as Element, rootRef.value) as HTMLElement;
if (!el) return;
const { scrollHeight, offsetHeight, scrollTop } = el;
let status = '11';

if (scrollTop === 0) {
status = offsetHeight >= scrollHeight ? '00' : '01';
} else if (scrollTop + offsetHeight >= scrollHeight) {
status = '10';
}

if (status !== '11' && touch.isVertical() && !(parseInt(status, 2) & parseInt(direction, 2))) {
if (event.cancelable) {
event.preventDefault();
}
}
};

const lock = () => {
document.addEventListener('touchstart', touch.start);
document.addEventListener('touchmove', onTouchMove, supportsPassive.value ? { passive: false } : false);

if (!totalLockCount) {
document.body.classList.add(BODY_LOCK_CLASS);
}

totalLockCount += 1;
};

const unlock = () => {
if (totalLockCount) {
document.removeEventListener('touchstart', touch.start);
document.removeEventListener('touchmove', onTouchMove);

totalLockCount -= 1;

if (!totalLockCount) {
document.body.classList.remove(BODY_LOCK_CLASS);
}
}
};

const init = () => shouldLock() && lock();

const destroy = () => shouldLock() && unlock();

onMounted(() => {
init();
nextTick(() => {
mounted = true;
});
});

onActivated(() => {
if (mounted) {
init();
}
});

onDeactivated(destroy);
onBeforeUnmount(destroy);

watch(shouldLock, (value) => {
value ? lock() : unlock();
});
}
32 changes: 32 additions & 0 deletions src/hooks/useTeleport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { computed, Ref, onMounted, ref, watch } from 'vue';
import isFunction from 'lodash/isFunction';
import { getSSRAttach, getAttach } from '../shared/dom';
import { AttachNode } from '../common';

/**
* @description 返回挂载的节点, 用于teleport
* @param attach 既可以是一个函数, 也可以是一个ref
* @param triggerNode 既可以是一个函数, 也可以是一个ref
*/
const useTeleport = (
attach: (() => AttachNode) | Ref<AttachNode>,
triggerNode?: (() => any) | Ref<any>,
): Ref<string | Element> => {
// 如果是函数, 则使用computed包裹 否则直接使用ref
const to = isFunction(attach) ? computed(attach) : ref(attach);
const innerTriggerNode = isFunction(triggerNode) ? computed(triggerNode) : ref(triggerNode);

const element = ref<string | Element>();

const getElement = () => {
element.value = getSSRAttach() || getAttach(to.value, innerTriggerNode.value);
};

onMounted(() => getElement());

watch([to, innerTriggerNode], () => getElement());

return element;
};

export default useTeleport;
26 changes: 26 additions & 0 deletions src/image-viewer/__test__/__snapshots__/demo.test.jsx.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`ImageViewer > ImageViewer alignVue demo works fine 1`] = `
<div
data-v-app=""
>
<button
aria-disabled="false"
class="t-button t-button--size-large t-button--outline t-button--primary t-button--rectangle t-button--block"
role="button"
type="button"
>
<!---->
<span
class="t-button__content"
>
基础图片预览 + 对齐方式
</span>
<!---->
</button>
<!---->
</div>
`;

exports[`ImageViewer > ImageViewer baseVue demo works fine 1`] = `
<div
data-v-app=""
Expand Down
2 changes: 2 additions & 0 deletions src/image-viewer/__test__/demo.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
*/

import { mount } from '@vue/test-utils';
import alignVue from '@/image-viewer/demos/align.vue';
import baseVue from '@/image-viewer/demos/base.vue';
import mobileVue from '@/image-viewer/demos/mobile.vue';
import operationVue from '@/image-viewer/demos/operation.vue';

const mapper = {
alignVue,
baseVue,
mobileVue,
operationVue,
Expand Down
6 changes: 3 additions & 3 deletions src/layout/__test__/__snapshots__/demo.test.jsx.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Col > Col baseVue demo works fine 1`] = `
exports[`Layout > Layout baseVue demo works fine 1`] = `
<div
data-v-app=""
>
Expand Down Expand Up @@ -78,7 +78,7 @@ exports[`Col > Col baseVue demo works fine 1`] = `
</div>
`;

exports[`Col > Col mobileVue demo works fine 1`] = `
exports[`Layout > Layout mobileVue demo works fine 1`] = `
<div
class="tdesign-mobile-demo"
data-v-05f1f61d=""
Expand Down Expand Up @@ -266,7 +266,7 @@ exports[`Col > Col mobileVue demo works fine 1`] = `
</div>
`;

exports[`Col > Col offsetVue demo works fine 1`] = `
exports[`Layout > Layout offsetVue demo works fine 1`] = `
<div
class="t-row"
data-v-5d81698e=""
Expand Down
4 changes: 2 additions & 2 deletions src/layout/__test__/demo.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ const mapper = {
offsetVue,
};

describe('Col', () => {
describe('Layout', () => {
Object.keys(mapper).forEach((demoName) => {
it(`Col ${demoName} demo works fine`, () => {
it(`Layout ${demoName} demo works fine`, () => {
const wrapper = mount(mapper[demoName]);
expect(wrapper.element).toMatchSnapshot();
});
Expand Down
Loading

0 comments on commit 84f2262

Please sign in to comment.