{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "calendar",
  "title": "Calendar",
  "description": "month grid",
  "dependencies": [
    "lucide-react-native@^1.21.0"
  ],
  "registryDependencies": [
    "@kit-native/icon",
    "@kit-native/lib-haptics",
    "@kit-native/lib-utils",
    "@kit-native/text"
  ],
  "files": [
    {
      "path": "components/kit/calendar.tsx",
      "content": "import { Icon } from '@/components/ui/icon';\nimport { Text } from '@/components/ui/text';\nimport { haptic } from '@/lib/haptics';\nimport { cn } from '@/lib/utils';\nimport { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react-native';\nimport * as React from 'react';\nimport { Pressable, View } from 'react-native';\n\ntype Props = { value?: Date; onChange: (date: Date) => void; className?: string };\n\nconst WEEKDAYS = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];\nconst MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];\nconst sameDay = (a: Date, b: Date) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();\n\n/** Month grid. Selected day is a primary disc; today has a primary ring. */\nexport function Calendar({ value, onChange, className }: Props) {\n  const today = new Date();\n  const [view, setView] = React.useState(() => {\n    const base = value ?? today;\n    return { year: base.getFullYear(), month: base.getMonth() };\n  });\n  const firstWeekday = new Date(view.year, view.month, 1).getDay();\n  const daysInMonth = new Date(view.year, view.month + 1, 0).getDate();\n  const cells: (number | null)[] = [...Array.from({ length: firstWeekday }, () => null), ...Array.from({ length: daysInMonth }, (_, i) => i + 1)];\n  while (cells.length % 7 !== 0) cells.push(null);\n  // Explicit rows of 7 with flex-1 cells: percentage widths round past 100% and wrap early,\n  // which left the Saturday column empty.\n  const weeks = Array.from({ length: cells.length / 7 }, (_, w) => cells.slice(w * 7, w * 7 + 7));\n  const shift = (delta: number) =>\n    setView((v) => {\n      const m = v.month + delta;\n      return { year: v.year + Math.floor(m / 12), month: ((m % 12) + 12) % 12 };\n    });\n\n  return (\n    <View className={className}>\n      <View className=\"mb-3 flex-row items-center justify-between\">\n        <Pressable accessibilityRole=\"button\" accessibilityLabel=\"Previous month\" hitSlop={8} onPress={() => shift(-1)} className=\"size-9 items-center justify-center\">\n          <Icon as={ChevronLeftIcon} size={20} />\n        </Pressable>\n        <Text className=\"font-semibold\">\n          {MONTHS[view.month]} {view.year}\n        </Text>\n        <Pressable accessibilityRole=\"button\" accessibilityLabel=\"Next month\" hitSlop={8} onPress={() => shift(1)} className=\"size-9 items-center justify-center\">\n          <Icon as={ChevronRightIcon} size={20} />\n        </Pressable>\n      </View>\n      <View className=\"flex-row\">\n        {WEEKDAYS.map((d, i) => (\n          <Text key={i} className=\"text-muted-foreground mb-1 flex-1 text-center text-xs\">\n            {d}\n          </Text>\n        ))}\n      </View>\n      {weeks.map((week, w) => (\n        <View key={w} className=\"flex-row\">\n          {week.map((day, i) => {\n            if (day === null) return <View key={`b${w}-${i}`} className=\"aspect-square flex-1\" />;\n            const date = new Date(view.year, view.month, day);\n            const selected = value ? sameDay(date, value) : false;\n            const isToday = sameDay(date, today);\n            return (\n              <View key={day} className=\"aspect-square flex-1 p-0.5\">\n                <Pressable\n                  accessibilityRole=\"button\"\n                  accessibilityState={{ selected }}\n                  // aria-pressed is web-only (react-native-web drops accessibilityState, and a button may not carry aria-selected).\n                  aria-pressed={selected}\n                  accessibilityLabel={date.toDateString()}\n                  onPress={() => {\n                    haptic('selection');\n                    onChange(date);\n                  }}\n                  className={cn('flex-1 items-center justify-center rounded-full', selected ? 'bg-primary' : isToday ? 'border-primary border' : 'active:bg-accent')}>\n                  <Text className={cn(selected && 'text-primary-foreground font-semibold')}>{day}</Text>\n                </Pressable>\n              </View>\n            );\n          })}\n        </View>\n      ))}\n    </View>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/kit/calendar.tsx"
    }
  ],
  "meta": {
    "exports": [
      "Calendar"
    ],
    "api": "<Calendar value onChange />"
  },
  "docs": "Run `npx expo install --fix` afterwards so Expo SDK packages match your SDK. Needs the kit theme (`@kit-native/theme`) and `KitThemeProvider` from `@kit-native/lib-theme-context` at the root.",
  "categories": [
    "inputs"
  ],
  "type": "registry:component"
}