From 8bdaee18a92d60ed238072a44facddf85aa0b9a6 Mon Sep 17 00:00:00 2001 From: undefined Date: Mon, 24 May 2021 22:16:29 +0800 Subject: [PATCH] style: lint --- src/useClickAway/__demo__/index.tsx | 40 +- src/useClickAway/__test__/index.spec.tsx | 72 +- src/useDraggable/__demo__/index.tsx | 36 +- src/useDraggable/__test__/index.spec.tsx | 980 +++++++++---------- src/useDraggable/index.ts | 394 ++++---- src/useEventListener/__demo__/index.tsx | 46 +- src/useEventListener/__test__/index.spec.tsx | 128 +-- src/useForm/__demo__/index.tsx | 242 +++-- src/useForm/index.ts | 10 +- src/useHover/__demo__/index.tsx | 48 +- src/useHover/__tests__/index.spec.tsx | 70 +- src/useHover/index.ts | 146 +-- src/useInViewport/__demo__/index.tsx | 34 +- src/useInViewport/index.ts | 54 +- src/useReactiveRef/__demo__/index.tsx | 42 +- src/useReactiveRef/__test__/index.spec.tsx | 50 +- src/useReactiveRef/index.ts | 26 +- src/useScroll/__demo__/index.tsx | 116 +-- src/useScroll/__test__/index.spec.tsx | 112 +-- src/useScroll/index.ts | 70 +- src/useSize/__demo__/index.tsx | 26 +- src/useSize/index.ts | 74 +- src/useToggle/__demo__/index.tsx | 64 +- src/useToggle/__test__/index.spec.ts | 28 +- src/useToggle/index.ts | 104 +- src/utils/testingHelpers.ts | 2 +- src/utils/typeHelpers.ts | 14 +- 27 files changed, 1513 insertions(+), 1515 deletions(-) diff --git a/src/useClickAway/__demo__/index.tsx b/src/useClickAway/__demo__/index.tsx index 9a90288..1deb128 100644 --- a/src/useClickAway/__demo__/index.tsx +++ b/src/useClickAway/__demo__/index.tsx @@ -1,20 +1,20 @@ -import { Component, ref, defineComponent } from 'vue'; -import useClickAway from '../index'; -export default defineComponent({ - setup() { - const count = ref(0); - const eleRef = ref(null); - useClickAway(eleRef, () => { - count.value++; - }); - return { eleRef, count }; - }, - render(_ctx) { - return ( -
- -
count:{_ctx.count}
-
- ); - }, -}) as Component; +import { Component, ref, defineComponent } from 'vue'; +import useClickAway from '../index'; +export default defineComponent({ + setup() { + const count = ref(0); + const eleRef = ref(null); + useClickAway(eleRef, () => { + count.value++; + }); + return { eleRef, count }; + }, + render(_ctx) { + return ( +
+ +
count:{_ctx.count}
+
+ ); + }, +}) as Component; diff --git a/src/useClickAway/__test__/index.spec.tsx b/src/useClickAway/__test__/index.spec.tsx index 10dfed7..5f833e2 100644 --- a/src/useClickAway/__test__/index.spec.tsx +++ b/src/useClickAway/__test__/index.spec.tsx @@ -1,36 +1,36 @@ -import { mount } from '@vue/test-utils'; - -import useClickAway from '../index'; -import { ref } from 'vue'; - -describe('useClickAway', () => { - test('should work with custom funtion', async () => { - // eslint-disable-next-line @typescript-eslint/no-empty-function - const fn = jest.fn(() => {}); - const eleRef = ref(null); - const wrapRef = ref(null); - let removeListener!: () => void; - const wrapper = mount({ - setup() { - removeListener = useClickAway(eleRef, fn, 'click', wrapRef); - return { eleRef, wrapRef }; - }, - render() { - return ( -
-

-

h2

-
- ); - }, - }); - await wrapper.vm.$nextTick(); - wrapper.find('h1').trigger('click'); - expect(fn).toHaveBeenCalledTimes(0); - wrapper.find('h2').trigger('click'); - expect(fn).toHaveBeenCalledTimes(1); - removeListener(); - wrapper.find('h2').trigger('click'); - expect(fn).toHaveBeenCalledTimes(1); - }); -}); +import { mount } from '@vue/test-utils'; + +import useClickAway from '../index'; +import { ref } from 'vue'; + +describe('useClickAway', () => { + test('should work with custom funtion', async () => { + // eslint-disable-next-line @typescript-eslint/no-empty-function + const fn = jest.fn(() => {}); + const eleRef = ref(null); + const wrapRef = ref(null); + let removeListener!: () => void; + const wrapper = mount({ + setup() { + removeListener = useClickAway(eleRef, fn, 'click', wrapRef); + return { eleRef, wrapRef }; + }, + render() { + return ( +
+

+

h2

+
+ ); + }, + }); + await wrapper.vm.$nextTick(); + wrapper.find('h1').trigger('click'); + expect(fn).toHaveBeenCalledTimes(0); + wrapper.find('h2').trigger('click'); + expect(fn).toHaveBeenCalledTimes(1); + removeListener(); + wrapper.find('h2').trigger('click'); + expect(fn).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/useDraggable/__demo__/index.tsx b/src/useDraggable/__demo__/index.tsx index dc9c505..55b2bfe 100644 --- a/src/useDraggable/__demo__/index.tsx +++ b/src/useDraggable/__demo__/index.tsx @@ -1,18 +1,18 @@ -import { Component, defineComponent } from 'vue'; -import useDraggable from '../index'; -export default defineComponent({ - setup() { - const [targetRef, handleRef, { delta }] = useDraggable({ controlStyle: true }); - return () => { - return ( - <> -
- -
-

{delta.value.x}

-

{delta.value.y}

- - ); - }; - }, -}) as Component; +import { Component, defineComponent } from 'vue'; +import useDraggable from '../index'; +export default defineComponent({ + setup() { + const [targetRef, handleRef, { delta }] = useDraggable({ controlStyle: true }); + return () => { + return ( + <> +
+ +
+

{delta.value.x}

+

{delta.value.y}

+ + ); + }; + }, +}) as Component; diff --git a/src/useDraggable/__test__/index.spec.tsx b/src/useDraggable/__test__/index.spec.tsx index b42588c..c3bd794 100644 --- a/src/useDraggable/__test__/index.spec.tsx +++ b/src/useDraggable/__test__/index.spec.tsx @@ -1,490 +1,490 @@ -/* eslint-disable @typescript-eslint/no-empty-function */ -import { mount } from '@vue/test-utils'; - -import useDraggable from '../index'; -import { defineComponent, CSSProperties } from 'vue'; - -describe('drag', () => { - let utils!: ReturnType; - beforeEach(() => { - utils = setup(); - }); - - describe('starting drag', async () => { - it('should supply proper props to target', async () => { - const { wrapper } = await utils; - wrapper.find('#handle').trigger('mousedown'); - await wrapper.vm.$nextTick(); - expect(wrapper.find('[aria-grabbed]')).toBeTruthy; - }); - - it('should return a delta position', async () => { - const startAt = { clientX: 10, clientY: 10 }; - const delta = { x: 5, y: 5 }; - const { drag, wrapper } = await utils; - await drag({ start: startAt, delta }); - await wrapper.vm.$nextTick(); - expect(wrapper.find('#output').text()).toEqual(`${delta.x}, ${delta.y}`); - }); - it('should return a correct delta position after more drag', async () => { - const startAt = { clientX: 10, clientY: 10 }; - const delta = { x: 5, y: 5 }; - const secondStart = { - clientX: startAt.clientX + delta.x, - clientY: startAt.clientY + delta.y, - }; - const { drag, wrapper } = await utils; - await drag({ start: startAt, delta }); - await drag({ - start: secondStart, - delta, - }); - await wrapper.vm.$nextTick(); - expect(wrapper.find('#output').text()).toEqual(`${2 * delta.x}, ${2 * delta.y}`); - }); - }); -}); - -describe('decorate with styles', async () => { - let utils!: ReturnType; - beforeEach(() => { - utils = setup({ useDraggableOption: { controlStyle: true } }); - }); - - it("should change target's style when dragging", async () => { - const { wrapper, drag } = await utils; - - await drag({ - start: { clientX: 3, clientY: 3 }, - delta: { x: 10, y: 15 }, - }); - - expect((wrapper.find('#main').element as HTMLElement).style.transform).toEqual( - `translate(10px, 15px)`, - ); - }); - - it("should change target's style when dragging (touches)", async () => { - const { wrapper, drag } = await utils; - - await drag({ - start: { clientX: 3, clientY: 3 }, - delta: { x: 10, y: 15 }, - touch: true, - }); - await wrapper.vm.$nextTick(); - expect((wrapper.find('#main').element as HTMLElement).style.transform).toEqual( - `translate(10px, 15px)`, - ); - }); - - it('should set proper cursor', async () => { - const { wrapper } = await utils; - await wrapper.vm.$nextTick(); - expect((wrapper.find('#handle').element as HTMLElement).style.cursor).toEqual('grab'); - }); - - it('should change cursor while dragging', async () => { - const { wrapper } = await utils; - wrapper.find('#handle').trigger('mousedown'); - await wrapper.vm.$nextTick(); - expect((wrapper.find('#handle').element as HTMLElement).style.cursor).toEqual('grabbing'); - }); - - it('should add `will-change: transform` to target', async () => { - const { wrapper } = await utils; - wrapper.find('#handle').trigger('mousedown'); - expect((wrapper.find('#main').element as HTMLElement).style.willChange).toEqual('transform'); - }); - - it('should remove `will-change: transform` from target', async () => { - const { wrapper, drag } = await utils; - await drag({ - start: { clientX: 3, clientY: 3 }, - delta: { x: 10, y: 15 }, - }); - expect((wrapper.find('#main').element as HTMLElement).style.willChange).toEqual(''); - }); -}); - -describe('ending drag', () => { - let utils!: ReturnType; - beforeEach(() => { - utils = setup({ useDraggableOption: { controlStyle: true }, style: {} }); - }); - it('should supply proper props to target', async () => { - const { drag, wrapper } = await utils; - - await drag(); - - expect(wrapper.find('[aria-grabbed]')).toBeNull; - }); -}); - -describe('limit in viewport', async () => { - let utils!: ReturnType; - beforeEach(() => { - utils = setup({ - useDraggableOption: { - controlStyle: true, - viewport: true, - }, - style: { - ...defaultStyle, - width: '180px', - left: 'auto', - right: '0', - }, - }); - }); - - it('should not change transition beyond given rect', async () => { - const { drag, wrapper } = await utils; - const targetElement = wrapper.find('#main').element as HTMLElement; - const rect = targetElement.getBoundingClientRect(); - const startAt = { clientX: rect.left + 5, clientY: rect.top + 5 }; - const delta = { x: 5, y: 5 }; - - await drag({ start: startAt, delta }); - await wrapper.vm.$nextTick(); - expect(targetElement.style.transform).toContain(`translate(5px, 5px)`); - }); - - it('should leave transition as it was before limit', async () => { - const { wrapper, beginDrag, move } = await utils; - const targetElement = wrapper.find('#main').element as HTMLElement; - - const startAt = { clientX: 0 + 5, clientY: 0 + 5 }; - const delta = { x: 5, y: 1 }; - - await beginDrag(startAt); - await move({ - clientX: startAt.clientX + delta.x, - clientY: startAt.clientY + delta.y, - }); - await move({ - clientX: startAt.clientX + delta.x + 10, - clientY: startAt.clientY + delta.y, - }); - await move({ - clientX: startAt.clientX + delta.x + 25, - clientY: startAt.clientY + delta.y, - }); - await move({ - clientX: startAt.clientX + delta.x + 50, - clientY: startAt.clientY + delta.y, - }); - - await wrapper.vm.$nextTick(); - expect(targetElement.style.transform).toContain(`translate(55px, 1px)`); - }); - - it('should keep limits when dragging more than once', async () => { - const { drag, wrapper } = await utils; - const targetElement = wrapper.find('#main').element as HTMLElement; - targetElement.style.right = '50px'; - const startAt = { clientX: 5, clientY: 5 }; - const delta = { x: 15, y: 1 }; - - await drag({ start: startAt, delta }); - await drag({ - start: { - clientX: startAt.clientX + delta.x, - clientY: startAt.clientY + delta.y, - }, - delta: { x: 50, y: 0 }, - }); - - await wrapper.vm.$nextTick(); - expect(targetElement.style.transform).toContain(`translate(65px, 1px)`); - }); -}); - -// describe('limit in rect', async () => { -// const limits = { -// left: 11, -// right: window.innerWidth - 11, -// top: 5, -// bottom: window.innerHeight - 13 -// }; - -// let utils!: ReturnType -// beforeEach(() => { -// utils = setup({ -// useDraggableOption: { -// controlStyle: true, -// rectLimits: limits, -// }, -// style: { -// ...defaultStyle, -// width: '180px', -// left: '20px' -// } -// }); -// }); - -// it('should not change transition beyond given rect', async () => { -// const { drag, wrapper } = await utils; -// const targetElement = wrapper.find('#main').element as HTMLElement; -// const rect = targetElement.getBoundingClientRect(); -// const startAt = { clientX: rect.left + 5, clientY: rect.top + 5 }; -// const delta = { x: -50, y: -90 }; - -// await drag({ start: startAt, delta }); -// await wrapper.vm.$nextTick() -// expect(targetElement.style.transform).toContain({ -// left: limits.left, -// top: limits.top -// }); -// }); - -// it('should keep limits when dragging more than once', async () => { -// const { drag, wrapper } = await utils; -// const targetElement = wrapper.find('#main').element as HTMLElement; -// targetElement.style.right = '50px'; -// targetElement.style.left = 'auto'; -// const rect = targetElement.getBoundingClientRect(); - -// const startAt = { clientX: rect.left + 5, clientY: rect.top + 5 }; -// const delta = { x: 15, y: 1 }; - -// drag({ start: startAt, delta }); -// drag({ -// start: { -// clientX: startAt.clientX + delta.x, -// clientY: startAt.clientY + delta.y -// }, -// delta: { x: 50, y: 0 } -// }); - -// const { left, width } = targetElement.getBoundingClientRect(); -// expect(left).toEqual(limits.right - width); -// }); -// }); - -describe('reset drags', () => { - let utils!: ReturnType; - beforeEach(() => { - utils = setup({ useDraggableOption: { controlStyle: true } }); - }); - - it('should start dragging from the original position', async () => { - const { wrapper, drag } = await utils; - await drag({ start: { clientX: 3, clientY: 5 }, delta: { x: 15, y: 20 } }); - wrapper.find('#reset').trigger('click'); - await wrapper.vm.$nextTick(); - expect((wrapper.find('#main').element as HTMLElement).style.transform).toEqual( - 'translate(0px, 0px)', - ); - }); - - describe('after reset', () => { - it('should start dragging from the original position', async () => { - const { wrapper, drag } = await utils; - await drag({ start: { clientX: 3, clientY: 5 }, delta: { x: 15, y: 20 } }); - wrapper.find('#reset').trigger('click'); - await drag({ start: { clientX: 3, clientY: 5 }, delta: { x: 15, y: 20 } }); - expect((wrapper.find('#main').element as HTMLElement).style.transform).toEqual( - 'translate(15px, 20px)', - ); - }); - }); -}); - -describe('useDraggable', () => { - test('starting drag', async () => { - const [targetRef] = useDraggable({ controlStyle: true }); - mount({ - setup() { - targetRef; - return { targetRef }; - }, - render() { - return ( - <> -

{ - targetRef.value = ele; - }} - > - {' '} - click{' '} -

- - ); - }, - }); - }); -}); -const Consumer = defineComponent({ - props: ['useDraggableOption', 'style'], - setup(props: { useDraggableOption: Parameters[0]; style: CSSProperties }) { - const [targetRef, handleRef, { getTargetProps, resetState, delta, dragging }] = useDraggable( - props.useDraggableOption, - ); - return () => ( -
- {dragging && Dragging to:} - - {delta.value.x}, {delta.value.y} - - - -
- ); - }, -}); - -const defaultStyle = { position: 'fixed', top: '11px', left: '11px' } as CSSProperties; -async function setup( - props: { useDraggableOption: Parameters[0]; style?: CSSProperties } = { - style: {}, - useDraggableOption: {}, - }, -) { - const wrapper = mount( - , - ); - async function drag({ - start = { clientX: 0, clientY: 0 }, - delta = { x: 0, y: 0 }, - touch = false, - } = {}) { - beginDrag(start, touch); - await wrapper.vm.$nextTick(); - move( - { - clientX: start.clientX + delta.x, - clientY: start.clientY + delta.y, - }, - touch, - ); - await wrapper.vm.$nextTick(); - endDrag( - { - clientX: start.clientX + delta.x, - clientY: start.clientY + delta.y, - }, - touch, - ); - } - - async function beginDrag(start, touch = false) { - const target = wrapper.find('#handle'); - if (touch) { - const ev = new TouchEvent('touchstart', { - bubbles: true, - cancelable: true, - touches: [createTouch({ target, ...start })], - }); - target.element.dispatchEvent(ev); - } else { - target.trigger('mousedown', start); - } - } - - async function move(to, touch = false) { - const target = wrapper.find('#handle'); - if (touch) { - const ev = new TouchEvent('touchmove', { - bubbles: true, - cancelable: true, - touches: [ - createTouch({ - target, - ...to, - }), - ], - }); - document.dispatchEvent(ev); - } else { - const ev = new MouseEvent('mousemove', { - view: window, - bubbles: true, - cancelable: true, - ...to, - }); - document.dispatchEvent(ev); - } - } - - async function endDrag(end, touch = false) { - const target = wrapper.find('#handle'); - if (touch) { - const ev = new TouchEvent('touchend', { - bubbles: true, - cancelable: true, - touches: [ - createTouch({ - target, - ...end, - }), - ], - }); - document.dispatchEvent(ev); - } else { - const ev = new MouseEvent('mouseup', { - view: window, - bubbles: true, - cancelable: true, - ...end, - }); - document.dispatchEvent(ev); - } - } - - return { - wrapper, - beginDrag, - move, - drag, - }; -} - -class Touch { - constructor(touchInit: any) { - this.altitudeAngle = touchInit.altitudeAngle; - this.azimuthAngle = touchInit.azimuthAngle; - this.clientX = touchInit.clientX; - this.clientY = touchInit.clientY; - this.force = touchInit.force; - this.identifier = touchInit.identifier; - this.pageX = touchInit.pageX; - this.pageY = touchInit.pageY; - this.radiusX = touchInit.radiusX; - this.radiusY = touchInit.radiusY; - this.rotationAngle = touchInit.rotationAngle; - this.screenX = touchInit.screenX; - this.screenY = touchInit.screenY; - this.target = touchInit.target; - this.touchType = touchInit.touchType; - } - readonly altitudeAngle: number; - readonly azimuthAngle: number; - readonly clientX: number; - readonly clientY: number; - readonly force: number; - readonly identifier: number; - readonly pageX: number; - readonly pageY: number; - readonly radiusX: number; - readonly radiusY: number; - readonly rotationAngle: number; - readonly screenX: number; - readonly screenY: number; - readonly target: EventTarget; - readonly touchType: TouchType; -} -function createTouch({ target, ...rest }) { - return new Touch({ identifier: Date.now(), target, ...rest }); -} +/* eslint-disable @typescript-eslint/no-empty-function */ +import { mount } from '@vue/test-utils'; + +import useDraggable from '../index'; +import { defineComponent, CSSProperties } from 'vue'; + +describe('drag', () => { + let utils!: ReturnType; + beforeEach(() => { + utils = setup(); + }); + + describe('starting drag', async () => { + it('should supply proper props to target', async () => { + const { wrapper } = await utils; + wrapper.find('#handle').trigger('mousedown'); + await wrapper.vm.$nextTick(); + expect(wrapper.find('[aria-grabbed]')).toBeTruthy; + }); + + it('should return a delta position', async () => { + const startAt = { clientX: 10, clientY: 10 }; + const delta = { x: 5, y: 5 }; + const { drag, wrapper } = await utils; + await drag({ start: startAt, delta }); + await wrapper.vm.$nextTick(); + expect(wrapper.find('#output').text()).toEqual(`${delta.x}, ${delta.y}`); + }); + it('should return a correct delta position after more drag', async () => { + const startAt = { clientX: 10, clientY: 10 }; + const delta = { x: 5, y: 5 }; + const secondStart = { + clientX: startAt.clientX + delta.x, + clientY: startAt.clientY + delta.y, + }; + const { drag, wrapper } = await utils; + await drag({ start: startAt, delta }); + await drag({ + start: secondStart, + delta, + }); + await wrapper.vm.$nextTick(); + expect(wrapper.find('#output').text()).toEqual(`${2 * delta.x}, ${2 * delta.y}`); + }); + }); +}); + +describe('decorate with styles', async () => { + let utils!: ReturnType; + beforeEach(() => { + utils = setup({ useDraggableOption: { controlStyle: true } }); + }); + + it("should change target's style when dragging", async () => { + const { wrapper, drag } = await utils; + + await drag({ + start: { clientX: 3, clientY: 3 }, + delta: { x: 10, y: 15 }, + }); + + expect((wrapper.find('#main').element as HTMLElement).style.transform).toEqual( + `translate(10px, 15px)`, + ); + }); + + it("should change target's style when dragging (touches)", async () => { + const { wrapper, drag } = await utils; + + await drag({ + start: { clientX: 3, clientY: 3 }, + delta: { x: 10, y: 15 }, + touch: true, + }); + await wrapper.vm.$nextTick(); + expect((wrapper.find('#main').element as HTMLElement).style.transform).toEqual( + `translate(10px, 15px)`, + ); + }); + + it('should set proper cursor', async () => { + const { wrapper } = await utils; + await wrapper.vm.$nextTick(); + expect((wrapper.find('#handle').element as HTMLElement).style.cursor).toEqual('grab'); + }); + + it('should change cursor while dragging', async () => { + const { wrapper } = await utils; + wrapper.find('#handle').trigger('mousedown'); + await wrapper.vm.$nextTick(); + expect((wrapper.find('#handle').element as HTMLElement).style.cursor).toEqual('grabbing'); + }); + + it('should add `will-change: transform` to target', async () => { + const { wrapper } = await utils; + wrapper.find('#handle').trigger('mousedown'); + expect((wrapper.find('#main').element as HTMLElement).style.willChange).toEqual('transform'); + }); + + it('should remove `will-change: transform` from target', async () => { + const { wrapper, drag } = await utils; + await drag({ + start: { clientX: 3, clientY: 3 }, + delta: { x: 10, y: 15 }, + }); + expect((wrapper.find('#main').element as HTMLElement).style.willChange).toEqual(''); + }); +}); + +describe('ending drag', () => { + let utils!: ReturnType; + beforeEach(() => { + utils = setup({ useDraggableOption: { controlStyle: true }, style: {} }); + }); + it('should supply proper props to target', async () => { + const { drag, wrapper } = await utils; + + await drag(); + + expect(wrapper.find('[aria-grabbed]')).toBeNull; + }); +}); + +describe('limit in viewport', async () => { + let utils!: ReturnType; + beforeEach(() => { + utils = setup({ + useDraggableOption: { + controlStyle: true, + viewport: true, + }, + style: { + ...defaultStyle, + width: '180px', + left: 'auto', + right: '0', + }, + }); + }); + + it('should not change transition beyond given rect', async () => { + const { drag, wrapper } = await utils; + const targetElement = wrapper.find('#main').element as HTMLElement; + const rect = targetElement.getBoundingClientRect(); + const startAt = { clientX: rect.left + 5, clientY: rect.top + 5 }; + const delta = { x: 5, y: 5 }; + + await drag({ start: startAt, delta }); + await wrapper.vm.$nextTick(); + expect(targetElement.style.transform).toContain(`translate(5px, 5px)`); + }); + + it('should leave transition as it was before limit', async () => { + const { wrapper, beginDrag, move } = await utils; + const targetElement = wrapper.find('#main').element as HTMLElement; + + const startAt = { clientX: 0 + 5, clientY: 0 + 5 }; + const delta = { x: 5, y: 1 }; + + await beginDrag(startAt); + await move({ + clientX: startAt.clientX + delta.x, + clientY: startAt.clientY + delta.y, + }); + await move({ + clientX: startAt.clientX + delta.x + 10, + clientY: startAt.clientY + delta.y, + }); + await move({ + clientX: startAt.clientX + delta.x + 25, + clientY: startAt.clientY + delta.y, + }); + await move({ + clientX: startAt.clientX + delta.x + 50, + clientY: startAt.clientY + delta.y, + }); + + await wrapper.vm.$nextTick(); + expect(targetElement.style.transform).toContain(`translate(55px, 1px)`); + }); + + it('should keep limits when dragging more than once', async () => { + const { drag, wrapper } = await utils; + const targetElement = wrapper.find('#main').element as HTMLElement; + targetElement.style.right = '50px'; + const startAt = { clientX: 5, clientY: 5 }; + const delta = { x: 15, y: 1 }; + + await drag({ start: startAt, delta }); + await drag({ + start: { + clientX: startAt.clientX + delta.x, + clientY: startAt.clientY + delta.y, + }, + delta: { x: 50, y: 0 }, + }); + + await wrapper.vm.$nextTick(); + expect(targetElement.style.transform).toContain(`translate(65px, 1px)`); + }); +}); + +// describe('limit in rect', async () => { +// const limits = { +// left: 11, +// right: window.innerWidth - 11, +// top: 5, +// bottom: window.innerHeight - 13 +// }; + +// let utils!: ReturnType +// beforeEach(() => { +// utils = setup({ +// useDraggableOption: { +// controlStyle: true, +// rectLimits: limits, +// }, +// style: { +// ...defaultStyle, +// width: '180px', +// left: '20px' +// } +// }); +// }); + +// it('should not change transition beyond given rect', async () => { +// const { drag, wrapper } = await utils; +// const targetElement = wrapper.find('#main').element as HTMLElement; +// const rect = targetElement.getBoundingClientRect(); +// const startAt = { clientX: rect.left + 5, clientY: rect.top + 5 }; +// const delta = { x: -50, y: -90 }; + +// await drag({ start: startAt, delta }); +// await wrapper.vm.$nextTick() +// expect(targetElement.style.transform).toContain({ +// left: limits.left, +// top: limits.top +// }); +// }); + +// it('should keep limits when dragging more than once', async () => { +// const { drag, wrapper } = await utils; +// const targetElement = wrapper.find('#main').element as HTMLElement; +// targetElement.style.right = '50px'; +// targetElement.style.left = 'auto'; +// const rect = targetElement.getBoundingClientRect(); + +// const startAt = { clientX: rect.left + 5, clientY: rect.top + 5 }; +// const delta = { x: 15, y: 1 }; + +// drag({ start: startAt, delta }); +// drag({ +// start: { +// clientX: startAt.clientX + delta.x, +// clientY: startAt.clientY + delta.y +// }, +// delta: { x: 50, y: 0 } +// }); + +// const { left, width } = targetElement.getBoundingClientRect(); +// expect(left).toEqual(limits.right - width); +// }); +// }); + +describe('reset drags', () => { + let utils!: ReturnType; + beforeEach(() => { + utils = setup({ useDraggableOption: { controlStyle: true } }); + }); + + it('should start dragging from the original position', async () => { + const { wrapper, drag } = await utils; + await drag({ start: { clientX: 3, clientY: 5 }, delta: { x: 15, y: 20 } }); + wrapper.find('#reset').trigger('click'); + await wrapper.vm.$nextTick(); + expect((wrapper.find('#main').element as HTMLElement).style.transform).toEqual( + 'translate(0px, 0px)', + ); + }); + + describe('after reset', () => { + it('should start dragging from the original position', async () => { + const { wrapper, drag } = await utils; + await drag({ start: { clientX: 3, clientY: 5 }, delta: { x: 15, y: 20 } }); + wrapper.find('#reset').trigger('click'); + await drag({ start: { clientX: 3, clientY: 5 }, delta: { x: 15, y: 20 } }); + expect((wrapper.find('#main').element as HTMLElement).style.transform).toEqual( + 'translate(15px, 20px)', + ); + }); + }); +}); + +describe('useDraggable', () => { + test('starting drag', async () => { + const [targetRef] = useDraggable({ controlStyle: true }); + mount({ + setup() { + targetRef; + return { targetRef }; + }, + render() { + return ( + <> +

{ + targetRef.value = ele; + }} + > + {' '} + click{' '} +

+ + ); + }, + }); + }); +}); +const Consumer = defineComponent({ + props: ['useDraggableOption', 'style'], + setup(props: { useDraggableOption: Parameters[0]; style: CSSProperties }) { + const [targetRef, handleRef, { getTargetProps, resetState, delta, dragging }] = useDraggable( + props.useDraggableOption, + ); + return () => ( +
+ {dragging && Dragging to:} + + {delta.value.x}, {delta.value.y} + + + +
+ ); + }, +}); + +const defaultStyle = { position: 'fixed', top: '11px', left: '11px' } as CSSProperties; +async function setup( + props: { useDraggableOption: Parameters[0]; style?: CSSProperties } = { + style: {}, + useDraggableOption: {}, + }, +) { + const wrapper = mount( + , + ); + async function drag({ + start = { clientX: 0, clientY: 0 }, + delta = { x: 0, y: 0 }, + touch = false, + } = {}) { + beginDrag(start, touch); + await wrapper.vm.$nextTick(); + move( + { + clientX: start.clientX + delta.x, + clientY: start.clientY + delta.y, + }, + touch, + ); + await wrapper.vm.$nextTick(); + endDrag( + { + clientX: start.clientX + delta.x, + clientY: start.clientY + delta.y, + }, + touch, + ); + } + + async function beginDrag(start, touch = false) { + const target = wrapper.find('#handle'); + if (touch) { + const ev = new TouchEvent('touchstart', { + bubbles: true, + cancelable: true, + touches: [createTouch({ target, ...start })], + }); + target.element.dispatchEvent(ev); + } else { + target.trigger('mousedown', start); + } + } + + async function move(to, touch = false) { + const target = wrapper.find('#handle'); + if (touch) { + const ev = new TouchEvent('touchmove', { + bubbles: true, + cancelable: true, + touches: [ + createTouch({ + target, + ...to, + }), + ], + }); + document.dispatchEvent(ev); + } else { + const ev = new MouseEvent('mousemove', { + view: window, + bubbles: true, + cancelable: true, + ...to, + }); + document.dispatchEvent(ev); + } + } + + async function endDrag(end, touch = false) { + const target = wrapper.find('#handle'); + if (touch) { + const ev = new TouchEvent('touchend', { + bubbles: true, + cancelable: true, + touches: [ + createTouch({ + target, + ...end, + }), + ], + }); + document.dispatchEvent(ev); + } else { + const ev = new MouseEvent('mouseup', { + view: window, + bubbles: true, + cancelable: true, + ...end, + }); + document.dispatchEvent(ev); + } + } + + return { + wrapper, + beginDrag, + move, + drag, + }; +} + +class Touch { + constructor(touchInit: any) { + this.altitudeAngle = touchInit.altitudeAngle; + this.azimuthAngle = touchInit.azimuthAngle; + this.clientX = touchInit.clientX; + this.clientY = touchInit.clientY; + this.force = touchInit.force; + this.identifier = touchInit.identifier; + this.pageX = touchInit.pageX; + this.pageY = touchInit.pageY; + this.radiusX = touchInit.radiusX; + this.radiusY = touchInit.radiusY; + this.rotationAngle = touchInit.rotationAngle; + this.screenX = touchInit.screenX; + this.screenY = touchInit.screenY; + this.target = touchInit.target; + this.touchType = touchInit.touchType; + } + readonly altitudeAngle: number; + readonly azimuthAngle: number; + readonly clientX: number; + readonly clientY: number; + readonly force: number; + readonly identifier: number; + readonly pageX: number; + readonly pageY: number; + readonly radiusX: number; + readonly radiusY: number; + readonly rotationAngle: number; + readonly screenX: number; + readonly screenY: number; + readonly target: EventTarget; + readonly touchType: TouchType; +} +function createTouch({ target, ...rest }) { + return new Touch({ identifier: Date.now(), target, ...rest }); +} diff --git a/src/useDraggable/index.ts b/src/useDraggable/index.ts index 5755d07..053523b 100644 --- a/src/useDraggable/index.ts +++ b/src/useDraggable/index.ts @@ -1,197 +1,197 @@ -import { Ref, ref, watchEffect, HTMLAttributes } from 'vue'; -import { isComponentPublicInstance, ElementType } from '../utils/typeHelpers'; - -export default function useDraggable( - config: { - target?: Ref; - handle?: Ref; - controlStyle?: boolean; - viewport?: boolean; - rectLimits?: { - left?: number; - right?: number; - top?: number; - bottom?: number; - }; - } = { controlStyle: true }, -): [ - Ref, - Ref, - { - getTargetProps: () => HTMLAttributes; - dragging: Ref; - delta: Ref<{ x: number; y: number }>; - resetState: () => void; - }, -] { - const { target: configTarget, handle, controlStyle, viewport, rectLimits } = config; - const targetRef = configTarget || ref(null); - const handleRef = handle || ref(null); - const dragging = ref(null); - const prev = ref({ x: 0, y: 0 }); - const delta = ref({ x: 0, y: 0 }); - const initial = ref({ x: 0, y: 0 }); - const limits: Ref<{ - minX: number; - maxX: number; - minY: number; - maxY: number; - }> = ref(null); - const targetEleRef = ref(null); - const handleEleRef = ref(null); - - watchEffect( - () => { - if (!targetRef.value) { - targetEleRef.value = null; - } else { - targetEleRef.value = isComponentPublicInstance(targetRef.value) - ? targetRef.value.$el - : targetRef.value; - } - if (!handleRef.value) { - handleEleRef.value = null; - } else { - handleEleRef.value = isComponentPublicInstance(handleRef.value) - ? handleRef.value.$el - : handleRef.value; - } - }, - { flush: 'post' }, - ); - watchEffect( - () => { - const handle = handleEleRef.value || targetEleRef.value; - if (!targetEleRef.value) return; - handle.addEventListener('mousedown', startDragging); - handle.addEventListener('touchstart', startDragging); - return () => { - handle.removeEventListener('mousedown', startDragging); - handle.removeEventListener('touchstart', startDragging); - }; - - function startDragging(event) { - event.preventDefault(); - dragging.value = true; - const source = (event.touches && event.touches[0]) || event; - const { clientX, clientY } = source; - initial.value = { x: clientX, y: clientY }; - if (controlStyle) { - targetEleRef.value.style.willChange = 'transform'; - } - if (viewport || rectLimits) { - const { left, top, width, height } = targetEleRef.value.getBoundingClientRect(); - - if (viewport) { - limits.value = { - minX: -left + delta.value.x, - maxX: window.innerWidth - width - left + delta.value.x, - minY: -top + delta.value.y, - maxY: window.innerHeight - height - top + delta.value.y, - }; - } else { - limits.value = { - minX: rectLimits.left - left + delta.value.x, - maxX: rectLimits.right - width - left + delta.value.x, - minY: rectLimits.top - top + delta.value.y, - maxY: rectLimits.bottom - height - top + delta.value.y, - }; - } - } - } - }, - { flush: 'post' }, - ); - - watchEffect( - () => { - const handle = handleEleRef.value || targetEleRef.value; - if (!targetEleRef.value) return; - const reposition = function(event) { - const source = - (event.changedTouches && event.changedTouches[0]) || - (event.touches && event.touches[0]) || - event; - const { clientX, clientY } = source; - const x = clientX - initial.value.x + prev.value.x; - const y = clientY - initial.value.y + prev.value.y; - - const newDelta = calcDelta({ - x, - y, - limits: limits.value, - }); - delta.value = newDelta; - - return newDelta; - }; - if (dragging.value) { - document.addEventListener('mousemove', reposition, { passive: true }); - document.addEventListener('touchmove', reposition, { passive: true }); - document.addEventListener('mouseup', stopDragging); - document.addEventListener('touchend', stopDragging); - } - - if (controlStyle) { - handle.style.cursor = dragging.value ? 'grabbing' : 'grab'; - } - - return () => { - if (controlStyle) { - handle.style.cursor = 'unset'; - } - document.removeEventListener('mousemove', reposition); - document.removeEventListener('touchmove', reposition); - document.removeEventListener('mouseup', stopDragging); - document.removeEventListener('touchend', stopDragging); - }; - - function stopDragging(event) { - event.preventDefault(); - dragging.value = false; - document.removeEventListener('mousemove', reposition); - document.removeEventListener('touchmove', reposition); - document.removeEventListener('mouseup', stopDragging); - document.removeEventListener('touchend', stopDragging); - const newDelta = reposition(event); - prev.value = newDelta; - if (controlStyle) { - targetEleRef.value.style.willChange = ''; - } - } - }, - { flush: 'post' }, - ); - - watchEffect( - () => { - targetEleRef.value && - (targetEleRef.value.style.transform = `translate(${delta.value.x}px, ${delta.value.y}px)`); - }, - { flush: 'post' }, - ); - - const getTargetProps = () => ({ - 'aria-grabbed': dragging.value || null, - }); - - const resetState = () => { - delta.value = { x: 0, y: 0 }; - prev.value = { x: 0, y: 0 }; - }; - - return [targetRef, handleRef, { getTargetProps, dragging, delta, resetState }]; -} - -function calcDelta({ x, y, limits }) { - if (!limits) { - return { x, y }; - } - - const { minX, maxX, minY, maxY } = limits; - - return { - x: Math.min(Math.max(x, minX), maxX), - y: Math.min(Math.max(y, minY), maxY), - }; -} +import { Ref, ref, watchEffect, HTMLAttributes } from 'vue'; +import { isComponentPublicInstance, ElementType } from '../utils/typeHelpers'; + +export default function useDraggable( + config: { + target?: Ref; + handle?: Ref; + controlStyle?: boolean; + viewport?: boolean; + rectLimits?: { + left?: number; + right?: number; + top?: number; + bottom?: number; + }; + } = { controlStyle: true }, +): [ + Ref, + Ref, + { + getTargetProps: () => HTMLAttributes; + dragging: Ref; + delta: Ref<{ x: number; y: number }>; + resetState: () => void; + }, +] { + const { target: configTarget, handle, controlStyle, viewport, rectLimits } = config; + const targetRef = configTarget || ref(null); + const handleRef = handle || ref(null); + const dragging = ref(null); + const prev = ref({ x: 0, y: 0 }); + const delta = ref({ x: 0, y: 0 }); + const initial = ref({ x: 0, y: 0 }); + const limits: Ref<{ + minX: number; + maxX: number; + minY: number; + maxY: number; + }> = ref(null); + const targetEleRef = ref(null); + const handleEleRef = ref(null); + + watchEffect( + () => { + if (!targetRef.value) { + targetEleRef.value = null; + } else { + targetEleRef.value = isComponentPublicInstance(targetRef.value) + ? targetRef.value.$el + : targetRef.value; + } + if (!handleRef.value) { + handleEleRef.value = null; + } else { + handleEleRef.value = isComponentPublicInstance(handleRef.value) + ? handleRef.value.$el + : handleRef.value; + } + }, + { flush: 'post' }, + ); + watchEffect( + () => { + const handle = handleEleRef.value || targetEleRef.value; + if (!targetEleRef.value) return; + handle.addEventListener('mousedown', startDragging); + handle.addEventListener('touchstart', startDragging); + return () => { + handle.removeEventListener('mousedown', startDragging); + handle.removeEventListener('touchstart', startDragging); + }; + + function startDragging(event) { + event.preventDefault(); + dragging.value = true; + const source = (event.touches && event.touches[0]) || event; + const { clientX, clientY } = source; + initial.value = { x: clientX, y: clientY }; + if (controlStyle) { + targetEleRef.value.style.willChange = 'transform'; + } + if (viewport || rectLimits) { + const { left, top, width, height } = targetEleRef.value.getBoundingClientRect(); + + if (viewport) { + limits.value = { + minX: -left + delta.value.x, + maxX: window.innerWidth - width - left + delta.value.x, + minY: -top + delta.value.y, + maxY: window.innerHeight - height - top + delta.value.y, + }; + } else { + limits.value = { + minX: rectLimits.left - left + delta.value.x, + maxX: rectLimits.right - width - left + delta.value.x, + minY: rectLimits.top - top + delta.value.y, + maxY: rectLimits.bottom - height - top + delta.value.y, + }; + } + } + } + }, + { flush: 'post' }, + ); + + watchEffect( + () => { + const handle = handleEleRef.value || targetEleRef.value; + if (!targetEleRef.value) return; + const reposition = function (event) { + const source = + (event.changedTouches && event.changedTouches[0]) || + (event.touches && event.touches[0]) || + event; + const { clientX, clientY } = source; + const x = clientX - initial.value.x + prev.value.x; + const y = clientY - initial.value.y + prev.value.y; + + const newDelta = calcDelta({ + x, + y, + limits: limits.value, + }); + delta.value = newDelta; + + return newDelta; + }; + if (dragging.value) { + document.addEventListener('mousemove', reposition, { passive: true }); + document.addEventListener('touchmove', reposition, { passive: true }); + document.addEventListener('mouseup', stopDragging); + document.addEventListener('touchend', stopDragging); + } + + if (controlStyle) { + handle.style.cursor = dragging.value ? 'grabbing' : 'grab'; + } + + return () => { + if (controlStyle) { + handle.style.cursor = 'unset'; + } + document.removeEventListener('mousemove', reposition); + document.removeEventListener('touchmove', reposition); + document.removeEventListener('mouseup', stopDragging); + document.removeEventListener('touchend', stopDragging); + }; + + function stopDragging(event) { + event.preventDefault(); + dragging.value = false; + document.removeEventListener('mousemove', reposition); + document.removeEventListener('touchmove', reposition); + document.removeEventListener('mouseup', stopDragging); + document.removeEventListener('touchend', stopDragging); + const newDelta = reposition(event); + prev.value = newDelta; + if (controlStyle) { + targetEleRef.value.style.willChange = ''; + } + } + }, + { flush: 'post' }, + ); + + watchEffect( + () => { + targetEleRef.value && + (targetEleRef.value.style.transform = `translate(${delta.value.x}px, ${delta.value.y}px)`); + }, + { flush: 'post' }, + ); + + const getTargetProps = () => ({ + 'aria-grabbed': dragging.value || null, + }); + + const resetState = () => { + delta.value = { x: 0, y: 0 }; + prev.value = { x: 0, y: 0 }; + }; + + return [targetRef, handleRef, { getTargetProps, dragging, delta, resetState }]; +} + +function calcDelta({ x, y, limits }) { + if (!limits) { + return { x, y }; + } + + const { minX, maxX, minY, maxY } = limits; + + return { + x: Math.min(Math.max(x, minX), maxX), + y: Math.min(Math.max(y, minY), maxY), + }; +} diff --git a/src/useEventListener/__demo__/index.tsx b/src/useEventListener/__demo__/index.tsx index 0a9c474..72d3a7b 100644 --- a/src/useEventListener/__demo__/index.tsx +++ b/src/useEventListener/__demo__/index.tsx @@ -1,23 +1,23 @@ -import { Component, ref } from 'vue'; -import useEventListener from '../index'; -export default { - setup() { - const count = ref(0); - const eleRef = ref(null); - useEventListener(eleRef, { - type: 'click', - listener: () => { - count.value++; - }, - }); - return { eleRef, count }; - }, - render(_ctx) { - return ( - <> -
click me
-
{_ctx.count}
- - ); - }, -} as Component; +import { Component, ref } from 'vue'; +import useEventListener from '../index'; +export default { + setup() { + const count = ref(0); + const eleRef = ref(null); + useEventListener(eleRef, { + type: 'click', + listener: () => { + count.value++; + }, + }); + return { eleRef, count }; + }, + render(_ctx) { + return ( + <> +
click me
+
{_ctx.count}
+ + ); + }, +} as Component; diff --git a/src/useEventListener/__test__/index.spec.tsx b/src/useEventListener/__test__/index.spec.tsx index 58deca8..50b1189 100644 --- a/src/useEventListener/__test__/index.spec.tsx +++ b/src/useEventListener/__test__/index.spec.tsx @@ -1,64 +1,64 @@ -/* eslint-disable @typescript-eslint/no-empty-function */ -import { shallowMount } from '@vue/test-utils'; - -import useEventListener from '../index'; -import { ref } from 'vue'; - -describe('useEventListener', () => { - test('should work with Ref parameter', async () => { - const clickFn = jest.fn(() => {}); - const eleRef = ref(null); - let removeListener!: () => void; - const wrapper = shallowMount({ - setup() { - removeListener = useEventListener(eleRef, { - type: 'click', - listener: clickFn, - }); - return { eleRef }; - }, - render() { - return ( - <> -

click

- - ); - }, - }); - await wrapper.vm.$nextTick(); - expect(clickFn).toHaveBeenCalledTimes(0); - wrapper.find('h1').trigger('click'); - expect(clickFn).toHaveBeenCalledTimes(1); - removeListener(); - wrapper.find('h1').trigger('click'); - expect(clickFn).toHaveBeenCalledTimes(1); - }); - test('should work with HTMLElement parameter', async () => { - const clickFn = jest.fn(() => {}); - const eleRef = ref(null); - let removeListener!: () => void; - const wrapper = shallowMount({ - setup() { - removeListener = useEventListener(eleRef, { - type: 'click', - listener: clickFn, - }); - return { eleRef }; - }, - render() { - return ( - <> -

click

- - ); - }, - }); - await wrapper.vm.$nextTick(); - expect(clickFn).toHaveBeenCalledTimes(0); - wrapper.find('h1').trigger('click'); - expect(clickFn).toHaveBeenCalledTimes(1); - removeListener(); - wrapper.find('h1').trigger('click'); - expect(clickFn).toHaveBeenCalledTimes(1); - }); -}); +/* eslint-disable @typescript-eslint/no-empty-function */ +import { shallowMount } from '@vue/test-utils'; + +import useEventListener from '../index'; +import { ref } from 'vue'; + +describe('useEventListener', () => { + test('should work with Ref parameter', async () => { + const clickFn = jest.fn(() => {}); + const eleRef = ref(null); + let removeListener!: () => void; + const wrapper = shallowMount({ + setup() { + removeListener = useEventListener(eleRef, { + type: 'click', + listener: clickFn, + }); + return { eleRef }; + }, + render() { + return ( + <> +

click

+ + ); + }, + }); + await wrapper.vm.$nextTick(); + expect(clickFn).toHaveBeenCalledTimes(0); + wrapper.find('h1').trigger('click'); + expect(clickFn).toHaveBeenCalledTimes(1); + removeListener(); + wrapper.find('h1').trigger('click'); + expect(clickFn).toHaveBeenCalledTimes(1); + }); + test('should work with HTMLElement parameter', async () => { + const clickFn = jest.fn(() => {}); + const eleRef = ref(null); + let removeListener!: () => void; + const wrapper = shallowMount({ + setup() { + removeListener = useEventListener(eleRef, { + type: 'click', + listener: clickFn, + }); + return { eleRef }; + }, + render() { + return ( + <> +

click

+ + ); + }, + }); + await wrapper.vm.$nextTick(); + expect(clickFn).toHaveBeenCalledTimes(0); + wrapper.find('h1').trigger('click'); + expect(clickFn).toHaveBeenCalledTimes(1); + removeListener(); + wrapper.find('h1').trigger('click'); + expect(clickFn).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/useForm/__demo__/index.tsx b/src/useForm/__demo__/index.tsx index 3ddfd8c..be33f0c 100644 --- a/src/useForm/__demo__/index.tsx +++ b/src/useForm/__demo__/index.tsx @@ -1,122 +1,120 @@ -import { Component, reactive, toRaw } from 'vue'; -// eslint-disable-next-line @typescript-eslint/no-unused-vars -import { Form, Input, Select } from 'ant-design-vue'; -import 'ant-design-vue/dist/antd.min.css'; -import useForm from '../index'; -export default { - setup() { - const modelRef = reactive({ - name1: '', - name2: '111', - obj: { - //嵌套数据 - test: [], - }, - }); - const rulesRef = reactive({ - name1: [ - { - required: true, - message: 'Please input Activity name', - }, - { - min: 3, - max: 5, - message: 'Length should be 3 to 5', - trigger: 'blur', - }, - ], - name2: [ - { - required: true, - message: 'Please input name2', - }, - ], - 'obj.test': [ - { - required: true, - message: 'Please select', - type: 'array', - }, - ], - }); - const { - resetFields, - validate, - validateInfos, - mergeValidateInfo, - clearValidate, - } = useForm(modelRef, rulesRef, { debounce: { wait: 300 } }); - const handleClick = e => { - e.preventDefault(); - validate() - .then(() => { - console.log(toRaw(modelRef)); - }) - .catch(err => { - console.log('error', err); - }); - }; - const handleReset = e => { - e.preventDefault(); - resetFields(); - }; - const clearValidateAll = () => { - clearValidate(); - }; - const clearValidateName1 = name => { - clearValidate(name); - }; - const handleResetWithValues = e => { - e.preventDefault(); - resetFields({ - name2: 'updated values', - }); - }; - return () => ( -
- - validate('name1')} /> - - - - - - - - - - - - - -
- ); - }, -} as Component; +import { Component, reactive, toRaw } from 'vue'; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { Form, Input, Select } from 'ant-design-vue'; +import 'ant-design-vue/dist/antd.min.css'; +import useForm from '../index'; +export default { + setup() { + const modelRef = reactive({ + name1: '', + name2: '111', + obj: { + //嵌套数据 + test: [], + }, + }); + const rulesRef = reactive({ + name1: [ + { + required: true, + message: 'Please input Activity name', + }, + { + min: 3, + max: 5, + message: 'Length should be 3 to 5', + trigger: 'blur', + }, + ], + name2: [ + { + required: true, + message: 'Please input name2', + }, + ], + 'obj.test': [ + { + required: true, + message: 'Please select', + type: 'array', + }, + ], + }); + const { resetFields, validate, validateInfos, mergeValidateInfo, clearValidate } = useForm( + modelRef, + rulesRef, + { debounce: { wait: 300 } }, + ); + const handleClick = (e) => { + e.preventDefault(); + validate() + .then(() => { + console.log(toRaw(modelRef)); + }) + .catch((err) => { + console.log('error', err); + }); + }; + const handleReset = (e) => { + e.preventDefault(); + resetFields(); + }; + const clearValidateAll = () => { + clearValidate(); + }; + const clearValidateName1 = (name) => { + clearValidate(name); + }; + const handleResetWithValues = (e) => { + e.preventDefault(); + resetFields({ + name2: 'updated values', + }); + }; + return () => ( +
+ + validate('name1')} /> + + + + + + + + + + + + + +
+ ); + }, +} as Component; diff --git a/src/useForm/index.ts b/src/useForm/index.ts index c3da300..8c94b2b 100644 --- a/src/useForm/index.ts +++ b/src/useForm/index.ts @@ -168,7 +168,7 @@ function useForm( const initialModel = cloneDeep(modelRef); let validateInfos: validateInfos = {}; - Object.keys(rulesRef).forEach(key => { + Object.keys(rulesRef).forEach((key) => { validateInfos[key] = { autoLink: false, required: isRequired(rulesRef[key]), @@ -182,7 +182,7 @@ function useForm( }); //modelRef = resetReactiveValue(initialModel, modelRef); nextTick(() => { - Object.keys(validateInfos).forEach(key => { + Object.keys(validateInfos).forEach((key) => { validateInfos[key] = { autoLink: false, required: isRequired(rulesRef[key]), @@ -194,7 +194,7 @@ function useForm( if (!trigger.length) { return rules; } else { - return rules.filter(rule => { + return rules.filter((rule) => { const triggerList = toArray(rule.trigger || 'change'); return intersection(triggerList, trigger).length; }); @@ -310,7 +310,7 @@ function useForm( } else { keys = [names]; } - keys.forEach(key => { + keys.forEach((key) => { validateInfos[key] && Object.assign(validateInfos[key], { validateStatus: '', @@ -337,7 +337,7 @@ function useForm( let oldModel = initialModel; const modelFn = (model: { [x: string]: any }) => { const names = []; - Object.keys(rulesRef).forEach(key => { + Object.keys(rulesRef).forEach((key) => { const prop = getPropByPath(model, key, false); const oldProp = getPropByPath(oldModel, key, false); if (!isEqual(prop.v, oldProp.v)) { diff --git a/src/useHover/__demo__/index.tsx b/src/useHover/__demo__/index.tsx index b189c80..2bb1987 100644 --- a/src/useHover/__demo__/index.tsx +++ b/src/useHover/__demo__/index.tsx @@ -1,24 +1,24 @@ -import { ref, Component } from 'vue'; -import useHover from '../index'; -export default { - setup() { - const eleRef = ref(null); - const [isHover] = useHover(eleRef, { - onEnter: () => { - console.log('enter'); - }, - }); - return { - eleRef, - isHover, - }; - }, - render(_ctx) { - return ( - <> -

move your mouse

-

{_ctx.isHover ? 'enter' : 'leave'}

- - ); - }, -} as Component; +import { ref, Component } from 'vue'; +import useHover from '../index'; +export default { + setup() { + const eleRef = ref(null); + const [isHover] = useHover(eleRef, { + onEnter: () => { + console.log('enter'); + }, + }); + return { + eleRef, + isHover, + }; + }, + render(_ctx) { + return ( + <> +

move your mouse

+

{_ctx.isHover ? 'enter' : 'leave'}

+ + ); + }, +} as Component; diff --git a/src/useHover/__tests__/index.spec.tsx b/src/useHover/__tests__/index.spec.tsx index 97ed4de..3f926ab 100644 --- a/src/useHover/__tests__/index.spec.tsx +++ b/src/useHover/__tests__/index.spec.tsx @@ -1,35 +1,35 @@ -/* eslint-disable @typescript-eslint/no-empty-function */ -import { shallowMount } from '@vue/test-utils'; -import useHover from '../index'; -import { ref } from 'vue'; - -describe('useHover', () => { - test('should work with custom event', async () => { - const onEnter = jest.fn(() => {}); - const onLeave = jest.fn(() => {}); - const wrapper = shallowMount({ - setup() { - const eleRef = ref(null); - const [isHover] = useHover(eleRef, { - onEnter, - onLeave, - }); - return { - eleRef, - isHover, - }; - }, - render() { - return

move your mouse

; - }, - }); - await wrapper.vm.$nextTick(); - wrapper.find('h1').trigger('mouseenter'); - expect(onEnter).toHaveBeenCalled(); - expect(wrapper.vm.isHover).toBe(true); - - wrapper.find('h1').trigger('mouseleave'); - expect(onLeave).toHaveBeenCalled(); - expect(wrapper.vm.isHover).toBe(false); - }); -}); +/* eslint-disable @typescript-eslint/no-empty-function */ +import { shallowMount } from '@vue/test-utils'; +import useHover from '../index'; +import { ref } from 'vue'; + +describe('useHover', () => { + test('should work with custom event', async () => { + const onEnter = jest.fn(() => {}); + const onLeave = jest.fn(() => {}); + const wrapper = shallowMount({ + setup() { + const eleRef = ref(null); + const [isHover] = useHover(eleRef, { + onEnter, + onLeave, + }); + return { + eleRef, + isHover, + }; + }, + render() { + return

move your mouse

; + }, + }); + await wrapper.vm.$nextTick(); + wrapper.find('h1').trigger('mouseenter'); + expect(onEnter).toHaveBeenCalled(); + expect(wrapper.vm.isHover).toBe(true); + + wrapper.find('h1').trigger('mouseleave'); + expect(onLeave).toHaveBeenCalled(); + expect(wrapper.vm.isHover).toBe(false); + }); +}); diff --git a/src/useHover/index.ts b/src/useHover/index.ts index 5420dfd..5fa9919 100644 --- a/src/useHover/index.ts +++ b/src/useHover/index.ts @@ -1,73 +1,73 @@ -import { ref, Ref, watch } from 'vue'; -export interface Options { - onEnter?: (e: MouseEvent) => void; - onLeave?: (e: MouseEvent) => void; -} - -type Action = { - actions: { - removelistener: () => void; - }; -}; - -/** - * useHover - * - * @param {Ref)} ele - * @param {Options} [options] - * @returns - */ -function useHover(target: Ref, options?: Options): [Ref, Action] { - if (!target) { - console.warn( - `fucntiuon useHover first parameter expect HTMLElement | Ref,bug got ${target}`, - ); - return; - } - const isHovering = ref(null); - const { onEnter, onLeave } = options || {}; - const onMouseEnter = (e: MouseEvent) => { - if (onEnter) { - onEnter(e); - } - isHovering.value = true; - }; - const onMouseLeave = (e: MouseEvent) => { - if (onLeave) { - onLeave(e); - } - isHovering.value = false; - }; - - const _addListeners = (ele: HTMLElement) => { - if (ele) { - ele.addEventListener('mouseenter', onMouseEnter); - ele.addEventListener('mouseleave', onMouseLeave); - } - }; - const _removeListeners = (ele: HTMLElement) => { - if (ele) { - ele.removeEventListener('mouseenter', onMouseEnter); - ele.removeEventListener('mouseleave', onMouseLeave); - } - }; - const removelistener = () => { - _removeListeners((target as Ref).value); - destoryWatcher(); - }; - const destoryWatcher = watch( - target as Ref, - (newValue, oldValue) => { - if (newValue) { - _addListeners(newValue); - } - if (oldValue) { - _removeListeners(oldValue); - } - }, - { flush: 'post' }, - ); - return [isHovering, { actions: { removelistener } }]; -} - -export default useHover; +import { ref, Ref, watch } from 'vue'; +export interface Options { + onEnter?: (e: MouseEvent) => void; + onLeave?: (e: MouseEvent) => void; +} + +type Action = { + actions: { + removelistener: () => void; + }; +}; + +/** + * useHover + * + * @param {Ref)} ele + * @param {Options} [options] + * @returns + */ +function useHover(target: Ref, options?: Options): [Ref, Action] { + if (!target) { + console.warn( + `fucntiuon useHover first parameter expect HTMLElement | Ref,bug got ${target}`, + ); + return; + } + const isHovering = ref(null); + const { onEnter, onLeave } = options || {}; + const onMouseEnter = (e: MouseEvent) => { + if (onEnter) { + onEnter(e); + } + isHovering.value = true; + }; + const onMouseLeave = (e: MouseEvent) => { + if (onLeave) { + onLeave(e); + } + isHovering.value = false; + }; + + const _addListeners = (ele: HTMLElement) => { + if (ele) { + ele.addEventListener('mouseenter', onMouseEnter); + ele.addEventListener('mouseleave', onMouseLeave); + } + }; + const _removeListeners = (ele: HTMLElement) => { + if (ele) { + ele.removeEventListener('mouseenter', onMouseEnter); + ele.removeEventListener('mouseleave', onMouseLeave); + } + }; + const removelistener = () => { + _removeListeners((target as Ref).value); + destoryWatcher(); + }; + const destoryWatcher = watch( + target as Ref, + (newValue, oldValue) => { + if (newValue) { + _addListeners(newValue); + } + if (oldValue) { + _removeListeners(oldValue); + } + }, + { flush: 'post' }, + ); + return [isHovering, { actions: { removelistener } }]; +} + +export default useHover; diff --git a/src/useInViewport/__demo__/index.tsx b/src/useInViewport/__demo__/index.tsx index 578245b..dd1124e 100644 --- a/src/useInViewport/__demo__/index.tsx +++ b/src/useInViewport/__demo__/index.tsx @@ -1,17 +1,17 @@ -import { Component, ref } from 'vue'; -import useInViewport from '../index'; -export default { - setup() { - const ele = ref(null); - const inViewPort = useInViewport(ele); - return { ele, inViewPort }; - }, - render: _ctx => ( -
-
observer dom
-
- {_ctx.inViewPort === null ? '' : _ctx.inViewPort ? 'visible' : 'hidden'} -
-
- ), -} as Component; +import { Component, ref } from 'vue'; +import useInViewport from '../index'; +export default { + setup() { + const ele = ref(null); + const inViewPort = useInViewport(ele); + return { ele, inViewPort }; + }, + render: (_ctx) => ( +
+
observer dom
+
+ {_ctx.inViewPort === null ? '' : _ctx.inViewPort ? 'visible' : 'hidden'} +
+
+ ), +} as Component; diff --git a/src/useInViewport/index.ts b/src/useInViewport/index.ts index 5e46c87..d2b9fca 100644 --- a/src/useInViewport/index.ts +++ b/src/useInViewport/index.ts @@ -1,27 +1,27 @@ -import { ref, Ref, watchEffect } from 'vue'; - -function useInViewport(target: Ref): Ref | Ref { - const inViewPort = ref(null); - let prevEl = null; - const observer = new IntersectionObserver(entries => { - for (const entry of entries) { - if (entry.isIntersecting) { - inViewPort.value = true; - } else { - inViewPort.value = false; - } - } - }); - watchEffect(() => { - if (prevEl) { - observer.disconnect(); - } - if (target.value) { - observer.observe((target as Ref).value); - } - prevEl = target.value; - }); - return inViewPort; -} - -export default useInViewport; +import { ref, Ref, watchEffect } from 'vue'; + +function useInViewport(target: Ref): Ref | Ref { + const inViewPort = ref(null); + let prevEl = null; + const observer = new IntersectionObserver((entries) => { + for (const entry of entries) { + if (entry.isIntersecting) { + inViewPort.value = true; + } else { + inViewPort.value = false; + } + } + }); + watchEffect(() => { + if (prevEl) { + observer.disconnect(); + } + if (target.value) { + observer.observe((target as Ref).value); + } + prevEl = target.value; + }); + return inViewPort; +} + +export default useInViewport; diff --git a/src/useReactiveRef/__demo__/index.tsx b/src/useReactiveRef/__demo__/index.tsx index ec1e18a..a0c6d09 100644 --- a/src/useReactiveRef/__demo__/index.tsx +++ b/src/useReactiveRef/__demo__/index.tsx @@ -1,21 +1,21 @@ -import { Component, ref, Ref, watchEffect } from 'vue'; -import useReactiveRef from '../index'; -export default { - setup() { - const [eleRef, setEle] = useReactiveRef(); - const flag = ref(true); - const toggle = () => { - flag.value = !flag.value; - }; - watchEffect(() => { - console.log((eleRef as Ref).value?.innerHTML); - }); - return () => ( - <> - - {flag.value ?

h1

: null} -

{(eleRef as Ref).value?.innerHTML}

- - ); - }, -} as Component; +import { Component, ref, Ref, watchEffect } from 'vue'; +import useReactiveRef from '../index'; +export default { + setup() { + const [eleRef, setEle] = useReactiveRef(); + const flag = ref(true); + const toggle = () => { + flag.value = !flag.value; + }; + watchEffect(() => { + console.log((eleRef as Ref).value?.innerHTML); + }); + return () => ( + <> + + {flag.value ?

h1

: null} +

{(eleRef as Ref).value?.innerHTML}

+ + ); + }, +} as Component; diff --git a/src/useReactiveRef/__test__/index.spec.tsx b/src/useReactiveRef/__test__/index.spec.tsx index 166d47a..4c2c809 100644 --- a/src/useReactiveRef/__test__/index.spec.tsx +++ b/src/useReactiveRef/__test__/index.spec.tsx @@ -1,25 +1,25 @@ -import { shallowMount } from '@vue/test-utils'; - -import useReactiveRef from '../index'; -import { ref } from 'vue'; - -describe('useReactiveRef', () => { - test('should work with custom event', async () => { - const [eleRef, setEle] = useReactiveRef(); - const showH1 = ref(false); - const wrapper = shallowMount({ - setup() { - return () => ( - <> - {showH1.value ?

: null} -

- - ); - }, - }); - expect(eleRef.value).toEqual(null); - showH1.value = true; - await wrapper.vm.$nextTick(); - expect(eleRef.value).toBe(wrapper.find('h1').element); - }); -}); +import { shallowMount } from '@vue/test-utils'; + +import useReactiveRef from '../index'; +import { ref } from 'vue'; + +describe('useReactiveRef', () => { + test('should work with custom event', async () => { + const [eleRef, setEle] = useReactiveRef(); + const showH1 = ref(false); + const wrapper = shallowMount({ + setup() { + return () => ( + <> + {showH1.value ?

: null} +

+ + ); + }, + }); + expect(eleRef.value).toEqual(null); + showH1.value = true; + await wrapper.vm.$nextTick(); + expect(eleRef.value).toBe(wrapper.find('h1').element); + }); +}); diff --git a/src/useReactiveRef/index.ts b/src/useReactiveRef/index.ts index 784c041..6dfad02 100644 --- a/src/useReactiveRef/index.ts +++ b/src/useReactiveRef/index.ts @@ -1,13 +1,13 @@ -import { ref, ComponentPublicInstance, Ref } from 'vue'; -type ElementType = HTMLElement | ComponentPublicInstance; -function useReactiveRef(): [Ref, (...args: any) => void] { - let prevEle = null as ElementType | null; - const eleRef = ref(prevEle); - function setEle(ele: HTMLElement) { - if (prevEle === ele) return; - prevEle = ele; - eleRef.value = prevEle; - } - return [eleRef, setEle]; -} -export default useReactiveRef; +import { ref, ComponentPublicInstance, Ref } from 'vue'; +type ElementType = HTMLElement | ComponentPublicInstance; +function useReactiveRef(): [Ref, (...args: any) => void] { + let prevEle = null as ElementType | null; + const eleRef = ref(prevEle); + function setEle(ele: HTMLElement) { + if (prevEle === ele) return; + prevEle = ele; + eleRef.value = prevEle; + } + return [eleRef, setEle]; +} +export default useReactiveRef; diff --git a/src/useScroll/__demo__/index.tsx b/src/useScroll/__demo__/index.tsx index acce038..d487ace 100644 --- a/src/useScroll/__demo__/index.tsx +++ b/src/useScroll/__demo__/index.tsx @@ -1,58 +1,58 @@ -import { Component, ref } from 'vue'; -import useScroll from '../index'; -export default { - setup() { - const eleRef = ref(null); - const scroll = useScroll(eleRef); - return { eleRef, scroll }; - }, - render(_ctx) { - return ( - <> -
{JSON.stringify(_ctx.scroll)}
-
-
- Lorem ipsum dolor sit amet, consectetur adipisicing elit. A aspernatur atque, debitis ex - excepturi explicabo iste iure labore molestiae neque optio perspiciatis -
-
- Aspernatur cupiditate, deleniti id incidunt mollitia omnis! A aspernatur assumenda - consequuntur culpa cumque dignissimos enim eos, et fugit natus nemo nesciunt -
-
- Alias aut deserunt expedita, inventore maiores minima officia porro rem. Accusamus - ducimus magni modi mollitia nihil nisi provident -
-
- Alias aut autem consequuntur doloremque esse facilis id molestiae neque officia placeat, - quia quisquam repellendus reprehenderit. -
-
- Adipisci blanditiis facere nam perspiciatis sit soluta ullam! Architecto aut blanditiis, - consectetur corporis cum deserunt distinctio dolore eius est exercitationem -
-
Ab aliquid asperiores assumenda corporis cumque dolorum expedita
-
- Culpa cumque eveniet natus totam! Adipisci, animi at commodi delectus distinctio dolore - earum, eum expedita facilis -
-
- Quod sit, temporibus! Amet animi fugit officiis perspiciatis, quis unde. Cumque - dignissimos distinctio, dolor eaque est fugit nisi non pariatur porro possimus, quas - quasi -
-
- - ); - }, -} as Component; +import { Component, ref } from 'vue'; +import useScroll from '../index'; +export default { + setup() { + const eleRef = ref(null); + const scroll = useScroll(eleRef); + return { eleRef, scroll }; + }, + render(_ctx) { + return ( + <> +
{JSON.stringify(_ctx.scroll)}
+
+
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. A aspernatur atque, debitis ex + excepturi explicabo iste iure labore molestiae neque optio perspiciatis +
+
+ Aspernatur cupiditate, deleniti id incidunt mollitia omnis! A aspernatur assumenda + consequuntur culpa cumque dignissimos enim eos, et fugit natus nemo nesciunt +
+
+ Alias aut deserunt expedita, inventore maiores minima officia porro rem. Accusamus + ducimus magni modi mollitia nihil nisi provident +
+
+ Alias aut autem consequuntur doloremque esse facilis id molestiae neque officia placeat, + quia quisquam repellendus reprehenderit. +
+
+ Adipisci blanditiis facere nam perspiciatis sit soluta ullam! Architecto aut blanditiis, + consectetur corporis cum deserunt distinctio dolore eius est exercitationem +
+
Ab aliquid asperiores assumenda corporis cumque dolorum expedita
+
+ Culpa cumque eveniet natus totam! Adipisci, animi at commodi delectus distinctio dolore + earum, eum expedita facilis +
+
+ Quod sit, temporibus! Amet animi fugit officiis perspiciatis, quis unde. Cumque + dignissimos distinctio, dolor eaque est fugit nisi non pariatur porro possimus, quas + quasi +
+
+ + ); + }, +} as Component; diff --git a/src/useScroll/__test__/index.spec.tsx b/src/useScroll/__test__/index.spec.tsx index ed6b95e..7e7f449 100644 --- a/src/useScroll/__test__/index.spec.tsx +++ b/src/useScroll/__test__/index.spec.tsx @@ -1,56 +1,56 @@ -import { mount } from '@vue/test-utils'; -import { ref } from 'vue'; -import useScroll from '../index'; - -describe('useScroll', () => { - it('define', async () => { - const elem = document.createElement('div'); - elem.style.height = '100px'; - if (document.body) { - document.body.appendChild(elem); - } - let scroll; - const wrapper = mount( - { - setup() { - scroll = useScroll(ref(elem)); - return {}; - }, - render() { - return

; - }, - }, - { - attachTo: elem, - }, - ); - await wrapper.vm.$nextTick(); - // elem did not trigger scroll - elem.scrollTop = 120; - await wrapper.vm.$nextTick(); - expect(scroll.value.left).toBe(0); - expect(scroll.value.top).toBe(0); - }); - // it('define2', async () => { - // const el = ref(null) - // const scroll = useScroll(el) - // const wrapper = mount({ - // setup() { - // return { el } - // }, - // render() { - // return ( - //
- //

sad

- //
- // ) - // } - // }) - // await wrapper.vm.$nextTick() - // el.value.scrollTop = 100 - // // elem did not trigger scroll - // await wrapper.vm.$nextTick() - // expect(scroll.value.left).toBe(0); - // expect(scroll.value.top).toBe(0); - // }); -}); +import { mount } from '@vue/test-utils'; +import { ref } from 'vue'; +import useScroll from '../index'; + +describe('useScroll', () => { + it('define', async () => { + const elem = document.createElement('div'); + elem.style.height = '100px'; + if (document.body) { + document.body.appendChild(elem); + } + let scroll; + const wrapper = mount( + { + setup() { + scroll = useScroll(ref(elem)); + return {}; + }, + render() { + return

; + }, + }, + { + attachTo: elem, + }, + ); + await wrapper.vm.$nextTick(); + // elem did not trigger scroll + elem.scrollTop = 120; + await wrapper.vm.$nextTick(); + expect(scroll.value.left).toBe(0); + expect(scroll.value.top).toBe(0); + }); + // it('define2', async () => { + // const el = ref(null) + // const scroll = useScroll(el) + // const wrapper = mount({ + // setup() { + // return { el } + // }, + // render() { + // return ( + //
+ //

sad

+ //
+ // ) + // } + // }) + // await wrapper.vm.$nextTick() + // el.value.scrollTop = 100 + // // elem did not trigger scroll + // await wrapper.vm.$nextTick() + // expect(scroll.value.left).toBe(0); + // expect(scroll.value.top).toBe(0); + // }); +}); diff --git a/src/useScroll/index.ts b/src/useScroll/index.ts index b2b9d8e..e1f5bef 100644 --- a/src/useScroll/index.ts +++ b/src/useScroll/index.ts @@ -1,35 +1,35 @@ -import { Ref, ref } from 'vue'; -import useEventListener from '../useEventListener'; -interface Position { - left: number; - top: number; -} -export default function useScroll(target: Ref): Ref { - const position = ref({ left: 0, top: 0 } as Position); - const updatePosition = (currentTarget: HTMLElement | Document) => { - let newPosition; - if (currentTarget === document) { - if (!document.scrollingElement) return; - newPosition = { - left: document.scrollingElement.scrollLeft, - top: document.scrollingElement.scrollTop, - }; - } else { - newPosition = { - left: (currentTarget as HTMLElement).scrollLeft, - top: (currentTarget as HTMLElement).scrollTop, - }; - } - position.value = newPosition; - }; - const listener = (event: Event) => { - if (!event.target) return; - updatePosition(event.target as HTMLElement | Document); - }; - useEventListener(target as Ref, { - type: 'scroll', - listener, - }); - - return position; -} +import { Ref, ref } from 'vue'; +import useEventListener from '../useEventListener'; +interface Position { + left: number; + top: number; +} +export default function useScroll(target: Ref): Ref { + const position = ref({ left: 0, top: 0 } as Position); + const updatePosition = (currentTarget: HTMLElement | Document) => { + let newPosition; + if (currentTarget === document) { + if (!document.scrollingElement) return; + newPosition = { + left: document.scrollingElement.scrollLeft, + top: document.scrollingElement.scrollTop, + }; + } else { + newPosition = { + left: (currentTarget as HTMLElement).scrollLeft, + top: (currentTarget as HTMLElement).scrollTop, + }; + } + position.value = newPosition; + }; + const listener = (event: Event) => { + if (!event.target) return; + updatePosition(event.target as HTMLElement | Document); + }; + useEventListener(target as Ref, { + type: 'scroll', + listener, + }); + + return position; +} diff --git a/src/useSize/__demo__/index.tsx b/src/useSize/__demo__/index.tsx index 82ec2f5..54c6a72 100644 --- a/src/useSize/__demo__/index.tsx +++ b/src/useSize/__demo__/index.tsx @@ -1,13 +1,13 @@ -import { Component } from 'vue'; -import useSize from '../index'; -export default { - setup() { - const [size, elRef] = useSize(); - return () => ( -
- try to resize the preview window
- dimensions -- width: {size.width} px, height: {size.height} px -
- ); - }, -} as Component; +import { Component } from 'vue'; +import useSize from '../index'; +export default { + setup() { + const [size, elRef] = useSize(); + return () => ( +
+ try to resize the preview window
+ dimensions -- width: {size.width} px, height: {size.height} px +
+ ); + }, +} as Component; diff --git a/src/useSize/index.ts b/src/useSize/index.ts index 12b155a..27d48bc 100644 --- a/src/useSize/index.ts +++ b/src/useSize/index.ts @@ -1,37 +1,37 @@ -import { Ref, reactive, onMounted, watch, ref } from 'vue'; -import ResizeObserver from 'resize-observer-polyfill'; - -type Size = { width?: number; height?: number }; - -function useSize(target?: Ref): [Size, Ref] { - const elRef = target || ref(null); - const state = reactive({ - width: ((elRef || {}) as HTMLElement).clientWidth, - height: ((elRef || {}) as HTMLElement).clientHeight, - }); - onMounted(() => { - let resizeObserver = null; - watch( - elRef, - (el, preElm, onInvalidate) => { - if (!el) return; - resizeObserver && resizeObserver.disconnect(); - resizeObserver = new ResizeObserver(entries => { - entries.forEach(entry => { - state.width = entry.target.clientWidth; - state.height = entry.target.clientHeight; - }); - }); - resizeObserver.observe(el as HTMLElement); - onInvalidate(() => { - resizeObserver && resizeObserver.disconnect(); - }); - }, - { immediate: true }, - ); - }); - - return [state, elRef]; -} - -export default useSize; +import { Ref, reactive, onMounted, watch, ref } from 'vue'; +import ResizeObserver from 'resize-observer-polyfill'; + +type Size = { width?: number; height?: number }; + +function useSize(target?: Ref): [Size, Ref] { + const elRef = target || ref(null); + const state = reactive({ + width: ((elRef || {}) as HTMLElement).clientWidth, + height: ((elRef || {}) as HTMLElement).clientHeight, + }); + onMounted(() => { + let resizeObserver = null; + watch( + elRef, + (el, preElm, onInvalidate) => { + if (!el) return; + resizeObserver && resizeObserver.disconnect(); + resizeObserver = new ResizeObserver((entries) => { + entries.forEach((entry) => { + state.width = entry.target.clientWidth; + state.height = entry.target.clientHeight; + }); + }); + resizeObserver.observe(el as HTMLElement); + onInvalidate(() => { + resizeObserver && resizeObserver.disconnect(); + }); + }, + { immediate: true }, + ); + }); + + return [state, elRef]; +} + +export default useSize; diff --git a/src/useToggle/__demo__/index.tsx b/src/useToggle/__demo__/index.tsx index 8417e68..2c42b09 100644 --- a/src/useToggle/__demo__/index.tsx +++ b/src/useToggle/__demo__/index.tsx @@ -1,32 +1,32 @@ -import { Component } from 'vue'; -import useToggle from '../index'; -export default { - setup() { - const [toggleRef, { toggle, setLeft, setRight }] = useToggle(); - return { - toggleRef, - toggle, - setLeft, - setRight, - }; - }, - render: _ctx => { - return ( -
-

Effects:{_ctx.toggleRef.toString()}

-

- - - -

-
- ); - }, -} as Component; +import { Component } from 'vue'; +import useToggle from '../index'; +export default { + setup() { + const [toggleRef, { toggle, setLeft, setRight }] = useToggle(); + return { + toggleRef, + toggle, + setLeft, + setRight, + }; + }, + render: (_ctx) => { + return ( +
+

Effects:{_ctx.toggleRef.toString()}

+

+ + + +

+
+ ); + }, +} as Component; diff --git a/src/useToggle/__test__/index.spec.ts b/src/useToggle/__test__/index.spec.ts index b8ae2b8..e74df39 100644 --- a/src/useToggle/__test__/index.spec.ts +++ b/src/useToggle/__test__/index.spec.ts @@ -1,14 +1,14 @@ -import useToggle from '../index'; - -describe('useToggle', () => { - test('default', async () => { - const [state, { toggle, setLeft, setRight }] = useToggle(); - expect(state.value).toBe(false); - toggle(); - expect(state.value).toBe(true); - setLeft(); - expect(state.value).toBe(false); - setRight(); - expect(state.value).toBe(true); - }); -}); +import useToggle from '../index'; + +describe('useToggle', () => { + test('default', async () => { + const [state, { toggle, setLeft, setRight }] = useToggle(); + expect(state.value).toBe(false); + toggle(); + expect(state.value).toBe(true); + setLeft(); + expect(state.value).toBe(false); + setRight(); + expect(state.value).toBe(true); + }); +}); diff --git a/src/useToggle/index.ts b/src/useToggle/index.ts index aa372e9..79acc11 100644 --- a/src/useToggle/index.ts +++ b/src/useToggle/index.ts @@ -1,52 +1,52 @@ -import { ref, Ref } from 'vue'; -type IState = string | number | boolean | undefined; - -export interface Actions { - setLeft: () => void; - setRight: () => void; - toggle: (value?: T) => void; -} - -function useToggle(): [Ref, Actions]; - -function useToggle(defaultValue: T): [Ref, Actions]; - -function useToggle( - defaultValue: T, - reverseValue: U, -): [T | U, Actions]; - -function useToggle( - defaultValue: D = false as D, - reverseValue?: R | boolean, -): [Ref, Actions] { - reverseValue = reverseValue === undefined ? !defaultValue : reverseValue; - const stateRef = ref(defaultValue) as Ref; - function toggle(value?: D | R) { - if (value === undefined) { - stateRef.value = stateRef.value === defaultValue ? reverseValue : defaultValue; - return; - } - if (value === defaultValue || value === reverseValue) { - stateRef.value = value; - } else { - stateRef.value = stateRef.value === defaultValue ? reverseValue : defaultValue; - console.warn(`Function toggle parameter must be ${defaultValue} or ${reverseValue}`); - } - return; - } - function setLeft() { - stateRef.value = defaultValue; - } - function setRight() { - stateRef.value = reverseValue; - } - const actions = { - toggle, - setLeft, - setRight, - }; - return [stateRef, actions]; -} - -export default useToggle; +import { ref, Ref } from 'vue'; +type IState = string | number | boolean | undefined; + +export interface Actions { + setLeft: () => void; + setRight: () => void; + toggle: (value?: T) => void; +} + +function useToggle(): [Ref, Actions]; + +function useToggle(defaultValue: T): [Ref, Actions]; + +function useToggle( + defaultValue: T, + reverseValue: U, +): [T | U, Actions]; + +function useToggle( + defaultValue: D = false as D, + reverseValue?: R | boolean, +): [Ref, Actions] { + reverseValue = reverseValue === undefined ? !defaultValue : reverseValue; + const stateRef = ref(defaultValue) as Ref; + function toggle(value?: D | R) { + if (value === undefined) { + stateRef.value = stateRef.value === defaultValue ? reverseValue : defaultValue; + return; + } + if (value === defaultValue || value === reverseValue) { + stateRef.value = value; + } else { + stateRef.value = stateRef.value === defaultValue ? reverseValue : defaultValue; + console.warn(`Function toggle parameter must be ${defaultValue} or ${reverseValue}`); + } + return; + } + function setLeft() { + stateRef.value = defaultValue; + } + function setRight() { + stateRef.value = reverseValue; + } + const actions = { + toggle, + setLeft, + setRight, + }; + return [stateRef, actions]; +} + +export default useToggle; diff --git a/src/utils/testingHelpers.ts b/src/utils/testingHelpers.ts index 9cf58f3..1626ac6 100644 --- a/src/utils/testingHelpers.ts +++ b/src/utils/testingHelpers.ts @@ -1,5 +1,5 @@ export function sleep(time: number): Promise { - return new Promise(resolve => { + return new Promise((resolve) => { setTimeout(() => { resolve(true); }, time); diff --git a/src/utils/typeHelpers.ts b/src/utils/typeHelpers.ts index dba6224..6beb75d 100644 --- a/src/utils/typeHelpers.ts +++ b/src/utils/typeHelpers.ts @@ -1,7 +1,7 @@ -import { ComponentPublicInstance } from 'vue'; -export type ElementType = Element | ComponentPublicInstance; -export function isComponentPublicInstance( - instance: ElementType, -): instance is ComponentPublicInstance { - return (instance as ComponentPublicInstance).$ !== undefined; -} +import { ComponentPublicInstance } from 'vue'; +export type ElementType = Element | ComponentPublicInstance; +export function isComponentPublicInstance( + instance: ElementType, +): instance is ComponentPublicInstance { + return (instance as ComponentPublicInstance).$ !== undefined; +}