Skip to content

Commit

Permalink
shave some bytes (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
charkour authored Apr 15, 2023
1 parent e27c85f commit 2f5965c
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 53 deletions.
3 changes: 2 additions & 1 deletion packages/zundo/__tests__/options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ describe('Middleware options', () => {
store.temporal.getState() as TemporalStateWithInternals<MyState>;
expect(__internal).toBeDefined();
expect(__internal.handleUserSet).toBeInstanceOf(Function);
expect(__internal.onSave).toBeInstanceOf(Function);
expect(__internal.onSave).toBe(undefined);
});
describe('onSave', () => {
it('should call onSave cb without adding a new state when onSave is set by user', () => {
Expand All @@ -452,6 +452,7 @@ describe('Middleware options', () => {
act(() => {
onSave(store.getState(), store.getState());
});
expect(__internal.onSave).toBeInstanceOf(Function);
expect(store.temporal.getState().pastStates.length).toBe(0);
expect(console.error).toHaveBeenCalledTimes(1);
});
Expand Down
86 changes: 45 additions & 41 deletions packages/zundo/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,54 +27,58 @@ declare module 'zustand/vanilla' {
}
}

type ZundoImpl = <TState>(
config: StateCreator<TState, [], []>,
options: ZundoOptions<TState>,
) => StateCreator<TState, [], []>;
const zundoImpl =
<TState>(
config: StateCreator<TState, [], []>,
{
partialize = (state: TState) => state,
equality,
onSave,
limit,
handleSet: userlandSetFactory = (handleSetCb) => handleSetCb,
} = {} as ZundoOptions<TState>,
): StateCreator<TState, [], []> =>
(set, get, _store) => {
type TState = ReturnType<typeof config>;
type StoreAddition = StoreApi<TemporalState<TState>>;

const zundoImpl: ZundoImpl = (config, baseOptions) => (set, get, _store) => {
type TState = ReturnType<typeof config>;
type StoreAddition = StoreApi<TemporalState<TState>>;
const temporalStore = createVanillaTemporal<TState>(set, get, {
partialize,
equality,
onSave,
limit,
});

const options = {
partialize: (state: TState) => state,
handleSet: (handleSetCb: typeof set) => handleSetCb,
...baseOptions,
};
const { partialize, handleSet: userlandSetFactory } = options;

const temporalStore = createVanillaTemporal<TState>(set, get, options);
const store = _store as Mutate<
StoreApi<TState>,
[['temporal', StoreAddition]]
>;
const { setState } = store;

const store = _store as Mutate<
StoreApi<TState>,
[['temporal', StoreAddition]]
>;
const { setState } = store;
// TODO: should temporal be only temporalStore.getState()?
// We can hide the rest of the store in the secret internals.
store.temporal = temporalStore;

// TODO: should temporal be only temporalStore.getState()?
// We can hide the rest of the store in the secret internals.
store.temporal = temporalStore;
const curriedUserLandSet = userlandSetFactory(
temporalStore.getState().__internal.handleUserSet,
);

const curriedUserLandSet = userlandSetFactory(
temporalStore.getState().__internal.handleUserSet,
);
const modifiedSetState: typeof setState = (state, replace) => {
const pastState = partialize(get());
setState(state, replace);
curriedUserLandSet(pastState);
};
store.setState = modifiedSetState;

const modifiedSetState: typeof setState = (state, replace) => {
const pastState = partialize(get());
setState(state, replace);
curriedUserLandSet(pastState);
};
store.setState = modifiedSetState;
const modifiedSetter: typeof set = (state, replace) => {
// Get most up to date state. Should this be the same as the state in the callback?
const pastState = partialize(get());
set(state, replace);
curriedUserLandSet(pastState);
};

const modifiedSetter: typeof set = (state, replace) => {
// Get most up to date state. Should this be the same as the state in the callback?
const pastState = partialize(get());
set(state, replace);
curriedUserLandSet(pastState);
return config(modifiedSetter, get, _store);
};

return config(modifiedSetter, get, _store);
};

export const temporal = zundoImpl as unknown as Zundo;
export type { ZundoOptions, Zundo, TemporalState };
export type { ZundoOptions, Zundo, TemporalState };
18 changes: 8 additions & 10 deletions packages/zundo/src/temporal.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { createStore, type StoreApi } from 'zustand';
import type { TemporalStateWithInternals, ZundoOptions } from './types';
import type { TemporalStateWithInternals, WithRequired, ZundoOptions } from './types';

export const createVanillaTemporal = <TState>(
userSet: StoreApi<TState>['setState'],
userGet: StoreApi<TState>['getState'],
baseOptions?: ZundoOptions<TState>,
{
partialize,
equality,
onSave,
limit,
} = {} as Omit<WithRequired<ZundoOptions<TState>, | 'partialize'>, 'handleSet'>,
) => {
const options = {
partialize: (state: TState) => state,
equality: (a: TState, b: TState) => false,
onSave: () => {},
...baseOptions,
};
const { partialize, onSave, limit, equality } = options;

return createStore<TemporalStateWithInternals<TState>>()((set, get) => {
return {
Expand Down Expand Up @@ -73,7 +71,7 @@ export const createVanillaTemporal = <TState>(
const currentState = partialize(userGet());
if (
trackingStatus === 'tracking' &&
!equality(currentState, pastState)
!equality?.(currentState, pastState)
) {
if (limit && ps.length >= limit) {
ps.shift();
Expand Down
5 changes: 4 additions & 1 deletion packages/zundo/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { StoreApi } from 'zustand';

type onSave<TState> = (pastState: TState, currentState: TState) => void;
type onSave<TState> = ((pastState: TState, currentState: TState) => void) | undefined;

export interface TemporalStateWithInternals<TState> {
pastStates: TState[];
Expand Down Expand Up @@ -37,3 +37,6 @@ export type TemporalState<TState> = Omit<
TemporalStateWithInternals<TState>,
'__internal'
>;

// https://stackoverflow.com/a/69328045/9931154
export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }

0 comments on commit 2f5965c

Please sign in to comment.