Sunflower UI
Search
Copy Code
Light Mode
SuMoTuWeThFrSa
SuMoTuWeThFrSa
calendar-demo.tsx
calendar.tsx
prompt.md
Collapse
Reset
Copy Code
Download
Run
1
"use client";
2
3
import * as React from "react"
4
import { createPortal } from "react-dom"
5
import { Calendar } from "./calendar"
6
import { Switch } from "./switch"
7
import { Select } from "./select"
8
import { enUS, ar, faIR, th, zhTW, ja } from "date-fns/locale"
9
10
export function CalendarDemo() {
11
const [date, setDate] = React.useState<Date | undefined>(new Date())
12
const [dates, setDates] = React.useState<Date[]>([])
13
const [range, setRange] = React.useState<{from: Date, to?: Date} | undefined>()
14
15
const [mounted, setMounted] = React.useState(false)
16
const [periods, setPeriods] = React.useState(true)
17
const [layout, setLayout] = React.useState("default")
18
const [mode, setMode] = React.useState("single")
19
const [caption, setCaption] = React.useState("dropdown")
20
const [disabledMode, setDisabledMode] = React.useState("none")
21
const [months, setMonths] = React.useState("2")
22
const [language, setLanguage] = React.useState("enUS")
23
const [calendarSystem, setCalendarSystem] = React.useState("gregorian")
24
25
React.useEffect(() => {
26
setMounted(true)
27
}, [])
28
29
const disabledProp = React.useMemo(() => {
30
if (disabledMode === "future") return [{ after: new Date() }]
31
if (disabledMode === "past") return [{ before: new Date() }]
32
return undefined
33
}, [disabledMode])
34
35
const localeObject = React.useMemo(() => {
36
switch(language) {
37
case "ar": return ar;
38
case "faIR": return faIR;
39
case "th": return th;
40
case "zhTW": return zhTW;
41
case "ja": return ja;
42
default: return enUS;
43
}
44
}, [language])
45
46
// Custom Controls to render in the right panel portal
47
const controls = (
48
<div className="flex flex-col gap-5 mt-6 border-t border-black/5 dark:border-white/5 pt-6 pb-20">
49
<div className="flex items-center gap-2 text-[13px] font-semibold text-[#1F1F1F] dark:text-[#D4D4D8]">
50
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="text-[#9FE870]"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="16"/><line x1="8" y1="12" x2="16" y2="12"/></svg>
51
Playground Options
52
</div>
53
54
<div className="flex items-center justify-between">
55
<label className="text-[13px] text-zinc-600 dark:text-zinc-400 font-medium">Periods</label>
56
<Switch checked={periods} onChange={(e) => setPeriods(e.target.checked)} />
57
</div>
58
59
<div className="flex flex-col gap-2">
60
<label className="text-[13px] text-zinc-600 dark:text-zinc-400 font-medium">Layout</label>
61
<Select
62
value={layout}
63
onValueChange={setLayout}
64
options={[{ value: "default", label: "Default" }, { value: "compact", label: "Compact" }, { value: "single", label: "Single" }]}
65
className="w-full"
66
/>
67
</div>
68
69
<div className="flex flex-col gap-2">
70
<label className="text-[13px] text-zinc-600 dark:text-zinc-400 font-medium">Mode</label>
71
<Select
72
value={mode}
73
onValueChange={setMode}
74
options={[{ value: "single", label: "Single" }, { value: "multiple", label: "Multiple" }, { value: "range", label: "Range" }]}
75
className="w-full"
76
/>
77
</div>
78
79
<div className="flex flex-col gap-2">
80
<label className="text-[13px] text-zinc-600 dark:text-zinc-400 font-medium">Caption</label>
81
<Select
82
value={caption}
83
onValueChange={setCaption}
84
options={[{ value: "dropdown", label: "Dropdown months" }, { value: "dropdown-buttons", label: "Dropdown years" }, { value: "buttons", label: "Buttons" }]}
85
className="w-full"
86
/>
87
</div>
88
89
<div className="flex flex-col gap-2">
90
<label className="text-[13px] text-zinc-600 dark:text-zinc-400 font-medium">Disabled</label>
91
<Select
92
value={disabledMode}
93
onValueChange={setDisabledMode}
94
options={[{ value: "none", label: "None" }, { value: "future", label: "Future" }, { value: "past", label: "Past" }]}
95
className="w-full"
96
/>
97
</div>
98
99
<div className="flex flex-col gap-2">
100
<label className="text-[13px] text-zinc-600 dark:text-zinc-400 font-medium">Months</label>
101
<Select
102
value={months}
103
onValueChange={setMonths}
104
options={[{ value: "1", label: "1" }, { value: "2", label: "2" }, { value: "3", label: "3" }]}
105
className="w-full"
106
/>
107
</div>
108
109
<div className="flex flex-col gap-2">
110
<label className="text-[13px] text-zinc-600 dark:text-zinc-400 font-medium">Language</label>
111
<Select
112
value={language}
113
onValueChange={setLanguage}
114
options={[
115
{ value: "enUS", label: "English" },
116
{ value: "ar", label: "Arabic" },
117
{ value: "faIR", label: "Persian" },
118
{ value: "th", label: "Thai" },
119
{ value: "zhTW", label: "Traditional Chinese" },
120
{ value: "ja", label: "Japanese" }
121
]}
122
className="w-full"
123
/>
124
</div>
125
126
<div className="flex flex-col gap-2">
127
<label className="text-[13px] text-zinc-600 dark:text-zinc-400 font-medium">Calendar</label>
128
<Select
129
value={calendarSystem}
130
onValueChange={setCalendarSystem}
131
options={[
132
{ value: "gregorian", label: "Gregorian" },
133
{ value: "hijri", label: "Hijri" },
134
{ value: "hijri-civil", label: "Hijri civil" },
135
{ value: "persian", label: "Persian" },
136
{ value: "buddhist", label: "Buddhist" },
137
{ value: "minguo", label: "Minguo" },
138
{ value: "japanese", label: "Japanese" }
139
]}
140
className="w-full"
141
/>
142
</div>
143
</div>
144
)
145
146
const portalTarget = typeof document !== "undefined" ? document.getElementById("custom-controls-portal") : null
147
148
return (
149
<div className="w-full h-full flex items-center justify-center p-4 sm:p-6 md:p-8">
150
{mounted && portalTarget && createPortal(controls, portalTarget)}
151
152
<div className="flex justify-center w-full">
153
<div className="shadow-2xl rounded-2xl">
154
{mode === "single" && (
155
<Calendar
156
mode="single"
157
selected={date}
158
onSelect={setDate as any}
159
className="bg-white dark:bg-[#111111]"
160
numberOfMonths={parseInt(months)}
161
showOutsideDays={periods}
162
captionLayout={caption as any}
163
disabled={disabledProp}
164
locale={localeObject}
165
/>
166
)}
167
{mode === "multiple" && (
168
<Calendar
169
mode="multiple"
170
selected={dates}
171
onSelect={setDates as any}
172
className="bg-white dark:bg-[#111111]"
173
numberOfMonths={parseInt(months)}
174
showOutsideDays={periods}
175
captionLayout={caption as any}
176
disabled={disabledProp}
177
locale={localeObject}
178
/>
179
)}
180
{mode === "range" && (
181
<Calendar
182
mode="range"
183
selected={range as any}
184
onSelect={setRange as any}
185
className="bg-white dark:bg-[#111111]"
186
numberOfMonths={parseInt(months)}
187
showOutsideDays={periods}
188
captionLayout={caption as any}
189
disabled={disabledProp}
190
locale={localeObject}
191
/>
192
)}
193
</div>
194
</div>
195
</div>
196
)
197
}
198