{"version":3,"file":"registerWithMask.cjs","sources":["../../../../../src/utilities/formatters/util/registerWithMask.ts"],"sourcesContent":["import type { ChangeEvent, KeyboardEventHandler } from \"react\";\nimport type {\n    FieldValues,\n    Path,\n    PathValue,\n    RegisterOptions,\n    UseFormRegisterReturn,\n    UseFormReturn,\n} from \"react-hook-form\";\nimport { formatDateString } from \"../date/formatDate.js\";\nimport { formatFodselsnummer } from \"../fodselsnummer/formatFodselsnummer.js\";\nimport { formatKontonummer } from \"../kontonummer/formatKontonummer.js\";\nimport { formatKortnummer } from \"../kortnummer/formatKortnummer.js\";\nimport { formatOrganisasjonsnummer } from \"../organisasjonsnummer/formatOrganisasjonsnummer.js\";\nimport { formatTelefonnummer } from \"../telefonnummer/formatTelefonnummer.js\";\nimport { formatNumber } from \"./formatNumber.js\";\n\nconst formatters = {\n    date: formatDateString,\n    fodselsnummer: formatFodselsnummer,\n    kortnummer: formatKortnummer,\n    kontonummer: formatKontonummer,\n    telefonnummer: formatTelefonnummer,\n    number: formatNumber,\n    organisasjonsnummer: formatOrganisasjonsnummer,\n};\nexport type Formatter = keyof typeof formatters;\n\nconst clamp = (value: number, min: number, max: number) =>\n    Math.min(Math.max(value, min), max);\n\nexport type RegisterWithMaskOptions<T extends FieldValues> = Omit<\n    RegisterOptions<T>,\n    \"setValueAs\"\n>;\n\nconst registerWithMask =\n    (formatter: Formatter) =>\n    <T extends FieldValues>(\n        form: UseFormReturn<T>,\n        name: Path<T>,\n        options?: RegisterWithMaskOptions<T>,\n    ) => {\n        let onKeyDownCaretPosition = 0;\n        let onKeyDownKeyPressed = \"\";\n        let deletedCharactersOnKeyDown = \"\";\n\n        const setValueAs = (value: string) => value.replace(/\\s/g, \"\");\n        const onChange = (event: ChangeEvent<HTMLInputElement>) => {\n            options?.onChange?.(event);\n\n            // save some values before event.target.value change\n            let onChangeCaretPosition = 0;\n            const inputLength = event.target.value.length;\n\n            // type checking formalities\n            if (event.target.selectionStart !== null) {\n                onChangeCaretPosition = event.target.selectionStart;\n            }\n\n            const formattedValue = formatters[formatter](event.target.value, {\n                partial: true,\n            });\n            const formattedLength = formattedValue.toString().length;\n\n            form.setValue(name, formattedValue as PathValue<T, Path<T>>);\n\n            let newPosition: number | null = null;\n\n            if ([\"Delete\", \"Backspace\"].includes(onKeyDownKeyPressed)) {\n                // handle removing content\n                // calculate how much to move the caret, this also accounts for removing sections of text\n                const delta = onKeyDownCaretPosition - onChangeCaretPosition;\n                const formattedLengthChange =\n                    deletedCharactersOnKeyDown.trim() === \"\"\n                        ? 0\n                        : formattedLength - inputLength;\n\n                // calculate new caret position (- because we move backwards)\n                newPosition =\n                    onKeyDownCaretPosition - delta + formattedLengthChange;\n            } else if (\n                onChangeCaretPosition < event.target.value.length ||\n                inputLength !== formattedLength\n            ) {\n                // handle adding content from inside the string\n                // calculate how much to move the caret forwards\n                const delta = formattedLength - inputLength;\n\n                // calculate new caret position (+ because we move forwards)\n                newPosition = onChangeCaretPosition + delta;\n            }\n\n            if (newPosition !== null) {\n                const clampedPosition = clamp(newPosition, 0, formattedLength);\n\n                event.target.setSelectionRange(\n                    clampedPosition,\n                    clampedPosition,\n                    undefined,\n                );\n            }\n        };\n\n        const registerOptions: RegisterOptions<T, Path<T>> = {\n            setValueAs,\n            onChange,\n        };\n        if (options) {\n            Object.assign(registerOptions, options);\n        }\n        const register = form.register(name, registerOptions);\n\n        // save the caret position before the change occured\n        const onKeyDown: KeyboardEventHandler<HTMLInputElement> = (event) => {\n            deletedCharactersOnKeyDown = \"\";\n\n            const input = event.target as HTMLInputElement;\n            const { selectionStart, selectionEnd, value } = input;\n\n            if (selectionStart !== null) {\n                onKeyDownCaretPosition = selectionStart;\n\n                if (selectionEnd !== null && selectionEnd > selectionStart) {\n                    deletedCharactersOnKeyDown = value.slice(\n                        selectionStart,\n                        selectionEnd,\n                    );\n                } else if (event.key === \"Backspace\") {\n                    deletedCharactersOnKeyDown =\n                        value[onKeyDownCaretPosition - 1] ?? \"\";\n                } else if (event.key === \"Delete\") {\n                    deletedCharactersOnKeyDown =\n                        value[onKeyDownCaretPosition] ?? \"\";\n                }\n            }\n            onKeyDownKeyPressed = event.key;\n        };\n\n        // add onKeyDown event handler to the registered input\n        const extra: Record<string, unknown> = {\n            onKeyDown,\n        };\n\n        return Object.assign(register, extra);\n    };\n\n/** @deprecated Bruk `registerWithMasks` i stedet */\nexport const registerWithFodselsnummerMask = registerWithMask(\"fodselsnummer\");\n/** @deprecated Bruk `registerWithMasks` i stedet */\nexport const registerWithKortnummerMask = registerWithMask(\"kortnummer\");\n/** @deprecated Bruk `registerWithMasks` i stedet */\nexport const registerWithKontonummerMask = registerWithMask(\"kontonummer\");\n/** @deprecated Bruk `registerWithMasks` i stedet */\nexport const registerWithTelefonnummerMask = registerWithMask(\"telefonnummer\");\n\n/**\n * Hjelpefunksjon for React Hook Form som lar deg bruke formateringsfunksjonene i denne pakken som inputmasker.\n */\nexport const registerWithMasks = <T extends FieldValues>(\n    form: UseFormReturn<T>,\n) => ({\n    registerWithFodselsnummerMask: (\n        name: Path<T>,\n        options?: RegisterWithMaskOptions<T>,\n    ): UseFormRegisterReturn =>\n        registerWithMask(\"fodselsnummer\")<T>(form, name, options),\n    registerWithKortnummerMask: (\n        name: Path<T>,\n        options?: RegisterWithMaskOptions<T>,\n    ): UseFormRegisterReturn =>\n        registerWithMask(\"kortnummer\")<T>(form, name, options),\n    registerWithKontonummerMask: (\n        name: Path<T>,\n        options?: RegisterWithMaskOptions<T>,\n    ): UseFormRegisterReturn =>\n        registerWithMask(\"kontonummer\")<T>(form, name, options),\n    registerWithTelefonnummerMask: (\n        name: Path<T>,\n        options?: RegisterWithMaskOptions<T>,\n    ): UseFormRegisterReturn =>\n        registerWithMask(\"telefonnummer\")<T>(form, name, options),\n    registerWithOrganisasjonsnummerMask: (\n        name: Path<T>,\n        options?: RegisterWithMaskOptions<T>,\n    ): UseFormRegisterReturn =>\n        registerWithMask(\"organisasjonsnummer\")<T>(form, name, options),\n    registerWithDateMask: (\n        name: Path<T>,\n        options?: RegisterWithMaskOptions<T>,\n    ): UseFormRegisterReturn =>\n        registerWithMask(\"date\")<T>(form, name, options),\n    registerWithNumber: (\n        name: Path<T>,\n        options?: RegisterWithMaskOptions<T>,\n    ): UseFormRegisterReturn =>\n        registerWithMask(\"number\")<T>(form, name, options),\n});\n"],"names":["formatters","date","formatDateString","fodselsnummer","formatFodselsnummer","kortnummer","formatKortnummer","kontonummer","formatKontonummer","telefonnummer","formatTelefonnummer","number","formatNumber","organisasjonsnummer","formatOrganisasjonsnummer","registerWithMask","formatter","form","name","options","onKeyDownCaretPosition","onKeyDownKeyPressed","deletedCharactersOnKeyDown","registerOptions","setValueAs","value","replace","onChange","event","onChangeCaretPosition","inputLength","target","length","selectionStart","formattedValue","partial","formattedLength","toString","setValue","newPosition","includes","delta","formattedLengthChange","trim","clampedPosition","min","max","Math","clamp","setSelectionRange","Object","assign","register","onKeyDown","input","selectionEnd","slice","key","registerWithFodselsnummerMask","registerWithKortnummerMask","registerWithKontonummerMask","registerWithTelefonnummerMask","registerWithOrganisasjonsnummerMask","registerWithDateMask","registerWithNumber"],"mappings":"0aAiBMA,EAAa,CACfC,KAAMC,EAAAA,iBACNC,cAAeC,EAAAA,oBACfC,WAAYC,EAAAA,iBACZC,YAAaC,EAAAA,kBACbC,cAAeC,EAAAA,oBACfC,OAAQC,EAAAA,aACRC,oBAAqBC,EAAAA,2BAYnBC,EACDC,GACD,CACIC,EACAC,EACAC,KAEA,IAAIC,EAAyB,EACzBC,EAAsB,GACtBC,EAA6B,GA2DjC,MAAMC,EAA+C,CACjDC,WA1DgBC,GAAkBA,EAAMC,QAAQ,MAAO,IA2DvDC,SA1DcC,IACdT,GAASQ,WAAWC,GAGpB,IAAIC,EAAwB,EAC5B,MAAMC,EAAcF,EAAMG,OAAON,MAAMO,OAGH,OAAhCJ,EAAMG,OAAOE,iBACbJ,EAAwBD,EAAMG,OAAOE,gBAGzC,MAAMC,EAAiBlC,EAAWgB,GAAWY,EAAMG,OAAON,MAAO,CAC7DU,SAAS,IAEPC,EAAkBF,EAAeG,WAAWL,OAElDf,EAAKqB,SAASpB,EAAMgB,GAEpB,IAAIK,EAA6B,KAEjC,GAAI,CAAC,SAAU,aAAaC,SAASnB,GAAsB,CAGvD,MAAMoB,EAAQrB,EAAyBS,EACjCa,EACoC,KAAtCpB,EAA2BqB,OACrB,EACAP,EAAkBN,EAG5BS,EACInB,EAAyBqB,EAAQC,CACzC,MAAA,GACIb,EAAwBD,EAAMG,OAAON,MAAMO,QAC3CF,IAAgBM,EAClB,CAMEG,EAAcV,GAHAO,EAAkBN,EAIpC,CAEA,GAAoB,OAAhBS,EAAsB,CACtB,MAAMK,EAlER,EAACnB,EAAeoB,EAAaC,IACvCC,KAAKF,IAAIE,KAAKD,IAAIrB,EAAOoB,GAAMC,GAiEKE,CAAMT,EAAa,EAAGH,GAE9CR,EAAMG,OAAOkB,kBACTL,EACAA,OACA,EAER,IAOAzB,GACA+B,OAAOC,OAAO5B,EAAiBJ,GAEnC,MAAMiC,EAAWnC,EAAKmC,SAASlC,EAAMK,GAiCrC,OAAO2B,OAAOC,OAAOC,EAJkB,CACnCC,UA3BuDzB,IACvDN,EAA6B,GAE7B,MAAMgC,EAAQ1B,EAAMG,QACZE,eAAAA,EAAgBsB,aAAAA,EAAc9B,MAAAA,GAAU6B,EAEzB,OAAnBrB,IACAb,EAAyBa,EAEJ,OAAjBsB,GAAyBA,EAAetB,EACxCX,EAA6BG,EAAM+B,MAC/BvB,EACAsB,GAEiB,cAAd3B,EAAM6B,IACbnC,EACIG,EAAML,EAAyB,IAAM,GACpB,WAAdQ,EAAM6B,MACbnC,EACIG,EAAML,IAA2B,KAG7CC,EAAsBO,EAAM6B,QAY3BC,EAAgC3C,EAAiB,iBAEjD4C,EAA6B5C,EAAiB,cAE9C6C,EAA8B7C,EAAiB,eAE/C8C,EAAgC9C,EAAiB,8JAM1DE,KAEAyC,8BAA+B,CAC3BxC,EACAC,IAEAJ,EAAiB,gBAAjBA,CAAqCE,EAAMC,EAAMC,GACrDwC,2BAA4B,CACxBzC,EACAC,IAEAJ,EAAiB,aAAjBA,CAAkCE,EAAMC,EAAMC,GAClDyC,4BAA6B,CACzB1C,EACAC,IAEAJ,EAAiB,cAAjBA,CAAmCE,EAAMC,EAAMC,GACnD0C,8BAA+B,CAC3B3C,EACAC,IAEAJ,EAAiB,gBAAjBA,CAAqCE,EAAMC,EAAMC,GACrD2C,oCAAqC,CACjC5C,EACAC,IAEAJ,EAAiB,sBAAjBA,CAA2CE,EAAMC,EAAMC,GAC3D4C,qBAAsB,CAClB7C,EACAC,IAEAJ,EAAiB,OAAjBA,CAA4BE,EAAMC,EAAMC,GAC5C6C,mBAAoB,CAChB9C,EACAC,IAEAJ,EAAiB,SAAjBA,CAA8BE,EAAMC,EAAMC"}