{"version":3,"file":"dumba.modern.mjs","sources":["../../src/utils.ts","../../src/field.ts","../../src/form.ts","../../src/validation.ts","../../src/runner.ts","../../src/field-factory.ts"],"sourcesContent":["import type { Form } from './form'\nimport type { Field } from './field'\n\n/*\nPerforms a deep comparison between two values to determine if they are equivalent.\n@see https://www.30secondsofcode.org/js/s/equals\n*/\nexport function equals(a: any, b: any): boolean {\n  if (a === b) return true\n  if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime()\n  if (!a || !b || (typeof a !== 'object' && typeof b !== 'object'))\n    return a === b\n  if (a.prototype !== b.prototype) return false\n  const keys = Object.keys(a)\n  if (keys.length !== Object.keys(b).length) return false\n\n  return keys.every((k) => equals(a[k], b[k]))\n}\n\n/**\n * Gets the form {@link Form} from the passed in field\n * @typeparam T - value of the Form schema\n */\nexport function getForm<T>(field: Field): Form<T> {\n  return field.form\n}\n","import { action, computed, makeObservable, observable, runInAction } from 'mobx'\nimport { Form } from './form'\nimport { Runner } from './runner'\nimport { equals } from './utils'\n\n/**\n * Result of the {@link Field} validation\n * @typeparam T - value of the {@link Field}\n */\nexport type FieldResult<T = any> = {\n  /**\n   * name of the field\n   */\n  name: string\n  /**\n   * value of the field\n   */\n  value: T\n  /**\n   * path of the field in the schema\n   */\n  path: string\n  /**\n   * error messages\n   */\n  errors: string[] | null\n}\n\n/**\n * Field form the {@link Form}\n * @typeparam T - type of the value for the field\n */\nexport class Field<T = any> {\n  /**\n   * Determines whether field is in the process of validating\n   */\n  isValidating = false\n\n  /**\n   * Determines whether field is validated. The value is true when field validations\n   * have run at least once\n   */\n  isValidated = false\n\n  /**\n   * Errors from the validation process\n   */\n  errors: string[] = []\n\n  /**\n   * Refrence to the {@link Form} that is holding the field instance\n   */\n  form!: Form<any>\n\n  /**\n   * Name  of field\n   */\n  name!: string\n\n  /**\n   * Path  of field in the {@link Form} that holds the field\n   */\n  path!: string\n\n  /**\n   * Initial value of field. Field will be reverted to this value after {@link Field.reset}\n   */\n  initialValue: T\n\n  /**\n   * Method to be hooked to the HTML \"onChange\" event. It will set the value to the field, and run validations.\n   * This method can also be hooked to the HTML \"onBlur\" event.\n   */\n  onChange: (...args: any[]) => Promise<void>\n\n  /**\n   * ID of debounced onChange event\n   */\n  protected timeoutId?: number\n\n  /**\n   * Fields that depend on this field\n   */\n  protected _dependants: Map<string, Field<any>> = new Map()\n\n  /**\n   * Creates an instance of field.\n   * @param runner\n   * @param value\n   * @param alwaysValid\n   * @param [parseValue]\n   * @param [delay]\n   * @param [dependsOn]\n   */\n  constructor(\n    public runner: Runner,\n    public value: T,\n    protected alwaysValid: boolean,\n    protected parseValue?: (data: any, field: Field<T>) => T,\n    public delay?: number,\n    protected dependsOn: string[] = [],\n    public isDisabled = false,\n    protected shouldDisable?: (\n      value: any,\n      field: Field<any>,\n      dependency?: Field<any>\n    ) => boolean | Promise<boolean>\n  ) {\n    this.initialValue = this.value\n\n    if (this.alwaysValid) {\n      this.isValidated = true\n    }\n\n    this.onChange = async (evt: any) => {\n      if (this.isDisabled) return\n      this.value = this.parseValue\n        ? this.parseValue(evt, this)\n        : evt?.currentTarget?.value != null\n        ? evt.currentTarget.value\n        : evt?.target?.value != null\n        ? evt.target.value\n        : null\n\n      this.checkForNull(this.value)\n\n      const validationTest = new Promise<void>((resolve) => {\n        if (typeof this.delay !== 'undefined') {\n          if (this.timeoutId) {\n            window.clearTimeout(this.timeoutId)\n          }\n          this.timeoutId = window.setTimeout(() => {\n            resolve(this.validateAsync())\n          }, this.delay)\n        } else {\n          resolve(this.validateAsync())\n        }\n      })\n      await validationTest\n\n      await this.validateDependants()\n    }\n\n    this.onChange = this.onChange.bind(this)\n    this.validate = this.validate.bind(this)\n    this.reset = this.reset.bind(this)\n    this.setValue = this.setValue.bind(this)\n    this.clearErrors = this.clearErrors.bind(this)\n\n    makeObservable(this, {\n      isValid: computed,\n      isDirty: computed,\n      isValidating: observable,\n      isDisabled: observable,\n      errors: observable,\n      value: observable,\n      isValidated: observable,\n      onChange: action,\n      setValue: action,\n      setDisabled: action,\n      validate: action,\n      reset: action,\n      clearErrors: action\n    })\n  }\n\n  /**\n   * Wires up dependencies for the field\n   * @internal\n   */\n  initDependencies() {\n    this.dependsOn.forEach((path) => {\n      const formField = this.form.fieldsByPath.get(path)\n      if (formField instanceof Field) {\n        formField._dependants.set(\n          this.path,\n\n          this\n        )\n      } else {\n        throw new Error(`Dependant field \"${path}\" not found`)\n      }\n    })\n  }\n\n  /**\n   * Runs validations on the dependant fields\n   * @returns  results of all validations\n   */\n  protected async validateDependants() {\n    const results = []\n    for (const field of this._dependants.values()) {\n      //field is a dependant field (not this)\n\n      const shouldDisable = await field.maybeDisable(this)\n      runInAction(() => {\n        field.isDisabled = shouldDisable\n      })\n\n      if (!field.isDisabled) {\n        results.push(field.validateAsync(this))\n      }\n    }\n\n    return await Promise.all(results)\n  }\n\n  protected async maybeDisable(dependency: Field<any>) {\n    if (this.shouldDisable) {\n      return await this.shouldDisable(this.value, this, dependency)\n    }\n\n    return this.isDisabled\n  }\n\n  async setDisabled(disable: boolean, cb?: (field: Field<T>) => void) {\n    this.isDisabled = disable\n\n    if (!this.isDisabled) {\n      await this.validateAsync()\n    } else {\n      /* setting \"isValidated\" to true in this case\n         is needed because when the field is disabled it could never be validated\n       */\n      this.isValidated = true\n    }\n    await this.validateDependants()\n\n    cb && cb(this)\n  }\n\n  /**\n   * Gets all the dependant fields\n   */\n  get dependants(): Pick<\n    Field<any>['_dependants'],\n    'entries' | 'forEach' | 'get' | 'keys' | 'size' | 'values'\n  > {\n    return this._dependants\n  }\n\n  /**\n   * Sets value to the field\n   * @param value - value for the field\n   * @param [cb] - callback that is triggerd when the value is set and all validations for the field\n   * and dependant fields are run.\n   */\n  async setValue(value: T, cb?: (field: Field<T>) => void): Promise<void> {\n    this.checkForNull(value)\n    this.value = value\n\n    await this.validateAsync()\n    await this.validateDependants()\n\n    cb && cb(this)\n  }\n\n  /**\n   * Sets data that determines at what location the field is attached to the {@link Form.}\n   * @param name - name of the field\n   * @param path - dot notation of the path e.g. info.location.zip\n   * @param form - reference to the {@link Form}\n   * @internal\n   */\n  setPathData(name: string, path: string, form: Form<any>): void {\n    this.name = name\n    this.path = path\n    this.form = form\n  }\n\n  /**\n   * Run all validations for the field\n   * @param [cb] - callback function that is triggerd after all validations are done\n   */\n  async validate(cb?: (field: Field<T>) => void): Promise<void> {\n    await this.validateAsync()\n    cb && cb(this)\n  }\n\n  /**\n   * Clears all field errors\n   */\n  clearErrors() {\n    this.errors = []\n  }\n\n  /**\n   * Runs validations\n   * @param [dependancy] - Dependency field that has trigged the validation process\n   * @internal\n   */\n  protected async validateAsync(dependancy?: Field<any>): Promise<void> {\n    runInAction(() => {\n      this.isValidating = true\n    })\n    const result = await this.runner.validate(this.value, this, dependancy)\n    runInAction(() => {\n      this.isValidating = false\n\n      this.errors = result.errors ?? []\n      this.isValidated = true\n    })\n  }\n\n  /**\n   * Gets whether field is valid. Field is valid when there are no errors.\n   */\n  get isValid(): boolean {\n    return !this.errors.length\n  }\n\n  /**\n   * Gets whether field is  dirty.\n   * Field is dirty when current value is not equal to the initial value\n   */\n  get isDirty(): boolean {\n    return !equals(this.initialValue, this.value)\n  }\n\n  /**\n   * Resets the field to the initial value, clears all errors, and runs validations\n   * on all dependant fields.\n   */\n  reset(): void {\n    this.value = this.initialValue\n    if (!this.alwaysValid) {\n      this.isValidated = false\n    }\n    this.clearErrors()\n\n    this.validateDependants()\n  }\n\n  /**\n   * Checks if value is null\n   * @param value - value to check\n   */\n  protected checkForNull(value: any): void {\n    if (value == null) {\n      throw new TypeError(`Test value can't be null or undefined`)\n    }\n  }\n}\n","// @ts-expect-error no typings\nimport deepForEach from 'deep-for-each'\nimport { action, computed, makeObservable, observable, runInAction } from 'mobx'\n// @ts-expect-error no typings\nimport setValue from 'set-value'\nimport { Field, FieldResult } from './field'\nimport type React from 'react'\n\n/**\n * Response string that is returned when the form fails validation\n */\nexport const FAILED_VALIDATION_RESPONSE = 'validation_failed'\n\n/**\n * Schema structure with values for the fields in the schema\n */\nexport type SchemaValues<T> = T extends Record<string, any>\n  ? {\n      [key in keyof T]: T[key] extends { value: any }\n        ? T[key]['value' & keyof T[key]]\n        : SchemaValues<T[key]>\n    }\n  : T\n\n/**\n * Schema structure with validation results for the fields in the schema\n */\nexport type SchemaResults<T> = T extends Record<string, any>\n  ? {\n      [key in keyof T]: T[key] extends { value: any }\n        ? FieldResult<T[key]['value' & keyof T[key]]>\n        : SchemaResults<T[key]>\n    }\n  : T\n\nexport type FormConfig = {\n  removeDisabled?: boolean\n  validateBeforeSubmit?: boolean\n}\n\nexport class Form<TSchema = any> {\n  /**\n   * Access to fields that are created from the schema\n   */\n  fields: TSchema\n\n  /**\n   * Determines whether form is in the process of submitting\n   */\n  isSubmitting = false\n\n  /**\n   * Holds last submission error\n   */\n  submitError: unknown = null\n\n  //@internal\n  fieldsByPath: Map<string, Field<any>> = new Map()\n\n  protected lastSavedDataByPath: Map<string, any> = new Map()\n\n  constructor(schema: TSchema, protected config: FormConfig = {}) {\n    // @ts-expect-error - must be initialized with empty object\n    this.fields = {}\n\n    this.config = {\n      removeDisabled: false,\n      validateBeforeSubmit: true,\n      ...this.config\n    }\n\n    this.fieldsByPath = new Map()\n    this.reset = this.reset.bind(this)\n    this.resetToLastSaved = this.resetToLastSaved.bind(this)\n\n    makeObservable<Form<any>, 'lastSavedDataByPath'>(this, {\n      fields: observable,\n      submitError: observable,\n      isSubmitting: observable,\n      lastSavedDataByPath: observable,\n      fieldsByPath: observable,\n      isValid: computed,\n      isValidating: computed,\n      lastSavedData: computed,\n      data: computed,\n      isDirty: computed,\n      handleSubmit: action\n    })\n\n    deepForEach(\n      schema,\n      (formField: Field<any>, key: string, _subject: any, path: string) => {\n        if (!(formField instanceof Field)) {\n          return\n        }\n\n        runInAction(() => {\n          formField.setPathData(key, path, this)\n          setValue(this.fields, path, formField)\n          this.fieldsByPath.set(path, formField)\n        })\n      }\n    )\n\n    for (const field of this.fieldsByPath.values()) {\n      field.initDependencies()\n    }\n  }\n\n  /**\n   * Validates form\n   * @param [cb] - Callback function that is called after the validation is complete\n   */\n  async validate(cb?: (form: Form<TSchema>) => void): Promise<void> {\n    const validations = []\n    for (const field of this.fieldsByPath.values()) {\n      if (!field.isDisabled) {\n        validations.push(field.validate())\n      }\n    }\n    await Promise.allSettled(validations)\n\n    if (cb) {\n      cb(this)\n    }\n  }\n\n  /**\n   * Clears errors for all form fields.\n   */\n  clearErrors() {\n    for (const field of this.fieldsByPath.values()) {\n      field.clearErrors()\n    }\n  }\n\n  /**\n   * Gets form data. This is an object with the same structure as the schema, but it\n   * only holds values, so it could be sent over the wire.\n   */\n  get data(): SchemaValues<TSchema> {\n    const data = {}\n    for (const [path, field] of this.fieldsByPath.entries()) {\n      if (field.isDisabled && this.config.removeDisabled) {\n        continue\n      }\n      setValue(data, path, field.value)\n    }\n\n    return data as SchemaValues<TSchema>\n  }\n\n  /**\n   * Gets whether all fields in the form are valid.\n   */\n  get isValid(): boolean {\n    for (const field of this.fieldsByPath.values()) {\n      if (!field.isDisabled && !field.isValid) {\n        return false\n      }\n    }\n\n    return true\n  }\n\n  /**\n   * Gets whether any of the fields in the form are currently validating.\n   */\n  get isValidating(): boolean {\n    for (const field of this.fieldsByPath.values()) {\n      if (!field.isDisabled && field.isValidating) {\n        return true\n      }\n    }\n\n    return false\n  }\n\n  /**\n   * Gets whether any of the fields in the form are dirty. Field is dirty if the current\n   * value of the is different from the value the field was initialized with.\n   */\n  get isDirty(): boolean {\n    for (const field of this.fieldsByPath.values()) {\n      if (!field.isDisabled && field.isDirty) {\n        return true\n      }\n    }\n\n    return false\n  }\n\n  /**\n   * Gets whether all the fields in the form have been validated at least once.\n   * Don't confuse this propety with {@link Form.isValid}\n   */\n  get isValidated(): boolean {\n    for (const field of this.fieldsByPath.values()) {\n      if (!field.isDisabled && !field.isValidated) {\n        return false\n      }\n    }\n\n    return true\n  }\n\n  /**\n   * After successful form submission, this field holds the data that the form head when it was submitted.\n   *\n   */\n  get lastSavedData(): SchemaValues<TSchema> | null {\n    if (this.lastSavedDataByPath.size === 0) {\n      return null\n    }\n    const data = {}\n    for (const [path, value] of this.lastSavedDataByPath.entries()) {\n      setValue(data, path, value)\n    }\n\n    return data as SchemaValues<TSchema>\n  }\n\n  /**\n   * Resets form fields to their initial values from the schema\n   */\n  reset(): void {\n    for (const field of this.fieldsByPath.values()) {\n      field.reset()\n    }\n  }\n\n  /**\n   * Resets form fields to last successfully saved values\n   */\n  resetToLastSaved(): void {\n    if (this.lastSavedDataByPath.size === 0) {\n      this.reset()\n    } else {\n      for (const [path, value] of this.lastSavedDataByPath.entries()) {\n        const field = this.fieldsByPath.get(path)\n        field!.setValue(value)\n      }\n    }\n  }\n\n  /**\n   * Handles submitting the form\n   * @param submission function that does the actuall submission process. The function will be awaited for, and the result will be returned.\n   * @param [onSuccess] function that is called after a successful submission\n   * @param [onError] function that is called after a unsuccessful submision\n   * @returns object with \"status\" filed that tells if submission was successful or not and \"response\" field with\n   * the response from the submission function\n   */\n  handleSubmit<T>(\n    submission: (form: this) => Promise<T>,\n    onSuccess?: (form: Form<TSchema>, response: T) => void,\n    onError?: (form: Form<TSchema>, response: any) => void\n  ) {\n    return async (event?: React.FormEvent<HTMLFormElement>) => {\n      event && event.preventDefault()\n\n      runInAction(() => {\n        this.isSubmitting = true\n        this.submitError = null\n      })\n\n      if (this.config.validateBeforeSubmit) {\n        await this.validate()\n      }\n\n      if (!this.isValid) {\n        //return fails\n        return {\n          status: 'rejected',\n          response: FAILED_VALIDATION_RESPONSE\n        }\n      }\n      const dataBeforeSave = new Map()\n\n      for (const [path, field] of this.fieldsByPath.entries()) {\n        let value = field.value\n        if (Array.isArray(value)) {\n          value = [...value]\n        } else if (typeof value === 'object') {\n          value = { ...value }\n        }\n\n        dataBeforeSave.set(path, value)\n      }\n\n      try {\n        const response = await submission(this)\n\n        runInAction(() => {\n          this.lastSavedDataByPath = dataBeforeSave\n          onSuccess && onSuccess(this, response)\n        })\n\n        return {\n          status: 'fulfilled',\n          response\n        }\n      } catch (err) {\n        runInAction(() => {\n          this.submitError = err\n          onError && onError(this, err)\n        })\n\n        return {\n          status: 'rejected',\n          response: err\n        }\n      } finally {\n        runInAction(() => {\n          this.isSubmitting = false\n        })\n      }\n    }\n  }\n}\n","import { Field } from './field'\n/**\n * Validation function signature\n * @param value - value to be validated\n * @param {@link Field} that holds the value that is being validated\n * @param {@link Field} dependency field that has changed and triggered this validation\n */\nexport type ValidationFn = (\n  value: any,\n  field: Field<any>,\n  dependency?: Field<any>\n) => boolean | Promise<boolean> | string | Promise<string>\n\nexport function createValidation(\n  fn: ValidationFn,\n  msg: string = Validation.defaultMessage\n) {\n  return new Validation(fn, msg)\n}\n\nexport class Validation {\n  static defaultMessage = 'not valid'\n\n  constructor(public fn: ValidationFn, public msg: string) {}\n}\n","import { Field } from './field'\nimport { Validation } from './validation'\n\n/**\n * Result of running all {@link Validation | Validations }\n */\nexport type RunnerResult = {\n  /**\n   *  error messages\n   */\n  errors: null | string[]\n  /**\n   * value that was validated against\n   */\n  value: any\n}\n\n/**\n * Runner\n * Runs validations and reports results\n */\nexport class Runner {\n  constructor(public validations: Validation[], protected bailEarly = false) {}\n\n  /**\n   * Run validations, it will run all validations, and then return the result.\n   * @param value - value to validate against\n   * @param field - {@link Field} associated with validations\n   * @param [dependency] Dependency {@link Field } that triggered the validation\n   * @returns promise of {@link RunnerResult}\n   */\n  async validate(\n    value: any,\n    field: Field<any>,\n    dependency?: Field<any>\n  ): Promise<RunnerResult> {\n    if (!this.validations.length) {\n      return { errors: null, value }\n    }\n    if (this.bailEarly) {\n      return await this.bailEarlyValidation(value, field, dependency)\n    }\n\n    const errors: string[] = []\n    const validationsToRun = []\n\n    for (const validation of this.validations) {\n      validationsToRun.push(\n        Promise.resolve(validation.fn(value, field, dependency)).then(\n          (result) => {\n            return {\n              result,\n              msg: validation.msg\n            }\n          }\n        )\n      )\n    }\n\n    const resolved = await Promise.all(validationsToRun)\n\n    for (const validation of resolved) {\n      if (typeof validation.result === 'string') {\n        errors.push(validation.result)\n      } else if (!validation.result) {\n        errors.push(validation.msg)\n      }\n    }\n\n    return errors.length ? { errors, value } : { errors: null, value }\n  }\n\n  /**\n   * Runs validations, and returns on first validation that errors out\n   * @param value\n   * @param field\n   * @param [dependency]\n   * @returns early validation\n   */\n  protected async bailEarlyValidation(\n    value: any,\n    field: Field<any>,\n    dependency?: Field<any>\n  ): Promise<RunnerResult> {\n    for (const validation of this.validations) {\n      const result = await validation.fn(value, field, dependency)\n\n      if (typeof result === 'string') {\n        return { errors: [result], value }\n      } else if (!result) {\n        return { errors: [validation.msg], value }\n      }\n    }\n\n    return { errors: null, value }\n  }\n}\n","import { Field } from './field'\nimport { Runner } from './runner'\nimport { Validation } from './validation'\n\n/**\n * Data for the {@link createField} factory\n * @typeparam T - type of value for the {@link Field}\n *\n * @example Depends on\n * ```\n * const schema = {\n *   info:{\n *     name:{}\n *     nick:{\n *       dependsOn:'info.name'\n *     }\n *   }\n * }\n * ```\n */\nexport type CreateFieldData<T> = {\n  /**\n   * value of the field\n   */\n  value: T\n\n  /**\n   * array of {@link Validation} to be used for validating the field\n   */\n  validations?: Validation[] | Validation\n\n  /**\n   * function that can intercept {@link Field.onChange} and return a custom value\n   */\n  parseValue?: (data: any, field: Field<T>) => any\n\n  /**\n   * delay for running the validations\n   */\n  delay?: number\n\n  /**\n   * return as soon as first validation returns error\n   */\n  bailEarly?: boolean\n\n  /**\n   * path to fields that current field should depend on\n   */\n  dependsOn?: string | string[]\n\n  shouldDisable?: (\n    value: any,\n    field: Field<any>,\n    dependency?: Field<any>\n  ) => boolean | Promise<boolean>\n  /**\n   * if field is disabled\n   */\n  disabled?: boolean\n}\n\n/**\n * Factory function that creates the @class Field\n * @param data - field data\n * @returns instance of {@link Field}\n */\nexport function createField<T>(data: CreateFieldData<T>) {\n  let alwaysValid = false\n  if (data.validations) {\n    if (!Array.isArray(data.validations)) {\n      data.validations = [data.validations]\n    }\n  } else {\n    data.validations = []\n    alwaysValid = true\n  }\n\n  const runner = new Runner(data.validations, data.bailEarly)\n\n  data.dependsOn = data.dependsOn\n    ? Array.isArray(data.dependsOn)\n      ? [...data.dependsOn]\n      : [data.dependsOn]\n    : []\n\n  const field = new Field(\n    runner,\n    data.value,\n    alwaysValid,\n    data.parseValue,\n    data.delay,\n    data.dependsOn,\n    data.disabled,\n    data.shouldDisable\n  )\n\n  return field\n}\n"],"names":["equals","a","b","Date","getTime","prototype","keys","Object","length","every","k","getForm","field","form","Field","constructor","runner","value","alwaysValid","parseValue","delay","dependsOn","isDisabled","shouldDisable","isValidating","isValidated","errors","name","path","initialValue","onChange","timeoutId","_dependants","Map","this","async","evt","_this","currentTarget","target","checkForNull","validationTest","Promise","resolve","window","clearTimeout","setTimeout","validateAsync","validateDependants","bind","validate","reset","setValue","clearErrors","makeObservable","isValid","computed","isDirty","observable","action","setDisabled","initDependencies","forEach","formField","fieldsByPath","get","Error","set","results","values","maybeDisable","runInAction","push","all","dependency","disable","cb","dependants","setPathData","dependancy","result","TypeError","FAILED_VALIDATION_RESPONSE","Form","schema","config","fields","isSubmitting","submitError","lastSavedDataByPath","removeDisabled","validateBeforeSubmit","resetToLastSaved","lastSavedData","data","handleSubmit","deepForEach","key","_subject","validations","allSettled","entries","size","submission","onSuccess","onError","event","preventDefault","status","response","dataBeforeSave","Array","isArray","err","createValidation","fn","msg","Validation","defaultMessage","Runner","bailEarly","bailEarlyValidation","validationsToRun","validation","then","resolved","createField","disabled"],"mappings":"gXAOgBA,EAAOC,EAAQC,GAC7B,GAAID,IAAMC,EAAG,SACb,GAAID,aAAaE,MAAQD,aAAaC,KAAM,OAAOF,EAAEG,YAAcF,EAAEE,UACrE,IAAKH,IAAMC,GAAmB,iBAAND,GAA+B,iBAANC,EAC/C,OAAOD,IAAMC,EACf,GAAID,EAAEI,YAAcH,EAAEG,UAAW,SACjC,MAAMC,EAAOC,OAAOD,KAAKL,GACzB,OAAIK,EAAKE,SAAWD,OAAOD,KAAKJ,GAAGM,QAE5BF,EAAKG,MAAOC,GAAMV,EAAOC,EAAES,GAAIR,EAAEQ,cAO1BC,EAAWC,GACzB,OAAOA,EAAMC,WCQFC,EA8DXC,YACSC,EACAC,EACGC,EACAC,EACHC,EACGC,EAAsB,GACzBC,GAAa,EACVC,mBAPHP,mBACAC,kBACGC,wBACAC,uBACHC,kBACGC,sBACHC,uBACGC,0BAlEZC,cAAe,OAMfC,aAAc,OAKdC,OAAmB,QAKnBb,iBAKAc,iBAKAC,iBAKAC,yBAMAC,qBAKUC,sBAKAC,YAAuC,IAAIC,IAY5CC,YAAAlB,EACAkB,WAAAjB,EACGiB,iBAAAhB,EACAgB,gBAAAf,EACHe,WAAAd,EACGc,eAAAb,EACHa,gBAAAZ,EACGY,mBAAAX,EAMVW,KAAKL,aAAeK,KAAKjB,MAErBiB,KAAKhB,cACPgB,KAAKT,aAAc,GAGrBS,KAAKJ,SAAWK,eAAOC,WACrB,GAAIC,EAAKf,WAAY,OACrBe,EAAKpB,MAAQoB,EAAKlB,WACdkB,EAAKlB,WAAWiB,EAAKC,GACQ,aAA7BD,YAAAA,EAAKE,wBAAerB,OACpBmB,EAAIE,cAAcrB,MACI,aAAtBmB,YAAAA,EAAKG,iBAAQtB,OACbmB,EAAIG,OAAOtB,MACX,KAEJoB,EAAKG,aAAaH,EAAKpB,OAEvB,MAAMwB,EAAiB,IAAIC,QAAeC,SACd,IAAfN,EAAKjB,OACViB,EAAKN,WACPa,OAAOC,aAAaR,EAAKN,WAE3BM,EAAKN,UAAYa,OAAOE,WAAW,KACjCH,EAAQN,EAAKU,kBACZV,EAAKjB,QAERuB,EAAQN,EAAKU,yBAGXN,QAEAJ,EAAKW,sBAGbd,KAAKJ,SAAWI,KAAKJ,SAASmB,KAAKf,MACnCA,KAAKgB,SAAWhB,KAAKgB,SAASD,KAAKf,MACnCA,KAAKiB,MAAQjB,KAAKiB,MAAMF,KAAKf,MAC7BA,KAAKkB,SAAWlB,KAAKkB,SAASH,KAAKf,MACnCA,KAAKmB,YAAcnB,KAAKmB,YAAYJ,KAAKf,MAEzCoB,EAAepB,KAAM,CACnBqB,QAASC,EACTC,QAASD,EACThC,aAAckC,EACdpC,WAAYoC,EACZhC,OAAQgC,EACRzC,MAAOyC,EACPjC,YAAaiC,EACb5B,SAAU6B,EACVP,SAAUO,EACVC,YAAaD,EACbT,SAAUS,EACVR,MAAOQ,EACPN,YAAaM,IAQjBE,mBACE3B,KAAKb,UAAUyC,QAASlC,IACtB,MAAMmC,EAAY7B,KAAKrB,KAAKmD,aAAaC,IAAIrC,GAC7C,KAAImC,aAAqBjD,GAOvB,UAAUoD,0BAA0BtC,gBANpCmC,EAAU/B,YAAYmC,IACpBjC,KAAKN,KAELM,QAY0BC,2BAChC,MAAMiC,EAAU,GAChB,IAAK,MAAMxD,UAAcoB,YAAYqC,SAAU,CAG7C,MAAM9C,QAAsBX,EAAM0D,aAAapC,MAC/CqC,EAAY,KACV3D,EAAMU,WAAaC,IAGhBX,EAAMU,YACT8C,EAAQI,KAAK5D,EAAMmC,cAAcb,OAIrC,aAAaQ,QAAQ+B,IAAIL,GAGCjC,mBAACuC,GAC3B,OAAIxC,KAAKX,yBACWA,cAAcW,KAAKjB,MAAOiB,KAAMwC,QAGxCpD,WAGGa,kBAACwC,EAAkBC,GAClC1C,KAAKZ,WAAaqD,EAEbzC,KAAKZ,WAMRY,KAAKT,aAAc,aALRsB,2BAOFC,qBAEX4B,GAAMA,EAAG1C,MAMP2C,iBAIF,YAAY7C,YASAG,eAAClB,EAAU2D,GACvB1C,KAAKM,aAAavB,GAClBiB,KAAKjB,MAAQA,aAEF8B,2BACAC,qBAEX4B,GAAMA,EAAG1C,MAUX4C,YAAYnD,EAAcC,EAAcf,GACtCqB,KAAKP,KAAOA,EACZO,KAAKN,KAAOA,EACZM,KAAKrB,KAAOA,EAOAsB,eAACyC,cACF7B,gBACX6B,GAAMA,EAAG1C,MAMXmB,cACEnB,KAAKR,OAAS,GAQaS,oBAAC4C,GAC5BR,EAAY,KACVrC,KAAKV,cAAe,IAEtB,MAAMwD,aAAoBhE,OAAOkC,SAAShB,KAAKjB,MAAOiB,KAAM6C,GAC5DR,EAAY,WACVrC,KAAKV,cAAe,EAEpBU,KAAKR,gBAASsD,EAAOtD,UAAU,GAC/BQ,KAAKT,aAAc,IAOnB8B,cACF,OAAQrB,KAAKR,OAAOlB,OAOlBiD,cACF,OAAQzD,EAAOkC,KAAKL,aAAcK,KAAKjB,OAOzCkC,QACEjB,KAAKjB,MAAQiB,KAAKL,aACbK,KAAKhB,cACRgB,KAAKT,aAAc,GAErBS,KAAKmB,cAELnB,KAAKc,qBAOGR,aAAavB,GACrB,GAAa,MAATA,EACF,UAAUgE,oDCxUHC,MAAAA,EAA6B,0BA6B7BC,EAqBXpE,YAAYqE,EAA2BC,EAAqB,SAArBA,mBAjBvCC,mBAKAC,cAAe,OAKfC,YAAuB,UAGvBxB,aAAwC,IAAI/B,SAElCwD,oBAAwC,IAAIxD,IAEfC,YAAAmD,EAErCnD,KAAKoD,OAAS,GAEdpD,KAAKmD,UACHK,gBAAgB,EAChBC,sBAAsB,GACnBzD,KAAKmD,QAGVnD,KAAK8B,aAAe,IAAI/B,IACxBC,KAAKiB,MAAQjB,KAAKiB,MAAMF,KAAKf,MAC7BA,KAAK0D,iBAAmB1D,KAAK0D,iBAAiB3C,KAAKf,MAEnDoB,EAAiDpB,KAAM,CACrDoD,OAAQ5B,EACR8B,YAAa9B,EACb6B,aAAc7B,EACd+B,oBAAqB/B,EACrBM,aAAcN,EACdH,QAASC,EACThC,aAAcgC,EACdqC,cAAerC,EACfsC,KAAMtC,EACNC,QAASD,EACTuC,aAAcpC,IAGhBqC,EACEZ,EACA,CAACrB,EAAuBkC,EAAaC,EAAetE,KAC5CmC,aAAqBjD,GAI3ByD,EAAY,KACVR,EAAUe,YAAYmB,EAAKrE,EAAMM,MACjCkB,EAASlB,KAAKoD,OAAQ1D,EAAMmC,GAC5B7B,KAAK8B,aAAaG,IAAIvC,EAAMmC,OAKlC,IAAK,MAAMnD,UAAcoD,aAAaK,SACpCzD,EAAMiD,mBAQI1B,eAACyC,GACb,MAAMuB,EAAc,GACpB,IAAK,MAAMvF,UAAcoD,aAAaK,SAC/BzD,EAAMU,YACT6E,EAAY3B,KAAK5D,EAAMsC,kBAGrBR,QAAQ0D,WAAWD,GAErBvB,GACFA,EAAG1C,MAOPmB,cACE,IAAK,MAAMzC,UAAcoD,aAAaK,SACpCzD,EAAMyC,cAQNyC,WACF,MAAMA,EAAO,GACb,IAAK,MAAOlE,EAAMhB,UAAeoD,aAAaqC,UACxCzF,EAAMU,YAAcY,KAAKmD,OAAOK,gBAGpCtC,EAAS0C,EAAMlE,EAAMhB,EAAMK,OAG7B,OAAO6E,EAMLvC,cACF,IAAK,MAAM3C,UAAcoD,aAAaK,SACpC,IAAKzD,EAAMU,aAAeV,EAAM2C,QAC9B,SAIJ,SAME/B,mBACF,IAAK,MAAMZ,UAAcoD,aAAaK,SACpC,IAAKzD,EAAMU,YAAcV,EAAMY,aAC7B,SAIJ,SAOEiC,cACF,IAAK,MAAM7C,UAAcoD,aAAaK,SACpC,IAAKzD,EAAMU,YAAcV,EAAM6C,QAC7B,SAIJ,SAOEhC,kBACF,IAAK,MAAMb,UAAcoD,aAAaK,SACpC,IAAKzD,EAAMU,aAAeV,EAAMa,YAC9B,SAIJ,SAOEoE,oBACF,GAAsC,IAAlC3D,KAAKuD,oBAAoBa,KAC3B,YAEF,MAAMR,EAAO,GACb,IAAK,MAAOlE,EAAMX,UAAewE,oBAAoBY,UACnDjD,EAAS0C,EAAMlE,EAAMX,GAGvB,OAAO6E,EAMT3C,QACE,IAAK,MAAMvC,UAAcoD,aAAaK,SACpCzD,EAAMuC,QAOVyC,mBACE,GAAsC,IAAlC1D,KAAKuD,oBAAoBa,KAC3BpE,KAAKiB,aAEL,IAAK,MAAOvB,EAAMX,UAAewE,oBAAoBY,UACrCnE,KAAK8B,aAAaC,IAAIrC,GAC7BwB,SAASnC,GAatB8E,aACEQ,EACAC,EACAC,cAEA,sBAAcC,GAYZ,GAXAA,GAASA,EAAMC,iBAEfpC,EAAY,KACVlC,EAAKkD,cAAe,EACpBlD,EAAKmD,YAAc,OAGjBnD,EAAKgD,OAAOM,4BACRtD,EAAKa,YAGRb,EAAKkB,QAER,MAAO,CACLqD,OAAQ,WACRC,SAvQgC,qBA0QpC,MAAMC,EAAiB,IAAI7E,IAE3B,IAAK,MAAOL,EAAMhB,KAAUyB,EAAK2B,aAAaqC,UAAW,CACvD,IAAIpF,EAAQL,EAAMK,MACd8F,MAAMC,QAAQ/F,GAChBA,EAAQ,IAAIA,GACc,iBAAVA,IAChBA,OAAaA,IAGf6F,EAAe3C,IAAIvC,EAAMX,GAG3B,IACE,MAAM4F,QAAiBN,EAAWlE,GAOlC,OALAkC,EAAY,KACVlC,EAAKoD,oBAAsBqB,EAC3BN,GAAaA,EAAUnE,EAAMwE,KAGxB,CACLD,OAAQ,YACRC,SAAAA,GAEF,MAAOI,GAMP,OALA1C,EAAY,KACVlC,EAAKmD,YAAcyB,EACnBR,GAAWA,EAAQpE,EAAM4E,KAGpB,CACLL,OAAQ,WACRC,SAAUI,GApBd,QAuBE1C,EAAY,KACVlC,EAAKkD,cAAe,gBC7Sd2B,EACdC,EACAC,EAAcC,EAAWC,gBAEzB,WAAWD,EAAWF,EAAIC,SAGfC,EAGXtG,YAAmBoG,EAAyBC,QAAzBD,eAAyBC,WAAzBlF,QAAAiF,EAAyBjF,SAAAkF,GAHjCC,EACJC,eAAiB,kBCAbC,EACXxG,YAAmBoF,EAAqCqB,GAAY,QAAjDrB,wBAAqCqB,iBAArCtF,iBAAAiE,EAAqCjE,eAAAsF,EAS1CrF,eACZlB,EACAL,EACA8D,GAEA,IAAKxC,KAAKiE,YAAY3F,OACpB,MAAO,CAAEkB,OAAQ,KAAMT,MAAAA,GAEzB,GAAIiB,KAAKsF,UACP,kBAAkBC,oBAAoBxG,EAAOL,EAAO8D,GAGtD,MAAMhD,EAAmB,GACnBgG,EAAmB,GAEzB,IAAK,MAAMC,UAAmBxB,YAC5BuB,EAAiBlD,KACf9B,QAAQC,QAAQgF,EAAWR,GAAGlG,EAAOL,EAAO8D,IAAakD,KACtD5C,IACQ,CACLA,OAAAA,EACAoC,IAAKO,EAAWP,QAO1B,MAAMS,QAAiBnF,QAAQ+B,IAAIiD,GAEnC,IAAK,MAAMC,KAAcE,EACU,iBAAtBF,EAAW3C,OACpBtD,EAAO8C,KAAKmD,EAAW3C,QACb2C,EAAW3C,QACrBtD,EAAO8C,KAAKmD,EAAWP,KAI3B,OAAO1F,EAAOlB,OAAS,CAAEkB,OAAAA,EAAQT,MAAAA,GAAU,CAAES,OAAQ,KAAMT,MAAAA,GAU1BkB,0BACjClB,EACAL,EACA8D,GAEA,IAAK,MAAMiD,UAAmBxB,YAAa,CACzC,MAAMnB,QAAe2C,EAAWR,GAAGlG,EAAOL,EAAO8D,GAEjD,GAAsB,iBAAXM,EACT,MAAO,CAAEtD,OAAQ,CAACsD,GAAS/D,MAAAA,OACjB+D,EACV,MAAO,CAAEtD,OAAQ,CAACiG,EAAWP,KAAMnG,MAAAA,GAIvC,MAAO,CAAES,OAAQ,KAAMT,MAAAA,aC3BX6G,EAAehC,GAC7B,IAAI5E,GAAc,EACd4E,EAAKK,YACFY,MAAMC,QAAQlB,EAAKK,eACtBL,EAAKK,YAAc,CAACL,EAAKK,eAG3BL,EAAKK,YAAc,GACnBjF,GAAc,GAGhB,MAAMF,EAAS,IAAIuG,EAAOzB,EAAKK,YAAaL,EAAK0B,WAmBjD,OAjBA1B,EAAKzE,UAAYyE,EAAKzE,UAClB0F,MAAMC,QAAQlB,EAAKzE,WACjB,IAAIyE,EAAKzE,WACT,CAACyE,EAAKzE,WACR,GAEU,IAAIP,EAChBE,EACA8E,EAAK7E,MACLC,EACA4E,EAAK3E,WACL2E,EAAK1E,MACL0E,EAAKzE,UACLyE,EAAKiC,SACLjC,EAAKvE"}