Skip to content

Commit

Permalink
feat(location): add option for default value
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan-Zayne committed Nov 12, 2024
1 parent 247e617 commit 907d3a4
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/tough-cooks-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@zayne-labs/toolkit": patch
---

add option for default value
22 changes: 13 additions & 9 deletions packages/toolkit/src/core/createLocationStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { Prettify } from "@/type-helpers";
import { isBrowser } from "./constants";
import type { StoreApi, SubscribeOptions } from "./createStore";
import type { EqualityFn, StoreApi } from "./createStore";
import { on } from "./on";

export type LocationState = {
Expand All @@ -10,15 +9,22 @@ export type LocationState = {
state: NonNullable<unknown> | null;
};

type LocationStoreOptions = Prettify<Pick<SubscribeOptions<LocationState>, "equalityFn">>;
type LocationStoreOptions = {
defaultState?: Partial<LocationState>;
equalityFn?: EqualityFn<LocationState>;
};

/* eslint-disable unicorn/prefer-global-this */
const createLocationStore = (options: LocationStoreOptions = {}) => {
const { defaultState, equalityFn = Object.is } = options;

let locationState: LocationState = {
hash: isBrowser() ? window.location.hash : "",
pathname: isBrowser() ? window.location.pathname : "",
search: isBrowser() ? window.location.search : "",
state: isBrowser() ? (window.history.state as LocationState["state"]) : null,
hash: isBrowser() ? (defaultState?.hash ?? window.location.hash) : "",
pathname: isBrowser() ? (defaultState?.pathname ?? window.location.pathname) : "",
search: isBrowser() ? (defaultState?.search ?? window.location.search) : "",
state: isBrowser()
? (defaultState?.state ?? (window.history.state as LocationState["state"]))
: null,
};

const initialState = locationState;
Expand All @@ -27,8 +33,6 @@ const createLocationStore = (options: LocationStoreOptions = {}) => {

const getInitialState = () => initialState;

const { equalityFn = Object.is } = options;

const triggerPopstateEvent = (state?: unknown) => {
// == This has to be done in order to actually trigger the popState event, which usually only fires in the user clicks on the forward/back button.
// LINK - https://stackoverflow.com/a/37492075/18813022
Expand Down
7 changes: 4 additions & 3 deletions packages/toolkit/src/core/createStore/createStore.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { isFunction } from "@/type-helpers/guard";
import type { PrettyPick } from "@/type-helpers/types";
import type { Listener, StoreApi, SubscribeOptions } from "./types";
import type { EqualityFn, Listener, StoreApi } from "./types";

export type StateInitializer<TState, TResult = TState> = (
get: StoreApi<TState>["getState"],
set: StoreApi<TState>["setState"],
api: StoreApi<TState>
) => TResult;

type StoreOptions<TState> = PrettyPick<SubscribeOptions<TState>, "equalityFn">;
type StoreOptions<TState> = {
equalityFn?: EqualityFn<TState>;
};

const createStore = <TState>(
initializer: StateInitializer<TState>,
Expand Down
6 changes: 5 additions & 1 deletion packages/toolkit/src/core/createStore/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ export type Listener<TState> = UnmaskType<(state: TState, prevState: TState) =>

type SelectorFn<TStore, TResult> = UnmaskType<(state: TStore) => TResult>;

export type EqualityFn<TState> = UnmaskType<
(nextState: Partial<TState>, previousState: TState) => boolean
>;

export type SubscribeOptions<TState> = {
equalityFn?: (nextState: Partial<TState>, previousState: TState) => boolean;
equalityFn?: EqualityFn<TState>;
fireListenerImmediately?: boolean;
};

Expand Down
5 changes: 3 additions & 2 deletions packages/toolkit/src/react/hooks/useLocation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ type UseLocationResult<TSlice> = [
];

const useLocation = <TSlice = LocationState>(
selector: SelectorFn<LocationState, TSlice> = (store) => store as TSlice
selector: SelectorFn<LocationState, TSlice>,
defaultLocationState: Partial<LocationState> = {}
) => {
const locationStore = useConstant(() => createLocationStore());
const locationStore = useConstant(() => createLocationStore({ defaultState: defaultLocationState }));

const stateSlice = useStore(locationStore as never, selector);

Expand Down
13 changes: 9 additions & 4 deletions packages/toolkit/src/react/hooks/useSearchParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,15 @@ export const createSearchParams = (paramsInit: URLSearchParamsInit = ""): URLSea
return new URLSearchParams(arrayOfKeyValuePairs);
};

const useSearchParams = <TSearchParams extends URLSearchParamsInit>(
action: "push" | "replace" = "push"
) => {
const [search, setSearch] = useLocation((state) => state.search);
type UseSearchParamsOptions = {
action?: "push" | "replace";
defaultValue?: string;
};

const useSearchParams = <TSearchParams extends URLSearchParamsInit>(options?: UseSearchParamsOptions) => {
const { action = "push", defaultValue } = options ?? {};

const [search, setSearch] = useLocation((state) => state.search, { search: defaultValue });

const searchParams = new URLSearchParams(search);

Expand Down
2 changes: 1 addition & 1 deletion packages/toolkit/src/type-helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type PrettyPick<TObject, Key extends keyof TObject> = Prettify<Pick<TObje

export type CallbackFn<in TParams, out TResult = void> = (...params: TParams[]) => TResult;

export type SelectorFn<in TStore, out TResult> = (state: TStore) => TResult;
export type SelectorFn<TStore, TResult> = (state: TStore) => TResult;

export type Writeable<TObject, TType extends "deep" | "shallow" = "shallow"> = {
-readonly [key in keyof TObject]: TType extends "shallow"
Expand Down

0 comments on commit 907d3a4

Please sign in to comment.