{"version":3,"file":"metaHelper.cjs","sources":["../../src/metaHelper.ts"],"sourcesContent":["import type {\n  FormApi,\n  FormAsyncValidateOrFn,\n  FormValidateOrFn,\n} from './FormApi'\nimport type { AnyFieldMeta } from './FieldApi'\nimport type { DeepKeys } from './util-types'\n\ntype ValueFieldMode = 'insert' | 'remove' | 'swap' | 'move'\n\nexport const defaultFieldMeta: AnyFieldMeta = {\n  isValidating: false,\n  isTouched: false,\n  isBlurred: false,\n  isDirty: false,\n  isPristine: true,\n  isValid: true,\n  isDefaultValue: true,\n  errors: [],\n  errorMap: {},\n  errorSourceMap: {},\n  _arrayVersion: 0,\n}\n\nexport function metaHelper<\n  TFormData,\n  TOnMount extends undefined | FormValidateOrFn<TFormData>,\n  TOnChange extends undefined | FormValidateOrFn<TFormData>,\n  TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n  TOnBlur extends undefined | FormValidateOrFn<TFormData>,\n  TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n  TOnSubmit extends undefined | FormValidateOrFn<TFormData>,\n  TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n  TOnDynamic extends undefined | FormValidateOrFn<TFormData>,\n  TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,\n  TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,\n  TSubmitMeta = never,\n>(\n  formApi: FormApi<\n    TFormData,\n    TOnMount,\n    TOnChange,\n    TOnChangeAsync,\n    TOnBlur,\n    TOnBlurAsync,\n    TOnSubmit,\n    TOnSubmitAsync,\n    TOnDynamic,\n    TOnDynamicAsync,\n    TOnServer,\n    TSubmitMeta\n  >,\n) {\n  /**\n   * Bump the `_arrayVersion` counter on the array field's meta. This\n   * provides a cheap, structural signal that adapters can subscribe to in\n   * order to trigger re-renders when the array is mutated in ways that\n   * `length` alone cannot detect (e.g. swaps and moves).\n   */\n  function bumpArrayVersion(field: DeepKeys<TFormData>) {\n    const currentMeta = formApi.getFieldMeta(field) ?? defaultFieldMeta\n    formApi.setFieldMeta(field, {\n      ...currentMeta,\n      _arrayVersion: (currentMeta._arrayVersion || 0) + 1,\n    })\n  }\n\n  /**\n   * Handle the meta shift caused from moving a field from one index to another.\n   */\n  function handleArrayMove(\n    field: DeepKeys<TFormData>,\n    fromIndex: number,\n    toIndex: number,\n  ) {\n    bumpArrayVersion(field)\n    const affectedFields = getAffectedFields(field, fromIndex, 'move', toIndex)\n\n    const startIndex = Math.min(fromIndex, toIndex)\n    const endIndex = Math.max(fromIndex, toIndex)\n    for (let i = startIndex; i <= endIndex; i++) {\n      affectedFields.push(getFieldPath(field, i))\n    }\n\n    // Store the original field meta that will be reapplied at the destination index\n    const fromFields = Object.keys(formApi.fieldInfo).reduce(\n      (fieldMap, fieldKey) => {\n        if (fieldKey.startsWith(getFieldPath(field, fromIndex))) {\n          fieldMap.set(\n            fieldKey as DeepKeys<TFormData>,\n            formApi.getFieldMeta(fieldKey as DeepKeys<TFormData>),\n          )\n        }\n        return fieldMap\n      },\n      new Map<DeepKeys<TFormData>, AnyFieldMeta | undefined>(),\n    )\n\n    shiftMeta(affectedFields, fromIndex < toIndex ? 'up' : 'down')\n\n    // Reapply the stored field meta at the destination index\n    Object.keys(formApi.fieldInfo)\n      .filter((fieldKey) => fieldKey.startsWith(getFieldPath(field, toIndex)))\n      .forEach((fieldKey) => {\n        const fromKey = fieldKey.replace(\n          getFieldPath(field, toIndex),\n          getFieldPath(field, fromIndex),\n        ) as DeepKeys<TFormData>\n\n        const fromMeta = fromFields.get(fromKey)\n        if (fromMeta) {\n          formApi.setFieldMeta(fieldKey as DeepKeys<TFormData>, fromMeta)\n        }\n      })\n  }\n\n  /**\n   * Handle the meta shift from removing a field at the specified index.\n   */\n  function handleArrayRemove(field: DeepKeys<TFormData>, index: number) {\n    bumpArrayVersion(field)\n    const affectedFields = getAffectedFields(field, index, 'remove')\n\n    shiftMeta(affectedFields, 'up')\n  }\n\n  /**\n   * Handle the meta shift from swapping two fields at the specified indeces.\n   */\n  function handleArraySwap(\n    field: DeepKeys<TFormData>,\n    index: number,\n    secondIndex: number,\n  ) {\n    bumpArrayVersion(field)\n    const affectedFields = getAffectedFields(field, index, 'swap', secondIndex)\n\n    affectedFields.forEach((fieldKey) => {\n      if (!fieldKey.toString().startsWith(getFieldPath(field, index))) {\n        return\n      }\n\n      const swappedKey = fieldKey\n        .toString()\n        .replace(\n          getFieldPath(field, index),\n          getFieldPath(field, secondIndex),\n        ) as DeepKeys<TFormData>\n\n      const [meta1, meta2] = [\n        formApi.getFieldMeta(fieldKey),\n        formApi.getFieldMeta(swappedKey),\n      ]\n\n      if (meta1) formApi.setFieldMeta(swappedKey, meta1)\n      if (meta2) formApi.setFieldMeta(fieldKey, meta2)\n    })\n  }\n\n  /**\n   * Handle the meta shift from inserting a field at the specified index.\n   */\n  function handleArrayInsert(field: DeepKeys<TFormData>, insertIndex: number) {\n    bumpArrayVersion(field)\n    const affectedFields = getAffectedFields(field, insertIndex, 'insert')\n\n    shiftMeta(affectedFields, 'down')\n\n    affectedFields.forEach((fieldKey) => {\n      if (fieldKey.toString().startsWith(getFieldPath(field, insertIndex))) {\n        formApi.setFieldMeta(fieldKey, getEmptyFieldMeta())\n      }\n    })\n  }\n\n  function getFieldPath(\n    field: DeepKeys<TFormData>,\n    index: number,\n  ): DeepKeys<TFormData> {\n    return `${field}[${index}]` as DeepKeys<TFormData>\n  }\n\n  function getAffectedFields(\n    field: DeepKeys<TFormData>,\n    index: number,\n    mode: ValueFieldMode,\n    secondIndex?: number,\n  ): DeepKeys<TFormData>[] {\n    const affectedFieldKeys = [getFieldPath(field, index)]\n\n    switch (mode) {\n      case 'swap':\n        affectedFieldKeys.push(getFieldPath(field, secondIndex!))\n        break\n      case 'move': {\n        const [startIndex, endIndex] = [\n          Math.min(index, secondIndex!),\n          Math.max(index, secondIndex!),\n        ]\n        for (let i = startIndex; i <= endIndex; i++) {\n          affectedFieldKeys.push(getFieldPath(field, i))\n        }\n        break\n      }\n      default: {\n        const currentValue = formApi.getFieldValue(field)\n        const fieldItems = Array.isArray(currentValue)\n          ? (currentValue as Array<unknown>).length\n          : 0\n        for (let i = index + 1; i < fieldItems; i++) {\n          affectedFieldKeys.push(getFieldPath(field, i))\n        }\n        break\n      }\n    }\n\n    return Object.keys(formApi.fieldInfo).filter((fieldKey) =>\n      affectedFieldKeys.some((key) => fieldKey.startsWith(key)),\n    ) as DeepKeys<TFormData>[]\n  }\n\n  function updateIndex(\n    fieldKey: string,\n    direction: 'up' | 'down',\n  ): DeepKeys<TFormData> {\n    return fieldKey.replace(/\\[(\\d+)\\]/, (_, num) => {\n      const currIndex = parseInt(num, 10)\n      const newIndex =\n        direction === 'up' ? currIndex + 1 : Math.max(0, currIndex - 1)\n      return `[${newIndex}]`\n    }) as DeepKeys<TFormData>\n  }\n\n  function shiftMeta(fields: DeepKeys<TFormData>[], direction: 'up' | 'down') {\n    const sortedFields = direction === 'up' ? fields : [...fields].reverse()\n\n    sortedFields.forEach((fieldKey) => {\n      const nextFieldKey = updateIndex(fieldKey.toString(), direction)\n      const nextFieldMeta = formApi.getFieldMeta(nextFieldKey)\n      if (nextFieldMeta) {\n        formApi.setFieldMeta(fieldKey, nextFieldMeta)\n      } else {\n        formApi.setFieldMeta(fieldKey, getEmptyFieldMeta())\n      }\n    })\n  }\n\n  const getEmptyFieldMeta = (): AnyFieldMeta => defaultFieldMeta\n\n  return {\n    bumpArrayVersion,\n    handleArrayMove,\n    handleArrayRemove,\n    handleArraySwap,\n    handleArrayInsert,\n  }\n}\n"],"names":[],"mappings":";;AAUO,MAAM,mBAAiC;AAAA,EAC5C,cAAc;AAAA,EACd,WAAW;AAAA,EACX,WAAW;AAAA,EACX,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,QAAQ,CAAA;AAAA,EACR,UAAU,CAAA;AAAA,EACV,gBAAgB,CAAA;AAAA,EAChB,eAAe;AACjB;AAEO,SAAS,WAcd,SAcA;AAOA,WAAS,iBAAiB,OAA4B;AACpD,UAAM,cAAc,QAAQ,aAAa,KAAK,KAAK;AACnD,YAAQ,aAAa,OAAO;AAAA,MAC1B,GAAG;AAAA,MACH,gBAAgB,YAAY,iBAAiB,KAAK;AAAA,IAAA,CACnD;AAAA,EACH;AAKA,WAAS,gBACP,OACA,WACA,SACA;AACA,qBAAiB,KAAK;AACtB,UAAM,iBAAiB,kBAAkB,OAAO,WAAW,QAAQ,OAAO;AAE1E,UAAM,aAAa,KAAK,IAAI,WAAW,OAAO;AAC9C,UAAM,WAAW,KAAK,IAAI,WAAW,OAAO;AAC5C,aAAS,IAAI,YAAY,KAAK,UAAU,KAAK;AAC3C,qBAAe,KAAK,aAAa,OAAO,CAAC,CAAC;AAAA,IAC5C;AAGA,UAAM,aAAa,OAAO,KAAK,QAAQ,SAAS,EAAE;AAAA,MAChD,CAAC,UAAU,aAAa;AACtB,YAAI,SAAS,WAAW,aAAa,OAAO,SAAS,CAAC,GAAG;AACvD,mBAAS;AAAA,YACP;AAAA,YACA,QAAQ,aAAa,QAA+B;AAAA,UAAA;AAAA,QAExD;AACA,eAAO;AAAA,MACT;AAAA,0BACI,IAAA;AAAA,IAAmD;AAGzD,cAAU,gBAAgB,YAAY,UAAU,OAAO,MAAM;AAG7D,WAAO,KAAK,QAAQ,SAAS,EAC1B,OAAO,CAAC,aAAa,SAAS,WAAW,aAAa,OAAO,OAAO,CAAC,CAAC,EACtE,QAAQ,CAAC,aAAa;AACrB,YAAM,UAAU,SAAS;AAAA,QACvB,aAAa,OAAO,OAAO;AAAA,QAC3B,aAAa,OAAO,SAAS;AAAA,MAAA;AAG/B,YAAM,WAAW,WAAW,IAAI,OAAO;AACvC,UAAI,UAAU;AACZ,gBAAQ,aAAa,UAAiC,QAAQ;AAAA,MAChE;AAAA,IACF,CAAC;AAAA,EACL;AAKA,WAAS,kBAAkB,OAA4B,OAAe;AACpE,qBAAiB,KAAK;AACtB,UAAM,iBAAiB,kBAAkB,OAAO,OAAO,QAAQ;AAE/D,cAAU,gBAAgB,IAAI;AAAA,EAChC;AAKA,WAAS,gBACP,OACA,OACA,aACA;AACA,qBAAiB,KAAK;AACtB,UAAM,iBAAiB,kBAAkB,OAAO,OAAO,QAAQ,WAAW;AAE1E,mBAAe,QAAQ,CAAC,aAAa;AACnC,UAAI,CAAC,SAAS,WAAW,WAAW,aAAa,OAAO,KAAK,CAAC,GAAG;AAC/D;AAAA,MACF;AAEA,YAAM,aAAa,SAChB,SAAA,EACA;AAAA,QACC,aAAa,OAAO,KAAK;AAAA,QACzB,aAAa,OAAO,WAAW;AAAA,MAAA;AAGnC,YAAM,CAAC,OAAO,KAAK,IAAI;AAAA,QACrB,QAAQ,aAAa,QAAQ;AAAA,QAC7B,QAAQ,aAAa,UAAU;AAAA,MAAA;AAGjC,UAAI,MAAO,SAAQ,aAAa,YAAY,KAAK;AACjD,UAAI,MAAO,SAAQ,aAAa,UAAU,KAAK;AAAA,IACjD,CAAC;AAAA,EACH;AAKA,WAAS,kBAAkB,OAA4B,aAAqB;AAC1E,qBAAiB,KAAK;AACtB,UAAM,iBAAiB,kBAAkB,OAAO,aAAa,QAAQ;AAErE,cAAU,gBAAgB,MAAM;AAEhC,mBAAe,QAAQ,CAAC,aAAa;AACnC,UAAI,SAAS,WAAW,WAAW,aAAa,OAAO,WAAW,CAAC,GAAG;AACpE,gBAAQ,aAAa,UAAU,mBAAmB;AAAA,MACpD;AAAA,IACF,CAAC;AAAA,EACH;AAEA,WAAS,aACP,OACA,OACqB;AACrB,WAAO,GAAG,KAAK,IAAI,KAAK;AAAA,EAC1B;AAEA,WAAS,kBACP,OACA,OACA,MACA,aACuB;AACvB,UAAM,oBAAoB,CAAC,aAAa,OAAO,KAAK,CAAC;AAErD,YAAQ,MAAA;AAAA,MACN,KAAK;AACH,0BAAkB,KAAK,aAAa,OAAO,WAAY,CAAC;AACxD;AAAA,MACF,KAAK,QAAQ;AACX,cAAM,CAAC,YAAY,QAAQ,IAAI;AAAA,UAC7B,KAAK,IAAI,OAAO,WAAY;AAAA,UAC5B,KAAK,IAAI,OAAO,WAAY;AAAA,QAAA;AAE9B,iBAAS,IAAI,YAAY,KAAK,UAAU,KAAK;AAC3C,4BAAkB,KAAK,aAAa,OAAO,CAAC,CAAC;AAAA,QAC/C;AACA;AAAA,MACF;AAAA,MACA,SAAS;AACP,cAAM,eAAe,QAAQ,cAAc,KAAK;AAChD,cAAM,aAAa,MAAM,QAAQ,YAAY,IACxC,aAAgC,SACjC;AACJ,iBAAS,IAAI,QAAQ,GAAG,IAAI,YAAY,KAAK;AAC3C,4BAAkB,KAAK,aAAa,OAAO,CAAC,CAAC;AAAA,QAC/C;AACA;AAAA,MACF;AAAA,IAAA;AAGF,WAAO,OAAO,KAAK,QAAQ,SAAS,EAAE;AAAA,MAAO,CAAC,aAC5C,kBAAkB,KAAK,CAAC,QAAQ,SAAS,WAAW,GAAG,CAAC;AAAA,IAAA;AAAA,EAE5D;AAEA,WAAS,YACP,UACA,WACqB;AACrB,WAAO,SAAS,QAAQ,aAAa,CAAC,GAAG,QAAQ;AAC/C,YAAM,YAAY,SAAS,KAAK,EAAE;AAClC,YAAM,WACJ,cAAc,OAAO,YAAY,IAAI,KAAK,IAAI,GAAG,YAAY,CAAC;AAChE,aAAO,IAAI,QAAQ;AAAA,IACrB,CAAC;AAAA,EACH;AAEA,WAAS,UAAU,QAA+B,WAA0B;AAC1E,UAAM,eAAe,cAAc,OAAO,SAAS,CAAC,GAAG,MAAM,EAAE,QAAA;AAE/D,iBAAa,QAAQ,CAAC,aAAa;AACjC,YAAM,eAAe,YAAY,SAAS,SAAA,GAAY,SAAS;AAC/D,YAAM,gBAAgB,QAAQ,aAAa,YAAY;AACvD,UAAI,eAAe;AACjB,gBAAQ,aAAa,UAAU,aAAa;AAAA,MAC9C,OAAO;AACL,gBAAQ,aAAa,UAAU,mBAAmB;AAAA,MACpD;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,oBAAoB,MAAoB;AAE9C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;;;"}