Skip to content

Commit

Permalink
formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
wobsoriano committed Feb 7, 2024
1 parent 93e2e22 commit 4bd6a75
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 81 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"prepublishOnly": "pnpm build",
"format": "prettier --ignore-path .gitignore -w \"src/**/*.{js,ts,json,css,tsx,jsx}\"",
"lint": "concurrently pnpm:lint:*",
"lint:code": "eslint --ignore-path .gitignore --max-warnings 0 src/**/*.{js,ts,tsx,jsx}",
"lint:code": "eslint --ignore-path .gitignore --max-warnings 0 \"src/**/*.{js,ts,json,css,tsx,jsx}\"",
"lint:types": "tsc --noEmit",
"update-deps": "pnpm up -Li"
},
Expand Down
55 changes: 25 additions & 30 deletions src/createWithSignal.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,51 @@
import type { Accessor } from 'solid-js';
import { createSignal, onCleanup } from 'solid-js';
import type {
StateCreator,
StoreApi,
} from 'zustand/vanilla';
import { createStore as createZustandStore } from 'zustand/vanilla';
import type { Create, ExtractState, IsFunction } from './types';
import type { Accessor } from 'solid-js'
import { createSignal, onCleanup } from 'solid-js'
import type { StateCreator, StoreApi } from 'zustand/vanilla'
import { createStore as createZustandStore } from 'zustand/vanilla'
import type { Create, ExtractState, IsFunction } from './types'

export function useStore<S extends StoreApi<unknown>>(api: S): ExtractState<S> extends IsFunction<ExtractState<S>> ? ExtractState<S> : Accessor<ExtractState<S>>;
export function useStore<S extends StoreApi<unknown>>(
api: S,
): ExtractState<S> extends IsFunction<ExtractState<S>> ? ExtractState<S> : Accessor<ExtractState<S>>

export function useStore<S extends StoreApi<unknown>, U>(
api: S,
selector: (state: ExtractState<S>) => U,
equalityFn?: (a: U, b: U) => boolean
): U extends IsFunction<U> ? U : Accessor<U>;
equalityFn?: (a: U, b: U) => boolean,
): U extends IsFunction<U> ? U : Accessor<U>

export function useStore<TState extends object, StateSlice>(
api: StoreApi<TState>,
selector: (state: TState) => StateSlice = api.getState as any,
equalityFn?: (a: StateSlice, b: StateSlice) => boolean,
) {
const initialValue = selector(api.getState());
const initialValue = selector(api.getState())

if (typeof initialValue === 'function')
return initialValue;
if (typeof initialValue === 'function') return initialValue

const options: Parameters<typeof createSignal>[1] = {};
if (equalityFn)
options.equals = equalityFn as any;
const options: Parameters<typeof createSignal>[1] = {}
if (equalityFn) options.equals = equalityFn as any

const [signal, setSignal] = createSignal(initialValue, options);
const [signal, setSignal] = createSignal(initialValue, options)

const unsubscribe = api.subscribe(setSignal);
onCleanup(() => unsubscribe());
const unsubscribe = api.subscribe(setSignal)
onCleanup(() => unsubscribe())

return signal;
return signal
}

function createImpl<T extends object>(createState: StateCreator<T, [], []>) {
const api
= typeof createState === 'function' ? createZustandStore(createState) : createState;
const api = typeof createState === 'function' ? createZustandStore(createState) : createState

const useBoundStore: any = (selector?: any, equalityFn?: any) =>
useStore(api, selector, equalityFn);
useStore(api, selector, equalityFn)

Object.assign(useBoundStore, api);
Object.assign(useBoundStore, api)

return useBoundStore;
return useBoundStore
}

const create = (<T extends object>(
createState: StateCreator<T, [], []> | undefined,
) => (createState ? createImpl(createState) : createImpl)) as Create<'signal'>;
const create = (<T extends object>(createState: StateCreator<T, [], []> | undefined) =>
createState ? createImpl(createState) : createImpl) as Create<'signal'>

export default create;
export default create
59 changes: 26 additions & 33 deletions src/createWithStore.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,53 @@
import { createStore, reconcile } from 'solid-js/store';
import { onCleanup } from 'solid-js';
import type {
StateCreator,
StoreApi,
} from 'zustand/vanilla';
import { createStore as createZustandStore } from 'zustand/vanilla';
import type { Create, ExtractState } from './types';
import { createStore, reconcile } from 'solid-js/store'
import { onCleanup } from 'solid-js'
import type { StateCreator, StoreApi } from 'zustand/vanilla'
import { createStore as createZustandStore } from 'zustand/vanilla'
import type { Create, ExtractState } from './types'

export function useStore<S extends StoreApi<unknown>>(api: S): ExtractState<S>;
export function useStore<S extends StoreApi<unknown>>(api: S): ExtractState<S>

export function useStore<S extends StoreApi<unknown>, U>(
api: S,
selector: (state: ExtractState<S>) => U,
equalityFn?: (a: U, b: U) => boolean
): U;
equalityFn?: (a: U, b: U) => boolean,
): U

export function useStore<TState extends object, StateSlice>(
api: StoreApi<TState>,
selector: (state: TState) => StateSlice = api.getState as any,
equalityFn?: (a: StateSlice, b: StateSlice) => boolean,
) {
const initialValue = selector(api.getState()) as any;
const [state, setState] = createStore(initialValue);
const initialValue = selector(api.getState()) as any
const [state, setState] = createStore(initialValue)

const listener = (nextState: TState, previousState: TState) => {
const prevStateSlice = selector(previousState);
const nextStateSlice = selector(nextState);
const prevStateSlice = selector(previousState)
const nextStateSlice = selector(nextState)

if (equalityFn !== undefined) {
if (!equalityFn(prevStateSlice, nextStateSlice))
setState(reconcile(nextStateSlice));
if (!equalityFn(prevStateSlice, nextStateSlice)) setState(reconcile(nextStateSlice))
} else {
setState(reconcile(nextStateSlice))
}
else {
setState(reconcile(nextStateSlice));
}
};
}

const unsubscribe = api.subscribe(listener);
onCleanup(() => unsubscribe());
return state;
const unsubscribe = api.subscribe(listener)
onCleanup(() => unsubscribe())
return state
}

function createImpl<T extends object>(createState: StateCreator<T, [], []>) {
const api
= typeof createState === 'function' ? createZustandStore(createState) : createState;
const api = typeof createState === 'function' ? createZustandStore(createState) : createState

const useBoundStore: any = (selector?: any, equalityFn?: any) =>
useStore(api, selector, equalityFn);
useStore(api, selector, equalityFn)

Object.assign(useBoundStore, api);
Object.assign(useBoundStore, api)

return useBoundStore;
return useBoundStore
}

const create = (<T extends object>(
createState: StateCreator<T, [], []> | undefined,
) => (createState ? createImpl(createState) : createImpl)) as Create<'store'>;
const create = (<T extends object>(createState: StateCreator<T, [], []> | undefined) =>
createState ? createImpl(createState) : createImpl) as Create<'store'>

export default create;
export default create
13 changes: 5 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import createWithSignal from './createWithSignal';
import createWithStore from './createWithStore';
import createWithSignal from './createWithSignal'
import createWithStore from './createWithStore'

const create = createWithStore;
const create = createWithStore

export {
createWithSignal,
createWithStore,
};
export { createWithSignal, createWithStore }

export default create;
export default create
22 changes: 13 additions & 9 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import type { Accessor } from 'solid-js';
import type { Mutate, StateCreator, StoreApi, StoreMutatorIdentifier } from 'zustand/vanilla';
import type { Accessor } from 'solid-js'
import type { Mutate, StateCreator, StoreApi, StoreMutatorIdentifier } from 'zustand/vanilla'

export type ExtractState<S> = S extends { getState: () => infer T } ? T : never;
export type ExtractState<S> = S extends { getState: () => infer T } ? T : never

export type IsFunction<T> = T extends (...args: any[]) => any ? T : never;
export type IsFunction<T> = T extends (...args: any[]) => any ? T : never

export type UseBoundStore<S extends StoreApi<unknown>, P extends 'store' | 'signal'> = {
(): P extends 'store' ? ExtractState<S> : ExtractState<S> extends IsFunction<ExtractState<S>> ? ExtractState<S> : Accessor<ExtractState<S>>
(): P extends 'store'
? ExtractState<S>
: ExtractState<S> extends IsFunction<ExtractState<S>>
? ExtractState<S>
: Accessor<ExtractState<S>>
<U>(
selector: (state: ExtractState<S>) => U,
equals?: (a: U, b: U) => boolean
equals?: (a: U, b: U) => boolean,
): P extends 'store' ? U : U extends IsFunction<U> ? U : Accessor<U>
} & S;
} & S

export interface Create<P extends 'store' | 'signal'> {
<T extends object, Mos extends [StoreMutatorIdentifier, unknown][] = []>(
initializer: StateCreator<T, [], Mos>
initializer: StateCreator<T, [], Mos>,
): UseBoundStore<Mutate<StoreApi<T>, Mos>, P>
<T extends object>(): <Mos extends [StoreMutatorIdentifier, unknown][] = []>(
initializer: StateCreator<T, [], Mos>
initializer: StateCreator<T, [], Mos>,
) => UseBoundStore<Mutate<StoreApi<T>, Mos>, P>
<S extends StoreApi<unknown>>(store: S): UseBoundStore<S, P>
}

0 comments on commit 4bd6a75

Please sign in to comment.