Skip to content

Commit

Permalink
Merge branch 'main' into fix/reactiveComputed-type
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Jul 30, 2023
2 parents 8f8136d + a32ae73 commit d9984a8
Show file tree
Hide file tree
Showing 76 changed files with 2,180 additions and 1,549 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ module.exports = {
'import/default': 'off',
'import/no-named-as-default': 'off',
'import/no-named-as-default-member': 'off',
'@typescript-eslint/ban-types': 'off',
'n/prefer-global/process': 'off',
},
overrides: [
{
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ on:
- main
- next

merge_group: {}

jobs:
lint:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -41,7 +43,7 @@ jobs:

strategy:
matrix:
node: [16.x, 18.x]
node: [16.x, 18.x, 20.x]
fail-fast: false

steps:
Expand Down
5 changes: 2 additions & 3 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
[build.environment]
NPM_FLAGS = "--version"
NODE_OPTIONS = "--max_old_space_size=4096"
NODE_VERSION = "16"
NODE_VERSION = "18"

[build]
publish = "packages/.vitepress/dist"
command = "npx pnpm i --store=node_modules/.pnpm-store && npm run install-fonts && npm run docs:build"
command = "pnpm run install-fonts && pnpm run docs:build"

[[redirects]]
from = "https://vueuse.js.org/*"
Expand Down
54 changes: 27 additions & 27 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@vueuse/monorepo",
"version": "10.2.1",
"private": true,
"packageManager": "pnpm@8.6.5",
"packageManager": "pnpm@8.6.10",
"description": "Collection of essential Vue Composition Utilities",
"author": "Anthony Fu<https://github.com/antfu>",
"license": "MIT",
Expand All @@ -11,7 +11,7 @@
"build:redirects": "esno scripts/redirects.ts",
"build:rollup": "NODE_OPTIONS=\"--max-old-space-size=6144\" rollup -c",
"build:types": "tsc --emitDeclarationOnly && nr types:fix",
"clean": "rimraf dist types \"packages/*/dist\"",
"clean": "rimraf --glob dist types \"packages/*/dist\"",
"dev": "nr update && nr docs",
"docs": "vue-demi-switch 3 && vitepress dev packages --open",
"docs:build": "nr update:full && vitepress build packages && nr build:redirects && esno scripts/post-docs.ts",
Expand All @@ -35,37 +35,37 @@
"watch": "esno scripts/build.ts --watch"
},
"devDependencies": {
"@antfu/eslint-config": "^0.39.5",
"@antfu/ni": "^0.21.4",
"@antfu/eslint-config": "^0.39.8",
"@antfu/ni": "^0.21.5",
"@iconify/json": "^2.2.84",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-replace": "^5.0.2",
"@type-challenges/utils": "^0.1.1",
"@types/fs-extra": "^11.0.1",
"@types/js-yaml": "^4.0.5",
"@types/md5": "^2.3.2",
"@types/node": "^20.3.2",
"@types/node": "^20.4.4",
"@types/prettier": "^2.7.3",
"@types/remove-markdown": "^0.3.1",
"@types/semver": "^7.5.0",
"@vitest/coverage-c8": "^0.32.2",
"@vitest/ui": "^0.32.2",
"@vitest/coverage-c8": "^0.33.0",
"@vitest/ui": "^0.33.0",
"@vue/compiler-sfc": "^3.3.4",
"@vue/test-utils": "^2.4.0",
"@vue/test-utils": "^2.4.1",
"@vueuse/core": "workspace:*",
"@vueuse/integrations": "workspace:*",
"@vueuse/math": "workspace:*",
"@vueuse/rxjs": "workspace:*",
"@vueuse/shared": "workspace:*",
"axios": "^1.4.0",
"bumpp": "^9.1.1",
"consola": "^3.2.2",
"consola": "^3.2.3",
"esbuild-register": "^3.4.2",
"eslint": "8.39.0",
"esno": "^0.16.3",
"eslint": "8.45.0",
"esno": "^0.17.0",
"export-size": "^0.5.2",
"fake-indexeddb": "^4.0.1",
"fast-glob": "^3.2.12",
"fake-indexeddb": "^4.0.2",
"fast-glob": "^3.3.1",
"firebase": "^9.23.0",
"fs-extra": "^11.1.1",
"fuse.js": "^6.6.2",
Expand All @@ -80,31 +80,31 @@
"node-fetch": "^3.3.1",
"node-fetch-native": "^1.2.0",
"ohmyfetch": "^0.4.21",
"pnpm": "^8.6.5",
"postcss": "^8.4.24",
"pnpm": "^8.6.10",
"postcss": "^8.4.27",
"postcss-nested": "^6.0.1",
"prettier": "^2.8.8",
"prism-theme-vars": "^0.2.4",
"remove-markdown": "^0.5.0",
"rimraf": "^5.0.1",
"rollup": "^3.25.3",
"rollup": "^3.26.3",
"rollup-plugin-dts": "^5.3.0",
"rollup-plugin-esbuild": "^5.0.0",
"rollup-plugin-pure": "^0.1.1",
"sharp": "0.32.1",
"sharp": "0.32.4",
"simple-git": "^3.19.1",
"simple-git-hooks": "^2.8.1",
"taze": "^0.10.2",
"typescript": "5.1.5",
"unocss": "^0.53.4",
"unplugin-icons": "^0.16.3",
"simple-git-hooks": "^2.9.0",
"taze": "^0.11.2",
"typescript": "5.1.6",
"unocss": "^0.53.6",
"unplugin-icons": "^0.16.5",
"unplugin-vue-components": "^0.25.1",
"vite": "^4.3.9",
"vite-plugin-inspect": "^0.7.29",
"vite": "^4.4.7",
"vite-plugin-inspect": "^0.7.33",
"vite-plugin-pwa": "^0.16.4",
"vitepress": "1.0.0-beta.3",
"vitest": "^0.32.2",
"vue": "^3.2.47",
"vitepress": "1.0.0-beta.6",
"vitest": "^0.33.0",
"vue": "^3.3.4",
"vue2": "npm:vue@^2.7.14"
},
"pnpm": {
Expand Down
1 change: 1 addition & 0 deletions packages/.test/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import process from 'node:process'
import './polyfillFetch'

export const isBelowNode18 = Number(process.version.slice(1).split('.')[0]) < 18
Expand Down
1 change: 1 addition & 0 deletions packages/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const Links = [

const Learn = [
{ text: 'Premium Video Course', link: 'https://vueschool.io/courses/vueuse-for-everyone?friend=vueuse' },
{ text: 'Official Vue Certification', link: 'https://certification.vuejs.org/?utm_source=vueuse&utm_medium=website&utm_campaign=affiliate&utm_content=guide&banner_type=text&friend=VUEUSE' },
]

const DefaultSideBar = [
Expand Down
33 changes: 33 additions & 0 deletions packages/core/createReusableTemplate/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,22 @@ describe.skipIf(isVue2)('createReusableTemplate', () => {
expect(wrapper.text()).toBe('{"msg":"Foo"}{"msg":"Bar"}')
})

it('attrs', () => {
const [DefineFoo, ReuseFoo] = createReusableTemplate()

const wrapper = mount({
render() {
return h(Fragment, null, [
h(DefineFoo, () => h('div', { class: 'foo' })),
h(ReuseFoo, { id: 'bar', class: 'bar' }),
])
},
})

expect(wrapper.get('#bar')).toBeDefined()
expect(wrapper.get('#bar').classes()).toEqual(['foo', 'bar'])
})

it('slots', () => {
const [DefineFoo, ReuseFoo] = createReusableTemplate<{ msg: string }, { default: Slot }>()

Expand All @@ -80,4 +96,21 @@ describe.skipIf(isVue2)('createReusableTemplate', () => {

expect(wrapper.text()).toBe('GoodbyeHi')
})

it('hyphen props', () => {
const [DefineFoo, ReuseFoo] = createReusableTemplate<{ myMsg: string }>()

const wrapper = mount({
render() {
return h(Fragment, null, [
h(DefineFoo, ({ $slots, ...args }: any) => h('pre', JSON.stringify(args))),
h(ReuseFoo, { myMsg: 'Foo' }),
// @ts-expect-error Vue automatically converts hyphenized props to camelCase
h(ReuseFoo, { 'my-msg': 'Bar' }),
])
},
})

expect(wrapper.text()).toBe('{"myMsg":"Foo"}{"myMsg":"Bar"}')
})
})
31 changes: 27 additions & 4 deletions packages/core/createReusableTemplate/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { DefineComponent, Slot } from 'vue-demi'
import { defineComponent, isVue3, shallowRef, version } from 'vue-demi'
import { makeDestructurable } from '@vueuse/shared'
import { camelize, makeDestructurable } from '@vueuse/shared'

export type DefineTemplateComponent<
Bindings extends object,
Expand All @@ -27,6 +27,15 @@ export type ReusableTemplatePair<
reuse: ReuseTemplateComponent<Bindings, Slots>
}

export interface CreateReusableTemplateOptions {
/**
* Inherit attrs from reuse component.
*
* @default true
*/
inheritAttrs?: boolean
}

/**
* This function creates `define` and `reuse` components in pair,
* It also allow to pass a generic to bind with type.
Expand All @@ -36,7 +45,9 @@ export type ReusableTemplatePair<
export function createReusableTemplate<
Bindings extends object,
Slots extends Record<string, Slot | undefined> = Record<string, Slot | undefined>,
>(): ReusableTemplatePair<Bindings, Slots> {
>(
options: CreateReusableTemplateOptions = {},
): ReusableTemplatePair<Bindings, Slots> {
// compatibility: Vue 2.7 or above
if (!isVue3 && !version.startsWith('2.7.')) {
if (process.env.NODE_ENV !== 'production')
Expand All @@ -45,6 +56,10 @@ export function createReusableTemplate<
return
}

const {
inheritAttrs = true,
} = options

const render = shallowRef<Slot | undefined>()

const define = defineComponent({
Expand All @@ -56,12 +71,13 @@ export function createReusableTemplate<
}) as DefineTemplateComponent<Bindings, Slots>

const reuse = defineComponent({
inheritAttrs: false,
inheritAttrs,
setup(_, { attrs, slots }) {
return () => {
if (!render.value && process.env.NODE_ENV !== 'production')
throw new Error('[VueUse] Failed to find the definition of reusable template')
return render.value?.({ ...attrs, $slots: slots })
const vnode = render.value?.({ ...keysToCamelKebabCase(attrs), $slots: slots })
return (inheritAttrs && vnode?.length === 1) ? vnode[0] : vnode
}
},
}) as ReuseTemplateComponent<Bindings, Slots>
Expand All @@ -71,3 +87,10 @@ export function createReusableTemplate<
[define, reuse],
) as any
}

function keysToCamelKebabCase(obj: Record<string, any>) {
const newObj: typeof obj = {}
for (const key in obj)
newObj[camelize(key)] = obj[key]
return newObj
}
1 change: 1 addition & 0 deletions packages/core/onClickOutside/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export function onClickOutside<T extends OnClickOutsideOptions>(
_iOSWorkaround = true
Array.from(window.document.body.children)
.forEach(el => el.addEventListener('click', noop))
window.document.documentElement.addEventListener('click', noop)
}

let shouldListen = true
Expand Down
3 changes: 1 addition & 2 deletions packages/core/onLongPress/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,5 @@ export function onLongPress(
}

useEventListener(elementRef, 'pointerdown', onDown, listenerOptions)
useEventListener(elementRef, 'pointerup', clear, listenerOptions)
useEventListener(elementRef, 'pointerleave', clear, listenerOptions)
useEventListener(elementRef, ['pointerup', 'pointerleave'], clear, listenerOptions)
}
4 changes: 1 addition & 3 deletions packages/core/useAnimate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,7 @@ export function useAnimate(
onReady?.(animate.value)
}

useEventListener(animate, 'cancel', syncPause)
useEventListener(animate, 'finish', syncPause)
useEventListener(animate, 'remove', syncPause)
useEventListener(animate, ['cancel', 'finish', 'remove'], syncPause)

const { resume: resumeRef, pause: pauseRef } = useRafFn(() => {
if (!animate.value)
Expand Down
2 changes: 1 addition & 1 deletion packages/core/useAsyncQueue/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function useAsyncQueue<T = any>(tasks: UseAsyncQueueTask<any>[], options:
rejected: 'rejected',
}

const initialResult = Array.from(new Array(tasks.length), () => ({ state: promiseState.pending, data: null }))
const initialResult = Array.from(Array.from({ length: tasks.length }), () => ({ state: promiseState.pending, data: null }))

const result = reactive(initialResult) as UseAsyncQueueResult<T>[]

Expand Down
3 changes: 1 addition & 2 deletions packages/core/useBattery/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ export function useBattery({ navigator = defaultNavigator }: ConfigurableNavigat
.then((_battery) => {
battery = _battery
updateBatteryInfo.call(battery)
for (const event of events)
useEventListener(battery, event, updateBatteryInfo, { passive: true })
useEventListener(battery, events, updateBatteryInfo, { passive: true })
})
}

Expand Down
8 changes: 2 additions & 6 deletions packages/core/useClipboard/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type { MaybeRefOrGetter } from '@vueuse/shared'
import { toValue, useTimeoutFn } from '@vueuse/shared'
import type { ComputedRef, Ref } from 'vue-demi'
import { computed, ref } from 'vue-demi'
import type { WindowEventName } from '../useEventListener'
import { useEventListener } from '../useEventListener'
import { useSupported } from '../useSupported'
import type { ConfigurableNavigator } from '../_configurable'
Expand Down Expand Up @@ -62,7 +61,6 @@ export function useClipboard(options: UseClipboardOptions<MaybeRefOrGetter<strin
legacy = false,
} = options

const events = ['copy', 'cut']
const isClipboardApiSupported = useSupported(() => (navigator && 'clipboard' in navigator))
const isSupported = computed(() => isClipboardApiSupported.value || legacy)
const text = ref('')
Expand All @@ -80,10 +78,8 @@ export function useClipboard(options: UseClipboardOptions<MaybeRefOrGetter<strin
}
}

if (isSupported.value && read) {
for (const event of events)
useEventListener(event as WindowEventName, updateText)
}
if (isSupported.value && read)
useEventListener(['copy', 'cut'], updateText)

async function copy(value = toValue(source)) {
if (isSupported.value && value != null) {
Expand Down
22 changes: 20 additions & 2 deletions packages/core/useEventListener/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,25 @@ export function useEventListener<E extends keyof DocumentEventMap>(
/**
* Register using addEventListener on mounted, and removeEventListener automatically on unmounted.
*
* Overload 4: Custom event target with event type infer
* Overload 4: Explicitly HTMLElement target
*
* @see https://vueuse.org/useEventListener
* @param target
* @param event
* @param listener
* @param options
*/
export function useEventListener<E extends keyof HTMLElementEventMap>(
target: MaybeRefOrGetter<HTMLElement | null | undefined>,
event: Arrayable<E>,
listener: (this: HTMLElement, ev: HTMLElementEventMap[E]) => any,
options?: boolean | AddEventListenerOptions
): () => void

/**
* Register using addEventListener on mounted, and removeEventListener automatically on unmounted.
*
* Overload 5: Custom event target with event type infer
*
* @see https://vueuse.org/useEventListener
* @param target
Expand All @@ -90,7 +108,7 @@ export function useEventListener<Names extends string, EventType = Event>(
/**
* Register using addEventListener on mounted, and removeEventListener automatically on unmounted.
*
* Overload 5: Custom event target fallback
* Overload 6: Custom event target fallback
*
* @see https://vueuse.org/useEventListener
* @param target
Expand Down

0 comments on commit d9984a8

Please sign in to comment.