{"version":3,"sources":["../src/helpers/FieldUtils.ts","../src/utils/index.ts"],"sourcesContent":["import { FieldError } from \"react-hook-form\";\n\n/**\n * Generates a consistent data-testid for field components.\n * Used by all adapter packages for test attribute generation.\n */\nexport const GetFieldDataTestId = (\n  fieldName: string,\n  testId?: string\n): string => {\n  return testId ? `${testId}-${fieldName}` : fieldName;\n};\n\n/**\n * Appends \"error\" to a className when a field has a validation error.\n * Used by Fluent and MUI adapters for error styling.\n */\nexport const FieldClassName = (className: string, error?: FieldError): string => {\n  return error ? `${className} error` : className;\n};\n\n/**\n * Returns a field state string based on the current field props.\n * Used by headless adapter for data-state attributes.\n */\nexport function getFieldState(props: {\n  error?: FieldError;\n  required?: boolean;\n  readOnly?: boolean;\n  disabled?: boolean;\n}): string | undefined {\n  if (props.error) return \"error\";\n  if (props.required) return \"required\";\n  if (props.readOnly) return \"readonly\";\n  if (props.disabled) return \"disabled\";\n  return undefined;\n}\n\n/**\n * Formats an ISO date string for display.\n * Returns short date (e.g. \"Jan 15, 2024\") or date+time (e.g. \"Jan 15, 2024, 02:30 PM\").\n */\nexport function formatDateTime(dateStr: string, options?: { hideTimestamp?: boolean }): string {\n  if (!dateStr) return \"\";\n  const date = new Date(dateStr);\n  if (isNaN(date.getTime())) return dateStr;\n  if (options?.hideTimestamp) {\n    return date.toLocaleDateString(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\" });\n  }\n  return date.toLocaleString(undefined, { year: \"numeric\", month: \"short\", day: \"numeric\", hour: \"2-digit\", minute: \"2-digit\" });\n}\n\n/**\n * Safely formats a value as a date+time string, falling back to String() on error.\n */\nexport function formatDateTimeValue(value: unknown): string {\n  if (!value) return \"\";\n  try {\n    return formatDateTime(value as string);\n  } catch {\n    return String(value);\n  }\n}\n\n/**\n * Formats a date range value for read-only display.\n * Returns \"start – end\", or just the one that exists.\n */\nexport function formatDateRange(value: unknown): string {\n  if (!value) return \"\";\n  const v = value as { start: string; end: string };\n  if (!v.start && !v.end) return \"\";\n  if (v.start && v.end) return `${v.start} – ${v.end}`;\n  return v.start || v.end;\n}\n\n/**\n * Extracts display names from File or File[] values.\n */\nexport function getFileNames(value: unknown): string {\n  if (!value) return \"\";\n  if (Array.isArray(value)) return (value as File[]).map(f => f.name).join(\", \");\n  return (value as File).name ?? \"\";\n}\n\n/**\n * Strips all non-digit characters from a string.\n */\nexport function extractDigits(value: string): string {\n  return value.replace(/\\D/g, \"\");\n}\n\n/**\n * Parses raw text-input content for a Number field.\n *\n * `Number(\"\")` and `Number(\"   \")` are `0` in JavaScript, so a naive\n * `!isNaN(Number(raw))` check turns \"user cleared the field\" into the value 0.\n * This helper distinguishes the three cases adapters need:\n *\n * - empty / whitespace-only input → `null` (the field was cleared)\n * - unparseable input → `undefined` (ignore the keystroke, keep current value)\n * - otherwise → the parsed number\n */\nexport function parseNumberInputValue(raw: string): number | null | undefined {\n  if (raw.trim() === \"\") return null;\n  const parsed = Number(raw);\n  return isNaN(parsed) ? undefined : parsed;\n}\n\n/**\n * Formats a digit string as a phone number.\n * Supports US \"(XXX) XXX-XXXX\", international \"+X XXX XXX XXXX\", and raw digits.\n */\nexport function formatPhone(digits: string, format: \"us\" | \"international\" | \"raw\"): string {\n  if (format === \"raw\") return digits;\n\n  if (format === \"international\") {\n    // +X XXX XXX XXXX\n    const d = digits.slice(0, 12);\n    if (d.length === 0) return \"\";\n    if (d.length <= 1) return `+${d}`;\n    if (d.length <= 4) return `+${d[0]} ${d.slice(1)}`;\n    if (d.length <= 7) return `+${d[0]} ${d.slice(1, 4)} ${d.slice(4)}`;\n    return `+${d[0]} ${d.slice(1, 4)} ${d.slice(4, 7)} ${d.slice(7)}`;\n  }\n\n  // US: (XXX) XXX-XXXX\n  const d = digits.slice(0, 10);\n  if (d.length === 0) return \"\";\n  if (d.length <= 3) return `(${d}`;\n  if (d.length <= 6) return `(${d.slice(0, 3)}) ${d.slice(3)}`;\n  return `(${d.slice(0, 3)}) ${d.slice(3, 6)}-${d.slice(6)}`;\n}\n\n/**\n * Truncates text with \"...\" if it exceeds maxChars.\n */\nexport function ellipsifyText(value: string, maxChars: number): string {\n  if (!value || value.length <= maxChars) return value ?? \"\";\n  const cutoff = maxChars - 3;\n  return `${value.substring(0, cutoff)}...`;\n}\n\n/** Default max file size in MB for FileUpload fields */\nexport const MAX_FILE_SIZE_MB_DEFAULT = 10;\n\n/** Shared strings for DocumentLinks component */\nexport const DocumentLinksStrings = {\n  link: \"Link\",\n  addLink: \"Add Link\",\n  addAnotherLink: \"Add Another Link\",\n  deleteLink: \"Delete Link\",\n  confirmDeleteLink: \"Are you sure you want to delete\",\n  delete: \"Delete\",\n  cancel: \"Cancel\",\n  saveChanges: \"Save Changes\",\n  save: \"Save\",\n};\n","/** Generic dictionary type */\nexport type Dictionary<T> = Record<string, T>;\n\n/** Entity data type */\nexport type IEntityData = Record<string, unknown>;\n\n/** Sub-entity value type */\nexport type SubEntityType = string | number | boolean | Date | object | null | undefined;\n\nexport function isEmpty(value: unknown): boolean {\n  if (value == null) return true;\n  if (typeof value === \"string\") return value.trim() === \"\";\n  if (Array.isArray(value)) return value.length === 0;\n  if (typeof value === \"object\") return Object.keys(value).length === 0;\n  return false;\n}\n\nexport function isNull(value: unknown): value is null | undefined {\n  return value == null;\n}\n\nexport function isStringEmpty(value: string | null | undefined): boolean {\n  return value == null || value.trim() === \"\";\n}\n\nexport function deepCopy<T>(obj: T): T {\n  return structuredClone(obj);\n}\n\nexport function convertBooleanToYesOrNoText(value: boolean | null | undefined): string {\n  if (value === true) return \"Yes\";\n  if (value === false) return \"No\";\n  return \"\";\n}\n\n/** Sort options alphabetically by label */\nexport function sortDropdownOptions(a: { label?: string }, b: { label?: string }): number {\n  const aText = a.label ? a.label.toLowerCase() : \"\";\n  const bText = b.label ? b.label.toLowerCase() : \"\";\n  return aText < bText ? -1 : aText > bText ? 1 : 0;\n}\n\n/** Create an option from a value string (value and label are the same) */\nexport function createOption(value: string): { value: string; label: string } {\n  return { value, label: value };\n}\n"],"mappings":"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","names":["d"]}