ข้ามไปเนื้อหา
WhereUI

ค้นหาในเอกสาร

ค้นหาชื่อ component หรือหน้าเอกสาร

DatePicker

WhereUI

ช่องเลือกวันที่พร้อมปฏิทิน popover แสดงวันที่ภาษาไทยและปี พ.ศ. ได้ตั้งแต่เริ่มต้น ค่าที่รับ/ส่งเป็น Date จริงเสมอ

ยังไม่ได้เลือกวันเริ่มงาน

ติดตั้ง

Terminal
pnpm dlx shadcn@latest add @whereui/date-picker

ต้องผูก registry และติดตั้ง @whereui/theme นำหน้าเสมอเมื่อติดตั้งครั้งแรก

การใช้งาน

import { DatePicker } from "@/components/ui/date-picker"const [date, setDate] = React.useState<Date | null>(null)<DatePicker value={date} onChange={setDate} />

ตัวอย่างเพิ่มเติม

จำกัดช่วงวันที่และสถานะต่าง ๆ
ลาได้เฉพาะวันทำการในปีนี้ (min/max)
แสดงปีเป็น ค.ศ.
ปิดใช้งาน

Props

proptypeค่าเริ่มต้นคำอธิบาย
valueDate | null—วันที่ที่เลือกอยู่ (null = ยังไม่เลือก)
onChange(date: Date | null) => void—เรียกเมื่อผู้ใช้เลือกวันที่จากปฏิทิน
placeholderstring"เลือกวันที่"ข้อความแสดงเมื่อยังไม่เลือกวันที่
minDate—วันต่ำสุดที่เลือกได้
maxDate—วันสูงสุดที่เลือกได้
buddhistErabooleantrueแสดงปีเป็น พ.ศ. (ค.ศ. + 543) เป็นเพียงการแสดงผล ค่าที่ส่งกลับยังเป็นปี ค.ศ.
disabledboolean—ปิดการใช้งานช่องเลือกวันที่

ข้อควรรู้

  • ค่าที่รับ/ส่งเป็น Date หรือ ISO yyyy-mm-dd เสมอ การแสดง พ.ศ. เป็นเรื่องการแสดงผลเท่านั้น
  • เปิดปฏิทินด้วยคีย์บอร์ดได้ (Tab เข้าปุ่มแล้วกด Enter) และเลื่อนวันในปฏิทินด้วยลูกศรได้

ซอร์สโค้ด

components/ui/date-picker.tsx
"use client"import * as React from "react"import { th } from "date-fns/locale"import { CalendarIcon } from "lucide-react"import { cn } from "cn"import type { Matcher } from "react-day-picker"import { Calendar } from "@/components/ui/calendar"import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"/** ชื่อเดือนภาษาไทย ("มกราคม", "ม.ค.") */function thaiMonth(date: Date, style: "long" | "short") {  return new Intl.DateTimeFormat("th-TH", { month: style }).format(date)}/** จัดรูปแบบวันที่ภาษาไทย เช่น "13 พฤศจิกายน 2569" — ปี พ.ศ. = ค.ศ. + 543 (เฉพาะการแสดงผล) */export function formatThaiDate(  date: Date,  buddhistEra: boolean,  style: "long" | "short" = "long") {  const year = date.getFullYear() + (buddhistEra ? 543 : 0)  return `${date.getDate()} ${thaiMonth(date, style)} ${year}`}function DatePicker({  value,  onChange,  placeholder = "เลือกวันที่",  disabled,  min,  max,  buddhistEra = true,  className,  ...props}: Omit<React.ComponentProps<"button">, "value" | "onChange"> & {  /** วันที่ที่เลือก (null = ยังไม่เลือก) */  value?: Date | null  onChange?: (date: Date | null) => void  placeholder?: string  /** วันต่ำสุดที่เลือกได้ */  min?: Date  /** วันสูงสุดที่เลือกได้ */  max?: Date  /** แสดงปีเป็น พ.ศ. (ค.ศ. + 543) */  buddhistEra?: boolean}) {  const [open, setOpen] = React.useState(false)  const disabledMatchers = React.useMemo(() => {    const matchers: Matcher[] = []    if (min) matchers.push({ before: min })    if (max) matchers.push({ after: max })    return matchers.length ? matchers : undefined  }, [min, max])  return (    <Popover open={open} onOpenChange={setOpen}>      <PopoverTrigger        type="button"        data-slot="date-picker"        disabled={disabled}        className={cn(          "flex h-8 w-full min-w-0 items-center justify-between gap-2 rounded-lg border border-input bg-transparent px-2.5 py-1 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground",          !value && "text-muted-foreground",          className        )}        {...props}      >        <span className="truncate">          {value ? formatThaiDate(value, buddhistEra) : placeholder}        </span>        <CalendarIcon aria-hidden="true" />      </PopoverTrigger>      <PopoverContent align="start" className="w-auto p-0">        <Calendar          mode="single"          locale={th}          defaultMonth={value ?? undefined}          selected={value ?? undefined}          onSelect={(date) => {            onChange?.(date ?? null)            setOpen(false)          }}          disabled={disabledMatchers}          formatters={{            formatCaption: (month) =>              `${thaiMonth(month, "long")} ${                month.getFullYear() + (buddhistEra ? 543 : 0)              }`,          }}        />      </PopoverContent>    </Popover>  )}export { DatePicker }