Skip to content

Commit

Permalink
feat: v1.0.0-rc.1
Browse files Browse the repository at this point in the history
  • Loading branch information
surmon-china committed Aug 30, 2024
1 parent 6f6151a commit 56b3ab6
Show file tree
Hide file tree
Showing 17 changed files with 506 additions and 385 deletions.
9 changes: 2 additions & 7 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.detectIndentation": false,
"editor.formatOnSave": true,
"editor.formatOnType": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"typescript.tsdk": "node_modules/typescript/lib"
"editor.formatOnSave": true
}
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "veact",
"version": "1.0.0-beta.2",
"version": "1.0.0-rc.1",
"description": "Mutable state enhancer library for React by @vue/reactivity",
"keywords": [
"React",
Expand Down Expand Up @@ -50,7 +50,7 @@
"react-dom": "^16.8.0 || ^17 || ^18 || ^19"
},
"dependencies": {
"@vue/reactivity": "^3.5.0-beta.2"
"@vue/reactivity": "^3.5.0-rc.1"
},
"devDependencies": {
"@eslint/js": "^9.x",
Expand All @@ -64,7 +64,7 @@
"eslint-config-prettier": "^9.x",
"eslint-plugin-prettier": "^5.x",
"globals": "^15.9.0",
"jsdom": "^24.x",
"jsdom": "^25.x",
"prettier": "^3.x",
"react": "^18.x",
"react-dom": "^18.x",
Expand Down
656 changes: 298 additions & 358 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/computed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import { useState as useReactState } from 'react'
import { useWatch } from './watch/watch'
import { useWatch } from './watch'
import { useForceUpdate } from './_utils'
import { computed as vComputed } from '@vue/reactivity'
import type {
Expand Down
12 changes: 5 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

// redirect all APIs from @vue/reactivity
export * from '@vue/reactivity'
export { watch as baseWatch } from '@vue/reactivity'

// lifecycle hooks
export { onMounted, onUpdated, onBeforeUnmount } from './lifecycle'
Expand All @@ -22,15 +23,12 @@ export { useReadonly, useShallowReadonly } from './readonly'
export { useComputed } from './computed'

// watch and hooks
export { watch, useWatch } from './watch/watch'
export type { WatchOptions, WatchSource, MultiWatchSources, WatchCallback } from './watch/watch'
export { watch, useWatch } from './watch'
export type { WatchOptions, MultiWatchSources } from './watch'

// watchEffect and hooks
export { watchEffect, useWatchEffect } from './watch/watchEffect'
export type { WatchEffect, WatchEffectOptions } from './watch/watchEffect'

// watch handle
export type { WatchStopHandle, WatchHandle } from './watch/type'
export { watchEffect, useWatchEffect } from './watchEffect'
export type { WatchEffectOptions } from './watchEffect'

// effectScope hooks
export { useEffectScope } from './effectScope'
Expand Down
2 changes: 1 addition & 1 deletion src/reactive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import { useState as useReactState } from 'react'
import { useWatch } from './watch/watch'
import { useWatch } from './watch'
import { useForceUpdate } from './_utils'
import { reactive as vReactive, shallowReactive as vShallowReactive } from '@vue/reactivity'
import type { Reactive, ShallowReactive } from '@vue/reactivity'
Expand Down
2 changes: 1 addition & 1 deletion src/reactivity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @author Surmon <https://github.com/surmon-china>
*/

import { useWatch } from './watch/watch'
import { useWatch } from './watch'
import { useForceUpdate } from './_utils'

/**
Expand Down
2 changes: 1 addition & 1 deletion src/readonly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import { useState as useReactState } from 'react'
import { useWatch } from './watch/watch'
import { useWatch } from './watch'
import { useForceUpdate } from './_utils'
import { readonly as vReadonly, shallowReadonly as vShallowReadonly } from '@vue/reactivity'
import type { DeepReadonly, UnwrapNestedRefs } from '@vue/reactivity'
Expand Down
2 changes: 1 addition & 1 deletion src/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { useState as useReactState } from 'react'
import { useForceUpdate, IfAny } from './_utils'
import { useWatch } from './watch/watch'
import { useWatch } from './watch'
import { ref as vRef, shallowRef as vShallowRef, customRef as vCustomRef } from '@vue/reactivity'
import type { Ref, UnwrapRef, ShallowRef, CustomRefFactory } from '@vue/reactivity'

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
121 changes: 121 additions & 0 deletions src/watch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/**
* @module veact.watch
* @author Surmon <https://github.com/surmon-china>
*/

import { useState as useReactState } from 'react'
import { watch as vueWatch } from '@vue/reactivity'
import type {
ReactiveMarker,
DebuggerOptions,
WatchCallback,
WatchSource,
WatchHandle,
} from '@vue/reactivity'
import { onBeforeUnmount } from './lifecycle'
import { logger } from './_logger'

// changelog: https://github.com/vuejs/core/blob/main/CHANGELOG.md
// https://github.com/vuejs/core/blob/main/packages/runtime-core/src/apiWatch.ts
// https://github.com/vuejs/core/blob/main/packages/reactivity/src/watch.ts

export interface WatchOptions<Immediate = boolean> extends DebuggerOptions {
immediate?: Immediate
deep?: boolean | number
once?: boolean
// The `flush` option is not supported in react at the moment.
// flush?: 'pre' | 'post' | 'sync'
}

export type MultiWatchSources = (WatchSource<unknown> | object)[]

type MaybeUndefined<T, I> = I extends true ? T | undefined : T
type MapSources<T, Immediate> = {
[K in keyof T]: T[K] extends WatchSource<infer V>
? MaybeUndefined<V, Immediate>
: T[K] extends object
? MaybeUndefined<T[K], Immediate>
: never
}

/**
* Watches one or more reactive data sources and invokes a callback function when the sources change.
*
* @param source - The watcher's source.
* @param callback - This function will be called when the source is changed.
* @param options - An optional options object that does not support the `flush` option compared to Vue (3.5.0).
* @see {@link https://vuejs.org/api/reactivity-core.html#watch Vue `watch()`}
*
* @example
* ```js
* const count = ref(0)
* watch(count, (count, prevCount) => {
* // ...
* })
* ```
*/

// overload: single source + cb
export function watch<T, Immediate extends Readonly<boolean> = false>(
source: WatchSource<T>,
callback: WatchCallback<T, MaybeUndefined<T, Immediate>>,
options?: WatchOptions<Immediate>,
): WatchHandle

// overload: reactive array or tuple of multiple sources + cb
export function watch<T extends Readonly<MultiWatchSources>, Immediate extends Readonly<boolean> = false>(
sources: readonly [...T] | T,
callback: [T] extends [ReactiveMarker]
? WatchCallback<T, MaybeUndefined<T, Immediate>>
: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
options?: WatchOptions<Immediate>,
): WatchHandle

// overload: array of multiple sources + cb
export function watch<T extends MultiWatchSources, Immediate extends Readonly<boolean> = false>(
sources: [...T],
callback: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
options?: WatchOptions<Immediate>,
): WatchHandle

// overload: watching reactive object w/ cb
export function watch<T extends object, Immediate extends Readonly<boolean> = false>(
source: T,
callback: WatchCallback<T, MaybeUndefined<T, Immediate>>,
options?: WatchOptions<Immediate>,
): WatchHandle

// implementation
export function watch<T = any, Immediate extends Readonly<boolean> = false>(
source: T | WatchSource<T>,
callback: WatchCallback<T>,
options: WatchOptions<Immediate> = {},
): WatchHandle {
return vueWatch(source as any, callback, {
...options,
onWarn: logger.warn,
scheduler: (job) => job(),
})
}

/**
* Watches one or more reactive data sources and invokes a callback function when the sources change.
*
* @param source - The watcher's source.
* @param callback - This function will be called when the source is changed.
* @param options - An optional options object that does not support the `flush` option compared to Vue (3.5.0).
* @see {@link https://vuejs.org/api/reactivity-core.html#watch Vue `watch()`}
*
* @example
* ```js
* const count = useRef(0)
* useWatch(count, (count, prevCount) => {
* // ...
* })
* ```
*/
export const useWatch: typeof watch = (source: any, callback: any, options = {}) => {
const [watchHandle] = useReactState(() => watch(source as any, callback, options))
onBeforeUnmount(() => watchHandle.stop())
return watchHandle
}
64 changes: 64 additions & 0 deletions src/watchEffect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* @module veact.watchEffect
* @author Surmon <https://github.com/surmon-china>
*/

import { useState as useReactState } from 'react'
import { watch as vueWatch } from '@vue/reactivity'
import type { WatchEffect, WatchHandle, DebuggerOptions } from '@vue/reactivity'
import { onBeforeUnmount } from './lifecycle'
import { logger } from './_logger'

// changelog: https://github.com/vuejs/core/blob/main/CHANGELOG.md
// https://github.com/vuejs/core/blob/main/packages/runtime-core/src/apiWatch.ts
// https://github.com/vuejs/core/blob/main/packages/reactivity/src/watch.ts

export type WatchEffectOptions = DebuggerOptions

/**
* Runs a function immediately while reactively tracking its dependencies and re-runs it whenever the dependencies are changed.
*
* @param effectFn - The effect function to run.
* @param options - An optional options object that can be used to adjust the effect's flush timing or to debug the effect's dependencies; the `flush` option is not supported compared to Vue (3.5.0).
* @see {@link https://vuejs.org/api/reactivity-core.html#watcheffect Vue `watchEffect()`}
*
* @example
* ```js
* const count = ref(0)
* watchEffect(() => console.log(count.value))
* // -> logs 0
*
* count.value++
* // -> logs 1
* ```
*/
export function watchEffect(effectFn: WatchEffect, options: WatchEffectOptions = {}): WatchHandle {
return vueWatch(effectFn, null, {
...options,
onWarn: logger.warn,
scheduler: (job) => job(),
})
}

/**
* Runs a function immediately while reactively tracking its dependencies and re-runs it whenever the dependencies are changed.
*
* @param effect - The effect function to run.
* @param options - An optional options object that can be used to adjust the effect's flush timing or to debug the effect's dependencies; the `flush` option is not supported compared to Vue (3.5.0).
* @see {@link https://vuejs.org/api/reactivity-core.html#watcheffect Vue `watchEffect()`}
*
* @example
* ```js
* const count = useRef(0)
* useWatchEffect(() => console.log(count.value))
* // -> logs 0
*
* count.value++
* // -> logs 1
* ```
*/
export const useWatchEffect: typeof watchEffect = (effect: any, options?: any) => {
const [watchHandle] = useReactState(() => watchEffect(effect, options))
onBeforeUnmount(() => watchHandle.stop())
return watchHandle
}
11 changes: 7 additions & 4 deletions tests/apis.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ import {
} from '../src'

test('<exports> should be export all @vue/reactivity members', () => {
expect(vueReactivity.watch).toBe(veact.baseWatch)
expect(
Object.keys(vueReactivity).every((key) => {
const targetMember = veact[key]
return targetMember && vueReactivity[key] === targetMember
}),
Object.keys(vueReactivity)
.filter((key) => key !== 'watch')
.every((key) => {
const targetMember = (veact as any)[key]
return targetMember && (vueReactivity as any)[key] === targetMember
}),
).toBeTruthy()
})

Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
"noImplicitReturns": true,
"outDir": "dist"
},
"exclude": ["node_modules", "dist", "dev", "tests"]
"exclude": ["node_modules", "dist"]
}

0 comments on commit 56b3ab6

Please sign in to comment.