@jayalfredprufrock/mobx-toolbox 0.6.4 → 0.7.0

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.
package/dist/form.d.mts CHANGED
@@ -13,6 +13,7 @@ declare class FormFieldModel<T extends T.TSchema = T.TSchema> {
13
13
  get errorMessage(): string;
14
14
  constructor(config: FormFieldConfig<T>);
15
15
  setValue(value?: T.Static<T>): void;
16
+ private convertValue;
16
17
  setTouched(touched: boolean): void;
17
18
  reset(): void;
18
19
  props(): any;
@@ -1 +1 @@
1
- {"version":3,"file":"form.d.mts","names":[],"sources":["../src/form/form-field.model.ts","../src/form/form.types.ts","../src/form/form.model.ts","../src/form/components/form.tsx","../src/form/components/form-when.tsx","../src/form/form.context.ts","../src/form/use-form.ts"],"mappings":"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"}
1
+ {"version":3,"file":"form.d.mts","names":[],"sources":["../src/form/form-field.model.ts","../src/form/form.types.ts","../src/form/form.model.ts","../src/form/components/form.tsx","../src/form/components/form-when.tsx","../src/form/form.context.ts","../src/form/use-form.ts"],"mappings":"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"}
package/dist/form.mjs CHANGED
@@ -79,7 +79,7 @@ var FormFieldModel = class {
79
79
  this.name = config.name;
80
80
  this.schema = config.schema;
81
81
  this.validator = Schema.Compile(this.schema);
82
- this.value = Value.Convert(this.schema, config.initialValue);
82
+ this.value = this.convertValue(config.initialValue);
83
83
  makeAutoObservable(this, {
84
84
  name: false,
85
85
  schema: false,
@@ -88,7 +88,11 @@ var FormFieldModel = class {
88
88
  });
89
89
  }
90
90
  setValue(value) {
91
- this.value = Value.Convert(this.schema, value);
91
+ this.value = this.convertValue(value);
92
+ }
93
+ convertValue(value) {
94
+ if (value === void 0 && !T.IsString(this.schema) && !T.IsBoolean(this.schema)) return;
95
+ return Value.Convert(this.schema, value);
92
96
  }
93
97
  setTouched(touched) {
94
98
  this.touched = touched;
package/dist/form.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"form.mjs","names":[],"sources":["../src/form/form.context.ts","../src/form/components/form.tsx","../src/form/components/form-when.tsx","../src/form/form-field.model.ts","../src/form/form.model.ts","../src/form/use-form.ts"],"sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { FormModel } from \"./form.model\";\n\nexport const formContext = createContext<FormModel | undefined>(undefined);\nexport const useFormContext = () => {\n const context = useContext(formContext);\n if (!context) {\n throw new Error(\n \"Form context not available. Make sure you are within the <Form> component or providing the form context manually.\",\n );\n }\n return context;\n};\n\nexport const FormProvider = formContext.Provider;\n\nexport const useFormContextIfAvailable = () => useContext(formContext);\n","import { forwardRef } from \"react\";\nimport { FormProvider } from \"../form.context\";\nimport type { FormModel } from \"../form.model\";\n\nexport interface MobxFormProps extends Omit<\n React.HTMLProps<HTMLFormElement>,\n \"form\" | \"action\" | \"method\"\n> {\n form: FormModel<any>;\n}\n\nexport const MobxForm = forwardRef(function MobxForm(\n { form, children, ...formProps }: MobxFormProps,\n ref,\n) {\n return (\n <FormProvider value={form}>\n <form noValidate {...formProps} ref={ref} {...form.props()}>\n {children}\n </form>\n </FormProvider>\n );\n});\n","import type { TUnion } from \"typebox\";\nimport { Observer } from \"mobx-react-lite\";\nimport type { FormModel } from \"../form.model\";\nimport type { FormFieldModel } from \"../form-field.model\";\nimport type {\n DiscriminatorKeys,\n DiscriminatorValue,\n FormFields,\n MatchVariant,\n} from \"../form.types\";\n\nexport interface FormWhenProps<T extends TUnion, D extends DiscriminatorKeys<T>, V extends string> {\n form: FormModel<T>;\n /** The discriminator field name. */\n field: D;\n /** Render the children only while the discriminator field equals this value. */\n value: V & DiscriminatorValue<T, D>;\n /** Receives the matching variant's fields. The form itself is already in scope. */\n children: (fields: FormFields<MatchVariant<T, D, V>>) => React.ReactNode;\n}\n\n/**\n * Renders its children only when the form's discriminator field currently holds\n * `value`, passing the fields narrowed to that variant. Stack one per variant to\n * lay out a discriminated-union form without manual conditionals or casts.\n */\nexport function FormWhen<T extends TUnion, D extends DiscriminatorKeys<T>, V extends string>({\n form,\n field,\n value,\n children,\n}: FormWhenProps<T, D, V>) {\n return (\n <Observer>\n {() => {\n const fields = form.rawFields as Record<string, FormFieldModel>;\n if (fields[field as string]?.value !== value) return null;\n return <>{children(fields as unknown as FormFields<MatchVariant<T, D, V>>)}</>;\n }}\n </Observer>\n );\n}\n","import Schema, { Validator } from \"typebox/schema\";\nimport * as Value from \"typebox/value\";\nimport * as T from \"typebox\";\nimport { makeAutoObservable, toJS } from \"mobx\";\nimport type { FormFieldConfig } from \"./form.types\";\n\n// TODO: should infer required prop\n// TODO: should also allow for \"id\", defaulting to name\n// TODO: probably shouldn't assume value is of correct type, maybe unknown?\n\nexport class FormFieldModel<T extends T.TSchema = T.TSchema> {\n readonly name: string;\n readonly schema: T;\n readonly config: FormFieldConfig<T>;\n readonly validator: Validator<T>;\n\n value: T.Static<T> | undefined;\n touched = false;\n\n get valid(): boolean {\n if (this.value === undefined && T.IsOptional(this.schema)) return true;\n return this.validator.Check(this.value);\n }\n\n get errorMessage(): string {\n if (this.valid || !this.touched) return \"\";\n // TODO: revisit this, now that .Errors returns success/fail\n const [_, errors] = this.validator.Errors(this.value);\n const error = errors.at(0);\n\n if (!error) return \"\";\n\n if (!T.IsOptional(this.schema) && (this.value === undefined || this.value === \"\")) {\n return \"This field is required.\";\n }\n\n if (\"errorMessage\" in this.schema) {\n if (typeof this.schema.errorMessage === \"string\") {\n return this.schema.errorMessage;\n } else if (typeof this.schema.errorMessage === \"function\") {\n return this.schema.errorMessage(this.value, this.schema);\n }\n }\n\n if (T.IsString(this.schema) && \"format\" in this.schema) {\n return `Please enter a valid ${String(this.schema.format)}`;\n }\n\n return error.message;\n }\n\n constructor(config: FormFieldConfig<T>) {\n this.config = config;\n this.name = config.name;\n this.schema = config.schema;\n this.validator = Schema.Compile(this.schema);\n this.value = Value.Convert(this.schema, config.initialValue) as T.Static<T>;\n\n makeAutoObservable(this, {\n name: false,\n schema: false,\n config: false,\n validator: false,\n });\n }\n\n setValue(value?: T.Static<T>) {\n // TODO: does this still make sense? If value is invalid,\n // then type will be wrong...revisit this\n this.value = Value.Convert(this.schema, value) as T.Static<T>;\n }\n\n setTouched(touched: boolean) {\n this.touched = touched;\n }\n\n reset() {\n this.setTouched(false);\n this.setValue(this.config.initialValue);\n }\n\n // TODO: this any type is dangerous, need to figure out a good way\n // to make this work OTTB for most form controls, while allowing\n // some kind of escape hatch for special cases\n props(): any {\n return {\n name: this.name,\n onChange: (v?: T.Static<T>) => this.setValue(v),\n value: this.value,\n onBlur: () => {\n this.setTouched(true);\n },\n };\n }\n\n toJSON(): T.Static<T> | undefined {\n return toJS(this.value);\n }\n}\n","import * as Format from \"typebox/format\";\nimport * as Value from \"typebox/value\";\nimport Schema, { type Validator } from \"typebox/schema\";\nimport { IsUnion, Union, type Static, type TObject, type TSchema } from \"typebox\";\nimport { makeAutoObservable } from \"mobx\";\nimport type { FormConfig, FormFields, FormSchema, RawFormFields } from \"./form.types\";\nimport { FormFieldModel } from \"./form-field.model\";\n\n// should these be here?\nFormat.Set(\"password\", () => true);\nFormat.Set(\"phone\", () => true);\n\n// Flatten a schema's fields into a single property map. For a discriminated\n// union this merges the properties of every variant, unioning the schemas of\n// any field that appears in more than one variant (which naturally turns the\n// discriminator into a union of its literals).\nfunction resolveProperties(schema: FormSchema): Record<string, TSchema> {\n if (!IsUnion(schema)) return schema.properties;\n\n const groups: Record<string, TSchema[]> = {};\n for (const variant of schema.anyOf) {\n for (const [key, propSchema] of Object.entries((variant as TObject).properties)) {\n (groups[key] ??= []).push(propSchema as TSchema);\n }\n }\n\n const merged: Record<string, TSchema> = {};\n for (const [key, schemas] of Object.entries(groups)) {\n const distinct = [...new Map(schemas.map((s) => [JSON.stringify(s), s])).values()];\n merged[key] = distinct.length === 1 ? distinct[0]! : Union(distinct);\n }\n return merged;\n}\n\n// consider using enumerable to allow spreading of\n// field model instead of calling props() unless we need\n// to pass data to props...\n\n// TODO:\n// handleSubmit should catch a special MobxFormError\n// that can set field-level errors from an API response\n\nexport class FormModel<T extends FormSchema = TObject> {\n /** Shared fields only (for unions); every field for a plain object schema. */\n readonly fields: FormFields<T>;\n /** Every field across all variants — escape hatch for reaching variant fields. */\n readonly rawFields: RawFormFields<T>;\n readonly config: FormConfig<T>;\n readonly schema: T;\n readonly validator: Validator<T>;\n\n // TODO: maybe refactor into a \"state\" property?\n submitting = false;\n submitted = false;\n\n // TODO: what should this type be? should it be generic?\n submitError: any;\n\n constructor(schema: T, config: FormConfig<T>) {\n this.schema = schema;\n this.config = config;\n this.validator = Schema.Compile(schema);\n\n makeAutoObservable(this, {\n fields: false,\n rawFields: false,\n schema: false,\n config: false,\n validator: false,\n });\n\n const initialValues = config?.initialValues as Record<string, unknown> | undefined;\n const fields = Object.entries(resolveProperties(schema)).reduce(\n (fields, [fieldName, fieldSchema]) => {\n fields[fieldName] = new FormFieldModel({\n name: fieldName,\n schema: fieldSchema,\n initialValue: initialValues?.[fieldName],\n });\n return fields;\n },\n {} as Record<string, FormFieldModel<TSchema>>,\n );\n\n // `fields` and `rawFields` are the same object; the types differ so that a\n // union form only surfaces shared fields by default.\n this.rawFields = fields as unknown as RawFormFields<T>;\n this.fields = fields as unknown as FormFields<T>;\n }\n\n get valid(): boolean {\n // A union form can't be validated field-by-field — fields belonging to the\n // inactive variant would fail — so validate the assembled object instead.\n if (IsUnion(this.schema)) {\n return this.validator.Check(this.toJSON());\n }\n return Object.values(this.fields).every((field) => field.valid);\n }\n\n props(): any {\n return {\n onSubmit: (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n\n this.setSubmitError(undefined);\n\n if (!this.validate()) {\n return;\n }\n\n this.setSubmitting(true);\n this.config\n .handleSubmit(this.toJSON() as Static<T>)\n .then((resp) => {\n this.setSubmitted(true);\n return resp;\n })\n .catch((e) => {\n this.setSubmitError(e);\n })\n .finally(() => {\n this.setSubmitting(false);\n });\n },\n };\n }\n\n setSubmitError(error: any): void {\n this.submitError = error;\n }\n\n protected setSubmitting(submitting: boolean): void {\n this.submitting = submitting;\n }\n\n protected setSubmitted(submitted: boolean): void {\n this.submitted = submitted;\n }\n\n reset(): void {\n this.setSubmitError(undefined);\n for (const field of Object.values(this.fields)) {\n field.reset();\n }\n }\n\n validate(): boolean {\n for (const field of Object.values(this.fields)) {\n field.setTouched(true);\n }\n return this.valid;\n }\n\n toJSON(): Partial<Static<T>> {\n const data = Object.values(this.fields).reduce(\n (fields, field) => {\n fields[field.name] = field.toJSON();\n return fields;\n },\n {} as Record<string, unknown>,\n );\n\n // Drop fields belonging to the inactive variant so submitted data matches\n // the selected member of the union exactly.\n if (IsUnion(this.schema)) {\n return Value.Clean(this.schema, data) as Partial<Static<T>>;\n }\n return data as Partial<Static<T>>;\n }\n}\n","import type { TObject } from \"typebox\";\nimport { useRef } from \"react\";\nimport { FormModel } from \"./form.model\";\nimport type { FormConfig, FormSchema } from \"./form.types\";\n\nexport const useForm = <T extends FormSchema = TObject>(\n schema: T,\n config: FormConfig<T>,\n): FormModel<T> => {\n const formRef = useRef<FormModel<T>>(undefined);\n if (formRef.current) {\n Object.assign(formRef.current.config, config);\n } else {\n formRef.current = new FormModel<T>(schema, config);\n }\n\n return formRef.current;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"form.mjs","names":[],"sources":["../src/form/form.context.ts","../src/form/components/form.tsx","../src/form/components/form-when.tsx","../src/form/form-field.model.ts","../src/form/form.model.ts","../src/form/use-form.ts"],"sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { FormModel } from \"./form.model\";\n\nexport const formContext = createContext<FormModel | undefined>(undefined);\nexport const useFormContext = () => {\n const context = useContext(formContext);\n if (!context) {\n throw new Error(\n \"Form context not available. Make sure you are within the <Form> component or providing the form context manually.\",\n );\n }\n return context;\n};\n\nexport const FormProvider = formContext.Provider;\n\nexport const useFormContextIfAvailable = () => useContext(formContext);\n","import { forwardRef } from \"react\";\nimport { FormProvider } from \"../form.context\";\nimport type { FormModel } from \"../form.model\";\n\nexport interface MobxFormProps extends Omit<\n React.HTMLProps<HTMLFormElement>,\n \"form\" | \"action\" | \"method\"\n> {\n form: FormModel<any>;\n}\n\nexport const MobxForm = forwardRef(function MobxForm(\n { form, children, ...formProps }: MobxFormProps,\n ref,\n) {\n return (\n <FormProvider value={form}>\n <form noValidate {...formProps} ref={ref} {...form.props()}>\n {children}\n </form>\n </FormProvider>\n );\n});\n","import type { TUnion } from \"typebox\";\nimport { Observer } from \"mobx-react-lite\";\nimport type { FormModel } from \"../form.model\";\nimport type { FormFieldModel } from \"../form-field.model\";\nimport type {\n DiscriminatorKeys,\n DiscriminatorValue,\n FormFields,\n MatchVariant,\n} from \"../form.types\";\n\nexport interface FormWhenProps<T extends TUnion, D extends DiscriminatorKeys<T>, V extends string> {\n form: FormModel<T>;\n /** The discriminator field name. */\n field: D;\n /** Render the children only while the discriminator field equals this value. */\n value: V & DiscriminatorValue<T, D>;\n /** Receives the matching variant's fields. The form itself is already in scope. */\n children: (fields: FormFields<MatchVariant<T, D, V>>) => React.ReactNode;\n}\n\n/**\n * Renders its children only when the form's discriminator field currently holds\n * `value`, passing the fields narrowed to that variant. Stack one per variant to\n * lay out a discriminated-union form without manual conditionals or casts.\n */\nexport function FormWhen<T extends TUnion, D extends DiscriminatorKeys<T>, V extends string>({\n form,\n field,\n value,\n children,\n}: FormWhenProps<T, D, V>) {\n return (\n <Observer>\n {() => {\n const fields = form.rawFields as Record<string, FormFieldModel>;\n if (fields[field as string]?.value !== value) return null;\n return <>{children(fields as unknown as FormFields<MatchVariant<T, D, V>>)}</>;\n }}\n </Observer>\n );\n}\n","import Schema, { Validator } from \"typebox/schema\";\nimport * as Value from \"typebox/value\";\nimport * as T from \"typebox\";\nimport { makeAutoObservable, toJS } from \"mobx\";\nimport type { FormFieldConfig } from \"./form.types\";\n\n// TODO: should infer required prop\n// TODO: should also allow for \"id\", defaulting to name\n// TODO: probably shouldn't assume value is of correct type, maybe unknown?\n\nexport class FormFieldModel<T extends T.TSchema = T.TSchema> {\n readonly name: string;\n readonly schema: T;\n readonly config: FormFieldConfig<T>;\n readonly validator: Validator<T>;\n\n value: T.Static<T> | undefined;\n touched = false;\n\n get valid(): boolean {\n if (this.value === undefined && T.IsOptional(this.schema)) return true;\n return this.validator.Check(this.value);\n }\n\n get errorMessage(): string {\n if (this.valid || !this.touched) return \"\";\n // TODO: revisit this, now that .Errors returns success/fail\n const [_, errors] = this.validator.Errors(this.value);\n const error = errors.at(0);\n\n if (!error) return \"\";\n\n if (!T.IsOptional(this.schema) && (this.value === undefined || this.value === \"\")) {\n return \"This field is required.\";\n }\n\n if (\"errorMessage\" in this.schema) {\n if (typeof this.schema.errorMessage === \"string\") {\n return this.schema.errorMessage;\n } else if (typeof this.schema.errorMessage === \"function\") {\n return this.schema.errorMessage(this.value, this.schema);\n }\n }\n\n if (T.IsString(this.schema) && \"format\" in this.schema) {\n return `Please enter a valid ${String(this.schema.format)}`;\n }\n\n return error.message;\n }\n\n constructor(config: FormFieldConfig<T>) {\n this.config = config;\n this.name = config.name;\n this.schema = config.schema;\n this.validator = Schema.Compile(this.schema);\n this.value = this.convertValue(config.initialValue);\n\n makeAutoObservable(this, {\n name: false,\n schema: false,\n config: false,\n validator: false,\n });\n }\n\n setValue(value?: T.Static<T>) {\n // TODO: does this still make sense? If value is invalid,\n // then type will be wrong...revisit this\n this.value = this.convertValue(value);\n }\n\n private convertValue(value: unknown): T.Static<T> | undefined {\n // Value.Convert fabricates zero-values for undefined primitives (\"\" / 0 / false).\n // Only \"\" and false faithfully represent an empty control; a fabricated 0 reads\n // as real input (e.g. an epoch-0 date), so everything else stays undefined.\n if (value === undefined && !T.IsString(this.schema) && !T.IsBoolean(this.schema)) {\n return undefined;\n }\n return Value.Convert(this.schema, value) as T.Static<T>;\n }\n\n setTouched(touched: boolean) {\n this.touched = touched;\n }\n\n reset() {\n this.setTouched(false);\n this.setValue(this.config.initialValue);\n }\n\n // TODO: this any type is dangerous, need to figure out a good way\n // to make this work OTTB for most form controls, while allowing\n // some kind of escape hatch for special cases\n props(): any {\n return {\n name: this.name,\n onChange: (v?: T.Static<T>) => this.setValue(v),\n value: this.value,\n onBlur: () => {\n this.setTouched(true);\n },\n };\n }\n\n toJSON(): T.Static<T> | undefined {\n return toJS(this.value);\n }\n}\n","import * as Format from \"typebox/format\";\nimport * as Value from \"typebox/value\";\nimport Schema, { type Validator } from \"typebox/schema\";\nimport { IsUnion, Union, type Static, type TObject, type TSchema } from \"typebox\";\nimport { makeAutoObservable } from \"mobx\";\nimport type { FormConfig, FormFields, FormSchema, RawFormFields } from \"./form.types\";\nimport { FormFieldModel } from \"./form-field.model\";\n\n// should these be here?\nFormat.Set(\"password\", () => true);\nFormat.Set(\"phone\", () => true);\n\n// Flatten a schema's fields into a single property map. For a discriminated\n// union this merges the properties of every variant, unioning the schemas of\n// any field that appears in more than one variant (which naturally turns the\n// discriminator into a union of its literals).\nfunction resolveProperties(schema: FormSchema): Record<string, TSchema> {\n if (!IsUnion(schema)) return schema.properties;\n\n const groups: Record<string, TSchema[]> = {};\n for (const variant of schema.anyOf) {\n for (const [key, propSchema] of Object.entries((variant as TObject).properties)) {\n (groups[key] ??= []).push(propSchema as TSchema);\n }\n }\n\n const merged: Record<string, TSchema> = {};\n for (const [key, schemas] of Object.entries(groups)) {\n const distinct = [...new Map(schemas.map((s) => [JSON.stringify(s), s])).values()];\n merged[key] = distinct.length === 1 ? distinct[0]! : Union(distinct);\n }\n return merged;\n}\n\n// consider using enumerable to allow spreading of\n// field model instead of calling props() unless we need\n// to pass data to props...\n\n// TODO:\n// handleSubmit should catch a special MobxFormError\n// that can set field-level errors from an API response\n\nexport class FormModel<T extends FormSchema = TObject> {\n /** Shared fields only (for unions); every field for a plain object schema. */\n readonly fields: FormFields<T>;\n /** Every field across all variants — escape hatch for reaching variant fields. */\n readonly rawFields: RawFormFields<T>;\n readonly config: FormConfig<T>;\n readonly schema: T;\n readonly validator: Validator<T>;\n\n // TODO: maybe refactor into a \"state\" property?\n submitting = false;\n submitted = false;\n\n // TODO: what should this type be? should it be generic?\n submitError: any;\n\n constructor(schema: T, config: FormConfig<T>) {\n this.schema = schema;\n this.config = config;\n this.validator = Schema.Compile(schema);\n\n makeAutoObservable(this, {\n fields: false,\n rawFields: false,\n schema: false,\n config: false,\n validator: false,\n });\n\n const initialValues = config?.initialValues as Record<string, unknown> | undefined;\n const fields = Object.entries(resolveProperties(schema)).reduce(\n (fields, [fieldName, fieldSchema]) => {\n fields[fieldName] = new FormFieldModel({\n name: fieldName,\n schema: fieldSchema,\n initialValue: initialValues?.[fieldName],\n });\n return fields;\n },\n {} as Record<string, FormFieldModel<TSchema>>,\n );\n\n // `fields` and `rawFields` are the same object; the types differ so that a\n // union form only surfaces shared fields by default.\n this.rawFields = fields as unknown as RawFormFields<T>;\n this.fields = fields as unknown as FormFields<T>;\n }\n\n get valid(): boolean {\n // A union form can't be validated field-by-field — fields belonging to the\n // inactive variant would fail — so validate the assembled object instead.\n if (IsUnion(this.schema)) {\n return this.validator.Check(this.toJSON());\n }\n return Object.values(this.fields).every((field) => field.valid);\n }\n\n props(): any {\n return {\n onSubmit: (e: React.FormEvent<HTMLFormElement>) => {\n e.preventDefault();\n\n this.setSubmitError(undefined);\n\n if (!this.validate()) {\n return;\n }\n\n this.setSubmitting(true);\n this.config\n .handleSubmit(this.toJSON() as Static<T>)\n .then((resp) => {\n this.setSubmitted(true);\n return resp;\n })\n .catch((e) => {\n this.setSubmitError(e);\n })\n .finally(() => {\n this.setSubmitting(false);\n });\n },\n };\n }\n\n setSubmitError(error: any): void {\n this.submitError = error;\n }\n\n protected setSubmitting(submitting: boolean): void {\n this.submitting = submitting;\n }\n\n protected setSubmitted(submitted: boolean): void {\n this.submitted = submitted;\n }\n\n reset(): void {\n this.setSubmitError(undefined);\n for (const field of Object.values(this.fields)) {\n field.reset();\n }\n }\n\n validate(): boolean {\n for (const field of Object.values(this.fields)) {\n field.setTouched(true);\n }\n return this.valid;\n }\n\n toJSON(): Partial<Static<T>> {\n const data = Object.values(this.fields).reduce(\n (fields, field) => {\n fields[field.name] = field.toJSON();\n return fields;\n },\n {} as Record<string, unknown>,\n );\n\n // Drop fields belonging to the inactive variant so submitted data matches\n // the selected member of the union exactly.\n if (IsUnion(this.schema)) {\n return Value.Clean(this.schema, data) as Partial<Static<T>>;\n }\n return data as Partial<Static<T>>;\n }\n}\n","import type { TObject } from \"typebox\";\nimport { useRef } from \"react\";\nimport { FormModel } from \"./form.model\";\nimport type { FormConfig, FormSchema } from \"./form.types\";\n\nexport const useForm = <T extends FormSchema = TObject>(\n schema: T,\n config: FormConfig<T>,\n): FormModel<T> => {\n const formRef = useRef<FormModel<T>>(undefined);\n if (formRef.current) {\n Object.assign(formRef.current.config, config);\n } else {\n formRef.current = new FormModel<T>(schema, config);\n }\n\n return formRef.current;\n};\n"],"mappings":"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"}
package/dist/router.d.mts CHANGED
@@ -1,50 +1,6 @@
1
1
  import React$1 from "react";
2
2
  import { History, Location } from "history";
3
3
 
4
- //#region src/router/outlet.d.ts
5
- interface OutletConfig {
6
- component?: Component | LazyComponent;
7
- loader?: Loader;
8
- }
9
- type RouteSegmentState = "preloading" | "loading" | "error" | "ready";
10
- declare const DefaultOutlet: Component;
11
- declare class Outlet {
12
- readonly config: OutletConfig;
13
- state: RouteSegmentState;
14
- promise: Promise<unknown> | undefined;
15
- data: unknown;
16
- component: Component | undefined;
17
- get Component(): Component | undefined;
18
- constructor(config: OutletConfig);
19
- load(route: Route): Promise<void>;
20
- setData(data: unknown): void;
21
- setState(state: RouteSegmentState): void;
22
- private loadData;
23
- private loadComponent;
24
- }
25
- //#endregion
26
- //#region src/router/route.d.ts
27
- interface RouteConfig$1 {
28
- path: string;
29
- outlets: Outlet[];
30
- guards: Guard[];
31
- context?: Obj;
32
- layout?: Component;
33
- params: Obj;
34
- }
35
- declare class Route {
36
- readonly path: string;
37
- readonly outlets: Outlet[];
38
- readonly guards: Guard[];
39
- readonly context: Obj;
40
- readonly params: Obj;
41
- readonly layout?: Component;
42
- get data(): Obj;
43
- constructor(def: RouteConfig$1);
44
- guard(): Promise<void>;
45
- load(): Promise<void>;
46
- }
47
- //#endregion
48
4
  //#region src/router/symbols.d.ts
49
5
  declare const CONTEXT: unique symbol;
50
6
  declare const LAYOUT: unique symbol;
@@ -52,6 +8,7 @@ declare const WRAPPER: unique symbol;
52
8
  declare const LOAD: unique symbol;
53
9
  declare const GUARD: unique symbol;
54
10
  declare const PAGE: unique symbol;
11
+ declare const ERROR: unique symbol;
55
12
  declare const REDIRECT: unique symbol;
56
13
  //#endregion
57
14
  //#region src/router/types.d.ts
@@ -60,12 +17,29 @@ type LazyComponent = () => Promise<any>;
60
17
  type Obj<T = any> = Record<string, T>;
61
18
  type Loader = (route: Route) => Promise<any>;
62
19
  type Guard = (route: Route) => Promise<void>;
20
+ /** The props every `[ERROR]` component receives. */
21
+ interface ErrorComponentProps {
22
+ route: Route;
23
+ error: RouterError;
24
+ }
25
+ /** @internal a guard together with the route level that declared it */
26
+ interface GuardEntry {
27
+ guard: Guard;
28
+ depth: number;
29
+ }
30
+ /** @internal per-level snapshot used to build synthetic error routes */
31
+ interface MatchLevel {
32
+ wrapper?: Component;
33
+ layout?: Component;
34
+ errorComponent?: Component;
35
+ }
63
36
  interface RouteConfig {
64
37
  [CONTEXT]?: Obj;
65
38
  [LAYOUT]?: Component;
66
39
  [WRAPPER]?: Component;
67
40
  [GUARD]?: Guard;
68
41
  [LOAD]?: Loader;
42
+ [ERROR]?: Component;
69
43
  }
70
44
  /**
71
45
  * A route page definition.
@@ -134,9 +108,148 @@ type DynamicRoutePath = Extract<RoutePath, `${string}:${string}`>;
134
108
  type StaticRoutePath = Exclude<RoutePath, `${string}:${string}`>;
135
109
  /********************************************************************************* */
136
110
  type JoinSegments<S1, S2> = `/${S1 extends string ? S1 : ""}${S2 extends string ? S2 : ""}`;
111
+ type SegmentName<S> = S extends `$${infer Param}` ? `:${Param}` : S;
137
112
  type ExtractParam<P, NextPart> = P extends `:${infer Param}` ? Record<Param, string> & NextPart : NextPart;
138
113
  type ExtractParams<P> = P extends `${infer S1}/${infer Rest}` ? ExtractParam<S1, ExtractParams<Rest>> : ExtractParam<P, {}>;
139
- type ExtractPaths<R> = { [S in keyof R]: S extends string ? S extends "index" ? "/" : R[S] extends Leaf ? `/${S}` : JoinSegments<S, ExtractPaths<R[S]>> : never }[keyof R];
114
+ type ExtractPaths<R> = { [S in keyof R]: S extends string ? S extends "index" ? "/" : R[S] extends Leaf ? `/${SegmentName<S> extends string ? SegmentName<S> : ""}` : JoinSegments<SegmentName<S>, ExtractPaths<R[S]>> : never }[keyof R];
115
+ //#endregion
116
+ //#region src/router/route.d.ts
117
+ interface RouteConfig$1 {
118
+ path: string;
119
+ outlets: Outlet[];
120
+ guards: GuardEntry[];
121
+ levels: MatchLevel[];
122
+ context?: Obj;
123
+ layout?: Component;
124
+ params: Obj;
125
+ error?: RouterError;
126
+ }
127
+ declare class Route {
128
+ readonly path: string;
129
+ readonly outlets: Outlet[];
130
+ readonly guards: Guard[];
131
+ readonly context: Obj;
132
+ readonly params: Obj;
133
+ readonly layout?: Component;
134
+ /** set on synthetic error routes; the error being rendered */
135
+ readonly error?: RouterError;
136
+ /** @internal */
137
+ readonly guardEntries: GuardEntry[];
138
+ /** @internal */
139
+ readonly levels: MatchLevel[];
140
+ get data(): Obj;
141
+ constructor(def: RouteConfig$1);
142
+ guard(): Promise<void>;
143
+ load(): Promise<void>;
144
+ }
145
+ //#endregion
146
+ //#region src/router/outlet.d.ts
147
+ interface OutletConfig {
148
+ component?: Component | LazyComponent;
149
+ loader?: Loader;
150
+ errorComponent?: Component;
151
+ }
152
+ type RouteSegmentState = "preloading" | "loading" | "error" | "ready";
153
+ declare const DefaultOutlet: Component;
154
+ declare class Outlet {
155
+ readonly config: OutletConfig;
156
+ state: RouteSegmentState;
157
+ promise: Promise<unknown> | undefined;
158
+ data: unknown;
159
+ error: RouterError | undefined;
160
+ component: Component | undefined;
161
+ get Component(): Component | undefined;
162
+ constructor(config: OutletConfig);
163
+ load(route: Route): Promise<void>;
164
+ setData(data: unknown): void;
165
+ setError(error: RouterError): void;
166
+ setState(state: RouteSegmentState): void;
167
+ private loadData;
168
+ private loadComponent;
169
+ }
170
+ //#endregion
171
+ //#region src/router/make-routes.d.ts
172
+ interface MatchState {
173
+ segments: string[];
174
+ context: Obj;
175
+ params: Obj;
176
+ outlets: (Outlet | undefined)[];
177
+ guards: GuardEntry[];
178
+ levels: MatchLevel[];
179
+ layout?: Component;
180
+ errorComponent?: Component;
181
+ }
182
+ declare const makeRoute: (matchState: MatchState) => Route;
183
+ /**
184
+ * Builds the synthetic route rendered when navigation fails. Bubbles
185
+ * from the failing level (`error.depth`, defaulting to the deepest
186
+ * matched level) to the nearest `[ERROR]` component, preserving the
187
+ * `[LAYOUT]` and `[WRAPPER]`s accumulated up to that level. Ancestor
188
+ * `[LOAD]` loaders are intentionally not run — error routes never
189
+ * fetch data.
190
+ */
191
+ declare const makeErrorRoute: (error: RouterError, pathname: string, source?: {
192
+ levels: MatchLevel[];
193
+ params: Obj;
194
+ context: Obj;
195
+ }) => Route;
196
+ declare const matchRoute: (path: string, routeDef: Routes, matchState?: MatchState) => Route;
197
+ declare const makeRoutes: () => <R extends Routes>(routes: R) => R;
198
+ //#endregion
199
+ //#region src/router/errors.d.ts
200
+ type RouterErrorType = "NOT_FOUND" | "GUARD" | "LOAD" | "RENDER";
201
+ interface RouterErrorOptions {
202
+ message?: string;
203
+ cause?: unknown;
204
+ path?: string;
205
+ }
206
+ /**
207
+ * The single error type surfaced to `[ERROR]` components. `type`
208
+ * discriminates the failure source; when the router wraps an
209
+ * application-level error (thrown by a guard or loader), the original
210
+ * is preserved on the standard `cause` property.
211
+ *
212
+ * Guards and loaders may also throw `RouterError` directly — e.g.
213
+ * `throw new RouterError("NOT_FOUND")` from a loader when an entity
214
+ * doesn't exist — and it passes through unwrapped.
215
+ */
216
+ declare class RouterError extends Error {
217
+ readonly type: RouterErrorType;
218
+ readonly path?: string;
219
+ /** @internal matched-prefix state captured when the matcher throws NOT_FOUND */
220
+ state?: MatchState;
221
+ /** @internal level index of the failing guard, for depth-aware bubbling */
222
+ depth?: number;
223
+ constructor(type: RouterErrorType, options?: RouterErrorOptions);
224
+ }
225
+ //#endregion
226
+ //#region src/router/components/error.d.ts
227
+ /**
228
+ * Rendered when an error occurs and no `[ERROR]` component is defined
229
+ * on the matched prefix. Deliberately minimal and dependency-free —
230
+ * define a root-level `[ERROR]` to replace it.
231
+ */
232
+ declare const DefaultErrorPage: Component;
233
+ interface RouteErrorBoundaryProps {
234
+ route: Route;
235
+ fallback: Component;
236
+ children?: React$1.ReactNode;
237
+ }
238
+ interface RouteErrorBoundaryState {
239
+ error?: RouterError;
240
+ }
241
+ /**
242
+ * Catches render-time crashes in page and `[WRAPPER]` components and
243
+ * renders the nearest `[ERROR]` component with `type: "RENDER"`. Mounted
244
+ * inside the `[LAYOUT]` so the layout survives page crashes; crashes in
245
+ * the layout itself (or in the fallback) propagate out of `<Router>` by
246
+ * design — those are developer bugs that should stay loud.
247
+ */
248
+ declare class RouteErrorBoundary extends React$1.Component<RouteErrorBoundaryProps, RouteErrorBoundaryState> {
249
+ state: RouteErrorBoundaryState;
250
+ static getDerivedStateFromError(cause: unknown): RouteErrorBoundaryState;
251
+ render(): React$1.ReactNode;
252
+ }
140
253
  //#endregion
141
254
  //#region src/router/components/link.d.ts
142
255
  type LinkComponentProps<C extends React$1.ElementType> = Omit<React$1.ComponentProps<C>, "ref" | "exact" | "to" | "params" | "onClick" | "asChild">;
@@ -204,19 +317,6 @@ declare const Router: (({
204
317
  displayName: string;
205
318
  };
206
319
  //#endregion
207
- //#region src/router/make-routes.d.ts
208
- interface MatchState {
209
- segments: string[];
210
- context: Obj;
211
- params: Obj;
212
- outlets: (Outlet | undefined)[];
213
- guards: (Guard | undefined)[];
214
- layout?: Component;
215
- }
216
- declare const makeRoute: (matchState: MatchState) => Route;
217
- declare const matchRoute: (path: string, routeDef: Routes, matchState?: MatchState) => Route;
218
- declare const makeRoutes: () => <R extends Routes>(routes: R) => R;
219
- //#endregion
220
320
  //#region src/router/redirect.d.ts
221
321
  declare class Redirect<P extends RoutePath> {
222
322
  readonly options: NavigateOptions<P>;
@@ -232,5 +332,5 @@ declare const isRedirect: (data: any) => data is Redirector;
232
332
  declare const isLeaf: (data: any) => data is Leaf;
233
333
  declare const isLazyComponent: (data: any) => data is LazyComponent;
234
334
  //#endregion
235
- export { CONTEXT, Component, DefaultOutlet, DynamicRoutePath, ExtractParam, ExtractParams, ExtractPaths, GUARD, Guard, HasParam, JoinSegments, LAYOUT, LOAD, LazyComponent, Leaf, LinkComponent, LinkPropsBase, Loader, MatchState, MobxRenderSegment, MobxRouter, MobxRouterConfig, MobxRouterRoutes, Navigate, NavigateOptions, Obj, Outlet, OutletConfig, PAGE, Page, PassThrough, REDIRECT, Redirect, Redirector, Route, RouteConfig, RoutePath, RouteSegmentState, Router, RouterOutlet, RouterProps, RouterStore, Routes, StaticRoutePath, WRAPPER, WithToAndParams, isComponent, isLazyComponent, isLeaf, isPage, isRedirect, makeLinkComponent, makeRoute, makeRoutes, matchRoute, redirect, resolvePath, routerContext, useRouter };
335
+ export { CONTEXT, Component, DefaultErrorPage, DefaultOutlet, DynamicRoutePath, ERROR, ErrorComponentProps, ExtractParam, ExtractParams, ExtractPaths, GUARD, Guard, GuardEntry, HasParam, JoinSegments, LAYOUT, LOAD, LazyComponent, Leaf, LinkComponent, LinkPropsBase, Loader, MatchLevel, MatchState, MobxRenderSegment, MobxRouter, MobxRouterConfig, MobxRouterRoutes, Navigate, NavigateOptions, Obj, Outlet, OutletConfig, PAGE, Page, PassThrough, REDIRECT, Redirect, Redirector, Route, RouteConfig, RouteErrorBoundary, RouteErrorBoundaryProps, RoutePath, RouteSegmentState, Router, RouterError, RouterErrorOptions, RouterErrorType, RouterOutlet, RouterProps, RouterStore, Routes, SegmentName, StaticRoutePath, WRAPPER, WithToAndParams, isComponent, isLazyComponent, isLeaf, isPage, isRedirect, makeErrorRoute, makeLinkComponent, makeRoute, makeRoutes, matchRoute, redirect, resolvePath, routerContext, useRouter };
236
336
  //# sourceMappingURL=router.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"router.d.mts","names":[],"sources":["../src/router/outlet.tsx","../src/router/route.tsx","../src/router/symbols.ts","../src/router/types.ts","../src/router/components/link.tsx","../src/router/components/navigate.tsx","../src/router/router.store.ts","../src/router/components/router.tsx","../src/router/make-routes.tsx","../src/router/redirect.ts","../src/router/util.ts"],"mappings":";;;;UAKiB,YAAA;EACf,SAAA,GAAY,SAAA,GAAY,aAAA;EACxB,MAAA,GAAS,MAAA;AAAA;AAAA,KAGC,iBAAA;AAAA,cAEC,aAAA,EAAe,SAAsC;AAAA,cAIrD,MAAA;EAAA,SAuBU,MAAA,EAAQ,YAAA;EAtB7B,KAAA,EAAO,iBAAA;EACP,OAAA,EAAS,OAAA;EACT,IAAA;EAOA,SAAA,EAAW,SAAA;EAAA,IAEP,SAAA,IAAa,SAAA;EAWjB,WAAA,CAAqB,MAAA,EAAQ,YAAA;EAavB,IAAA,CAAK,KAAA,EAAO,KAAA,GAAQ,OAAA;EAiD1B,OAAA,CAAQ,IAAA;EAIR,QAAA,CAAS,KAAA,EAAO,iBAAA;EAAA,QAIF,QAAA;EAAA,QAIA,aAAA;AAAA;;;UC7GC,aAAA;EACf,IAAA;EACA,OAAA,EAAS,MAAA;EACT,MAAA,EAAQ,KAAA;EACR,OAAA,GAAU,GAAA;EACV,MAAA,GAAS,SAAA;EACT,MAAA,EAAQ,GAAA;AAAA;AAAA,cAGG,KAAA;EAAA,SACF,IAAA;EAAA,SACA,OAAA,EAAS,MAAA;EAAA,SACT,MAAA,EAAQ,KAAA;EAAA,SACR,OAAA,EAAS,GAAA;EAAA,SACT,MAAA,EAAQ,GAAA;EAAA,SACR,MAAA,GAAS,SAAA;EAAA,IAEd,IAAA,IAAQ,GAAA;EAIZ,WAAA,CAAY,GAAA,EAAK,aAAA;EAaX,KAAA,IAAS,OAAA;EAMT,IAAA,IAAQ,OAAA;AAAA;;;cC5CH,OAAA;AAAA,cACA,MAAA;AAAA,cACA,OAAA;AAAA,cACA,IAAA;AAAA,cACA,KAAA;AAAA,cACA,IAAA;AAAA,cACA,QAAA;;;KCFD,SAAA,GAAY,KAAA,CAAM,EAAE;AAAA,KACpB,aAAA,SAAsB,OAAO;AAAA,KAC7B,GAAA,YAAe,MAAM,SAAS,CAAA;AAAA,KAC9B,MAAA,IAAU,KAAA,EAAO,KAAA,KAAU,OAAO;AAAA,KAClC,KAAA,IAAS,KAAA,EAAO,KAAA,KAAU,OAAO;AAAA,UAE5B,WAAA;EAAA,CACd,OAAA,IAAW,GAAA;EAAA,CACX,MAAA,IAAU,SAAA;EAAA,CACV,OAAA,IAAW,SAAA;EAAA,CACX,KAAA,IAAS,KAAA;EAAA,CACT,IAAA,IAAQ,MAAA;AAAA;;;;AHRM;AAGjB;;;;AAA6B;AAE7B;;;;AAAkE;AAIlE;;;;;;;;;;;UG2BiB,IAAA,SAAa,IAAA,CAAK,WAAA,SAAoB,OAAA;EAAA,CACpD,IAAA,GAAO,SAAA,GAAY,aAAA;AAAA;AAAA,UAGL,UAAA;EAAA,CACd,QAAQ,YAAY,eAAA;AAAA;AAAA,KAGX,IAAA,GAAO,IAAA,GAAO,UAAA,GAAa,SAAA,GAAY,aAAA;AAAA,UAElC,MAAA,SAAe,WAAA;EAAA,CAC7B,OAAA,WAAkB,IAAA,GAAO,MAAA;AAAA;AAAA,KAGhB,QAAA,MAAc,CAAC;AAAA,KAEf,eAAA,WAA0B,SAAA,uBACzB,aAAA,CAAc,CAAA;EACnB,EAAA,EAAI,CAAA;EAAG,MAAA;AAAA,IAAuB,IAAA,CAAK,CAAA;EACnC,EAAA,EAAI,CAAA;EAAG,MAAA,EAAQ,aAAA,CAAc,CAAA;AAAA,IAAO,IAAA,CAAK,CAAA;AAAA,KAErC,eAAA;EACV,EAAA,EAAI,CAAA;EACJ,OAAA;EACA,KAAA;EACA,MAAA,GAAS,MAAA,mBAAyB,eAAA;EAClC,cAAA;AAAA,KACG,QAAA,CAAS,CAAA;EAAoB,MAAA,EAAQ,aAAA,CAAc,CAAA;AAAA;EAAS,MAAA;AAAA;AH2CpC;AAAA,UGrCZ,UAAA;AAAA,KAEL,gBAAA,GAAmB,UAAA;EAAqB,MAAA;AAAA,IAAoB,CAAA,GAAI,MAAM;AAAA,UAEjE,gBAAA;EACf,OAAA,GAAU,OAAO;AAAA;AAAA,KAGP,SAAA,GACV,YAAA,CAAa,gBAAA,+BAA+C,YAAA,CAAa,gBAAA;AAAA,KAE/D,gBAAA,GAAmB,OAAO,CAAC,SAAA;AAAA,KAC3B,eAAA,GAAkB,OAAO,CAAC,SAAA;;KAK1B,YAAA,eAA2B,EAAA,kBAAoB,EAAA,QAAU,EAAA,kBAAoB,EAAA;AAAA,KAE7E,YAAA,gBAA4B,CAAA,6BACpC,MAAA,CAAO,KAAA,YAAiB,QAAA,GACxB,QAAA;AAAA,KACQ,aAAA,MAAmB,CAAA,uCAC3B,YAAA,CAAa,EAAA,EAAI,aAAA,CAAc,IAAA,KAC/B,YAAA,CAAa,CAAA;AAAA,KAEL,YAAA,oBACE,CAAA,GAAI,CAAA,kBACZ,CAAA,yBAEE,CAAA,CAAE,CAAA,UAAW,IAAA,OACP,CAAA,KACJ,YAAA,CAAa,CAAA,EAAG,YAAA,CAAa,CAAA,CAAE,CAAA,oBAEjC,CAAA;;;KClGH,kBAAA,WAA6B,OAAA,CAAM,WAAA,IAAe,IAAA,CACrD,OAAA,CAAM,cAAA,CAAe,CAAA;AAAA,KAIX,aAAA,WACA,OAAA,CAAM,WAAA,YACN,OAAA,CAAM,WAAA,GAAc,CAAA,IAC5B,kBAAA,CAAmB,CAAA;EACrB,KAAA;EACA,cAAA;EACA,GAAA,GAAM,OAAA,CAAM,GAAA,CAAI,OAAA,CAAM,YAAA,CAAa,CAAA;AAAA;AAAA,UAOpB,aAAA,WAAwB,OAAA,CAAM,WAAA,YAAuB,OAAA,CAAM,WAAA,GAAc,CAAA;EAAA,WAC7E,eAAA,EACT,KAAA,EAAO,aAAA,CAAc,CAAA,EAAG,CAAA;IAAO,EAAA,EAAI,CAAA;IAAG,MAAA;EAAA,IACrC,OAAA,CAAM,SAAA;EAAA,WACE,gBAAA,EACT,KAAA,EAAO,aAAA,CAAc,CAAA,EAAG,CAAA;IAAO,EAAA,EAAI,CAAA;IAAG,MAAA,EAAQ,aAAA,CAAc,CAAA;EAAA,IAC3D,OAAA,CAAM,SAAA;AAAA;AAAA,cAME,iBAAA,aAA+B,OAAA,CAAM,WAAA,YAAuB,OAAA,CAAM,WAAA,GAAc,CAAA,EAAC,CAAA,EACzF,CAAA,EAAC,SAAA,GACQ,OAAA,CAAQ,kBAAA,CAAmB,CAAA;EAAQ,EAAA,GAAK,CAAA;AAAA,MAwB9C,aAAA,CAAc,CAAA,EAAG,CAAA;;;cChEZ,QAAA,aAAsB,SAAA,EAAS,KAAA,EAAS,eAAA,CAAgB,CAAA;;;UCIpD,iBAAA;EACf,OAAA;EACA,SAAA,EAAW,SAAA;EACX,KAAA,GAAQ,GAAG;AAAA;AAAA,cAGA,WAAA;EAAA,SACF,OAAA,EAAS,OAAA;EAElB,SAAA,GAAY,MAAA;EAEZ,QAAA,EAAW,QAAA;EACX,WAAA,EAAa,KAAA;EAAA,IAET,MAAA,IAAU,eAAA;EAAA,IAIV,KAAA,IAAS,MAAA;EAAA,IAIT,UAAA,IAAc,MAAA;EAAA,IAgBd,cAAA;EAIJ,WAAA,CAAY,MAAA,GAAS,gBAAA;EAerB,UAAA,CAAW,SAAA,EAAW,MAAA;EAStB,aAAA,WAAwB,SAAA,EAAW,IAAA,EAAM,CAAA,EAAG,KAAA;EAa5C,QAAA,WAAmB,SAAA,EAAW,OAAA,EAAS,eAAA,CAAgB,CAAA;EASvD,SAAA,WAAoB,SAAA,EAAW,OAAA,EAAS,eAAA,CAAgB,CAAA;EAyBxD,aAAA,CAAc,KAAA,UAAe,KAAA;EAM7B,gBAAA,CAAiB,KAAA;EAUX,WAAA,CAAY,QAAA,EAAU,QAAA,GAAW,OAAA;AAAA;;;cCnI5B,WAAA,EAAa,SAAsC;AAAA,cAMnD,YAAA,EAAc,KAAA,CAAM,EAAA;EAAK,KAAA,EAAO,KAAA;EAAO,UAAA,GAAa,SAAA;AAAA;AAAA,cAepD,aAAA,kBAAa,OAAA,CAAA,WAAA;AAAA,cACb,SAAA,QAAS,WAAkC;AAAA,UAEvC,WAAA;EACf,KAAA,EAAO,WAAW;AAAA;AAAA,cAGP,MAAA;EAAM;AAAA,GAAwB,WAAW,iCAAA,GAAA,CAAA,OAAA;;;;;UCvBrC,UAAA;EACf,QAAA;EACA,OAAA,EAAS,GAAA;EACT,MAAA,EAAQ,GAAA;EACR,OAAA,GAAU,MAAA;EACV,MAAA,GAAS,KAAA;EACT,MAAA,GAAS,SAAA;AAAA;AAAA,cAGE,SAAA,GAAS,UAAA,EAAgB,UAAA,KAAa,KAKlD;AAAA,cAEY,UAAA,GAAU,IAAA,UAAgB,QAAA,EAAY,MAAA,EAAM,UAAA,GAAe,UAAA,KAAa,KAAA;AAAA,cA+ExE,UAAA,mBAEA,MAAA,EAAM,MAAA,EAAU,CAAA,KAAI,CAAA;;;cC1GpB,QAAA,WAAmB,SAAA;EAAA,SACT,OAAA,EAAS,eAAA,CAAgB,CAAA;EAA9C,WAAA,CAAqB,OAAA,EAAS,eAAA,CAAgB,CAAA;AAAA;AAAA,cAGnC,QAAA,aAAsB,SAAA,EAAS,OAAA,EAAW,eAAA,CAAgB,CAAA,MAAK,QAAA,CAAS,CAAA;;;cCHxE,WAAA,GAAW,EAAA,UAAc,MAAA,GAAW,GAAG;AAAA,cASvC,WAAA,GAAW,IAAA,UAAgB,IAAA,IAAQ,SAM/C;AAAA,cAEY,MAAA,GAAM,IAAA,UAAgB,IAAA,IAAQ,IAI1C;AAAA,cAEY,UAAA,GAAU,IAAA,UAAgB,IAAA,IAAQ,UAI9C;AAAA,cAEY,MAAA,GAAM,IAAA,UAAgB,IAAA,IAAQ,IAE1C;AAAA,cAEY,eAAA,GAAe,IAAA,UAAgB,IAAA,IAAQ,aAEnD"}
1
+ {"version":3,"file":"router.d.mts","names":[],"sources":["../src/router/symbols.ts","../src/router/types.ts","../src/router/route.tsx","../src/router/outlet.tsx","../src/router/make-routes.tsx","../src/router/errors.ts","../src/router/components/error.tsx","../src/router/components/link.tsx","../src/router/components/navigate.tsx","../src/router/router.store.ts","../src/router/components/router.tsx","../src/router/redirect.ts","../src/router/util.ts"],"mappings":"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"}
package/dist/router.mjs CHANGED
@@ -1,9 +1,77 @@
1
1
  import { observer } from "mobx-react-lite";
2
2
  import React, { createContext, useCallback, useContext, useLayoutEffect } from "react";
3
3
  import { action, computed, makeAutoObservable, makeObservable, observable, runInAction } from "mobx";
4
- import { jsx } from "react/jsx-runtime";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
5
  import { createBrowserHistory } from "history";
6
6
 
7
+ //#region src/router/errors.ts
8
+ const defaultMessage = (type, path) => {
9
+ switch (type) {
10
+ case "NOT_FOUND": return path ? `No route matches '${path}'.` : "No matching route.";
11
+ case "GUARD": return "A route guard rejected the navigation.";
12
+ case "LOAD": return "A route loader or lazy component failed.";
13
+ case "RENDER": return "A route component failed to render.";
14
+ }
15
+ };
16
+ /**
17
+ * The single error type surfaced to `[ERROR]` components. `type`
18
+ * discriminates the failure source; when the router wraps an
19
+ * application-level error (thrown by a guard or loader), the original
20
+ * is preserved on the standard `cause` property.
21
+ *
22
+ * Guards and loaders may also throw `RouterError` directly — e.g.
23
+ * `throw new RouterError("NOT_FOUND")` from a loader when an entity
24
+ * doesn't exist — and it passes through unwrapped.
25
+ */
26
+ var RouterError = class extends Error {
27
+ type;
28
+ path;
29
+ /** @internal matched-prefix state captured when the matcher throws NOT_FOUND */
30
+ state;
31
+ /** @internal level index of the failing guard, for depth-aware bubbling */
32
+ depth;
33
+ constructor(type, options) {
34
+ super(options?.message ?? defaultMessage(type, options?.path), { cause: options?.cause });
35
+ this.name = "RouterError";
36
+ this.type = type;
37
+ this.path = options?.path;
38
+ }
39
+ };
40
+
41
+ //#endregion
42
+ //#region src/router/components/error.tsx
43
+ /**
44
+ * Rendered when an error occurs and no `[ERROR]` component is defined
45
+ * on the matched prefix. Deliberately minimal and dependency-free —
46
+ * define a root-level `[ERROR]` to replace it.
47
+ */
48
+ const DefaultErrorPage = ({ error }) => /* @__PURE__ */ jsxs("div", {
49
+ role: "alert",
50
+ children: [/* @__PURE__ */ jsx("h1", { children: error.type === "NOT_FOUND" ? "Page Not Found" : "Something Went Wrong" }), /* @__PURE__ */ jsx("p", { children: error.message })]
51
+ });
52
+ /**
53
+ * Catches render-time crashes in page and `[WRAPPER]` components and
54
+ * renders the nearest `[ERROR]` component with `type: "RENDER"`. Mounted
55
+ * inside the `[LAYOUT]` so the layout survives page crashes; crashes in
56
+ * the layout itself (or in the fallback) propagate out of `<Router>` by
57
+ * design — those are developer bugs that should stay loud.
58
+ */
59
+ var RouteErrorBoundary = class extends React.Component {
60
+ state = {};
61
+ static getDerivedStateFromError(cause) {
62
+ return { error: cause instanceof RouterError ? cause : new RouterError("RENDER", { cause }) };
63
+ }
64
+ render() {
65
+ if (!this.state.error) return this.props.children;
66
+ const Fallback = this.props.fallback;
67
+ return /* @__PURE__ */ jsx(Fallback, {
68
+ route: this.props.route,
69
+ error: this.state.error
70
+ });
71
+ }
72
+ };
73
+
74
+ //#endregion
7
75
  //#region src/router/symbols.ts
8
76
  const CONTEXT = Symbol.for("MOBX_ROUTER_CONTEXT");
9
77
  const LAYOUT = Symbol.for("MOBX_ROUTER_LAYOUT");
@@ -11,6 +79,7 @@ const WRAPPER = Symbol.for("MOBX_ROUTER_WRAPPER");
11
79
  const LOAD = Symbol.for("MOBX_ROUTER_LOAD");
12
80
  const GUARD = Symbol.for("MOBX_ROUTER_GUARD");
13
81
  const PAGE = Symbol.for("MOBX_ROUTER_PAGE");
82
+ const ERROR = Symbol.for("MOBX_ROUTER_ERROR");
14
83
  const REDIRECT = Symbol.for("MOBX_ROUTER_REDIRECT");
15
84
 
16
85
  //#endregion
@@ -18,7 +87,7 @@ const REDIRECT = Symbol.for("MOBX_ROUTER_REDIRECT");
18
87
  const resolvePath = (to, params) => {
19
88
  return to.replaceAll(/:[^/]*/g, (segment) => {
20
89
  const value = params?.[segment.slice(1)];
21
- if (!value) throw new Error(`Unable to resolve route '${to}. Paramater '${segment}' not specified.`);
90
+ if (!value) throw new Error(`Unable to resolve route '${to}'. Parameter '${segment}' not specified.`);
22
91
  return value;
23
92
  });
24
93
  };
@@ -58,17 +127,23 @@ const RouterOutlet = ({ route, components }) => {
58
127
  const routerContext = createContext(null);
59
128
  const useRouter = () => useContext(routerContext);
60
129
  const Router = observer(({ store }) => {
61
- if (!store.activeRoute) return null;
62
- const Layout = store.activeRoute.layout ?? PassThrough;
63
- const components = store.activeRoute.outlets.map((o) => o.Component);
130
+ const route = store.activeRoute;
131
+ if (!route) return null;
132
+ const Layout = route.layout ?? PassThrough;
133
+ const outlet = /* @__PURE__ */ jsx(RouterOutlet, {
134
+ route,
135
+ components: route.outlets.map((o) => o.Component)
136
+ });
137
+ const fallback = route.levels.at(-1)?.errorComponent ?? DefaultErrorPage;
64
138
  return /* @__PURE__ */ jsx(routerContext.Provider, {
65
139
  value: store,
66
140
  children: /* @__PURE__ */ jsx(Layout, {
67
- route: store.activeRoute,
68
- children: /* @__PURE__ */ jsx(RouterOutlet, {
69
- route: store.activeRoute,
70
- components
71
- })
141
+ route,
142
+ children: route.error ? outlet : /* @__PURE__ */ jsx(RouteErrorBoundary, {
143
+ route,
144
+ fallback,
145
+ children: outlet
146
+ }, store.location.key)
72
147
  })
73
148
  });
74
149
  });
@@ -90,7 +165,7 @@ const makeLinkComponent = (C, baseProps) => {
90
165
  router.navigate({
91
166
  to,
92
167
  preserveSearch,
93
- ...params
168
+ params
94
169
  });
95
170
  }, [
96
171
  router,
@@ -112,6 +187,16 @@ const Navigate = (props) => {
112
187
  return null;
113
188
  };
114
189
 
190
+ //#endregion
191
+ //#region src/router/redirect.ts
192
+ var Redirect = class {
193
+ options;
194
+ constructor(options) {
195
+ this.options = options;
196
+ }
197
+ };
198
+ const redirect = (options) => new Redirect(options);
199
+
115
200
  //#endregion
116
201
  //#region src/router/outlet.tsx
117
202
  const DefaultOutlet = ({ children }) => children;
@@ -121,11 +206,20 @@ var Outlet = class {
121
206
  state = "preloading";
122
207
  promise;
123
208
  data;
209
+ error;
124
210
  component;
125
211
  get Component() {
126
212
  switch (this.state) {
127
213
  case "loading": return LoadingPlaceholder;
128
214
  case "ready": return this.component ?? DefaultOutlet;
215
+ case "error": {
216
+ const ErrorComponent = this.config.errorComponent ?? DefaultErrorPage;
217
+ const error = this.error ?? new RouterError("LOAD");
218
+ return (props) => /* @__PURE__ */ jsx(ErrorComponent, {
219
+ ...props,
220
+ error
221
+ });
222
+ }
129
223
  default: return;
130
224
  }
131
225
  }
@@ -135,6 +229,7 @@ var Outlet = class {
135
229
  makeAutoObservable(this, {
136
230
  promise: observable.ref,
137
231
  data: observable.ref,
232
+ error: observable.ref,
138
233
  component: false,
139
234
  config: false
140
235
  });
@@ -156,15 +251,20 @@ var Outlet = class {
156
251
  this.setState("ready");
157
252
  }, 300);
158
253
  else this.setState("ready");
159
- }).catch(() => {
254
+ }).catch((e) => {
160
255
  clearTimeout(preloadingTimer);
161
256
  this.setState("error");
257
+ if (e instanceof Redirect) throw e;
258
+ this.setError(e instanceof RouterError ? e : new RouterError("LOAD", { cause: e }));
162
259
  });
163
260
  await this.promise;
164
261
  }
165
262
  setData(data) {
166
263
  this.data = data;
167
264
  }
265
+ setError(error) {
266
+ this.error = error;
267
+ }
168
268
  setState(state) {
169
269
  this.state = state;
170
270
  }
@@ -182,16 +282,6 @@ var Outlet = class {
182
282
  }
183
283
  };
184
284
 
185
- //#endregion
186
- //#region src/router/redirect.ts
187
- var Redirect = class {
188
- options;
189
- constructor(options) {
190
- this.options = options;
191
- }
192
- };
193
- const redirect = (options) => new Redirect(options);
194
-
195
285
  //#endregion
196
286
  //#region src/router/route.tsx
197
287
  var Route = class {
@@ -201,20 +291,36 @@ var Route = class {
201
291
  context;
202
292
  params;
203
293
  layout;
294
+ /** set on synthetic error routes; the error being rendered */
295
+ error;
296
+ /** @internal */
297
+ guardEntries;
298
+ /** @internal */
299
+ levels;
204
300
  get data() {
205
301
  return Object.assign({}, ...this.outlets.map((o) => o.data));
206
302
  }
207
303
  constructor(def) {
208
304
  this.path = def.path;
209
- this.guards = def.guards;
305
+ this.guardEntries = def.guards;
306
+ this.guards = def.guards.map((entry) => entry.guard);
307
+ this.levels = def.levels;
210
308
  this.context = def.context ?? {};
211
309
  this.outlets = def.outlets;
212
310
  this.params = def.params;
213
311
  this.layout = def.layout;
312
+ this.error = def.error;
214
313
  makeObservable(this, { data: computed });
215
314
  }
216
315
  async guard() {
217
- for (const guard of this.guards) await guard(this);
316
+ for (const { guard, depth } of this.guardEntries) try {
317
+ await guard(this);
318
+ } catch (e) {
319
+ if (e instanceof Redirect) throw e;
320
+ const error = e instanceof RouterError ? e : new RouterError("GUARD", { cause: e });
321
+ error.depth ??= depth;
322
+ throw error;
323
+ }
218
324
  }
219
325
  async load() {
220
326
  await Promise.all(this.outlets.map((outlet) => outlet.load(this)));
@@ -228,59 +334,126 @@ const pathToSegments = (path) => {
228
334
  };
229
335
  const makeRoute = (matchState) => {
230
336
  const outlets = matchState.outlets.filter((o) => o !== void 0);
231
- const guards = matchState.guards.filter((g) => g !== void 0);
232
337
  return new Route({
233
338
  ...matchState,
234
339
  outlets,
235
- guards,
236
340
  path: matchState.segments.join("/")
237
341
  });
238
342
  };
343
+ /**
344
+ * Builds the synthetic route rendered when navigation fails. Bubbles
345
+ * from the failing level (`error.depth`, defaulting to the deepest
346
+ * matched level) to the nearest `[ERROR]` component, preserving the
347
+ * `[LAYOUT]` and `[WRAPPER]`s accumulated up to that level. Ancestor
348
+ * `[LOAD]` loaders are intentionally not run — error routes never
349
+ * fetch data.
350
+ */
351
+ const makeErrorRoute = (error, pathname, source) => {
352
+ const levels = error.state?.levels ?? source?.levels ?? [];
353
+ const depth = Math.min(error.depth ?? levels.length - 1, levels.length - 1);
354
+ const level = depth >= 0 ? levels[depth] : void 0;
355
+ const ErrorComponent = level?.errorComponent ?? DefaultErrorPage;
356
+ const outlets = levels.slice(0, depth + 1).flatMap((l) => l.wrapper ? [new Outlet({ component: l.wrapper })] : []);
357
+ outlets.push(new Outlet({ component: (props) => /* @__PURE__ */ jsx(ErrorComponent, {
358
+ ...props,
359
+ error
360
+ }) }));
361
+ return new Route({
362
+ path: pathname.replace(/^\/+/, ""),
363
+ outlets,
364
+ guards: [],
365
+ levels: [],
366
+ params: error.state?.params ?? source?.params ?? {},
367
+ context: error.state?.context ?? source?.context ?? {},
368
+ layout: level?.layout,
369
+ error
370
+ });
371
+ };
372
+ const notFound = (state, attemptedSegments) => {
373
+ const error = new RouterError("NOT_FOUND", { path: `/${attemptedSegments.filter((s) => s !== "").join("/")}` });
374
+ error.state = state;
375
+ return error;
376
+ };
239
377
  const matchRoute = (path, routeDef, matchState) => {
378
+ const depth = matchState?.levels.length ?? 0;
379
+ const layout = routeDef[LAYOUT] ?? matchState?.layout;
380
+ const errorComponent = routeDef[ERROR] ?? matchState?.errorComponent;
240
381
  const state = {
241
382
  segments: [],
242
383
  params: {},
243
384
  ...matchState,
244
- layout: routeDef[LAYOUT] ?? matchState?.layout,
385
+ layout,
386
+ errorComponent,
245
387
  context: {
246
388
  ...matchState?.context,
247
389
  ...routeDef[CONTEXT]
248
390
  },
249
- guards: [...matchState?.guards ?? [], routeDef[GUARD]],
391
+ guards: [...matchState?.guards ?? [], ...routeDef[GUARD] ? [{
392
+ guard: routeDef[GUARD],
393
+ depth
394
+ }] : []],
250
395
  outlets: [
251
396
  ...matchState?.outlets ?? [],
252
- routeDef[WRAPPER] ? new Outlet({ component: routeDef[WRAPPER] }) : void 0,
253
- routeDef[LOAD] ? new Outlet({ loader: routeDef[LOAD] }) : void 0
254
- ]
397
+ routeDef[WRAPPER] ? new Outlet({
398
+ component: routeDef[WRAPPER],
399
+ errorComponent
400
+ }) : void 0,
401
+ routeDef[LOAD] ? new Outlet({
402
+ loader: routeDef[LOAD],
403
+ errorComponent
404
+ }) : void 0
405
+ ],
406
+ levels: [...matchState?.levels ?? [], {
407
+ wrapper: routeDef[WRAPPER],
408
+ layout,
409
+ errorComponent
410
+ }]
255
411
  };
256
412
  const [segment, ...remainingSegments] = pathToSegments(path);
257
413
  const remainingPath = remainingSegments.join("/");
258
414
  let defAtSegment = routeDef[segment || "index"];
259
415
  if (!defAtSegment) {
260
- const matchedSegment = Object.keys(routeDef).find((segment) => segment.startsWith("$"));
416
+ const matchedSegment = Object.keys(routeDef).find((segment) => segment.startsWith("$") || segment.startsWith(":"));
261
417
  if (matchedSegment) {
262
418
  defAtSegment = routeDef[matchedSegment];
263
419
  state.params[matchedSegment.slice(1)] = segment;
264
420
  }
265
421
  }
266
- if (!defAtSegment) throw new Error("Not Found.");
422
+ if (!defAtSegment) throw notFound(state, [
423
+ ...state.segments,
424
+ segment ?? "",
425
+ ...remainingSegments
426
+ ]);
267
427
  state.segments.push(segment ?? "index");
268
428
  if (isLeaf(defAtSegment)) {
269
- if (remainingPath) throw new Error("Not Found.");
429
+ if (remainingPath) throw notFound(state, [...state.segments, ...remainingSegments]);
270
430
  if (isRedirect(defAtSegment)) throw new Redirect(typeof defAtSegment[REDIRECT] === "string" ? { to: defAtSegment[REDIRECT] } : defAtSegment[REDIRECT]);
271
431
  if (isComponent(defAtSegment) || isLazyComponent(defAtSegment)) {
272
- state.outlets.push(new Outlet({ component: defAtSegment }));
432
+ state.outlets.push(new Outlet({
433
+ component: defAtSegment,
434
+ errorComponent
435
+ }));
273
436
  return makeRoute(state);
274
437
  }
275
438
  }
276
439
  if (isPage(defAtSegment)) {
277
440
  state.layout = defAtSegment[LAYOUT] ?? state.layout;
441
+ state.errorComponent = defAtSegment[ERROR] ?? state.errorComponent;
278
442
  Object.assign(state.context, defAtSegment[CONTEXT]);
279
- state.guards.push(defAtSegment[GUARD]);
443
+ if (defAtSegment[GUARD]) state.guards.push({
444
+ guard: defAtSegment[GUARD],
445
+ depth
446
+ });
280
447
  state.outlets.push(new Outlet({
281
448
  component: defAtSegment[PAGE],
282
- loader: defAtSegment[LOAD]
449
+ loader: defAtSegment[LOAD],
450
+ errorComponent: state.errorComponent
283
451
  }));
452
+ state.levels[state.levels.length - 1] = {
453
+ ...state.levels[state.levels.length - 1],
454
+ layout: state.layout,
455
+ errorComponent: state.errorComponent
456
+ };
284
457
  return makeRoute(state);
285
458
  }
286
459
  return matchRoute(remainingPath, defAtSegment, state);
@@ -303,14 +476,7 @@ var RouterStore = class {
303
476
  return Object.fromEntries(this.search);
304
477
  }
305
478
  get pathParams() {
306
- const params = {};
307
- const paramSegments = this.activeSegments.filter((segment) => segment.startsWith("$"));
308
- const pathValues = this.location.pathname.split("/").slice(1);
309
- paramSegments.forEach((segment, index) => {
310
- const value = pathValues[index + 1];
311
- if (value) params[segment] = value;
312
- });
313
- return params;
479
+ return { ...this.activeRoute?.params };
314
480
  }
315
481
  get activeSegments() {
316
482
  return this.activeRoute?.path.split("/") ?? [];
@@ -335,7 +501,7 @@ var RouterStore = class {
335
501
  }
336
502
  doesPathMatch(path, exact) {
337
503
  const segments = path.slice(1).split("/");
338
- return segments.every((segment, i) => segment === this.activeSegments[i] || segment.startsWith("$")) && this.activeSegments.length >= segments.length && (!exact || segments.length === this.activeSegments.length);
504
+ return segments.every((segment, i) => segment === this.activeSegments[i] || segment.startsWith(":")) && this.activeSegments.length >= segments.length && (!exact || segments.length === this.activeSegments.length);
339
505
  }
340
506
  navigate(options) {
341
507
  if (!document.startViewTransition) this._navigate(options);
@@ -378,8 +544,9 @@ var RouterStore = class {
378
544
  return;
379
545
  }
380
546
  this.location = location;
547
+ let matchedRoute;
381
548
  try {
382
- const matchedRoute = matchRoute(location.pathname, this.routesDef);
549
+ matchedRoute = matchRoute(location.pathname, this.routesDef);
383
550
  await matchedRoute.guard();
384
551
  if (this.location !== location) return;
385
552
  runInAction(() => {
@@ -391,11 +558,21 @@ var RouterStore = class {
391
558
  this.navigate(e.options);
392
559
  return;
393
560
  }
394
- throw e;
561
+ if (this.location !== location) return;
562
+ const error = e instanceof RouterError ? e : new RouterError("RENDER", {
563
+ cause: e,
564
+ path: location.pathname
565
+ });
566
+ console.error(error);
567
+ const errorRoute = makeErrorRoute(error, location.pathname, matchedRoute);
568
+ runInAction(() => {
569
+ this.activeRoute = errorRoute;
570
+ });
571
+ await errorRoute.load();
395
572
  }
396
573
  }
397
574
  };
398
575
 
399
576
  //#endregion
400
- export { CONTEXT, DefaultOutlet, GUARD, LAYOUT, LOAD, Navigate, Outlet, PAGE, PassThrough, REDIRECT, Redirect, Route, Router, RouterOutlet, RouterStore, WRAPPER, isComponent, isLazyComponent, isLeaf, isPage, isRedirect, makeLinkComponent, makeRoute, makeRoutes, matchRoute, redirect, resolvePath, routerContext, useRouter };
577
+ export { CONTEXT, DefaultErrorPage, DefaultOutlet, ERROR, GUARD, LAYOUT, LOAD, Navigate, Outlet, PAGE, PassThrough, REDIRECT, Redirect, Route, RouteErrorBoundary, Router, RouterError, RouterOutlet, RouterStore, WRAPPER, isComponent, isLazyComponent, isLeaf, isPage, isRedirect, makeErrorRoute, makeLinkComponent, makeRoute, makeRoutes, matchRoute, redirect, resolvePath, routerContext, useRouter };
401
578
  //# sourceMappingURL=router.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"router.mjs","names":[],"sources":["../src/router/symbols.ts","../src/router/util.ts","../src/router/components/router.tsx","../src/router/components/link.tsx","../src/router/components/navigate.tsx","../src/router/outlet.tsx","../src/router/redirect.ts","../src/router/route.tsx","../src/router/make-routes.tsx","../src/router/router.store.ts"],"sourcesContent":["export const CONTEXT: unique symbol = Symbol.for(\"MOBX_ROUTER_CONTEXT\");\nexport const LAYOUT: unique symbol = Symbol.for(\"MOBX_ROUTER_LAYOUT\");\nexport const WRAPPER: unique symbol = Symbol.for(\"MOBX_ROUTER_WRAPPER\");\nexport const LOAD: unique symbol = Symbol.for(\"MOBX_ROUTER_LOAD\");\nexport const GUARD: unique symbol = Symbol.for(\"MOBX_ROUTER_GUARD\");\nexport const PAGE: unique symbol = Symbol.for(\"MOBX_ROUTER_PAGE\");\nexport const REDIRECT: unique symbol = Symbol.for(\"MOBX_ROUTER_REDIRECT\");\n","import { PAGE, REDIRECT } from \"./symbols\";\nimport type { Component, LazyComponent, Leaf, Obj, Page, Redirector } from \"./types\";\n\nexport const resolvePath = (to: string, params?: Obj): string => {\n return to.replaceAll(/:[^/]*/g, (segment) => {\n const value = params?.[segment.slice(1)];\n if (!value)\n throw new Error(`Unable to resolve route '${to}. Paramater '${segment}' not specified.`);\n return value;\n });\n};\n\nexport const isComponent = (data: any): data is Component => {\n if (!data) return false;\n return (\n typeof data === \"function\" ||\n (typeof data === \"object\" && data[\"$$typeof\"] === Symbol.for(\"react.memo\"))\n );\n};\n\nexport const isPage = (data: any): data is Page => {\n if (typeof data !== \"object\") return false;\n const symbols = Object.getOwnPropertySymbols(data);\n return symbols.includes(PAGE);\n};\n\nexport const isRedirect = (data: any): data is Redirector => {\n if (typeof data !== \"object\") return false;\n const symbols = Object.getOwnPropertySymbols(data);\n return symbols.includes(REDIRECT);\n};\n\nexport const isLeaf = (data: any): data is Leaf => {\n return isComponent(data) || isPage(data) || isRedirect(data);\n};\n\nexport const isLazyComponent = (data: any): data is LazyComponent => {\n return typeof data === \"function\" && data.toString().startsWith(\"() => import(\");\n};\n","import { observer } from \"mobx-react-lite\";\nimport { createContext, useContext } from \"react\";\nimport type { Route } from \"../route\";\nimport type { RouterStore } from \"../router.store\";\nimport type { Component } from \"../types\";\n\nexport const PassThrough: Component = ({ children }) => children;\n\n// Plain (non-observer) renderer. State observation lives one level up\n// in `Router`, so the page component renders as a child of a plain\n// FunctionComponent — no memo wrapper in the parent chain to interact\n// with React Refresh's family-update propagation.\nexport const RouterOutlet: React.FC<{ route: Route; components: (Component | undefined)[] }> = ({\n route,\n components,\n}) => {\n const [C, ...remaining] = components;\n\n if (!C) return null;\n\n return (\n <C route={route}>\n {remaining.length > 0 && <RouterOutlet route={route} components={remaining} />}\n </C>\n );\n};\n\nexport const routerContext = createContext<RouterStore>(null as any);\nexport const useRouter = () => useContext(routerContext);\n\nexport interface RouterProps {\n store: RouterStore;\n}\n\nexport const Router = observer(({ store }: RouterProps) => {\n if (!store.activeRoute) {\n return null;\n }\n\n const Layout = store.activeRoute.layout ?? PassThrough;\n const components = store.activeRoute.outlets.map((o) => o.Component);\n\n return (\n <routerContext.Provider value={store}>\n <Layout route={store.activeRoute}>\n <RouterOutlet route={store.activeRoute} components={components} />\n </Layout>\n </routerContext.Provider>\n );\n});\n","import { observer } from \"mobx-react-lite\";\nimport React, { useCallback } from \"react\";\nimport type {\n DynamicRoutePath,\n ExtractParams,\n NavigateOptions,\n RoutePath,\n StaticRoutePath,\n} from \"../types\";\nimport { resolvePath } from \"../util\";\nimport { useRouter } from \"./router\";\n\ntype LinkComponentProps<C extends React.ElementType> = Omit<\n React.ComponentProps<C>,\n \"ref\" | \"exact\" | \"to\" | \"params\" | \"onClick\" | \"asChild\"\n>;\n\nexport type LinkPropsBase<\n C extends React.ElementType,\n I extends React.ElementType = C,\n> = LinkComponentProps<C> & {\n exact?: boolean;\n preserveSearch?: boolean;\n ref?: React.Ref<React.ComponentRef<I>>;\n};\n\n// function overloading is much faster than leveraging conditional types\n// but once the typescript go compiler is released and performance is no\n// longer an issue, it might make sense to simplify this a bit so it can\n// be more easily consumed by users\nexport interface LinkComponent<C extends React.ElementType, I extends React.ElementType = C> {\n <P extends StaticRoutePath>(\n props: LinkPropsBase<C, I> & { to: P; params?: undefined },\n ): React.ReactNode;\n <P extends DynamicRoutePath>(\n props: LinkPropsBase<C, I> & { to: P; params: ExtractParams<P> },\n ): React.ReactNode;\n}\n\n// final thing to do is make sure refs still work in React 19\n\n// this smooths over some of the awkwardness when extending this component\nexport const makeLinkComponent = <C extends React.ElementType, I extends React.ElementType = C>(\n C: C,\n baseProps?: Partial<LinkComponentProps<C>> & { as?: I },\n) => {\n return observer(({ to, params, exact, preserveSearch, children, ...props }: any) => {\n const router = useRouter();\n const mergedProps = { ...baseProps, ...props };\n\n if (props.role !== \"link\") {\n mergedProps.href = resolvePath(to, params);\n }\n\n if (router.doesPathMatch(to, exact)) {\n mergedProps[\"aria-current\"] = \"page\";\n }\n\n mergedProps.onClick = useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n event.preventDefault();\n if (props.disabled) return;\n router.navigate({ to, preserveSearch, ...(params as any) } as NavigateOptions<RoutePath>);\n },\n [router, params, to, props.disabled],\n );\n\n return React.createElement(C, mergedProps, children);\n }) as LinkComponent<C, I>;\n};\n\n//export const Link = makeLinkComponent('a');\n","import { useLayoutEffect } from \"react\";\nimport type { NavigateOptions, RoutePath } from \"../types\";\nimport { useRouter } from \"./router\";\n\nexport const Navigate = <P extends RoutePath>(props: NavigateOptions<P>) => {\n const router = useRouter();\n\n useLayoutEffect(() => {\n router.navigate(props);\n }, [router, props]);\n\n return null;\n};\n","import { makeAutoObservable, observable } from \"mobx\";\nimport type { Route } from \"./route\";\nimport type { Component, LazyComponent, Loader } from \"./types\";\nimport { isLazyComponent } from \"./util\";\n\nexport interface OutletConfig {\n component?: Component | LazyComponent;\n loader?: Loader;\n}\n\nexport type RouteSegmentState = \"preloading\" | \"loading\" | \"error\" | \"ready\";\n\nexport const DefaultOutlet: Component = ({ children }) => children;\n\nconst LoadingPlaceholder: Component = () => <p>Loading...</p>;\n\nexport class Outlet {\n state: RouteSegmentState = \"preloading\";\n promise: Promise<unknown> | undefined;\n data: unknown;\n\n // Plain (non-observable) reference. The page component must reach\n // React unmediated by MobX — once MobX deep-observes the holder,\n // React Refresh can no longer swap the page identity via family\n // lookup on the original function. This mirrors how Route holds\n // `layout` as a plain field under makeObservable.\n component: Component | undefined;\n\n get Component(): Component | undefined {\n switch (this.state) {\n case \"loading\":\n return LoadingPlaceholder;\n case \"ready\":\n return this.component ?? DefaultOutlet;\n default:\n return undefined;\n }\n }\n\n constructor(readonly config: OutletConfig) {\n if (!isLazyComponent(config.component)) {\n this.component = config.component;\n }\n\n makeAutoObservable<Outlet, \"component\" | \"config\">(this, {\n promise: observable.ref,\n data: observable.ref,\n component: false,\n config: false,\n });\n }\n\n async load(route: Route): Promise<void> {\n const promises: Promise<void>[] = [];\n\n if (isLazyComponent(this.config.component) && !this.component) {\n promises.push(this.loadComponent());\n }\n\n if (this.config.loader) {\n promises.push(this.loadData(route));\n }\n\n if (!promises.length) {\n this.setState(\"ready\");\n return;\n }\n\n // wait to transition to loading to avoid\n // screen flashes when the loader function\n // executes quickly\n const preloadingTimer = setTimeout(() => {\n if (this.state === \"preloading\") {\n this.setState(\"loading\");\n }\n }, 300);\n\n this.promise = Promise.all(promises)\n .then(() => {\n clearTimeout(preloadingTimer);\n if (this.state === \"loading\") {\n // if we had to transition to regular loading because\n // the loader was taking too long, force an additional\n // timeout to prevent a loading flash\n setTimeout(() => {\n this.setState(\"ready\");\n }, 300);\n } else {\n this.setState(\"ready\");\n }\n })\n .catch(() => {\n clearTimeout(preloadingTimer);\n // TODO: check for type of error\n // handle access denied and redirects\n this.setState(\"error\");\n });\n\n await this.promise;\n }\n\n setData(data: unknown) {\n this.data = data;\n }\n\n setState(state: RouteSegmentState) {\n this.state = state;\n }\n\n private async loadData(route: Route): Promise<void> {\n await this.config.loader?.(route).then((data) => this.setData(data));\n }\n\n private async loadComponent(): Promise<void> {\n if (!isLazyComponent(this.config.component)) return;\n const module = await this.config.component();\n for (const exportName in module) {\n if (exportName === \"default\" || exportName.endsWith(\"Page\")) {\n this.component = module[exportName];\n return;\n }\n }\n throw new Error(\n \"Lazy route component module did not export `default` or a `*Page` named export\",\n );\n }\n}\n","import type { NavigateOptions, RoutePath } from \"./types\";\n\nexport class Redirect<P extends RoutePath> {\n constructor(readonly options: NavigateOptions<P>) {}\n}\n\nexport const redirect = <P extends RoutePath>(options: NavigateOptions<P>): Redirect<P> =>\n new Redirect(options);\n","import { computed, makeObservable } from \"mobx\";\nimport type { Outlet } from \"./outlet\";\nimport type { Component, Guard, Obj } from \"./types\";\n\nexport interface RouteConfig {\n path: string;\n outlets: Outlet[];\n guards: Guard[];\n context?: Obj;\n layout?: Component;\n params: Obj;\n}\n\nexport class Route {\n readonly path: string;\n readonly outlets: Outlet[];\n readonly guards: Guard[];\n readonly context: Obj;\n readonly params: Obj;\n readonly layout?: Component;\n\n get data(): Obj {\n return Object.assign({}, ...this.outlets.map((o) => o.data));\n }\n\n constructor(def: RouteConfig) {\n this.path = def.path;\n this.guards = def.guards;\n this.context = def.context ?? {};\n this.outlets = def.outlets;\n this.params = def.params;\n this.layout = def.layout;\n\n makeObservable(this, {\n data: computed,\n });\n }\n\n async guard(): Promise<void> {\n for (const guard of this.guards) {\n await guard(this);\n }\n }\n\n async load(): Promise<void> {\n await Promise.all(this.outlets.map((outlet) => outlet.load(this)));\n }\n}\n","import { Outlet } from \"./outlet\";\nimport { Redirect } from \"./redirect\";\nimport { Route } from \"./route\";\nimport { CONTEXT, GUARD, LAYOUT, LOAD, PAGE, REDIRECT, WRAPPER } from \"./symbols\";\nimport type { Component, Guard, Obj, Routes } from \"./types\";\nimport { isComponent, isLazyComponent, isLeaf, isPage, isRedirect } from \"./util\";\n\nconst pathToSegments = (path: string): string[] => {\n return path.replace(/^\\/+|\\/+$/g, \"\").split(\"/\");\n};\n\nexport interface MatchState {\n segments: string[];\n context: Obj;\n params: Obj;\n outlets: (Outlet | undefined)[];\n guards: (Guard | undefined)[];\n layout?: Component;\n}\n\nexport const makeRoute = (matchState: MatchState): Route => {\n const outlets = matchState.outlets.filter((o) => o !== undefined);\n const guards = matchState.guards.filter((g) => g !== undefined);\n\n return new Route({ ...matchState, outlets, guards, path: matchState.segments.join(\"/\") });\n};\n\nexport const matchRoute = (path: string, routeDef: Routes, matchState?: MatchState): Route => {\n const state: MatchState = {\n segments: [],\n params: {},\n ...matchState,\n layout: routeDef[LAYOUT] ?? matchState?.layout,\n context: { ...matchState?.context, ...routeDef[CONTEXT] },\n guards: [...(matchState?.guards ?? []), routeDef[GUARD]],\n outlets: [\n ...(matchState?.outlets ?? []),\n routeDef[WRAPPER] ? new Outlet({ component: routeDef[WRAPPER] }) : undefined,\n routeDef[LOAD] ? new Outlet({ loader: routeDef[LOAD] }) : undefined,\n ],\n };\n\n const [segment, ...remainingSegments] = pathToSegments(path);\n const remainingPath = remainingSegments.join(\"/\");\n\n let defAtSegment = routeDef[segment || \"index\"];\n\n if (!defAtSegment) {\n const matchedSegment = Object.keys(routeDef).find((segment) => segment.startsWith(\"$\"));\n if (matchedSegment) {\n defAtSegment = routeDef[matchedSegment];\n state.params[matchedSegment.slice(1)] = segment;\n }\n }\n\n if (!defAtSegment) {\n throw new Error(\"Not Found.\");\n }\n\n state.segments.push(segment ?? \"index\");\n\n if (isLeaf(defAtSegment)) {\n if (remainingPath) {\n throw new Error(\"Not Found.\");\n }\n\n if (isRedirect(defAtSegment)) {\n const redirect =\n typeof defAtSegment[REDIRECT] === \"string\"\n ? { to: defAtSegment[REDIRECT] }\n : defAtSegment[REDIRECT];\n throw new Redirect(redirect as any);\n }\n\n if (isComponent(defAtSegment) || isLazyComponent(defAtSegment)) {\n state.outlets.push(new Outlet({ component: defAtSegment }));\n return makeRoute(state);\n }\n }\n\n // at this point we have a nested route or a [Page] definition\n\n if (isPage(defAtSegment)) {\n state.layout = defAtSegment[LAYOUT] ?? state.layout;\n Object.assign(state.context, defAtSegment[CONTEXT]);\n state.guards.push(defAtSegment[GUARD]);\n state.outlets.push(\n new Outlet({\n component: defAtSegment[PAGE],\n loader: defAtSegment[LOAD],\n }),\n );\n\n return makeRoute(state);\n }\n\n // now we know we have a nested route\n return matchRoute(remainingPath, defAtSegment, state);\n};\n\n// TODO: ideally this could resolve to something less than R,\n// but specific enough to infer all paths as a literal union.\n// As it stands, there are certain things we can't access reliably\n// without the compiler complaining about circular references\n// try \"as const satisfies\" approach which would allow us to\n// exchange a less specific version of MobxRoutesRoot for this\nexport const makeRoutes =\n () =>\n <R extends Routes>(routes: R): R => {\n // todo: perform some validation here\n // - no forward slashes in keys\n // - at most one variable segment per level\n // - only lowercase letters (except variables)\n // - paths/variables cannot contain $ that aren't at the beginning\n // - path variables must be unique across a path\n\n return routes;\n };\n","import { createBrowserHistory, type History, type Location } from \"history\";\nimport { action, computed, makeObservable, observable, runInAction } from \"mobx\";\nimport { matchRoute } from \"./make-routes\";\nimport { Redirect } from \"./redirect\";\nimport type { Route } from \"./route\";\nimport type { Component, MobxRouterConfig, NavigateOptions, Obj, RoutePath, Routes } from \"./types\";\nimport { resolvePath } from \"./util\";\n\nexport interface MobxRenderSegment {\n segment: string;\n component: Component;\n props?: Obj;\n}\n\nexport class RouterStore {\n readonly history: History;\n\n routesDef?: Routes;\n\n location!: Location;\n activeRoute: Route | undefined;\n\n get search(): URLSearchParams {\n return new URLSearchParams(this.location?.search);\n }\n\n get query(): Record<string, string> {\n return Object.fromEntries(this.search);\n }\n\n get pathParams(): Record<string, string> {\n const params = {} as Record<string, string>;\n\n const paramSegments = this.activeSegments.filter((segment) => segment.startsWith(\"$\"));\n const pathValues = this.location.pathname.split(\"/\").slice(1);\n\n paramSegments.forEach((segment, index) => {\n const value = pathValues[index + 1];\n if (value) {\n params[segment] = value;\n }\n });\n\n return params as Record<string, string>;\n }\n\n get activeSegments(): string[] {\n return this.activeRoute?.path.split(\"/\") ?? [];\n }\n\n constructor(config?: MobxRouterConfig) {\n makeObservable(this, {\n location: observable.ref,\n activeRoute: observable.ref,\n\n search: computed,\n pathParams: computed,\n activeSegments: computed,\n\n setLocation: action,\n });\n\n this.history = config?.history ?? createBrowserHistory();\n }\n\n initialize(routesDef: Routes): void {\n this.routesDef = routesDef;\n this.history.listen((data) => {\n void this.setLocation(data.location);\n });\n\n void this.setLocation(this.history.location);\n }\n\n doesPathMatch<P extends RoutePath>(path: P, exact?: boolean): boolean {\n const segments = path.slice(1).split(\"/\");\n const segmentsMatch = segments.every(\n (segment, i) => segment === this.activeSegments[i] || segment.startsWith(\"$\"),\n );\n\n return (\n segmentsMatch &&\n this.activeSegments.length >= segments.length &&\n (!exact || segments.length === this.activeSegments.length)\n );\n }\n\n navigate<P extends RoutePath>(options: NavigateOptions<P>): void {\n if (!document.startViewTransition) {\n this._navigate(options);\n } else {\n const transition = document.startViewTransition(() => this._navigate(options));\n transition.ready.catch((e) => console.log(e, typeof e));\n }\n }\n\n _navigate<P extends RoutePath>(options: NavigateOptions<P>): void {\n const { to, replace, state, search = {}, preserveSearch, params } = options;\n\n const searchParams = search instanceof URLSearchParams ? search : new URLSearchParams(search);\n\n if (preserveSearch) {\n for (const [name, value] of this.search) {\n if (!searchParams.has(name)) {\n searchParams.set(name, value);\n }\n }\n }\n\n const location = {\n pathname: resolvePath(to, params),\n search: searchParams.size ? `?${searchParams.toString()}` : undefined,\n };\n\n if (replace) {\n this.history.replace(location, state);\n } else {\n this.history.push(location, state);\n }\n }\n\n setQueryParam(param: string, value: string): void {\n const params = new URLSearchParams(this.location.search);\n params.set(param, value);\n this.history.replace({ search: params.toString() });\n }\n\n removeQueryParam(param: string): string | undefined {\n const params = new URLSearchParams(this.location.search);\n const value = params.get(param) ?? undefined;\n if (value !== undefined) {\n params.delete(param);\n this.history.replace({ search: params.toString() });\n }\n return value;\n }\n\n async setLocation(location: Location): Promise<void> {\n if (!this.routesDef) return;\n\n // TODO: this should not be the responsibility of mobx-router\n // and should really be handled server-side\n if (location.pathname !== \"/\" && location.pathname.endsWith(\"/\")) {\n this.history.replace({ ...location, pathname: location.pathname.slice(0, -1) });\n return;\n }\n\n this.location = location;\n\n try {\n const matchedRoute = matchRoute(location.pathname, this.routesDef);\n\n await matchedRoute.guard();\n\n // navigating within a guard function\n // is essentially a redirect\n if (this.location !== location) {\n return;\n }\n\n runInAction(() => {\n this.activeRoute = matchedRoute;\n });\n\n await this.activeRoute?.load();\n } catch (e) {\n if (e instanceof Redirect) {\n this.navigate(e.options);\n return;\n }\n throw e;\n }\n }\n}\n"],"mappings":";;;;;;;AAAA,MAAa,UAAyB,OAAO,IAAI,qBAAqB;AACtE,MAAa,SAAwB,OAAO,IAAI,oBAAoB;AACpE,MAAa,UAAyB,OAAO,IAAI,qBAAqB;AACtE,MAAa,OAAsB,OAAO,IAAI,kBAAkB;AAChE,MAAa,QAAuB,OAAO,IAAI,mBAAmB;AAClE,MAAa,OAAsB,OAAO,IAAI,kBAAkB;AAChE,MAAa,WAA0B,OAAO,IAAI,sBAAsB;;;;ACHxE,MAAa,eAAe,IAAY,WAAyB;CAC/D,OAAO,GAAG,WAAW,YAAY,YAAY;EAC3C,MAAM,QAAQ,SAAS,QAAQ,MAAM,CAAC;EACtC,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,4BAA4B,GAAG,eAAe,QAAQ,iBAAiB;EACzF,OAAO;CACT,CAAC;AACH;AAEA,MAAa,eAAe,SAAiC;CAC3D,IAAI,CAAC,MAAM,OAAO;CAClB,OACE,OAAO,SAAS,cACf,OAAO,SAAS,YAAY,KAAK,gBAAgB,OAAO,IAAI,YAAY;AAE7E;AAEA,MAAa,UAAU,SAA4B;CACjD,IAAI,OAAO,SAAS,UAAU,OAAO;CAErC,OADgB,OAAO,sBAAsB,IAChC,CAAC,CAAC,SAAS,IAAI;AAC9B;AAEA,MAAa,cAAc,SAAkC;CAC3D,IAAI,OAAO,SAAS,UAAU,OAAO;CAErC,OADgB,OAAO,sBAAsB,IAChC,CAAC,CAAC,SAAS,QAAQ;AAClC;AAEA,MAAa,UAAU,SAA4B;CACjD,OAAO,YAAY,IAAI,KAAK,OAAO,IAAI,KAAK,WAAW,IAAI;AAC7D;AAEA,MAAa,mBAAmB,SAAqC;CACnE,OAAO,OAAO,SAAS,cAAc,KAAK,SAAS,CAAC,CAAC,WAAW,eAAe;AACjF;;;;AChCA,MAAa,eAA0B,EAAE,eAAe;AAMxD,MAAa,gBAAmF,EAC9F,OACA,iBACI;CACJ,MAAM,CAAC,GAAG,GAAG,aAAa;CAE1B,IAAI,CAAC,GAAG,OAAO;CAEf,OACE,oBAAC,GAAD;EAAU;YACP,UAAU,SAAS,KAAK,oBAAC,cAAD;GAAqB;GAAO,YAAY;EAAY;CAC5E;AAEP;AAEA,MAAa,gBAAgB,cAA2B,IAAW;AACnE,MAAa,kBAAkB,WAAW,aAAa;AAMvD,MAAa,SAAS,UAAU,EAAE,YAAyB;CACzD,IAAI,CAAC,MAAM,aACT,OAAO;CAGT,MAAM,SAAS,MAAM,YAAY,UAAU;CAC3C,MAAM,aAAa,MAAM,YAAY,QAAQ,KAAK,MAAM,EAAE,SAAS;CAEnE,OACE,oBAAC,cAAc,UAAf;EAAwB,OAAO;YAC7B,oBAAC,QAAD;GAAQ,OAAO,MAAM;aACnB,oBAAC,cAAD;IAAc,OAAO,MAAM;IAAyB;GAAa;EAC3D;CACc;AAE5B,CAAC;;;;ACPD,MAAa,qBACX,GACA,cACG;CACH,OAAO,UAAU,EAAE,IAAI,QAAQ,OAAO,gBAAgB,UAAU,GAAG,YAAiB;EAClF,MAAM,SAAS,UAAU;EACzB,MAAM,cAAc;GAAE,GAAG;GAAW,GAAG;EAAM;EAE7C,IAAI,MAAM,SAAS,QACjB,YAAY,OAAO,YAAY,IAAI,MAAM;EAG3C,IAAI,OAAO,cAAc,IAAI,KAAK,GAChC,YAAY,kBAAkB;EAGhC,YAAY,UAAU,aACnB,UAAyC;GACxC,MAAM,eAAe;GACrB,IAAI,MAAM,UAAU;GACpB,OAAO,SAAS;IAAE;IAAI;IAAgB,GAAI;GAAe,CAA+B;EAC1F,GACA;GAAC;GAAQ;GAAQ;GAAI,MAAM;EAAQ,CACrC;EAEA,OAAO,MAAM,cAAc,GAAG,aAAa,QAAQ;CACrD,CAAC;AACH;;;;ACjEA,MAAa,YAAiC,UAA8B;CAC1E,MAAM,SAAS,UAAU;CAEzB,sBAAsB;EACpB,OAAO,SAAS,KAAK;CACvB,GAAG,CAAC,QAAQ,KAAK,CAAC;CAElB,OAAO;AACT;;;;ACAA,MAAa,iBAA4B,EAAE,eAAe;AAE1D,MAAM,2BAAsC,oBAAC,KAAD,YAAG,aAAa;AAE5D,IAAa,SAAb,MAAoB;CAuBG;CAtBrB,QAA2B;CAC3B;CACA;CAOA;CAEA,IAAI,YAAmC;EACrC,QAAQ,KAAK,OAAb;GACE,KAAK,WACH,OAAO;GACT,KAAK,SACH,OAAO,KAAK,aAAa;GAC3B,SACE;EACJ;CACF;CAEA,YAAY,AAAS,QAAsB;EAAtB;EACnB,IAAI,CAAC,gBAAgB,OAAO,SAAS,GACnC,KAAK,YAAY,OAAO;EAG1B,mBAAmD,MAAM;GACvD,SAAS,WAAW;GACpB,MAAM,WAAW;GACjB,WAAW;GACX,QAAQ;EACV,CAAC;CACH;CAEA,MAAM,KAAK,OAA6B;EACtC,MAAM,WAA4B,CAAC;EAEnC,IAAI,gBAAgB,KAAK,OAAO,SAAS,KAAK,CAAC,KAAK,WAClD,SAAS,KAAK,KAAK,cAAc,CAAC;EAGpC,IAAI,KAAK,OAAO,QACd,SAAS,KAAK,KAAK,SAAS,KAAK,CAAC;EAGpC,IAAI,CAAC,SAAS,QAAQ;GACpB,KAAK,SAAS,OAAO;GACrB;EACF;EAKA,MAAM,kBAAkB,iBAAiB;GACvC,IAAI,KAAK,UAAU,cACjB,KAAK,SAAS,SAAS;EAE3B,GAAG,GAAG;EAEN,KAAK,UAAU,QAAQ,IAAI,QAAQ,CAAC,CACjC,WAAW;GACV,aAAa,eAAe;GAC5B,IAAI,KAAK,UAAU,WAIjB,iBAAiB;IACf,KAAK,SAAS,OAAO;GACvB,GAAG,GAAG;QAEN,KAAK,SAAS,OAAO;EAEzB,CAAC,CAAC,CACD,YAAY;GACX,aAAa,eAAe;GAG5B,KAAK,SAAS,OAAO;EACvB,CAAC;EAEH,MAAM,KAAK;CACb;CAEA,QAAQ,MAAe;EACrB,KAAK,OAAO;CACd;CAEA,SAAS,OAA0B;EACjC,KAAK,QAAQ;CACf;CAEA,MAAc,SAAS,OAA6B;EAClD,MAAM,KAAK,OAAO,SAAS,KAAK,CAAC,CAAC,MAAM,SAAS,KAAK,QAAQ,IAAI,CAAC;CACrE;CAEA,MAAc,gBAA+B;EAC3C,IAAI,CAAC,gBAAgB,KAAK,OAAO,SAAS,GAAG;EAC7C,MAAM,SAAS,MAAM,KAAK,OAAO,UAAU;EAC3C,KAAK,MAAM,cAAc,QACvB,IAAI,eAAe,aAAa,WAAW,SAAS,MAAM,GAAG;GAC3D,KAAK,YAAY,OAAO;GACxB;EACF;EAEF,MAAM,IAAI,MACR,gFACF;CACF;AACF;;;;AC5HA,IAAa,WAAb,MAA2C;CACpB;CAArB,YAAY,AAAS,SAA6B;EAA7B;CAA8B;AACrD;AAEA,MAAa,YAAiC,YAC5C,IAAI,SAAS,OAAO;;;;ACMtB,IAAa,QAAb,MAAmB;CACjB,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CACT,AAAS;CAET,IAAI,OAAY;EACd,OAAO,OAAO,OAAO,CAAC,GAAG,GAAG,KAAK,QAAQ,KAAK,MAAM,EAAE,IAAI,CAAC;CAC7D;CAEA,YAAY,KAAkB;EAC5B,KAAK,OAAO,IAAI;EAChB,KAAK,SAAS,IAAI;EAClB,KAAK,UAAU,IAAI,WAAW,CAAC;EAC/B,KAAK,UAAU,IAAI;EACnB,KAAK,SAAS,IAAI;EAClB,KAAK,SAAS,IAAI;EAElB,eAAe,MAAM,EACnB,MAAM,SACR,CAAC;CACH;CAEA,MAAM,QAAuB;EAC3B,KAAK,MAAM,SAAS,KAAK,QACvB,MAAM,MAAM,IAAI;CAEpB;CAEA,MAAM,OAAsB;EAC1B,MAAM,QAAQ,IAAI,KAAK,QAAQ,KAAK,WAAW,OAAO,KAAK,IAAI,CAAC,CAAC;CACnE;AACF;;;;ACxCA,MAAM,kBAAkB,SAA2B;CACjD,OAAO,KAAK,QAAQ,cAAc,EAAE,CAAC,CAAC,MAAM,GAAG;AACjD;AAWA,MAAa,aAAa,eAAkC;CAC1D,MAAM,UAAU,WAAW,QAAQ,QAAQ,MAAM,MAAM,MAAS;CAChE,MAAM,SAAS,WAAW,OAAO,QAAQ,MAAM,MAAM,MAAS;CAE9D,OAAO,IAAI,MAAM;EAAE,GAAG;EAAY;EAAS;EAAQ,MAAM,WAAW,SAAS,KAAK,GAAG;CAAE,CAAC;AAC1F;AAEA,MAAa,cAAc,MAAc,UAAkB,eAAmC;CAC5F,MAAM,QAAoB;EACxB,UAAU,CAAC;EACX,QAAQ,CAAC;EACT,GAAG;EACH,QAAQ,SAAS,WAAW,YAAY;EACxC,SAAS;GAAE,GAAG,YAAY;GAAS,GAAG,SAAS;EAAS;EACxD,QAAQ,CAAC,GAAI,YAAY,UAAU,CAAC,GAAI,SAAS,MAAM;EACvD,SAAS;GACP,GAAI,YAAY,WAAW,CAAC;GAC5B,SAAS,WAAW,IAAI,OAAO,EAAE,WAAW,SAAS,SAAS,CAAC,IAAI;GACnE,SAAS,QAAQ,IAAI,OAAO,EAAE,QAAQ,SAAS,MAAM,CAAC,IAAI;EAC5D;CACF;CAEA,MAAM,CAAC,SAAS,GAAG,qBAAqB,eAAe,IAAI;CAC3D,MAAM,gBAAgB,kBAAkB,KAAK,GAAG;CAEhD,IAAI,eAAe,SAAS,WAAW;CAEvC,IAAI,CAAC,cAAc;EACjB,MAAM,iBAAiB,OAAO,KAAK,QAAQ,CAAC,CAAC,MAAM,YAAY,QAAQ,WAAW,GAAG,CAAC;EACtF,IAAI,gBAAgB;GAClB,eAAe,SAAS;GACxB,MAAM,OAAO,eAAe,MAAM,CAAC,KAAK;EAC1C;CACF;CAEA,IAAI,CAAC,cACH,MAAM,IAAI,MAAM,YAAY;CAG9B,MAAM,SAAS,KAAK,WAAW,OAAO;CAEtC,IAAI,OAAO,YAAY,GAAG;EACxB,IAAI,eACF,MAAM,IAAI,MAAM,YAAY;EAG9B,IAAI,WAAW,YAAY,GAKzB,MAAM,IAAI,SAHR,OAAO,aAAa,cAAc,WAC9B,EAAE,IAAI,aAAa,UAAU,IAC7B,aAAa,SACe;EAGpC,IAAI,YAAY,YAAY,KAAK,gBAAgB,YAAY,GAAG;GAC9D,MAAM,QAAQ,KAAK,IAAI,OAAO,EAAE,WAAW,aAAa,CAAC,CAAC;GAC1D,OAAO,UAAU,KAAK;EACxB;CACF;CAIA,IAAI,OAAO,YAAY,GAAG;EACxB,MAAM,SAAS,aAAa,WAAW,MAAM;EAC7C,OAAO,OAAO,MAAM,SAAS,aAAa,QAAQ;EAClD,MAAM,OAAO,KAAK,aAAa,MAAM;EACrC,MAAM,QAAQ,KACZ,IAAI,OAAO;GACT,WAAW,aAAa;GACxB,QAAQ,aAAa;EACvB,CAAC,CACH;EAEA,OAAO,UAAU,KAAK;CACxB;CAGA,OAAO,WAAW,eAAe,cAAc,KAAK;AACtD;AAQA,MAAa,oBAEQ,WAAiB;CAQlC,OAAO;AACT;;;;ACvGF,IAAa,cAAb,MAAyB;CACvB,AAAS;CAET;CAEA;CACA;CAEA,IAAI,SAA0B;EAC5B,OAAO,IAAI,gBAAgB,KAAK,UAAU,MAAM;CAClD;CAEA,IAAI,QAAgC;EAClC,OAAO,OAAO,YAAY,KAAK,MAAM;CACvC;CAEA,IAAI,aAAqC;EACvC,MAAM,SAAS,CAAC;EAEhB,MAAM,gBAAgB,KAAK,eAAe,QAAQ,YAAY,QAAQ,WAAW,GAAG,CAAC;EACrF,MAAM,aAAa,KAAK,SAAS,SAAS,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;EAE5D,cAAc,SAAS,SAAS,UAAU;GACxC,MAAM,QAAQ,WAAW,QAAQ;GACjC,IAAI,OACF,OAAO,WAAW;EAEtB,CAAC;EAED,OAAO;CACT;CAEA,IAAI,iBAA2B;EAC7B,OAAO,KAAK,aAAa,KAAK,MAAM,GAAG,KAAK,CAAC;CAC/C;CAEA,YAAY,QAA2B;EACrC,eAAe,MAAM;GACnB,UAAU,WAAW;GACrB,aAAa,WAAW;GAExB,QAAQ;GACR,YAAY;GACZ,gBAAgB;GAEhB,aAAa;EACf,CAAC;EAED,KAAK,UAAU,QAAQ,WAAW,qBAAqB;CACzD;CAEA,WAAW,WAAyB;EAClC,KAAK,YAAY;EACjB,KAAK,QAAQ,QAAQ,SAAS;GAC5B,AAAK,KAAK,YAAY,KAAK,QAAQ;EACrC,CAAC;EAED,AAAK,KAAK,YAAY,KAAK,QAAQ,QAAQ;CAC7C;CAEA,cAAmC,MAAS,OAA0B;EACpE,MAAM,WAAW,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG;EAKxC,OAJsB,SAAS,OAC5B,SAAS,MAAM,YAAY,KAAK,eAAe,MAAM,QAAQ,WAAW,GAAG,CAIhE,KACZ,KAAK,eAAe,UAAU,SAAS,WACtC,CAAC,SAAS,SAAS,WAAW,KAAK,eAAe;CAEvD;CAEA,SAA8B,SAAmC;EAC/D,IAAI,CAAC,SAAS,qBACZ,KAAK,UAAU,OAAO;OAGtB,AADmB,SAAS,0BAA0B,KAAK,UAAU,OAAO,CACnE,CAAC,CAAC,MAAM,OAAO,MAAM,QAAQ,IAAI,GAAG,OAAO,CAAC,CAAC;CAE1D;CAEA,UAA+B,SAAmC;EAChE,MAAM,EAAE,IAAI,SAAS,OAAO,SAAS,CAAC,GAAG,gBAAgB,WAAW;EAEpE,MAAM,eAAe,kBAAkB,kBAAkB,SAAS,IAAI,gBAAgB,MAAM;EAE5F,IAAI,gBACF;QAAK,MAAM,CAAC,MAAM,UAAU,KAAK,QAC/B,IAAI,CAAC,aAAa,IAAI,IAAI,GACxB,aAAa,IAAI,MAAM,KAAK;EAEhC;EAGF,MAAM,WAAW;GACf,UAAU,YAAY,IAAI,MAAM;GAChC,QAAQ,aAAa,OAAO,IAAI,aAAa,SAAS,MAAM;EAC9D;EAEA,IAAI,SACF,KAAK,QAAQ,QAAQ,UAAU,KAAK;OAEpC,KAAK,QAAQ,KAAK,UAAU,KAAK;CAErC;CAEA,cAAc,OAAe,OAAqB;EAChD,MAAM,SAAS,IAAI,gBAAgB,KAAK,SAAS,MAAM;EACvD,OAAO,IAAI,OAAO,KAAK;EACvB,KAAK,QAAQ,QAAQ,EAAE,QAAQ,OAAO,SAAS,EAAE,CAAC;CACpD;CAEA,iBAAiB,OAAmC;EAClD,MAAM,SAAS,IAAI,gBAAgB,KAAK,SAAS,MAAM;EACvD,MAAM,QAAQ,OAAO,IAAI,KAAK,KAAK;EACnC,IAAI,UAAU,QAAW;GACvB,OAAO,OAAO,KAAK;GACnB,KAAK,QAAQ,QAAQ,EAAE,QAAQ,OAAO,SAAS,EAAE,CAAC;EACpD;EACA,OAAO;CACT;CAEA,MAAM,YAAY,UAAmC;EACnD,IAAI,CAAC,KAAK,WAAW;EAIrB,IAAI,SAAS,aAAa,OAAO,SAAS,SAAS,SAAS,GAAG,GAAG;GAChE,KAAK,QAAQ,QAAQ;IAAE,GAAG;IAAU,UAAU,SAAS,SAAS,MAAM,GAAG,EAAE;GAAE,CAAC;GAC9E;EACF;EAEA,KAAK,WAAW;EAEhB,IAAI;GACF,MAAM,eAAe,WAAW,SAAS,UAAU,KAAK,SAAS;GAEjE,MAAM,aAAa,MAAM;GAIzB,IAAI,KAAK,aAAa,UACpB;GAGF,kBAAkB;IAChB,KAAK,cAAc;GACrB,CAAC;GAED,MAAM,KAAK,aAAa,KAAK;EAC/B,SAAS,GAAG;GACV,IAAI,aAAa,UAAU;IACzB,KAAK,SAAS,EAAE,OAAO;IACvB;GACF;GACA,MAAM;EACR;CACF;AACF"}
1
+ {"version":3,"file":"router.mjs","names":[],"sources":["../src/router/errors.ts","../src/router/components/error.tsx","../src/router/symbols.ts","../src/router/util.ts","../src/router/components/router.tsx","../src/router/components/link.tsx","../src/router/components/navigate.tsx","../src/router/redirect.ts","../src/router/outlet.tsx","../src/router/route.tsx","../src/router/make-routes.tsx","../src/router/router.store.ts"],"sourcesContent":["import type { MatchState } from \"./make-routes\";\n\nexport type RouterErrorType = \"NOT_FOUND\" | \"GUARD\" | \"LOAD\" | \"RENDER\";\n\nexport interface RouterErrorOptions {\n message?: string;\n cause?: unknown;\n path?: string;\n}\n\nconst defaultMessage = (type: RouterErrorType, path?: string): string => {\n switch (type) {\n case \"NOT_FOUND\":\n return path ? `No route matches '${path}'.` : \"No matching route.\";\n case \"GUARD\":\n return \"A route guard rejected the navigation.\";\n case \"LOAD\":\n return \"A route loader or lazy component failed.\";\n case \"RENDER\":\n return \"A route component failed to render.\";\n }\n};\n\n/**\n * The single error type surfaced to `[ERROR]` components. `type`\n * discriminates the failure source; when the router wraps an\n * application-level error (thrown by a guard or loader), the original\n * is preserved on the standard `cause` property.\n *\n * Guards and loaders may also throw `RouterError` directly — e.g.\n * `throw new RouterError(\"NOT_FOUND\")` from a loader when an entity\n * doesn't exist — and it passes through unwrapped.\n */\nexport class RouterError extends Error {\n readonly type: RouterErrorType;\n readonly path?: string;\n\n /** @internal matched-prefix state captured when the matcher throws NOT_FOUND */\n state?: MatchState;\n /** @internal level index of the failing guard, for depth-aware bubbling */\n depth?: number;\n\n constructor(type: RouterErrorType, options?: RouterErrorOptions) {\n super(options?.message ?? defaultMessage(type, options?.path), { cause: options?.cause });\n this.name = \"RouterError\";\n this.type = type;\n this.path = options?.path;\n }\n}\n","import React from \"react\";\nimport { RouterError } from \"../errors\";\nimport type { Route } from \"../route\";\nimport type { Component, ErrorComponentProps } from \"../types\";\n\n/**\n * Rendered when an error occurs and no `[ERROR]` component is defined\n * on the matched prefix. Deliberately minimal and dependency-free —\n * define a root-level `[ERROR]` to replace it.\n */\nexport const DefaultErrorPage: Component = ({ error }: ErrorComponentProps) => (\n <div role=\"alert\">\n <h1>{error.type === \"NOT_FOUND\" ? \"Page Not Found\" : \"Something Went Wrong\"}</h1>\n <p>{error.message}</p>\n </div>\n);\n\nexport interface RouteErrorBoundaryProps {\n route: Route;\n fallback: Component;\n children?: React.ReactNode;\n}\n\ninterface RouteErrorBoundaryState {\n error?: RouterError;\n}\n\n/**\n * Catches render-time crashes in page and `[WRAPPER]` components and\n * renders the nearest `[ERROR]` component with `type: \"RENDER\"`. Mounted\n * inside the `[LAYOUT]` so the layout survives page crashes; crashes in\n * the layout itself (or in the fallback) propagate out of `<Router>` by\n * design — those are developer bugs that should stay loud.\n */\nexport class RouteErrorBoundary extends React.Component<\n RouteErrorBoundaryProps,\n RouteErrorBoundaryState\n> {\n override state: RouteErrorBoundaryState = {};\n\n static getDerivedStateFromError(cause: unknown): RouteErrorBoundaryState {\n return { error: cause instanceof RouterError ? cause : new RouterError(\"RENDER\", { cause }) };\n }\n\n override render(): React.ReactNode {\n if (!this.state.error) return this.props.children;\n\n const Fallback = this.props.fallback;\n return <Fallback route={this.props.route} error={this.state.error} />;\n }\n}\n","export const CONTEXT: unique symbol = Symbol.for(\"MOBX_ROUTER_CONTEXT\");\nexport const LAYOUT: unique symbol = Symbol.for(\"MOBX_ROUTER_LAYOUT\");\nexport const WRAPPER: unique symbol = Symbol.for(\"MOBX_ROUTER_WRAPPER\");\nexport const LOAD: unique symbol = Symbol.for(\"MOBX_ROUTER_LOAD\");\nexport const GUARD: unique symbol = Symbol.for(\"MOBX_ROUTER_GUARD\");\nexport const PAGE: unique symbol = Symbol.for(\"MOBX_ROUTER_PAGE\");\nexport const ERROR: unique symbol = Symbol.for(\"MOBX_ROUTER_ERROR\");\nexport const REDIRECT: unique symbol = Symbol.for(\"MOBX_ROUTER_REDIRECT\");\n","import { PAGE, REDIRECT } from \"./symbols\";\nimport type { Component, LazyComponent, Leaf, Obj, Page, Redirector } from \"./types\";\n\nexport const resolvePath = (to: string, params?: Obj): string => {\n return to.replaceAll(/:[^/]*/g, (segment) => {\n const value = params?.[segment.slice(1)];\n if (!value)\n throw new Error(`Unable to resolve route '${to}'. Parameter '${segment}' not specified.`);\n return value;\n });\n};\n\nexport const isComponent = (data: any): data is Component => {\n if (!data) return false;\n return (\n typeof data === \"function\" ||\n (typeof data === \"object\" && data[\"$$typeof\"] === Symbol.for(\"react.memo\"))\n );\n};\n\nexport const isPage = (data: any): data is Page => {\n if (typeof data !== \"object\") return false;\n const symbols = Object.getOwnPropertySymbols(data);\n return symbols.includes(PAGE);\n};\n\nexport const isRedirect = (data: any): data is Redirector => {\n if (typeof data !== \"object\") return false;\n const symbols = Object.getOwnPropertySymbols(data);\n return symbols.includes(REDIRECT);\n};\n\nexport const isLeaf = (data: any): data is Leaf => {\n return isComponent(data) || isPage(data) || isRedirect(data);\n};\n\nexport const isLazyComponent = (data: any): data is LazyComponent => {\n return typeof data === \"function\" && data.toString().startsWith(\"() => import(\");\n};\n","import { observer } from \"mobx-react-lite\";\nimport { createContext, useContext } from \"react\";\nimport type { Route } from \"../route\";\nimport type { RouterStore } from \"../router.store\";\nimport type { Component } from \"../types\";\nimport { DefaultErrorPage, RouteErrorBoundary } from \"./error\";\n\nexport const PassThrough: Component = ({ children }) => children;\n\n// Plain (non-observer) renderer. State observation lives one level up\n// in `Router`, so the page component renders as a child of a plain\n// FunctionComponent — no memo wrapper in the parent chain to interact\n// with React Refresh's family-update propagation.\nexport const RouterOutlet: React.FC<{ route: Route; components: (Component | undefined)[] }> = ({\n route,\n components,\n}) => {\n const [C, ...remaining] = components;\n\n if (!C) return null;\n\n return (\n <C route={route}>\n {remaining.length > 0 && <RouterOutlet route={route} components={remaining} />}\n </C>\n );\n};\n\nexport const routerContext = createContext<RouterStore>(null as any);\nexport const useRouter = () => useContext(routerContext);\n\nexport interface RouterProps {\n store: RouterStore;\n}\n\nexport const Router = observer(({ store }: RouterProps) => {\n const route = store.activeRoute;\n if (!route) {\n return null;\n }\n\n const Layout = route.layout ?? PassThrough;\n const components = route.outlets.map((o) => o.Component);\n const outlet = <RouterOutlet route={route} components={components} />;\n\n // Render crashes in pages/wrappers funnel to the nearest [ERROR]\n // component; the layout survives. On synthetic error routes the\n // boundary is omitted so a crashing [ERROR] component propagates\n // out of <Router> — a developer bug that should stay loud. Layout\n // crashes propagate for the same reason.\n const fallback = route.levels.at(-1)?.errorComponent ?? DefaultErrorPage;\n\n return (\n <routerContext.Provider value={store}>\n <Layout route={route}>\n {route.error ? (\n outlet\n ) : (\n <RouteErrorBoundary key={store.location.key} route={route} fallback={fallback}>\n {outlet}\n </RouteErrorBoundary>\n )}\n </Layout>\n </routerContext.Provider>\n );\n});\n","import { observer } from \"mobx-react-lite\";\nimport React, { useCallback } from \"react\";\nimport type {\n DynamicRoutePath,\n ExtractParams,\n NavigateOptions,\n RoutePath,\n StaticRoutePath,\n} from \"../types\";\nimport { resolvePath } from \"../util\";\nimport { useRouter } from \"./router\";\n\ntype LinkComponentProps<C extends React.ElementType> = Omit<\n React.ComponentProps<C>,\n \"ref\" | \"exact\" | \"to\" | \"params\" | \"onClick\" | \"asChild\"\n>;\n\nexport type LinkPropsBase<\n C extends React.ElementType,\n I extends React.ElementType = C,\n> = LinkComponentProps<C> & {\n exact?: boolean;\n preserveSearch?: boolean;\n ref?: React.Ref<React.ComponentRef<I>>;\n};\n\n// function overloading is much faster than leveraging conditional types\n// but once the typescript go compiler is released and performance is no\n// longer an issue, it might make sense to simplify this a bit so it can\n// be more easily consumed by users\nexport interface LinkComponent<C extends React.ElementType, I extends React.ElementType = C> {\n <P extends StaticRoutePath>(\n props: LinkPropsBase<C, I> & { to: P; params?: undefined },\n ): React.ReactNode;\n <P extends DynamicRoutePath>(\n props: LinkPropsBase<C, I> & { to: P; params: ExtractParams<P> },\n ): React.ReactNode;\n}\n\n// final thing to do is make sure refs still work in React 19\n\n// this smooths over some of the awkwardness when extending this component\nexport const makeLinkComponent = <C extends React.ElementType, I extends React.ElementType = C>(\n C: C,\n baseProps?: Partial<LinkComponentProps<C>> & { as?: I },\n) => {\n return observer(({ to, params, exact, preserveSearch, children, ...props }: any) => {\n const router = useRouter();\n const mergedProps = { ...baseProps, ...props };\n\n if (props.role !== \"link\") {\n mergedProps.href = resolvePath(to, params);\n }\n\n if (router.doesPathMatch(to, exact)) {\n mergedProps[\"aria-current\"] = \"page\";\n }\n\n mergedProps.onClick = useCallback(\n (event: React.MouseEvent<HTMLElement>) => {\n event.preventDefault();\n if (props.disabled) return;\n router.navigate({ to, preserveSearch, params } as NavigateOptions<RoutePath>);\n },\n [router, params, to, props.disabled],\n );\n\n return React.createElement(C, mergedProps, children);\n }) as LinkComponent<C, I>;\n};\n\n//export const Link = makeLinkComponent('a');\n","import { useLayoutEffect } from \"react\";\nimport type { NavigateOptions, RoutePath } from \"../types\";\nimport { useRouter } from \"./router\";\n\nexport const Navigate = <P extends RoutePath>(props: NavigateOptions<P>) => {\n const router = useRouter();\n\n useLayoutEffect(() => {\n router.navigate(props);\n }, [router, props]);\n\n return null;\n};\n","import type { NavigateOptions, RoutePath } from \"./types\";\n\nexport class Redirect<P extends RoutePath> {\n constructor(readonly options: NavigateOptions<P>) {}\n}\n\nexport const redirect = <P extends RoutePath>(options: NavigateOptions<P>): Redirect<P> =>\n new Redirect(options);\n","import { makeAutoObservable, observable } from \"mobx\";\nimport { DefaultErrorPage } from \"./components/error\";\nimport { RouterError } from \"./errors\";\nimport { Redirect } from \"./redirect\";\nimport type { Route } from \"./route\";\nimport type { Component, LazyComponent, Loader, Obj } from \"./types\";\nimport { isLazyComponent } from \"./util\";\n\nexport interface OutletConfig {\n component?: Component | LazyComponent;\n loader?: Loader;\n errorComponent?: Component;\n}\n\nexport type RouteSegmentState = \"preloading\" | \"loading\" | \"error\" | \"ready\";\n\nexport const DefaultOutlet: Component = ({ children }) => children;\n\nconst LoadingPlaceholder: Component = () => <p>Loading...</p>;\n\nexport class Outlet {\n state: RouteSegmentState = \"preloading\";\n promise: Promise<unknown> | undefined;\n data: unknown;\n error: RouterError | undefined;\n\n // Plain (non-observable) reference. The page component must reach\n // React unmediated by MobX — once MobX deep-observes the holder,\n // React Refresh can no longer swap the page identity via family\n // lookup on the original function. This mirrors how Route holds\n // `layout` as a plain field under makeObservable.\n component: Component | undefined;\n\n get Component(): Component | undefined {\n switch (this.state) {\n case \"loading\":\n return LoadingPlaceholder;\n case \"ready\":\n return this.component ?? DefaultOutlet;\n case \"error\": {\n // render the nearest [ERROR] component in this outlet's slot,\n // leaving the rest of the page intact\n const ErrorComponent = this.config.errorComponent ?? DefaultErrorPage;\n const error = this.error ?? new RouterError(\"LOAD\");\n return (props: Obj) => <ErrorComponent {...props} error={error} />;\n }\n default:\n return undefined;\n }\n }\n\n constructor(readonly config: OutletConfig) {\n if (!isLazyComponent(config.component)) {\n this.component = config.component;\n }\n\n makeAutoObservable<Outlet, \"component\" | \"config\">(this, {\n promise: observable.ref,\n data: observable.ref,\n error: observable.ref,\n component: false,\n config: false,\n });\n }\n\n async load(route: Route): Promise<void> {\n const promises: Promise<void>[] = [];\n\n if (isLazyComponent(this.config.component) && !this.component) {\n promises.push(this.loadComponent());\n }\n\n if (this.config.loader) {\n promises.push(this.loadData(route));\n }\n\n if (!promises.length) {\n this.setState(\"ready\");\n return;\n }\n\n // wait to transition to loading to avoid\n // screen flashes when the loader function\n // executes quickly\n const preloadingTimer = setTimeout(() => {\n if (this.state === \"preloading\") {\n this.setState(\"loading\");\n }\n }, 300);\n\n this.promise = Promise.all(promises)\n .then(() => {\n clearTimeout(preloadingTimer);\n if (this.state === \"loading\") {\n // if we had to transition to regular loading because\n // the loader was taking too long, force an additional\n // timeout to prevent a loading flash\n setTimeout(() => {\n this.setState(\"ready\");\n }, 300);\n } else {\n this.setState(\"ready\");\n }\n })\n .catch((e) => {\n clearTimeout(preloadingTimer);\n this.setState(\"error\");\n // a Redirect thrown by a loader propagates so the router\n // navigates; everything else renders in-slot error UI\n if (e instanceof Redirect) throw e;\n this.setError(e instanceof RouterError ? e : new RouterError(\"LOAD\", { cause: e }));\n });\n\n await this.promise;\n }\n\n setData(data: unknown) {\n this.data = data;\n }\n\n setError(error: RouterError) {\n this.error = error;\n }\n\n setState(state: RouteSegmentState) {\n this.state = state;\n }\n\n private async loadData(route: Route): Promise<void> {\n await this.config.loader?.(route).then((data) => this.setData(data));\n }\n\n private async loadComponent(): Promise<void> {\n if (!isLazyComponent(this.config.component)) return;\n const module = await this.config.component();\n for (const exportName in module) {\n if (exportName === \"default\" || exportName.endsWith(\"Page\")) {\n this.component = module[exportName];\n return;\n }\n }\n throw new Error(\n \"Lazy route component module did not export `default` or a `*Page` named export\",\n );\n }\n}\n","import { computed, makeObservable } from \"mobx\";\nimport { RouterError } from \"./errors\";\nimport type { Outlet } from \"./outlet\";\nimport { Redirect } from \"./redirect\";\nimport type { Component, Guard, GuardEntry, MatchLevel, Obj } from \"./types\";\n\nexport interface RouteConfig {\n path: string;\n outlets: Outlet[];\n guards: GuardEntry[];\n levels: MatchLevel[];\n context?: Obj;\n layout?: Component;\n params: Obj;\n error?: RouterError;\n}\n\nexport class Route {\n readonly path: string;\n readonly outlets: Outlet[];\n readonly guards: Guard[];\n readonly context: Obj;\n readonly params: Obj;\n readonly layout?: Component;\n /** set on synthetic error routes; the error being rendered */\n readonly error?: RouterError;\n /** @internal */\n readonly guardEntries: GuardEntry[];\n /** @internal */\n readonly levels: MatchLevel[];\n\n get data(): Obj {\n return Object.assign({}, ...this.outlets.map((o) => o.data));\n }\n\n constructor(def: RouteConfig) {\n this.path = def.path;\n this.guardEntries = def.guards;\n this.guards = def.guards.map((entry) => entry.guard);\n this.levels = def.levels;\n this.context = def.context ?? {};\n this.outlets = def.outlets;\n this.params = def.params;\n this.layout = def.layout;\n this.error = def.error;\n\n makeObservable(this, {\n data: computed,\n });\n }\n\n async guard(): Promise<void> {\n for (const { guard, depth } of this.guardEntries) {\n try {\n await guard(this);\n } catch (e) {\n if (e instanceof Redirect) throw e;\n const error = e instanceof RouterError ? e : new RouterError(\"GUARD\", { cause: e });\n error.depth ??= depth;\n throw error;\n }\n }\n }\n\n async load(): Promise<void> {\n await Promise.all(this.outlets.map((outlet) => outlet.load(this)));\n }\n}\n","import { DefaultErrorPage } from \"./components/error\";\nimport { RouterError } from \"./errors\";\nimport { Outlet } from \"./outlet\";\nimport { Redirect } from \"./redirect\";\nimport { Route } from \"./route\";\nimport { CONTEXT, ERROR, GUARD, LAYOUT, LOAD, PAGE, REDIRECT, WRAPPER } from \"./symbols\";\nimport type { Component, GuardEntry, MatchLevel, Obj, Routes } from \"./types\";\nimport { isComponent, isLazyComponent, isLeaf, isPage, isRedirect } from \"./util\";\n\nconst pathToSegments = (path: string): string[] => {\n return path.replace(/^\\/+|\\/+$/g, \"\").split(\"/\");\n};\n\nexport interface MatchState {\n segments: string[];\n context: Obj;\n params: Obj;\n outlets: (Outlet | undefined)[];\n guards: GuardEntry[];\n levels: MatchLevel[];\n layout?: Component;\n errorComponent?: Component;\n}\n\nexport const makeRoute = (matchState: MatchState): Route => {\n const outlets = matchState.outlets.filter((o) => o !== undefined);\n\n return new Route({ ...matchState, outlets, path: matchState.segments.join(\"/\") });\n};\n\n/**\n * Builds the synthetic route rendered when navigation fails. Bubbles\n * from the failing level (`error.depth`, defaulting to the deepest\n * matched level) to the nearest `[ERROR]` component, preserving the\n * `[LAYOUT]` and `[WRAPPER]`s accumulated up to that level. Ancestor\n * `[LOAD]` loaders are intentionally not run — error routes never\n * fetch data.\n */\nexport const makeErrorRoute = (\n error: RouterError,\n pathname: string,\n source?: { levels: MatchLevel[]; params: Obj; context: Obj },\n): Route => {\n const levels = error.state?.levels ?? source?.levels ?? [];\n const depth = Math.min(error.depth ?? levels.length - 1, levels.length - 1);\n const level = depth >= 0 ? levels[depth] : undefined;\n\n const ErrorComponent = level?.errorComponent ?? DefaultErrorPage;\n const outlets = levels\n .slice(0, depth + 1)\n .flatMap((l) => (l.wrapper ? [new Outlet({ component: l.wrapper })] : []));\n outlets.push(\n new Outlet({ component: (props: Obj) => <ErrorComponent {...props} error={error} /> }),\n );\n\n return new Route({\n path: pathname.replace(/^\\/+/, \"\"),\n outlets,\n guards: [],\n levels: [],\n params: error.state?.params ?? source?.params ?? {},\n context: error.state?.context ?? source?.context ?? {},\n layout: level?.layout,\n error,\n });\n};\n\nconst notFound = (state: MatchState, attemptedSegments: string[]): RouterError => {\n const error = new RouterError(\"NOT_FOUND\", {\n path: `/${attemptedSegments.filter((s) => s !== \"\").join(\"/\")}`,\n });\n error.state = state;\n return error;\n};\n\nexport const matchRoute = (path: string, routeDef: Routes, matchState?: MatchState): Route => {\n const depth = matchState?.levels.length ?? 0;\n const layout = routeDef[LAYOUT] ?? matchState?.layout;\n const errorComponent = routeDef[ERROR] ?? matchState?.errorComponent;\n\n const state: MatchState = {\n segments: [],\n params: {},\n ...matchState,\n layout,\n errorComponent,\n context: { ...matchState?.context, ...routeDef[CONTEXT] },\n guards: [\n ...(matchState?.guards ?? []),\n ...(routeDef[GUARD] ? [{ guard: routeDef[GUARD], depth }] : []),\n ],\n outlets: [\n ...(matchState?.outlets ?? []),\n routeDef[WRAPPER] ? new Outlet({ component: routeDef[WRAPPER], errorComponent }) : undefined,\n routeDef[LOAD] ? new Outlet({ loader: routeDef[LOAD], errorComponent }) : undefined,\n ],\n levels: [...(matchState?.levels ?? []), { wrapper: routeDef[WRAPPER], layout, errorComponent }],\n };\n\n const [segment, ...remainingSegments] = pathToSegments(path);\n const remainingPath = remainingSegments.join(\"/\");\n\n let defAtSegment = routeDef[segment || \"index\"];\n\n if (!defAtSegment) {\n const matchedSegment = Object.keys(routeDef).find(\n (segment) => segment.startsWith(\"$\") || segment.startsWith(\":\"),\n );\n if (matchedSegment) {\n defAtSegment = routeDef[matchedSegment];\n state.params[matchedSegment.slice(1)] = segment;\n }\n }\n\n if (!defAtSegment) {\n throw notFound(state, [...state.segments, segment ?? \"\", ...remainingSegments]);\n }\n\n state.segments.push(segment ?? \"index\");\n\n if (isLeaf(defAtSegment)) {\n if (remainingPath) {\n throw notFound(state, [...state.segments, ...remainingSegments]);\n }\n\n if (isRedirect(defAtSegment)) {\n const redirect =\n typeof defAtSegment[REDIRECT] === \"string\"\n ? { to: defAtSegment[REDIRECT] }\n : defAtSegment[REDIRECT];\n throw new Redirect(redirect as any);\n }\n\n if (isComponent(defAtSegment) || isLazyComponent(defAtSegment)) {\n state.outlets.push(new Outlet({ component: defAtSegment, errorComponent }));\n return makeRoute(state);\n }\n }\n\n // at this point we have a nested route or a [Page] definition\n\n if (isPage(defAtSegment)) {\n state.layout = defAtSegment[LAYOUT] ?? state.layout;\n state.errorComponent = defAtSegment[ERROR] ?? state.errorComponent;\n Object.assign(state.context, defAtSegment[CONTEXT]);\n if (defAtSegment[GUARD]) {\n state.guards.push({ guard: defAtSegment[GUARD], depth });\n }\n state.outlets.push(\n new Outlet({\n component: defAtSegment[PAGE],\n loader: defAtSegment[LOAD],\n errorComponent: state.errorComponent,\n }),\n );\n state.levels[state.levels.length - 1] = {\n ...state.levels[state.levels.length - 1],\n layout: state.layout,\n errorComponent: state.errorComponent,\n };\n\n return makeRoute(state);\n }\n\n // now we know we have a nested route\n return matchRoute(remainingPath, defAtSegment, state);\n};\n\n// TODO: ideally this could resolve to something less than R,\n// but specific enough to infer all paths as a literal union.\n// As it stands, there are certain things we can't access reliably\n// without the compiler complaining about circular references\n// try \"as const satisfies\" approach which would allow us to\n// exchange a less specific version of MobxRoutesRoot for this\nexport const makeRoutes =\n () =>\n <R extends Routes>(routes: R): R => {\n // todo: perform some validation here\n // - no forward slashes in keys\n // - at most one variable segment per level\n // - only lowercase letters (except variables)\n // - paths/variables cannot contain $ or : that aren't at the beginning\n // - path variables must be unique across a path\n return routes;\n };\n","import { createBrowserHistory, type History, type Location } from \"history\";\nimport { action, computed, makeObservable, observable, runInAction } from \"mobx\";\nimport { RouterError } from \"./errors\";\nimport { makeErrorRoute, matchRoute } from \"./make-routes\";\nimport { Redirect } from \"./redirect\";\nimport type { Route } from \"./route\";\nimport type { Component, MobxRouterConfig, NavigateOptions, Obj, RoutePath, Routes } from \"./types\";\nimport { resolvePath } from \"./util\";\n\nexport interface MobxRenderSegment {\n segment: string;\n component: Component;\n props?: Obj;\n}\n\nexport class RouterStore {\n readonly history: History;\n\n routesDef?: Routes;\n\n location!: Location;\n activeRoute: Route | undefined;\n\n get search(): URLSearchParams {\n return new URLSearchParams(this.location?.search);\n }\n\n get query(): Record<string, string> {\n return Object.fromEntries(this.search);\n }\n\n get pathParams(): Record<string, string> {\n return { ...this.activeRoute?.params };\n }\n\n get activeSegments(): string[] {\n return this.activeRoute?.path.split(\"/\") ?? [];\n }\n\n constructor(config?: MobxRouterConfig) {\n makeObservable(this, {\n location: observable.ref,\n activeRoute: observable.ref,\n\n search: computed,\n pathParams: computed,\n activeSegments: computed,\n\n setLocation: action,\n });\n\n this.history = config?.history ?? createBrowserHistory();\n }\n\n initialize(routesDef: Routes): void {\n this.routesDef = routesDef;\n this.history.listen((data) => {\n void this.setLocation(data.location);\n });\n\n void this.setLocation(this.history.location);\n }\n\n doesPathMatch<P extends RoutePath>(path: P, exact?: boolean): boolean {\n const segments = path.slice(1).split(\"/\");\n const segmentsMatch = segments.every(\n (segment, i) => segment === this.activeSegments[i] || segment.startsWith(\":\"),\n );\n\n return (\n segmentsMatch &&\n this.activeSegments.length >= segments.length &&\n (!exact || segments.length === this.activeSegments.length)\n );\n }\n\n navigate<P extends RoutePath>(options: NavigateOptions<P>): void {\n if (!document.startViewTransition) {\n this._navigate(options);\n } else {\n const transition = document.startViewTransition(() => this._navigate(options));\n transition.ready.catch((e) => console.log(e, typeof e));\n }\n }\n\n _navigate<P extends RoutePath>(options: NavigateOptions<P>): void {\n const { to, replace, state, search = {}, preserveSearch, params } = options;\n\n const searchParams = search instanceof URLSearchParams ? search : new URLSearchParams(search);\n\n if (preserveSearch) {\n for (const [name, value] of this.search) {\n if (!searchParams.has(name)) {\n searchParams.set(name, value);\n }\n }\n }\n\n const location = {\n pathname: resolvePath(to, params),\n search: searchParams.size ? `?${searchParams.toString()}` : undefined,\n };\n\n if (replace) {\n this.history.replace(location, state);\n } else {\n this.history.push(location, state);\n }\n }\n\n setQueryParam(param: string, value: string): void {\n const params = new URLSearchParams(this.location.search);\n params.set(param, value);\n this.history.replace({ search: params.toString() });\n }\n\n removeQueryParam(param: string): string | undefined {\n const params = new URLSearchParams(this.location.search);\n const value = params.get(param) ?? undefined;\n if (value !== undefined) {\n params.delete(param);\n this.history.replace({ search: params.toString() });\n }\n return value;\n }\n\n async setLocation(location: Location): Promise<void> {\n if (!this.routesDef) return;\n\n // TODO: this should not be the responsibility of mobx-router\n // and should really be handled server-side\n if (location.pathname !== \"/\" && location.pathname.endsWith(\"/\")) {\n this.history.replace({ ...location, pathname: location.pathname.slice(0, -1) });\n return;\n }\n\n this.location = location;\n\n let matchedRoute: Route | undefined;\n try {\n matchedRoute = matchRoute(location.pathname, this.routesDef);\n\n await matchedRoute.guard();\n\n // navigating within a guard function\n // is essentially a redirect\n if (this.location !== location) {\n return;\n }\n\n runInAction(() => {\n this.activeRoute = matchedRoute;\n });\n\n await this.activeRoute?.load();\n } catch (e) {\n if (e instanceof Redirect) {\n this.navigate(e.options);\n return;\n }\n\n // navigating within a guard before it threw — treat as a redirect\n if (this.location !== location) {\n return;\n }\n\n const error =\n e instanceof RouterError\n ? e\n : new RouterError(\"RENDER\", { cause: e, path: location.pathname });\n console.error(error);\n\n const errorRoute = makeErrorRoute(error, location.pathname, matchedRoute);\n runInAction(() => {\n this.activeRoute = errorRoute;\n });\n await errorRoute.load();\n }\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jayalfredprufrock/mobx-toolbox",
3
- "version": "0.6.4",
3
+ "version": "0.7.0",
4
4
  "description": "Misc mobx/react modules/utilities.",
5
5
  "homepage": "https://github.com/jayalfredprufrock/mobx-toolbox#readme",
6
6
  "bugs": {