UNPKG

react-text-mask-modern

Version:

A modern, React 19+ compatible input masking component using hooks and TypeScript.

1 lines 32 kB
{"version":3,"sources":["../src/MaskedInput.tsx","../src/adjustCaretPosition.ts","../constants.ts","../utils.ts","../src/conformToMask.ts","../src/createTextMaskInputElement.ts"],"sourcesContent":["import React, {\n useEffect,\n useRef,\n useCallback,\n InputHTMLAttributes,\n ChangeEvent,\n FocusEvent,\n forwardRef,\n} from 'react';\n\nimport createTextMaskInputElement from './createTextMaskInputElement';\n\nexport interface MaskedInputProps\n extends Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'value' | 'onChange' | 'onBlur'\n > {\n mask: any;\n guide?: boolean;\n value?: string | number;\n pipe?: any;\n placeholderChar?: string;\n keepCharPositions?: boolean;\n showMask?: boolean;\n onBlur?: (event: FocusEvent<HTMLInputElement>) => void;\n onChange?: (event: ChangeEvent<HTMLInputElement>) => void;\n}\n\nexport const MaskedInput = forwardRef<HTMLInputElement, MaskedInputProps>(\n (\n {\n mask,\n guide,\n value,\n pipe,\n placeholderChar,\n keepCharPositions,\n showMask,\n onBlur,\n onChange,\n ...rest\n },\n ref\n ) => {\n const localRef = useRef<HTMLInputElement | null>(null);\n const inputRef =\n (ref as React.RefObject<HTMLInputElement | null>) ?? localRef;\n\n const textMaskRef = useRef<any>(null);\n\n const initTextMask = useCallback(() => {\n if (!inputRef.current) return;\n\n textMaskRef.current = createTextMaskInputElement({\n inputElement: inputRef.current,\n mask,\n guide,\n pipe,\n placeholderChar,\n keepCharPositions,\n showMask,\n });\n\n textMaskRef.current.update(value);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n mask,\n guide,\n pipe,\n placeholderChar,\n keepCharPositions,\n showMask,\n value,\n ]);\n\n useEffect(() => {\n initTextMask();\n }, [initTextMask]);\n\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n textMaskRef.current?.update();\n onChange?.(event);\n };\n\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\n onBlur?.(event);\n };\n\n return (\n <input\n ref={(el) => {\n localRef.current = el;\n if (typeof ref === 'function') {\n ref(el);\n } else if (ref) {\n (ref as React.RefObject<HTMLInputElement | null>).current = el;\n }\n }}\n onBlur={handleBlur}\n onChange={handleChange}\n value={value}\n {...rest}\n />\n );\n }\n);\n","const defaultArray: any[] = [];\nconst emptyString = '';\n\ninterface AdjustCaretPositionArgs {\n previousConformedValue?: string;\n previousPlaceholder?: string;\n currentCaretPosition?: number;\n conformedValue: string;\n rawValue: string;\n placeholderChar: string;\n placeholder: string;\n indexesOfPipedChars?: number[];\n caretTrapIndexes?: number[];\n}\n\nexport default function adjustCaretPosition({\n previousConformedValue = emptyString,\n previousPlaceholder = emptyString,\n currentCaretPosition = 0,\n conformedValue,\n rawValue,\n placeholderChar,\n placeholder,\n indexesOfPipedChars = defaultArray,\n caretTrapIndexes = defaultArray,\n}: AdjustCaretPositionArgs): number {\n if (currentCaretPosition === 0 || !rawValue.length) {\n return 0;\n }\n\n const rawValueLength = rawValue.length;\n const previousConformedValueLength = previousConformedValue.length;\n const placeholderLength = placeholder.length;\n const conformedValueLength = conformedValue.length;\n const editLength = rawValueLength - previousConformedValueLength;\n const isAddition = editLength > 0;\n const isFirstRawValue = previousConformedValueLength === 0;\n const isPartialMultiCharEdit =\n editLength > 1 && !isAddition && !isFirstRawValue;\n\n if (isPartialMultiCharEdit) {\n return currentCaretPosition;\n }\n\n const possiblyHasRejectedChar =\n isAddition &&\n (previousConformedValue === conformedValue ||\n conformedValue === placeholder);\n\n let startingSearchIndex = 0;\n let trackRightCharacter = false;\n let targetChar: string | undefined;\n\n if (possiblyHasRejectedChar) {\n startingSearchIndex = currentCaretPosition - editLength;\n } else {\n const normalizedConformedValue = conformedValue.toLowerCase();\n const normalizedRawValue = rawValue.toLowerCase();\n const leftHalfChars = normalizedRawValue\n .substring(0, currentCaretPosition)\n .split(emptyString);\n const intersection = leftHalfChars.filter(\n (char) => normalizedConformedValue.indexOf(char) !== -1\n );\n targetChar = intersection[intersection.length - 1];\n\n const previousLeftMaskChars = previousPlaceholder\n .substring(0, intersection.length)\n .split(emptyString)\n .filter((char) => char !== placeholderChar).length;\n\n const leftMaskChars = placeholder\n .substring(0, intersection.length)\n .split(emptyString)\n .filter((char) => char !== placeholderChar).length;\n\n const maskLengthChanged = leftMaskChars !== previousLeftMaskChars;\n\n const targetIsMaskMovingLeft =\n previousPlaceholder[intersection.length - 1] !== undefined &&\n placeholder[intersection.length - 2] !== undefined &&\n previousPlaceholder[intersection.length - 1] !== placeholderChar &&\n previousPlaceholder[intersection.length - 1] !==\n placeholder[intersection.length - 1] &&\n previousPlaceholder[intersection.length - 1] ===\n placeholder[intersection.length - 2];\n\n if (\n !isAddition &&\n (maskLengthChanged || targetIsMaskMovingLeft) &&\n previousLeftMaskChars > 0 &&\n placeholder.indexOf(targetChar) > -1 &&\n rawValue[currentCaretPosition] !== undefined\n ) {\n trackRightCharacter = true;\n targetChar = rawValue[currentCaretPosition];\n }\n\n const pipedChars = indexesOfPipedChars.map(\n (index) => normalizedConformedValue[index]\n );\n\n const countTargetCharInPipedChars = pipedChars.filter(\n (c) => c === targetChar\n ).length;\n const countTargetCharInIntersection = intersection.filter(\n (c) => c === targetChar\n ).length;\n const countTargetCharInPlaceholder = placeholder\n .substring(0, placeholder.indexOf(placeholderChar))\n .split(emptyString)\n .filter(\n (char, index) => char === targetChar && rawValue[index] !== char\n ).length;\n\n const requiredNumberOfMatches =\n countTargetCharInPlaceholder +\n countTargetCharInIntersection +\n countTargetCharInPipedChars +\n (trackRightCharacter ? 1 : 0);\n\n let numberOfEncounteredMatches = 0;\n for (let i = 0; i < conformedValueLength; i++) {\n const conformedValueChar = normalizedConformedValue[i];\n startingSearchIndex = i + 1;\n if (conformedValueChar === targetChar) {\n numberOfEncounteredMatches++;\n }\n if (numberOfEncounteredMatches >= requiredNumberOfMatches) {\n break;\n }\n }\n }\n\n if (isAddition) {\n let lastPlaceholderChar = startingSearchIndex;\n for (let i = startingSearchIndex; i <= placeholderLength; i++) {\n if (placeholder[i] === placeholderChar) {\n lastPlaceholderChar = i;\n }\n if (\n placeholder[i] === placeholderChar ||\n caretTrapIndexes.indexOf(i) !== -1 ||\n i === placeholderLength\n ) {\n return lastPlaceholderChar;\n }\n }\n } else {\n if (trackRightCharacter) {\n for (let i = startingSearchIndex - 1; i >= 0; i--) {\n if (\n conformedValue[i] === targetChar ||\n caretTrapIndexes.indexOf(i) !== -1 ||\n i === 0\n ) {\n return i;\n }\n }\n } else {\n for (let i = startingSearchIndex; i >= 0; i--) {\n if (\n placeholder[i - 1] === placeholderChar ||\n caretTrapIndexes.indexOf(i) !== -1 ||\n i === 0\n ) {\n return i;\n }\n }\n }\n }\n\n return currentCaretPosition;\n}\n","export const placeholderChar = '_';\nexport const strFunction = 'function';\n","import { placeholderChar as defaultPlaceholderChar } from './constants';\n\nexport function convertMaskToPlaceholder(\n mask: Array<string | RegExp> = [],\n placeholderChar: string = defaultPlaceholderChar\n): string {\n if (!isArray(mask)) {\n throw new Error(\n 'Text-mask: convertMaskToPlaceholder; The mask must be an array.'\n );\n }\n\n if (mask.includes(placeholderChar)) {\n throw new Error(\n `Placeholder character must not be used inside the mask.\\n\\n` +\n `Received placeholder: ${JSON.stringify(placeholderChar)}\\n` +\n `Received mask: ${JSON.stringify(mask)}`\n );\n }\n\n return mask\n .map((char) => (char instanceof RegExp ? placeholderChar : char))\n .join('');\n}\n\nexport function isArray(value: unknown): value is any[] {\n return Array.isArray(value);\n}\n\nexport function isString(value: unknown): value is string {\n return typeof value === 'string' || value instanceof String;\n}\n\nexport function isNumber(value: unknown): value is number {\n return typeof value === 'number' && !isNaN(value);\n}\n\nexport function isNil(value: unknown): value is null | undefined {\n return value === null || typeof value === 'undefined';\n}\n\nconst strCaretTrap = '[]';\n\nexport interface ProcessCaretTrapsResult {\n maskWithoutCaretTraps: Array<string | RegExp>;\n indexes: number[];\n}\n\n/**\n * Removes caret traps (`[]`) from the mask and returns both cleaned mask and indexes where they were found.\n */\nexport function processCaretTraps(\n mask: Array<string | RegExp | string>\n): ProcessCaretTrapsResult {\n const indexes: number[] = [];\n const resultMask: Array<string | RegExp> = [];\n\n mask.forEach((item, index) => {\n if (item === strCaretTrap) {\n indexes.push(index);\n } else {\n resultMask.push(item);\n }\n });\n\n return {\n maskWithoutCaretTraps: resultMask,\n indexes,\n };\n}\n","import { convertMaskToPlaceholder, isArray, processCaretTraps } from '../utils';\nimport { placeholderChar as defaultPlaceholderChar } from '../constants';\n\ntype Mask =\n | Array<string | RegExp>\n | ((value: string, config?: any) => Array<string | RegExp> | false);\n\ninterface ConformToMaskConfig {\n guide?: boolean;\n previousConformedValue?: string;\n placeholderChar?: string;\n placeholder?: string;\n currentCaretPosition?: number;\n keepCharPositions?: boolean;\n}\n\ninterface ConformToMaskResult {\n conformedValue: string;\n meta: {\n someCharsRejected: boolean;\n };\n}\n\nconst emptyString = '';\n\nexport default function conformToMask(\n rawValue: string = emptyString,\n mask: Mask,\n config: ConformToMaskConfig = {}\n): ConformToMaskResult {\n if (!isArray(mask)) {\n if (typeof mask === 'function') {\n const result = mask(rawValue, config);\n if (result === false)\n return { conformedValue: rawValue, meta: { someCharsRejected: false } };\n mask = processCaretTraps(result).maskWithoutCaretTraps;\n } else {\n throw new Error(\n 'Text-mask: conformToMask; The mask must be an array or a function.'\n );\n }\n }\n\n const {\n guide = true,\n previousConformedValue = emptyString,\n placeholderChar = defaultPlaceholderChar,\n placeholder = convertMaskToPlaceholder(mask, placeholderChar),\n currentCaretPosition,\n keepCharPositions,\n } = config;\n\n const suppressGuide = guide === false && previousConformedValue !== undefined;\n const rawValueLength = rawValue.length;\n const previousConformedValueLength = previousConformedValue.length;\n const placeholderLength = placeholder.length;\n const maskLength = mask.length;\n const editDistance = rawValueLength - previousConformedValueLength;\n const isAddition = editDistance > 0;\n const indexOfFirstChange =\n typeof currentCaretPosition === 'number'\n ? currentCaretPosition + (isAddition ? -editDistance : 0)\n : 0;\n const indexOfLastChange = indexOfFirstChange + Math.abs(editDistance);\n\n if (keepCharPositions === true && !isAddition) {\n let compensatingPlaceholderChars = '';\n for (let i = indexOfFirstChange; i < indexOfLastChange; i++) {\n if (placeholder[i] === placeholderChar) {\n compensatingPlaceholderChars += placeholderChar;\n }\n }\n rawValue =\n rawValue.slice(0, indexOfFirstChange) +\n compensatingPlaceholderChars +\n rawValue.slice(indexOfFirstChange);\n }\n\n const rawValueArr = rawValue.split('').map((char, i) => ({\n char,\n isNew: i >= indexOfFirstChange && i < indexOfLastChange,\n }));\n\n for (let i = rawValueLength - 1; i >= 0; i--) {\n const { char } = rawValueArr[i];\n if (char !== placeholderChar) {\n const shouldOffset =\n i >= indexOfFirstChange && previousConformedValueLength === maskLength;\n if (char === placeholder[shouldOffset ? i - editDistance : i]) {\n rawValueArr.splice(i, 1);\n }\n }\n }\n\n let conformedValue = '';\n let someCharsRejected = false;\n\n placeholderLoop: for (let i = 0; i < placeholderLength; i++) {\n const charInPlaceholder = placeholder[i];\n\n if (charInPlaceholder === placeholderChar) {\n if (rawValueArr.length > 0) {\n while (rawValueArr.length > 0) {\n const { char: rawValueChar, isNew } = rawValueArr.shift()!;\n\n if (rawValueChar === placeholderChar && suppressGuide !== true) {\n conformedValue += placeholderChar;\n continue placeholderLoop;\n } else if ((mask[i] as RegExp).test(rawValueChar)) {\n if (\n keepCharPositions !== true ||\n isNew === false ||\n previousConformedValue === emptyString ||\n guide === false ||\n !isAddition\n ) {\n conformedValue += rawValueChar;\n } else {\n const rawValueArrLength = rawValueArr.length;\n let indexOfNextAvailablePlaceholderChar: number | null = null;\n for (let j = 0; j < rawValueArrLength; j++) {\n const charData = rawValueArr[j];\n if (\n charData.char !== placeholderChar &&\n charData.isNew === false\n )\n break;\n if (charData.char === placeholderChar) {\n indexOfNextAvailablePlaceholderChar = j;\n break;\n }\n }\n if (indexOfNextAvailablePlaceholderChar !== null) {\n conformedValue += rawValueChar;\n rawValueArr.splice(indexOfNextAvailablePlaceholderChar, 1);\n } else {\n i--;\n }\n }\n continue placeholderLoop;\n } else {\n someCharsRejected = true;\n }\n }\n }\n\n if (!suppressGuide) {\n conformedValue += placeholder.slice(i);\n }\n break;\n } else {\n conformedValue += charInPlaceholder;\n }\n }\n\n if (suppressGuide && !isAddition) {\n let indexOfLastFilledPlaceholderChar: number | null = null;\n for (let i = 0; i < conformedValue.length; i++) {\n if (placeholder[i] === placeholderChar) {\n indexOfLastFilledPlaceholderChar = i;\n }\n }\n conformedValue =\n indexOfLastFilledPlaceholderChar !== null\n ? conformedValue.slice(0, indexOfLastFilledPlaceholderChar + 1)\n : '';\n }\n\n return {\n conformedValue,\n meta: { someCharsRejected },\n };\n}\n","import adjustCaretPosition from './adjustCaretPosition';\nimport conformToMask from './conformToMask';\nimport {\n convertMaskToPlaceholder,\n isString,\n isNumber,\n processCaretTraps,\n} from '../utils';\nimport { placeholderChar as defaultPlaceholderChar } from '../constants';\n\nconst emptyString = '';\nconst strNone = 'none';\nconst strObject = 'object';\nconst isAndroid =\n typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent);\n const defer = (cb: () => void) => {\n if (typeof requestAnimationFrame !== 'undefined') {\n requestAnimationFrame(cb);\n } else {\n setTimeout(cb, 0);\n }\n };\n \n\nexport interface CreateTextMaskInputElementConfig {\n inputElement: HTMLInputElement;\n mask:\n | Array<string | RegExp>\n | ((value: string, config?: any) => Array<string | RegExp> | false)\n | boolean\n | {\n mask:\n | Array<string | RegExp>\n | ((value: string, config?: any) => Array<string | RegExp> | false);\n pipe?: (\n conformedValue: string,\n config: any\n ) => false | string | { value: string; [key: string]: any };\n };\n guide?: boolean;\n pipe?: (\n conformedValue: string,\n config: any\n ) => false | string | { value: string; [key: string]: any };\n placeholderChar?: string;\n keepCharPositions?: boolean;\n showMask?: boolean;\n}\n\nexport interface TextMaskInputElement {\n state: {\n previousConformedValue?: string;\n previousPlaceholder?: string;\n };\n update: (\n rawValue?: string | number,\n configOverride?: Partial<CreateTextMaskInputElementConfig>\n ) => void;\n}\n\nexport default function createTextMaskInputElement(\n config: CreateTextMaskInputElementConfig\n): TextMaskInputElement {\n const state: TextMaskInputElement['state'] = {\n previousConformedValue: undefined,\n previousPlaceholder: undefined,\n };\n\n return {\n state,\n\n update(\n rawValue?: string | number,\n {\n inputElement,\n mask: providedMask,\n guide,\n pipe,\n placeholderChar = defaultPlaceholderChar,\n keepCharPositions = false,\n showMask = false,\n }: Partial<CreateTextMaskInputElementConfig> = config\n ) {\n if (typeof rawValue === 'undefined') {\n rawValue = inputElement?.value;\n }\n\n if (rawValue === state.previousConformedValue) return;\n\n if (\n typeof providedMask === strObject &&\n (providedMask as any).pipe !== undefined &&\n (providedMask as any).mask !== undefined\n ) {\n pipe = (providedMask as any).pipe;\n providedMask = (providedMask as any).mask;\n }\n\n let mask: any = providedMask;\n let placeholder: string | undefined;\n let caretTrapIndexes: number[] | undefined;\n\n if (Array.isArray(mask)) {\n placeholder = convertMaskToPlaceholder(mask, placeholderChar);\n } else if (typeof mask === 'function') {\n const evaluatedMask = mask(getSafeRawValue(rawValue), {\n currentCaretPosition: inputElement?.selectionEnd,\n previousConformedValue: state.previousConformedValue,\n placeholderChar,\n });\n\n if (evaluatedMask === false) return;\n\n const { maskWithoutCaretTraps, indexes } =\n processCaretTraps(evaluatedMask);\n\n mask = maskWithoutCaretTraps;\n caretTrapIndexes = indexes;\n placeholder = convertMaskToPlaceholder(mask, placeholderChar);\n }\n\n if (mask === false) return;\n\n const safeRawValue = getSafeRawValue(rawValue);\n const currentCaretPosition = inputElement?.selectionEnd ?? 0;\n const { previousConformedValue, previousPlaceholder } = state;\n\n const conformToMaskConfig = {\n previousConformedValue,\n guide,\n placeholderChar,\n pipe,\n placeholder,\n currentCaretPosition,\n keepCharPositions,\n };\n\n const { conformedValue } = conformToMask(\n safeRawValue,\n mask,\n conformToMaskConfig\n );\n\n let finalConformedValue = conformedValue;\n let indexesOfPipedChars: number[] = [];\n\n if (typeof pipe === 'function') {\n let pipeResult = pipe(conformedValue, {\n rawValue: safeRawValue,\n ...conformToMaskConfig,\n });\n\n if (pipeResult === false) {\n pipeResult = {\n value: previousConformedValue || '',\n rejected: true,\n };\n } else if (isString(pipeResult)) {\n pipeResult = { value: pipeResult };\n }\n\n finalConformedValue = (pipeResult as any).value;\n indexesOfPipedChars = (pipeResult as any).indexesOfPipedChars || [];\n }\n\n const adjustedCaretPosition = adjustCaretPosition({\n previousConformedValue,\n previousPlaceholder,\n conformedValue: finalConformedValue,\n placeholder: placeholder ?? '',\n rawValue: safeRawValue,\n currentCaretPosition,\n placeholderChar,\n indexesOfPipedChars,\n caretTrapIndexes: caretTrapIndexes || [],\n });\n\n const inputValueShouldBeEmpty =\n finalConformedValue === placeholder && adjustedCaretPosition === 0;\n const emptyValue = showMask ? placeholder ?? '' : emptyString;\n const inputElementValue = inputValueShouldBeEmpty\n ? emptyValue\n : finalConformedValue;\n\n state.previousConformedValue = inputElementValue;\n state.previousPlaceholder = placeholder;\n\n if (!inputElement || inputElement.value === inputElementValue) return;\n\n inputElement.value = inputElementValue;\n safeSetSelection(inputElement, adjustedCaretPosition || 0);\n },\n };\n}\n\nfunction safeSetSelection(element: HTMLInputElement, position: number) {\n if (document.activeElement === element) {\n const cb = () => element.setSelectionRange(position, position, strNone);\n\n if (isAndroid) {\n defer(cb);\n } else {\n element.setSelectionRange(position, position, strNone);\n }\n }\n}\nfunction getSafeRawValue(value: unknown): string {\n if (isString(value)) return value;\n if (isNumber(value)) return String(value);\n if (value === undefined || value === null) return emptyString;\n\n throw new Error(\n `The 'value' provided to Text Mask needs to be a string or a number. Received: ${JSON.stringify(\n value\n )}`\n );\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,OACK;;;ACRP,IAAM,eAAsB,CAAC;AAC7B,IAAM,cAAc;AAcL,SAAR,oBAAqC;AAAA,EAC1C,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,uBAAuB;AAAA,EACvB;AAAA,EACA;AAAA,EACA,iBAAAA;AAAA,EACA;AAAA,EACA,sBAAsB;AAAA,EACtB,mBAAmB;AACrB,GAAoC;AAClC,MAAI,yBAAyB,KAAK,CAAC,SAAS,QAAQ;AAClD,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,SAAS;AAChC,QAAM,+BAA+B,uBAAuB;AAC5D,QAAM,oBAAoB,YAAY;AACtC,QAAM,uBAAuB,eAAe;AAC5C,QAAM,aAAa,iBAAiB;AACpC,QAAM,aAAa,aAAa;AAChC,QAAM,kBAAkB,iCAAiC;AACzD,QAAM,yBACJ,aAAa,KAAK,CAAC,cAAc,CAAC;AAEpC,MAAI,wBAAwB;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,0BACJ,eACC,2BAA2B,kBAC1B,mBAAmB;AAEvB,MAAI,sBAAsB;AAC1B,MAAI,sBAAsB;AAC1B,MAAI;AAEJ,MAAI,yBAAyB;AAC3B,0BAAsB,uBAAuB;AAAA,EAC/C,OAAO;AACL,UAAM,2BAA2B,eAAe,YAAY;AAC5D,UAAM,qBAAqB,SAAS,YAAY;AAChD,UAAM,gBAAgB,mBACnB,UAAU,GAAG,oBAAoB,EACjC,MAAM,WAAW;AACpB,UAAM,eAAe,cAAc;AAAA,MACjC,CAAC,SAAS,yBAAyB,QAAQ,IAAI,MAAM;AAAA,IACvD;AACA,iBAAa,aAAa,aAAa,SAAS,CAAC;AAEjD,UAAM,wBAAwB,oBAC3B,UAAU,GAAG,aAAa,MAAM,EAChC,MAAM,WAAW,EACjB,OAAO,CAAC,SAAS,SAASA,gBAAe,EAAE;AAE9C,UAAM,gBAAgB,YACnB,UAAU,GAAG,aAAa,MAAM,EAChC,MAAM,WAAW,EACjB,OAAO,CAAC,SAAS,SAASA,gBAAe,EAAE;AAE9C,UAAM,oBAAoB,kBAAkB;AAE5C,UAAM,yBACJ,oBAAoB,aAAa,SAAS,CAAC,MAAM,UACjD,YAAY,aAAa,SAAS,CAAC,MAAM,UACzC,oBAAoB,aAAa,SAAS,CAAC,MAAMA,oBACjD,oBAAoB,aAAa,SAAS,CAAC,MACzC,YAAY,aAAa,SAAS,CAAC,KACrC,oBAAoB,aAAa,SAAS,CAAC,MACzC,YAAY,aAAa,SAAS,CAAC;AAEvC,QACE,CAAC,eACA,qBAAqB,2BACtB,wBAAwB,KACxB,YAAY,QAAQ,UAAU,IAAI,MAClC,SAAS,oBAAoB,MAAM,QACnC;AACA,4BAAsB;AACtB,mBAAa,SAAS,oBAAoB;AAAA,IAC5C;AAEA,UAAM,aAAa,oBAAoB;AAAA,MACrC,CAAC,UAAU,yBAAyB,KAAK;AAAA,IAC3C;AAEA,UAAM,8BAA8B,WAAW;AAAA,MAC7C,CAAC,MAAM,MAAM;AAAA,IACf,EAAE;AACF,UAAM,gCAAgC,aAAa;AAAA,MACjD,CAAC,MAAM,MAAM;AAAA,IACf,EAAE;AACF,UAAM,+BAA+B,YAClC,UAAU,GAAG,YAAY,QAAQA,gBAAe,CAAC,EACjD,MAAM,WAAW,EACjB;AAAA,MACC,CAAC,MAAM,UAAU,SAAS,cAAc,SAAS,KAAK,MAAM;AAAA,IAC9D,EAAE;AAEJ,UAAM,0BACJ,+BACA,gCACA,+BACC,sBAAsB,IAAI;AAE7B,QAAI,6BAA6B;AACjC,aAAS,IAAI,GAAG,IAAI,sBAAsB,KAAK;AAC7C,YAAM,qBAAqB,yBAAyB,CAAC;AACrD,4BAAsB,IAAI;AAC1B,UAAI,uBAAuB,YAAY;AACrC;AAAA,MACF;AACA,UAAI,8BAA8B,yBAAyB;AACzD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY;AACd,QAAI,sBAAsB;AAC1B,aAAS,IAAI,qBAAqB,KAAK,mBAAmB,KAAK;AAC7D,UAAI,YAAY,CAAC,MAAMA,kBAAiB;AACtC,8BAAsB;AAAA,MACxB;AACA,UACE,YAAY,CAAC,MAAMA,oBACnB,iBAAiB,QAAQ,CAAC,MAAM,MAChC,MAAM,mBACN;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI,qBAAqB;AACvB,eAAS,IAAI,sBAAsB,GAAG,KAAK,GAAG,KAAK;AACjD,YACE,eAAe,CAAC,MAAM,cACtB,iBAAiB,QAAQ,CAAC,MAAM,MAChC,MAAM,GACN;AACA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,OAAO;AACL,eAAS,IAAI,qBAAqB,KAAK,GAAG,KAAK;AAC7C,YACE,YAAY,IAAI,CAAC,MAAMA,oBACvB,iBAAiB,QAAQ,CAAC,MAAM,MAChC,MAAM,GACN;AACA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AC7KO,IAAM,kBAAkB;;;ACExB,SAAS,yBACd,OAA+B,CAAC,GAChCC,mBAA0B,iBAClB;AACR,MAAI,CAAC,QAAQ,IAAI,GAAG;AAClB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,MAAI,KAAK,SAASA,gBAAe,GAAG;AAClC,UAAM,IAAI;AAAA,MACR;AAAA;AAAA,wBAC2B,KAAK,UAAUA,gBAAe,CAAC;AAAA,iBACtC,KAAK,UAAU,IAAI,CAAC;AAAA,IAC1C;AAAA,EACF;AAEA,SAAO,KACJ,IAAI,CAAC,SAAU,gBAAgB,SAASA,mBAAkB,IAAK,EAC/D,KAAK,EAAE;AACZ;AAEO,SAAS,QAAQ,OAAgC;AACtD,SAAO,MAAM,QAAQ,KAAK;AAC5B;AAEO,SAAS,SAAS,OAAiC;AACxD,SAAO,OAAO,UAAU,YAAY,iBAAiB;AACvD;AAEO,SAAS,SAAS,OAAiC;AACxD,SAAO,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK;AAClD;AAMA,IAAM,eAAe;AAUd,SAAS,kBACd,MACyB;AACzB,QAAM,UAAoB,CAAC;AAC3B,QAAM,aAAqC,CAAC;AAE5C,OAAK,QAAQ,CAAC,MAAM,UAAU;AAC5B,QAAI,SAAS,cAAc;AACzB,cAAQ,KAAK,KAAK;AAAA,IACpB,OAAO;AACL,iBAAW,KAAK,IAAI;AAAA,IACtB;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,uBAAuB;AAAA,IACvB;AAAA,EACF;AACF;;;AC9CA,IAAMC,eAAc;AAEL,SAAR,cACL,WAAmBA,cACnB,MACA,SAA8B,CAAC,GACV;AACrB,MAAI,CAAC,QAAQ,IAAI,GAAG;AAClB,QAAI,OAAO,SAAS,YAAY;AAC9B,YAAM,SAAS,KAAK,UAAU,MAAM;AACpC,UAAI,WAAW;AACb,eAAO,EAAE,gBAAgB,UAAU,MAAM,EAAE,mBAAmB,MAAM,EAAE;AACxE,aAAO,kBAAkB,MAAM,EAAE;AAAA,IACnC,OAAO;AACL,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM;AAAA,IACJ,QAAQ;AAAA,IACR,yBAAyBA;AAAA,IACzB,iBAAAC,mBAAkB;AAAA,IAClB,cAAc,yBAAyB,MAAMA,gBAAe;AAAA,IAC5D;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,gBAAgB,UAAU,SAAS,2BAA2B;AACpE,QAAM,iBAAiB,SAAS;AAChC,QAAM,+BAA+B,uBAAuB;AAC5D,QAAM,oBAAoB,YAAY;AACtC,QAAM,aAAa,KAAK;AACxB,QAAM,eAAe,iBAAiB;AACtC,QAAM,aAAa,eAAe;AAClC,QAAM,qBACJ,OAAO,yBAAyB,WAC5B,wBAAwB,aAAa,CAAC,eAAe,KACrD;AACN,QAAM,oBAAoB,qBAAqB,KAAK,IAAI,YAAY;AAEpE,MAAI,sBAAsB,QAAQ,CAAC,YAAY;AAC7C,QAAI,+BAA+B;AACnC,aAAS,IAAI,oBAAoB,IAAI,mBAAmB,KAAK;AAC3D,UAAI,YAAY,CAAC,MAAMA,kBAAiB;AACtC,wCAAgCA;AAAA,MAClC;AAAA,IACF;AACA,eACE,SAAS,MAAM,GAAG,kBAAkB,IACpC,+BACA,SAAS,MAAM,kBAAkB;AAAA,EACrC;AAEA,QAAM,cAAc,SAAS,MAAM,EAAE,EAAE,IAAI,CAAC,MAAM,OAAO;AAAA,IACvD;AAAA,IACA,OAAO,KAAK,sBAAsB,IAAI;AAAA,EACxC,EAAE;AAEF,WAAS,IAAI,iBAAiB,GAAG,KAAK,GAAG,KAAK;AAC5C,UAAM,EAAE,KAAK,IAAI,YAAY,CAAC;AAC9B,QAAI,SAASA,kBAAiB;AAC5B,YAAM,eACJ,KAAK,sBAAsB,iCAAiC;AAC9D,UAAI,SAAS,YAAY,eAAe,IAAI,eAAe,CAAC,GAAG;AAC7D,oBAAY,OAAO,GAAG,CAAC;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,iBAAiB;AACrB,MAAI,oBAAoB;AAExB;AAAiB,aAAS,IAAI,GAAG,IAAI,mBAAmB,KAAK;AAC3D,YAAM,oBAAoB,YAAY,CAAC;AAEvC,UAAI,sBAAsBA,kBAAiB;AACzC,YAAI,YAAY,SAAS,GAAG;AAC1B,iBAAO,YAAY,SAAS,GAAG;AAC7B,kBAAM,EAAE,MAAM,cAAc,MAAM,IAAI,YAAY,MAAM;AAExD,gBAAI,iBAAiBA,oBAAmB,kBAAkB,MAAM;AAC9D,gCAAkBA;AAClB,uBAAS;AAAA,YACX,WAAY,KAAK,CAAC,EAAa,KAAK,YAAY,GAAG;AACjD,kBACE,sBAAsB,QACtB,UAAU,SACV,2BAA2BD,gBAC3B,UAAU,SACV,CAAC,YACD;AACA,kCAAkB;AAAA,cACpB,OAAO;AACL,sBAAM,oBAAoB,YAAY;AACtC,oBAAI,sCAAqD;AACzD,yBAAS,IAAI,GAAG,IAAI,mBAAmB,KAAK;AAC1C,wBAAM,WAAW,YAAY,CAAC;AAC9B,sBACE,SAAS,SAASC,oBAClB,SAAS,UAAU;AAEnB;AACF,sBAAI,SAAS,SAASA,kBAAiB;AACrC,0DAAsC;AACtC;AAAA,kBACF;AAAA,gBACF;AACA,oBAAI,wCAAwC,MAAM;AAChD,oCAAkB;AAClB,8BAAY,OAAO,qCAAqC,CAAC;AAAA,gBAC3D,OAAO;AACL;AAAA,gBACF;AAAA,cACF;AACA,uBAAS;AAAA,YACX,OAAO;AACL,kCAAoB;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAEA,YAAI,CAAC,eAAe;AAClB,4BAAkB,YAAY,MAAM,CAAC;AAAA,QACvC;AACA;AAAA,MACF,OAAO;AACL,0BAAkB;AAAA,MACpB;AAAA,IACF;AAEA,MAAI,iBAAiB,CAAC,YAAY;AAChC,QAAI,mCAAkD;AACtD,aAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,UAAI,YAAY,CAAC,MAAMA,kBAAiB;AACtC,2CAAmC;AAAA,MACrC;AAAA,IACF;AACA,qBACE,qCAAqC,OACjC,eAAe,MAAM,GAAG,mCAAmC,CAAC,IAC5D;AAAA,EACR;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM,EAAE,kBAAkB;AAAA,EAC5B;AACF;;;AClKA,IAAMC,eAAc;AACpB,IAAM,UAAU;AAChB,IAAM,YAAY;AAClB,IAAM,YACJ,OAAO,cAAc,eAAe,WAAW,KAAK,UAAU,SAAS;AACvE,IAAM,QAAQ,CAAC,OAAmB;AAChC,MAAI,OAAO,0BAA0B,aAAa;AAChD,0BAAsB,EAAE;AAAA,EAC1B,OAAO;AACL,eAAW,IAAI,CAAC;AAAA,EAClB;AACF;AAuCa,SAAR,2BACL,QACsB;AACtB,QAAM,QAAuC;AAAA,IAC3C,wBAAwB;AAAA,IACxB,qBAAqB;AAAA,EACvB;AAEA,SAAO;AAAA,IACL;AAAA,IAEA,OACE,UACA;AAAA,MACE;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,iBAAAC,mBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB,WAAW;AAAA,IACb,IAA+C,QAC/C;AACA,UAAI,OAAO,aAAa,aAAa;AACnC,mBAAW,cAAc;AAAA,MAC3B;AAEA,UAAI,aAAa,MAAM;AAAwB;AAE/C,UACE,OAAO,iBAAiB,aACvB,aAAqB,SAAS,UAC9B,aAAqB,SAAS,QAC/B;AACA,eAAQ,aAAqB;AAC7B,uBAAgB,aAAqB;AAAA,MACvC;AAEA,UAAI,OAAY;AAChB,UAAI;AACJ,UAAI;AAEJ,UAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,sBAAc,yBAAyB,MAAMA,gBAAe;AAAA,MAC9D,WAAW,OAAO,SAAS,YAAY;AACrC,cAAM,gBAAgB,KAAK,gBAAgB,QAAQ,GAAG;AAAA,UACpD,sBAAsB,cAAc;AAAA,UACpC,wBAAwB,MAAM;AAAA,UAC9B,iBAAAA;AAAA,QACF,CAAC;AAED,YAAI,kBAAkB;AAAO;AAE7B,cAAM,EAAE,uBAAuB,QAAQ,IACrC,kBAAkB,aAAa;AAEjC,eAAO;AACP,2BAAmB;AACnB,sBAAc,yBAAyB,MAAMA,gBAAe;AAAA,MAC9D;AAEA,UAAI,SAAS;AAAO;AAEpB,YAAM,eAAe,gBAAgB,QAAQ;AAC7C,YAAM,uBAAuB,cAAc,gBAAgB;AAC3D,YAAM,EAAE,wBAAwB,oBAAoB,IAAI;AAExD,YAAM,sBAAsB;AAAA,QAC1B;AAAA,QACA;AAAA,QACA,iBAAAA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,EAAE,eAAe,IAAI;AAAA,QACzB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,UAAI,sBAAsB;AAC1B,UAAI,sBAAgC,CAAC;AAErC,UAAI,OAAO,SAAS,YAAY;AAC9B,YAAI,aAAa,KAAK,gBAAgB;AAAA,UACpC,UAAU;AAAA,UACV,GAAG;AAAA,QACL,CAAC;AAED,YAAI,eAAe,OAAO;AACxB,uBAAa;AAAA,YACX,OAAO,0BAA0B;AAAA,YACjC,UAAU;AAAA,UACZ;AAAA,QACF,WAAW,SAAS,UAAU,GAAG;AAC/B,uBAAa,EAAE,OAAO,WAAW;AAAA,QACnC;AAEA,8BAAuB,WAAmB;AAC1C,8BAAuB,WAAmB,uBAAuB,CAAC;AAAA,MACpE;AAEA,YAAM,wBAAwB,oBAAoB;AAAA,QAChD;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAChB,aAAa,eAAe;AAAA,QAC5B,UAAU;AAAA,QACV;AAAA,QACA,iBAAAA;AAAA,QACA;AAAA,QACA,kBAAkB,oBAAoB,CAAC;AAAA,MACzC,CAAC;AAED,YAAM,0BACJ,wBAAwB,eAAe,0BAA0B;AACnE,YAAM,aAAa,WAAW,eAAe,KAAKD;AAClD,YAAM,oBAAoB,0BACtB,aACA;AAEJ,YAAM,yBAAyB;AAC/B,YAAM,sBAAsB;AAE5B,UAAI,CAAC,gBAAgB,aAAa,UAAU;AAAmB;AAE/D,mBAAa,QAAQ;AACrB,uBAAiB,cAAc,yBAAyB,CAAC;AAAA,IAC3D;AAAA,EACF;AACF;AAEA,SAAS,iBAAiB,SAA2B,UAAkB;AACrE,MAAI,SAAS,kBAAkB,SAAS;AACtC,UAAM,KAAK,MAAM,QAAQ,kBAAkB,UAAU,UAAU,OAAO;AAEtE,QAAI,WAAW;AACb,YAAM,EAAE;AAAA,IACV,OAAO;AACL,cAAQ,kBAAkB,UAAU,UAAU,OAAO;AAAA,IACvD;AAAA,EACF;AACF;AACA,SAAS,gBAAgB,OAAwB;AAC/C,MAAI,SAAS,KAAK;AAAG,WAAO;AAC5B,MAAI,SAAS,KAAK;AAAG,WAAO,OAAO,KAAK;AACxC,MAAI,UAAU,UAAa,UAAU;AAAM,WAAOA;AAElD,QAAM,IAAI;AAAA,IACR,iFAAiF,KAAK;AAAA,MACpF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AL/HM;AA7DC,IAAM,cAAc;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAAE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,WAAW,OAAgC,IAAI;AACrD,UAAM,WACH,OAAoD;AAEvD,UAAM,cAAc,OAAY,IAAI;AAEpC,UAAM,eAAe,YAAY,MAAM;AACrC,UAAI,CAAC,SAAS;AAAS;AAEvB,kBAAY,UAAU,2BAA2B;AAAA,QAC/C,cAAc,SAAS;AAAA,QACvB;AAAA,QACA;AAAA,QACA;AAAA,QACA,iBAAAA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,kBAAY,QAAQ,OAAO,KAAK;AAAA,IAElC,GAAG;AAAA,MACD;AAAA,MACA;AAAA,MACA;AAAA,MACAA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,cAAU,MAAM;AACd,mBAAa;AAAA,IACf,GAAG,CAAC,YAAY,CAAC;AAEjB,UAAM,eAAe,CAAC,UAAyC;AAC7D,kBAAY,SAAS,OAAO;AAC5B,iBAAW,KAAK;AAAA,IAClB;AAEA,UAAM,aAAa,CAAC,UAAwC;AAC1D,eAAS,KAAK;AAAA,IAChB;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK,CAAC,OAAO;AACX,mBAAS,UAAU;AACnB,cAAI,OAAO,QAAQ,YAAY;AAC7B,gBAAI,EAAE;AAAA,UACR,WAAW,KAAK;AACd,YAAC,IAAiD,UAAU;AAAA,UAC9D;AAAA,QACF;AAAA,QACA,QAAQ;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACC,GAAG;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;","names":["placeholderChar","placeholderChar","emptyString","placeholderChar","emptyString","placeholderChar","placeholderChar"]}