@vendure/dashboard 3.3.6-master-202507030732 → 3.3.6-master-202507030835
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/dist/plugin/vite-plugin-vendure-dashboard.js +1 -1
- package/package.json +40 -27
- package/src/app/routes/_authenticated/_collections/collections.graphql.ts +32 -0
- package/src/app/routes/_authenticated/_collections/collections.tsx +153 -133
- package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +34 -1
- package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +430 -0
- package/src/app/routes/_authenticated/_collections/components/move-single-collection.tsx +33 -0
- package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +8 -3
- package/src/lib/components/data-table/data-table.tsx +1 -1
- package/src/lib/components/shared/paginated-list-data-table.tsx +1 -1
- package/src/lib/components/ui/accordion.tsx +50 -45
- package/src/lib/components/ui/alert-dialog.tsx +122 -93
- package/src/lib/components/ui/alert.tsx +54 -48
- package/src/lib/components/ui/aspect-ratio.tsx +9 -0
- package/src/lib/components/ui/avatar.tsx +53 -0
- package/src/lib/components/ui/badge.tsx +37 -29
- package/src/lib/components/ui/breadcrumb.tsx +89 -82
- package/src/lib/components/ui/button.tsx +52 -51
- package/src/lib/components/ui/calendar.tsx +196 -435
- package/src/lib/components/ui/card.tsx +78 -33
- package/src/lib/components/ui/carousel.tsx +241 -0
- package/src/lib/components/ui/chart.tsx +351 -0
- package/src/lib/components/ui/checkbox.tsx +28 -23
- package/src/lib/components/ui/collapsible.tsx +0 -2
- package/src/lib/components/ui/command.tsx +159 -114
- package/src/lib/components/ui/context-menu.tsx +252 -0
- package/src/lib/components/ui/dialog.tsx +115 -90
- package/src/lib/components/ui/drawer.tsx +133 -0
- package/src/lib/components/ui/dropdown-menu.tsx +207 -170
- package/src/lib/components/ui/form.tsx +138 -114
- package/src/lib/components/ui/hover-card.tsx +32 -26
- package/src/lib/components/ui/input-otp.tsx +77 -0
- package/src/lib/components/ui/input.tsx +17 -15
- package/src/lib/components/ui/label.tsx +19 -16
- package/src/lib/components/ui/menubar.tsx +274 -0
- package/src/lib/components/ui/navigation-menu.tsx +168 -0
- package/src/lib/components/ui/pagination.tsx +108 -87
- package/src/lib/components/ui/popover.tsx +36 -28
- package/src/lib/components/ui/progress.tsx +29 -0
- package/src/lib/components/ui/radio-group.tsx +45 -0
- package/src/lib/components/ui/resizable.tsx +54 -0
- package/src/lib/components/ui/scroll-area.tsx +48 -40
- package/src/lib/components/ui/select.tsx +151 -129
- package/src/lib/components/ui/separator.tsx +22 -20
- package/src/lib/components/ui/sheet.tsx +110 -91
- package/src/lib/components/ui/sidebar.tsx +652 -622
- package/src/lib/components/ui/skeleton.tsx +10 -10
- package/src/lib/components/ui/slider.tsx +63 -0
- package/src/lib/components/ui/sonner.tsx +7 -11
- package/src/lib/components/ui/switch.tsx +27 -22
- package/src/lib/components/ui/table.tsx +96 -64
- package/src/lib/components/ui/tabs.tsx +56 -38
- package/src/lib/components/ui/textarea.tsx +14 -14
- package/src/lib/components/ui/toggle-group.tsx +73 -0
- package/src/lib/components/ui/toggle.tsx +45 -0
- package/src/lib/components/ui/tooltip.tsx +45 -37
- package/src/lib/framework/page/list-page.tsx +1 -1
- package/vite/vite-plugin-vendure-dashboard.ts +1 -1
|
@@ -1,447 +1,208 @@
|
|
|
1
|
-
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import {
|
|
3
|
+
ChevronDownIcon,
|
|
4
|
+
ChevronLeftIcon,
|
|
5
|
+
ChevronRightIcon,
|
|
6
|
+
} from "lucide-react"
|
|
7
|
+
import { DayButton, DayPicker, getDefaultClassNames } from "react-day-picker"
|
|
2
8
|
|
|
3
|
-
|
|
4
|
-
|
|
9
|
+
import { cn } from "@/vdb/lib/utils"
|
|
10
|
+
import { Button, buttonVariants } from "@/vdb/components/ui/button"
|
|
5
11
|
|
|
6
|
-
import { Button, buttonVariants } from '@/vdb/components/ui/button.js';
|
|
7
|
-
import { cn } from '@/vdb/lib/utils.js';
|
|
8
|
-
import { differenceInCalendarDays } from 'date-fns';
|
|
9
|
-
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
10
|
-
import * as React from 'react';
|
|
11
|
-
import { DayPicker, labelNext, labelPrevious, useDayPicker, type DayPickerProps } from 'react-day-picker';
|
|
12
|
-
|
|
13
|
-
export type CalendarProps = DayPickerProps & {
|
|
14
|
-
/**
|
|
15
|
-
* In the year view, the number of years to display at once.
|
|
16
|
-
* @default 12
|
|
17
|
-
*/
|
|
18
|
-
yearRange?: number;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Wether to show the year switcher in the caption.
|
|
22
|
-
* @default true
|
|
23
|
-
*/
|
|
24
|
-
showYearSwitcher?: boolean;
|
|
25
|
-
|
|
26
|
-
monthsClassName?: string;
|
|
27
|
-
monthCaptionClassName?: string;
|
|
28
|
-
weekdaysClassName?: string;
|
|
29
|
-
weekdayClassName?: string;
|
|
30
|
-
monthClassName?: string;
|
|
31
|
-
captionClassName?: string;
|
|
32
|
-
captionLabelClassName?: string;
|
|
33
|
-
buttonNextClassName?: string;
|
|
34
|
-
buttonPreviousClassName?: string;
|
|
35
|
-
navClassName?: string;
|
|
36
|
-
monthGridClassName?: string;
|
|
37
|
-
weekClassName?: string;
|
|
38
|
-
dayClassName?: string;
|
|
39
|
-
dayButtonClassName?: string;
|
|
40
|
-
rangeStartClassName?: string;
|
|
41
|
-
rangeEndClassName?: string;
|
|
42
|
-
selectedClassName?: string;
|
|
43
|
-
todayClassName?: string;
|
|
44
|
-
outsideClassName?: string;
|
|
45
|
-
disabledClassName?: string;
|
|
46
|
-
rangeMiddleClassName?: string;
|
|
47
|
-
hiddenClassName?: string;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
type NavView = 'days' | 'years';
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* A custom calendar component built on top of react-day-picker.
|
|
54
|
-
* @param props The props for the calendar.
|
|
55
|
-
* @default yearRange 12
|
|
56
|
-
* @returns
|
|
57
|
-
*/
|
|
58
12
|
function Calendar({
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
to: number;
|
|
70
|
-
}>(
|
|
71
|
-
React.useMemo(() => {
|
|
72
|
-
const currentYear = new Date().getFullYear();
|
|
73
|
-
return {
|
|
74
|
-
from: currentYear - Math.floor(yearRange / 2 - 1),
|
|
75
|
-
to: currentYear + Math.ceil(yearRange / 2),
|
|
76
|
-
};
|
|
77
|
-
}, [yearRange]),
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
const { onNextClick, onPrevClick, startMonth, endMonth } = props;
|
|
81
|
-
|
|
82
|
-
const columnsDisplayed = navView === 'years' ? 1 : numberOfMonths;
|
|
83
|
-
|
|
84
|
-
const _monthsClassName = cn('relative flex', props.monthsClassName);
|
|
85
|
-
const _monthCaptionClassName = cn(
|
|
86
|
-
'relative mx-10 flex h-7 items-center justify-center',
|
|
87
|
-
props.monthCaptionClassName,
|
|
88
|
-
);
|
|
89
|
-
const _weekdaysClassName = cn('flex flex-row', props.weekdaysClassName);
|
|
90
|
-
const _weekdayClassName = cn('w-8 text-sm font-normal text-muted-foreground', props.weekdayClassName);
|
|
91
|
-
const _monthClassName = cn('w-full', props.monthClassName);
|
|
92
|
-
const _captionClassName = cn('relative flex items-center justify-center pt-1', props.captionClassName);
|
|
93
|
-
const _captionLabelClassName = cn('truncate text-sm font-medium', props.captionLabelClassName);
|
|
94
|
-
const buttonNavClassName = buttonVariants({
|
|
95
|
-
variant: 'outline',
|
|
96
|
-
className: 'absolute h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
|
|
97
|
-
});
|
|
98
|
-
const _buttonNextClassName = cn(buttonNavClassName, 'right-0', props.buttonNextClassName);
|
|
99
|
-
const _buttonPreviousClassName = cn(buttonNavClassName, 'left-0', props.buttonPreviousClassName);
|
|
100
|
-
const _navClassName = cn('flex items-start', props.navClassName);
|
|
101
|
-
const _monthGridClassName = cn('mx-auto mt-4', props.monthGridClassName);
|
|
102
|
-
const _weekClassName = cn('mt-2 flex w-max items-start', props.weekClassName);
|
|
103
|
-
const _dayClassName = cn(
|
|
104
|
-
'flex size-8 flex-1 items-center justify-center p-0 text-sm',
|
|
105
|
-
props.dayClassName,
|
|
106
|
-
);
|
|
107
|
-
const _dayButtonClassName = cn(
|
|
108
|
-
buttonVariants({ variant: 'ghost' }),
|
|
109
|
-
'size-8 rounded-md p-0 font-normal transition-none aria-selected:opacity-100',
|
|
110
|
-
props.dayButtonClassName,
|
|
111
|
-
);
|
|
112
|
-
const buttonRangeClassName =
|
|
113
|
-
'bg-accent [&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground';
|
|
114
|
-
const _rangeStartClassName = cn(
|
|
115
|
-
buttonRangeClassName,
|
|
116
|
-
'day-range-start rounded-s-md',
|
|
117
|
-
props.rangeStartClassName,
|
|
118
|
-
);
|
|
119
|
-
const _rangeEndClassName = cn(
|
|
120
|
-
buttonRangeClassName,
|
|
121
|
-
'day-range-end rounded-e-md',
|
|
122
|
-
props.rangeEndClassName,
|
|
123
|
-
);
|
|
124
|
-
const _rangeMiddleClassName = cn(
|
|
125
|
-
'bg-accent !text-foreground [&>button]:bg-transparent [&>button]:!text-foreground [&>button]:hover:bg-transparent [&>button]:hover:!text-foreground',
|
|
126
|
-
props.rangeMiddleClassName,
|
|
127
|
-
);
|
|
128
|
-
const _selectedClassName = cn(
|
|
129
|
-
'[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground',
|
|
130
|
-
props.selectedClassName,
|
|
131
|
-
);
|
|
132
|
-
const _todayClassName = cn(
|
|
133
|
-
'[&>button]:bg-accent [&>button]:text-accent-foreground',
|
|
134
|
-
props.todayClassName,
|
|
135
|
-
);
|
|
136
|
-
const _outsideClassName = cn(
|
|
137
|
-
'day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30',
|
|
138
|
-
props.outsideClassName,
|
|
139
|
-
);
|
|
140
|
-
const _disabledClassName = cn('text-muted-foreground opacity-50', props.disabledClassName);
|
|
141
|
-
const _hiddenClassName = cn('invisible flex-1', props.hiddenClassName);
|
|
142
|
-
|
|
143
|
-
return (
|
|
144
|
-
<DayPicker
|
|
145
|
-
showOutsideDays={showOutsideDays}
|
|
146
|
-
className={cn('p-3', className)}
|
|
147
|
-
style={{
|
|
148
|
-
width: 248.8 * (columnsDisplayed ?? 1) + 'px',
|
|
149
|
-
}}
|
|
150
|
-
classNames={{
|
|
151
|
-
months: _monthsClassName,
|
|
152
|
-
month_caption: _monthCaptionClassName,
|
|
153
|
-
weekdays: _weekdaysClassName,
|
|
154
|
-
weekday: _weekdayClassName,
|
|
155
|
-
month: _monthClassName,
|
|
156
|
-
caption: _captionClassName,
|
|
157
|
-
caption_label: _captionLabelClassName,
|
|
158
|
-
button_next: _buttonNextClassName,
|
|
159
|
-
button_previous: _buttonPreviousClassName,
|
|
160
|
-
nav: _navClassName,
|
|
161
|
-
month_grid: _monthGridClassName,
|
|
162
|
-
week: _weekClassName,
|
|
163
|
-
day: _dayClassName,
|
|
164
|
-
day_button: _dayButtonClassName,
|
|
165
|
-
range_start: _rangeStartClassName,
|
|
166
|
-
range_middle: _rangeMiddleClassName,
|
|
167
|
-
range_end: _rangeEndClassName,
|
|
168
|
-
selected: _selectedClassName,
|
|
169
|
-
today: _todayClassName,
|
|
170
|
-
outside: _outsideClassName,
|
|
171
|
-
disabled: _disabledClassName,
|
|
172
|
-
hidden: _hiddenClassName,
|
|
173
|
-
}}
|
|
174
|
-
components={{
|
|
175
|
-
Chevron: ({ orientation }) => {
|
|
176
|
-
const Icon = orientation === 'left' ? ChevronLeft : ChevronRight;
|
|
177
|
-
return <Icon className="h-4 w-4" />;
|
|
178
|
-
},
|
|
179
|
-
Nav: ({ className }) => (
|
|
180
|
-
<Nav
|
|
181
|
-
className={className}
|
|
182
|
-
displayYears={displayYears}
|
|
183
|
-
navView={navView}
|
|
184
|
-
setDisplayYears={setDisplayYears}
|
|
185
|
-
startMonth={startMonth}
|
|
186
|
-
endMonth={endMonth}
|
|
187
|
-
onPrevClick={onPrevClick}
|
|
188
|
-
/>
|
|
189
|
-
),
|
|
190
|
-
CaptionLabel: props => (
|
|
191
|
-
<CaptionLabel
|
|
192
|
-
showYearSwitcher={showYearSwitcher}
|
|
193
|
-
navView={navView}
|
|
194
|
-
setNavView={setNavView}
|
|
195
|
-
displayYears={displayYears}
|
|
196
|
-
{...props}
|
|
197
|
-
/>
|
|
198
|
-
),
|
|
199
|
-
MonthGrid: ({ className, children, ...props }) => (
|
|
200
|
-
<MonthGrid
|
|
201
|
-
children={children}
|
|
202
|
-
className={className}
|
|
203
|
-
displayYears={displayYears}
|
|
204
|
-
startMonth={startMonth}
|
|
205
|
-
endMonth={endMonth}
|
|
206
|
-
navView={navView}
|
|
207
|
-
setNavView={setNavView}
|
|
208
|
-
{...props}
|
|
209
|
-
/>
|
|
210
|
-
),
|
|
211
|
-
}}
|
|
212
|
-
numberOfMonths={columnsDisplayed}
|
|
213
|
-
{...props}
|
|
214
|
-
/>
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
Calendar.displayName = 'Calendar';
|
|
219
|
-
|
|
220
|
-
function Nav({
|
|
221
|
-
className,
|
|
222
|
-
navView,
|
|
223
|
-
startMonth,
|
|
224
|
-
endMonth,
|
|
225
|
-
displayYears,
|
|
226
|
-
setDisplayYears,
|
|
227
|
-
onPrevClick,
|
|
228
|
-
onNextClick,
|
|
229
|
-
}: {
|
|
230
|
-
className?: string;
|
|
231
|
-
navView: NavView;
|
|
232
|
-
startMonth?: Date;
|
|
233
|
-
endMonth?: Date;
|
|
234
|
-
displayYears: { from: number; to: number };
|
|
235
|
-
setDisplayYears: React.Dispatch<React.SetStateAction<{ from: number; to: number }>>;
|
|
236
|
-
onPrevClick?: (date: Date) => void;
|
|
237
|
-
onNextClick?: (date: Date) => void;
|
|
13
|
+
className,
|
|
14
|
+
classNames,
|
|
15
|
+
showOutsideDays = true,
|
|
16
|
+
captionLayout = "label",
|
|
17
|
+
buttonVariant = "ghost",
|
|
18
|
+
formatters,
|
|
19
|
+
components,
|
|
20
|
+
...props
|
|
21
|
+
}: React.ComponentProps<typeof DayPicker> & {
|
|
22
|
+
buttonVariant?: React.ComponentProps<typeof Button>["variant"]
|
|
238
23
|
}) {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
24
|
+
const defaultClassNames = getDefaultClassNames()
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<DayPicker
|
|
28
|
+
showOutsideDays={showOutsideDays}
|
|
29
|
+
className={cn(
|
|
30
|
+
"bg-background group/calendar p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
|
|
31
|
+
String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
|
|
32
|
+
String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
|
|
33
|
+
className
|
|
34
|
+
)}
|
|
35
|
+
captionLayout={captionLayout}
|
|
36
|
+
formatters={{
|
|
37
|
+
formatMonthDropdown: (date) =>
|
|
38
|
+
date.toLocaleString("default", { month: "short" }),
|
|
39
|
+
...formatters,
|
|
40
|
+
}}
|
|
41
|
+
classNames={{
|
|
42
|
+
root: cn("w-fit", defaultClassNames.root),
|
|
43
|
+
months: cn(
|
|
44
|
+
"flex gap-4 flex-col md:flex-row relative",
|
|
45
|
+
defaultClassNames.months
|
|
46
|
+
),
|
|
47
|
+
month: cn("flex flex-col w-full gap-4", defaultClassNames.month),
|
|
48
|
+
nav: cn(
|
|
49
|
+
"flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between",
|
|
50
|
+
defaultClassNames.nav
|
|
51
|
+
),
|
|
52
|
+
button_previous: cn(
|
|
53
|
+
buttonVariants({ variant: buttonVariant }),
|
|
54
|
+
"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
|
|
55
|
+
defaultClassNames.button_previous
|
|
56
|
+
),
|
|
57
|
+
button_next: cn(
|
|
58
|
+
buttonVariants({ variant: buttonVariant }),
|
|
59
|
+
"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none",
|
|
60
|
+
defaultClassNames.button_next
|
|
61
|
+
),
|
|
62
|
+
month_caption: cn(
|
|
63
|
+
"flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)",
|
|
64
|
+
defaultClassNames.month_caption
|
|
65
|
+
),
|
|
66
|
+
dropdowns: cn(
|
|
67
|
+
"w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5",
|
|
68
|
+
defaultClassNames.dropdowns
|
|
69
|
+
),
|
|
70
|
+
dropdown_root: cn(
|
|
71
|
+
"relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md",
|
|
72
|
+
defaultClassNames.dropdown_root
|
|
73
|
+
),
|
|
74
|
+
dropdown: cn("absolute inset-0 opacity-0", defaultClassNames.dropdown),
|
|
75
|
+
caption_label: cn(
|
|
76
|
+
"select-none font-medium",
|
|
77
|
+
captionLayout === "label"
|
|
78
|
+
? "text-sm"
|
|
79
|
+
: "rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5",
|
|
80
|
+
defaultClassNames.caption_label
|
|
81
|
+
),
|
|
82
|
+
table: "w-full border-collapse",
|
|
83
|
+
weekdays: cn("flex", defaultClassNames.weekdays),
|
|
84
|
+
weekday: cn(
|
|
85
|
+
"text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none",
|
|
86
|
+
defaultClassNames.weekday
|
|
87
|
+
),
|
|
88
|
+
week: cn("flex w-full mt-2", defaultClassNames.week),
|
|
89
|
+
week_number_header: cn(
|
|
90
|
+
"select-none w-(--cell-size)",
|
|
91
|
+
defaultClassNames.week_number_header
|
|
92
|
+
),
|
|
93
|
+
week_number: cn(
|
|
94
|
+
"text-[0.8rem] select-none text-muted-foreground",
|
|
95
|
+
defaultClassNames.week_number
|
|
96
|
+
),
|
|
97
|
+
day: cn(
|
|
98
|
+
"relative w-full h-full p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
|
|
99
|
+
defaultClassNames.day
|
|
100
|
+
),
|
|
101
|
+
range_start: cn(
|
|
102
|
+
"rounded-l-md bg-accent",
|
|
103
|
+
defaultClassNames.range_start
|
|
104
|
+
),
|
|
105
|
+
range_middle: cn("rounded-none", defaultClassNames.range_middle),
|
|
106
|
+
range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
|
|
107
|
+
today: cn(
|
|
108
|
+
"bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none",
|
|
109
|
+
defaultClassNames.today
|
|
110
|
+
),
|
|
111
|
+
outside: cn(
|
|
112
|
+
"text-muted-foreground aria-selected:text-muted-foreground",
|
|
113
|
+
defaultClassNames.outside
|
|
114
|
+
),
|
|
115
|
+
disabled: cn(
|
|
116
|
+
"text-muted-foreground opacity-50",
|
|
117
|
+
defaultClassNames.disabled
|
|
118
|
+
),
|
|
119
|
+
hidden: cn("invisible", defaultClassNames.hidden),
|
|
120
|
+
...classNames,
|
|
121
|
+
}}
|
|
122
|
+
components={{
|
|
123
|
+
Root: ({ className, rootRef, ...props }) => {
|
|
124
|
+
return (
|
|
125
|
+
<div
|
|
126
|
+
data-slot="calendar"
|
|
127
|
+
ref={rootRef}
|
|
128
|
+
className={cn(className)}
|
|
129
|
+
{...props}
|
|
130
|
+
/>
|
|
131
|
+
)
|
|
132
|
+
},
|
|
133
|
+
Chevron: ({ className, orientation, ...props }) => {
|
|
134
|
+
if (orientation === "left") {
|
|
243
135
|
return (
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
);
|
|
248
|
-
}
|
|
249
|
-
return !previousMonth;
|
|
250
|
-
})();
|
|
136
|
+
<ChevronLeftIcon className={cn("size-4", className)} {...props} />
|
|
137
|
+
)
|
|
138
|
+
}
|
|
251
139
|
|
|
252
|
-
|
|
253
|
-
if (navView === 'years') {
|
|
140
|
+
if (orientation === "right") {
|
|
254
141
|
return (
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
(endMonth && differenceInCalendarDays(new Date(displayYears.to + 1, 0, 1), endMonth) > 0)
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
return !nextMonth;
|
|
261
|
-
})();
|
|
262
|
-
|
|
263
|
-
const handlePreviousClick = React.useCallback(() => {
|
|
264
|
-
if (!previousMonth) return;
|
|
265
|
-
if (navView === 'years') {
|
|
266
|
-
setDisplayYears(prev => ({
|
|
267
|
-
from: prev.from - (prev.to - prev.from + 1),
|
|
268
|
-
to: prev.to - (prev.to - prev.from + 1),
|
|
269
|
-
}));
|
|
270
|
-
onPrevClick?.(new Date(displayYears.from - (displayYears.to - displayYears.from), 0, 1));
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
goToMonth(previousMonth);
|
|
274
|
-
onPrevClick?.(previousMonth);
|
|
275
|
-
}, [previousMonth, goToMonth]);
|
|
276
|
-
|
|
277
|
-
const handleNextClick = React.useCallback(() => {
|
|
278
|
-
if (!nextMonth) return;
|
|
279
|
-
if (navView === 'years') {
|
|
280
|
-
setDisplayYears(prev => ({
|
|
281
|
-
from: prev.from + (prev.to - prev.from + 1),
|
|
282
|
-
to: prev.to + (prev.to - prev.from + 1),
|
|
283
|
-
}));
|
|
284
|
-
onNextClick?.(new Date(displayYears.from + (displayYears.to - displayYears.from), 0, 1));
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
goToMonth(nextMonth);
|
|
288
|
-
onNextClick?.(nextMonth);
|
|
289
|
-
}, [goToMonth, nextMonth]);
|
|
290
|
-
return (
|
|
291
|
-
<nav className={cn('flex items-center', className)}>
|
|
292
|
-
<Button
|
|
293
|
-
variant="outline"
|
|
294
|
-
className="absolute left-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100"
|
|
295
|
-
type="button"
|
|
296
|
-
tabIndex={isPreviousDisabled ? undefined : -1}
|
|
297
|
-
disabled={isPreviousDisabled}
|
|
298
|
-
aria-label={
|
|
299
|
-
navView === 'years'
|
|
300
|
-
? `Go to the previous ${displayYears.to - displayYears.from + 1} years`
|
|
301
|
-
: labelPrevious(previousMonth)
|
|
302
|
-
}
|
|
303
|
-
onClick={handlePreviousClick}
|
|
304
|
-
>
|
|
305
|
-
<ChevronLeft className="h-4 w-4" />
|
|
306
|
-
</Button>
|
|
307
|
-
|
|
308
|
-
<Button
|
|
309
|
-
variant="outline"
|
|
310
|
-
className="absolute right-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100"
|
|
311
|
-
type="button"
|
|
312
|
-
tabIndex={isNextDisabled ? undefined : -1}
|
|
313
|
-
disabled={isNextDisabled}
|
|
314
|
-
aria-label={
|
|
315
|
-
navView === 'years'
|
|
316
|
-
? `Go to the next ${displayYears.to - displayYears.from + 1} years`
|
|
317
|
-
: labelNext(nextMonth)
|
|
318
|
-
}
|
|
319
|
-
onClick={handleNextClick}
|
|
320
|
-
>
|
|
321
|
-
<ChevronRight className="h-4 w-4" />
|
|
322
|
-
</Button>
|
|
323
|
-
</nav>
|
|
324
|
-
);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
function CaptionLabel({
|
|
328
|
-
children,
|
|
329
|
-
showYearSwitcher,
|
|
330
|
-
navView,
|
|
331
|
-
setNavView,
|
|
332
|
-
displayYears,
|
|
333
|
-
...props
|
|
334
|
-
}: {
|
|
335
|
-
showYearSwitcher?: boolean;
|
|
336
|
-
navView: NavView;
|
|
337
|
-
setNavView: React.Dispatch<React.SetStateAction<NavView>>;
|
|
338
|
-
displayYears: { from: number; to: number };
|
|
339
|
-
} & React.HTMLAttributes<HTMLSpanElement>) {
|
|
340
|
-
if (!showYearSwitcher) return <span {...props}>{children}</span>;
|
|
341
|
-
return (
|
|
342
|
-
<Button
|
|
343
|
-
className="h-7 w-full truncate text-sm font-medium"
|
|
344
|
-
variant="ghost"
|
|
345
|
-
size="sm"
|
|
346
|
-
onClick={() => setNavView(prev => (prev === 'days' ? 'years' : 'days'))}
|
|
347
|
-
>
|
|
348
|
-
{navView === 'days' ? children : displayYears.from + ' - ' + displayYears.to}
|
|
349
|
-
</Button>
|
|
350
|
-
);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
function MonthGrid({
|
|
354
|
-
className,
|
|
355
|
-
children,
|
|
356
|
-
displayYears,
|
|
357
|
-
startMonth,
|
|
358
|
-
endMonth,
|
|
359
|
-
navView,
|
|
360
|
-
setNavView,
|
|
361
|
-
...props
|
|
362
|
-
}: {
|
|
363
|
-
className?: string;
|
|
364
|
-
children: React.ReactNode;
|
|
365
|
-
displayYears: { from: number; to: number };
|
|
366
|
-
startMonth?: Date;
|
|
367
|
-
endMonth?: Date;
|
|
368
|
-
navView: NavView;
|
|
369
|
-
setNavView: React.Dispatch<React.SetStateAction<NavView>>;
|
|
370
|
-
} & React.TableHTMLAttributes<HTMLTableElement>) {
|
|
371
|
-
if (navView === 'years') {
|
|
372
|
-
return (
|
|
373
|
-
<YearGrid
|
|
374
|
-
displayYears={displayYears}
|
|
375
|
-
startMonth={startMonth}
|
|
376
|
-
endMonth={endMonth}
|
|
377
|
-
setNavView={setNavView}
|
|
378
|
-
navView={navView}
|
|
379
|
-
className={className}
|
|
142
|
+
<ChevronRightIcon
|
|
143
|
+
className={cn("size-4", className)}
|
|
380
144
|
{...props}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
{
|
|
387
|
-
|
|
388
|
-
|
|
145
|
+
/>
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<ChevronDownIcon className={cn("size-4", className)} {...props} />
|
|
151
|
+
)
|
|
152
|
+
},
|
|
153
|
+
DayButton: CalendarDayButton,
|
|
154
|
+
WeekNumber: ({ children, ...props }) => {
|
|
155
|
+
return (
|
|
156
|
+
<td {...props}>
|
|
157
|
+
<div className="flex size-(--cell-size) items-center justify-center text-center">
|
|
158
|
+
{children}
|
|
159
|
+
</div>
|
|
160
|
+
</td>
|
|
161
|
+
)
|
|
162
|
+
},
|
|
163
|
+
...components,
|
|
164
|
+
}}
|
|
165
|
+
{...props}
|
|
166
|
+
/>
|
|
167
|
+
)
|
|
389
168
|
}
|
|
390
169
|
|
|
391
|
-
function
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
variant="ghost"
|
|
428
|
-
onClick={() => {
|
|
429
|
-
setNavView('days');
|
|
430
|
-
goToMonth(
|
|
431
|
-
new Date(
|
|
432
|
-
displayYears.from + i,
|
|
433
|
-
(selected as Date | undefined)?.getMonth() ?? 0,
|
|
434
|
-
),
|
|
435
|
-
);
|
|
436
|
-
}}
|
|
437
|
-
disabled={navView === 'years' ? isDisabled : undefined}
|
|
438
|
-
>
|
|
439
|
-
{displayYears.from + i}
|
|
440
|
-
</Button>
|
|
441
|
-
);
|
|
442
|
-
})}
|
|
443
|
-
</div>
|
|
444
|
-
);
|
|
170
|
+
function CalendarDayButton({
|
|
171
|
+
className,
|
|
172
|
+
day,
|
|
173
|
+
modifiers,
|
|
174
|
+
...props
|
|
175
|
+
}: React.ComponentProps<typeof DayButton>) {
|
|
176
|
+
const defaultClassNames = getDefaultClassNames()
|
|
177
|
+
|
|
178
|
+
const ref = React.useRef<HTMLButtonElement>(null)
|
|
179
|
+
React.useEffect(() => {
|
|
180
|
+
if (modifiers.focused) ref.current?.focus()
|
|
181
|
+
}, [modifiers.focused])
|
|
182
|
+
|
|
183
|
+
return (
|
|
184
|
+
<Button
|
|
185
|
+
ref={ref}
|
|
186
|
+
variant="ghost"
|
|
187
|
+
size="icon"
|
|
188
|
+
data-day={day.date.toLocaleDateString()}
|
|
189
|
+
data-selected-single={
|
|
190
|
+
modifiers.selected &&
|
|
191
|
+
!modifiers.range_start &&
|
|
192
|
+
!modifiers.range_end &&
|
|
193
|
+
!modifiers.range_middle
|
|
194
|
+
}
|
|
195
|
+
data-range-start={modifiers.range_start}
|
|
196
|
+
data-range-end={modifiers.range_end}
|
|
197
|
+
data-range-middle={modifiers.range_middle}
|
|
198
|
+
className={cn(
|
|
199
|
+
"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-accent-foreground flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md [&>span]:text-xs [&>span]:opacity-70",
|
|
200
|
+
defaultClassNames.day,
|
|
201
|
+
className
|
|
202
|
+
)}
|
|
203
|
+
{...props}
|
|
204
|
+
/>
|
|
205
|
+
)
|
|
445
206
|
}
|
|
446
207
|
|
|
447
|
-
export { Calendar }
|
|
208
|
+
export { Calendar, CalendarDayButton }
|