@jfdevelops/multi-step-form-core 1.0.0-alpha.11 → 1.0.0-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/utils/casing.ts","../src/utils/field-types.ts","../src/storage.ts","../src/subscribable.ts","../src/steps/schema.ts","../src/schema.ts","../src/observable.ts"],"sourcesContent":["import type { Expand, SetDefaultString } from './types';\r\n\r\nexport type CasingType = (typeof CASING_TYPES)[number];\r\nexport type ToLower<S extends string> = S extends `${infer F}${infer R}`\r\n ? `${Lowercase<F>}${ToLower<R>}`\r\n : S;\r\n\r\nexport type CapitalizeWord<S extends string> = S extends `${infer F}${infer R}`\r\n ? `${Uppercase<F>}${ToLower<R>}`\r\n : S;\r\n// Pascal => Capitalize each \"word\" chunk\r\ntype Pascalize<S extends string> = Capitalize<S>; // naive\r\n\r\n// SnakeCase: turn spaces/hyphens into underscores, lowercase\r\ntype SnakeCase<S extends string> = Lowercase<\r\n S extends `${infer A} ${infer B}`\r\n ? `${A}_${SnakeCase<B>}`\r\n : S extends `${infer A}-${infer B}`\r\n ? `${A}_${SnakeCase<B>}`\r\n : S\r\n>;\r\n\r\n// KebabCase: same as snake but with \"-\"\r\ntype KebabCase<S extends string> = Lowercase<\r\n S extends `${infer A} ${infer B}`\r\n ? `${A}-${KebabCase<B>}`\r\n : S extends `${infer A}_${infer B}`\r\n ? `${A}-${KebabCase<B>}`\r\n : S\r\n>;\r\n\r\n// Flat: just strip spaces/underscores/hyphens\r\ntype RemoveDelimiters<S extends string> = S extends `${infer A} ${infer B}`\r\n ? `${A}${RemoveDelimiters<B>}`\r\n : S extends `${infer A}_${infer B}`\r\n ? `${A}${RemoveDelimiters<B>}`\r\n : S extends `${infer A}-${infer B}`\r\n ? `${A}${RemoveDelimiters<B>}`\r\n : S;\r\n\r\n// TitleCase: Capitalize the whole thing\r\ntype TitleCase<S extends string> = Capitalize<Lowercase<S>>;\r\n\r\n// SentenceCase: First word capped, rest lower\r\ntype SentenceCase<S extends string> = Capitalize<Lowercase<S>>;\r\nexport type ChangeCasing<\r\n S extends string,\r\n T extends CasingType\r\n> = T extends 'lower'\r\n ? Lowercase<S>\r\n : T extends 'upper'\r\n ? Uppercase<S>\r\n : T extends 'camel'\r\n ? Uncapitalize<Pascalize<S>>\r\n : T extends 'pascal'\r\n ? Pascalize<S>\r\n : T extends 'snake'\r\n ? SnakeCase<S>\r\n : T extends 'screaming-snake'\r\n ? Uppercase<SnakeCase<S>>\r\n : T extends 'kebab'\r\n ? KebabCase<S>\r\n : T extends 'flat'\r\n ? RemoveDelimiters<Lowercase<S>>\r\n : T extends 'title'\r\n ? TitleCase<S>\r\n : T extends 'sentence'\r\n ? SentenceCase<S>\r\n : S;\r\nexport type ChangeObjectCasing<\r\n T extends object,\r\n TCasing extends CasingType\r\n> = Expand<{\r\n [K in keyof T as K extends string ? ChangeCasing<K, TCasing> : K]: T[K];\r\n}>;\r\n\r\nexport const CASING_TYPES = [\r\n 'sentence',\r\n 'title',\r\n 'camel',\r\n 'lower',\r\n 'upper',\r\n 'pascal',\r\n 'snake',\r\n 'screaming-snake',\r\n 'flat',\r\n 'kebab',\r\n] as const;\r\n\r\nexport type DefaultCasing = typeof DEFAULT_CASING;\r\nexport const DEFAULT_CASING: SetDefaultString<CasingType, 'title'> = 'title';\r\n\r\n/**\r\n * Changes the casing of a string according to the specified casing type.\r\n *\r\n * @param input - The string to transform.\r\n * @param type - The casing type to apply.\r\n * @returns The transformed string in the specified casing.\r\n */\r\n// TODO make return type safe\r\nexport function changeCasing<TValue extends string, TType extends CasingType>(\r\n input: TValue,\r\n type: TType\r\n): ChangeCasing<TValue, TType>;\r\nexport function changeCasing<TValue extends string, TType extends CasingType>(\r\n input: TValue,\r\n type: TType\r\n) {\r\n // Step 1: Normalize to words\r\n const words = input\r\n // Replace camelCase boundaries with space\r\n .replace(/([a-z])([A-Z])/g, '$1 $2')\r\n // Replace separators with space\r\n .replace(/[-_]+/g, ' ')\r\n // Trim and split into words\r\n .trim()\r\n .split(/\\s+/)\r\n .map((w) => w.toLowerCase());\r\n\r\n // Step 2: Apply casing\r\n switch (type) {\r\n case 'sentence':\r\n return (\r\n words[0].charAt(0).toUpperCase() +\r\n words[0].slice(1) +\r\n (words.length > 1 ? ' ' + words.slice(1).join(' ') : '')\r\n );\r\n\r\n case 'title':\r\n return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');\r\n\r\n case 'camel':\r\n return (\r\n words[0] +\r\n words\r\n .slice(1)\r\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\r\n .join('')\r\n );\r\n\r\n case 'pascal':\r\n return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join('');\r\n\r\n case 'lower':\r\n return words.join(' ');\r\n\r\n case 'upper':\r\n return words.join(' ').toUpperCase();\r\n\r\n case 'snake':\r\n return words.join('_');\r\n\r\n case 'screaming-snake':\r\n return words.join('_').toUpperCase();\r\n\r\n case 'kebab':\r\n return words.join('-');\r\n\r\n case 'flat':\r\n return words.join('');\r\n\r\n default:\r\n return input;\r\n }\r\n}\r\n\r\nexport function quote(str: string, quoteChar: '\"' | \"'\" = '\"') {\r\n const startsWithQuote = str.startsWith(quoteChar);\r\n const endsWithQuote = str.endsWith(quoteChar);\r\n\r\n if (startsWithQuote && endsWithQuote) {\r\n // Already wrapped correctly\r\n return str;\r\n }\r\n\r\n // If it starts or ends with a quote but not both → strip those first\r\n const trimmed = str.replace(/^['\"]|['\"]$/g, '');\r\n\r\n // Then add new quotes consistently\r\n return `${quoteChar}${trimmed}${quoteChar}`;\r\n}\r\n\r\nexport function isCasingValid(value: unknown): value is CasingType {\r\n if (typeof value !== 'string') {\r\n return false;\r\n }\r\n\r\n const isValid = CASING_TYPES.includes(value as CasingType);\r\n\r\n // invariant(isValid, () => {\r\n // const formatter = new Intl.ListFormat('en', {\r\n // style: 'long',\r\n // type: 'conjunction',\r\n // });\r\n\r\n // return `${value} is not a valid casing type. Valid types include ${formatter.format(\r\n // CASING_TYPES.map((word) => quote(word))\r\n // )}`;\r\n // });\r\n\r\n return isValid;\r\n}\r\n\r\n/**\r\n * Validates {@linkcode input} is a valid {@linkcode CasingType}.\r\n *\r\n * If there is no explicit {@linkcode fallback} value provided,\r\n * it will default to {@linkcode DEFAULT_CASING}.\r\n * @param input The input to check.\r\n * @param fallback An optional fallback value if {@linkcode input} is `undefined`.\r\n * @returns The {@linkcode input} or {@linkcode fallback} if {@linkcode input} is `undefined` or an {@linkcode isCasingValid invalid} {@linkcode CasingType}.\r\n */\r\nexport function setCasingType<TCasing extends CasingType>(\r\n input: TCasing | undefined,\r\n fallback: CasingType = DEFAULT_CASING\r\n) {\r\n if (isCasingValid(input)) {\r\n return input;\r\n }\r\n\r\n return fallback;\r\n}\r\n","import type { SetDefaultString } from './types';\r\n\r\nexport type FieldType = (typeof FIELD_TYPES)[number];\r\nexport type DefaultFieldType = typeof DEFAULT_FIELD_TYPE;\r\nexport const FIELD_TYPES = [\r\n 'string',\r\n 'string.phone',\r\n 'string.email',\r\n 'string.time',\r\n 'number',\r\n 'number.counter',\r\n 'date',\r\n 'dateTime',\r\n 'boolean.switch',\r\n] as const;\r\nexport const DEFAULT_FIELD_TYPE: SetDefaultString<FieldType, 'string'> =\r\n 'string';\r\n\r\nexport function isFieldType(value: unknown): value is FieldType {\r\n return typeof value === 'string' && FIELD_TYPES.includes(value as FieldType);\r\n}\r\n","import type { Updater } from '@/steps/types';\r\nimport { invariant } from '@/utils/invariant';\r\nimport { MultiStepFormLogger } from '@/utils/logger';\r\n\r\nexport type DefaultStorageKey = typeof DEFAULT_STORAGE_KEY;\r\nexport type StorageConfig<TData, TKey extends string> = {\r\n key: TKey;\r\n data: TData;\r\n store?: Storage;\r\n /**\r\n * An extra option to throw an error when {@linkcode window} is `undefined`\r\n * @default false\r\n */\r\n throwWhenUndefined?: boolean;\r\n};\r\n\r\nconst WINDOW_UNDEFINED_MESSAGE =\r\n '\"window\" in undefined. No storage is available';\r\nexport const DEFAULT_STORAGE_KEY = 'MultiStepForm';\r\n\r\nexport class MultiStepFormStorage<\r\n data,\r\n key extends string = DefaultStorageKey\r\n> {\r\n readonly key: key;\r\n readonly store!: Storage;\r\n readonly data: data;\r\n private readonly log: MultiStepFormLogger;\r\n private readonly shouldRunActions: boolean;\r\n private readonly throwWhenUndefined: boolean;\r\n\r\n constructor(config: StorageConfig<data, key>) {\r\n const { key, data, store, throwWhenUndefined = false } = config;\r\n\r\n this.log = new MultiStepFormLogger({\r\n prefix: DEFAULT_STORAGE_KEY,\r\n });\r\n this.key = key;\r\n this.data = data;\r\n this.throwWhenUndefined = throwWhenUndefined;\r\n\r\n if (store) {\r\n this.store = store;\r\n this.shouldRunActions = true;\r\n\r\n if (typeof window === 'undefined') {\r\n this.shouldRunActions = false;\r\n this.log.warn(WINDOW_UNDEFINED_MESSAGE);\r\n }\r\n } else if (typeof window !== 'undefined') {\r\n this.store = window.localStorage;\r\n this.shouldRunActions = true;\r\n } else {\r\n this.shouldRunActions = false;\r\n this.log.warn(WINDOW_UNDEFINED_MESSAGE);\r\n }\r\n }\r\n\r\n private throwOnEmptyStore() {\r\n if (!this.throwWhenUndefined) {\r\n return;\r\n }\r\n\r\n invariant(this.store, () => {\r\n if (this.shouldRunActions) {\r\n return WINDOW_UNDEFINED_MESSAGE;\r\n }\r\n\r\n return 'No storage available';\r\n });\r\n }\r\n\r\n private resolveValue(value: Updater<data>) {\r\n if (typeof value === 'object') {\r\n return value;\r\n }\r\n\r\n if (typeof value === 'function') {\r\n return (value as (input: data) => data)(this.data);\r\n }\r\n\r\n this.log.error(\r\n `The updater value must be a function or object. Was a ${typeof value}`,\r\n { throw: true }\r\n );\r\n }\r\n\r\n hasKey() {\r\n return this.store.getItem(this.key) !== null;\r\n }\r\n\r\n get() {\r\n this.throwOnEmptyStore();\r\n\r\n if (!this.shouldRunActions) {\r\n return;\r\n }\r\n\r\n const item = this.store.getItem(this.key);\r\n\r\n if (item) {\r\n const parsed = JSON.parse(item);\r\n\r\n return parsed as data;\r\n }\r\n }\r\n\r\n remove() {\r\n this.throwOnEmptyStore();\r\n\r\n if (!this.shouldRunActions) {\r\n return;\r\n }\r\n\r\n this.store.removeItem(this.key);\r\n }\r\n\r\n add(value: Updater<data>) {\r\n this.throwOnEmptyStore();\r\n\r\n if (!this.shouldRunActions) {\r\n return;\r\n }\r\n\r\n const resolvedValue = JSON.stringify(this.resolveValue(value));\r\n\r\n this.store.setItem(this.key, resolvedValue);\r\n }\r\n}\r\n","export abstract class Subscribable<TListener extends Function> {\r\n protected listeners = new Set<TListener>();\r\n\r\n constructor() {\r\n this.subscribe = this.subscribe.bind(this);\r\n }\r\n\r\n subscribe(listener: TListener) {\r\n this.listeners.add(listener);\r\n\r\n this.onSubscribe();\r\n\r\n return () => {\r\n this.listeners.delete(listener);\r\n this.onUnsubscribe();\r\n };\r\n }\r\n\r\n hasListeners() {\r\n return this.listeners.size > 0;\r\n }\r\n\r\n protected onSubscribe() {}\r\n protected onUnsubscribe() {}\r\n protected abstract notify(): void;\r\n abstract getSnapshot(): this;\r\n}\r\n","import {\r\n MultiStepFormStepSchemaInternal,\r\n isValidStepKey,\r\n} from '@/internals/step-schema';\r\nimport {\r\n DEFAULT_STORAGE_KEY,\r\n DefaultStorageKey,\r\n MultiStepFormStorage,\r\n} from '@/storage';\r\nimport {\r\n DEFAULT_CASING,\r\n DEFAULT_FIELD_TYPE,\r\n changeCasing,\r\n isCasingValid,\r\n isFieldType,\r\n setCasingType,\r\n type CasingType,\r\n type Constrain,\r\n type DefaultCasing,\r\n type Expand,\r\n type Join,\r\n} from '@/utils';\r\nimport { invariant } from '@/utils/invariant';\r\nimport {\r\n runStandardValidation,\r\n type AnyValidator,\r\n type DefaultValidator,\r\n type StandardSchemaValidator,\r\n} from '@/utils/validator';\r\nimport { Subscribable } from '../subscribable';\r\nimport { fields as fieldsUtils } from './fields';\r\nimport {\r\n AnyResolvedStep,\r\n AnyStepField,\r\n AnyStepFieldOption,\r\n CreateHelperFunctionOptionsWithCustomCtxOptions,\r\n CreateHelperFunctionOptionsWithValidator,\r\n CreateHelperFunctionOptionsWithoutValidator,\r\n CreateStepHelperFn,\r\n CreatedHelperFnWithInput,\r\n CreatedHelperFnWithoutInput,\r\n ExtractStepFromKey,\r\n FirstStep,\r\n GetCurrentStep,\r\n HelperFnChosenSteps,\r\n HelperFnWithValidator,\r\n HelperFnWithoutValidator,\r\n InferStepOptions,\r\n LastStep,\r\n MultiStepFormSchemaStepConfig,\r\n ResolvedFields,\r\n ResolvedStep,\r\n Step,\r\n StepData,\r\n StepNumbers,\r\n StepOptions,\r\n UnionToTuple,\r\n UpdateFn,\r\n ValidStepKey\r\n} from './types';\r\nimport { getStep, type GetStepOptions } from './utils';\r\n\r\nexport interface MultiStepFormStepSchemaFunctions<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>\r\n> {\r\n update: UpdateFn.general<TResolvedStep, TStepNumbers>;\r\n createHelperFn: CreateStepHelperFn<TResolvedStep, TStepNumbers>;\r\n}\r\nexport type AsType = (typeof AS_TYPES)[number];\r\ntype Quote<T extends string[]> = {\r\n [K in keyof T]: T[K] extends string ? `'${T[K]}'` : never;\r\n};\r\nexport type AsTypeMap<\r\n resolvedStep extends AnyResolvedStep,\r\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>\r\n> = {\r\n // Exclude is needed due to all the Constrains\r\n string: Exclude<\r\n Join<\r\n Constrain<\r\n Quote<Constrain<UnionToTuple<`${stepNumbers}`>, string[]>>,\r\n string[]\r\n >,\r\n ' | '\r\n >,\r\n ''\r\n >;\r\n number: Exclude<\r\n Join<Constrain<UnionToTuple<`${stepNumbers}`>, string[]>, ' | '>,\r\n ''\r\n >;\r\n 'array.string': UnionToTuple<`${stepNumbers}`>;\r\n 'array.string.untyped': string[];\r\n};\r\nexport type AsFunctionReturn<\r\n resolvedStep extends AnyResolvedStep,\r\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>,\r\n asType extends AsType\r\n> = AsTypeMap<resolvedStep, stepNumbers>[asType];\r\nexport type AsFunction<\r\n resolvedStep extends AnyResolvedStep,\r\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>\r\n> = <asType extends AsType>(\r\n asType: asType\r\n) => AsFunctionReturn<resolvedStep, stepNumbers, asType>;\r\nexport type MultiStepFormStepStepsConfig<\r\n TStep extends Step<TCasing>,\r\n TCasing extends CasingType,\r\n TResolvedStep extends ResolvedStep<TStep, TCasing> = ResolvedStep<\r\n TStep,\r\n TCasing\r\n >,\r\n TStepNumbers extends StepNumbers<TResolvedStep> = StepNumbers<TResolvedStep>\r\n> = {\r\n first: FirstStep<TResolvedStep>;\r\n last: LastStep<TResolvedStep>;\r\n value: ReadonlyArray<TStepNumbers>;\r\n as: AsFunction<TResolvedStep, TStepNumbers>;\r\n isValidStepNumber: (stepNumber: number) => stepNumber is TStepNumbers;\r\n isValidStepKey: (\r\n value: string\r\n ) => value is Constrain<keyof TResolvedStep, string>;\r\n};\r\nexport type MultiStepFormStepSchemaListener<\r\n TStep extends Step<TCasing>,\r\n TCasing extends CasingType\r\n> = (data: {\r\n original: InferStepOptions<TStep>;\r\n value: ResolvedStep<TStep, TCasing>;\r\n steps: MultiStepFormStepStepsConfig<TStep, TCasing>;\r\n defaultNameTransformationCasing: TCasing;\r\n}) => void;\r\n\r\n/**\r\n * Available transformation types for the step numbers.\r\n */\r\nconst AS_TYPES = [\r\n 'string',\r\n 'number',\r\n 'array.string',\r\n 'array.string.untyped',\r\n] as const;\r\nexport const VALIDATED_STEP_REGEX = /^step\\d+$/i;\r\n\r\ntype ValueCheck<T> = (v: unknown) => v is T;\r\n\r\ntype FieldChecks<T extends object> = {\r\n [K in keyof T]: ValueCheck<T[K]>;\r\n};\r\n\r\nfunction assertObjectFields<T extends object>(\r\n obj: unknown,\r\n checks: FieldChecks<T>\r\n): obj is T {\r\n if (typeof obj !== 'object' || obj === null) return false;\r\n\r\n for (const key of Object.keys(checks) as (keyof T)[]) {\r\n // Check that the property exists\r\n if (!(key in obj)) return false;\r\n\r\n // Now check the type\r\n const checkFn = checks[key];\r\n const value = (obj as any)[key];\r\n if (!checkFn(value)) return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nfunction createFieldLabel(\r\n label: string | false | undefined,\r\n fieldName: string,\r\n casingType: CasingType\r\n) {\r\n return label ?? changeCasing(fieldName, casingType);\r\n}\r\n\r\nfunction createStepFields(options: {\r\n fields: AnyStepField;\r\n validateFields:\r\n | Constrain<unknown, AnyValidator, DefaultValidator>\r\n | undefined;\r\n defaultCasing: CasingType;\r\n}) {\r\n const resolvedFields: Record<string, unknown> = {};\r\n const { fields, defaultCasing, validateFields } = options;\r\n\r\n for (const [name, values] of Object.entries(fields)) {\r\n invariant(\r\n typeof name === 'string',\r\n `Each key for the \"fields\" option must be a string. Key ${name} was a ${typeof name}`\r\n );\r\n invariant(\r\n typeof values === 'object',\r\n `The value for key ${name} must be an object. Was ${typeof values}`\r\n );\r\n\r\n const {\r\n defaultValue,\r\n label,\r\n nameTransformCasing,\r\n type = DEFAULT_FIELD_TYPE,\r\n } = values;\r\n\r\n if (validateFields) {\r\n resolvedFields[name] = defaultValue;\r\n } else {\r\n const casing = nameTransformCasing ?? defaultCasing;\r\n\r\n resolvedFields[name] = {\r\n ...(resolvedFields[name] as Record<string, unknown>),\r\n nameTransformCasing: casing,\r\n type,\r\n defaultValue,\r\n label: createFieldLabel(label, name, casing),\r\n\r\n // TODO add more fields here\r\n };\r\n }\r\n }\r\n\r\n if (validateFields) {\r\n const validatedFields = runStandardValidation(\r\n validateFields as StandardSchemaValidator,\r\n resolvedFields\r\n );\r\n\r\n invariant(\r\n typeof validatedFields === 'object',\r\n `The result of the validated fields must be an object, was (${typeof validatedFields}). This is probably an internal error, so open up an issue about it`\r\n );\r\n invariant(\r\n !!validatedFields,\r\n 'The result of the validated fields must be defined. This is probably an internal error, so open up an issue about it'\r\n );\r\n\r\n for (const [name, defaultValue] of Object.entries(validatedFields)) {\r\n const currentField = fields[name];\r\n\r\n invariant(\r\n currentField,\r\n `No field found in the fields config for \"${name}\"`\r\n );\r\n\r\n const {\r\n label,\r\n type = DEFAULT_FIELD_TYPE,\r\n nameTransformCasing,\r\n } = currentField;\r\n const casing = nameTransformCasing ?? defaultCasing;\r\n\r\n resolvedFields[name] = {\r\n ...(resolvedFields[name] as Record<string, unknown>),\r\n nameTransformCasing: casing,\r\n type,\r\n defaultValue,\r\n label: createFieldLabel(label, name, casing),\r\n };\r\n }\r\n }\r\n\r\n return resolvedFields;\r\n}\r\n\r\nexport function createStep<\r\n step extends Step<casing>,\r\n casing extends CasingType = DefaultCasing\r\n>(stepsConfig: InferStepOptions<step>) {\r\n const resolvedSteps = {} as ResolvedStep<step, casing>;\r\n\r\n invariant(!!stepsConfig, 'The steps config must be defined', TypeError);\r\n invariant(\r\n typeof stepsConfig === 'object',\r\n `The steps config must be an object, was (${typeof stepsConfig})`,\r\n TypeError\r\n );\r\n\r\n for (const [stepKey, stepValue] of Object.entries(stepsConfig)) {\r\n invariant(\r\n typeof stepKey === 'string',\r\n `Each key for the step config must be a string. Key \"${stepKey}\" was ${typeof stepKey} `,\r\n TypeError\r\n );\r\n invariant(\r\n VALIDATED_STEP_REGEX.test(stepKey),\r\n `The key \"${stepKey}\" isn't formatted properly. Each key in the step config must be the following format: \"step{number}\"`\r\n );\r\n\r\n const validStepKey = stepKey as keyof typeof resolvedSteps;\r\n const {\r\n fields,\r\n title,\r\n nameTransformCasing: defaultCasing = DEFAULT_CASING,\r\n description,\r\n validateFields,\r\n } = stepValue;\r\n\r\n const currentStep = validStepKey.toString().replace('step', '');\r\n\r\n invariant(\r\n fields,\r\n `Missing fields for step ${currentStep} (${String(validStepKey)})`,\r\n TypeError\r\n );\r\n invariant(\r\n typeof fields === 'object',\r\n 'Fields must be an object',\r\n TypeError\r\n );\r\n invariant(\r\n Object.keys(fields).length > 0,\r\n `The fields config for step ${currentStep} (${String(\r\n validStepKey\r\n )}) is empty. Please add a field`\r\n );\r\n invariant(\r\n typeof fields === 'object',\r\n `The \"fields\" property must be an object. Was ${typeof fields}`\r\n );\r\n\r\n const resolvedFields = createStepFields({\r\n defaultCasing,\r\n fields,\r\n validateFields,\r\n });\r\n\r\n resolvedSteps[validStepKey] = {\r\n ...resolvedSteps[validStepKey],\r\n title,\r\n nameTransformCasing: defaultCasing,\r\n // Only add the description if it's defined\r\n ...(typeof description === 'string' ? { description } : {}),\r\n fields: resolvedFields,\r\n };\r\n }\r\n\r\n return resolvedSteps;\r\n}\r\n\r\nexport class MultiStepFormStepSchema<\r\n step extends Step<casing>,\r\n casing extends CasingType = DefaultCasing,\r\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<\r\n step,\r\n casing\r\n >,\r\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\r\n storageKey extends string = DefaultStorageKey\r\n >\r\n extends Subscribable<MultiStepFormStepSchemaListener<step, casing>>\r\n implements MultiStepFormStepSchemaFunctions<resolvedStep, stepNumbers>\r\n{\r\n /**\r\n * The original config before any validation or transformations have been applied.\r\n */\r\n readonly original: InferStepOptions<step>;\r\n /**\r\n * The resolved step values.\r\n */\r\n value: resolvedStep;\r\n readonly steps: MultiStepFormStepStepsConfig<step, casing>;\r\n readonly defaultNameTransformationCasing: casing;\r\n //@ts-ignore\r\n private readonly firstStep: StepData<resolvedStep, FirstStep<resolvedStep>>;\r\n private readonly lastStep: StepData<resolvedStep, LastStep<resolvedStep>>;\r\n private readonly stepNumbers: Array<number>;\r\n private readonly storage: MultiStepFormStorage<resolvedStep, storageKey>;\r\n readonly #internal: MultiStepFormStepSchemaInternal<\r\n resolvedStep,\r\n stepNumbers\r\n >;\r\n\r\n constructor(\r\n config: MultiStepFormSchemaStepConfig<\r\n step,\r\n Constrain<casing, CasingType>,\r\n storageKey\r\n >\r\n ) {\r\n super();\r\n\r\n const { steps, nameTransformCasing, storage } = config;\r\n\r\n this.defaultNameTransformationCasing = setCasingType(\r\n nameTransformCasing\r\n ) as casing;\r\n\r\n this.original = steps;\r\n\r\n this.value = createStep<step, casing>(this.original) as resolvedStep;\r\n this.storage = new MultiStepFormStorage<resolvedStep, storageKey>({\r\n data: this.value,\r\n key: (storage?.key ?? DEFAULT_STORAGE_KEY) as storageKey,\r\n store: storage?.store,\r\n throwWhenUndefined: storage?.throwWhenUndefined ?? false,\r\n });\r\n this.#internal = new MultiStepFormStepSchemaInternal<\r\n resolvedStep,\r\n stepNumbers\r\n >({\r\n getValue: () => this.value,\r\n setValue: (next) => this.handlePostUpdate(next),\r\n });\r\n\r\n this.value = this.#internal.enrichValues(this.value);\r\n this.stepNumbers = Object.keys(this.value).map((key) =>\r\n Number.parseInt(key.replace('step', ''))\r\n );\r\n\r\n this.firstStep = this.first();\r\n this.lastStep = this.last();\r\n this.steps = {\r\n first: this.firstStep.step,\r\n last: this.lastStep.step,\r\n value: this.stepNumbers as unknown as ReadonlyArray<stepNumbers>,\r\n as: (asType): any => {\r\n invariant(\r\n typeof asType === 'string',\r\n `The type of the target transformation type must be a string, was ${typeof asType}`\r\n );\r\n\r\n if (asType === 'string') {\r\n return this.stepNumbers.map((value) => `'${value}'`).join(' | ');\r\n }\r\n\r\n if (asType === 'number') {\r\n return this.stepNumbers.join(' | ');\r\n }\r\n\r\n if (asType.includes('array.string')) {\r\n return this.stepNumbers.map((value) => `${value}`);\r\n }\r\n\r\n throw new Error(\r\n `Transformation type \"${asType}\" is not supported. Available transformations include: ${AS_TYPES.map(\r\n (value) => `\"${value}\"`\r\n ).join(', ')}`\r\n );\r\n },\r\n isValidStepNumber: (stepNumber): stepNumber is stepNumbers =>\r\n this.stepNumbers.includes(stepNumber),\r\n isValidStepKey: (value) =>\r\n isValidStepKey<resolvedStep>(this.value, value),\r\n };\r\n\r\n this.sync();\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n __getStorage() {\r\n return this.storage;\r\n }\r\n\r\n getSnapshot() {\r\n return this;\r\n }\r\n\r\n /**\r\n * Syncs the values from storage to {@linkcode value}.\r\n */\r\n sync() {\r\n // TODO add \"syncOptions\" so caller can chose where to sync from ('storage' | 'instance')\r\n const storageValues = this.__getStorage().get();\r\n\r\n if (storageValues) {\r\n const enrichedValues = this.#internal.enrichValues(storageValues);\r\n\r\n this.value = { ...enrichedValues };\r\n }\r\n }\r\n\r\n protected notify() {\r\n for (const listener of this.listeners) {\r\n listener({\r\n defaultNameTransformationCasing: this.defaultNameTransformationCasing,\r\n original: this.original,\r\n steps: this.steps,\r\n value: this.value,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Gets the data for a specific step.\r\n * @param options The options for getting the step data.\r\n * @returns The step data for the target step.\r\n */\r\n get<stepNumber extends stepNumbers>(\r\n options: GetStepOptions<resolvedStep, stepNumbers, stepNumber>\r\n ) {\r\n return getStep(this.value)(options);\r\n }\r\n\r\n /**\r\n * Gets the data for the first step.\r\n * @returns The data for the first step.\r\n */\r\n first() {\r\n const firstStep = Math.min(...this.stepNumbers) as FirstStep<resolvedStep>;\r\n\r\n return this.get({ step: firstStep });\r\n }\r\n\r\n /**\r\n * Gets the data for the last step.\r\n * @returns The data for the last step.\r\n */\r\n last() {\r\n const lastStep = Math.max(...this.stepNumbers);\r\n\r\n return this.get<LastStep<resolvedStep>>({ step: lastStep as never });\r\n }\r\n\r\n protected handlePostUpdate(next: resolvedStep) {\r\n this.value = { ...next };\r\n\r\n this.__getStorage().add(this.value);\r\n this.sync();\r\n this.notify();\r\n }\r\n\r\n update<\r\n targetStep extends ValidStepKey<stepNumbers>,\r\n field extends UpdateFn.chosenFields<\r\n UpdateFn.resolvedStep<resolvedStep, stepNumbers, targetStep>\r\n > = 'all',\r\n additionalCtx extends Record<string, unknown> = {}\r\n >(\r\n options: UpdateFn.options<\r\n resolvedStep,\r\n stepNumbers,\r\n targetStep,\r\n field,\r\n additionalCtx\r\n >\r\n ) {\r\n this.#internal.update(options);\r\n }\r\n\r\n /**\r\n * Create a helper function with validated input.\r\n */\r\n createHelperFn<\r\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\r\n validator,\r\n additionalCtx extends Record<string, unknown>,\r\n response\r\n >(\r\n options: CreateHelperFunctionOptionsWithValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx\r\n >,\r\n fn: HelperFnWithValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx,\r\n response\r\n >\r\n ): CreatedHelperFnWithInput<validator, response>;\r\n /**\r\n * Create a helper function without input.\r\n */\r\n createHelperFn<\r\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\r\n additionalCtx extends Record<string, unknown>,\r\n response\r\n >(\r\n options: CreateHelperFunctionOptionsWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps\r\n > &\r\n CreateHelperFunctionOptionsWithCustomCtxOptions<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n additionalCtx\r\n >,\r\n fn: HelperFnWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n additionalCtx,\r\n response\r\n >\r\n ): CreatedHelperFnWithoutInput<response>;\r\n // Implementation\r\n createHelperFn<\r\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\r\n response,\r\n additionalCtx extends Record<string, unknown>,\r\n validator = never\r\n >(\r\n options:\r\n | CreateHelperFunctionOptionsWithValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx\r\n >\r\n | CreateHelperFunctionOptionsWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps\r\n >,\r\n fn:\r\n | HelperFnWithValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx,\r\n response\r\n >\r\n | HelperFnWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n additionalCtx,\r\n response\r\n >\r\n ) {\r\n const { stepData, ...rest } = options;\r\n\r\n return this.#internal.createStepHelperFn(stepData)(rest, fn);\r\n }\r\n\r\n /**\r\n * Validates that a given object is the proper shape for step data.\r\n * @param value\r\n */\r\n static hasData<\r\n step extends Step<casing>,\r\n resolvedStep extends ResolvedStep<step, casing>,\r\n stepNumbers extends StepNumbers<resolvedStep>,\r\n casing extends CasingType = DefaultCasing\r\n >(\r\n value: unknown,\r\n options?: {\r\n optionalKeysToCheck?: FieldChecks<\r\n Pick<StepOptions, 'description' | 'validateFields'>\r\n >;\r\n }\r\n ): value is GetCurrentStep<resolvedStep, stepNumbers> {\r\n if (value === null || typeof value !== 'object') {\r\n return false;\r\n }\r\n\r\n return assertObjectFields<\r\n | GetCurrentStep<resolvedStep, stepNumbers>\r\n | (Omit<StepOptions, 'fields'> & {\r\n fields: Expand<\r\n ResolvedFields<InferStepOptions<step>, keyof InferStepOptions<step>>\r\n >;\r\n })\r\n >(value, {\r\n title: (v) => typeof v === 'string',\r\n fields: (\r\n v\r\n ): v is Expand<\r\n ResolvedFields<InferStepOptions<step>, keyof InferStepOptions<step>>\r\n > => {\r\n if (v === null || typeof v !== 'object') {\r\n return false;\r\n }\r\n\r\n for (const key of Object.keys(v)) {\r\n if (typeof key !== 'string' || !(key in v)) {\r\n return false;\r\n }\r\n\r\n const current = (v as Record<string, unknown>)[key];\r\n\r\n if (current === null || typeof current !== 'object') {\r\n return false;\r\n }\r\n\r\n const hasField = assertObjectFields<AnyStepFieldOption>(current, {\r\n defaultValue: (v): v is {} => v !== 'undefined' && v !== null,\r\n label: (v) =>\r\n typeof v === 'string' || (typeof v === 'boolean' && !v),\r\n nameTransformCasing: isCasingValid,\r\n type: isFieldType,\r\n });\r\n\r\n if (!hasField) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n },\r\n createHelperFn: (\r\n v\r\n ): v is GetCurrentStep<resolvedStep, stepNumbers>['createHelperFn'] =>\r\n typeof v === 'function',\r\n // update: (v): v is GetCurrentStep<resolvedStep, stepNumbers>['update'] =>\r\n // typeof v === 'function',\r\n nameTransformCasing: isCasingValid,\r\n ...options?.optionalKeysToCheck,\r\n });\r\n }\r\n\r\n /**\r\n * Gets the value of a given field for a given step.\r\n * @param step The step to get the value from.\r\n * @param field The field to get the value from.\r\n * @returns The value of the {@linkcode field}.\r\n */\r\n getValue<\r\n step extends keyof resolvedStep,\r\n field extends fieldsUtils.getDeep<resolvedStep, step>\r\n >(step: step, field: field) {\r\n const stepData = this.value[step];\r\n const baseErrorMessage = `Unable to get the value for \"${String(\r\n step\r\n )}.fields.${String(field)}\"`;\r\n\r\n invariant('fields' in stepData, baseErrorMessage);\r\n invariant(\r\n typeof stepData.fields === 'object',\r\n `${baseErrorMessage} because \"fields\" is not an object. This shouldn't be the case, so please open an issue`\r\n );\r\n\r\n const fields = stepData.fields as AnyStepField;\r\n\r\n const defaultValue = fieldsUtils.resolvedDeepPath<\r\n resolvedStep,\r\n step,\r\n fieldsUtils.get<resolvedStep, step>,\r\n field\r\n >(field, fields as fieldsUtils.get<resolvedStep, step>);\r\n\r\n return defaultValue;\r\n }\r\n}\r\n","import {\r\n MultiStepFormStepSchema,\r\n type MultiStepFormSchemaStepConfig,\r\n type ResolvedStep,\r\n type Step,\r\n type StepNumbers,\r\n} from '@/steps';\r\nimport {\r\n setCasingType,\r\n type CasingType,\r\n type Constrain,\r\n type DefaultCasing,\r\n} from '@/utils';\r\nimport {\r\n DEFAULT_STORAGE_KEY,\r\n MultiStepFormStorage,\r\n type DefaultStorageKey,\r\n} from './storage.js';\r\nimport { Subscribable } from './subscribable.js';\r\n\r\nexport interface MultiStepFormSchemaOptions<\r\n TStep extends Step<TCasing>,\r\n TCasing extends CasingType,\r\n TStorageKey extends string\r\n> extends MultiStepFormSchemaStepConfig<TStep, TCasing, TStorageKey> {}\r\nexport type MultiStepFormSchemaListener<\r\n TStep extends Step<TCasing>,\r\n TCasing extends CasingType,\r\n TStorageKey extends string\r\n> = (data: MultiStepFormSchemaOptions<TStep, TCasing, TStorageKey>) => void;\r\n\r\nexport class MultiStepFormSchema<\r\n step extends Step<casing>,\r\n casing extends CasingType = DefaultCasing,\r\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<step, casing>,\r\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\r\n storageKey extends string = DefaultStorageKey\r\n> extends Subscribable<MultiStepFormSchemaListener<step, casing, storageKey>> {\r\n readonly defaultNameTransformationCasing: casing;\r\n readonly stepSchema: MultiStepFormStepSchema<\r\n step,\r\n casing,\r\n resolvedStep,\r\n stepNumbers,\r\n storageKey\r\n >;\r\n storage: MultiStepFormStorage<resolvedStep, storageKey>;\r\n private mountCount = 0;\r\n\r\n constructor(\r\n options: MultiStepFormSchemaOptions<\r\n step,\r\n // Allows full autocomplete\r\n Constrain<casing, CasingType>,\r\n storageKey\r\n >\r\n ) {\r\n super();\r\n\r\n const { steps, nameTransformCasing, storage } = options;\r\n\r\n this.defaultNameTransformationCasing = setCasingType(\r\n nameTransformCasing\r\n ) as casing;\r\n // @ts-ignore Type instantiation is excessively deep and possibly infinite\r\n this.stepSchema = new MultiStepFormStepSchema({\r\n steps,\r\n nameTransformCasing: this.defaultNameTransformationCasing,\r\n });\r\n this.storage = new MultiStepFormStorage<resolvedStep, storageKey>({\r\n key: (storage?.key ?? DEFAULT_STORAGE_KEY) as storageKey,\r\n data: this.stepSchema.value as never,\r\n store: storage?.store,\r\n throwWhenUndefined: storage?.throwWhenUndefined ?? false,\r\n });\r\n\r\n this.stepSchema.subscribe(() => {\r\n this.notify();\r\n });\r\n }\r\n\r\n getSnapshot() {\r\n return this;\r\n }\r\n\r\n mount() {\r\n this.mountCount++;\r\n\r\n if (this.mountCount === 1) {\r\n this.onMount();\r\n }\r\n\r\n return () => {\r\n this.unmount();\r\n };\r\n }\r\n\r\n unmount() {\r\n this.mountCount = Math.max(0, this.mountCount - 1);\r\n\r\n if (this.mountCount === 0) {\r\n this.onUnmount();\r\n }\r\n }\r\n\r\n isMounted() {\r\n return this.mountCount > 0;\r\n }\r\n\r\n protected onMount() {}\r\n protected onUnmount() {}\r\n\r\n protected notify() {\r\n for (const listener of this.listeners) {\r\n listener({\r\n nameTransformCasing: this.defaultNameTransformationCasing,\r\n storage: {\r\n key: this.storage.key,\r\n store: this.storage.store,\r\n },\r\n steps: this.stepSchema.original,\r\n });\r\n }\r\n }\r\n}\r\n\r\nexport function createMultiStepFormSchema<\r\n step extends Step<casing>,\r\n casing extends CasingType = DefaultCasing,\r\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<step, casing>,\r\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\r\n storageKey extends string = DefaultStorageKey\r\n>(\r\n options: MultiStepFormSchemaOptions<\r\n step,\r\n // Allows full autocomplete\r\n Constrain<casing, CasingType>,\r\n storageKey\r\n >\r\n) {\r\n return new MultiStepFormSchema<\r\n step,\r\n casing,\r\n resolvedStep,\r\n stepNumbers,\r\n storageKey\r\n >(options);\r\n}\r\n","import type { MultiStepFormSchema } from './schema';\r\nimport type {\r\n ResolvedStep,\r\n Step,\r\n StepNumbers\r\n} from '@/steps/types';\r\nimport { Subscribable } from './subscribable';\r\nimport type { CasingType } from '@/utils/casing';\r\n\r\nexport type ObserverListener<\r\n TStep extends Step<TCasing>,\r\n TResolvedStep extends ResolvedStep<TStep, TCasing>,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TCasing extends CasingType,\r\n TStorageKey extends string\r\n> = (\r\n schema: MultiStepFormSchema<\r\n TStep,\r\n TCasing,\r\n TResolvedStep,\r\n TStepNumbers,\r\n TStorageKey\r\n >\r\n) => void;\r\n\r\nexport type ObserverOptions<\r\n TStep extends Step<TCasing>,\r\n TResolvedStep extends ResolvedStep<TStep, TCasing>,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TCasing extends CasingType,\r\n TStorageKey extends string\r\n> = {\r\n schema: MultiStepFormSchema<\r\n TStep,\r\n TCasing,\r\n TResolvedStep,\r\n TStepNumbers,\r\n TStorageKey\r\n >;\r\n};\r\n\r\nexport class MultiStepFormObserver<\r\n step extends Step<casing>,\r\n resolvedStep extends ResolvedStep<step, casing>,\r\n stepNumbers extends StepNumbers<resolvedStep>,\r\n casing extends CasingType,\r\n storageKey extends string\r\n> extends Subscribable<\r\n ObserverListener<step, resolvedStep, stepNumbers, casing, storageKey>\r\n> {\r\n protected schema: MultiStepFormSchema<\r\n step,\r\n casing,\r\n resolvedStep,\r\n stepNumbers,\r\n storageKey\r\n >;\r\n private unsubscribeFromSchema?: () => void;\r\n\r\n constructor(\r\n options: ObserverOptions<\r\n step,\r\n resolvedStep,\r\n stepNumbers,\r\n casing,\r\n storageKey\r\n >\r\n ) {\r\n super();\r\n\r\n this.schema = options.schema;\r\n this.subscribeToSchema();\r\n }\r\n\r\n protected subscribeToSchema() {\r\n this.unsubscribeFromSchema = this.schema.subscribe(() => {\r\n this.notify();\r\n });\r\n }\r\n\r\n getSnapshot() {\r\n return this;\r\n }\r\n\r\n getResult() {\r\n return this.schema;\r\n }\r\n\r\n setOptions(\r\n options: Partial<\r\n ObserverOptions<step, resolvedStep, stepNumbers, casing, storageKey>\r\n >\r\n ) {\r\n if (options.schema && options.schema !== this.schema) {\r\n this.unsubscribeFromSchema?.();\r\n this.schema = options.schema;\r\n this.subscribeToSchema();\r\n this.notify();\r\n }\r\n }\r\n\r\n protected notify() {\r\n for (const listener of this.listeners) {\r\n listener(this.schema);\r\n }\r\n }\r\n\r\n destroy() {\r\n this.unsubscribeFromSchema?.();\r\n this.listeners.clear();\r\n }\r\n\r\n protected onSubscribe() {}\r\n\r\n protected onUnsubscribe() {}\r\n}\r\n"],"names":["MultiStepFormLogger","invariant","runStandardValidation","MultiStepFormStepSchemaInternal","isValidStepKey","getStep","v","fieldsUtils"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils/casing.ts","../src/utils/field-types.ts","../src/storage.ts","../src/subscribable.ts","../src/steps/schema.ts","../src/schema.ts","../src/observable.ts"],"sourcesContent":["import type { Expand, SetDefaultString } from './types';\n\nexport type CasingType = (typeof CASING_TYPES)[number];\nexport type ToLower<S extends string> = S extends `${infer F}${infer R}`\n ? `${Lowercase<F>}${ToLower<R>}`\n : S;\n\nexport type CapitalizeWord<S extends string> = S extends `${infer F}${infer R}`\n ? `${Uppercase<F>}${ToLower<R>}`\n : S;\n// Pascal => Capitalize each \"word\" chunk\ntype Pascalize<S extends string> = Capitalize<S>; // naive\n\n// SnakeCase: turn spaces/hyphens into underscores, lowercase\ntype SnakeCase<S extends string> = Lowercase<\n S extends `${infer A} ${infer B}`\n ? `${A}_${SnakeCase<B>}`\n : S extends `${infer A}-${infer B}`\n ? `${A}_${SnakeCase<B>}`\n : S\n>;\n\n// KebabCase: same as snake but with \"-\"\ntype KebabCase<S extends string> = Lowercase<\n S extends `${infer A} ${infer B}`\n ? `${A}-${KebabCase<B>}`\n : S extends `${infer A}_${infer B}`\n ? `${A}-${KebabCase<B>}`\n : S\n>;\n\n// Flat: just strip spaces/underscores/hyphens\ntype RemoveDelimiters<S extends string> = S extends `${infer A} ${infer B}`\n ? `${A}${RemoveDelimiters<B>}`\n : S extends `${infer A}_${infer B}`\n ? `${A}${RemoveDelimiters<B>}`\n : S extends `${infer A}-${infer B}`\n ? `${A}${RemoveDelimiters<B>}`\n : S;\n\n// TitleCase: Capitalize the whole thing\ntype TitleCase<S extends string> = Capitalize<Lowercase<S>>;\n\n// SentenceCase: First word capped, rest lower\ntype SentenceCase<S extends string> = Capitalize<Lowercase<S>>;\nexport type ChangeCasing<\n S extends string,\n T extends CasingType\n> = T extends 'lower'\n ? Lowercase<S>\n : T extends 'upper'\n ? Uppercase<S>\n : T extends 'camel'\n ? Uncapitalize<Pascalize<S>>\n : T extends 'pascal'\n ? Pascalize<S>\n : T extends 'snake'\n ? SnakeCase<S>\n : T extends 'screaming-snake'\n ? Uppercase<SnakeCase<S>>\n : T extends 'kebab'\n ? KebabCase<S>\n : T extends 'flat'\n ? RemoveDelimiters<Lowercase<S>>\n : T extends 'title'\n ? TitleCase<S>\n : T extends 'sentence'\n ? SentenceCase<S>\n : S;\nexport type ChangeObjectCasing<\n T extends object,\n TCasing extends CasingType\n> = Expand<{\n [K in keyof T as K extends string ? ChangeCasing<K, TCasing> : K]: T[K];\n}>;\n\nexport const CASING_TYPES = [\n 'sentence',\n 'title',\n 'camel',\n 'lower',\n 'upper',\n 'pascal',\n 'snake',\n 'screaming-snake',\n 'flat',\n 'kebab',\n] as const;\n\nexport type DefaultCasing = typeof DEFAULT_CASING;\nexport const DEFAULT_CASING: SetDefaultString<CasingType, 'title'> = 'title';\n\n/**\n * Changes the casing of a string according to the specified casing type.\n *\n * @param input - The string to transform.\n * @param type - The casing type to apply.\n * @returns The transformed string in the specified casing.\n */\n// TODO make return type safe\nexport function changeCasing<TValue extends string, TType extends CasingType>(\n input: TValue,\n type: TType\n): ChangeCasing<TValue, TType>;\nexport function changeCasing<TValue extends string, TType extends CasingType>(\n input: TValue,\n type: TType\n) {\n // Step 1: Normalize to words\n const words = input\n // Replace camelCase boundaries with space\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n // Replace separators with space\n .replace(/[-_]+/g, ' ')\n // Trim and split into words\n .trim()\n .split(/\\s+/)\n .map((w) => w.toLowerCase());\n\n // Step 2: Apply casing\n switch (type) {\n case 'sentence':\n return (\n words[0].charAt(0).toUpperCase() +\n words[0].slice(1) +\n (words.length > 1 ? ' ' + words.slice(1).join(' ') : '')\n );\n\n case 'title':\n return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');\n\n case 'camel':\n return (\n words[0] +\n words\n .slice(1)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('')\n );\n\n case 'pascal':\n return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join('');\n\n case 'lower':\n return words.join(' ');\n\n case 'upper':\n return words.join(' ').toUpperCase();\n\n case 'snake':\n return words.join('_');\n\n case 'screaming-snake':\n return words.join('_').toUpperCase();\n\n case 'kebab':\n return words.join('-');\n\n case 'flat':\n return words.join('');\n\n default:\n return input;\n }\n}\n\nexport function quote(str: string, quoteChar: '\"' | \"'\" = '\"') {\n const startsWithQuote = str.startsWith(quoteChar);\n const endsWithQuote = str.endsWith(quoteChar);\n\n if (startsWithQuote && endsWithQuote) {\n // Already wrapped correctly\n return str;\n }\n\n // If it starts or ends with a quote but not both → strip those first\n const trimmed = str.replace(/^['\"]|['\"]$/g, '');\n\n // Then add new quotes consistently\n return `${quoteChar}${trimmed}${quoteChar}`;\n}\n\nexport function isCasingValid(value: unknown): value is CasingType {\n if (typeof value !== 'string') {\n return false;\n }\n\n const isValid = CASING_TYPES.includes(value as CasingType);\n\n // invariant(isValid, () => {\n // const formatter = new Intl.ListFormat('en', {\n // style: 'long',\n // type: 'conjunction',\n // });\n\n // return `${value} is not a valid casing type. Valid types include ${formatter.format(\n // CASING_TYPES.map((word) => quote(word))\n // )}`;\n // });\n\n return isValid;\n}\n\n/**\n * Validates {@linkcode input} is a valid {@linkcode CasingType}.\n *\n * If there is no explicit {@linkcode fallback} value provided,\n * it will default to {@linkcode DEFAULT_CASING}.\n * @param input The input to check.\n * @param fallback An optional fallback value if {@linkcode input} is `undefined`.\n * @returns The {@linkcode input} or {@linkcode fallback} if {@linkcode input} is `undefined` or an {@linkcode isCasingValid invalid} {@linkcode CasingType}.\n */\nexport function setCasingType<TCasing extends CasingType>(\n input: TCasing | undefined,\n fallback: CasingType = DEFAULT_CASING\n) {\n if (isCasingValid(input)) {\n return input;\n }\n\n return fallback;\n}\n","import type { SetDefaultString } from './types';\n\nexport type FieldType = (typeof FIELD_TYPES)[number];\nexport type DefaultFieldType = typeof DEFAULT_FIELD_TYPE;\nexport const FIELD_TYPES = [\n 'string',\n 'string.phone',\n 'string.email',\n 'string.time',\n 'number',\n 'number.counter',\n 'date',\n 'dateTime',\n 'boolean.switch',\n] as const;\nexport const DEFAULT_FIELD_TYPE: SetDefaultString<FieldType, 'string'> =\n 'string';\n\nexport function isFieldType(value: unknown): value is FieldType {\n return typeof value === 'string' && FIELD_TYPES.includes(value as FieldType);\n}\n","import type { Updater } from '@/steps/types';\nimport { invariant } from '@/utils/invariant';\nimport { MultiStepFormLogger } from '@/utils/logger';\n\nexport type DefaultStorageKey = typeof DEFAULT_STORAGE_KEY;\nexport type StorageConfig<TData, TKey extends string> = {\n key: TKey;\n data: TData;\n store?: Storage;\n /**\n * An extra option to throw an error when {@linkcode window} is `undefined`\n * @default false\n */\n throwWhenUndefined?: boolean;\n};\n\nconst WINDOW_UNDEFINED_MESSAGE =\n '\"window\" in undefined. No storage is available';\nexport const DEFAULT_STORAGE_KEY = 'MultiStepForm';\n\nexport class MultiStepFormStorage<\n data,\n key extends string = DefaultStorageKey\n> {\n readonly key: key;\n readonly store!: Storage;\n readonly data: data;\n private readonly log: MultiStepFormLogger;\n private readonly shouldRunActions: boolean;\n private readonly throwWhenUndefined: boolean;\n\n constructor(config: StorageConfig<data, key>) {\n const { key, data, store, throwWhenUndefined = false } = config;\n\n this.log = new MultiStepFormLogger({\n prefix: DEFAULT_STORAGE_KEY,\n });\n this.key = key;\n this.data = data;\n this.throwWhenUndefined = throwWhenUndefined;\n\n if (store) {\n this.store = store;\n this.shouldRunActions = true;\n\n if (typeof window === 'undefined') {\n this.shouldRunActions = false;\n this.log.warn(WINDOW_UNDEFINED_MESSAGE);\n }\n } else if (typeof window !== 'undefined') {\n this.store = window.localStorage;\n this.shouldRunActions = true;\n } else {\n this.shouldRunActions = false;\n this.log.warn(WINDOW_UNDEFINED_MESSAGE);\n }\n }\n\n private throwOnEmptyStore() {\n if (!this.throwWhenUndefined) {\n return;\n }\n\n invariant(this.store, () => {\n if (this.shouldRunActions) {\n return WINDOW_UNDEFINED_MESSAGE;\n }\n\n return 'No storage available';\n });\n }\n\n private resolveValue(value: Updater<data>) {\n if (typeof value === 'object') {\n return value;\n }\n\n if (typeof value === 'function') {\n return (value as (input: data) => data)(this.data);\n }\n\n this.log.error(\n `The updater value must be a function or object. Was a ${typeof value}`,\n { throw: true }\n );\n }\n\n hasKey() {\n return this.store.getItem(this.key) !== null;\n }\n\n get() {\n this.throwOnEmptyStore();\n\n if (!this.shouldRunActions) {\n return;\n }\n\n const item = this.store.getItem(this.key);\n\n if (item) {\n const parsed = JSON.parse(item);\n\n return parsed as data;\n }\n }\n\n remove() {\n this.throwOnEmptyStore();\n\n if (!this.shouldRunActions) {\n return;\n }\n\n this.store.removeItem(this.key);\n }\n\n add(value: Updater<data>) {\n this.throwOnEmptyStore();\n\n if (!this.shouldRunActions) {\n return;\n }\n\n const resolvedValue = JSON.stringify(this.resolveValue(value));\n\n this.store.setItem(this.key, resolvedValue);\n }\n}\n","export abstract class Subscribable<TListener extends Function> {\n protected listeners = new Set<TListener>();\n\n constructor() {\n this.subscribe = this.subscribe.bind(this);\n }\n\n subscribe(listener: TListener) {\n this.listeners.add(listener);\n\n this.onSubscribe();\n\n return () => {\n this.listeners.delete(listener);\n this.onUnsubscribe();\n };\n }\n\n hasListeners() {\n return this.listeners.size > 0;\n }\n\n protected onSubscribe() {}\n protected onUnsubscribe() {}\n protected abstract notify(): void;\n abstract getSnapshot(): this;\n}\n","import {\n MultiStepFormStepSchemaInternal,\n isValidStepKey,\n} from '@/internals/step-schema';\nimport {\n DEFAULT_STORAGE_KEY,\n DefaultStorageKey,\n MultiStepFormStorage,\n} from '@/storage';\nimport {\n DEFAULT_CASING,\n DEFAULT_FIELD_TYPE,\n changeCasing,\n isCasingValid,\n isFieldType,\n setCasingType,\n type CasingType,\n type Constrain,\n type DefaultCasing,\n type Expand,\n type Join,\n} from '@/utils';\nimport { invariant } from '@/utils/invariant';\nimport {\n runStandardValidation,\n type AnyValidator,\n type DefaultValidator,\n type StandardSchemaValidator,\n} from '@/utils/validator';\nimport { Subscribable } from '../subscribable';\nimport { fields as fieldsUtils } from './fields';\nimport {\n AnyResolvedStep,\n AnyStepField,\n AnyStepFieldOption,\n CreateHelperFunctionOptionsWithCustomCtxOptions,\n CreateHelperFunctionOptionsWithValidator,\n CreateHelperFunctionOptionsWithoutValidator,\n CreateStepHelperFn,\n CreatedHelperFnWithInput,\n CreatedHelperFnWithoutInput,\n ExtractStepFromKey,\n FirstStep,\n GetCurrentStep,\n HelperFnChosenSteps,\n HelperFnWithValidator,\n HelperFnWithoutValidator,\n InferStepOptions,\n LastStep,\n MultiStepFormSchemaStepConfig,\n ResolvedFields,\n ResolvedStep,\n Step,\n StepData,\n StepNumbers,\n StepOptions,\n UnionToTuple,\n UpdateFn,\n ValidStepKey\n} from './types';\nimport { getStep, type GetStepOptions } from './utils';\n\nexport interface MultiStepFormStepSchemaFunctions<\n TResolvedStep extends AnyResolvedStep,\n TStepNumbers extends StepNumbers<TResolvedStep>\n> {\n update: UpdateFn.general<TResolvedStep, TStepNumbers>;\n createHelperFn: CreateStepHelperFn<TResolvedStep, TStepNumbers>;\n}\nexport type AsType = (typeof AS_TYPES)[number];\ntype Quote<T extends string[]> = {\n [K in keyof T]: T[K] extends string ? `'${T[K]}'` : never;\n};\nexport type AsTypeMap<\n resolvedStep extends AnyResolvedStep,\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>\n> = {\n // Exclude is needed due to all the Constrains\n string: Exclude<\n Join<\n Constrain<\n Quote<Constrain<UnionToTuple<`${stepNumbers}`>, string[]>>,\n string[]\n >,\n ' | '\n >,\n ''\n >;\n number: Exclude<\n Join<Constrain<UnionToTuple<`${stepNumbers}`>, string[]>, ' | '>,\n ''\n >;\n 'array.string': UnionToTuple<`${stepNumbers}`>;\n 'array.string.untyped': string[];\n};\nexport type AsFunctionReturn<\n resolvedStep extends AnyResolvedStep,\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>,\n asType extends AsType\n> = AsTypeMap<resolvedStep, stepNumbers>[asType];\nexport type AsFunction<\n resolvedStep extends AnyResolvedStep,\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>\n> = <asType extends AsType>(\n asType: asType\n) => AsFunctionReturn<resolvedStep, stepNumbers, asType>;\nexport type MultiStepFormStepStepsConfig<\n TStep extends Step<TCasing>,\n TCasing extends CasingType,\n TResolvedStep extends ResolvedStep<TStep, TCasing> = ResolvedStep<\n TStep,\n TCasing\n >,\n TStepNumbers extends StepNumbers<TResolvedStep> = StepNumbers<TResolvedStep>\n> = {\n first: FirstStep<TResolvedStep>;\n last: LastStep<TResolvedStep>;\n value: ReadonlyArray<TStepNumbers>;\n as: AsFunction<TResolvedStep, TStepNumbers>;\n isValidStepNumber: (stepNumber: number) => stepNumber is TStepNumbers;\n isValidStepKey: (\n value: string\n ) => value is Constrain<keyof TResolvedStep, string>;\n};\nexport type MultiStepFormStepSchemaListener<\n TStep extends Step<TCasing>,\n TCasing extends CasingType\n> = (data: {\n original: InferStepOptions<TStep>;\n value: ResolvedStep<TStep, TCasing>;\n steps: MultiStepFormStepStepsConfig<TStep, TCasing>;\n defaultNameTransformationCasing: TCasing;\n}) => void;\n\n/**\n * Available transformation types for the step numbers.\n */\nconst AS_TYPES = [\n 'string',\n 'number',\n 'array.string',\n 'array.string.untyped',\n] as const;\nexport const VALIDATED_STEP_REGEX = /^step\\d+$/i;\n\ntype ValueCheck<T> = (v: unknown) => v is T;\n\ntype FieldChecks<T extends object> = {\n [K in keyof T]: ValueCheck<T[K]>;\n};\n\nfunction assertObjectFields<T extends object>(\n obj: unknown,\n checks: FieldChecks<T>\n): obj is T {\n if (typeof obj !== 'object' || obj === null) return false;\n\n for (const key of Object.keys(checks) as (keyof T)[]) {\n // Check that the property exists\n if (!(key in obj)) return false;\n\n // Now check the type\n const checkFn = checks[key];\n const value = (obj as any)[key];\n if (!checkFn(value)) return false;\n }\n\n return true;\n}\n\nfunction createFieldLabel(\n label: string | false | undefined,\n fieldName: string,\n casingType: CasingType\n) {\n return label ?? changeCasing(fieldName, casingType);\n}\n\nfunction createStepFields(options: {\n fields: AnyStepField;\n validateFields:\n | Constrain<unknown, AnyValidator, DefaultValidator>\n | undefined;\n defaultCasing: CasingType;\n}) {\n const resolvedFields: Record<string, unknown> = {};\n const { fields, defaultCasing, validateFields } = options;\n\n for (const [name, values] of Object.entries(fields)) {\n invariant(\n typeof name === 'string',\n `Each key for the \"fields\" option must be a string. Key ${name} was a ${typeof name}`\n );\n invariant(\n typeof values === 'object',\n `The value for key ${name} must be an object. Was ${typeof values}`\n );\n\n const {\n defaultValue,\n label,\n nameTransformCasing,\n type = DEFAULT_FIELD_TYPE,\n } = values;\n\n if (validateFields) {\n resolvedFields[name] = defaultValue;\n } else {\n const casing = nameTransformCasing ?? defaultCasing;\n\n resolvedFields[name] = {\n ...(resolvedFields[name] as Record<string, unknown>),\n nameTransformCasing: casing,\n type,\n defaultValue,\n label: createFieldLabel(label, name, casing),\n\n // TODO add more fields here\n };\n }\n }\n\n if (validateFields) {\n const validatedFields = runStandardValidation(\n validateFields as StandardSchemaValidator,\n resolvedFields\n );\n\n invariant(\n typeof validatedFields === 'object',\n `The result of the validated fields must be an object, was (${typeof validatedFields}). This is probably an internal error, so open up an issue about it`\n );\n invariant(\n !!validatedFields,\n 'The result of the validated fields must be defined. This is probably an internal error, so open up an issue about it'\n );\n\n for (const [name, defaultValue] of Object.entries(validatedFields)) {\n const currentField = fields[name];\n\n invariant(\n currentField,\n `No field found in the fields config for \"${name}\"`\n );\n\n const {\n label,\n type = DEFAULT_FIELD_TYPE,\n nameTransformCasing,\n } = currentField;\n const casing = nameTransformCasing ?? defaultCasing;\n\n resolvedFields[name] = {\n ...(resolvedFields[name] as Record<string, unknown>),\n nameTransformCasing: casing,\n type,\n defaultValue,\n label: createFieldLabel(label, name, casing),\n };\n }\n }\n\n return resolvedFields;\n}\n\nexport function createStep<\n step extends Step<casing>,\n casing extends CasingType = DefaultCasing\n>(stepsConfig: InferStepOptions<step>) {\n const resolvedSteps = {} as ResolvedStep<step, casing>;\n\n invariant(!!stepsConfig, 'The steps config must be defined', TypeError);\n invariant(\n typeof stepsConfig === 'object',\n `The steps config must be an object, was (${typeof stepsConfig})`,\n TypeError\n );\n\n for (const [stepKey, stepValue] of Object.entries(stepsConfig)) {\n invariant(\n typeof stepKey === 'string',\n `Each key for the step config must be a string. Key \"${stepKey}\" was ${typeof stepKey} `,\n TypeError\n );\n invariant(\n VALIDATED_STEP_REGEX.test(stepKey),\n `The key \"${stepKey}\" isn't formatted properly. Each key in the step config must be the following format: \"step{number}\"`\n );\n\n const validStepKey = stepKey as keyof typeof resolvedSteps;\n const {\n fields,\n title,\n nameTransformCasing: defaultCasing = DEFAULT_CASING,\n description,\n validateFields,\n } = stepValue;\n\n const currentStep = validStepKey.toString().replace('step', '');\n\n invariant(\n fields,\n `Missing fields for step ${currentStep} (${String(validStepKey)})`,\n TypeError\n );\n invariant(\n typeof fields === 'object',\n 'Fields must be an object',\n TypeError\n );\n invariant(\n Object.keys(fields).length > 0,\n `The fields config for step ${currentStep} (${String(\n validStepKey\n )}) is empty. Please add a field`\n );\n invariant(\n typeof fields === 'object',\n `The \"fields\" property must be an object. Was ${typeof fields}`\n );\n\n const resolvedFields = createStepFields({\n defaultCasing,\n fields,\n validateFields,\n });\n\n resolvedSteps[validStepKey] = {\n ...resolvedSteps[validStepKey],\n title,\n nameTransformCasing: defaultCasing,\n // Only add the description if it's defined\n ...(typeof description === 'string' ? { description } : {}),\n fields: resolvedFields,\n };\n }\n\n return resolvedSteps;\n}\n\nexport class MultiStepFormStepSchema<\n step extends Step<casing>,\n casing extends CasingType = DefaultCasing,\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<\n step,\n casing\n >,\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\n storageKey extends string = DefaultStorageKey\n >\n extends Subscribable<MultiStepFormStepSchemaListener<step, casing>>\n implements MultiStepFormStepSchemaFunctions<resolvedStep, stepNumbers>\n{\n /**\n * The original config before any validation or transformations have been applied.\n */\n readonly original: InferStepOptions<step>;\n /**\n * The resolved step values.\n */\n value: resolvedStep;\n readonly steps: MultiStepFormStepStepsConfig<step, casing>;\n readonly defaultNameTransformationCasing: casing;\n //@ts-ignore\n private readonly firstStep: StepData<resolvedStep, FirstStep<resolvedStep>>;\n private readonly lastStep: StepData<resolvedStep, LastStep<resolvedStep>>;\n private readonly stepNumbers: Array<number>;\n private readonly storage: MultiStepFormStorage<resolvedStep, storageKey>;\n readonly #internal: MultiStepFormStepSchemaInternal<\n resolvedStep,\n stepNumbers\n >;\n\n constructor(\n config: MultiStepFormSchemaStepConfig<\n step,\n Constrain<casing, CasingType>,\n storageKey\n >\n ) {\n super();\n\n const { steps, nameTransformCasing, storage } = config;\n\n this.defaultNameTransformationCasing = setCasingType(\n nameTransformCasing\n ) as casing;\n\n this.original = steps;\n\n this.value = createStep<step, casing>(this.original) as resolvedStep;\n this.storage = new MultiStepFormStorage<resolvedStep, storageKey>({\n data: this.value,\n key: (storage?.key ?? DEFAULT_STORAGE_KEY) as storageKey,\n store: storage?.store,\n throwWhenUndefined: storage?.throwWhenUndefined ?? false,\n });\n this.#internal = new MultiStepFormStepSchemaInternal<\n resolvedStep,\n stepNumbers\n >({\n getValue: () => this.value,\n setValue: (next) => this.handlePostUpdate(next),\n });\n\n this.value = this.#internal.enrichValues(this.value);\n this.stepNumbers = Object.keys(this.value).map((key) =>\n Number.parseInt(key.replace('step', ''))\n );\n\n this.firstStep = this.first();\n this.lastStep = this.last();\n this.steps = {\n first: this.firstStep.step,\n last: this.lastStep.step,\n value: this.stepNumbers as unknown as ReadonlyArray<stepNumbers>,\n as: (asType): any => {\n invariant(\n typeof asType === 'string',\n `The type of the target transformation type must be a string, was ${typeof asType}`\n );\n\n if (asType === 'string') {\n return this.stepNumbers.map((value) => `'${value}'`).join(' | ');\n }\n\n if (asType === 'number') {\n return this.stepNumbers.join(' | ');\n }\n\n if (asType.includes('array.string')) {\n return this.stepNumbers.map((value) => `${value}`);\n }\n\n throw new Error(\n `Transformation type \"${asType}\" is not supported. Available transformations include: ${AS_TYPES.map(\n (value) => `\"${value}\"`\n ).join(', ')}`\n );\n },\n isValidStepNumber: (stepNumber): stepNumber is stepNumbers =>\n this.stepNumbers.includes(stepNumber),\n isValidStepKey: (value) =>\n isValidStepKey<resolvedStep>(this.value, value),\n };\n\n this.sync();\n }\n\n /**\n * @internal\n */\n __getStorage() {\n return this.storage;\n }\n\n getSnapshot() {\n return this;\n }\n\n /**\n * Syncs the values from storage to {@linkcode value}.\n */\n sync() {\n // TODO add \"syncOptions\" so caller can chose where to sync from ('storage' | 'instance')\n const storageValues = this.__getStorage().get();\n\n if (storageValues) {\n const enrichedValues = this.#internal.enrichValues(storageValues);\n\n this.value = { ...enrichedValues };\n }\n }\n\n protected notify() {\n for (const listener of this.listeners) {\n listener({\n defaultNameTransformationCasing: this.defaultNameTransformationCasing,\n original: this.original,\n steps: this.steps,\n value: this.value,\n });\n }\n }\n\n /**\n * Gets the data for a specific step.\n * @param options The options for getting the step data.\n * @returns The step data for the target step.\n */\n get<stepNumber extends stepNumbers>(\n options: GetStepOptions<resolvedStep, stepNumbers, stepNumber>\n ) {\n return getStep(this.value)(options);\n }\n\n /**\n * Gets the data for the first step.\n * @returns The data for the first step.\n */\n first() {\n const firstStep = Math.min(...this.stepNumbers) as FirstStep<resolvedStep>;\n\n return this.get({ step: firstStep });\n }\n\n /**\n * Gets the data for the last step.\n * @returns The data for the last step.\n */\n last() {\n const lastStep = Math.max(...this.stepNumbers);\n\n return this.get<LastStep<resolvedStep>>({ step: lastStep as never });\n }\n\n protected handlePostUpdate(next: resolvedStep) {\n this.value = { ...next };\n\n this.__getStorage().add(this.value);\n this.sync();\n this.notify();\n }\n\n update<\n targetStep extends ValidStepKey<stepNumbers>,\n field extends UpdateFn.chosenFields<\n UpdateFn.resolvedStep<resolvedStep, stepNumbers, targetStep>\n > = 'all',\n additionalCtx extends Record<string, unknown> = {}\n >(\n options: UpdateFn.options<\n resolvedStep,\n stepNumbers,\n targetStep,\n field,\n additionalCtx\n >\n ) {\n this.#internal.update(options);\n }\n\n /**\n * Create a helper function with validated input.\n */\n createHelperFn<\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\n validator,\n additionalCtx extends Record<string, unknown>,\n response\n >(\n options: CreateHelperFunctionOptionsWithValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n validator,\n additionalCtx\n >,\n fn: HelperFnWithValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n validator,\n additionalCtx,\n response\n >\n ): CreatedHelperFnWithInput<validator, response>;\n /**\n * Create a helper function without input.\n */\n createHelperFn<\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\n additionalCtx extends Record<string, unknown>,\n response\n >(\n options: CreateHelperFunctionOptionsWithoutValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps\n > &\n CreateHelperFunctionOptionsWithCustomCtxOptions<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n additionalCtx\n >,\n fn: HelperFnWithoutValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n additionalCtx,\n response\n >\n ): CreatedHelperFnWithoutInput<response>;\n // Implementation\n createHelperFn<\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\n response,\n additionalCtx extends Record<string, unknown>,\n validator = never\n >(\n options:\n | CreateHelperFunctionOptionsWithValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n validator,\n additionalCtx\n >\n | CreateHelperFunctionOptionsWithoutValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps\n >,\n fn:\n | HelperFnWithValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n validator,\n additionalCtx,\n response\n >\n | HelperFnWithoutValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n additionalCtx,\n response\n >\n ) {\n const { stepData, ...rest } = options;\n\n return this.#internal.createStepHelperFn(stepData)(rest, fn);\n }\n\n /**\n * Validates that a given object is the proper shape for step data.\n * @param value\n */\n static hasData<\n step extends Step<casing>,\n resolvedStep extends ResolvedStep<step, casing>,\n stepNumbers extends StepNumbers<resolvedStep>,\n casing extends CasingType = DefaultCasing\n >(\n value: unknown,\n options?: {\n optionalKeysToCheck?: FieldChecks<\n Pick<StepOptions, 'description' | 'validateFields'>\n >;\n }\n ): value is GetCurrentStep<resolvedStep, stepNumbers> {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n return assertObjectFields<\n | GetCurrentStep<resolvedStep, stepNumbers>\n | (Omit<StepOptions, 'fields'> & {\n fields: Expand<\n ResolvedFields<InferStepOptions<step>, keyof InferStepOptions<step>>\n >;\n })\n >(value, {\n title: (v) => typeof v === 'string',\n fields: (\n v\n ): v is Expand<\n ResolvedFields<InferStepOptions<step>, keyof InferStepOptions<step>>\n > => {\n if (v === null || typeof v !== 'object') {\n return false;\n }\n\n for (const key of Object.keys(v)) {\n if (typeof key !== 'string' || !(key in v)) {\n return false;\n }\n\n const current = (v as Record<string, unknown>)[key];\n\n if (current === null || typeof current !== 'object') {\n return false;\n }\n\n const hasField = assertObjectFields<AnyStepFieldOption>(current, {\n defaultValue: (v): v is {} => v !== 'undefined' && v !== null,\n label: (v) =>\n typeof v === 'string' || (typeof v === 'boolean' && !v),\n nameTransformCasing: isCasingValid,\n type: isFieldType,\n });\n\n if (!hasField) {\n return false;\n }\n }\n\n return true;\n },\n createHelperFn: (\n v\n ): v is GetCurrentStep<resolvedStep, stepNumbers>['createHelperFn'] =>\n typeof v === 'function',\n // update: (v): v is GetCurrentStep<resolvedStep, stepNumbers>['update'] =>\n // typeof v === 'function',\n nameTransformCasing: isCasingValid,\n ...options?.optionalKeysToCheck,\n });\n }\n\n /**\n * Gets the value of a given field for a given step.\n * @param step The step to get the value from.\n * @param field The field to get the value from.\n * @returns The value of the {@linkcode field}.\n */\n getValue<\n step extends keyof resolvedStep,\n field extends fieldsUtils.getDeep<resolvedStep, step>\n >(step: step, field: field) {\n const stepData = this.value[step];\n const baseErrorMessage = `Unable to get the value for \"${String(\n step\n )}.fields.${String(field)}\"`;\n\n invariant('fields' in stepData, baseErrorMessage);\n invariant(\n typeof stepData.fields === 'object',\n `${baseErrorMessage} because \"fields\" is not an object. This shouldn't be the case, so please open an issue`\n );\n\n const fields = stepData.fields as AnyStepField;\n\n const defaultValue = fieldsUtils.resolvedDeepPath<\n resolvedStep,\n step,\n fieldsUtils.get<resolvedStep, step>,\n field\n >(field, fields as fieldsUtils.get<resolvedStep, step>);\n\n return defaultValue;\n }\n}\n","import {\n MultiStepFormStepSchema,\n type MultiStepFormSchemaStepConfig,\n type ResolvedStep,\n type Step,\n type StepNumbers,\n} from '@/steps';\nimport {\n setCasingType,\n type CasingType,\n type Constrain,\n type DefaultCasing,\n} from '@/utils';\nimport {\n DEFAULT_STORAGE_KEY,\n MultiStepFormStorage,\n type DefaultStorageKey,\n} from './storage.js';\nimport { Subscribable } from './subscribable.js';\n\nexport interface MultiStepFormSchemaOptions<\n TStep extends Step<TCasing>,\n TCasing extends CasingType,\n TStorageKey extends string\n> extends MultiStepFormSchemaStepConfig<TStep, TCasing, TStorageKey> {}\nexport type MultiStepFormSchemaListener<\n TStep extends Step<TCasing>,\n TCasing extends CasingType,\n TStorageKey extends string\n> = (data: MultiStepFormSchemaOptions<TStep, TCasing, TStorageKey>) => void;\n\nexport class MultiStepFormSchema<\n step extends Step<casing>,\n casing extends CasingType = DefaultCasing,\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<step, casing>,\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\n storageKey extends string = DefaultStorageKey\n> extends Subscribable<MultiStepFormSchemaListener<step, casing, storageKey>> {\n readonly defaultNameTransformationCasing: casing;\n readonly stepSchema: MultiStepFormStepSchema<\n step,\n casing,\n resolvedStep,\n stepNumbers,\n storageKey\n >;\n storage: MultiStepFormStorage<resolvedStep, storageKey>;\n private mountCount = 0;\n\n constructor(\n options: MultiStepFormSchemaOptions<\n step,\n // Allows full autocomplete\n Constrain<casing, CasingType>,\n storageKey\n >\n ) {\n super();\n\n const { steps, nameTransformCasing, storage } = options;\n\n this.defaultNameTransformationCasing = setCasingType(\n nameTransformCasing\n ) as casing;\n // @ts-ignore Type instantiation is excessively deep and possibly infinite\n this.stepSchema = new MultiStepFormStepSchema({\n steps,\n nameTransformCasing: this.defaultNameTransformationCasing,\n });\n this.storage = new MultiStepFormStorage<resolvedStep, storageKey>({\n key: (storage?.key ?? DEFAULT_STORAGE_KEY) as storageKey,\n data: this.stepSchema.value as never,\n store: storage?.store,\n throwWhenUndefined: storage?.throwWhenUndefined ?? false,\n });\n\n this.stepSchema.subscribe(() => {\n this.notify();\n });\n }\n\n getSnapshot() {\n return this;\n }\n\n mount() {\n this.mountCount++;\n\n if (this.mountCount === 1) {\n this.onMount();\n }\n\n return () => {\n this.unmount();\n };\n }\n\n unmount() {\n this.mountCount = Math.max(0, this.mountCount - 1);\n\n if (this.mountCount === 0) {\n this.onUnmount();\n }\n }\n\n isMounted() {\n return this.mountCount > 0;\n }\n\n protected onMount() {}\n protected onUnmount() {}\n\n protected notify() {\n for (const listener of this.listeners) {\n listener({\n nameTransformCasing: this.defaultNameTransformationCasing,\n storage: {\n key: this.storage.key,\n store: this.storage.store,\n },\n steps: this.stepSchema.original,\n });\n }\n }\n}\n\nexport function createMultiStepFormSchema<\n step extends Step<casing>,\n casing extends CasingType = DefaultCasing,\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<step, casing>,\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\n storageKey extends string = DefaultStorageKey\n>(\n options: MultiStepFormSchemaOptions<\n step,\n // Allows full autocomplete\n Constrain<casing, CasingType>,\n storageKey\n >\n) {\n return new MultiStepFormSchema<\n step,\n casing,\n resolvedStep,\n stepNumbers,\n storageKey\n >(options);\n}\n","import type { MultiStepFormSchema } from './schema';\nimport type {\n ResolvedStep,\n Step,\n StepNumbers\n} from '@/steps/types';\nimport { Subscribable } from './subscribable';\nimport type { CasingType } from '@/utils/casing';\n\nexport type ObserverListener<\n TStep extends Step<TCasing>,\n TResolvedStep extends ResolvedStep<TStep, TCasing>,\n TStepNumbers extends StepNumbers<TResolvedStep>,\n TCasing extends CasingType,\n TStorageKey extends string\n> = (\n schema: MultiStepFormSchema<\n TStep,\n TCasing,\n TResolvedStep,\n TStepNumbers,\n TStorageKey\n >\n) => void;\n\nexport type ObserverOptions<\n TStep extends Step<TCasing>,\n TResolvedStep extends ResolvedStep<TStep, TCasing>,\n TStepNumbers extends StepNumbers<TResolvedStep>,\n TCasing extends CasingType,\n TStorageKey extends string\n> = {\n schema: MultiStepFormSchema<\n TStep,\n TCasing,\n TResolvedStep,\n TStepNumbers,\n TStorageKey\n >;\n};\n\nexport class MultiStepFormObserver<\n step extends Step<casing>,\n resolvedStep extends ResolvedStep<step, casing>,\n stepNumbers extends StepNumbers<resolvedStep>,\n casing extends CasingType,\n storageKey extends string\n> extends Subscribable<\n ObserverListener<step, resolvedStep, stepNumbers, casing, storageKey>\n> {\n protected schema: MultiStepFormSchema<\n step,\n casing,\n resolvedStep,\n stepNumbers,\n storageKey\n >;\n private unsubscribeFromSchema?: () => void;\n\n constructor(\n options: ObserverOptions<\n step,\n resolvedStep,\n stepNumbers,\n casing,\n storageKey\n >\n ) {\n super();\n\n this.schema = options.schema;\n this.subscribeToSchema();\n }\n\n protected subscribeToSchema() {\n this.unsubscribeFromSchema = this.schema.subscribe(() => {\n this.notify();\n });\n }\n\n getSnapshot() {\n return this;\n }\n\n getResult() {\n return this.schema;\n }\n\n setOptions(\n options: Partial<\n ObserverOptions<step, resolvedStep, stepNumbers, casing, storageKey>\n >\n ) {\n if (options.schema && options.schema !== this.schema) {\n this.unsubscribeFromSchema?.();\n this.schema = options.schema;\n this.subscribeToSchema();\n this.notify();\n }\n }\n\n protected notify() {\n for (const listener of this.listeners) {\n listener(this.schema);\n }\n }\n\n destroy() {\n this.unsubscribeFromSchema?.();\n this.listeners.clear();\n }\n\n protected onSubscribe() {}\n\n protected onUnsubscribe() {}\n}\n"],"names":["MultiStepFormLogger","invariant","runStandardValidation","MultiStepFormStepSchemaInternal","isValidStepKey","getStep","v","fieldsUtils"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/utils/casing.ts","../src/utils/field-types.ts","../src/storage.ts","../src/subscribable.ts","../src/steps/schema.ts","../src/schema.ts","../src/observable.ts"],"sourcesContent":["import type { Expand, SetDefaultString } from './types';\r\n\r\nexport type CasingType = (typeof CASING_TYPES)[number];\r\nexport type ToLower<S extends string> = S extends `${infer F}${infer R}`\r\n ? `${Lowercase<F>}${ToLower<R>}`\r\n : S;\r\n\r\nexport type CapitalizeWord<S extends string> = S extends `${infer F}${infer R}`\r\n ? `${Uppercase<F>}${ToLower<R>}`\r\n : S;\r\n// Pascal => Capitalize each \"word\" chunk\r\ntype Pascalize<S extends string> = Capitalize<S>; // naive\r\n\r\n// SnakeCase: turn spaces/hyphens into underscores, lowercase\r\ntype SnakeCase<S extends string> = Lowercase<\r\n S extends `${infer A} ${infer B}`\r\n ? `${A}_${SnakeCase<B>}`\r\n : S extends `${infer A}-${infer B}`\r\n ? `${A}_${SnakeCase<B>}`\r\n : S\r\n>;\r\n\r\n// KebabCase: same as snake but with \"-\"\r\ntype KebabCase<S extends string> = Lowercase<\r\n S extends `${infer A} ${infer B}`\r\n ? `${A}-${KebabCase<B>}`\r\n : S extends `${infer A}_${infer B}`\r\n ? `${A}-${KebabCase<B>}`\r\n : S\r\n>;\r\n\r\n// Flat: just strip spaces/underscores/hyphens\r\ntype RemoveDelimiters<S extends string> = S extends `${infer A} ${infer B}`\r\n ? `${A}${RemoveDelimiters<B>}`\r\n : S extends `${infer A}_${infer B}`\r\n ? `${A}${RemoveDelimiters<B>}`\r\n : S extends `${infer A}-${infer B}`\r\n ? `${A}${RemoveDelimiters<B>}`\r\n : S;\r\n\r\n// TitleCase: Capitalize the whole thing\r\ntype TitleCase<S extends string> = Capitalize<Lowercase<S>>;\r\n\r\n// SentenceCase: First word capped, rest lower\r\ntype SentenceCase<S extends string> = Capitalize<Lowercase<S>>;\r\nexport type ChangeCasing<\r\n S extends string,\r\n T extends CasingType\r\n> = T extends 'lower'\r\n ? Lowercase<S>\r\n : T extends 'upper'\r\n ? Uppercase<S>\r\n : T extends 'camel'\r\n ? Uncapitalize<Pascalize<S>>\r\n : T extends 'pascal'\r\n ? Pascalize<S>\r\n : T extends 'snake'\r\n ? SnakeCase<S>\r\n : T extends 'screaming-snake'\r\n ? Uppercase<SnakeCase<S>>\r\n : T extends 'kebab'\r\n ? KebabCase<S>\r\n : T extends 'flat'\r\n ? RemoveDelimiters<Lowercase<S>>\r\n : T extends 'title'\r\n ? TitleCase<S>\r\n : T extends 'sentence'\r\n ? SentenceCase<S>\r\n : S;\r\nexport type ChangeObjectCasing<\r\n T extends object,\r\n TCasing extends CasingType\r\n> = Expand<{\r\n [K in keyof T as K extends string ? ChangeCasing<K, TCasing> : K]: T[K];\r\n}>;\r\n\r\nexport const CASING_TYPES = [\r\n 'sentence',\r\n 'title',\r\n 'camel',\r\n 'lower',\r\n 'upper',\r\n 'pascal',\r\n 'snake',\r\n 'screaming-snake',\r\n 'flat',\r\n 'kebab',\r\n] as const;\r\n\r\nexport type DefaultCasing = typeof DEFAULT_CASING;\r\nexport const DEFAULT_CASING: SetDefaultString<CasingType, 'title'> = 'title';\r\n\r\n/**\r\n * Changes the casing of a string according to the specified casing type.\r\n *\r\n * @param input - The string to transform.\r\n * @param type - The casing type to apply.\r\n * @returns The transformed string in the specified casing.\r\n */\r\n// TODO make return type safe\r\nexport function changeCasing<TValue extends string, TType extends CasingType>(\r\n input: TValue,\r\n type: TType\r\n): ChangeCasing<TValue, TType>;\r\nexport function changeCasing<TValue extends string, TType extends CasingType>(\r\n input: TValue,\r\n type: TType\r\n) {\r\n // Step 1: Normalize to words\r\n const words = input\r\n // Replace camelCase boundaries with space\r\n .replace(/([a-z])([A-Z])/g, '$1 $2')\r\n // Replace separators with space\r\n .replace(/[-_]+/g, ' ')\r\n // Trim and split into words\r\n .trim()\r\n .split(/\\s+/)\r\n .map((w) => w.toLowerCase());\r\n\r\n // Step 2: Apply casing\r\n switch (type) {\r\n case 'sentence':\r\n return (\r\n words[0].charAt(0).toUpperCase() +\r\n words[0].slice(1) +\r\n (words.length > 1 ? ' ' + words.slice(1).join(' ') : '')\r\n );\r\n\r\n case 'title':\r\n return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');\r\n\r\n case 'camel':\r\n return (\r\n words[0] +\r\n words\r\n .slice(1)\r\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\r\n .join('')\r\n );\r\n\r\n case 'pascal':\r\n return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join('');\r\n\r\n case 'lower':\r\n return words.join(' ');\r\n\r\n case 'upper':\r\n return words.join(' ').toUpperCase();\r\n\r\n case 'snake':\r\n return words.join('_');\r\n\r\n case 'screaming-snake':\r\n return words.join('_').toUpperCase();\r\n\r\n case 'kebab':\r\n return words.join('-');\r\n\r\n case 'flat':\r\n return words.join('');\r\n\r\n default:\r\n return input;\r\n }\r\n}\r\n\r\nexport function quote(str: string, quoteChar: '\"' | \"'\" = '\"') {\r\n const startsWithQuote = str.startsWith(quoteChar);\r\n const endsWithQuote = str.endsWith(quoteChar);\r\n\r\n if (startsWithQuote && endsWithQuote) {\r\n // Already wrapped correctly\r\n return str;\r\n }\r\n\r\n // If it starts or ends with a quote but not both → strip those first\r\n const trimmed = str.replace(/^['\"]|['\"]$/g, '');\r\n\r\n // Then add new quotes consistently\r\n return `${quoteChar}${trimmed}${quoteChar}`;\r\n}\r\n\r\nexport function isCasingValid(value: unknown): value is CasingType {\r\n if (typeof value !== 'string') {\r\n return false;\r\n }\r\n\r\n const isValid = CASING_TYPES.includes(value as CasingType);\r\n\r\n // invariant(isValid, () => {\r\n // const formatter = new Intl.ListFormat('en', {\r\n // style: 'long',\r\n // type: 'conjunction',\r\n // });\r\n\r\n // return `${value} is not a valid casing type. Valid types include ${formatter.format(\r\n // CASING_TYPES.map((word) => quote(word))\r\n // )}`;\r\n // });\r\n\r\n return isValid;\r\n}\r\n\r\n/**\r\n * Validates {@linkcode input} is a valid {@linkcode CasingType}.\r\n *\r\n * If there is no explicit {@linkcode fallback} value provided,\r\n * it will default to {@linkcode DEFAULT_CASING}.\r\n * @param input The input to check.\r\n * @param fallback An optional fallback value if {@linkcode input} is `undefined`.\r\n * @returns The {@linkcode input} or {@linkcode fallback} if {@linkcode input} is `undefined` or an {@linkcode isCasingValid invalid} {@linkcode CasingType}.\r\n */\r\nexport function setCasingType<TCasing extends CasingType>(\r\n input: TCasing | undefined,\r\n fallback: CasingType = DEFAULT_CASING\r\n) {\r\n if (isCasingValid(input)) {\r\n return input;\r\n }\r\n\r\n return fallback;\r\n}\r\n","import type { SetDefaultString } from './types';\r\n\r\nexport type FieldType = (typeof FIELD_TYPES)[number];\r\nexport type DefaultFieldType = typeof DEFAULT_FIELD_TYPE;\r\nexport const FIELD_TYPES = [\r\n 'string',\r\n 'string.phone',\r\n 'string.email',\r\n 'string.time',\r\n 'number',\r\n 'number.counter',\r\n 'date',\r\n 'dateTime',\r\n 'boolean.switch',\r\n] as const;\r\nexport const DEFAULT_FIELD_TYPE: SetDefaultString<FieldType, 'string'> =\r\n 'string';\r\n\r\nexport function isFieldType(value: unknown): value is FieldType {\r\n return typeof value === 'string' && FIELD_TYPES.includes(value as FieldType);\r\n}\r\n","import type { Updater } from '@/steps/types';\r\nimport { invariant } from '@/utils/invariant';\r\nimport { MultiStepFormLogger } from '@/utils/logger';\r\n\r\nexport type DefaultStorageKey = typeof DEFAULT_STORAGE_KEY;\r\nexport type StorageConfig<TData, TKey extends string> = {\r\n key: TKey;\r\n data: TData;\r\n store?: Storage;\r\n /**\r\n * An extra option to throw an error when {@linkcode window} is `undefined`\r\n * @default false\r\n */\r\n throwWhenUndefined?: boolean;\r\n};\r\n\r\nconst WINDOW_UNDEFINED_MESSAGE =\r\n '\"window\" in undefined. No storage is available';\r\nexport const DEFAULT_STORAGE_KEY = 'MultiStepForm';\r\n\r\nexport class MultiStepFormStorage<\r\n data,\r\n key extends string = DefaultStorageKey\r\n> {\r\n readonly key: key;\r\n readonly store!: Storage;\r\n readonly data: data;\r\n private readonly log: MultiStepFormLogger;\r\n private readonly shouldRunActions: boolean;\r\n private readonly throwWhenUndefined: boolean;\r\n\r\n constructor(config: StorageConfig<data, key>) {\r\n const { key, data, store, throwWhenUndefined = false } = config;\r\n\r\n this.log = new MultiStepFormLogger({\r\n prefix: DEFAULT_STORAGE_KEY,\r\n });\r\n this.key = key;\r\n this.data = data;\r\n this.throwWhenUndefined = throwWhenUndefined;\r\n\r\n if (store) {\r\n this.store = store;\r\n this.shouldRunActions = true;\r\n\r\n if (typeof window === 'undefined') {\r\n this.shouldRunActions = false;\r\n this.log.warn(WINDOW_UNDEFINED_MESSAGE);\r\n }\r\n } else if (typeof window !== 'undefined') {\r\n this.store = window.localStorage;\r\n this.shouldRunActions = true;\r\n } else {\r\n this.shouldRunActions = false;\r\n this.log.warn(WINDOW_UNDEFINED_MESSAGE);\r\n }\r\n }\r\n\r\n private throwOnEmptyStore() {\r\n if (!this.throwWhenUndefined) {\r\n return;\r\n }\r\n\r\n invariant(this.store, () => {\r\n if (this.shouldRunActions) {\r\n return WINDOW_UNDEFINED_MESSAGE;\r\n }\r\n\r\n return 'No storage available';\r\n });\r\n }\r\n\r\n private resolveValue(value: Updater<data>) {\r\n if (typeof value === 'object') {\r\n return value;\r\n }\r\n\r\n if (typeof value === 'function') {\r\n return (value as (input: data) => data)(this.data);\r\n }\r\n\r\n this.log.error(\r\n `The updater value must be a function or object. Was a ${typeof value}`,\r\n { throw: true }\r\n );\r\n }\r\n\r\n hasKey() {\r\n return this.store.getItem(this.key) !== null;\r\n }\r\n\r\n get() {\r\n this.throwOnEmptyStore();\r\n\r\n if (!this.shouldRunActions) {\r\n return;\r\n }\r\n\r\n const item = this.store.getItem(this.key);\r\n\r\n if (item) {\r\n const parsed = JSON.parse(item);\r\n\r\n return parsed as data;\r\n }\r\n }\r\n\r\n remove() {\r\n this.throwOnEmptyStore();\r\n\r\n if (!this.shouldRunActions) {\r\n return;\r\n }\r\n\r\n this.store.removeItem(this.key);\r\n }\r\n\r\n add(value: Updater<data>) {\r\n this.throwOnEmptyStore();\r\n\r\n if (!this.shouldRunActions) {\r\n return;\r\n }\r\n\r\n const resolvedValue = JSON.stringify(this.resolveValue(value));\r\n\r\n this.store.setItem(this.key, resolvedValue);\r\n }\r\n}\r\n","export abstract class Subscribable<TListener extends Function> {\r\n protected listeners = new Set<TListener>();\r\n\r\n constructor() {\r\n this.subscribe = this.subscribe.bind(this);\r\n }\r\n\r\n subscribe(listener: TListener) {\r\n this.listeners.add(listener);\r\n\r\n this.onSubscribe();\r\n\r\n return () => {\r\n this.listeners.delete(listener);\r\n this.onUnsubscribe();\r\n };\r\n }\r\n\r\n hasListeners() {\r\n return this.listeners.size > 0;\r\n }\r\n\r\n protected onSubscribe() {}\r\n protected onUnsubscribe() {}\r\n protected abstract notify(): void;\r\n abstract getSnapshot(): this;\r\n}\r\n","import {\r\n MultiStepFormStepSchemaInternal,\r\n isValidStepKey,\r\n} from '@/internals/step-schema';\r\nimport {\r\n DEFAULT_STORAGE_KEY,\r\n DefaultStorageKey,\r\n MultiStepFormStorage,\r\n} from '@/storage';\r\nimport {\r\n DEFAULT_CASING,\r\n DEFAULT_FIELD_TYPE,\r\n changeCasing,\r\n isCasingValid,\r\n isFieldType,\r\n setCasingType,\r\n type CasingType,\r\n type Constrain,\r\n type DefaultCasing,\r\n type Expand,\r\n type Join,\r\n} from '@/utils';\r\nimport { invariant } from '@/utils/invariant';\r\nimport {\r\n runStandardValidation,\r\n type AnyValidator,\r\n type DefaultValidator,\r\n type StandardSchemaValidator,\r\n} from '@/utils/validator';\r\nimport { Subscribable } from '../subscribable';\r\nimport { fields as fieldsUtils } from './fields';\r\nimport {\r\n AnyResolvedStep,\r\n AnyStepField,\r\n AnyStepFieldOption,\r\n CreateHelperFunctionOptionsWithCustomCtxOptions,\r\n CreateHelperFunctionOptionsWithValidator,\r\n CreateHelperFunctionOptionsWithoutValidator,\r\n CreateStepHelperFn,\r\n CreatedHelperFnWithInput,\r\n CreatedHelperFnWithoutInput,\r\n ExtractStepFromKey,\r\n FirstStep,\r\n GetCurrentStep,\r\n HelperFnChosenSteps,\r\n HelperFnWithValidator,\r\n HelperFnWithoutValidator,\r\n InferStepOptions,\r\n LastStep,\r\n MultiStepFormSchemaStepConfig,\r\n ResolvedFields,\r\n ResolvedStep,\r\n Step,\r\n StepData,\r\n StepNumbers,\r\n StepOptions,\r\n UnionToTuple,\r\n UpdateFn,\r\n ValidStepKey\r\n} from './types';\r\nimport { getStep, type GetStepOptions } from './utils';\r\n\r\nexport interface MultiStepFormStepSchemaFunctions<\r\n TResolvedStep extends AnyResolvedStep,\r\n TStepNumbers extends StepNumbers<TResolvedStep>\r\n> {\r\n update: UpdateFn.general<TResolvedStep, TStepNumbers>;\r\n createHelperFn: CreateStepHelperFn<TResolvedStep, TStepNumbers>;\r\n}\r\nexport type AsType = (typeof AS_TYPES)[number];\r\ntype Quote<T extends string[]> = {\r\n [K in keyof T]: T[K] extends string ? `'${T[K]}'` : never;\r\n};\r\nexport type AsTypeMap<\r\n resolvedStep extends AnyResolvedStep,\r\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>\r\n> = {\r\n // Exclude is needed due to all the Constrains\r\n string: Exclude<\r\n Join<\r\n Constrain<\r\n Quote<Constrain<UnionToTuple<`${stepNumbers}`>, string[]>>,\r\n string[]\r\n >,\r\n ' | '\r\n >,\r\n ''\r\n >;\r\n number: Exclude<\r\n Join<Constrain<UnionToTuple<`${stepNumbers}`>, string[]>, ' | '>,\r\n ''\r\n >;\r\n 'array.string': UnionToTuple<`${stepNumbers}`>;\r\n 'array.string.untyped': string[];\r\n};\r\nexport type AsFunctionReturn<\r\n resolvedStep extends AnyResolvedStep,\r\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>,\r\n asType extends AsType\r\n> = AsTypeMap<resolvedStep, stepNumbers>[asType];\r\nexport type AsFunction<\r\n resolvedStep extends AnyResolvedStep,\r\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>\r\n> = <asType extends AsType>(\r\n asType: asType\r\n) => AsFunctionReturn<resolvedStep, stepNumbers, asType>;\r\nexport type MultiStepFormStepStepsConfig<\r\n TStep extends Step<TCasing>,\r\n TCasing extends CasingType,\r\n TResolvedStep extends ResolvedStep<TStep, TCasing> = ResolvedStep<\r\n TStep,\r\n TCasing\r\n >,\r\n TStepNumbers extends StepNumbers<TResolvedStep> = StepNumbers<TResolvedStep>\r\n> = {\r\n first: FirstStep<TResolvedStep>;\r\n last: LastStep<TResolvedStep>;\r\n value: ReadonlyArray<TStepNumbers>;\r\n as: AsFunction<TResolvedStep, TStepNumbers>;\r\n isValidStepNumber: (stepNumber: number) => stepNumber is TStepNumbers;\r\n isValidStepKey: (\r\n value: string\r\n ) => value is Constrain<keyof TResolvedStep, string>;\r\n};\r\nexport type MultiStepFormStepSchemaListener<\r\n TStep extends Step<TCasing>,\r\n TCasing extends CasingType\r\n> = (data: {\r\n original: InferStepOptions<TStep>;\r\n value: ResolvedStep<TStep, TCasing>;\r\n steps: MultiStepFormStepStepsConfig<TStep, TCasing>;\r\n defaultNameTransformationCasing: TCasing;\r\n}) => void;\r\n\r\n/**\r\n * Available transformation types for the step numbers.\r\n */\r\nconst AS_TYPES = [\r\n 'string',\r\n 'number',\r\n 'array.string',\r\n 'array.string.untyped',\r\n] as const;\r\nexport const VALIDATED_STEP_REGEX = /^step\\d+$/i;\r\n\r\ntype ValueCheck<T> = (v: unknown) => v is T;\r\n\r\ntype FieldChecks<T extends object> = {\r\n [K in keyof T]: ValueCheck<T[K]>;\r\n};\r\n\r\nfunction assertObjectFields<T extends object>(\r\n obj: unknown,\r\n checks: FieldChecks<T>\r\n): obj is T {\r\n if (typeof obj !== 'object' || obj === null) return false;\r\n\r\n for (const key of Object.keys(checks) as (keyof T)[]) {\r\n // Check that the property exists\r\n if (!(key in obj)) return false;\r\n\r\n // Now check the type\r\n const checkFn = checks[key];\r\n const value = (obj as any)[key];\r\n if (!checkFn(value)) return false;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nfunction createFieldLabel(\r\n label: string | false | undefined,\r\n fieldName: string,\r\n casingType: CasingType\r\n) {\r\n return label ?? changeCasing(fieldName, casingType);\r\n}\r\n\r\nfunction createStepFields(options: {\r\n fields: AnyStepField;\r\n validateFields:\r\n | Constrain<unknown, AnyValidator, DefaultValidator>\r\n | undefined;\r\n defaultCasing: CasingType;\r\n}) {\r\n const resolvedFields: Record<string, unknown> = {};\r\n const { fields, defaultCasing, validateFields } = options;\r\n\r\n for (const [name, values] of Object.entries(fields)) {\r\n invariant(\r\n typeof name === 'string',\r\n `Each key for the \"fields\" option must be a string. Key ${name} was a ${typeof name}`\r\n );\r\n invariant(\r\n typeof values === 'object',\r\n `The value for key ${name} must be an object. Was ${typeof values}`\r\n );\r\n\r\n const {\r\n defaultValue,\r\n label,\r\n nameTransformCasing,\r\n type = DEFAULT_FIELD_TYPE,\r\n } = values;\r\n\r\n if (validateFields) {\r\n resolvedFields[name] = defaultValue;\r\n } else {\r\n const casing = nameTransformCasing ?? defaultCasing;\r\n\r\n resolvedFields[name] = {\r\n ...(resolvedFields[name] as Record<string, unknown>),\r\n nameTransformCasing: casing,\r\n type,\r\n defaultValue,\r\n label: createFieldLabel(label, name, casing),\r\n\r\n // TODO add more fields here\r\n };\r\n }\r\n }\r\n\r\n if (validateFields) {\r\n const validatedFields = runStandardValidation(\r\n validateFields as StandardSchemaValidator,\r\n resolvedFields\r\n );\r\n\r\n invariant(\r\n typeof validatedFields === 'object',\r\n `The result of the validated fields must be an object, was (${typeof validatedFields}). This is probably an internal error, so open up an issue about it`\r\n );\r\n invariant(\r\n !!validatedFields,\r\n 'The result of the validated fields must be defined. This is probably an internal error, so open up an issue about it'\r\n );\r\n\r\n for (const [name, defaultValue] of Object.entries(validatedFields)) {\r\n const currentField = fields[name];\r\n\r\n invariant(\r\n currentField,\r\n `No field found in the fields config for \"${name}\"`\r\n );\r\n\r\n const {\r\n label,\r\n type = DEFAULT_FIELD_TYPE,\r\n nameTransformCasing,\r\n } = currentField;\r\n const casing = nameTransformCasing ?? defaultCasing;\r\n\r\n resolvedFields[name] = {\r\n ...(resolvedFields[name] as Record<string, unknown>),\r\n nameTransformCasing: casing,\r\n type,\r\n defaultValue,\r\n label: createFieldLabel(label, name, casing),\r\n };\r\n }\r\n }\r\n\r\n return resolvedFields;\r\n}\r\n\r\nexport function createStep<\r\n step extends Step<casing>,\r\n casing extends CasingType = DefaultCasing\r\n>(stepsConfig: InferStepOptions<step>) {\r\n const resolvedSteps = {} as ResolvedStep<step, casing>;\r\n\r\n invariant(!!stepsConfig, 'The steps config must be defined', TypeError);\r\n invariant(\r\n typeof stepsConfig === 'object',\r\n `The steps config must be an object, was (${typeof stepsConfig})`,\r\n TypeError\r\n );\r\n\r\n for (const [stepKey, stepValue] of Object.entries(stepsConfig)) {\r\n invariant(\r\n typeof stepKey === 'string',\r\n `Each key for the step config must be a string. Key \"${stepKey}\" was ${typeof stepKey} `,\r\n TypeError\r\n );\r\n invariant(\r\n VALIDATED_STEP_REGEX.test(stepKey),\r\n `The key \"${stepKey}\" isn't formatted properly. Each key in the step config must be the following format: \"step{number}\"`\r\n );\r\n\r\n const validStepKey = stepKey as keyof typeof resolvedSteps;\r\n const {\r\n fields,\r\n title,\r\n nameTransformCasing: defaultCasing = DEFAULT_CASING,\r\n description,\r\n validateFields,\r\n } = stepValue;\r\n\r\n const currentStep = validStepKey.toString().replace('step', '');\r\n\r\n invariant(\r\n fields,\r\n `Missing fields for step ${currentStep} (${String(validStepKey)})`,\r\n TypeError\r\n );\r\n invariant(\r\n typeof fields === 'object',\r\n 'Fields must be an object',\r\n TypeError\r\n );\r\n invariant(\r\n Object.keys(fields).length > 0,\r\n `The fields config for step ${currentStep} (${String(\r\n validStepKey\r\n )}) is empty. Please add a field`\r\n );\r\n invariant(\r\n typeof fields === 'object',\r\n `The \"fields\" property must be an object. Was ${typeof fields}`\r\n );\r\n\r\n const resolvedFields = createStepFields({\r\n defaultCasing,\r\n fields,\r\n validateFields,\r\n });\r\n\r\n resolvedSteps[validStepKey] = {\r\n ...resolvedSteps[validStepKey],\r\n title,\r\n nameTransformCasing: defaultCasing,\r\n // Only add the description if it's defined\r\n ...(typeof description === 'string' ? { description } : {}),\r\n fields: resolvedFields,\r\n };\r\n }\r\n\r\n return resolvedSteps;\r\n}\r\n\r\nexport class MultiStepFormStepSchema<\r\n step extends Step<casing>,\r\n casing extends CasingType = DefaultCasing,\r\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<\r\n step,\r\n casing\r\n >,\r\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\r\n storageKey extends string = DefaultStorageKey\r\n >\r\n extends Subscribable<MultiStepFormStepSchemaListener<step, casing>>\r\n implements MultiStepFormStepSchemaFunctions<resolvedStep, stepNumbers>\r\n{\r\n /**\r\n * The original config before any validation or transformations have been applied.\r\n */\r\n readonly original: InferStepOptions<step>;\r\n /**\r\n * The resolved step values.\r\n */\r\n value: resolvedStep;\r\n readonly steps: MultiStepFormStepStepsConfig<step, casing>;\r\n readonly defaultNameTransformationCasing: casing;\r\n //@ts-ignore\r\n private readonly firstStep: StepData<resolvedStep, FirstStep<resolvedStep>>;\r\n private readonly lastStep: StepData<resolvedStep, LastStep<resolvedStep>>;\r\n private readonly stepNumbers: Array<number>;\r\n private readonly storage: MultiStepFormStorage<resolvedStep, storageKey>;\r\n readonly #internal: MultiStepFormStepSchemaInternal<\r\n resolvedStep,\r\n stepNumbers\r\n >;\r\n\r\n constructor(\r\n config: MultiStepFormSchemaStepConfig<\r\n step,\r\n Constrain<casing, CasingType>,\r\n storageKey\r\n >\r\n ) {\r\n super();\r\n\r\n const { steps, nameTransformCasing, storage } = config;\r\n\r\n this.defaultNameTransformationCasing = setCasingType(\r\n nameTransformCasing\r\n ) as casing;\r\n\r\n this.original = steps;\r\n\r\n this.value = createStep<step, casing>(this.original) as resolvedStep;\r\n this.storage = new MultiStepFormStorage<resolvedStep, storageKey>({\r\n data: this.value,\r\n key: (storage?.key ?? DEFAULT_STORAGE_KEY) as storageKey,\r\n store: storage?.store,\r\n throwWhenUndefined: storage?.throwWhenUndefined ?? false,\r\n });\r\n this.#internal = new MultiStepFormStepSchemaInternal<\r\n resolvedStep,\r\n stepNumbers\r\n >({\r\n getValue: () => this.value,\r\n setValue: (next) => this.handlePostUpdate(next),\r\n });\r\n\r\n this.value = this.#internal.enrichValues(this.value);\r\n this.stepNumbers = Object.keys(this.value).map((key) =>\r\n Number.parseInt(key.replace('step', ''))\r\n );\r\n\r\n this.firstStep = this.first();\r\n this.lastStep = this.last();\r\n this.steps = {\r\n first: this.firstStep.step,\r\n last: this.lastStep.step,\r\n value: this.stepNumbers as unknown as ReadonlyArray<stepNumbers>,\r\n as: (asType): any => {\r\n invariant(\r\n typeof asType === 'string',\r\n `The type of the target transformation type must be a string, was ${typeof asType}`\r\n );\r\n\r\n if (asType === 'string') {\r\n return this.stepNumbers.map((value) => `'${value}'`).join(' | ');\r\n }\r\n\r\n if (asType === 'number') {\r\n return this.stepNumbers.join(' | ');\r\n }\r\n\r\n if (asType.includes('array.string')) {\r\n return this.stepNumbers.map((value) => `${value}`);\r\n }\r\n\r\n throw new Error(\r\n `Transformation type \"${asType}\" is not supported. Available transformations include: ${AS_TYPES.map(\r\n (value) => `\"${value}\"`\r\n ).join(', ')}`\r\n );\r\n },\r\n isValidStepNumber: (stepNumber): stepNumber is stepNumbers =>\r\n this.stepNumbers.includes(stepNumber),\r\n isValidStepKey: (value) =>\r\n isValidStepKey<resolvedStep>(this.value, value),\r\n };\r\n\r\n this.sync();\r\n }\r\n\r\n /**\r\n * @internal\r\n */\r\n __getStorage() {\r\n return this.storage;\r\n }\r\n\r\n getSnapshot() {\r\n return this;\r\n }\r\n\r\n /**\r\n * Syncs the values from storage to {@linkcode value}.\r\n */\r\n sync() {\r\n // TODO add \"syncOptions\" so caller can chose where to sync from ('storage' | 'instance')\r\n const storageValues = this.__getStorage().get();\r\n\r\n if (storageValues) {\r\n const enrichedValues = this.#internal.enrichValues(storageValues);\r\n\r\n this.value = { ...enrichedValues };\r\n }\r\n }\r\n\r\n protected notify() {\r\n for (const listener of this.listeners) {\r\n listener({\r\n defaultNameTransformationCasing: this.defaultNameTransformationCasing,\r\n original: this.original,\r\n steps: this.steps,\r\n value: this.value,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Gets the data for a specific step.\r\n * @param options The options for getting the step data.\r\n * @returns The step data for the target step.\r\n */\r\n get<stepNumber extends stepNumbers>(\r\n options: GetStepOptions<resolvedStep, stepNumbers, stepNumber>\r\n ) {\r\n return getStep(this.value)(options);\r\n }\r\n\r\n /**\r\n * Gets the data for the first step.\r\n * @returns The data for the first step.\r\n */\r\n first() {\r\n const firstStep = Math.min(...this.stepNumbers) as FirstStep<resolvedStep>;\r\n\r\n return this.get({ step: firstStep });\r\n }\r\n\r\n /**\r\n * Gets the data for the last step.\r\n * @returns The data for the last step.\r\n */\r\n last() {\r\n const lastStep = Math.max(...this.stepNumbers);\r\n\r\n return this.get<LastStep<resolvedStep>>({ step: lastStep as never });\r\n }\r\n\r\n protected handlePostUpdate(next: resolvedStep) {\r\n this.value = { ...next };\r\n\r\n this.__getStorage().add(this.value);\r\n this.sync();\r\n this.notify();\r\n }\r\n\r\n update<\r\n targetStep extends ValidStepKey<stepNumbers>,\r\n field extends UpdateFn.chosenFields<\r\n UpdateFn.resolvedStep<resolvedStep, stepNumbers, targetStep>\r\n > = 'all',\r\n additionalCtx extends Record<string, unknown> = {}\r\n >(\r\n options: UpdateFn.options<\r\n resolvedStep,\r\n stepNumbers,\r\n targetStep,\r\n field,\r\n additionalCtx\r\n >\r\n ) {\r\n this.#internal.update(options);\r\n }\r\n\r\n /**\r\n * Create a helper function with validated input.\r\n */\r\n createHelperFn<\r\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\r\n validator,\r\n additionalCtx extends Record<string, unknown>,\r\n response\r\n >(\r\n options: CreateHelperFunctionOptionsWithValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx\r\n >,\r\n fn: HelperFnWithValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx,\r\n response\r\n >\r\n ): CreatedHelperFnWithInput<validator, response>;\r\n /**\r\n * Create a helper function without input.\r\n */\r\n createHelperFn<\r\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\r\n additionalCtx extends Record<string, unknown>,\r\n response\r\n >(\r\n options: CreateHelperFunctionOptionsWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps\r\n > &\r\n CreateHelperFunctionOptionsWithCustomCtxOptions<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n additionalCtx\r\n >,\r\n fn: HelperFnWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n additionalCtx,\r\n response\r\n >\r\n ): CreatedHelperFnWithoutInput<response>;\r\n // Implementation\r\n createHelperFn<\r\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\r\n response,\r\n additionalCtx extends Record<string, unknown>,\r\n validator = never\r\n >(\r\n options:\r\n | CreateHelperFunctionOptionsWithValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx\r\n >\r\n | CreateHelperFunctionOptionsWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps\r\n >,\r\n fn:\r\n | HelperFnWithValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n validator,\r\n additionalCtx,\r\n response\r\n >\r\n | HelperFnWithoutValidator<\r\n resolvedStep,\r\n stepNumbers,\r\n chosenSteps,\r\n additionalCtx,\r\n response\r\n >\r\n ) {\r\n const { stepData, ...rest } = options;\r\n\r\n return this.#internal.createStepHelperFn(stepData)(rest, fn);\r\n }\r\n\r\n /**\r\n * Validates that a given object is the proper shape for step data.\r\n * @param value\r\n */\r\n static hasData<\r\n step extends Step<casing>,\r\n resolvedStep extends ResolvedStep<step, casing>,\r\n stepNumbers extends StepNumbers<resolvedStep>,\r\n casing extends CasingType = DefaultCasing\r\n >(\r\n value: unknown,\r\n options?: {\r\n optionalKeysToCheck?: FieldChecks<\r\n Pick<StepOptions, 'description' | 'validateFields'>\r\n >;\r\n }\r\n ): value is GetCurrentStep<resolvedStep, stepNumbers> {\r\n if (value === null || typeof value !== 'object') {\r\n return false;\r\n }\r\n\r\n return assertObjectFields<\r\n | GetCurrentStep<resolvedStep, stepNumbers>\r\n | (Omit<StepOptions, 'fields'> & {\r\n fields: Expand<\r\n ResolvedFields<InferStepOptions<step>, keyof InferStepOptions<step>>\r\n >;\r\n })\r\n >(value, {\r\n title: (v) => typeof v === 'string',\r\n fields: (\r\n v\r\n ): v is Expand<\r\n ResolvedFields<InferStepOptions<step>, keyof InferStepOptions<step>>\r\n > => {\r\n if (v === null || typeof v !== 'object') {\r\n return false;\r\n }\r\n\r\n for (const key of Object.keys(v)) {\r\n if (typeof key !== 'string' || !(key in v)) {\r\n return false;\r\n }\r\n\r\n const current = (v as Record<string, unknown>)[key];\r\n\r\n if (current === null || typeof current !== 'object') {\r\n return false;\r\n }\r\n\r\n const hasField = assertObjectFields<AnyStepFieldOption>(current, {\r\n defaultValue: (v): v is {} => v !== 'undefined' && v !== null,\r\n label: (v) =>\r\n typeof v === 'string' || (typeof v === 'boolean' && !v),\r\n nameTransformCasing: isCasingValid,\r\n type: isFieldType,\r\n });\r\n\r\n if (!hasField) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n },\r\n createHelperFn: (\r\n v\r\n ): v is GetCurrentStep<resolvedStep, stepNumbers>['createHelperFn'] =>\r\n typeof v === 'function',\r\n // update: (v): v is GetCurrentStep<resolvedStep, stepNumbers>['update'] =>\r\n // typeof v === 'function',\r\n nameTransformCasing: isCasingValid,\r\n ...options?.optionalKeysToCheck,\r\n });\r\n }\r\n\r\n /**\r\n * Gets the value of a given field for a given step.\r\n * @param step The step to get the value from.\r\n * @param field The field to get the value from.\r\n * @returns The value of the {@linkcode field}.\r\n */\r\n getValue<\r\n step extends keyof resolvedStep,\r\n field extends fieldsUtils.getDeep<resolvedStep, step>\r\n >(step: step, field: field) {\r\n const stepData = this.value[step];\r\n const baseErrorMessage = `Unable to get the value for \"${String(\r\n step\r\n )}.fields.${String(field)}\"`;\r\n\r\n invariant('fields' in stepData, baseErrorMessage);\r\n invariant(\r\n typeof stepData.fields === 'object',\r\n `${baseErrorMessage} because \"fields\" is not an object. This shouldn't be the case, so please open an issue`\r\n );\r\n\r\n const fields = stepData.fields as AnyStepField;\r\n\r\n const defaultValue = fieldsUtils.resolvedDeepPath<\r\n resolvedStep,\r\n step,\r\n fieldsUtils.get<resolvedStep, step>,\r\n field\r\n >(field, fields as fieldsUtils.get<resolvedStep, step>);\r\n\r\n return defaultValue;\r\n }\r\n}\r\n","import {\r\n MultiStepFormStepSchema,\r\n type MultiStepFormSchemaStepConfig,\r\n type ResolvedStep,\r\n type Step,\r\n type StepNumbers,\r\n} from '@/steps';\r\nimport {\r\n setCasingType,\r\n type CasingType,\r\n type Constrain,\r\n type DefaultCasing,\r\n} from '@/utils';\r\nimport {\r\n DEFAULT_STORAGE_KEY,\r\n MultiStepFormStorage,\r\n type DefaultStorageKey,\r\n} from './storage.js';\r\nimport { Subscribable } from './subscribable.js';\r\n\r\nexport interface MultiStepFormSchemaOptions<\r\n TStep extends Step<TCasing>,\r\n TCasing extends CasingType,\r\n TStorageKey extends string\r\n> extends MultiStepFormSchemaStepConfig<TStep, TCasing, TStorageKey> {}\r\nexport type MultiStepFormSchemaListener<\r\n TStep extends Step<TCasing>,\r\n TCasing extends CasingType,\r\n TStorageKey extends string\r\n> = (data: MultiStepFormSchemaOptions<TStep, TCasing, TStorageKey>) => void;\r\n\r\nexport class MultiStepFormSchema<\r\n step extends Step<casing>,\r\n casing extends CasingType = DefaultCasing,\r\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<step, casing>,\r\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\r\n storageKey extends string = DefaultStorageKey\r\n> extends Subscribable<MultiStepFormSchemaListener<step, casing, storageKey>> {\r\n readonly defaultNameTransformationCasing: casing;\r\n readonly stepSchema: MultiStepFormStepSchema<\r\n step,\r\n casing,\r\n resolvedStep,\r\n stepNumbers,\r\n storageKey\r\n >;\r\n storage: MultiStepFormStorage<resolvedStep, storageKey>;\r\n private mountCount = 0;\r\n\r\n constructor(\r\n options: MultiStepFormSchemaOptions<\r\n step,\r\n // Allows full autocomplete\r\n Constrain<casing, CasingType>,\r\n storageKey\r\n >\r\n ) {\r\n super();\r\n\r\n const { steps, nameTransformCasing, storage } = options;\r\n\r\n this.defaultNameTransformationCasing = setCasingType(\r\n nameTransformCasing\r\n ) as casing;\r\n // @ts-ignore Type instantiation is excessively deep and possibly infinite\r\n this.stepSchema = new MultiStepFormStepSchema({\r\n steps,\r\n nameTransformCasing: this.defaultNameTransformationCasing,\r\n });\r\n this.storage = new MultiStepFormStorage<resolvedStep, storageKey>({\r\n key: (storage?.key ?? DEFAULT_STORAGE_KEY) as storageKey,\r\n data: this.stepSchema.value as never,\r\n store: storage?.store,\r\n throwWhenUndefined: storage?.throwWhenUndefined ?? false,\r\n });\r\n\r\n this.stepSchema.subscribe(() => {\r\n this.notify();\r\n });\r\n }\r\n\r\n getSnapshot() {\r\n return this;\r\n }\r\n\r\n mount() {\r\n this.mountCount++;\r\n\r\n if (this.mountCount === 1) {\r\n this.onMount();\r\n }\r\n\r\n return () => {\r\n this.unmount();\r\n };\r\n }\r\n\r\n unmount() {\r\n this.mountCount = Math.max(0, this.mountCount - 1);\r\n\r\n if (this.mountCount === 0) {\r\n this.onUnmount();\r\n }\r\n }\r\n\r\n isMounted() {\r\n return this.mountCount > 0;\r\n }\r\n\r\n protected onMount() {}\r\n protected onUnmount() {}\r\n\r\n protected notify() {\r\n for (const listener of this.listeners) {\r\n listener({\r\n nameTransformCasing: this.defaultNameTransformationCasing,\r\n storage: {\r\n key: this.storage.key,\r\n store: this.storage.store,\r\n },\r\n steps: this.stepSchema.original,\r\n });\r\n }\r\n }\r\n}\r\n\r\nexport function createMultiStepFormSchema<\r\n step extends Step<casing>,\r\n casing extends CasingType = DefaultCasing,\r\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<step, casing>,\r\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\r\n storageKey extends string = DefaultStorageKey\r\n>(\r\n options: MultiStepFormSchemaOptions<\r\n step,\r\n // Allows full autocomplete\r\n Constrain<casing, CasingType>,\r\n storageKey\r\n >\r\n) {\r\n return new MultiStepFormSchema<\r\n step,\r\n casing,\r\n resolvedStep,\r\n stepNumbers,\r\n storageKey\r\n >(options);\r\n}\r\n","import type { MultiStepFormSchema } from './schema';\r\nimport type {\r\n ResolvedStep,\r\n Step,\r\n StepNumbers\r\n} from '@/steps/types';\r\nimport { Subscribable } from './subscribable';\r\nimport type { CasingType } from '@/utils/casing';\r\n\r\nexport type ObserverListener<\r\n TStep extends Step<TCasing>,\r\n TResolvedStep extends ResolvedStep<TStep, TCasing>,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TCasing extends CasingType,\r\n TStorageKey extends string\r\n> = (\r\n schema: MultiStepFormSchema<\r\n TStep,\r\n TCasing,\r\n TResolvedStep,\r\n TStepNumbers,\r\n TStorageKey\r\n >\r\n) => void;\r\n\r\nexport type ObserverOptions<\r\n TStep extends Step<TCasing>,\r\n TResolvedStep extends ResolvedStep<TStep, TCasing>,\r\n TStepNumbers extends StepNumbers<TResolvedStep>,\r\n TCasing extends CasingType,\r\n TStorageKey extends string\r\n> = {\r\n schema: MultiStepFormSchema<\r\n TStep,\r\n TCasing,\r\n TResolvedStep,\r\n TStepNumbers,\r\n TStorageKey\r\n >;\r\n};\r\n\r\nexport class MultiStepFormObserver<\r\n step extends Step<casing>,\r\n resolvedStep extends ResolvedStep<step, casing>,\r\n stepNumbers extends StepNumbers<resolvedStep>,\r\n casing extends CasingType,\r\n storageKey extends string\r\n> extends Subscribable<\r\n ObserverListener<step, resolvedStep, stepNumbers, casing, storageKey>\r\n> {\r\n protected schema: MultiStepFormSchema<\r\n step,\r\n casing,\r\n resolvedStep,\r\n stepNumbers,\r\n storageKey\r\n >;\r\n private unsubscribeFromSchema?: () => void;\r\n\r\n constructor(\r\n options: ObserverOptions<\r\n step,\r\n resolvedStep,\r\n stepNumbers,\r\n casing,\r\n storageKey\r\n >\r\n ) {\r\n super();\r\n\r\n this.schema = options.schema;\r\n this.subscribeToSchema();\r\n }\r\n\r\n protected subscribeToSchema() {\r\n this.unsubscribeFromSchema = this.schema.subscribe(() => {\r\n this.notify();\r\n });\r\n }\r\n\r\n getSnapshot() {\r\n return this;\r\n }\r\n\r\n getResult() {\r\n return this.schema;\r\n }\r\n\r\n setOptions(\r\n options: Partial<\r\n ObserverOptions<step, resolvedStep, stepNumbers, casing, storageKey>\r\n >\r\n ) {\r\n if (options.schema && options.schema !== this.schema) {\r\n this.unsubscribeFromSchema?.();\r\n this.schema = options.schema;\r\n this.subscribeToSchema();\r\n this.notify();\r\n }\r\n }\r\n\r\n protected notify() {\r\n for (const listener of this.listeners) {\r\n listener(this.schema);\r\n }\r\n }\r\n\r\n destroy() {\r\n this.unsubscribeFromSchema?.();\r\n this.listeners.clear();\r\n }\r\n\r\n protected onSubscribe() {}\r\n\r\n protected onUnsubscribe() {}\r\n}\r\n"],"names":["fields","v","fieldsUtils"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/utils/casing.ts","../src/utils/field-types.ts","../src/storage.ts","../src/subscribable.ts","../src/steps/schema.ts","../src/schema.ts","../src/observable.ts"],"sourcesContent":["import type { Expand, SetDefaultString } from './types';\n\nexport type CasingType = (typeof CASING_TYPES)[number];\nexport type ToLower<S extends string> = S extends `${infer F}${infer R}`\n ? `${Lowercase<F>}${ToLower<R>}`\n : S;\n\nexport type CapitalizeWord<S extends string> = S extends `${infer F}${infer R}`\n ? `${Uppercase<F>}${ToLower<R>}`\n : S;\n// Pascal => Capitalize each \"word\" chunk\ntype Pascalize<S extends string> = Capitalize<S>; // naive\n\n// SnakeCase: turn spaces/hyphens into underscores, lowercase\ntype SnakeCase<S extends string> = Lowercase<\n S extends `${infer A} ${infer B}`\n ? `${A}_${SnakeCase<B>}`\n : S extends `${infer A}-${infer B}`\n ? `${A}_${SnakeCase<B>}`\n : S\n>;\n\n// KebabCase: same as snake but with \"-\"\ntype KebabCase<S extends string> = Lowercase<\n S extends `${infer A} ${infer B}`\n ? `${A}-${KebabCase<B>}`\n : S extends `${infer A}_${infer B}`\n ? `${A}-${KebabCase<B>}`\n : S\n>;\n\n// Flat: just strip spaces/underscores/hyphens\ntype RemoveDelimiters<S extends string> = S extends `${infer A} ${infer B}`\n ? `${A}${RemoveDelimiters<B>}`\n : S extends `${infer A}_${infer B}`\n ? `${A}${RemoveDelimiters<B>}`\n : S extends `${infer A}-${infer B}`\n ? `${A}${RemoveDelimiters<B>}`\n : S;\n\n// TitleCase: Capitalize the whole thing\ntype TitleCase<S extends string> = Capitalize<Lowercase<S>>;\n\n// SentenceCase: First word capped, rest lower\ntype SentenceCase<S extends string> = Capitalize<Lowercase<S>>;\nexport type ChangeCasing<\n S extends string,\n T extends CasingType\n> = T extends 'lower'\n ? Lowercase<S>\n : T extends 'upper'\n ? Uppercase<S>\n : T extends 'camel'\n ? Uncapitalize<Pascalize<S>>\n : T extends 'pascal'\n ? Pascalize<S>\n : T extends 'snake'\n ? SnakeCase<S>\n : T extends 'screaming-snake'\n ? Uppercase<SnakeCase<S>>\n : T extends 'kebab'\n ? KebabCase<S>\n : T extends 'flat'\n ? RemoveDelimiters<Lowercase<S>>\n : T extends 'title'\n ? TitleCase<S>\n : T extends 'sentence'\n ? SentenceCase<S>\n : S;\nexport type ChangeObjectCasing<\n T extends object,\n TCasing extends CasingType\n> = Expand<{\n [K in keyof T as K extends string ? ChangeCasing<K, TCasing> : K]: T[K];\n}>;\n\nexport const CASING_TYPES = [\n 'sentence',\n 'title',\n 'camel',\n 'lower',\n 'upper',\n 'pascal',\n 'snake',\n 'screaming-snake',\n 'flat',\n 'kebab',\n] as const;\n\nexport type DefaultCasing = typeof DEFAULT_CASING;\nexport const DEFAULT_CASING: SetDefaultString<CasingType, 'title'> = 'title';\n\n/**\n * Changes the casing of a string according to the specified casing type.\n *\n * @param input - The string to transform.\n * @param type - The casing type to apply.\n * @returns The transformed string in the specified casing.\n */\n// TODO make return type safe\nexport function changeCasing<TValue extends string, TType extends CasingType>(\n input: TValue,\n type: TType\n): ChangeCasing<TValue, TType>;\nexport function changeCasing<TValue extends string, TType extends CasingType>(\n input: TValue,\n type: TType\n) {\n // Step 1: Normalize to words\n const words = input\n // Replace camelCase boundaries with space\n .replace(/([a-z])([A-Z])/g, '$1 $2')\n // Replace separators with space\n .replace(/[-_]+/g, ' ')\n // Trim and split into words\n .trim()\n .split(/\\s+/)\n .map((w) => w.toLowerCase());\n\n // Step 2: Apply casing\n switch (type) {\n case 'sentence':\n return (\n words[0].charAt(0).toUpperCase() +\n words[0].slice(1) +\n (words.length > 1 ? ' ' + words.slice(1).join(' ') : '')\n );\n\n case 'title':\n return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');\n\n case 'camel':\n return (\n words[0] +\n words\n .slice(1)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join('')\n );\n\n case 'pascal':\n return words.map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join('');\n\n case 'lower':\n return words.join(' ');\n\n case 'upper':\n return words.join(' ').toUpperCase();\n\n case 'snake':\n return words.join('_');\n\n case 'screaming-snake':\n return words.join('_').toUpperCase();\n\n case 'kebab':\n return words.join('-');\n\n case 'flat':\n return words.join('');\n\n default:\n return input;\n }\n}\n\nexport function quote(str: string, quoteChar: '\"' | \"'\" = '\"') {\n const startsWithQuote = str.startsWith(quoteChar);\n const endsWithQuote = str.endsWith(quoteChar);\n\n if (startsWithQuote && endsWithQuote) {\n // Already wrapped correctly\n return str;\n }\n\n // If it starts or ends with a quote but not both → strip those first\n const trimmed = str.replace(/^['\"]|['\"]$/g, '');\n\n // Then add new quotes consistently\n return `${quoteChar}${trimmed}${quoteChar}`;\n}\n\nexport function isCasingValid(value: unknown): value is CasingType {\n if (typeof value !== 'string') {\n return false;\n }\n\n const isValid = CASING_TYPES.includes(value as CasingType);\n\n // invariant(isValid, () => {\n // const formatter = new Intl.ListFormat('en', {\n // style: 'long',\n // type: 'conjunction',\n // });\n\n // return `${value} is not a valid casing type. Valid types include ${formatter.format(\n // CASING_TYPES.map((word) => quote(word))\n // )}`;\n // });\n\n return isValid;\n}\n\n/**\n * Validates {@linkcode input} is a valid {@linkcode CasingType}.\n *\n * If there is no explicit {@linkcode fallback} value provided,\n * it will default to {@linkcode DEFAULT_CASING}.\n * @param input The input to check.\n * @param fallback An optional fallback value if {@linkcode input} is `undefined`.\n * @returns The {@linkcode input} or {@linkcode fallback} if {@linkcode input} is `undefined` or an {@linkcode isCasingValid invalid} {@linkcode CasingType}.\n */\nexport function setCasingType<TCasing extends CasingType>(\n input: TCasing | undefined,\n fallback: CasingType = DEFAULT_CASING\n) {\n if (isCasingValid(input)) {\n return input;\n }\n\n return fallback;\n}\n","import type { SetDefaultString } from './types';\n\nexport type FieldType = (typeof FIELD_TYPES)[number];\nexport type DefaultFieldType = typeof DEFAULT_FIELD_TYPE;\nexport const FIELD_TYPES = [\n 'string',\n 'string.phone',\n 'string.email',\n 'string.time',\n 'number',\n 'number.counter',\n 'date',\n 'dateTime',\n 'boolean.switch',\n] as const;\nexport const DEFAULT_FIELD_TYPE: SetDefaultString<FieldType, 'string'> =\n 'string';\n\nexport function isFieldType(value: unknown): value is FieldType {\n return typeof value === 'string' && FIELD_TYPES.includes(value as FieldType);\n}\n","import type { Updater } from '@/steps/types';\nimport { invariant } from '@/utils/invariant';\nimport { MultiStepFormLogger } from '@/utils/logger';\n\nexport type DefaultStorageKey = typeof DEFAULT_STORAGE_KEY;\nexport type StorageConfig<TData, TKey extends string> = {\n key: TKey;\n data: TData;\n store?: Storage;\n /**\n * An extra option to throw an error when {@linkcode window} is `undefined`\n * @default false\n */\n throwWhenUndefined?: boolean;\n};\n\nconst WINDOW_UNDEFINED_MESSAGE =\n '\"window\" in undefined. No storage is available';\nexport const DEFAULT_STORAGE_KEY = 'MultiStepForm';\n\nexport class MultiStepFormStorage<\n data,\n key extends string = DefaultStorageKey\n> {\n readonly key: key;\n readonly store!: Storage;\n readonly data: data;\n private readonly log: MultiStepFormLogger;\n private readonly shouldRunActions: boolean;\n private readonly throwWhenUndefined: boolean;\n\n constructor(config: StorageConfig<data, key>) {\n const { key, data, store, throwWhenUndefined = false } = config;\n\n this.log = new MultiStepFormLogger({\n prefix: DEFAULT_STORAGE_KEY,\n });\n this.key = key;\n this.data = data;\n this.throwWhenUndefined = throwWhenUndefined;\n\n if (store) {\n this.store = store;\n this.shouldRunActions = true;\n\n if (typeof window === 'undefined') {\n this.shouldRunActions = false;\n this.log.warn(WINDOW_UNDEFINED_MESSAGE);\n }\n } else if (typeof window !== 'undefined') {\n this.store = window.localStorage;\n this.shouldRunActions = true;\n } else {\n this.shouldRunActions = false;\n this.log.warn(WINDOW_UNDEFINED_MESSAGE);\n }\n }\n\n private throwOnEmptyStore() {\n if (!this.throwWhenUndefined) {\n return;\n }\n\n invariant(this.store, () => {\n if (this.shouldRunActions) {\n return WINDOW_UNDEFINED_MESSAGE;\n }\n\n return 'No storage available';\n });\n }\n\n private resolveValue(value: Updater<data>) {\n if (typeof value === 'object') {\n return value;\n }\n\n if (typeof value === 'function') {\n return (value as (input: data) => data)(this.data);\n }\n\n this.log.error(\n `The updater value must be a function or object. Was a ${typeof value}`,\n { throw: true }\n );\n }\n\n hasKey() {\n return this.store.getItem(this.key) !== null;\n }\n\n get() {\n this.throwOnEmptyStore();\n\n if (!this.shouldRunActions) {\n return;\n }\n\n const item = this.store.getItem(this.key);\n\n if (item) {\n const parsed = JSON.parse(item);\n\n return parsed as data;\n }\n }\n\n remove() {\n this.throwOnEmptyStore();\n\n if (!this.shouldRunActions) {\n return;\n }\n\n this.store.removeItem(this.key);\n }\n\n add(value: Updater<data>) {\n this.throwOnEmptyStore();\n\n if (!this.shouldRunActions) {\n return;\n }\n\n const resolvedValue = JSON.stringify(this.resolveValue(value));\n\n this.store.setItem(this.key, resolvedValue);\n }\n}\n","export abstract class Subscribable<TListener extends Function> {\n protected listeners = new Set<TListener>();\n\n constructor() {\n this.subscribe = this.subscribe.bind(this);\n }\n\n subscribe(listener: TListener) {\n this.listeners.add(listener);\n\n this.onSubscribe();\n\n return () => {\n this.listeners.delete(listener);\n this.onUnsubscribe();\n };\n }\n\n hasListeners() {\n return this.listeners.size > 0;\n }\n\n protected onSubscribe() {}\n protected onUnsubscribe() {}\n protected abstract notify(): void;\n abstract getSnapshot(): this;\n}\n","import {\n MultiStepFormStepSchemaInternal,\n isValidStepKey,\n} from '@/internals/step-schema';\nimport {\n DEFAULT_STORAGE_KEY,\n DefaultStorageKey,\n MultiStepFormStorage,\n} from '@/storage';\nimport {\n DEFAULT_CASING,\n DEFAULT_FIELD_TYPE,\n changeCasing,\n isCasingValid,\n isFieldType,\n setCasingType,\n type CasingType,\n type Constrain,\n type DefaultCasing,\n type Expand,\n type Join,\n} from '@/utils';\nimport { invariant } from '@/utils/invariant';\nimport {\n runStandardValidation,\n type AnyValidator,\n type DefaultValidator,\n type StandardSchemaValidator,\n} from '@/utils/validator';\nimport { Subscribable } from '../subscribable';\nimport { fields as fieldsUtils } from './fields';\nimport {\n AnyResolvedStep,\n AnyStepField,\n AnyStepFieldOption,\n CreateHelperFunctionOptionsWithCustomCtxOptions,\n CreateHelperFunctionOptionsWithValidator,\n CreateHelperFunctionOptionsWithoutValidator,\n CreateStepHelperFn,\n CreatedHelperFnWithInput,\n CreatedHelperFnWithoutInput,\n ExtractStepFromKey,\n FirstStep,\n GetCurrentStep,\n HelperFnChosenSteps,\n HelperFnWithValidator,\n HelperFnWithoutValidator,\n InferStepOptions,\n LastStep,\n MultiStepFormSchemaStepConfig,\n ResolvedFields,\n ResolvedStep,\n Step,\n StepData,\n StepNumbers,\n StepOptions,\n UnionToTuple,\n UpdateFn,\n ValidStepKey\n} from './types';\nimport { getStep, type GetStepOptions } from './utils';\n\nexport interface MultiStepFormStepSchemaFunctions<\n TResolvedStep extends AnyResolvedStep,\n TStepNumbers extends StepNumbers<TResolvedStep>\n> {\n update: UpdateFn.general<TResolvedStep, TStepNumbers>;\n createHelperFn: CreateStepHelperFn<TResolvedStep, TStepNumbers>;\n}\nexport type AsType = (typeof AS_TYPES)[number];\ntype Quote<T extends string[]> = {\n [K in keyof T]: T[K] extends string ? `'${T[K]}'` : never;\n};\nexport type AsTypeMap<\n resolvedStep extends AnyResolvedStep,\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>\n> = {\n // Exclude is needed due to all the Constrains\n string: Exclude<\n Join<\n Constrain<\n Quote<Constrain<UnionToTuple<`${stepNumbers}`>, string[]>>,\n string[]\n >,\n ' | '\n >,\n ''\n >;\n number: Exclude<\n Join<Constrain<UnionToTuple<`${stepNumbers}`>, string[]>, ' | '>,\n ''\n >;\n 'array.string': UnionToTuple<`${stepNumbers}`>;\n 'array.string.untyped': string[];\n};\nexport type AsFunctionReturn<\n resolvedStep extends AnyResolvedStep,\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>,\n asType extends AsType\n> = AsTypeMap<resolvedStep, stepNumbers>[asType];\nexport type AsFunction<\n resolvedStep extends AnyResolvedStep,\n stepNumbers extends ExtractStepFromKey<Constrain<keyof resolvedStep, string>>\n> = <asType extends AsType>(\n asType: asType\n) => AsFunctionReturn<resolvedStep, stepNumbers, asType>;\nexport type MultiStepFormStepStepsConfig<\n TStep extends Step<TCasing>,\n TCasing extends CasingType,\n TResolvedStep extends ResolvedStep<TStep, TCasing> = ResolvedStep<\n TStep,\n TCasing\n >,\n TStepNumbers extends StepNumbers<TResolvedStep> = StepNumbers<TResolvedStep>\n> = {\n first: FirstStep<TResolvedStep>;\n last: LastStep<TResolvedStep>;\n value: ReadonlyArray<TStepNumbers>;\n as: AsFunction<TResolvedStep, TStepNumbers>;\n isValidStepNumber: (stepNumber: number) => stepNumber is TStepNumbers;\n isValidStepKey: (\n value: string\n ) => value is Constrain<keyof TResolvedStep, string>;\n};\nexport type MultiStepFormStepSchemaListener<\n TStep extends Step<TCasing>,\n TCasing extends CasingType\n> = (data: {\n original: InferStepOptions<TStep>;\n value: ResolvedStep<TStep, TCasing>;\n steps: MultiStepFormStepStepsConfig<TStep, TCasing>;\n defaultNameTransformationCasing: TCasing;\n}) => void;\n\n/**\n * Available transformation types for the step numbers.\n */\nconst AS_TYPES = [\n 'string',\n 'number',\n 'array.string',\n 'array.string.untyped',\n] as const;\nexport const VALIDATED_STEP_REGEX = /^step\\d+$/i;\n\ntype ValueCheck<T> = (v: unknown) => v is T;\n\ntype FieldChecks<T extends object> = {\n [K in keyof T]: ValueCheck<T[K]>;\n};\n\nfunction assertObjectFields<T extends object>(\n obj: unknown,\n checks: FieldChecks<T>\n): obj is T {\n if (typeof obj !== 'object' || obj === null) return false;\n\n for (const key of Object.keys(checks) as (keyof T)[]) {\n // Check that the property exists\n if (!(key in obj)) return false;\n\n // Now check the type\n const checkFn = checks[key];\n const value = (obj as any)[key];\n if (!checkFn(value)) return false;\n }\n\n return true;\n}\n\nfunction createFieldLabel(\n label: string | false | undefined,\n fieldName: string,\n casingType: CasingType\n) {\n return label ?? changeCasing(fieldName, casingType);\n}\n\nfunction createStepFields(options: {\n fields: AnyStepField;\n validateFields:\n | Constrain<unknown, AnyValidator, DefaultValidator>\n | undefined;\n defaultCasing: CasingType;\n}) {\n const resolvedFields: Record<string, unknown> = {};\n const { fields, defaultCasing, validateFields } = options;\n\n for (const [name, values] of Object.entries(fields)) {\n invariant(\n typeof name === 'string',\n `Each key for the \"fields\" option must be a string. Key ${name} was a ${typeof name}`\n );\n invariant(\n typeof values === 'object',\n `The value for key ${name} must be an object. Was ${typeof values}`\n );\n\n const {\n defaultValue,\n label,\n nameTransformCasing,\n type = DEFAULT_FIELD_TYPE,\n } = values;\n\n if (validateFields) {\n resolvedFields[name] = defaultValue;\n } else {\n const casing = nameTransformCasing ?? defaultCasing;\n\n resolvedFields[name] = {\n ...(resolvedFields[name] as Record<string, unknown>),\n nameTransformCasing: casing,\n type,\n defaultValue,\n label: createFieldLabel(label, name, casing),\n\n // TODO add more fields here\n };\n }\n }\n\n if (validateFields) {\n const validatedFields = runStandardValidation(\n validateFields as StandardSchemaValidator,\n resolvedFields\n );\n\n invariant(\n typeof validatedFields === 'object',\n `The result of the validated fields must be an object, was (${typeof validatedFields}). This is probably an internal error, so open up an issue about it`\n );\n invariant(\n !!validatedFields,\n 'The result of the validated fields must be defined. This is probably an internal error, so open up an issue about it'\n );\n\n for (const [name, defaultValue] of Object.entries(validatedFields)) {\n const currentField = fields[name];\n\n invariant(\n currentField,\n `No field found in the fields config for \"${name}\"`\n );\n\n const {\n label,\n type = DEFAULT_FIELD_TYPE,\n nameTransformCasing,\n } = currentField;\n const casing = nameTransformCasing ?? defaultCasing;\n\n resolvedFields[name] = {\n ...(resolvedFields[name] as Record<string, unknown>),\n nameTransformCasing: casing,\n type,\n defaultValue,\n label: createFieldLabel(label, name, casing),\n };\n }\n }\n\n return resolvedFields;\n}\n\nexport function createStep<\n step extends Step<casing>,\n casing extends CasingType = DefaultCasing\n>(stepsConfig: InferStepOptions<step>) {\n const resolvedSteps = {} as ResolvedStep<step, casing>;\n\n invariant(!!stepsConfig, 'The steps config must be defined', TypeError);\n invariant(\n typeof stepsConfig === 'object',\n `The steps config must be an object, was (${typeof stepsConfig})`,\n TypeError\n );\n\n for (const [stepKey, stepValue] of Object.entries(stepsConfig)) {\n invariant(\n typeof stepKey === 'string',\n `Each key for the step config must be a string. Key \"${stepKey}\" was ${typeof stepKey} `,\n TypeError\n );\n invariant(\n VALIDATED_STEP_REGEX.test(stepKey),\n `The key \"${stepKey}\" isn't formatted properly. Each key in the step config must be the following format: \"step{number}\"`\n );\n\n const validStepKey = stepKey as keyof typeof resolvedSteps;\n const {\n fields,\n title,\n nameTransformCasing: defaultCasing = DEFAULT_CASING,\n description,\n validateFields,\n } = stepValue;\n\n const currentStep = validStepKey.toString().replace('step', '');\n\n invariant(\n fields,\n `Missing fields for step ${currentStep} (${String(validStepKey)})`,\n TypeError\n );\n invariant(\n typeof fields === 'object',\n 'Fields must be an object',\n TypeError\n );\n invariant(\n Object.keys(fields).length > 0,\n `The fields config for step ${currentStep} (${String(\n validStepKey\n )}) is empty. Please add a field`\n );\n invariant(\n typeof fields === 'object',\n `The \"fields\" property must be an object. Was ${typeof fields}`\n );\n\n const resolvedFields = createStepFields({\n defaultCasing,\n fields,\n validateFields,\n });\n\n resolvedSteps[validStepKey] = {\n ...resolvedSteps[validStepKey],\n title,\n nameTransformCasing: defaultCasing,\n // Only add the description if it's defined\n ...(typeof description === 'string' ? { description } : {}),\n fields: resolvedFields,\n };\n }\n\n return resolvedSteps;\n}\n\nexport class MultiStepFormStepSchema<\n step extends Step<casing>,\n casing extends CasingType = DefaultCasing,\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<\n step,\n casing\n >,\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\n storageKey extends string = DefaultStorageKey\n >\n extends Subscribable<MultiStepFormStepSchemaListener<step, casing>>\n implements MultiStepFormStepSchemaFunctions<resolvedStep, stepNumbers>\n{\n /**\n * The original config before any validation or transformations have been applied.\n */\n readonly original: InferStepOptions<step>;\n /**\n * The resolved step values.\n */\n value: resolvedStep;\n readonly steps: MultiStepFormStepStepsConfig<step, casing>;\n readonly defaultNameTransformationCasing: casing;\n //@ts-ignore\n private readonly firstStep: StepData<resolvedStep, FirstStep<resolvedStep>>;\n private readonly lastStep: StepData<resolvedStep, LastStep<resolvedStep>>;\n private readonly stepNumbers: Array<number>;\n private readonly storage: MultiStepFormStorage<resolvedStep, storageKey>;\n readonly #internal: MultiStepFormStepSchemaInternal<\n resolvedStep,\n stepNumbers\n >;\n\n constructor(\n config: MultiStepFormSchemaStepConfig<\n step,\n Constrain<casing, CasingType>,\n storageKey\n >\n ) {\n super();\n\n const { steps, nameTransformCasing, storage } = config;\n\n this.defaultNameTransformationCasing = setCasingType(\n nameTransformCasing\n ) as casing;\n\n this.original = steps;\n\n this.value = createStep<step, casing>(this.original) as resolvedStep;\n this.storage = new MultiStepFormStorage<resolvedStep, storageKey>({\n data: this.value,\n key: (storage?.key ?? DEFAULT_STORAGE_KEY) as storageKey,\n store: storage?.store,\n throwWhenUndefined: storage?.throwWhenUndefined ?? false,\n });\n this.#internal = new MultiStepFormStepSchemaInternal<\n resolvedStep,\n stepNumbers\n >({\n getValue: () => this.value,\n setValue: (next) => this.handlePostUpdate(next),\n });\n\n this.value = this.#internal.enrichValues(this.value);\n this.stepNumbers = Object.keys(this.value).map((key) =>\n Number.parseInt(key.replace('step', ''))\n );\n\n this.firstStep = this.first();\n this.lastStep = this.last();\n this.steps = {\n first: this.firstStep.step,\n last: this.lastStep.step,\n value: this.stepNumbers as unknown as ReadonlyArray<stepNumbers>,\n as: (asType): any => {\n invariant(\n typeof asType === 'string',\n `The type of the target transformation type must be a string, was ${typeof asType}`\n );\n\n if (asType === 'string') {\n return this.stepNumbers.map((value) => `'${value}'`).join(' | ');\n }\n\n if (asType === 'number') {\n return this.stepNumbers.join(' | ');\n }\n\n if (asType.includes('array.string')) {\n return this.stepNumbers.map((value) => `${value}`);\n }\n\n throw new Error(\n `Transformation type \"${asType}\" is not supported. Available transformations include: ${AS_TYPES.map(\n (value) => `\"${value}\"`\n ).join(', ')}`\n );\n },\n isValidStepNumber: (stepNumber): stepNumber is stepNumbers =>\n this.stepNumbers.includes(stepNumber),\n isValidStepKey: (value) =>\n isValidStepKey<resolvedStep>(this.value, value),\n };\n\n this.sync();\n }\n\n /**\n * @internal\n */\n __getStorage() {\n return this.storage;\n }\n\n getSnapshot() {\n return this;\n }\n\n /**\n * Syncs the values from storage to {@linkcode value}.\n */\n sync() {\n // TODO add \"syncOptions\" so caller can chose where to sync from ('storage' | 'instance')\n const storageValues = this.__getStorage().get();\n\n if (storageValues) {\n const enrichedValues = this.#internal.enrichValues(storageValues);\n\n this.value = { ...enrichedValues };\n }\n }\n\n protected notify() {\n for (const listener of this.listeners) {\n listener({\n defaultNameTransformationCasing: this.defaultNameTransformationCasing,\n original: this.original,\n steps: this.steps,\n value: this.value,\n });\n }\n }\n\n /**\n * Gets the data for a specific step.\n * @param options The options for getting the step data.\n * @returns The step data for the target step.\n */\n get<stepNumber extends stepNumbers>(\n options: GetStepOptions<resolvedStep, stepNumbers, stepNumber>\n ) {\n return getStep(this.value)(options);\n }\n\n /**\n * Gets the data for the first step.\n * @returns The data for the first step.\n */\n first() {\n const firstStep = Math.min(...this.stepNumbers) as FirstStep<resolvedStep>;\n\n return this.get({ step: firstStep });\n }\n\n /**\n * Gets the data for the last step.\n * @returns The data for the last step.\n */\n last() {\n const lastStep = Math.max(...this.stepNumbers);\n\n return this.get<LastStep<resolvedStep>>({ step: lastStep as never });\n }\n\n protected handlePostUpdate(next: resolvedStep) {\n this.value = { ...next };\n\n this.__getStorage().add(this.value);\n this.sync();\n this.notify();\n }\n\n update<\n targetStep extends ValidStepKey<stepNumbers>,\n field extends UpdateFn.chosenFields<\n UpdateFn.resolvedStep<resolvedStep, stepNumbers, targetStep>\n > = 'all',\n additionalCtx extends Record<string, unknown> = {}\n >(\n options: UpdateFn.options<\n resolvedStep,\n stepNumbers,\n targetStep,\n field,\n additionalCtx\n >\n ) {\n this.#internal.update(options);\n }\n\n /**\n * Create a helper function with validated input.\n */\n createHelperFn<\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\n validator,\n additionalCtx extends Record<string, unknown>,\n response\n >(\n options: CreateHelperFunctionOptionsWithValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n validator,\n additionalCtx\n >,\n fn: HelperFnWithValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n validator,\n additionalCtx,\n response\n >\n ): CreatedHelperFnWithInput<validator, response>;\n /**\n * Create a helper function without input.\n */\n createHelperFn<\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\n additionalCtx extends Record<string, unknown>,\n response\n >(\n options: CreateHelperFunctionOptionsWithoutValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps\n > &\n CreateHelperFunctionOptionsWithCustomCtxOptions<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n additionalCtx\n >,\n fn: HelperFnWithoutValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n additionalCtx,\n response\n >\n ): CreatedHelperFnWithoutInput<response>;\n // Implementation\n createHelperFn<\n const chosenSteps extends HelperFnChosenSteps<resolvedStep, stepNumbers>,\n response,\n additionalCtx extends Record<string, unknown>,\n validator = never\n >(\n options:\n | CreateHelperFunctionOptionsWithValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n validator,\n additionalCtx\n >\n | CreateHelperFunctionOptionsWithoutValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps\n >,\n fn:\n | HelperFnWithValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n validator,\n additionalCtx,\n response\n >\n | HelperFnWithoutValidator<\n resolvedStep,\n stepNumbers,\n chosenSteps,\n additionalCtx,\n response\n >\n ) {\n const { stepData, ...rest } = options;\n\n return this.#internal.createStepHelperFn(stepData)(rest, fn);\n }\n\n /**\n * Validates that a given object is the proper shape for step data.\n * @param value\n */\n static hasData<\n step extends Step<casing>,\n resolvedStep extends ResolvedStep<step, casing>,\n stepNumbers extends StepNumbers<resolvedStep>,\n casing extends CasingType = DefaultCasing\n >(\n value: unknown,\n options?: {\n optionalKeysToCheck?: FieldChecks<\n Pick<StepOptions, 'description' | 'validateFields'>\n >;\n }\n ): value is GetCurrentStep<resolvedStep, stepNumbers> {\n if (value === null || typeof value !== 'object') {\n return false;\n }\n\n return assertObjectFields<\n | GetCurrentStep<resolvedStep, stepNumbers>\n | (Omit<StepOptions, 'fields'> & {\n fields: Expand<\n ResolvedFields<InferStepOptions<step>, keyof InferStepOptions<step>>\n >;\n })\n >(value, {\n title: (v) => typeof v === 'string',\n fields: (\n v\n ): v is Expand<\n ResolvedFields<InferStepOptions<step>, keyof InferStepOptions<step>>\n > => {\n if (v === null || typeof v !== 'object') {\n return false;\n }\n\n for (const key of Object.keys(v)) {\n if (typeof key !== 'string' || !(key in v)) {\n return false;\n }\n\n const current = (v as Record<string, unknown>)[key];\n\n if (current === null || typeof current !== 'object') {\n return false;\n }\n\n const hasField = assertObjectFields<AnyStepFieldOption>(current, {\n defaultValue: (v): v is {} => v !== 'undefined' && v !== null,\n label: (v) =>\n typeof v === 'string' || (typeof v === 'boolean' && !v),\n nameTransformCasing: isCasingValid,\n type: isFieldType,\n });\n\n if (!hasField) {\n return false;\n }\n }\n\n return true;\n },\n createHelperFn: (\n v\n ): v is GetCurrentStep<resolvedStep, stepNumbers>['createHelperFn'] =>\n typeof v === 'function',\n // update: (v): v is GetCurrentStep<resolvedStep, stepNumbers>['update'] =>\n // typeof v === 'function',\n nameTransformCasing: isCasingValid,\n ...options?.optionalKeysToCheck,\n });\n }\n\n /**\n * Gets the value of a given field for a given step.\n * @param step The step to get the value from.\n * @param field The field to get the value from.\n * @returns The value of the {@linkcode field}.\n */\n getValue<\n step extends keyof resolvedStep,\n field extends fieldsUtils.getDeep<resolvedStep, step>\n >(step: step, field: field) {\n const stepData = this.value[step];\n const baseErrorMessage = `Unable to get the value for \"${String(\n step\n )}.fields.${String(field)}\"`;\n\n invariant('fields' in stepData, baseErrorMessage);\n invariant(\n typeof stepData.fields === 'object',\n `${baseErrorMessage} because \"fields\" is not an object. This shouldn't be the case, so please open an issue`\n );\n\n const fields = stepData.fields as AnyStepField;\n\n const defaultValue = fieldsUtils.resolvedDeepPath<\n resolvedStep,\n step,\n fieldsUtils.get<resolvedStep, step>,\n field\n >(field, fields as fieldsUtils.get<resolvedStep, step>);\n\n return defaultValue;\n }\n}\n","import {\n MultiStepFormStepSchema,\n type MultiStepFormSchemaStepConfig,\n type ResolvedStep,\n type Step,\n type StepNumbers,\n} from '@/steps';\nimport {\n setCasingType,\n type CasingType,\n type Constrain,\n type DefaultCasing,\n} from '@/utils';\nimport {\n DEFAULT_STORAGE_KEY,\n MultiStepFormStorage,\n type DefaultStorageKey,\n} from './storage.js';\nimport { Subscribable } from './subscribable.js';\n\nexport interface MultiStepFormSchemaOptions<\n TStep extends Step<TCasing>,\n TCasing extends CasingType,\n TStorageKey extends string\n> extends MultiStepFormSchemaStepConfig<TStep, TCasing, TStorageKey> {}\nexport type MultiStepFormSchemaListener<\n TStep extends Step<TCasing>,\n TCasing extends CasingType,\n TStorageKey extends string\n> = (data: MultiStepFormSchemaOptions<TStep, TCasing, TStorageKey>) => void;\n\nexport class MultiStepFormSchema<\n step extends Step<casing>,\n casing extends CasingType = DefaultCasing,\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<step, casing>,\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\n storageKey extends string = DefaultStorageKey\n> extends Subscribable<MultiStepFormSchemaListener<step, casing, storageKey>> {\n readonly defaultNameTransformationCasing: casing;\n readonly stepSchema: MultiStepFormStepSchema<\n step,\n casing,\n resolvedStep,\n stepNumbers,\n storageKey\n >;\n storage: MultiStepFormStorage<resolvedStep, storageKey>;\n private mountCount = 0;\n\n constructor(\n options: MultiStepFormSchemaOptions<\n step,\n // Allows full autocomplete\n Constrain<casing, CasingType>,\n storageKey\n >\n ) {\n super();\n\n const { steps, nameTransformCasing, storage } = options;\n\n this.defaultNameTransformationCasing = setCasingType(\n nameTransformCasing\n ) as casing;\n // @ts-ignore Type instantiation is excessively deep and possibly infinite\n this.stepSchema = new MultiStepFormStepSchema({\n steps,\n nameTransformCasing: this.defaultNameTransformationCasing,\n });\n this.storage = new MultiStepFormStorage<resolvedStep, storageKey>({\n key: (storage?.key ?? DEFAULT_STORAGE_KEY) as storageKey,\n data: this.stepSchema.value as never,\n store: storage?.store,\n throwWhenUndefined: storage?.throwWhenUndefined ?? false,\n });\n\n this.stepSchema.subscribe(() => {\n this.notify();\n });\n }\n\n getSnapshot() {\n return this;\n }\n\n mount() {\n this.mountCount++;\n\n if (this.mountCount === 1) {\n this.onMount();\n }\n\n return () => {\n this.unmount();\n };\n }\n\n unmount() {\n this.mountCount = Math.max(0, this.mountCount - 1);\n\n if (this.mountCount === 0) {\n this.onUnmount();\n }\n }\n\n isMounted() {\n return this.mountCount > 0;\n }\n\n protected onMount() {}\n protected onUnmount() {}\n\n protected notify() {\n for (const listener of this.listeners) {\n listener({\n nameTransformCasing: this.defaultNameTransformationCasing,\n storage: {\n key: this.storage.key,\n store: this.storage.store,\n },\n steps: this.stepSchema.original,\n });\n }\n }\n}\n\nexport function createMultiStepFormSchema<\n step extends Step<casing>,\n casing extends CasingType = DefaultCasing,\n resolvedStep extends ResolvedStep<step, casing> = ResolvedStep<step, casing>,\n stepNumbers extends StepNumbers<resolvedStep> = StepNumbers<resolvedStep>,\n storageKey extends string = DefaultStorageKey\n>(\n options: MultiStepFormSchemaOptions<\n step,\n // Allows full autocomplete\n Constrain<casing, CasingType>,\n storageKey\n >\n) {\n return new MultiStepFormSchema<\n step,\n casing,\n resolvedStep,\n stepNumbers,\n storageKey\n >(options);\n}\n","import type { MultiStepFormSchema } from './schema';\nimport type {\n ResolvedStep,\n Step,\n StepNumbers\n} from '@/steps/types';\nimport { Subscribable } from './subscribable';\nimport type { CasingType } from '@/utils/casing';\n\nexport type ObserverListener<\n TStep extends Step<TCasing>,\n TResolvedStep extends ResolvedStep<TStep, TCasing>,\n TStepNumbers extends StepNumbers<TResolvedStep>,\n TCasing extends CasingType,\n TStorageKey extends string\n> = (\n schema: MultiStepFormSchema<\n TStep,\n TCasing,\n TResolvedStep,\n TStepNumbers,\n TStorageKey\n >\n) => void;\n\nexport type ObserverOptions<\n TStep extends Step<TCasing>,\n TResolvedStep extends ResolvedStep<TStep, TCasing>,\n TStepNumbers extends StepNumbers<TResolvedStep>,\n TCasing extends CasingType,\n TStorageKey extends string\n> = {\n schema: MultiStepFormSchema<\n TStep,\n TCasing,\n TResolvedStep,\n TStepNumbers,\n TStorageKey\n >;\n};\n\nexport class MultiStepFormObserver<\n step extends Step<casing>,\n resolvedStep extends ResolvedStep<step, casing>,\n stepNumbers extends StepNumbers<resolvedStep>,\n casing extends CasingType,\n storageKey extends string\n> extends Subscribable<\n ObserverListener<step, resolvedStep, stepNumbers, casing, storageKey>\n> {\n protected schema: MultiStepFormSchema<\n step,\n casing,\n resolvedStep,\n stepNumbers,\n storageKey\n >;\n private unsubscribeFromSchema?: () => void;\n\n constructor(\n options: ObserverOptions<\n step,\n resolvedStep,\n stepNumbers,\n casing,\n storageKey\n >\n ) {\n super();\n\n this.schema = options.schema;\n this.subscribeToSchema();\n }\n\n protected subscribeToSchema() {\n this.unsubscribeFromSchema = this.schema.subscribe(() => {\n this.notify();\n });\n }\n\n getSnapshot() {\n return this;\n }\n\n getResult() {\n return this.schema;\n }\n\n setOptions(\n options: Partial<\n ObserverOptions<step, resolvedStep, stepNumbers, casing, storageKey>\n >\n ) {\n if (options.schema && options.schema !== this.schema) {\n this.unsubscribeFromSchema?.();\n this.schema = options.schema;\n this.subscribeToSchema();\n this.notify();\n }\n }\n\n protected notify() {\n for (const listener of this.listeners) {\n listener(this.schema);\n }\n }\n\n destroy() {\n this.unsubscribeFromSchema?.();\n this.listeners.clear();\n }\n\n protected onSubscribe() {}\n\n protected onUnsubscribe() {}\n}\n"],"names":["fields","v","fieldsUtils"],"mappings":"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"}