{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "calendar-utils",
  "title": "Calendar Utilities",
  "description": "Date maths for the calendar and the date pickers, free of any date library.",
  "files": [
    {
      "path": "src/components/ui/calendar-utils.ts",
      "content": "function sameDay(a?: Date | null, b?: Date | null) {\n  return Boolean(\n    a &&\n      b &&\n      a.getFullYear() === b.getFullYear() &&\n      a.getMonth() === b.getMonth() &&\n      a.getDate() === b.getDate(),\n  )\n}\n\nfunction dateKey(date: Date) {\n  return [\n    date.getFullYear(),\n    String(date.getMonth() + 1).padStart(2, \"0\"),\n    String(date.getDate()).padStart(2, \"0\"),\n  ].join(\"-\")\n}\n\nfunction isDateSelectable(\n  date: Date,\n  options: {\n    disabled?: boolean\n    isDateUnavailable?: (date: Date) => boolean\n    max?: Date\n    min?: Date\n  },\n) {\n  const candidate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 12)\n  const minimum = options.min\n    ? new Date(options.min.getFullYear(), options.min.getMonth(), options.min.getDate(), 12)\n    : null\n  const maximum = options.max\n    ? new Date(options.max.getFullYear(), options.max.getMonth(), options.max.getDate(), 12)\n    : null\n\n  return !(\n    options.disabled ||\n    (minimum && candidate < minimum) ||\n    (maximum && candidate > maximum) ||\n    options.isDateUnavailable?.(candidate)\n  )\n}\n\n/**\n * The weekday a locale's calendar starts on, as a `Date.getDay()` index\n * (0 = Sunday).\n *\n * Most of the world starts on Monday; the Sunday-first grid is a US\n * convention. `Intl.Locale` knows which, through `getWeekInfo()` — a method in\n * newer engines and a `weekInfo` property in slightly older ones, so both are\n * tried before falling back.\n *\n * The fallback is Sunday rather than Monday only because it is what the\n * component did before this existed; it is reached solely on engines that\n * expose neither, which no longer includes any current browser.\n *\n * Note the conversion: week info numbers days 1–7 with Monday as 1 and Sunday\n * as 7, while `Date.getDay()` numbers them 0–6 with Sunday as 0. Getting that\n * off by one rotates the whole grid, which is exactly the bug this replaces.\n */\nfunction firstDayOfWeek(locale: string): number {\n  try {\n    const info = new Intl.Locale(locale) as Intl.Locale & {\n      getWeekInfo?: () => { firstDay: number }\n      weekInfo?: { firstDay: number }\n    }\n    const firstDay = info.getWeekInfo?.().firstDay ?? info.weekInfo?.firstDay\n    if (firstDay) return firstDay % 7\n  } catch {\n    // An unparseable locale tag is the caller's problem, not a reason to fail\n    // to render a calendar.\n  }\n  return 0\n}\n\n/** How many days back from `date` the containing week began. */\nfunction daysSinceWeekStart(date: Date, weekStart: number) {\n  return (date.getDay() - weekStart + 7) % 7\n}\n\nexport { dateKey, daysSinceWeekStart, firstDayOfWeek, isDateSelectable, sameDay }\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "forms"
  ],
  "type": "registry:ui"
}