Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.0.0 #7

Merged
merged 5 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}
3 changes: 3 additions & 0 deletions dev/Readonly.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ export const Component: React.FC = () => {
<div>
<mark>renderCount: {renderCount}</mark>
<pre>shallowReadonlyObject = {JSON.stringify(shallowReadonlyObject, null, 2)}</pre>
{/* @ts-ignore */}
<button onClick={() => shallowReadonlyObject.data++}>shallowReadonlyObject.data++</button>
<button onClick={() => shallowReadonlyObject.nested.data++}>shallowReadonlyObject.nested.data++</button>
<hr />
<pre>readonlyObject = {JSON.stringify(readonlyObject, null, 2)}</pre>
{/* @ts-ignore */}
<button onClick={() => readonlyObject.data++}>readonlyObject.data++</button>
{/* @ts-ignore */}
<button onClick={() => readonlyObject.nested.data++}>readonlyObject.nested.data++</button>
</div>
)
Expand Down
8 changes: 4 additions & 4 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",
"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"
},
"devDependencies": {
"@eslint/js": "^9.x",
Expand All @@ -64,14 +64,14 @@
"eslint-config-prettier": "^9.x",
"eslint-plugin-prettier": "^5.x",
"globals": "^15.9.0",
"jsdom": "^24.x",
"happy-dom": "^15.x",
"prettier": "^3.x",
"react": "^18.x",
"react-dom": "^18.x",
"typescript": "^5.5.4",
"typescript-eslint": "^8.x",
"vite": "^5.x",
"vite-plugin-dts": "^4.0.3",
"vite-plugin-dts": "^4.1.0",
"vitest": "^2.x"
}
}
1,018 changes: 335 additions & 683 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

45 changes: 0 additions & 45 deletions src/_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,48 +10,3 @@ export type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N

export const increment = (s: number) => s + 1
export const useForceUpdate = () => useReducer(increment, 0)[1]

// compare whether a value has changed, accounting for NaN.
export const hasChanged = (value: any, oldValue: any): boolean => {
return value !== oldValue && (value === value || oldValue === oldValue)
}

export const isArray = Array.isArray
export const objectToString = Object.prototype.toString
export const toTypeString = (value: unknown): string => {
return objectToString.call(value)
}
export const isMap = (value: unknown): value is Map<any, any> => {
return toTypeString(value) === '[object Map]'
}
export const isSet = (value: unknown): value is Set<any> => {
return toTypeString(value) === '[object Set]'
}
export const isDate = (value: unknown): value is Date => {
return value instanceof Date
}
export const isFunction = (value: unknown): value is (...args: any[]) => any => {
return typeof value === 'function'
}
export const isString = (value: unknown): value is string => {
return typeof value === 'string'
}
export const isSymbol = (value: unknown): value is symbol => {
return typeof value === 'symbol'
}
export const isObject = (value: unknown): value is Record<any, any> => {
return value !== null && typeof value === 'object'
}
export const isPlainObject = (value: unknown): value is object => {
return toTypeString(value) === '[object Object]'
}
export const isPromise = <T = any>(value: unknown): value is Promise<T> => {
return isObject(value) && isFunction(value.then) && isFunction(value.catch)
}

export const removeArrayItem = <T>(array: T[], element: T) => {
const i = array.indexOf(element)
if (i > -1) {
array.splice(i, 1)
}
}
14 changes: 7 additions & 7 deletions src/computed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
*/

import { useState as useReactState } from 'react'
import { useWatch } from './watch/watch'
import { useForceUpdate } from './_utils'
import { computed as vComputed } from '@vue/reactivity'
import { computed as vueComputed } from '@vue/reactivity'
import type {
ComputedGetter,
DebuggerOptions,
ComputedRef,
WritableComputedOptions,
ComputedGetter,
WritableComputedRef,
WritableComputedOptions,
DebuggerOptions,
} from '@vue/reactivity'
import { useWatch } from './watch'
import { useForceUpdate } from './_utils'

/**
* Takes a getter function and returns a readonly reactive ref object for the
Expand Down Expand Up @@ -55,7 +55,7 @@ export function useComputed<T, S = T>(
debugOptions?: DebuggerOptions,
): WritableComputedRef<T, S>
export function useComputed(arg1: any, arg2: any) {
const [value] = useReactState(() => vComputed(arg1, arg2))
const [value] = useReactState(() => vueComputed(arg1, arg2))
const forceUpdate = useForceUpdate()
useWatch(value, forceUpdate)
return value
Expand Down
6 changes: 3 additions & 3 deletions src/effectScope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import { useState as useReactState, useRef as useReactRef, useCallback as useReactCallback } from 'react'
import { effectScope } from '@vue/reactivity'
import { effectScope as vueEffectScope } from '@vue/reactivity'
import { ArgumentTypes } from './_utils'

/**
Expand All @@ -16,9 +16,9 @@ import { ArgumentTypes } from './_utils'
* @param detached - Can be used to create a "detached" effect scope.
* @see {@link https://vuejs.org/api/reactivity-advanced.html#effectscope Vue `effectScope()`}
*/
export function useEffectScope(...args: ArgumentTypes<typeof effectScope>) {
export function useEffectScope(...args: ArgumentTypes<typeof vueEffectScope>) {
const hasRun = useReactRef(false)
const [scope] = useReactState(() => effectScope(...args))
const [scope] = useReactState(() => vueEffectScope(...args))
const originalRunRef = useReactRef(scope.run)
const runFn = useReactCallback(<T>(fn: () => T) => {
if (!hasRun.current) {
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
10 changes: 5 additions & 5 deletions src/reactive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
*/

import { useState as useReactState } from 'react'
import { useWatch } from './watch/watch'
import { useForceUpdate } from './_utils'
import { reactive as vReactive, shallowReactive as vShallowReactive } from '@vue/reactivity'
import { reactive as vueReactive, shallowReactive as vueShallowReactive } from '@vue/reactivity'
import type { Reactive, ShallowReactive } from '@vue/reactivity'
import { useWatch } from './watch'
import { useForceUpdate } from './_utils'

/**
* Returns a reactive proxy of the object.
Expand All @@ -26,7 +26,7 @@ import type { Reactive, ShallowReactive } from '@vue/reactivity'
*/
export function useReactive<T extends object>(target: T): Reactive<T>
export function useReactive(target: object) {
const [value] = useReactState(() => vReactive(target))
const [value] = useReactState(() => vueReactive(target))
const forceUpdate = useForceUpdate()
useWatch(value, forceUpdate)
return value
Expand Down Expand Up @@ -63,7 +63,7 @@ export function useReactive(target: object) {
* ```
*/
export function useShallowReactive<T extends object>(target: T): ShallowReactive<T> {
const [value] = useReactState(() => vShallowReactive(target))
const [value] = useReactState(() => vueShallowReactive(target))
const forceUpdate = useForceUpdate()
useWatch(value, forceUpdate)
return value
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
10 changes: 5 additions & 5 deletions src/readonly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
*/

import { useState as useReactState } from 'react'
import { useWatch } from './watch/watch'
import { useForceUpdate } from './_utils'
import { readonly as vReadonly, shallowReadonly as vShallowReadonly } from '@vue/reactivity'
import { readonly as vueReadonly, shallowReadonly as vueShallowReadonly } from '@vue/reactivity'
import type { DeepReadonly, UnwrapNestedRefs } from '@vue/reactivity'
import { useWatch } from './watch'
import { useForceUpdate } from './_utils'

/**
* Takes an object (reactive or plain) or a ref and returns a readonly proxy to
Expand Down Expand Up @@ -38,7 +38,7 @@ import type { DeepReadonly, UnwrapNestedRefs } from '@vue/reactivity'
* ```
*/
export function useReadonly<T extends object>(target: T): DeepReadonly<UnwrapNestedRefs<T>> {
const [value] = useReactState(() => vReadonly(target))
const [value] = useReactState(() => vueReadonly(target))
const forceUpdate = useForceUpdate()
useWatch(value, forceUpdate)
return value
Expand Down Expand Up @@ -78,7 +78,7 @@ export function useReadonly<T extends object>(target: T): DeepReadonly<UnwrapNes
* ```
*/
export function useShallowReadonly<T extends object>(target: T): Readonly<T> {
const [value] = useReactState(() => vShallowReadonly(target))
const [value] = useReactState(() => vueShallowReadonly(target))
const forceUpdate = useForceUpdate()
useWatch(value, forceUpdate)
return value
Expand Down
24 changes: 12 additions & 12 deletions src/ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
*/

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

/**
* Takes an inner value and returns a reactive and mutable ref object, which
Expand All @@ -30,10 +30,10 @@ export function useRef<T>(
): [T] extends [Ref] ? IfAny<T, Ref<T>, T> : Ref<UnwrapRef<T>, UnwrapRef<T> | T>
export function useRef<T = any>(): Ref<T | undefined>
export function useRef(initValue?: unknown) {
const [refObj] = useReactState(() => vRef(initValue))
const [refObject] = useReactState(() => vueRef(initValue))
const forceUpdate = useForceUpdate()
useWatch(refObj, forceUpdate, { deep: true })
return refObj as unknown as any
useWatch(refObject, forceUpdate, { deep: true })
return refObject as unknown as any
}

/**
Expand All @@ -56,10 +56,10 @@ export function useShallowRef<T>(
): Ref extends T ? (T extends Ref ? IfAny<T, ShallowRef<T>, T> : ShallowRef<T>) : ShallowRef<T>
export function useShallowRef<T = any>(): ShallowRef<T | undefined>
export function useShallowRef(initValue?: unknown) {
const [sRefObj] = useReactState(() => vShallowRef(initValue))
const [shallowRefObject] = useReactState(() => vueShallowRef(initValue))
const forceUpdate = useForceUpdate()
useWatch(sRefObj, forceUpdate)
return sRefObj
useWatch(shallowRefObject, forceUpdate)
return shallowRefObject
}

/**
Expand All @@ -70,8 +70,8 @@ export function useShallowRef(initValue?: unknown) {
* @see {@link https://vuejs.org/api/reactivity-advanced.html#customref Vue `customRef()`}
*/
export function useCustomRef<T>(factory: CustomRefFactory<T>): Ref<T> {
const [cRefObj] = useReactState(() => vCustomRef(factory))
const [customRefObject] = useReactState(() => vueCustomRef(factory))
const forceUpdate = useForceUpdate()
useWatch(cRefObj, forceUpdate)
return cRefObj
useWatch(customRefObject, forceUpdate)
return customRefObject
}
Loading
Loading