{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"formater","type":"registry:component","description":"Formater utilities.","files":[{"path":"lib/formater.ts","type":"registry:component","content":"/** Shared locale for dashboard (charts, KPIs, tables). */\nexport const DASHBOARD_LOCALE = \"en-US\";\n\n/** Noon anchor avoids off-by-one labels around timezone boundaries for ISO date strings. */\nexport function parseIsoCalendarDate(isoDate: string): Date {\n\treturn new Date(`${isoDate}T12:00:00`);\n}\n\nexport type DashboardDateStyle = \"month\" | \"day-month\" | \"full\";\n\nexport function formatDate(isoDate: string, style: DashboardDateStyle): string {\n\tconst date = parseIsoCalendarDate(isoDate);\n\tif (style === \"month\") {\n\t\treturn date.toLocaleDateString(DASHBOARD_LOCALE, { month: \"short\" });\n\t}\n\tif (style === \"day-month\") {\n\t\treturn date.toLocaleDateString(DASHBOARD_LOCALE, {\n\t\t\tday: \"numeric\",\n\t\t\tmonth: \"short\",\n\t\t});\n\t}\n\treturn date.toLocaleDateString(DASHBOARD_LOCALE, {\n\t\tday: \"numeric\",\n\t\tmonth: \"short\",\n\t\tyear: \"numeric\",\n\t});\n}\n\n/** X-axis for range charts: weekday when showing ~a week, otherwise month + day. */\nexport function formatChartAxisTick(\n\tisoDate: string,\n\tperiodDays: number\n): string {\n\tconst date = parseIsoCalendarDate(isoDate);\n\tif (periodDays <= 7) {\n\t\treturn date.toLocaleDateString(DASHBOARD_LOCALE, { weekday: \"short\" });\n\t}\n\treturn formatDate(isoDate, \"day-month\");\n}\n\nexport type ChartTooltipWeekdayStyle = \"short\" | \"long\";\n\n/** Tooltip label for a chart point (weekday + month + day). */\nexport function formatChartTooltipDate(\n\tisoDate: string,\n\tweekdayStyle: ChartTooltipWeekdayStyle = \"short\"\n): string {\n\tconst date = parseIsoCalendarDate(isoDate);\n\treturn date.toLocaleDateString(DASHBOARD_LOCALE, {\n\t\tweekday: weekdayStyle,\n\t\tday: \"numeric\",\n\t\tmonth: \"short\",\n\t});\n}\n\nexport function formatCompactCurrency(\n\tvalue: number,\n\toptions?: { maximumFractionDigits?: number }\n) {\n\tconst { maximumFractionDigits = 0 } = options ?? {};\n\treturn new Intl.NumberFormat(DASHBOARD_LOCALE, {\n\t\tcurrency: \"USD\",\n\t\tmaximumFractionDigits,\n\t\tnotation: \"compact\",\n\t\tstyle: \"currency\",\n\t}).format(value);\n}\n\n/** Full-precision USD (e.g. average order value). */\nexport function formatFullCurrency(value: number) {\n\treturn new Intl.NumberFormat(DASHBOARD_LOCALE, {\n\t\tcurrency: \"USD\",\n\t\tminimumFractionDigits: 2,\n\t\tmaximumFractionDigits: 2,\n\t\tstyle: \"currency\",\n\t}).format(value);\n}\n\nexport function formatCompactNumber(value: number) {\n\treturn new Intl.NumberFormat(DASHBOARD_LOCALE, {\n\t\tmaximumFractionDigits: 1,\n\t\tnotation: \"compact\",\n\t}).format(value);\n}\n\n/** Whole numbers with grouping (visits, sessions, counts). */\nexport function formatInteger(value: number) {\n\treturn new Intl.NumberFormat(DASHBOARD_LOCALE, {\n\t\tmaximumFractionDigits: 0,\n\t}).format(value);\n}\n\n/** Percentage with fixed decimal places (e.g. conversion rate). */\nexport function formatPercent(value: number, fractionDigits = 2) {\n\treturn `${value.toFixed(fractionDigits)}%`;\n}\n"}]}