From 34dc5b0f87b68ee818825b97e0d5d677e4950f07 Mon Sep 17 00:00:00 2001 From: MarkLo Date: Tue, 2 Dec 2025 23:03:41 +0800 Subject: [PATCH] --- frontend/app/analysis/page.tsx | 2 +- frontend/app/analysis/results/page.tsx | 4 +- frontend/app/globals.css | 222 +++++------------- frontend/app/page.tsx | 12 +- frontend/components/analysis/AnalysisForm.tsx | 12 +- .../components/analysis/AnalystReport.tsx | 2 +- .../components/analysis/DownloadReports.tsx | 2 +- frontend/components/analysis/PriceChart.tsx | 2 +- .../components/analysis/TradingDecision.tsx | 2 +- frontend/components/ui/button.tsx | 2 +- frontend/components/ui/calendar.tsx | 216 +++++++++++++++++ frontend/components/ui/card.tsx | 2 +- frontend/components/ui/checkbox.tsx | 5 +- frontend/components/ui/date-picker.tsx | 59 +++++ frontend/components/ui/input.tsx | 7 +- frontend/components/ui/popover.tsx | 48 ++++ frontend/components/ui/select.tsx | 7 +- frontend/package.json | 2 + frontend/pnpm-lock.yaml | 65 +++++ 19 files changed, 482 insertions(+), 191 deletions(-) create mode 100644 frontend/components/ui/calendar.tsx create mode 100644 frontend/components/ui/date-picker.tsx create mode 100644 frontend/components/ui/popover.tsx diff --git a/frontend/app/analysis/page.tsx b/frontend/app/analysis/page.tsx index 506b502e..e17fbbae 100644 --- a/frontend/app/analysis/page.tsx +++ b/frontend/app/analysis/page.tsx @@ -44,7 +44,7 @@ export default function AnalysisPage() { }; return ( -
+
{/* 標題區域 - 置中對齊 */} diff --git a/frontend/app/analysis/results/page.tsx b/frontend/app/analysis/results/page.tsx index 10987746..e8b5a7be 100644 --- a/frontend/app/analysis/results/page.tsx +++ b/frontend/app/analysis/results/page.tsx @@ -129,7 +129,7 @@ export default function AnalysisResultsPage() { const currentReport = getNestedValue(analysisResult.reports, currentAnalyst?.reportKey || ""); return ( -
+
{/* Header */} @@ -180,7 +180,7 @@ export default function AnalysisResultsPage() { )} {/* 分析師報告 */} - + {analyst.label} 報告 diff --git a/frontend/app/globals.css b/frontend/app/globals.css index d5389cba..1646a857 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -257,13 +257,13 @@ GRADIENT UTILITIES ======================================== */ -/* Gradient Backgrounds */ +/* Gradient Backgrounds - Purple/Pink theme */ .gradient-bg-primary { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background: linear-gradient(135deg, #9333EA 0%, #EC4899 100%); } .dark .gradient-bg-primary { - background: linear-gradient(135deg, #4c51bf 0%, #553c9a 100%); + background: linear-gradient(135deg, #7C3AED 0%, #DB2777 100%); } .gradient-bg-secondary { @@ -410,9 +410,9 @@ } } -/* Gradient Text */ +/* Gradient Text - Purple/Pink theme */ .gradient-text-primary { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background: linear-gradient(135deg, #9333EA 0%, #EC4899 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; @@ -535,181 +535,67 @@ } /* ======================================== - DATE PICKER CUSTOM STYLING + GLASSMORPHISM UTILITIES ======================================== */ -/* Modern Date Input Styling */ -input[type="date"] { - position: relative; - padding: 0.75rem 1rem; - font-size: 1rem; - font-weight: 500; - line-height: 1.5; - color: var(--foreground); - background: linear-gradient( - 135deg, - rgba(102, 126, 234, 0.05) 0%, - rgba(118, 75, 162, 0.05) 100% - ); - border: 2px solid rgba(102, 126, 234, 0.3); - border-radius: 0.75rem; - transition: all 0.3s ease; - cursor: pointer; +/* Base glassmorphism style - Subtle white with hint of pink */ +.glass { + background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); + border: 1px solid rgba(147, 51, 234, 0.08); + box-shadow: 0 2px 12px 0 rgba(147, 51, 234, 0.04); } -input[type="date"]:hover { +.dark .glass { + background: rgba(30, 20, 40, 0.95); + border: 1px solid rgba(147, 51, 234, 0.15); + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.4); +} + +/* Enhanced glass with gradient - Very subtle pink/purple tint */ +.glass-gradient { background: linear-gradient( 135deg, - rgba(102, 126, 234, 0.1) 0%, - rgba(118, 75, 162, 0.1) 100% + rgba(255, 255, 255, 0.98) 0%, + rgba(252, 248, 255, 0.98) 100% ); - border-color: rgba(102, 126, 234, 0.5); - box-shadow: 0 4px 12px rgba(102, 126, 234, 0.2); + backdrop-filter: blur(10px); + -webkit-backdrop-filter: blur(10px); + border: 1px solid rgba(147, 51, 234, 0.1); + box-shadow: 0 2px 16px 0 rgba(147, 51, 234, 0.06), + inset 0 1px 0 0 rgba(255, 255, 255, 0.5); +} + +.dark .glass-gradient { + background: linear-gradient( + 135deg, + rgba(30, 20, 40, 0.95) 0%, + rgba(40, 25, 50, 0.95) 100% + ); + border: 1px solid rgba(147, 51, 234, 0.2); + box-shadow: 0 2px 16px 0 rgba(147, 51, 234, 0.15), + inset 0 1px 0 0 rgba(255, 255, 255, 0.05); +} + +/* Glass hover effect - Subtle */ +.glass-hover { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +.glass-hover:hover { + background: rgba(255, 255, 255, 1); + border-color: rgba(147, 51, 234, 0.15); + box-shadow: 0 4px 20px 0 rgba(147, 51, 234, 0.1), + inset 0 1px 0 0 rgba(255, 255, 255, 0.8); transform: translateY(-2px); } -input[type="date"]:focus { - outline: none; - background: linear-gradient( - 135deg, - rgba(102, 126, 234, 0.15) 0%, - rgba(118, 75, 162, 0.15) 100% - ); - border-color: rgba(102, 126, 234, 0.6); - box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1), - 0 8px 16px rgba(102, 126, 234, 0.25); - transform: translateY(-2px); +.dark .glass-hover:hover { + background: rgba(30, 20, 40, 1); + border-color: rgba(147, 51, 234, 0.3); + box-shadow: 0 4px 20px 0 rgba(147, 51, 234, 0.2), + inset 0 1px 0 0 rgba(255, 255, 255, 0.1); } -/* Dark mode date input */ -.dark input[type="date"] { - background: linear-gradient( - 135deg, - rgba(76, 81, 191, 0.15) 0%, - rgba(85, 60, 154, 0.15) 100% - ); - border-color: rgba(76, 81, 191, 0.4); -} -.dark input[type="date"]:hover { - background: linear-gradient( - 135deg, - rgba(76, 81, 191, 0.2) 0%, - rgba(85, 60, 154, 0.2) 100% - ); - border-color: rgba(76, 81, 191, 0.6); - box-shadow: 0 4px 12px rgba(76, 81, 191, 0.3); -} - -.dark input[type="date"]:focus { - background: linear-gradient( - 135deg, - rgba(76, 81, 191, 0.25) 0%, - rgba(85, 60, 154, 0.25) 100% - ); - border-color: rgba(76, 81, 191, 0.7); - box-shadow: 0 0 0 3px rgba(76, 81, 191, 0.15), - 0 8px 16px rgba(76, 81, 191, 0.35); -} - -/* Calendar icon styling */ -input[type="date"]::-webkit-calendar-picker-indicator { - cursor: pointer; - opacity: 0.8; - padding: 0.25rem; - border-radius: 0.375rem; - transition: all 0.2s ease; - filter: brightness(0.9); -} - -input[type="date"]::-webkit-calendar-picker-indicator:hover { - opacity: 1; - background: rgba(102, 126, 234, 0.15); - transform: scale(1.1); - filter: brightness(1.1); -} - -.dark input[type="date"]::-webkit-calendar-picker-indicator { - filter: invert(1) brightness(0.9); -} - -.dark input[type="date"]::-webkit-calendar-picker-indicator:hover { - background: rgba(76, 81, 191, 0.25); - filter: invert(1) brightness(1.1); -} - -/* Date input inner elements (webkit) */ -input[type="date"]::-webkit-datetime-edit-fields-wrapper { - padding: 0; -} - -input[type="date"]::-webkit-datetime-edit-text { - padding: 0 0.25rem; - opacity: 0.7; -} - -input[type="date"]::-webkit-datetime-edit-month-field, -input[type="date"]::-webkit-datetime-edit-day-field, -input[type="date"]::-webkit-datetime-edit-year-field { - padding: 0.25rem 0.5rem; - border-radius: 0.375rem; - transition: all 0.2s ease; -} - -input[type="date"]::-webkit-datetime-edit-month-field:hover, -input[type="date"]::-webkit-datetime-edit-day-field:hover, -input[type="date"]::-webkit-datetime-edit-year-field:hover { - background: rgba(102, 126, 234, 0.2); - color: var(--foreground); -} - -input[type="date"]::-webkit-datetime-edit-month-field:focus, -input[type="date"]::-webkit-datetime-edit-day-field:focus, -input[type="date"]::-webkit-datetime-edit-year-field:focus { - background: rgba(102, 126, 234, 0.25); - color: var(--foreground); - outline: none; -} - -.dark input[type="date"]::-webkit-datetime-edit-month-field:hover, -.dark input[type="date"]::-webkit-datetime-edit-day-field:hover, -.dark input[type="date"]::-webkit-datetime-edit-year-field:hover { - background: rgba(76, 81, 191, 0.3); -} - -.dark input[type="date"]::-webkit-datetime-edit-month-field:focus, -.dark input[type="date"]::-webkit-datetime-edit-day-field:focus, -.dark input[type="date"]::-webkit-datetime-edit-year-field:focus { - background: rgba(76, 81, 191, 0.35); -} - -/* Placeholder styling when empty */ -input[type="date"]:invalid::-webkit-datetime-edit { - color: var(--muted-foreground); -} - -/* Animation for date picker open */ -@keyframes datePickerSlide { - from { - opacity: 0; - transform: translateY(-10px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -/* Additional polish */ -input[type="date"]::before { - content: attr(placeholder); - width: 100%; - color: var(--muted-foreground); -} - -input[type="date"]:focus::before, -input[type="date"]:valid::before { - display: none; -} diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index d60ee28e..fcff08c1 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -11,7 +11,7 @@ import { export default function HomePage() { return ( -
+
{/* Hero Section */}
@@ -248,7 +248,7 @@ export default function HomePage() {

TradingAgentsX 模擬真實交易公司,配備專業化的 LLM 代理

- +
+
{icon}
{title} @@ -380,7 +380,7 @@ function AgentCard({ responsibilities: string[]; }) { return ( - + {name} {role} @@ -421,7 +421,7 @@ function LLMProviderCard({ const logoSrc = logoMap[name]; return ( - +
{logoSrc ? ( @@ -462,7 +462,7 @@ function TechnicalCard({ features: string[]; }) { return ( - + {title} diff --git a/frontend/components/analysis/AnalysisForm.tsx b/frontend/components/analysis/AnalysisForm.tsx index c4dda477..3abae6ea 100644 --- a/frontend/components/analysis/AnalysisForm.tsx +++ b/frontend/components/analysis/AnalysisForm.tsx @@ -10,6 +10,7 @@ import * as z from "zod"; import { format } from "date-fns"; import { Button } from "@/components/ui/button"; +import { DatePicker } from "@/components/ui/date-picker"; import { Form, FormControl, @@ -122,7 +123,7 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) { } return ( - +
分析日期 - + { + field.onChange(date ? format(date, "yyyy-MM-dd") : "") + }} + placeholder="選擇分析日期" + className="w-full" + /> 選擇分析日期 diff --git a/frontend/components/analysis/AnalystReport.tsx b/frontend/components/analysis/AnalystReport.tsx index a2348293..694c1d37 100644 --- a/frontend/components/analysis/AnalystReport.tsx +++ b/frontend/components/analysis/AnalystReport.tsx @@ -35,7 +35,7 @@ export function AnalystReport({ reports }: AnalystReportProps) { } return ( - + 分析報告 來自所有代理團隊的詳細報告 diff --git a/frontend/components/analysis/DownloadReports.tsx b/frontend/components/analysis/DownloadReports.tsx index 52154d47..07ba03a8 100644 --- a/frontend/components/analysis/DownloadReports.tsx +++ b/frontend/components/analysis/DownloadReports.tsx @@ -134,7 +134,7 @@ export function DownloadReports({ const isAllSelected = selectedAnalysts.length === availableAnalysts.length && availableAnalysts.length > 0; return ( - + diff --git a/frontend/components/analysis/PriceChart.tsx b/frontend/components/analysis/PriceChart.tsx index 12a117a9..951e9f3c 100644 --- a/frontend/components/analysis/PriceChart.tsx +++ b/frontend/components/analysis/PriceChart.tsx @@ -44,7 +44,7 @@ export function PriceChart({ priceData, priceStats, ticker }: PriceChartProps) { const priceRange = maxPrice - minPrice; return ( - +
{ticker} 價格走勢 diff --git a/frontend/components/analysis/TradingDecision.tsx b/frontend/components/analysis/TradingDecision.tsx index 24559aa3..feddad6f 100644 --- a/frontend/components/analysis/TradingDecision.tsx +++ b/frontend/components/analysis/TradingDecision.tsx @@ -41,7 +41,7 @@ export function TradingDecision({ result }: TradingDecisionProps) { }; return ( - +
交易決策 diff --git a/frontend/components/ui/button.tsx b/frontend/components/ui/button.tsx index 21409a06..29db4625 100644 --- a/frontend/components/ui/button.tsx +++ b/frontend/components/ui/button.tsx @@ -13,7 +13,7 @@ const buttonVariants = cva( destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", outline: - "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + "glass-gradient border-2 shadow-md hover:shadow-lg hover:scale-105 hover:border-primary/50", secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", ghost: diff --git a/frontend/components/ui/calendar.tsx b/frontend/components/ui/calendar.tsx new file mode 100644 index 00000000..6f304b5b --- /dev/null +++ b/frontend/components/ui/calendar.tsx @@ -0,0 +1,216 @@ +"use client" + +import * as React from "react" +import { + ChevronDownIcon, + ChevronLeftIcon, + ChevronRightIcon, +} from "lucide-react" +import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker" + +import { cn } from "@/lib/utils" +import { Button, buttonVariants } from "@/components/ui/button" + +function Calendar({ + className, + classNames, + showOutsideDays = true, + captionLayout = "label", + buttonVariant = "ghost", + formatters, + components, + ...props +}: React.ComponentProps & { + buttonVariant?: React.ComponentProps["variant"] +}) { + const defaultClassNames = getDefaultClassNames() + + return ( + svg]:rotate-180`, + String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`, + className + )} + captionLayout={captionLayout} + formatters={{ + formatMonthDropdown: (date) => + date.toLocaleString("default", { month: "short" }), + ...formatters, + }} + classNames={{ + root: cn("w-fit", defaultClassNames.root), + months: cn( + "flex gap-4 flex-col md:flex-row relative", + defaultClassNames.months + ), + month: cn("flex flex-col w-full gap-4", defaultClassNames.month), + nav: cn( + "flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between", + defaultClassNames.nav + ), + button_previous: cn( + buttonVariants({ variant: buttonVariant }), + "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none", + defaultClassNames.button_previous + ), + button_next: cn( + buttonVariants({ variant: buttonVariant }), + "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none", + defaultClassNames.button_next + ), + month_caption: cn( + "flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)", + defaultClassNames.month_caption + ), + dropdowns: cn( + "w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5", + defaultClassNames.dropdowns + ), + dropdown_root: cn( + "relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md", + defaultClassNames.dropdown_root + ), + dropdown: cn( + "absolute bg-popover inset-0 opacity-0", + defaultClassNames.dropdown + ), + caption_label: cn( + "select-none font-medium", + captionLayout === "label" + ? "text-sm" + : "rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5", + defaultClassNames.caption_label + ), + table: "w-full border-collapse", + weekdays: cn("flex", defaultClassNames.weekdays), + weekday: cn( + "text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none", + defaultClassNames.weekday + ), + week: cn("flex w-full mt-2", defaultClassNames.week), + week_number_header: cn( + "select-none w-(--cell-size)", + defaultClassNames.week_number_header + ), + week_number: cn( + "text-[0.8rem] select-none text-muted-foreground", + defaultClassNames.week_number + ), + day: cn( + "relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none", + props.showWeekNumber + ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md" + : "[&:first-child[data-selected=true]_button]:rounded-l-md", + defaultClassNames.day + ), + range_start: cn( + "rounded-l-md bg-accent", + defaultClassNames.range_start + ), + range_middle: cn("rounded-none", defaultClassNames.range_middle), + range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end), + today: cn( + "bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none", + defaultClassNames.today + ), + outside: cn( + "text-muted-foreground aria-selected:text-muted-foreground", + defaultClassNames.outside + ), + disabled: cn( + "text-muted-foreground opacity-50", + defaultClassNames.disabled + ), + hidden: cn("invisible", defaultClassNames.hidden), + ...classNames, + }} + components={{ + Root: ({ className, rootRef, ...props }) => { + return ( +
+ ) + }, + Chevron: ({ className, orientation, ...props }) => { + if (orientation === "left") { + return ( + + ) + } + + if (orientation === "right") { + return ( + + ) + } + + return ( + + ) + }, + DayButton: CalendarDayButton, + WeekNumber: ({ children, ...props }) => { + return ( + +
+ {children} +
+ + ) + }, + ...components, + }} + {...props} + /> + ) +} + +function CalendarDayButton({ + className, + day, + modifiers, + ...props +}: React.ComponentProps) { + const defaultClassNames = getDefaultClassNames() + + const ref = React.useRef(null) + React.useEffect(() => { + if (modifiers.focused) ref.current?.focus() + }, [modifiers.focused]) + + return ( + + + + { + onDateChange(selectedDate) + setOpen(false) + }} + initialFocus + /> + + + ) +} diff --git a/frontend/components/ui/input.tsx b/frontend/components/ui/input.tsx index 89169058..c7760ea4 100644 --- a/frontend/components/ui/input.tsx +++ b/frontend/components/ui/input.tsx @@ -8,9 +8,10 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) { type={type} data-slot="input" className={cn( - "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", - "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", - "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + "glass-gradient file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground h-9 w-full min-w-0 rounded-lg border-2 px-3 py-1 text-base shadow-md transition-all outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", + "hover:border-primary/50 hover:shadow-lg hover:scale-[1.01]", + "focus-visible:border-primary focus-visible:ring-4 focus-visible:ring-primary/20 focus-visible:shadow-xl focus-visible:scale-[1.01]", + "aria-invalid:border-destructive aria-invalid:ring-4 aria-invalid:ring-destructive/20", className )} {...props} diff --git a/frontend/components/ui/popover.tsx b/frontend/components/ui/popover.tsx new file mode 100644 index 00000000..01e468b6 --- /dev/null +++ b/frontend/components/ui/popover.tsx @@ -0,0 +1,48 @@ +"use client" + +import * as React from "react" +import * as PopoverPrimitive from "@radix-ui/react-popover" + +import { cn } from "@/lib/utils" + +function Popover({ + ...props +}: React.ComponentProps) { + return +} + +function PopoverTrigger({ + ...props +}: React.ComponentProps) { + return +} + +function PopoverContent({ + className, + align = "center", + sideOffset = 4, + ...props +}: React.ComponentProps) { + return ( + + + + ) +} + +function PopoverAnchor({ + ...props +}: React.ComponentProps) { + return +} + +export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } diff --git a/frontend/components/ui/select.tsx b/frontend/components/ui/select.tsx index 25e54394..09edcd11 100644 --- a/frontend/components/ui/select.tsx +++ b/frontend/components/ui/select.tsx @@ -37,7 +37,10 @@ function SelectTrigger({ data-slot="select-trigger" data-size={size} className={cn( - "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "glass-gradient data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex w-fit items-center justify-between gap-2 rounded-lg border-2 px-3 py-2 text-sm whitespace-nowrap shadow-md transition-all outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "hover:border-primary/50 hover:shadow-lg hover:scale-105", + "focus-visible:border-primary focus-visible:ring-4 focus-visible:ring-primary/20 focus-visible:shadow-xl", + "aria-invalid:border-destructive aria-invalid:ring-4 aria-invalid:ring-destructive/20", className )} {...props} @@ -62,7 +65,7 @@ function SelectContent({ =6.9.0'} + '@date-fns/tz@1.4.1': + resolution: {integrity: sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==} + '@emnapi/core@1.7.1': resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} @@ -662,6 +671,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-popover@1.1.15': + resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-popper@1.2.8': resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} peerDependencies: @@ -1461,6 +1483,9 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} + date-fns-jalali@4.1.0-0: + resolution: {integrity: sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==} + date-fns@4.1.0: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} @@ -2531,6 +2556,12 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + react-day-picker@9.11.3: + resolution: {integrity: sha512-7lD12UvGbkyXqgzbYIGQTbl+x29B9bAf+k0pP5Dcs1evfpKk6zv4EdH/edNc8NxcmCiTNXr2HIYPrSZ3XvmVBg==} + engines: {node: '>=18'} + peerDependencies: + react: '>=16.8.0' + react-dom@19.2.0: resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==} peerDependencies: @@ -3100,6 +3131,8 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@date-fns/tz@1.4.1': {} + '@emnapi/core@1.7.1': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -3530,6 +3563,29 @@ snapshots: '@types/react': 19.2.6 '@types/react-dom': 19.2.3(@types/react@19.2.6) + '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.6))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.6)(react@19.2.0) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.6)(react@19.2.0) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.6))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.6)(react@19.2.0) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.6))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.6)(react@19.2.0) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.6))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.6))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.6))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.6))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.6)(react@19.2.0) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.6)(react@19.2.0) + aria-hidden: 1.2.6 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + react-remove-scroll: 2.7.1(@types/react@19.2.6)(react@19.2.0) + optionalDependencies: + '@types/react': 19.2.6 + '@types/react-dom': 19.2.3(@types/react@19.2.6) + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.6))(@types/react@19.2.6)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': dependencies: '@floating-ui/react-dom': 2.1.6(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -4314,6 +4370,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + date-fns-jalali@4.1.0-0: {} + date-fns@4.1.0: {} debug@3.2.7: @@ -5749,6 +5807,13 @@ snapshots: queue-microtask@1.2.3: {} + react-day-picker@9.11.3(react@19.2.0): + dependencies: + '@date-fns/tz': 1.4.1 + date-fns: 4.1.0 + date-fns-jalali: 4.1.0-0 + react: 19.2.0 + react-dom@19.2.0(react@19.2.0): dependencies: react: 19.2.0