@srcroot/ui 0.0.44 → 0.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/registry/analytics/google-tag-manager.tsx +1 -1
- package/src/registry/themes/v3/slate.css +1 -1
- package/src/registry/themes/v4/blue.css +34 -36
- package/src/registry/themes/v4/gray.css +36 -38
- package/src/registry/themes/v4/green.css +34 -36
- package/src/registry/themes/v4/neutral.css +36 -38
- package/src/registry/themes/v4/orange.css +34 -36
- package/src/registry/themes/v4/rose.css +34 -36
- package/src/registry/themes/v4/slate.css +37 -39
- package/src/registry/themes/v4/stone.css +36 -38
- package/src/registry/themes/v4/violet.css +36 -38
- package/src/registry/themes/v4/zinc.css +34 -36
- package/src/registry/ui/calendar.tsx +2 -2
- package/src/registry/ui/chart.tsx +17 -15
- package/src/registry/ui/date-picker.tsx +64 -15
- package/src/registry/ui/dropdown-menu.tsx +92 -15
- package/src/registry/ui/popover.tsx +3 -2
- package/src/registry/ui/sidebar.tsx +159 -0
- package/src/registry/ui/theme-switcher.tsx +66 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @srcroot/ui - Slate Theme (Tailwind 4)
|
|
3
|
-
* Cool gray with strong blue undertones (
|
|
3
|
+
* Cool gray with strong blue undertones (default)
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
@import "tailwindcss";
|
|
@@ -126,54 +126,52 @@
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
:
|
|
131
|
-
|
|
132
|
-
--foreground: hsl(210 40% 98%);
|
|
129
|
+
.dark {
|
|
130
|
+
--background: hsl(222.2 84% 4.9%);
|
|
131
|
+
--foreground: hsl(210 40% 98%);
|
|
133
132
|
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
--card: hsl(222.2 84% 4.9%);
|
|
134
|
+
--card-foreground: hsl(210 40% 98%);
|
|
136
135
|
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
--popover: hsl(222.2 84% 4.9%);
|
|
137
|
+
--popover-foreground: hsl(210 40% 98%);
|
|
139
138
|
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
--primary: hsl(210 40% 98%);
|
|
140
|
+
--primary-foreground: hsl(222.2 47.4% 11.2%);
|
|
142
141
|
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
--secondary: hsl(217.2 32.6% 17.5%);
|
|
143
|
+
--secondary-foreground: hsl(210 40% 98%);
|
|
145
144
|
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
--muted: hsl(217.2 32.6% 17.5%);
|
|
146
|
+
--muted-foreground: hsl(215 20.2% 65.1%);
|
|
148
147
|
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
--accent: hsl(217.2 32.6% 17.5%);
|
|
149
|
+
--accent-foreground: hsl(210 40% 98%);
|
|
151
150
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
--success: hsl(142.1 70.6% 45.3%);
|
|
156
|
-
--success-foreground: hsl(222.2 47.4% 11.2%);
|
|
157
|
-
|
|
158
|
-
--warning: hsl(48 96.5% 53.1%);
|
|
159
|
-
--warning-foreground: hsl(222.2 47.4% 11.2%);
|
|
151
|
+
--destructive: hsl(0 62.8% 30.6%);
|
|
152
|
+
--destructive-foreground: hsl(210 40% 98%);
|
|
160
153
|
|
|
161
|
-
|
|
162
|
-
|
|
154
|
+
--success: hsl(142.1 70.6% 45.3%);
|
|
155
|
+
--success-foreground: hsl(222.2 47.4% 11.2%);
|
|
163
156
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
--ring: hsl(212.7 26.8% 83.9%);
|
|
157
|
+
--warning: hsl(48 96.5% 53.1%);
|
|
158
|
+
--warning-foreground: hsl(222.2 47.4% 11.2%);
|
|
167
159
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
160
|
+
--info: hsl(199.4 95.5% 53.8%);
|
|
161
|
+
--info-foreground: hsl(222.2 47.4% 11.2%);
|
|
162
|
+
|
|
163
|
+
--border: hsl(217.2 32.6% 17.5%);
|
|
164
|
+
--input: hsl(217.2 32.6% 17.5%);
|
|
165
|
+
--ring: hsl(212.7 26.8% 83.9%);
|
|
166
|
+
|
|
167
|
+
--sidebar-background: hsl(222.2 84% 10%);
|
|
168
|
+
--sidebar-foreground: hsl(210 40% 98%);
|
|
169
|
+
--sidebar-primary: hsl(210 40% 98%);
|
|
170
|
+
--sidebar-primary-foreground: hsl(222.2 47.4% 11.2%);
|
|
171
|
+
--sidebar-accent: hsl(217.2 32.6% 17.5%);
|
|
172
|
+
--sidebar-accent-foreground: hsl(210 40% 98%);
|
|
173
|
+
--sidebar-border: hsl(217.2 32.6% 17.5%);
|
|
174
|
+
--sidebar-ring: hsl(212.7 26.8% 83.9%);
|
|
177
175
|
}
|
|
178
176
|
|
|
179
177
|
body {
|
|
@@ -126,54 +126,52 @@
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
:
|
|
131
|
-
|
|
132
|
-
--foreground: hsl(60 9.1% 97.8%);
|
|
129
|
+
.dark {
|
|
130
|
+
--background: hsl(24 9.8% 10%);
|
|
131
|
+
--foreground: hsl(60 9.1% 97.8%);
|
|
133
132
|
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
--card: hsl(24 9.8% 10%);
|
|
134
|
+
--card-foreground: hsl(60 9.1% 97.8%);
|
|
136
135
|
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
--popover: hsl(24 9.8% 10%);
|
|
137
|
+
--popover-foreground: hsl(60 9.1% 97.8%);
|
|
139
138
|
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
--primary: hsl(60 9.1% 97.8%);
|
|
140
|
+
--primary-foreground: hsl(24 9.8% 10%);
|
|
142
141
|
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
--secondary: hsl(12 6.5% 15.1%);
|
|
143
|
+
--secondary-foreground: hsl(60 9.1% 97.8%);
|
|
145
144
|
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
--muted: hsl(12 6.5% 15.1%);
|
|
146
|
+
--muted-foreground: hsl(24 5.4% 63.9%);
|
|
148
147
|
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
--accent: hsl(12 6.5% 15.1%);
|
|
149
|
+
--accent-foreground: hsl(60 9.1% 97.8%);
|
|
151
150
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
--success: hsl(142.1 70.6% 45.3%);
|
|
156
|
-
--success-foreground: hsl(24 9.8% 10%);
|
|
157
|
-
|
|
158
|
-
--warning: hsl(48 96.5% 53.1%);
|
|
159
|
-
--warning-foreground: hsl(24 9.8% 10%);
|
|
151
|
+
--destructive: hsl(0 62.8% 30.6%);
|
|
152
|
+
--destructive-foreground: hsl(60 9.1% 97.8%);
|
|
160
153
|
|
|
161
|
-
|
|
162
|
-
|
|
154
|
+
--success: hsl(142.1 70.6% 45.3%);
|
|
155
|
+
--success-foreground: hsl(24 9.8% 10%);
|
|
163
156
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
--ring: hsl(24 5.7% 82.9%);
|
|
157
|
+
--warning: hsl(48 96.5% 53.1%);
|
|
158
|
+
--warning-foreground: hsl(24 9.8% 10%);
|
|
167
159
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
160
|
+
--info: hsl(199.4 95.5% 53.8%);
|
|
161
|
+
--info-foreground: hsl(24 9.8% 10%);
|
|
162
|
+
|
|
163
|
+
--border: hsl(12 6.5% 15.1%);
|
|
164
|
+
--input: hsl(12 6.5% 15.1%);
|
|
165
|
+
--ring: hsl(24 5.7% 82.9%);
|
|
166
|
+
|
|
167
|
+
--sidebar-background: hsl(24 9.8% 14%);
|
|
168
|
+
--sidebar-foreground: hsl(60 9.1% 97.8%);
|
|
169
|
+
--sidebar-primary: hsl(60 9.1% 97.8%);
|
|
170
|
+
--sidebar-primary-foreground: hsl(24 9.8% 10%);
|
|
171
|
+
--sidebar-accent: hsl(12 6.5% 15.1%);
|
|
172
|
+
--sidebar-accent-foreground: hsl(60 9.1% 97.8%);
|
|
173
|
+
--sidebar-border: hsl(12 6.5% 15.1%);
|
|
174
|
+
--sidebar-ring: hsl(24 5.7% 82.9%);
|
|
177
175
|
}
|
|
178
176
|
|
|
179
177
|
body {
|
|
@@ -126,54 +126,52 @@
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
:
|
|
131
|
-
|
|
132
|
-
--foreground: hsl(0 0% 98%);
|
|
129
|
+
.dark {
|
|
130
|
+
--background: hsl(246 20% 6%);
|
|
131
|
+
--foreground: hsl(0 0% 98%);
|
|
133
132
|
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
--card: hsl(246 20% 8%);
|
|
134
|
+
--card-foreground: hsl(0 0% 98%);
|
|
136
135
|
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
--popover: hsl(246 20% 8%);
|
|
137
|
+
--popover-foreground: hsl(0 0% 98%);
|
|
139
138
|
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
--primary: hsl(246 80% 65%);
|
|
140
|
+
--primary-foreground: hsl(246 20% 6%);
|
|
142
141
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
--muted: hsl(246 20% 15%);
|
|
147
|
-
--muted-foreground: hsl(246 10% 60%);
|
|
148
|
-
|
|
149
|
-
--accent: hsl(320 85% 60%);
|
|
150
|
-
--accent-foreground: hsl(0 0% 100%);
|
|
142
|
+
--secondary: hsl(320 85% 60%);
|
|
143
|
+
--secondary-foreground: hsl(0 0% 100%);
|
|
151
144
|
|
|
152
|
-
|
|
153
|
-
|
|
145
|
+
--muted: hsl(246 20% 15%);
|
|
146
|
+
--muted-foreground: hsl(246 10% 60%);
|
|
154
147
|
|
|
155
|
-
|
|
156
|
-
|
|
148
|
+
--accent: hsl(320 85% 60%);
|
|
149
|
+
--accent-foreground: hsl(0 0% 100%);
|
|
157
150
|
|
|
158
|
-
|
|
159
|
-
|
|
151
|
+
--destructive: hsl(0 62.8% 30.6%);
|
|
152
|
+
--destructive-foreground: hsl(0 0% 98%);
|
|
160
153
|
|
|
161
|
-
|
|
162
|
-
|
|
154
|
+
--success: hsl(142.1 70.6% 45.3%);
|
|
155
|
+
--success-foreground: hsl(246 80% 60%);
|
|
163
156
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
--ring: hsl(246 80% 65%);
|
|
157
|
+
--warning: hsl(48 96.5% 53.1%);
|
|
158
|
+
--warning-foreground: hsl(246 80% 60%);
|
|
167
159
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
160
|
+
--info: hsl(199.4 95.5% 53.8%);
|
|
161
|
+
--info-foreground: hsl(246 80% 60%);
|
|
162
|
+
|
|
163
|
+
--border: hsl(246 20% 18%);
|
|
164
|
+
--input: hsl(246 20% 18%);
|
|
165
|
+
--ring: hsl(246 80% 65%);
|
|
166
|
+
|
|
167
|
+
--sidebar-background: hsl(246 20% 10%);
|
|
168
|
+
--sidebar-foreground: hsl(0 0% 98%);
|
|
169
|
+
--sidebar-primary: hsl(246 80% 65%);
|
|
170
|
+
--sidebar-primary-foreground: hsl(246 20% 6%);
|
|
171
|
+
--sidebar-accent: hsl(320 85% 60%);
|
|
172
|
+
--sidebar-accent-foreground: hsl(0 0% 100%);
|
|
173
|
+
--sidebar-border: hsl(246 20% 18%);
|
|
174
|
+
--sidebar-ring: hsl(246 80% 65%);
|
|
177
175
|
}
|
|
178
176
|
|
|
179
177
|
body {
|
|
@@ -126,54 +126,52 @@
|
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
:
|
|
131
|
-
|
|
132
|
-
--foreground: hsl(0 0% 98%);
|
|
129
|
+
.dark {
|
|
130
|
+
--background: hsl(240 10% 3.9%);
|
|
131
|
+
--foreground: hsl(0 0% 98%);
|
|
133
132
|
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
--card: hsl(240 10% 3.9%);
|
|
134
|
+
--card-foreground: hsl(0 0% 98%);
|
|
136
135
|
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
--popover: hsl(240 10% 3.9%);
|
|
137
|
+
--popover-foreground: hsl(0 0% 98%);
|
|
139
138
|
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
--primary: hsl(0 0% 98%);
|
|
140
|
+
--primary-foreground: hsl(240 5.9% 10%);
|
|
142
141
|
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
--secondary: hsl(240 3.7% 15.9%);
|
|
143
|
+
--secondary-foreground: hsl(0 0% 98%);
|
|
145
144
|
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
--muted: hsl(240 3.7% 15.9%);
|
|
146
|
+
--muted-foreground: hsl(240 5% 64.9%);
|
|
148
147
|
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
--accent: hsl(240 3.7% 15.9%);
|
|
149
|
+
--accent-foreground: hsl(0 0% 98%);
|
|
151
150
|
|
|
152
|
-
|
|
153
|
-
|
|
151
|
+
--destructive: hsl(0 62.8% 30.6%);
|
|
152
|
+
--destructive-foreground: hsl(0 0% 98%);
|
|
154
153
|
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
--success: hsl(142.1 70.6% 45.3%);
|
|
155
|
+
--success-foreground: hsl(240 5.9% 10%);
|
|
157
156
|
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
--warning: hsl(48 96.5% 53.1%);
|
|
158
|
+
--warning-foreground: hsl(240 5.9% 10%);
|
|
160
159
|
|
|
161
|
-
|
|
162
|
-
|
|
160
|
+
--info: hsl(199.4 95.5% 53.8%);
|
|
161
|
+
--info-foreground: hsl(240 5.9% 10%);
|
|
163
162
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
--border: hsl(240 3.7% 15.9%);
|
|
164
|
+
--input: hsl(240 3.7% 15.9%);
|
|
165
|
+
--ring: hsl(240 4.9% 83.9%);
|
|
167
166
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
}
|
|
167
|
+
--sidebar-background: hsl(240 5.9% 10%);
|
|
168
|
+
--sidebar-foreground: hsl(240 4.8% 95.9%);
|
|
169
|
+
--sidebar-primary: hsl(224.3 76.3% 48%);
|
|
170
|
+
--sidebar-primary-foreground: hsl(0 0% 100%);
|
|
171
|
+
--sidebar-accent: hsl(240 3.7% 15.9%);
|
|
172
|
+
--sidebar-accent-foreground: hsl(240 4.8% 95.9%);
|
|
173
|
+
--sidebar-border: hsl(240 3.7% 15.9%);
|
|
174
|
+
--sidebar-ring: hsl(217.2 91.2% 59.8%);
|
|
177
175
|
}
|
|
178
176
|
|
|
179
177
|
body {
|
|
@@ -72,7 +72,8 @@ function getDaysInMonth(year: number, month: number): Date[] {
|
|
|
72
72
|
return days
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
function isSameDay(d1: Date, d2: Date): boolean {
|
|
75
|
+
function isSameDay(d1: Date | undefined | null, d2: Date | undefined | null): boolean {
|
|
76
|
+
if (!d1 || !d2) return false
|
|
76
77
|
return d1.getDate() === d2.getDate() &&
|
|
77
78
|
d1.getMonth() === d2.getMonth() &&
|
|
78
79
|
d1.getFullYear() === d2.getFullYear()
|
|
@@ -509,4 +510,3 @@ const Calendar = React.forwardRef<HTMLDivElement, CalendarProps>(
|
|
|
509
510
|
Calendar.displayName = "Calendar"
|
|
510
511
|
|
|
511
512
|
export { Calendar }
|
|
512
|
-
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import * as React from "react"
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
Legend as ChartLegendPrimitive,
|
|
6
|
+
ResponsiveContainer,
|
|
7
|
+
Tooltip as ChartTooltipPrimitive,
|
|
8
|
+
} from "recharts"
|
|
5
9
|
|
|
6
10
|
import { cn } from "@/lib/utils"
|
|
7
11
|
|
|
@@ -102,13 +106,19 @@ const ChartTooltip = ChartTooltipPrimitive
|
|
|
102
106
|
|
|
103
107
|
const ChartTooltipContent = React.forwardRef<
|
|
104
108
|
HTMLDivElement,
|
|
105
|
-
React.ComponentProps<typeof ChartTooltipPrimitive> &
|
|
109
|
+
Omit<React.ComponentProps<typeof ChartTooltipPrimitive>, "payload"> &
|
|
106
110
|
React.ComponentProps<"div"> & {
|
|
107
111
|
hideLabel?: boolean
|
|
108
112
|
hideIndicator?: boolean
|
|
109
113
|
indicator?: "line" | "dot" | "dashed"
|
|
110
114
|
nameKey?: string
|
|
111
115
|
labelKey?: string
|
|
116
|
+
payload?: any[]
|
|
117
|
+
label?: any
|
|
118
|
+
labelFormatter?: any
|
|
119
|
+
labelClassName?: string
|
|
120
|
+
formatter?: any
|
|
121
|
+
color?: string
|
|
112
122
|
}
|
|
113
123
|
>(
|
|
114
124
|
(
|
|
@@ -181,7 +191,7 @@ const ChartTooltipContent = React.forwardRef<
|
|
|
181
191
|
>
|
|
182
192
|
{!nestLabel ? tooltipLabel : null}
|
|
183
193
|
<div className="grid gap-1.5">
|
|
184
|
-
{payload.map((item, index) => {
|
|
194
|
+
{payload.map((item: any, index: number) => {
|
|
185
195
|
const key = `${nameKey || item.name || item.dataKey || "value"}`
|
|
186
196
|
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
|
187
197
|
const indicatorColor = color || item.payload.fill || item.color
|
|
@@ -257,7 +267,9 @@ const ChartLegend = ChartLegendPrimitive
|
|
|
257
267
|
const ChartLegendContent = React.forwardRef<
|
|
258
268
|
HTMLDivElement,
|
|
259
269
|
React.ComponentProps<"div"> &
|
|
260
|
-
|
|
270
|
+
{
|
|
271
|
+
payload?: any[]
|
|
272
|
+
verticalAlign?: "top" | "middle" | "bottom"
|
|
261
273
|
hideIcon?: boolean
|
|
262
274
|
nameKey?: string
|
|
263
275
|
}
|
|
@@ -281,7 +293,7 @@ const ChartLegendContent = React.forwardRef<
|
|
|
281
293
|
className
|
|
282
294
|
)}
|
|
283
295
|
>
|
|
284
|
-
{payload.map((item) => {
|
|
296
|
+
{(payload as any[]).map((item) => {
|
|
285
297
|
const key = `${nameKey || item.dataKey || "value"}`
|
|
286
298
|
const itemConfig = getPayloadConfigFromPayload(config, item, key)
|
|
287
299
|
|
|
@@ -351,16 +363,6 @@ function getPayloadConfigFromPayload(
|
|
|
351
363
|
: config[key as keyof typeof config]
|
|
352
364
|
}
|
|
353
365
|
|
|
354
|
-
// Recharts Primitive Imports - We import specific components to avoid large bundle reference but for now let's just use * and assume tree shaking or specific imports in consuming app.
|
|
355
|
-
// However, the above code uses RechartsPrimitive.Tooltip and Legend.
|
|
356
|
-
// Ideally we should import them from recharts.
|
|
357
|
-
|
|
358
|
-
import {
|
|
359
|
-
Legend as ChartLegendPrimitive,
|
|
360
|
-
Tooltip as ChartTooltipPrimitive,
|
|
361
|
-
ResponsiveContainer,
|
|
362
|
-
} from "recharts"
|
|
363
|
-
|
|
364
366
|
export {
|
|
365
367
|
ChartContainer,
|
|
366
368
|
ChartTooltip,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import * as React from "react"
|
|
4
|
+
import { addDays, startOfMonth, endOfMonth } from "date-fns"
|
|
4
5
|
import { Calendar } from "./calendar"
|
|
5
6
|
import { Popover, PopoverContent, PopoverTrigger } from "./popover"
|
|
6
7
|
import { Button } from "./button"
|
|
@@ -125,6 +126,31 @@ const DatePicker = React.forwardRef<HTMLButtonElement, DatePickerProps>(
|
|
|
125
126
|
: mode === "multiple" ? "Pick dates"
|
|
126
127
|
: "Pick a date range"
|
|
127
128
|
|
|
129
|
+
// Presets for Range Mode
|
|
130
|
+
const presets = [
|
|
131
|
+
{
|
|
132
|
+
label: "Last 7 Days",
|
|
133
|
+
getValue: () => {
|
|
134
|
+
const today = new Date()
|
|
135
|
+
return [addDays(today, -7), today]
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
label: "Last 30 Days",
|
|
140
|
+
getValue: () => {
|
|
141
|
+
const today = new Date()
|
|
142
|
+
return [addDays(today, -30), today]
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
label: "This Month",
|
|
147
|
+
getValue: () => {
|
|
148
|
+
const today = new Date()
|
|
149
|
+
return [startOfMonth(today), endOfMonth(today)]
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
]
|
|
153
|
+
|
|
128
154
|
// Handle selection
|
|
129
155
|
const handleSelect = (value: any) => {
|
|
130
156
|
if (mode === "single") {
|
|
@@ -135,10 +161,18 @@ const DatePicker = React.forwardRef<HTMLButtonElement, DatePickerProps>(
|
|
|
135
161
|
} else {
|
|
136
162
|
const dates = value || []
|
|
137
163
|
; (onSelect as ((dates: Date[]) => void))?.(dates)
|
|
138
|
-
//
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
164
|
+
// Do not close automatically for range to allow adjustment
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const handlePresetSelect = (preset: { getValue: () => Date[] }) => {
|
|
169
|
+
if (mode === "range") {
|
|
170
|
+
const dates = preset.getValue()
|
|
171
|
+
; (onSelect as ((dates: Date[]) => void))?.(dates)
|
|
172
|
+
// Update internal state if uncontrolled (not covered here fully but ensures trigger updates if parent consumes correctly)
|
|
173
|
+
// For this component to be fully controlled, parent must pass `selected`.
|
|
174
|
+
// If we want it to close on preset select:
|
|
175
|
+
setOpen(false)
|
|
142
176
|
}
|
|
143
177
|
}
|
|
144
178
|
|
|
@@ -150,9 +184,8 @@ const DatePicker = React.forwardRef<HTMLButtonElement, DatePickerProps>(
|
|
|
150
184
|
variant="outline"
|
|
151
185
|
disabled={disabled}
|
|
152
186
|
className={cn(
|
|
153
|
-
"w-[
|
|
187
|
+
"w-[260px] justify-start text-left font-normal",
|
|
154
188
|
!displayText && "text-muted-foreground",
|
|
155
|
-
numberOfMonths === 2 && "w-[320px]",
|
|
156
189
|
className
|
|
157
190
|
)}
|
|
158
191
|
>
|
|
@@ -160,15 +193,31 @@ const DatePicker = React.forwardRef<HTMLButtonElement, DatePickerProps>(
|
|
|
160
193
|
{displayText || <span>{placeholder || defaultPlaceholder}</span>}
|
|
161
194
|
</Button>
|
|
162
195
|
</PopoverTrigger>
|
|
163
|
-
<PopoverContent className="w-auto p-0">
|
|
164
|
-
<
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
196
|
+
<PopoverContent className="w-auto p-0" align="end">
|
|
197
|
+
<div className="flex">
|
|
198
|
+
{mode === "range" && (
|
|
199
|
+
<div className="border-r p-2 space-y-1 w-[140px]">
|
|
200
|
+
{presets.map((preset) => (
|
|
201
|
+
<Button
|
|
202
|
+
key={preset.label}
|
|
203
|
+
variant="ghost"
|
|
204
|
+
className="w-full justify-start font-normal"
|
|
205
|
+
onClick={() => handlePresetSelect(preset)}
|
|
206
|
+
>
|
|
207
|
+
{preset.label}
|
|
208
|
+
</Button>
|
|
209
|
+
))}
|
|
210
|
+
</div>
|
|
211
|
+
)}
|
|
212
|
+
<Calendar
|
|
213
|
+
mode={mode}
|
|
214
|
+
numberOfMonths={numberOfMonths}
|
|
215
|
+
size={size}
|
|
216
|
+
selected={selected}
|
|
217
|
+
onSelect={handleSelect}
|
|
218
|
+
className="rounded-md border-0 shadow-none"
|
|
219
|
+
/>
|
|
220
|
+
</div>
|
|
172
221
|
</PopoverContent>
|
|
173
222
|
</Popover>
|
|
174
223
|
)
|