UNPKG

query-state-hook

Version:

Easily manage the state of your React components via URL query parameters

105 lines (90 loc) 3.29 kB
import { MultiBuildProps, StateValue, URLSearchParamsProps } from "./types"; import { URLStateHandler } from "./URLStateHandler"; import { unhandledValue } from "./utils"; type GetState<TValue extends string> = ReturnType<URLStateHandler<TValue>["getState"]>; type SetState<TValue extends string> = ReturnType<URLStateHandler<TValue>["setState"]>; type SetStateProps<TValue extends string, TKey extends string> = { searchParams: URLSearchParamsProps; key: TKey; value: StateValue<TValue> | StateValue<TValue>[]; }; export class URLMultiStateHandler< TKey extends string = string, TId extends string = string, TValue extends string = string > { private constructor(private props: MultiBuildProps<TKey, TId, TValue>) {} static buildComposed<TKey extends string = string, TId extends string = string, TValue extends string = string>( props: MultiBuildProps<TKey, TId, TValue> ) { return new URLMultiStateHandler(props); } static container<TKey extends string = string, TId extends string = string, TValue extends string = string>( ids: MultiBuildProps<TKey, TId, TValue>["ids"] ) { return new URLMultiStateHandler<string, TId, TValue>({ name: "", ids, }); } getState(searchParams: URLSearchParamsProps, key: keyof typeof this.props.ids): GetState<TValue> { return this.build(key).getState(searchParams); } setState({ key, searchParams, value }: SetStateProps<TValue, keyof typeof this.props.ids>): SetState<TValue> { return this.build(key).setState(searchParams, value); } getAll(searchParams: URLSearchParamsProps) { const url = new URLSearchParams(); Object.entries(this.props.ids).forEach(([k, v]) => { const key = k as keyof typeof this.props.ids; const state = this.build(key).getState(searchParams); if (!state) return; url.set(this.buildNameFromKey(key), state.toString()); }); return url.toString(); } private build(key: keyof typeof this.props.ids) { const value = this.props.ids[key]; const type = value.type; let handler: URLStateHandler<TValue>; switch (type) { case "custom": handler = URLStateHandler.customValidation({ name: this.buildNameFromKey(key), getState: value.params.getState, setState: value.params.setState, }); break; case "simple": handler = URLStateHandler.build<TValue>({ name: this.buildNameFromKey(key), values: value.params.values, defaultValue: value.params.defaultValue, }); break; case "any": handler = URLStateHandler.customValidation({ name: this.buildNameFromKey(key), getState(searchParams) { return searchParams.get() ?? ("" as any); }, setState(urlSearchParams, value) { if (!value) { urlSearchParams.delete(); return urlSearchParams; } urlSearchParams.set(value); return urlSearchParams; }, }); break; default: throw unhandledValue(type); } return handler; } private buildNameFromKey(key: string) { const name = this.props.name; return name ? `${name}.${key}` : key; } }