import { Injector, WritableSignal } from "@angular/core"; import type { FormGroup } from "@angular/forms"; import type { Jsonify, JsonValue } from "type-fest"; type Deserializer = { /** * A function to use to safely convert your type from json to your expected type. * * @param jsonValue The JSON object representation of your state. * @returns The fully typed version of your state. */ readonly deserializer?: (jsonValue: Jsonify) => T | null; }; type BaseCacheOptions = { /** A unique key for saving the cached value to state */ key: string; /** An optional injector. Required if the method is called outside of an injection context. */ injector?: Injector; /** * Optional flag to persist the cached value between navigation events. */ persistNavigation?: boolean; } & (T extends JsonValue ? Deserializer : Required>); export type SignalCacheOptions = BaseCacheOptions & { /** The initial value for the signal. */ initialValue: T; }; /** Extract the value type from a FormGroup */ type FormValue = TFormGroup["value"]; export type FormCacheOptions = BaseCacheOptions< FormValue > & { control: TFormGroup; }; /** * Cache for temporary component state * * [Read more](./view-cache.md) * * #### Implementations * - browser extension popup: used to persist UI between popup open and close * - all other clients: noop */ export abstract class ViewCacheService { /** * Create a signal from a previously cached value. Whenever the signal is updated, the new value is saved to the cache. * * Non browser extension implementations are noop and return a normal signal. * * @returns the created signal * * @example * ```ts * const mySignal = this.viewCacheService.signal({ * key: "popup-search-text" * initialValue: "" * }); * ``` */ abstract signal(options: SignalCacheOptions): WritableSignal; /** * - Initialize a form from a cached value * - Save form value to cache when it changes * - The form is marked dirty if the restored value is not `undefined`. * * Non browser extension implementations are noop and return the original form group. * * @example * ```ts * this.loginDetailsForm = this.viewCacheService.formGroup({ * key: "vault-login-details-form", * control: this.formBuilder.group({ * username: [""], * email: [""], * }) * }); * ``` **/ abstract formGroup( options: FormCacheOptions, ): TFormGroup; }