@samline/formatter 1.0.1 → 1.1.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/README.md +6 -4
- package/dist/browser/global.d.ts +209 -10
- package/dist/browser/global.global.js +239 -44
- package/dist/index.cjs +209 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +316 -6
- package/dist/index.d.ts +316 -6
- package/dist/index.js +209 -14
- package/dist/index.js.map +1 -1
- package/dist/vanilla/index.cjs +209 -14
- package/dist/vanilla/index.cjs.map +1 -1
- package/dist/vanilla/index.d.cts +316 -6
- package/dist/vanilla/index.d.ts +316 -6
- package/dist/vanilla/index.js +209 -14
- package/dist/vanilla/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/phone.ts","../../src/core/raw.ts","../../src/core/format.ts","../../src/core/formatter.ts","../../src/core/regex.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { AsYouType, type CountryCode } from 'libphonenumber-js'\n\n/**\n * Format a phone number string using `libphonenumber-js`'s `AsYouType`.\n *\n * Non-digit characters are stripped before formatting (the leading `+` is\n * preserved so international numbers keep their country prefix). After\n * formatting, spaces produced by `AsYouType` are swapped for `delimiter` when\n * a custom delimiter is provided.\n *\n * @param value - The raw input (digits, `+`, spaces, dashes, parentheses, etc.).\n * @param country - ISO 3166-1 alpha-2 country code (e.g. `'MX'`, `'US'`).\n * @param delimiter - Character used to separate groups in the output.\n * @returns The formatted phone string, or `''` when `value` is empty.\n */\nexport const formatPhone = (\n value: string,\n country: string = 'MX',\n delimiter: string = ' '\n): string => {\n if (!value) return ''\n\n // Preserve '+' so international numbers keep their prefix.\n const digits = value.replace(/[^\\d+]/g, '')\n const formatter = new AsYouType(country as CountryCode)\n const formatted = formatter.input(digits)\n\n if (delimiter !== ' ') {\n return formatted.replace(/ /g, delimiter)\n }\n\n return formatted\n}","import {\n unformatCreditCard,\n unformatGeneral,\n unformatNumeral,\n type DatePatternType,\n type DateUnit,\n type FormatCreditCardOptions,\n type FormatDateOptions,\n type FormatGeneralOptions,\n type FormatNumeralOptions,\n type FormatTimeOptions,\n type TimePatternType,\n type TimeUnit\n} from 'cleave-zen'\n\nexport type FormatType =\n | 'general'\n | 'phone'\n | 'numeral'\n | 'date'\n | 'time'\n | 'creditCard'\n | 'creditCardType'\n\ntype ExtraFormatOptions = {\n country?: string\n dateRawPattern?: DatePatternType\n dateRawPatternDelimiter?: string\n timeRawPattern?: TimePatternType\n timeRawPatternDelimiter?: string\n tailPrefix?: boolean\n}\n\nexport type FormatOptions = Partial<\nFormatGeneralOptions &\nFormatNumeralOptions &\nFormatDateOptions &\nFormatTimeOptions &\nFormatCreditCardOptions\n> &\nExtraFormatOptions\n\ntype DateSegmentKey = 'day' | 'month' | 'year'\ntype TimeSegmentKey = 'hours' | 'minutes' | 'seconds'\n\nconst DEFAULT_DATE_PATTERN: DatePatternType = ['d', 'm', 'Y']\nconst DEFAULT_DATE_RAW_PATTERN: DatePatternType = ['Y', 'm', 'd']\nconst DEFAULT_DATE_RAW_PATTERN_DELIMITER = '-'\nconst DEFAULT_TIME_PATTERN: TimePatternType = ['h', 'm', 's']\nconst DEFAULT_TIME_RAW_PATTERN: TimePatternType = ['h', 'm']\nconst DEFAULT_TIME_RAW_PATTERN_DELIMITER = ':'\n\nconst getDateSegmentKey = (unit: DateUnit): DateSegmentKey => {\n switch (unit.toLowerCase()) {\n case 'd':\n return 'day'\n case 'm':\n return 'month'\n default:\n return 'year'\n }\n}\n\nconst getDateUnitLength = (unit: DateUnit): 2 | 4 =>\n unit === 'Y' ? 4 : 2\n\nconst normalizeDateSegment = (segment: string, unit: DateUnit): string => {\n if (!segment) return ''\n\n switch (unit) {\n case 'y':\n return segment.slice(-2)\n case 'Y':\n return segment.slice(0, 4)\n default:\n return segment.slice(0, 2)\n }\n}\n\nconst getDateSegments = (\n value: string,\n pattern: DatePatternType\n): Partial<Record<DateSegmentKey, string>> => {\n const digits = value.replace(/[^\\d]/g, '')\n const segments: Partial<Record<DateSegmentKey, string>> = {}\n let start = 0\n\n for (const unit of pattern) {\n const end = start + getDateUnitLength(unit)\n const segment = digits.slice(start, end)\n\n if (segment) {\n segments[getDateSegmentKey(unit)] = segment\n }\n\n start = end\n }\n\n return segments\n}\n\nconst formatDateSegments = (\n segments: Partial<Record<DateSegmentKey, string>>,\n pattern: DatePatternType,\n delimiter = ''\n): string =>\n pattern\n .map((unit) =>\n normalizeDateSegment(segments[getDateSegmentKey(unit)] ?? '', unit)\n )\n .filter(Boolean)\n .join(delimiter)\n\nconst getTimeSegmentKey = (unit: TimeUnit): TimeSegmentKey => {\n switch (unit) {\n case 'h':\n return 'hours'\n case 'm':\n return 'minutes'\n default:\n return 'seconds'\n }\n}\n\nconst getTimeSegments = (\n value: string,\n pattern: TimePatternType\n): Partial<Record<TimeSegmentKey, string>> => {\n const digits = value.replace(/[^\\d]/g, '')\n const segments: Partial<Record<TimeSegmentKey, string>> = {}\n let start = 0\n\n for (const unit of pattern) {\n const end = start + 2\n const segment = digits.slice(start, end)\n\n if (segment) {\n segments[getTimeSegmentKey(unit)] = segment\n }\n\n start = end\n }\n\n return segments\n}\n\nconst formatTimeSegments = (\n segments: Partial<Record<TimeSegmentKey, string>>,\n pattern: TimePatternType,\n delimiter = ''\n): string =>\n pattern\n .map((unit) => (segments[getTimeSegmentKey(unit)] ?? '').slice(0, 2))\n .filter(Boolean)\n .join(delimiter)\n\n/**\n * Convert a raw date string (e.g. `2026-05-12`) into the digit order of the\n * display pattern (e.g. `12/05/2026` → `12052026`).\n *\n * The output is intentionally digits-only and un-delimited — the caller is\n * expected to pass the result through `cleave-zen`'s `formatDate` (or an\n * equivalent) to add the configured delimiter. The source pattern is\n * `dateRawPattern`; the target pattern is `datePattern`.\n */\nexport const getDateValueFromRaw = (\n value: string,\n options: FormatOptions = {}\n): string => {\n const sourcePattern = options.dateRawPattern ?? DEFAULT_DATE_RAW_PATTERN\n const targetPattern = options.datePattern ?? DEFAULT_DATE_PATTERN\n\n return formatDateSegments(\n getDateSegments(value, sourcePattern),\n targetPattern\n )\n}\n\n/**\n * Convert a raw time string (e.g. `14:30`) into the digit order of the\n * display pattern (e.g. `14:30:00` → `1430`).\n *\n * The output is intentionally digits-only and un-delimited — the caller is\n * expected to pass the result through `cleave-zen`'s `formatTime` (or an\n * equivalent) to add the configured delimiter and pad missing segments.\n * The source pattern is `timeRawPattern`; the target pattern is\n * `timePattern`.\n */\nexport const getTimeValueFromRaw = (\n value: string,\n options: FormatOptions = {}\n): string => {\n const sourcePattern =\n options.timeRawPattern ?? options.timePattern ?? DEFAULT_TIME_RAW_PATTERN\n const targetPattern = options.timePattern ?? DEFAULT_TIME_PATTERN\n\n return formatTimeSegments(\n getTimeSegments(value, sourcePattern),\n targetPattern\n )\n}\n\nconst getDateRawValue = (\n value: string,\n options: FormatOptions = {}\n): string => {\n const sourcePattern = options.datePattern ?? DEFAULT_DATE_PATTERN\n const targetPattern = options.dateRawPattern ?? DEFAULT_DATE_RAW_PATTERN\n const delimiter =\n options.dateRawPatternDelimiter ?? DEFAULT_DATE_RAW_PATTERN_DELIMITER\n\n return formatDateSegments(\n getDateSegments(value, sourcePattern),\n targetPattern,\n delimiter\n )\n}\n\nconst getTimeRawValue = (\n value: string,\n options: FormatOptions = {}\n): string => {\n const sourcePattern = options.timePattern ?? DEFAULT_TIME_PATTERN\n const targetPattern =\n options.timeRawPattern ?? options.timePattern ?? DEFAULT_TIME_RAW_PATTERN\n const delimiter =\n options.timeRawPatternDelimiter ?? DEFAULT_TIME_RAW_PATTERN_DELIMITER\n\n return formatTimeSegments(\n getTimeSegments(value, sourcePattern),\n targetPattern,\n delimiter\n )\n}\n\n/**\n * Strip a configured `prefix` from either the start or the end of `value`.\n * `tailPrefix: true` treats the prefix as a suffix.\n */\nexport const stripPrefixAndSuffix = (\n value: string,\n options: FormatOptions = {}\n): string => {\n if (!value || !options.prefix) return value\n\n const { prefix } = options\n const tailPrefix = options.tailPrefix ?? false\n\n if (tailPrefix && value.endsWith(prefix)) {\n return value.slice(0, -prefix.length)\n }\n\n if (!tailPrefix && value.startsWith(prefix)) {\n return value.slice(prefix.length)\n }\n\n return value\n}\n\n/**\n * Convert a formatted value back into its raw counterpart (digits only,\n * canonical structure ready to ship to a backend).\n */\nexport const getRawValue = (\n value: string,\n formatType: FormatType,\n options: FormatOptions = {}\n): string => {\n if (!value) return ''\n\n const cleanValue = stripPrefixAndSuffix(value, options)\n\n switch (formatType) {\n case 'numeral': {\n const numeralOpts: { numeralDecimalMark?: string } = {}\n if (options.numeralDecimalMark !== undefined) {\n numeralOpts.numeralDecimalMark = options.numeralDecimalMark\n }\n return unformatNumeral(cleanValue, numeralOpts)\n }\n\n case 'creditCard':\n case 'creditCardType':\n return unformatCreditCard(cleanValue)\n\n case 'general': {\n const generalOpts: {\n delimiter?: string\n delimiters?: string[]\n } = {}\n if (options.delimiter !== undefined) generalOpts.delimiter = options.delimiter\n if (options.delimiters !== undefined) generalOpts.delimiters = options.delimiters\n return unformatGeneral(cleanValue, generalOpts)\n }\n\n case 'date':\n return getDateRawValue(cleanValue, options)\n\n case 'time':\n return getTimeRawValue(cleanValue, options)\n\n case 'phone':\n return cleanValue.replace(/[^\\d+]/g, '')\n\n default:\n return cleanValue.replace(/\\s+/g, '')\n }\n}","import {\n formatCreditCard,\n formatDate,\n formatGeneral,\n formatNumeral,\n formatTime,\n getCreditCardType,\n type FormatGeneralOptions\n} from 'cleave-zen'\n\nimport { formatPhone } from './phone.js'\nimport {\n getDateValueFromRaw,\n getTimeValueFromRaw,\n type FormatOptions,\n type FormatType\n} from './raw.js'\n\nexport type { FormatOptions, FormatType }\n\nexport const FORMAT_TYPES = [\n 'general',\n 'phone',\n 'numeral',\n 'date',\n 'time',\n 'creditCard',\n 'creditCardType'\n] as const satisfies readonly FormatType[]\n\nexport const isFormatType = (value: unknown): value is FormatType =>\n typeof value === 'string' &&\n (FORMAT_TYPES as readonly string[]).includes(value)\n\ntype RuntimeOptions = FormatOptions & {\n country: string\n delimiter?: string\n}\n\n// Per-type defaults applied only when the caller does not pass their own.\n// `phone` overrides cleave-zen because libphonenumber emits spaces natively;\n// every other type lets cleave-zen pick its own idiomatic delimiter\n// (`/`, `:`, `,`, etc.) by leaving `delimiter` undefined on the runtime\n// options object passed downstream.\nconst PHONE_DEFAULT_DELIMITER = ' '\nconst PHONE_DEFAULT_COUNTRY = 'MX'\n\n/**\n * Internal: pick a country/delimiter-aware runtime options object with\n * phone-specific defaults applied. For non-phone formats the `delimiter`\n * is left as the user supplied it (or absent) so cleave-zen falls back to\n * its idiomatic defaults.\n */\nconst resolveRuntimeOptions = (\n formatType: FormatType,\n options: FormatOptions = {}\n): RuntimeOptions => {\n const isPhone = formatType === 'phone'\n const country = options.country ?? (isPhone ? PHONE_DEFAULT_COUNTRY : '')\n\n // Build the runtime options without ever assigning `undefined` to optional\n // fields (so `exactOptionalPropertyTypes` stays happy) and without ever\n // adding an explicit empty-string `delimiter` for non-phone types (so\n // cleave-zen falls back to its own idiomatic default).\n const runtime: RuntimeOptions = {\n ...options,\n country\n }\n\n if (options.delimiter !== undefined) {\n runtime.delimiter = options.delimiter\n } else if (isPhone) {\n runtime.delimiter = PHONE_DEFAULT_DELIMITER\n }\n\n return runtime\n}\n\n/**\n * Internal: format a pre-processed value into its display representation\n * by delegating to the matching `cleave-zen` (or `formatPhone`) helper.\n */\nconst formatValue = (\n value: string,\n formatType: FormatType,\n options: RuntimeOptions\n): string => {\n switch (formatType) {\n case 'phone':\n return formatPhone(value, options.country, options.delimiter)\n\n case 'numeral':\n return formatNumeral(value, options)\n\n case 'date':\n return formatDate(value, options)\n\n case 'time':\n return formatTime(value, options)\n\n case 'creditCard':\n return formatCreditCard(value, options)\n\n case 'creditCardType':\n return getCreditCardType(value, options.delimiter)\n\n case 'general':\n // cleave-zen's `formatGeneral` requires `blocks` in its options;\n // `FormatOptions` does not declare it (consumers pick blocks via\n // their own configuration). This cast is the documented seam.\n return formatGeneral(\n value,\n options as unknown as FormatGeneralOptions\n )\n }\n}\n\n/**\n * Internal: pre-process `value` before passing it to the per-type formatter.\n * Date and time inputs are first converted from raw to the display pattern\n * (so users can type either formatted or raw and still get sensible output).\n */\nconst getValueForFormatting = (\n value: string,\n formatType: FormatType,\n options: RuntimeOptions\n): string => {\n if (formatType === 'date') {\n return getDateValueFromRaw(value, options)\n }\n\n if (formatType === 'time') {\n return getTimeValueFromRaw(value, options)\n }\n\n return value\n}\n\nexport { formatValue, getValueForFormatting, resolveRuntimeOptions }","import {\n formatValue,\n getValueForFormatting,\n resolveRuntimeOptions,\n FORMAT_TYPES,\n isFormatType,\n type FormatType\n} from './format.js'\n\nimport { getRawValue, stripPrefixAndSuffix } from './raw.js'\n\nimport type { FormatterResult, FormatOptions } from './types.js'\n\nexport type { FormatOptions, FormatType, FormatterResult }\nexport { FORMAT_TYPES, isFormatType, stripPrefixAndSuffix }\n\n/**\n * Format `value` according to `formatType`, returning both a presentable\n * `formatted` string and a backend-ready `raw` string.\n *\n * The function is pure: it never touches the DOM and never reads from the\n * network. Pair it with your own input wiring (React, Vue, Svelte, vanilla)\n * to drive the visible field; mirror `result.raw` into a hidden input when\n * shipping to a server that expects clean digits.\n *\n * @param value - The raw value typed by the user (`null`/`undefined`/`''` return an empty result).\n * @param formatType - One of the supported `FormatType` values.\n * @param options - Per-type options (see `FormatOptions`).\n * @returns A `FormatterResult` with `formatted`, `raw`, and the echoed `type`.\n * @throws {TypeError} When `formatType` is not one of the supported types.\n */\nexport const format = (\n value: unknown,\n formatType: FormatType,\n options: FormatOptions = {}\n): FormatterResult => {\n if (!isFormatType(formatType)) {\n throw new TypeError(\n `Invalid formatType: ${String(formatType)}. Expected one of: ${FORMAT_TYPES.join(', ')}`\n )\n }\n\n if (value === null || value === undefined || value === '') {\n return { formatted: '', raw: '', type: formatType }\n }\n\n const runtime = resolveRuntimeOptions(formatType, options)\n const stringValue = typeof value === 'string' ? value : String(value)\n const cleanValue = stripPrefixAndSuffix(stringValue, runtime)\n const preValue = getValueForFormatting(cleanValue, formatType, runtime)\n const formatted = formatValue(preValue, formatType, runtime)\n // `getRawValue` normally consumes the *formatted* display string (mirrors\n // the original `syncRawInputValue` pipeline). The one exception is\n // `creditCardType`, where `formatted` is the card brand name (e.g. \"visa\")\n // rather than the card number — the raw needs to come from the cleaned\n // input directly.\n const raw =\n formatType === 'creditCardType'\n ? getRawValue(cleanValue, formatType, runtime)\n : getRawValue(formatted, formatType, runtime)\n\n return { formatted, raw, type: formatType }\n}","// Validation patterns exposed as public API for form consumers that pair\n// formatting with validation. Each entry bundles the regex with a ready-to-use\n// error message so consumers do not have to keep them in sync.\n\nexport const regex = {\n phone: {\n // 10 digit phone numbers, allowing for optional country code and delimiters\n pattern: /^(?:\\D*\\d){10}\\D*$/,\n errorMessage: 'Please enter a valid 10-digit phone number.'\n },\n email: {\n pattern: /^[^\\s@]+@[^\\s@]+\\.[a-zA-Z]{2,}$/,\n errorMessage: 'Please enter a valid email address.'\n },\n rfc: {\n // Mexican RFC format (simplified)\n pattern: /^([A-ZÑ&]{3,4})\\d{6}([A-Z0-9]{0,3})$/i,\n errorMessage: 'Please enter a valid RFC.'\n },\n numeral: {\n // Numbers with optional thousand separators and decimal points\n pattern: /\\d{1,3}(,\\d{3})*(\\.\\d+)?/,\n errorMessage: 'Please enter a valid number.'\n },\n onlyNumbers: {\n pattern: /^\\d+$/,\n errorMessage: 'Please enter only numbers.'\n },\n creditCard: {\n // 15 or 16 digits, allowing spaces or delimiters\n pattern: /^(?:\\D*\\d){15,16}\\D*$/,\n errorMessage: 'Please enter a valid card number.'\n },\n expirationDate: {\n // MM/YY format\n pattern: /^(0[1-9]|1[0-2])\\/\\d{2}$/,\n errorMessage: 'Please enter a valid expiration date.'\n },\n cardCvc: {\n // 3 or 4 digit card security codes\n pattern: /^\\d{3,4}$/,\n errorMessage: 'Please enter a valid CVC.'\n },\n onlyLetters: {\n // Letters only (including accented characters and spaces)\n pattern: /^[A-Za-zÁÉÍÓÚáéíóúÑñ\\s]+$/,\n errorMessage: 'Please enter only letters.'\n },\n onlyAlphanumeric: {\n // Letters and numbers (including accented characters and spaces)\n pattern: /^[A-Za-zÁÉÍÓÚáéíóúÑñ0-9\\s]+$/,\n errorMessage: 'Please enter only letters and numbers.'\n }\n} as const\n\nexport type RegexKey = keyof typeof regex"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/phone.ts","../../src/core/raw.ts","../../src/core/format.ts","../../src/core/formatter.ts","../../src/core/regex.ts"],"names":["digits"],"mappings":"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","file":"index.js","sourcesContent":["import { AsYouType, type CountryCode } from 'libphonenumber-js'\n\n/**\n * Format a phone number string using `libphonenumber-js`'s `AsYouType`.\n *\n * Non-digit characters are stripped before formatting (the leading `+` is\n * preserved so international numbers keep their country prefix). After\n * formatting, spaces produced by `AsYouType` are swapped for `delimiter` when\n * a custom delimiter is provided.\n *\n * @param value - The raw input (digits, `+`, spaces, dashes, parentheses, etc.).\n * @param country - ISO 3166-1 alpha-2 country code (e.g. `'MX'`, `'US'`).\n * @param delimiter - Character used to separate groups in the output.\n * @returns The formatted phone string, or `''` when `value` is empty.\n */\nexport const formatPhone = (\n value: string,\n country: string = 'MX',\n delimiter: string = ' '\n): string => {\n if (!value) return ''\n\n // Preserve '+' so international numbers keep their prefix.\n const digits = value.replace(/[^\\d+]/g, '')\n const formatter = new AsYouType(country as CountryCode)\n const formatted = formatter.input(digits)\n\n if (delimiter !== ' ') {\n return formatted.replace(/ /g, delimiter)\n }\n\n return formatted\n}","import {\n unformatCreditCard,\n unformatGeneral,\n unformatNumeral,\n type DatePatternType,\n type DateUnit,\n type FormatCreditCardOptions,\n type FormatDateOptions,\n type FormatGeneralOptions,\n type FormatNumeralOptions,\n type FormatTimeOptions,\n type TimePatternType,\n type TimeUnit\n} from 'cleave-zen'\n\nexport type FormatType =\n | 'general'\n | 'phone'\n | 'numeral'\n | 'date'\n | 'time'\n | 'creditCard'\n | 'creditCardType'\n\ntype ExtraFormatOptions = {\n country?: string\n dateRawPattern?: DatePatternType\n dateRawPatternDelimiter?: string\n timeRawPattern?: TimePatternType\n timeRawPatternDelimiter?: string\n tailPrefix?: boolean\n}\n\nexport type FormatOptions = Partial<\nFormatGeneralOptions &\nFormatNumeralOptions &\nFormatDateOptions &\nFormatTimeOptions &\nFormatCreditCardOptions\n> &\nExtraFormatOptions\n\ntype DateSegmentKey = 'day' | 'month' | 'year'\ntype TimeSegmentKey = 'hours' | 'minutes' | 'seconds'\n\nconst DEFAULT_DATE_PATTERN: DatePatternType = ['d', 'm', 'Y']\nconst DEFAULT_DATE_RAW_PATTERN: DatePatternType = ['Y', 'm', 'd']\nconst DEFAULT_DATE_RAW_PATTERN_DELIMITER = '-'\nconst DEFAULT_TIME_PATTERN: TimePatternType = ['h', 'm', 's']\nconst DEFAULT_TIME_RAW_PATTERN: TimePatternType = ['h', 'm']\nconst DEFAULT_TIME_RAW_PATTERN_DELIMITER = ':'\n\nconst getDateSegmentKey = (unit: DateUnit): DateSegmentKey => {\n switch (unit.toLowerCase()) {\n case 'd':\n return 'day'\n case 'm':\n return 'month'\n default:\n return 'year'\n }\n}\n\nconst getDateUnitLength = (unit: DateUnit): 2 | 4 =>\n unit === 'Y' ? 4 : 2\n\nconst normalizeDateSegment = (segment: string, unit: DateUnit): string => {\n if (!segment) return ''\n\n switch (unit) {\n case 'y':\n return segment.slice(-2)\n case 'Y':\n return segment.slice(0, 4)\n default:\n return segment.slice(0, 2)\n }\n}\n\nconst getDateSegments = (\n value: string,\n pattern: DatePatternType\n): Partial<Record<DateSegmentKey, string>> => {\n const digits = value.replace(/[^\\d]/g, '')\n const segments: Partial<Record<DateSegmentKey, string>> = {}\n let start = 0\n\n for (const unit of pattern) {\n const end = start + getDateUnitLength(unit)\n const segment = digits.slice(start, end)\n\n if (segment) {\n segments[getDateSegmentKey(unit)] = segment\n }\n\n start = end\n }\n\n return segments\n}\n\nconst formatDateSegments = (\n segments: Partial<Record<DateSegmentKey, string>>,\n pattern: DatePatternType,\n delimiter = ''\n): string =>\n pattern\n .map((unit) =>\n normalizeDateSegment(segments[getDateSegmentKey(unit)] ?? '', unit)\n )\n .filter(Boolean)\n .join(delimiter)\n\nconst getTimeSegmentKey = (unit: TimeUnit): TimeSegmentKey => {\n switch (unit) {\n case 'h':\n return 'hours'\n case 'm':\n return 'minutes'\n default:\n return 'seconds'\n }\n}\n\nconst getTimeSegments = (\n value: string,\n pattern: TimePatternType\n): Partial<Record<TimeSegmentKey, string>> => {\n const digits = value.replace(/[^\\d]/g, '')\n const segments: Partial<Record<TimeSegmentKey, string>> = {}\n let start = 0\n\n for (const unit of pattern) {\n const end = start + 2\n const segment = digits.slice(start, end)\n\n if (segment) {\n segments[getTimeSegmentKey(unit)] = segment\n }\n\n start = end\n }\n\n return segments\n}\n\nconst formatTimeSegments = (\n segments: Partial<Record<TimeSegmentKey, string>>,\n pattern: TimePatternType,\n delimiter = ''\n): string =>\n pattern\n .map((unit) => (segments[getTimeSegmentKey(unit)] ?? '').slice(0, 2))\n .filter(Boolean)\n .join(delimiter)\n\n/**\n * Convert a raw date string (e.g. `2026-05-12`) into the digit order of the\n * display pattern (e.g. `12/05/2026` → `12052026`).\n *\n * The output is intentionally digits-only and un-delimited — the caller is\n * expected to pass the result through `cleave-zen`'s `formatDate` (or an\n * equivalent) to add the configured delimiter. The source pattern is\n * `dateRawPattern`; the target pattern is `datePattern`.\n */\nexport const getDateValueFromRaw = (\n value: string,\n options: FormatOptions = {}\n): string => {\n const sourcePattern = options.dateRawPattern ?? DEFAULT_DATE_RAW_PATTERN\n const targetPattern = options.datePattern ?? DEFAULT_DATE_PATTERN\n\n return formatDateSegments(\n getDateSegments(value, sourcePattern),\n targetPattern\n )\n}\n\n/**\n * Convert a raw time string (e.g. `14:30`) into the digit order of the\n * display pattern (e.g. `14:30:00` → `1430`).\n *\n * The output is intentionally digits-only and un-delimited — the caller is\n * expected to pass the result through `cleave-zen`'s `formatTime` (or an\n * equivalent) to add the configured delimiter and pad missing segments.\n * The source pattern is `timeRawPattern`; the target pattern is\n * `timePattern`.\n */\nexport const getTimeValueFromRaw = (\n value: string,\n options: FormatOptions = {}\n): string => {\n const sourcePattern =\n options.timeRawPattern ?? options.timePattern ?? DEFAULT_TIME_RAW_PATTERN\n const targetPattern = options.timePattern ?? DEFAULT_TIME_PATTERN\n\n return formatTimeSegments(\n getTimeSegments(value, sourcePattern),\n targetPattern\n )\n}\n\nconst getDateRawValue = (\n value: string,\n options: FormatOptions = {}\n): string => {\n const sourcePattern = options.datePattern ?? DEFAULT_DATE_PATTERN\n const targetPattern = options.dateRawPattern ?? DEFAULT_DATE_RAW_PATTERN\n const delimiter =\n options.dateRawPatternDelimiter ?? DEFAULT_DATE_RAW_PATTERN_DELIMITER\n\n return formatDateSegments(\n getDateSegments(value, sourcePattern),\n targetPattern,\n delimiter\n )\n}\n\nconst getTimeRawValue = (\n value: string,\n options: FormatOptions = {}\n): string => {\n const sourcePattern = options.timePattern ?? DEFAULT_TIME_PATTERN\n const targetPattern =\n options.timeRawPattern ?? options.timePattern ?? DEFAULT_TIME_RAW_PATTERN\n const delimiter =\n options.timeRawPatternDelimiter ?? DEFAULT_TIME_RAW_PATTERN_DELIMITER\n\n return formatTimeSegments(\n getTimeSegments(value, sourcePattern),\n targetPattern,\n delimiter\n )\n}\n\n/**\n * Strip a configured `prefix` from either the start or the end of `value`.\n * `tailPrefix: true` treats the prefix as a suffix.\n */\nexport const stripPrefixAndSuffix = (\n value: string,\n options: FormatOptions = {}\n): string => {\n if (!value || !options.prefix) return value\n\n const { prefix } = options\n const tailPrefix = options.tailPrefix ?? false\n\n if (tailPrefix && value.endsWith(prefix)) {\n return value.slice(0, -prefix.length)\n }\n\n if (!tailPrefix && value.startsWith(prefix)) {\n return value.slice(prefix.length)\n }\n\n return value\n}\n\n/**\n * Convert a formatted value back into its raw counterpart (digits only,\n * canonical structure ready to ship to a backend).\n */\nexport const getRawValue = (\n value: string,\n formatType: FormatType,\n options: FormatOptions = {}\n): string => {\n if (!value) return ''\n\n const cleanValue = stripPrefixAndSuffix(value, options)\n\n switch (formatType) {\n case 'numeral': {\n const numeralOpts: { numeralDecimalMark?: string } = {}\n if (options.numeralDecimalMark !== undefined) {\n numeralOpts.numeralDecimalMark = options.numeralDecimalMark\n }\n return unformatNumeral(cleanValue, numeralOpts)\n }\n\n case 'creditCard':\n case 'creditCardType':\n return unformatCreditCard(cleanValue)\n\n case 'general': {\n const generalOpts: {\n delimiter?: string\n delimiters?: string[]\n } = {}\n if (options.delimiter !== undefined) generalOpts.delimiter = options.delimiter\n if (options.delimiters !== undefined) generalOpts.delimiters = options.delimiters\n return unformatGeneral(cleanValue, generalOpts)\n }\n\n case 'date':\n return getDateRawValue(cleanValue, options)\n\n case 'time':\n return getTimeRawValue(cleanValue, options)\n\n case 'phone':\n return cleanValue.replace(/[^\\d+]/g, '')\n\n default:\n return cleanValue.replace(/\\s+/g, '')\n }\n}","import {\n formatCreditCard,\n formatDate,\n formatGeneral,\n formatNumeral,\n formatTime,\n getCreditCardType,\n type FormatGeneralOptions\n} from 'cleave-zen'\n\nimport { formatPhone } from './phone.js'\nimport {\n getDateValueFromRaw,\n getTimeValueFromRaw,\n type FormatOptions,\n type FormatType\n} from './raw.js'\n\nexport type { FormatOptions, FormatType }\n\nexport const FORMAT_TYPES = [\n 'general',\n 'phone',\n 'numeral',\n 'date',\n 'time',\n 'creditCard',\n 'creditCardType'\n] as const satisfies readonly FormatType[]\n\nexport const isFormatType = (value: unknown): value is FormatType =>\n typeof value === 'string' &&\n (FORMAT_TYPES as readonly string[]).includes(value)\n\ntype RuntimeOptions = FormatOptions & {\n country: string\n delimiter?: string\n}\n\n// Per-type defaults applied only when the caller does not pass their own.\n// `phone` overrides cleave-zen because libphonenumber emits spaces natively;\n// every other type lets cleave-zen pick its own idiomatic delimiter\n// (`/`, `:`, `,`, etc.) by leaving `delimiter` undefined on the runtime\n// options object passed downstream.\nconst PHONE_DEFAULT_DELIMITER = ' '\nconst PHONE_DEFAULT_COUNTRY = 'MX'\n\n/**\n * Internal: pick a country/delimiter-aware runtime options object with\n * phone-specific defaults applied. For non-phone formats the `delimiter`\n * is left as the user supplied it (or absent) so cleave-zen falls back to\n * its idiomatic defaults.\n */\nconst resolveRuntimeOptions = (\n formatType: FormatType,\n options: FormatOptions = {}\n): RuntimeOptions => {\n const isPhone = formatType === 'phone'\n const country = options.country ?? (isPhone ? PHONE_DEFAULT_COUNTRY : '')\n\n // Build the runtime options without ever assigning `undefined` to optional\n // fields (so `exactOptionalPropertyTypes` stays happy) and without ever\n // adding an explicit empty-string `delimiter` for non-phone types (so\n // cleave-zen falls back to its own idiomatic default).\n const runtime: RuntimeOptions = {\n ...options,\n country\n }\n\n if (options.delimiter !== undefined) {\n runtime.delimiter = options.delimiter\n } else if (isPhone) {\n runtime.delimiter = PHONE_DEFAULT_DELIMITER\n }\n\n return runtime\n}\n\n/**\n * Internal: format a pre-processed value into its display representation\n * by delegating to the matching `cleave-zen` (or `formatPhone`) helper.\n */\nconst formatValue = (\n value: string,\n formatType: FormatType,\n options: RuntimeOptions\n): string => {\n switch (formatType) {\n case 'phone':\n return formatPhone(value, options.country, options.delimiter)\n\n case 'numeral':\n return formatNumeral(value, options)\n\n case 'date':\n return formatDate(value, options)\n\n case 'time':\n return formatTime(value, options)\n\n case 'creditCard':\n return formatCreditCard(value, options)\n\n case 'creditCardType':\n return getCreditCardType(value, options.delimiter)\n\n case 'general':\n // cleave-zen's `formatGeneral` requires `blocks` in its options;\n // `FormatOptions` does not declare it (consumers pick blocks via\n // their own configuration). This cast is the documented seam.\n return formatGeneral(\n value,\n options as unknown as FormatGeneralOptions\n )\n }\n}\n\n/**\n * Internal: pre-process `value` before passing it to the per-type formatter.\n * Date and time inputs are first converted from raw to the display pattern\n * (so users can type either formatted or raw and still get sensible output).\n */\nconst getValueForFormatting = (\n value: string,\n formatType: FormatType,\n options: RuntimeOptions\n): string => {\n if (formatType === 'date') {\n return getDateValueFromRaw(value, options)\n }\n\n if (formatType === 'time') {\n return getTimeValueFromRaw(value, options)\n }\n\n return value\n}\n\nexport { formatValue, getValueForFormatting, resolveRuntimeOptions }","import {\n formatValue,\n getValueForFormatting,\n resolveRuntimeOptions,\n FORMAT_TYPES,\n isFormatType,\n type FormatType\n} from './format.js'\n\nimport { getRawValue, stripPrefixAndSuffix } from './raw.js'\n\nimport type { FormatterResult, FormatOptions } from './types.js'\n\nexport type { FormatOptions, FormatType, FormatterResult }\nexport { FORMAT_TYPES, isFormatType, stripPrefixAndSuffix }\n\n/**\n * Format `value` according to `formatType`, returning both a presentable\n * `formatted` string and a backend-ready `raw` string.\n *\n * The function is pure: it never touches the DOM and never reads from the\n * network. Pair it with your own input wiring (React, Vue, Svelte, vanilla)\n * to drive the visible field; mirror `result.raw` into a hidden input when\n * shipping to a server that expects clean digits.\n *\n * @param value - The raw value typed by the user (`null`/`undefined`/`''` return an empty result).\n * @param formatType - One of the supported `FormatType` values.\n * @param options - Per-type options (see `FormatOptions`).\n * @returns A `FormatterResult` with `formatted`, `raw`, and the echoed `type`.\n * @throws {TypeError} When `formatType` is not one of the supported types.\n */\nexport const format = (\n value: unknown,\n formatType: FormatType,\n options: FormatOptions = {}\n): FormatterResult => {\n if (!isFormatType(formatType)) {\n throw new TypeError(\n `Invalid formatType: ${String(formatType)}. Expected one of: ${FORMAT_TYPES.join(', ')}`\n )\n }\n\n if (value === null || value === undefined || value === '') {\n return { formatted: '', raw: '', type: formatType }\n }\n\n const runtime = resolveRuntimeOptions(formatType, options)\n const stringValue = typeof value === 'string' ? value : String(value)\n const cleanValue = stripPrefixAndSuffix(stringValue, runtime)\n const preValue = getValueForFormatting(cleanValue, formatType, runtime)\n const formatted = formatValue(preValue, formatType, runtime)\n // `getRawValue` normally consumes the *formatted* display string (mirrors\n // the original `syncRawInputValue` pipeline). The one exception is\n // `creditCardType`, where `formatted` is the card brand name (e.g. \"visa\")\n // rather than the card number — the raw needs to come from the cleaned\n // input directly.\n const raw =\n formatType === 'creditCardType'\n ? getRawValue(cleanValue, formatType, runtime)\n : getRawValue(formatted, formatType, runtime)\n\n return { formatted, raw, type: formatType }\n}","/**\n * # Regex Module\n *\n * Validation patterns exposed as public API for form consumers that pair\n * formatting with validation. Each entry bundles the regex with a ready-to-use\n * error message so consumers do not have to keep them in sync.\n *\n * ## Usage\n *\n * **Static (backward compatible):**\n * ```ts\n * regex.phone.pattern.test('5512345678') // true\n * regex.email.errorMessage // 'Please enter a valid email address.'\n * ```\n *\n * **Parametric (dynamic):**\n * ```ts\n * regex.digits(10).pattern.test('1234567890') // true\n * regex.digits(7).pattern.test('1234567') // true\n * regex.phone({ length: 10 }).pattern.test('1234567890')\n * regex.phone({ length: 7 }).pattern.test('1234567')\n * ```\n *\n * **Custom regex:**\n * ```ts\n * regex.custom(/^[A-Z]{5}$/, 'Must be 5 uppercase letters').pattern.test('HELLO')\n * ```\n *\n * ## Available Patterns\n *\n * | Key | Static | Parametric | Description |\n * | --- | --- | --- | --- |\n * | `phone` | ✅ | ✅ `({ length })` | Phone numbers |\n * | `email` | ✅ | — | Email addresses |\n * | `rfc` | ✅ | — | Mexican RFC |\n * | `curp` | ✅ | — | Mexican CURP |\n * | `cp` | ✅ | — | Mexican postal code (5 digits) |\n * | `numeral` | ✅ | — | Numbers with separators |\n * | `onlyNumbers` | ✅ | ✅ `({ length })` | Digits only |\n * | `digits` | — | ✅ `({ length, min, max })` | Variable digit count |\n * | `creditCard` | ✅ | ✅ `({ min, max })` | Card numbers |\n * | `expirationDate` | ✅ | — | MM/YY format |\n * | `cardCvc` | ✅ | — | 3-4 digit CVC |\n * | `onlyLetters` | ✅ | — | Letters only |\n * | `onlyAlphanumeric` | ✅ | — | Letters and numbers |\n * | `url` | ✅ | ✅ `({ protocol })` | URLs |\n * | `ipv4` | ✅ | — | IPv4 addresses |\n * | `ipv6` | ✅ | — | IPv6 addresses |\n * | `uuid` | ✅ | — | UUID v4 |\n * | `hexColor` | ✅ | — | Hex color codes |\n * | `hashtag` | ✅ | — | Social media hashtags |\n * | `mention` | ✅ | — | Social media mentions |\n * | `password` | — | ✅ `({ min, max, rules })` | Password strength |\n * | `custom` | — | ✅ `({ pattern, errorMessage })` | User-defined regex |\n */\n\n// ─── Types ─────────────────────────────────────────────────────────────────\n\nexport interface RegexEntry {\n pattern: RegExp\n errorMessage: string\n}\n\ninterface PhoneParams {\n length?: number\n}\n\ninterface DigitsParams {\n length?: number\n min?: number\n max?: number\n}\n\ninterface CreditCardParams {\n min?: number\n max?: number\n}\n\ninterface UrlParams {\n protocol?: 'http' | 'https' | 'ftp' | 'all'\n}\n\ninterface PasswordParams {\n min?: number\n max?: number\n uppercase?: boolean\n lowercase?: boolean\n numbers?: boolean\n special?: boolean\n}\n\ninterface CustomParams {\n pattern: RegExp\n errorMessage: string\n}\n\n\n// ─── Internal Factories ──────────────────────────────────────────────────────\n\nfunction createDigits(min: number, max: number, errorMsg: string): RegexEntry {\n return {\n pattern: new RegExp(`^\\\\d{${min},${max}}$`),\n errorMessage: errorMsg\n }\n}\n\nfunction createPhone(length: number): RegexEntry {\n return {\n pattern: new RegExp(`^(?:\\\\D*\\\\d){${length}}\\\\D*$`),\n errorMessage: `Please enter a valid ${length}-digit phone number.`\n }\n}\n\nfunction createCreditCard(min: number, max: number): RegexEntry {\n return {\n pattern: new RegExp(`^(?:\\\\D*\\\\d){${min},${max}}\\\\D*$`),\n errorMessage: `Please enter a valid card number (${min}-${max} digits).`\n }\n}\n\nfunction createUrl(requireProtocol: 'http' | 'https' | 'ftp' | 'all'): RegexEntry {\n const protocol = requireProtocol === 'all' ? 'https?' : requireProtocol\n return {\n pattern: new RegExp(`^${protocol}://[^\\\\s]+$`),\n errorMessage: `Please enter a valid URL${requireProtocol !== 'all' ? ` (${requireProtocol}://...)` : ''}.`\n }\n}\n\nfunction createPassword(params: PasswordParams): RegexEntry {\n const {\n min = 8,\n max = 128,\n uppercase = true,\n lowercase = true,\n numbers = true,\n special = false\n } = params\n\n // Build the character class with proper escaping (put - last to avoid range issues)\n let chars = ''\n if (uppercase) chars += 'A-Z'\n if (lowercase) chars += 'a-z'\n if (numbers) chars += '0-9'\n if (special) chars += '!@#$%^&*()_+\\\\-=\\\\[\\\\]{}|;:\\'\",.<>?/'\n\n const ruleParts: string[] = []\n if (uppercase) ruleParts.push('uppercase letter')\n if (lowercase) ruleParts.push('lowercase letter')\n if (numbers) ruleParts.push('number')\n if (special) ruleParts.push('special character')\n\n const rulesText = ruleParts.length > 2\n ? ruleParts.slice(0, -1).join(', ') + ' and ' + ruleParts.slice(-1)\n : ruleParts.join(' and ')\n\n return {\n pattern: new RegExp(`^[${chars}]{${min},${max}}$`),\n errorMessage: `Password must be ${min}-${max} characters with at least one ${rulesText}.`\n }\n}\n\n// ─── Static Patterns ─────────────────────────────────────────────────────────\n\nconst _regex = {\n phone: {\n pattern: /^(?:\\D*\\d){10}\\D*$/,\n errorMessage: 'Please enter a valid 10-digit phone number.'\n },\n email: {\n // Simple but effective email validation\n pattern: /^[^\\s@]+@[^\\s@]+\\.[a-zA-Z]{2,}$/,\n errorMessage: 'Please enter a valid email address.'\n },\n rfc: {\n // Mexican RFC ( Personas Morales y Físicas )\n pattern: /^([A-ZÑ&]{3,4})\\d{6}([A-Z0-9]{0,3})$/i,\n errorMessage: 'Please enter a valid RFC.'\n },\n curp: {\n // Mexican CURP (18 characters)\n pattern: /^[A-Z]{4}\\d{6}[A-Z]{6}[0-9A-Z]\\d$/i,\n errorMessage: 'Please enter a valid CURP.'\n },\n cp: {\n // Mexican postal code (5 digits)\n pattern: /^\\d{5}$/,\n errorMessage: 'Please enter a valid 5-digit postal code.'\n },\n numeral: {\n // Numbers with optional thousand separators and decimal points\n pattern: /\\d{1,3}(,\\d{3})*(\\.\\d+)?/,\n errorMessage: 'Please enter a valid number.'\n },\n onlyNumbers: {\n pattern: /^\\d+$/,\n errorMessage: 'Please enter only numbers.'\n },\n creditCard: {\n // 15 or 16 digits, allowing spaces or delimiters\n pattern: /^(?:\\D*\\d){15,16}\\D*$/,\n errorMessage: 'Please enter a valid card number (15-16 digits).'\n },\n expirationDate: {\n // MM/YY or MM/YYYY format\n pattern: /^(0[1-9]|1[0-2])\\/(\\d{2}|\\d{4})$/,\n errorMessage: 'Please enter a valid expiration date (MM/YY or MM/YYYY).'\n },\n cardCvc: {\n // 3 or 4 digit card security codes\n pattern: /^\\d{3,4}$/,\n errorMessage: 'Please enter a valid CVC (3-4 digits).'\n },\n onlyLetters: {\n // Letters only (including accented characters and spaces)\n pattern: /^[A-Za-zÁÉÍÓÚáéíóúÑñ\\s]+$/,\n errorMessage: 'Please enter only letters.'\n },\n onlyAlphanumeric: {\n // Letters and numbers (including accented characters and spaces)\n pattern: /^[A-Za-zÁÉÍÓÚáéíóúÑñ0-9\\s]+$/,\n errorMessage: 'Please enter only letters and numbers.'\n },\n url: {\n // Accepts http, https, ftp\n pattern: /^(?:https?|ftp):\\/\\/[^\\s]+$/,\n errorMessage: 'Please enter a valid URL.'\n },\n ipv4: {\n // IPv4 addresses (0-255 per octet)\n pattern: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,\n errorMessage: 'Please enter a valid IPv4 address.'\n },\n ipv6: {\n // IPv6 addresses (simplified)\n pattern: /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/,\n errorMessage: 'Please enter a valid IPv6 address.'\n },\n uuid: {\n // UUID v4\n pattern: /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,\n errorMessage: 'Please enter a valid UUID.'\n },\n hexColor: {\n // Hex color codes (#RGB or #RRGGBB)\n pattern: /^#(?:[0-9a-fA-F]{3}){1,2}$/,\n errorMessage: 'Please enter a valid hex color code (e.g., #FFF or #FFFFFF).'\n },\n hashtag: {\n // Social media hashtags\n pattern: /^#[a-zA-Z_][a-zA-Z0-9_]*$/,\n errorMessage: 'Please enter a valid hashtag (e.g., #example).'\n },\n mention: {\n // Social media mentions\n pattern: /^@[a-zA-Z_][a-zA-Z0-9_]*$/,\n errorMessage: 'Please enter a valid mention (e.g., @username).'\n },\n postalCode: {\n // Generic 5-digit postal code (US-style ZIP / MX CP)\n pattern: /^\\d{5}(?:-\\d{4})?$/,\n errorMessage: 'Please enter a valid postal code (e.g., 90210 or 90210-1234).'\n },\n time24: {\n // 24-hour time HH:MM\n pattern: /^([01]\\d|2[0-3]):([0-5]\\d)$/,\n errorMessage: 'Please enter a valid 24-hour time (HH:MM).'\n },\n date: {\n // ISO-like date YYYY-MM-DD (loose)\n pattern: /^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$/,\n errorMessage: 'Please enter a valid date (YYYY-MM-DD).'\n },\n slug: {\n // URL slug (lowercase, hyphens, no spaces)\n pattern: /^[a-z0-9]+(?:-[a-z0-9]+)*$/,\n errorMessage: 'Please enter a valid slug (lowercase, hyphens, no spaces).'\n },\n username: {\n // Username: 3-20 chars, alphanumeric, underscore, hyphen\n pattern: /^[a-zA-Z0-9_-]{3,20}$/,\n errorMessage: 'Please enter a valid username (3-20 chars, letters, numbers, _ or -).'\n },\n macAddress: {\n // MAC address (colon or hyphen separated)\n pattern: /^([0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}$/,\n errorMessage: 'Please enter a valid MAC address (e.g., 00:1B:44:11:3A:B7).'\n },\n semver: {\n // Semantic version (X.Y.Z with optional -prerelease)\n pattern: /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-[a-zA-Z0-9.-]+)?$/,\n errorMessage: 'Please enter a valid semantic version (e.g., 1.2.3).'\n },\n base64: {\n // Base64 encoded string\n pattern: /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/,\n errorMessage: 'Please enter a valid Base64 encoded string.'\n }\n} as const\n\n// ─── Parametric Extensions ───────────────────────────────────────────────────\n\n/**\n * Digits with configurable length.\n * @example\n * regex.digits(10).pattern.test('1234567890') // true\n * regex.digits({ length: 7 }).pattern.test('1234567') // true\n * regex.digits({ min: 3, max: 10 }).pattern.test('12345') // true\n */\nfunction digits(params?: number | DigitsParams): RegexEntry {\n if (typeof params === 'number') {\n return createDigits(params, params, `Please enter exactly ${params} digits.`)\n }\n const { length, min = 1, max = 20 } = params ?? {}\n const actualMin = length ?? min\n const actualMax = length ?? max\n if (actualMin === actualMax) {\n return createDigits(actualMin, actualMax, `Please enter exactly ${actualMin} digits.`)\n }\n return createDigits(actualMin, actualMax, `Please enter ${actualMin}-${actualMax} digits.`)\n}\n\n/**\n * Phone with configurable digit count.\n *\n * Also available as static entry: regex.phone.pattern (10 digits)\n * @example\n * regex.phone().pattern.test('5512345678') // true (10 digits)\n * regex.phone({ length: 7 }).pattern.test('1234567') // true (7 digits)\n */\nfunction _phoneFn(params?: PhoneParams): RegexEntry {\n const length = params?.length ?? 10\n return createPhone(length)\n}\n\n/**\n * Credit card with configurable digit range.\n *\n * Also available as static entry: regex.creditCard.pattern (15-16 digits)\n * @example\n * regex.creditCard().pattern.test('4111111111111111') // true (15-16)\n * regex.creditCard({ min: 13, max: 19 }).pattern.test('1234567890123') // true\n */\nfunction _creditCardFn(params?: CreditCardParams): RegexEntry {\n const min = params?.min ?? 15\n const max = params?.max ?? 16\n return createCreditCard(min, max)\n}\n\n/**\n * URL with configurable protocol.\n *\n * Also available as static entry: regex.url.pattern (any protocol)\n * @example\n * regex.url().pattern.test('https://example.com') // true\n * regex.url({ protocol: 'https' }).pattern.test('https://example.com') // true\n * regex.url({ protocol: 'https' }).pattern.test('ftp://example.com') // false\n */\nfunction _urlFn(params?: UrlParams): RegexEntry {\n const protocol = params?.protocol ?? 'all'\n return createUrl(protocol)\n}\n\n/**\n * Password with configurable strength rules.\n * @example\n * regex.password().pattern.test('Passw0rd!') // true (default: 8+ chars, upper, lower, number)\n * regex.password({ min: 12, special: true }).pattern.test('MyP@ssw0rd!') // true\n */\nfunction _passwordFn(params?: PasswordParams): RegexEntry {\n return createPassword(params ?? {})\n}\n\n/**\n * Custom regex provided by the user.\n * @example\n * regex.custom(/^[A-Z]{5}$/, 'Must be 5 uppercase letters').pattern.test('HELLO') // true\n * regex.custom({ pattern: /^\\d+$/, errorMessage: 'Numbers only' }).pattern.test('123') // true\n */\nfunction _customFn(pattern: RegExp, errorMessage?: string): RegexEntry\nfunction _customFn(params: CustomParams): RegexEntry\nfunction _customFn(\n arg1: RegExp | CustomParams,\n arg2?: string\n): RegexEntry {\n if (arg1 instanceof RegExp) {\n return { pattern: arg1, errorMessage: arg2 ?? 'Invalid value.' }\n }\n return { pattern: arg1.pattern, errorMessage: arg1.errorMessage }\n}\n\n// ─── Callable Objects with Attached Pattern ──────────────────────────────────\n\n// These are callable functions that also have .pattern and .errorMessage attached\n// This allows both: regex.phone({ length: 7 }) AND regex.phone.pattern\n\nconst phoneFn = _phoneFn as typeof _phoneFn & RegexEntry\nphoneFn.pattern = _regex.phone.pattern\nphoneFn.errorMessage = _regex.phone.errorMessage\n\nconst creditCardFn = _creditCardFn as typeof _creditCardFn & RegexEntry\ncreditCardFn.pattern = _regex.creditCard.pattern\ncreditCardFn.errorMessage = _regex.creditCard.errorMessage\n\nconst urlFn = _urlFn as typeof _urlFn & RegexEntry\nurlFn.pattern = _regex.url.pattern\nurlFn.errorMessage = _regex.url.errorMessage\n\n// Parametric-only functions need default error messages\nconst digitsFn = digits as typeof digits & RegexEntry\ndigitsFn.errorMessage = 'Please enter a valid number.'\n\nconst passwordFn = _passwordFn as typeof _passwordFn & RegexEntry\npasswordFn.errorMessage = 'Please enter a valid password.'\n\nconst customFn = _customFn as typeof _customFn & RegexEntry\ncustomFn.errorMessage = 'Please enter a valid value.'\n\n// ─── Final Export ─────────────────────────────────────────────────────────────\n\nexport const regex = {\n // Static entries (backward compatible - spread first)\n ..._regex,\n\n // Parametric functions\n digits: digitsFn,\n phone: phoneFn,\n creditCard: creditCardFn,\n url: urlFn,\n password: passwordFn,\n custom: customFn\n} as const\n\nexport type RegexKey = keyof typeof _regex\nexport type Regex = typeof regex"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@samline/formatter",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Lightweight, framework-agnostic input formatter (phone, numeral, date, time, credit card, general) that returns split formatted/raw outputs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"bugs": {
|
|
65
65
|
"url": "https://github.com/samline/formatter/issues"
|
|
66
66
|
},
|
|
67
|
-
"homepage": "https://github.
|
|
67
|
+
"homepage": "https://samline.github.io/formatter",
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"cleave-zen": "^0.0.17",
|
|
70
70
|
"libphonenumber-js": "^1.13.7"
|