feat: Implement Calendar component, UiProvider, and a cn utility, while enhancing picker components with new icons and styles.
This commit is contained in:
@@ -13,19 +13,27 @@ import {
|
||||
MonthRangePicker,
|
||||
QuarterRangePicker,
|
||||
YearRangePicker,
|
||||
InputStatusType
|
||||
InputStatusType,
|
||||
Calendar,
|
||||
} from '@repo/ui'; // Sesuaikan path
|
||||
import { DateUtils } from '@repo/utils';
|
||||
|
||||
// --- UI Helper Components ---
|
||||
const Section = ({ title, description, children }: { title: string; description?: string; children: React.ReactNode }) => (
|
||||
const Section = ({
|
||||
title,
|
||||
description,
|
||||
children,
|
||||
}: {
|
||||
title: string;
|
||||
description?: string;
|
||||
children: React.ReactNode;
|
||||
}) => (
|
||||
<section className="bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden mb-8">
|
||||
<div className="bg-gray-50 px-6 py-4 border-b border-gray-200">
|
||||
<h2 className="text-lg font-bold text-gray-800">{title}</h2>
|
||||
{description && <p className="text-sm text-gray-500 mt-1">{description}</p>}
|
||||
</div>
|
||||
<div className="p-6 grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
|
||||
{children}
|
||||
</div>
|
||||
<div className="p-6 grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">{children}</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -35,22 +43,17 @@ const Card = ({ label, code, children }: { label: string; code?: string; childre
|
||||
<label className="text-sm font-semibold text-gray-700">{label}</label>
|
||||
{code && <span className="text-xs font-mono text-gray-400 bg-gray-100 px-1.5 py-0.5 rounded">{code}</span>}
|
||||
</div>
|
||||
<div className="w-full">
|
||||
{children}
|
||||
</div>
|
||||
<div className="w-full">{children}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default function PickerShowcase({status}: {status: InputStatusType}) {
|
||||
export default function PickerShowcase({ status }: { status: InputStatusType }) {
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 py-10 px-4 sm:px-6 lg:px-8 font-sans">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
|
||||
{/* Header */}
|
||||
<div className="mb-10 text-center">
|
||||
<h1 className="text-3xl font-extrabold text-gray-900 tracking-tight">
|
||||
Component Picker Showcase
|
||||
</h1>
|
||||
<h1 className="text-3xl font-extrabold text-gray-900 tracking-tight">Component Picker Showcase</h1>
|
||||
<p className="mt-2 text-lg text-gray-600">
|
||||
Fully typed, Tailwind-styled, and robust date manipulation components.
|
||||
</p>
|
||||
@@ -65,7 +68,7 @@ export default function PickerShowcase({status}: {status: InputStatusType}) {
|
||||
<Card label="Date Picker" code="<DatePicker />">
|
||||
<DatePicker placeholder="Select date..." className="w-full" />
|
||||
</Card>
|
||||
|
||||
|
||||
<Card label="Week Picker" code="<WeekPicker />">
|
||||
<WeekPicker placeholder="Select week..." className="w-full" />
|
||||
</Card>
|
||||
@@ -74,23 +77,21 @@ export default function PickerShowcase({status}: {status: InputStatusType}) {
|
||||
<MonthPicker placeholder="Select month..." className="w-full" />
|
||||
</Card>
|
||||
|
||||
<Card label="Quarter Picker" code="<QuarterPicker />">
|
||||
<Card label="Quarter Picker" code="<QuarterPicker />">
|
||||
<QuarterPicker placeholder="Select quarter..." className="w-full" />
|
||||
</Card>
|
||||
|
||||
<Card label="Year Picker" code="<YearPicker />">
|
||||
<YearPicker placeholder="Select year..." className="w-full" />
|
||||
</Card>
|
||||
|
||||
|
||||
</Section>
|
||||
|
||||
{/* 2. Range Pickers */}
|
||||
<Section title="Range Pickers" description="Komponen untuk memilih rentang waktu (Start - End).">
|
||||
<Card label="Time Range" code="<TimeRangePicker />">
|
||||
<Card label="Time Range" code="<TimeRangePicker />">
|
||||
<TimeRangePicker className="w-full" />
|
||||
</Card>
|
||||
|
||||
|
||||
<Card label="Date Range" code="<DateRangePicker />">
|
||||
<DateRangePicker className="w-full" />
|
||||
</Card>
|
||||
@@ -110,23 +111,21 @@ export default function PickerShowcase({status}: {status: InputStatusType}) {
|
||||
<Card label="Year Range" code="<YearRangePicker />">
|
||||
<YearRangePicker className="w-full" />
|
||||
</Card>
|
||||
|
||||
|
||||
</Section>
|
||||
|
||||
{/* 3. Validation States */}
|
||||
<Section title="Validation & States" description="Visualisasi state error, warning, dan disabled.">
|
||||
<Card label="Error State" code={`status="${status}"`} >
|
||||
<Card label="Error State" code={`status="${status}"`}>
|
||||
<DatePicker status={status} placeholder="Field is required" />
|
||||
<span className="text-xs text-red-500 mt-1 block">This field is required.</span>
|
||||
</Card>
|
||||
|
||||
<Card label="Warning State" code={`status="${status}"`} >
|
||||
<Card label="Warning State" code={`status="${status}"`}>
|
||||
<DatePicker status={status} placeholder="Check compatibility" defaultValue={dayjs()} />
|
||||
<span className="text-xs text-yellow-600 mt-1 block">Warning: Date is in the past.</span>
|
||||
</Card>
|
||||
|
||||
<Card label="Success State" code={`status="${status}"`} >
|
||||
<Card label="Success State" code={`status="${status}"`}>
|
||||
<DatePicker status={status} defaultValue={dayjs()} />
|
||||
</Card>
|
||||
|
||||
@@ -141,22 +140,15 @@ export default function PickerShowcase({status}: {status: InputStatusType}) {
|
||||
{/* 4. Advanced & Customization */}
|
||||
<Section title="Advanced Features" description="Fitur lanjutan seperti format, waktu, dan presets.">
|
||||
<Card label="Date & Time" code="showTime">
|
||||
<DatePicker
|
||||
showTime
|
||||
format="YYYY-MM-DD HH:mm"
|
||||
placeholder="Select date & time"
|
||||
/>
|
||||
<DatePicker showTime format="YYYY-MM-DD HH:mm" placeholder="Select date & time" />
|
||||
</Card>
|
||||
|
||||
<Card label="Custom Format" code='format="DD/MM/YYYY"'>
|
||||
<DatePicker
|
||||
format="DD/MM/YYYY"
|
||||
placeholder="31/12/2025"
|
||||
/>
|
||||
<DatePicker format="DD/MM/YYYY" placeholder="31/12/2025" />
|
||||
</Card>
|
||||
|
||||
<Card label="Range with Presets" code="presets={[...]}">
|
||||
<DateRangePicker
|
||||
<DateRangePicker
|
||||
presets={[
|
||||
{ label: 'Today', value: [dayjs(), dayjs()] },
|
||||
{ label: 'Next 7 Days', value: [dayjs(), dayjs().add(7, 'd')] },
|
||||
@@ -166,11 +158,51 @@ export default function PickerShowcase({status}: {status: InputStatusType}) {
|
||||
</Card>
|
||||
|
||||
<Card label="Read Only Input" code="inputReadOnly">
|
||||
<DatePicker inputReadOnly placeholder="Click to open (No typing)" />
|
||||
<DatePicker inputReadOnly placeholder="Click to open (No typing)" />
|
||||
</Card>
|
||||
</Section>
|
||||
|
||||
{/* 5. STATIC CALENDAR (Picker Panel) */}
|
||||
<Section
|
||||
title="Static Calendar (Embedded)"
|
||||
description="Kalender statis yang langsung ditampilkan di halaman (bukan popup)."
|
||||
>
|
||||
{/* Basic Calendar */}
|
||||
<div className="col-span-1 md:col-span-1">
|
||||
<Card label="Standard Calendar" code="<Calendar />">
|
||||
<div className="border border-gray-200 rounded-lg shadow-sm bg-white inline-block overflow-hidden">
|
||||
<Calendar />
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Calendar with State & Time */}
|
||||
<div className="col-span-1 md:col-span-2">
|
||||
<Card label="Calendar with Date & Time" code="<Calendar showTime />">
|
||||
<div className="flex flex-col sm:flex-row gap-6 items-start">
|
||||
{/* Visual Calendar */}
|
||||
<div className="border border-gray-200 rounded-lg shadow-sm bg-white inline-block overflow-hidden">
|
||||
<Calendar
|
||||
showTime
|
||||
onChange={(date) => {
|
||||
console.log('Selected:', new DateUtils(date as any).format('YYYY-MM-DD HH:mm:ss'));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Info Text */}
|
||||
<div className="p-4 bg-blue-50 text-blue-800 rounded-lg text-sm max-w-xs">
|
||||
<p className="font-semibold mb-2">Info:</p>
|
||||
<p>
|
||||
Komponen <code>Calendar</code> ini adalah <i>Panel</i> dasar. Sangat berguna untuk sidebar,
|
||||
dashboard widget, atau form yang membutuhkan pemilihan tanggal yang selalu terlihat.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { InputStatusType } from '@repo/ui';
|
||||
import CheckboxShowcase from './components/checkbox.showcase';
|
||||
import InputShowCase from './components/input.showcase';
|
||||
import { SwitchShowcase } from './components/switch.showcase';
|
||||
import PickerShowcase from './components/date-picker.showcase';
|
||||
|
||||
export default function Showcase() {
|
||||
// State untuk menyimpan status yang dipilih
|
||||
@@ -66,9 +67,10 @@ export default function Showcase() {
|
||||
</div>
|
||||
|
||||
<div className="space-y-12 p-8 ">
|
||||
<SwitchShowcase />
|
||||
<CheckboxShowcase status={selectedStatus} />
|
||||
<InputShowCase status={selectedStatus} />
|
||||
{/* <SwitchShowcase /> */}
|
||||
{/* <CheckboxShowcase status={selectedStatus} /> */}
|
||||
{/* <InputShowCase status={selectedStatus} /> */}
|
||||
<PickerShowcase status={selectedStatus} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user