Skip to content

Commit

Permalink
feat(computedInject): new function (#571)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
MinatoHikari and antfu committed Jul 5, 2021
1 parent 476eba1 commit 408e269
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 2 deletions.
7 changes: 7 additions & 0 deletions indexes.json
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,13 @@
"category": "Utilities",
"description": "a ref which will be reset to the default value after some time"
},
{
"name": "computedInject",
"package": "core",
"docs": "https://vueuse.org/core/computedInject/",
"category": "Component",
"description": "combine computed and inject"
},
{
"name": "createGlobalState",
"package": "core",
Expand Down
25 changes: 24 additions & 1 deletion packages/.test/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineComponent, createApp, h } from 'vue-demi'
import { defineComponent, createApp, h, provide, ref, InjectionKey, Ref } from 'vue-demi';

type InstanceType<V> = V extends { new (...arg: any[]): infer X } ? X : never
type VM<V> = InstanceType<V> & { unmount(): void }
Expand All @@ -24,3 +24,26 @@ export function useSetup<V>(setup: () => V) {

return mount(Comp)
}

export const Key: InjectionKey<Ref<number>> = Symbol('num')

export function useInjectedSetup<V>(setup: () => V) {
const Comp = defineComponent({
setup,
render() {
return h('div', [])
},
})

const Provider = defineComponent({
components: Comp,
setup() {
provide(Key, ref(1))
},
render() {
return h('div', [])
},
})

return mount(Provider)
}
15 changes: 15 additions & 0 deletions packages/core/computedInject/demo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script setup lang="ts">
import { provide, ref } from 'vue-demi'
import Receiver, { ArrayKey } from './demoReceiver.vue'
const array = ref([{ key: 1, value: '1' }, { key: 2, value: '2' }, { key: 3, value: '3' }])
provide(ArrayKey, array)
</script>

<template>
<div>
<p>Array: {{ array }}</p>
<Receiver />
</div>
</template>
32 changes: 32 additions & 0 deletions packages/core/computedInject/demoReceiver.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<template>
<div>ComputedArr: {{ computedArr }}</div>
</template>

<script lang="ts">
import { InjectionKey, Ref, defineComponent, ref } from 'vue-demi'
import { computedInject } from './index'
type OptionsRef = Ref<{ key: number; value: string }[]>
export const ArrayKey: InjectionKey<OptionsRef> = Symbol('array')
export default defineComponent({
name: 'DemoProvider',
setup() {
const computedArr = computedInject(ArrayKey, (source) => {
if (!source) return ref([]) as OptionsRef
const arr = [...source.value]
arr.unshift({ key: 0, value: 'all' })
return arr
})
return {
computedArr,
}
},
})
</script>

<style scoped>
</style>
84 changes: 84 additions & 0 deletions packages/core/computedInject/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
category: Component
---

# computedInject

Combine computed and inject

## Usage

In Provider Component
```ts
import { InjectionKey, provide, Ref, ref } from 'vue-demi';

export const ArrayKey: InjectionKey<Ref<{ key: number, value: string }[]>> = Symbol()

const array = ref([{ key: 1, value: '1' }, { key: 2, value: '2' }, { key: 3, value: '3' }])

provide(ArrayKey, array)
```

In Receiver Component
```ts
import { computedInject } from '@vueuse/core'

import { ArrayKey } from "./provider"

const computedArray = computedInject(ArrayKey, (source) => {
const arr = [...source.value]
arr.unshift({ key: 0, value: 'all' })
return arr
})
```


<!--FOOTER_STARTS-->
## Type Declarations

```typescript
export declare type ComputedInjectGetter<T, K> = (
source: T | undefined,
ctx?: any
) => K
export declare type ComputedInjectGetterWithDefault<T, K> = (
source: T,
ctx?: any
) => K
export declare type ComputedInjectSetter<T> = (v: T) => void
export interface WritableComputedInjectOptions<T, K> {
get: ComputedInjectGetter<T, K>
set: ComputedInjectSetter<K>
}
export interface WritableComputedInjectOptionsWithDefault<T, K> {
get: ComputedInjectGetterWithDefault<T, K>
set: ComputedInjectSetter<K>
}
export declare function computedInject<T, K = any>(
key: InjectionKey<T> | string,
getter: ComputedInjectGetter<T, K>
): ComputedRef<K | undefined>
export declare function computedInject<T, K = any>(
key: InjectionKey<T> | string,
options: WritableComputedInjectOptions<T, K>
): ComputedRef<K | undefined>
export declare function computedInject<T, K = any>(
key: InjectionKey<T> | string,
getter: ComputedInjectGetterWithDefault<T, K>,
defaultSource: T,
treatDefaultAsFactory?: false
): ComputedRef<K>
export declare function computedInject<T, K = any>(
key: InjectionKey<T> | string,
options: WritableComputedInjectOptionsWithDefault<T, K>,
defaultSource: T | (() => T),
treatDefaultAsFactory: true
): ComputedRef<K>
```

## Source

[Source](https://github.com/vueuse/vueuse/blob/main/packages/core/computedInject/index.ts) • [Demo](https://github.com/vueuse/vueuse/blob/main/packages/core/computedInject/demo.vue) • [Docs](https://github.com/vueuse/vueuse/blob/main/packages/core/computedInject/index.md)


<!--FOOTER_ENDS-->
23 changes: 23 additions & 0 deletions packages/core/computedInject/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useInjectedSetup, Key } from '../../.test'
import { ref } from 'vue-demi'
import { computedInject } from '.'

describe('useCounter', () => {
it('should be defined', () => {
expect(computedInject).toBeDefined()
})

it('should be computedRef', () => {
useInjectedSetup(() => {
const computedNum = computedInject(Key, (source) => {
if (source) return source.value + 1
})
const anotherComputedNum = computedInject(Key, (source) => {
if (source) return source.value + 10
}, ref(10))

expect(computedNum.value).toBe(2)
expect(anotherComputedNum.value).toBe(11)
})
})
})
58 changes: 58 additions & 0 deletions packages/core/computedInject/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { computed, inject, ComputedRef, InjectionKey } from 'vue-demi'

export type ComputedInjectGetter<T, K> = (source: T | undefined, ctx?: any) => K
export type ComputedInjectGetterWithDefault<T, K> = (source: T, ctx?: any) => K
export type ComputedInjectSetter<T> = (v: T) => void

export interface WritableComputedInjectOptions<T, K> {
get: ComputedInjectGetter<T, K>
set: ComputedInjectSetter<K>
}

export interface WritableComputedInjectOptionsWithDefault<T, K> {
get: ComputedInjectGetterWithDefault<T, K>
set: ComputedInjectSetter<K>
}

export function computedInject<T, K = any>(
key: InjectionKey<T> | string,
getter: ComputedInjectGetter<T, K>
): ComputedRef<K | undefined>
export function computedInject<T, K = any>(
key: InjectionKey<T> | string,
options: WritableComputedInjectOptions<T, K>
): ComputedRef<K | undefined>
export function computedInject<T, K = any>(
key: InjectionKey<T> | string,
getter: ComputedInjectGetterWithDefault<T, K>,
defaultSource: T,
treatDefaultAsFactory?: false
): ComputedRef<K>
export function computedInject<T, K = any>(
key: InjectionKey<T> | string,
options: WritableComputedInjectOptionsWithDefault<T, K>,
defaultSource: T | (() => T),
treatDefaultAsFactory: true
): ComputedRef<K>
export function computedInject<T, K = any>(
key: InjectionKey<T> | string,
options: ComputedInjectGetter<T, K> | WritableComputedInjectOptions<T, K>,
defaultSource?: T | (() => T),
treatDefaultAsFactory?: boolean,
) {
let source = inject(key) as T | undefined
if (defaultSource)
source = inject(key, defaultSource) as T
if (treatDefaultAsFactory)
source = inject(key, defaultSource, treatDefaultAsFactory) as T

if (typeof options === 'function') {
return computed(ctx => options(source, ctx))
}
else {
return computed({
get: ctx => options.get(source, ctx),
set: options.set,
})
}
}
1 change: 1 addition & 0 deletions packages/core/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './asyncComputed'
export * from './autoResetRef'
export * from './computedInject'
export * from './createGlobalState'
export * from './onClickOutside'
export * from './onKeyStroke'
Expand Down
6 changes: 6 additions & 0 deletions packages/core/useMousePressed/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ export interface MousePressedOptions extends ConfigurableWindow {
* @default true
*/
touch?: boolean
/**
* Listen to `dragstart` `drop` and `dragend` events
*
* @default true
*/
drag?: boolean
/**
* Initial values
*
Expand Down
2 changes: 1 addition & 1 deletion packages/core/usePointerSwipe/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export interface PointerSwipeReturn {
* @param options
*/
export declare function usePointerSwipe(
target: MaybeRef<Element | null | undefined>,
target: MaybeRef<HTMLElement | null | undefined>,
options?: PointerSwipeOptions
): PointerSwipeReturn
```
Expand Down
1 change: 1 addition & 0 deletions packages/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
- [`useUrlSearchParams`](https://vueuse.org/core/useUrlSearchParams/) — reactive [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)

### Component
- [`computedInject`](https://vueuse.org/core/computedInject/) — combine computed and inject
- [`templateRef`](https://vueuse.org/core/templateRef/) — shorthand for binding ref to template element
- [`tryOnMounted`](https://vueuse.org/shared/tryOnMounted/) — safe `onMounted`
- [`tryOnUnmounted`](https://vueuse.org/shared/tryOnUnmounted/) — safe `onUnmounted`
Expand Down

0 comments on commit 408e269

Please sign in to comment.