@dxos/react-ui-calendar 0.9.0 → 0.9.1-main.c7dcc2e112
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/lib/browser/index.mjs +582 -107
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +582 -107
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/Calendar/Calendar.d.ts +25 -35
- package/dist/types/src/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/types/src/components/Calendar/Calendar.stories.d.ts +2 -0
- package/dist/types/src/components/Calendar/Calendar.stories.d.ts.map +1 -1
- package/dist/types/src/components/Calendar/Week.d.ts +30 -0
- package/dist/types/src/components/Calendar/Week.d.ts.map +1 -0
- package/dist/types/src/components/Calendar/Weekdays.d.ts +18 -0
- package/dist/types/src/components/Calendar/Weekdays.d.ts.map +1 -0
- package/dist/types/src/components/Calendar/context.d.ts +40 -0
- package/dist/types/src/components/Calendar/context.d.ts.map +1 -0
- package/dist/types/src/components/Calendar/util.d.ts +36 -0
- package/dist/types/src/components/Calendar/util.d.ts.map +1 -1
- package/dist/types/src/components/Calendar/util.test.d.ts +2 -0
- package/dist/types/src/components/Calendar/util.test.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +12 -12
- package/src/components/Calendar/Calendar.stories.tsx +43 -3
- package/src/components/Calendar/Calendar.tsx +117 -96
- package/src/components/Calendar/Week.tsx +488 -0
- package/src/components/Calendar/Weekdays.tsx +57 -0
- package/src/components/Calendar/context.ts +60 -0
- package/src/components/Calendar/util.test.ts +90 -0
- package/src/components/Calendar/util.ts +92 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-calendar",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.1-main.c7dcc2e112",
|
|
4
4
|
"description": "A calendar component.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
"react-resize-detector": "^11.0.1",
|
|
40
40
|
"react-virtualized": "^9.22.6",
|
|
41
41
|
"react-window": "^2.2.3",
|
|
42
|
-
"@dxos/async": "0.9.
|
|
43
|
-
"@dxos/invariant": "0.9.
|
|
44
|
-
"@dxos/
|
|
45
|
-
"@dxos/
|
|
46
|
-
"@dxos/util": "0.9.
|
|
42
|
+
"@dxos/async": "0.9.1-main.c7dcc2e112",
|
|
43
|
+
"@dxos/invariant": "0.9.1-main.c7dcc2e112",
|
|
44
|
+
"@dxos/log": "0.9.1-main.c7dcc2e112",
|
|
45
|
+
"@dxos/debug": "0.9.1-main.c7dcc2e112",
|
|
46
|
+
"@dxos/util": "0.9.1-main.c7dcc2e112"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/react": "~19.2.7",
|
|
@@ -53,17 +53,17 @@
|
|
|
53
53
|
"react": "~19.2.3",
|
|
54
54
|
"react-dom": "~19.2.3",
|
|
55
55
|
"vite": "^8.0.16",
|
|
56
|
-
"@dxos/random": "0.9.
|
|
57
|
-
"@dxos/react-ui": "0.9.
|
|
58
|
-
"@dxos/
|
|
59
|
-
"@dxos/
|
|
56
|
+
"@dxos/random": "0.9.1-main.c7dcc2e112",
|
|
57
|
+
"@dxos/react-ui": "0.9.1-main.c7dcc2e112",
|
|
58
|
+
"@dxos/storybook-utils": "0.9.1-main.c7dcc2e112",
|
|
59
|
+
"@dxos/ui-theme": "0.9.1-main.c7dcc2e112"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"effect": "3.21.3",
|
|
63
63
|
"react": "~19.2.3",
|
|
64
64
|
"react-dom": "~19.2.3",
|
|
65
|
-
"@dxos/react-ui": "0.9.
|
|
66
|
-
"@dxos/ui-theme": "0.9.
|
|
65
|
+
"@dxos/react-ui": "0.9.1-main.c7dcc2e112",
|
|
66
|
+
"@dxos/ui-theme": "0.9.1-main.c7dcc2e112"
|
|
67
67
|
},
|
|
68
68
|
"publishConfig": {
|
|
69
69
|
"access": "public"
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
-
import { format } from 'date-fns';
|
|
7
|
-
import React, { useState } from 'react';
|
|
6
|
+
import { addDays, addMinutes, format, startOfDay, startOfWeek } from 'date-fns';
|
|
7
|
+
import React, { useMemo, useRef, useState } from 'react';
|
|
8
8
|
|
|
9
9
|
import { Panel } from '@dxos/react-ui';
|
|
10
10
|
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
11
|
|
|
12
12
|
import { translations } from '#translations';
|
|
13
13
|
|
|
14
|
-
import { Calendar, type Range as DateRange } from './Calendar';
|
|
14
|
+
import { Calendar, type CalendarEvent, type Range as DateRange } from './Calendar';
|
|
15
15
|
|
|
16
16
|
const meta = {
|
|
17
17
|
title: 'ui/react-ui-calendar/Calendar',
|
|
@@ -68,3 +68,43 @@ export const Column: Story = {
|
|
|
68
68
|
</Calendar.Root>
|
|
69
69
|
),
|
|
70
70
|
};
|
|
71
|
+
|
|
72
|
+
export const Week: StoryObj<typeof Calendar.Week> = {
|
|
73
|
+
decorators: [withTheme(), withLayout({ layout: 'column', classNames: 'w-auto' })],
|
|
74
|
+
render: () => {
|
|
75
|
+
const idRef = useRef(100);
|
|
76
|
+
const initial = useMemo<CalendarEvent[]>(() => {
|
|
77
|
+
const weekStart = startOfWeek(new Date(), { weekStartsOn: 1 });
|
|
78
|
+
const at = (dayOffset: number, hour: number, minute = 0) =>
|
|
79
|
+
addMinutes(startOfDay(addDays(weekStart, dayOffset)), hour * 60 + minute);
|
|
80
|
+
return [
|
|
81
|
+
{ id: '1', title: 'Standup', start: at(1, 9, 0), end: at(1, 9, 30) },
|
|
82
|
+
{ id: '2', title: 'Design review', start: at(1, 9, 15), end: at(1, 10, 30) },
|
|
83
|
+
{ id: '3', title: 'Lunch', start: at(2, 12, 0), end: at(2, 13, 0) },
|
|
84
|
+
{ id: '4', title: '1:1', start: at(3, 14, 0), end: at(3, 15, 0) },
|
|
85
|
+
{ id: '5', title: 'Focus', start: at(3, 14, 30), end: at(3, 16, 0) },
|
|
86
|
+
{ id: '6', title: 'Planning', start: at(4, 10, 0), end: at(4, 11, 30) },
|
|
87
|
+
];
|
|
88
|
+
}, []);
|
|
89
|
+
const [events, setEvents] = useState<CalendarEvent[]>(initial);
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<Calendar.Root>
|
|
93
|
+
<Panel.Root>
|
|
94
|
+
<Panel.Toolbar asChild>
|
|
95
|
+
<Calendar.Toolbar />
|
|
96
|
+
</Panel.Toolbar>
|
|
97
|
+
<Calendar.Week
|
|
98
|
+
events={events}
|
|
99
|
+
onEventCreate={({ start, end }) =>
|
|
100
|
+
setEvents((current) => [...current, { id: `${idRef.current++}`, title: 'New event', start, end }])
|
|
101
|
+
}
|
|
102
|
+
onEventUpdate={({ id, start, end }) =>
|
|
103
|
+
setEvents((current) => current.map((event) => (event.id === id ? { ...event, start, end } : event)))
|
|
104
|
+
}
|
|
105
|
+
/>
|
|
106
|
+
</Panel.Root>
|
|
107
|
+
</Calendar.Root>
|
|
108
|
+
);
|
|
109
|
+
},
|
|
110
|
+
};
|
|
@@ -2,14 +2,11 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import { type Day, addDays, format, startOfDay, startOfWeek } from 'date-fns';
|
|
5
|
+
import { addDays, format, startOfDay } from 'date-fns';
|
|
7
6
|
import React, {
|
|
8
|
-
type Dispatch,
|
|
9
7
|
type KeyboardEvent as ReactKeyboardEvent,
|
|
10
8
|
type PointerEvent as ReactPointerEvent,
|
|
11
9
|
type PropsWithChildren,
|
|
12
|
-
type SetStateAction,
|
|
13
10
|
forwardRef,
|
|
14
11
|
useCallback,
|
|
15
12
|
useEffect,
|
|
@@ -28,10 +25,20 @@ import { mx } from '@dxos/ui-theme';
|
|
|
28
25
|
|
|
29
26
|
import { translationKey } from '#translations';
|
|
30
27
|
|
|
31
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
type CalendarContextValue,
|
|
30
|
+
type CalendarController,
|
|
31
|
+
CalendarContextProvider,
|
|
32
|
+
type CalendarScrollEvent,
|
|
33
|
+
type Range,
|
|
34
|
+
useCalendarContext,
|
|
35
|
+
} from './context';
|
|
36
|
+
import { getDate, getRowIndex, gridEpoch, isSameDay } from './util';
|
|
37
|
+
import { CalendarWeek, type CalendarEvent, type CalendarWeekProps } from './Week';
|
|
38
|
+
import { Weekdays } from './Weekdays';
|
|
32
39
|
|
|
33
40
|
const maxRows = 50 * 100;
|
|
34
|
-
const start =
|
|
41
|
+
const start = gridEpoch;
|
|
35
42
|
const size = 40;
|
|
36
43
|
const defaultWidth = 7 * size;
|
|
37
44
|
|
|
@@ -39,19 +46,17 @@ const defaultWidth = 7 * size;
|
|
|
39
46
|
const EDGE_SCROLL_ZONE = 32; // px
|
|
40
47
|
const EDGE_SCROLL_MAX_SPEED = 12; // px per frame
|
|
41
48
|
|
|
49
|
+
const DATE_CLASS_NAMES = {
|
|
50
|
+
current: 'ring-2 ring-primary-500',
|
|
51
|
+
today: 'border-2 border-amber-500 bg-amber-500/50 text-inverse-fg',
|
|
52
|
+
busy: 'border border-green-700',
|
|
53
|
+
starred: 'border-2 border-dashed border-amber-500',
|
|
54
|
+
};
|
|
55
|
+
|
|
42
56
|
//
|
|
43
57
|
// Range
|
|
44
58
|
//
|
|
45
59
|
|
|
46
|
-
/**
|
|
47
|
-
* Inclusive date range. `from <= to`. Both endpoints are anchored at the
|
|
48
|
-
* start of their day; callers should not rely on time-of-day precision.
|
|
49
|
-
*/
|
|
50
|
-
export type Range = {
|
|
51
|
-
from: Date;
|
|
52
|
-
to: Date;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
60
|
/** Normalize an ordered pair of dates into a Range (start-of-day, from <= to). */
|
|
56
61
|
const makeRange = (a: Date, b: Date): Range => {
|
|
57
62
|
const dayA = startOfDay(a);
|
|
@@ -81,40 +86,6 @@ const cellDate = (el: Element | null): Date | undefined => {
|
|
|
81
86
|
return undefined;
|
|
82
87
|
};
|
|
83
88
|
|
|
84
|
-
//
|
|
85
|
-
// Context
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
type CalendarEvent = {
|
|
89
|
-
type: 'scroll';
|
|
90
|
-
date: Date;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
type CalendarContextValue = {
|
|
94
|
-
weekStartsOn: Day;
|
|
95
|
-
event: Event<CalendarEvent>;
|
|
96
|
-
index: number | undefined;
|
|
97
|
-
setIndex: Dispatch<SetStateAction<number | undefined>>;
|
|
98
|
-
selected: Date | undefined;
|
|
99
|
-
setSelected: Dispatch<SetStateAction<Date | undefined>>;
|
|
100
|
-
/** Committed date range, set by the most recent drag or shift+arrow selection. */
|
|
101
|
-
range: Range | undefined;
|
|
102
|
-
setRange: Dispatch<SetStateAction<Range | undefined>>;
|
|
103
|
-
/** Live drag preview; non-undefined only while the user is dragging. */
|
|
104
|
-
pendingRange: Range | undefined;
|
|
105
|
-
setPendingRange: Dispatch<SetStateAction<Range | undefined>>;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const [CalendarContextProvider, useCalendarContext] = createContext<CalendarContextValue>('Calendar');
|
|
109
|
-
|
|
110
|
-
//
|
|
111
|
-
// Controller
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
type CalendarController = {
|
|
115
|
-
scrollTo: (date: Date) => void;
|
|
116
|
-
};
|
|
117
|
-
|
|
118
89
|
//
|
|
119
90
|
// Root
|
|
120
91
|
//
|
|
@@ -123,7 +94,7 @@ type CalendarRootProps = PropsWithChildren<Partial<Pick<CalendarContextValue, 'w
|
|
|
123
94
|
|
|
124
95
|
const CalendarRoot = forwardRef<CalendarController, CalendarRootProps>(
|
|
125
96
|
({ children, weekStartsOn = 1 }, forwardedRef) => {
|
|
126
|
-
const event = useMemo(() => new Event<
|
|
97
|
+
const event = useMemo(() => new Event<CalendarScrollEvent>(), []);
|
|
127
98
|
const [selected, setSelected] = useState<Date | undefined>();
|
|
128
99
|
const [index, setIndex] = useState<number | undefined>();
|
|
129
100
|
const [range, setRange] = useState<Range | undefined>();
|
|
@@ -135,6 +106,9 @@ const CalendarRoot = forwardRef<CalendarController, CalendarRootProps>(
|
|
|
135
106
|
scrollTo: (date: Date) => {
|
|
136
107
|
event.emit({ type: 'scroll', date });
|
|
137
108
|
},
|
|
109
|
+
select: (date: Date) => {
|
|
110
|
+
event.emit({ type: 'select', date });
|
|
111
|
+
},
|
|
138
112
|
}),
|
|
139
113
|
[event],
|
|
140
114
|
);
|
|
@@ -183,7 +157,6 @@ const CalendarToolbar = composable<HTMLDivElement, CalendarToolbarProps>(({ clas
|
|
|
183
157
|
classNames: ['shrink-0 grid! grid-cols-3 items-center bg-toolbar-surface', classNames],
|
|
184
158
|
})}
|
|
185
159
|
ref={forwardedRef}
|
|
186
|
-
style={{ width: defaultWidth }}
|
|
187
160
|
>
|
|
188
161
|
<div className='flex justify-start'>
|
|
189
162
|
<IconButton
|
|
@@ -209,16 +182,30 @@ CalendarToolbar.displayName = CALENDAR_TOOLBAR_NAME;
|
|
|
209
182
|
|
|
210
183
|
const CALENDAR_GRID_NAME = 'CalendarGrid';
|
|
211
184
|
|
|
185
|
+
/** Semantic kind of a {@link DateMarker}; the grid maps each kind to its own border treatment. */
|
|
186
|
+
export type DateMarkerTag = 'busy' | 'star';
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* A date (or inclusive date range) to mark on the grid. */
|
|
190
|
+
export type DateMarker = { startDate: Date; endDate?: Date; tag?: DateMarkerTag };
|
|
191
|
+
|
|
212
192
|
type CalendarGridProps = {
|
|
213
193
|
rows?: number;
|
|
214
|
-
/**
|
|
215
|
-
|
|
194
|
+
/**
|
|
195
|
+
* Dates to mark on the grid; each marked day gets a border keyed off its `tag` kind (defaults to `busy`).
|
|
196
|
+
*/
|
|
197
|
+
dates?: DateMarker[];
|
|
216
198
|
/**
|
|
217
199
|
* Date the grid scrolls into view on mount, and whenever this value changes.
|
|
218
200
|
* Defaults to today. Pass a stable (memoized) Date so the grid does not
|
|
219
201
|
* re-scroll on every render.
|
|
220
202
|
*/
|
|
221
203
|
initialDate?: Date;
|
|
204
|
+
/**
|
|
205
|
+
* Weeks of context kept above a date when scrolling it into view (on mount and via the controller's
|
|
206
|
+
* `scrollTo`), so the date sits below the top edge rather than pinned to it. Defaults to 2.
|
|
207
|
+
*/
|
|
208
|
+
scrollMargin?: number;
|
|
222
209
|
/** Fired when a user selects a single date (click or arrow key). */
|
|
223
210
|
onSelect?: (event: { date: Date }) => void;
|
|
224
211
|
/**
|
|
@@ -230,7 +217,10 @@ type CalendarGridProps = {
|
|
|
230
217
|
};
|
|
231
218
|
|
|
232
219
|
const CalendarGrid = composable<HTMLDivElement, CalendarGridProps>(
|
|
233
|
-
(
|
|
220
|
+
(
|
|
221
|
+
{ classNames, rows, dates = [], initialDate, scrollMargin = 2, onSelect, onSelectRange, ...props },
|
|
222
|
+
forwardedRef,
|
|
223
|
+
) => {
|
|
234
224
|
const { weekStartsOn, event, setIndex, selected, setSelected, range, setRange, pendingRange, setPendingRange } =
|
|
235
225
|
useCalendarContext(CALENDAR_GRID_NAME);
|
|
236
226
|
const { ref: containerRef, width = 0, height = 0 } = useResizeDetector();
|
|
@@ -239,36 +229,50 @@ const CalendarGrid = composable<HTMLDivElement, CalendarGridProps>(
|
|
|
239
229
|
const gridRef = useRef<HTMLDivElement>(null);
|
|
240
230
|
const today = useMemo(() => new Date(), []);
|
|
241
231
|
|
|
242
|
-
//
|
|
243
|
-
|
|
232
|
+
// Map each marked ISO day to its tag kind, expanding ranges. `star` wins over `busy` on the same
|
|
233
|
+
// day so a starred event keeps its highlighted border.
|
|
234
|
+
const dateMarkers = useMemo(() => {
|
|
235
|
+
const markers = new Map<string, DateMarkerTag>();
|
|
236
|
+
for (const { startDate, endDate, tag = 'busy' } of dates) {
|
|
237
|
+
const end = endDate ? startOfDay(endDate) : startOfDay(startDate);
|
|
238
|
+
for (let date = startOfDay(startDate); date <= end; date = addDays(date, 1)) {
|
|
239
|
+
const iso = date.toISOString();
|
|
240
|
+
if (markers.get(iso) !== 'star') {
|
|
241
|
+
markers.set(iso, tag);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
244
245
|
|
|
245
|
-
|
|
246
|
+
return markers;
|
|
247
|
+
}, [dates]);
|
|
248
|
+
|
|
249
|
+
const getMarker = useCallback(
|
|
250
|
+
(date: Date): { tag: DateMarkerTag } | undefined => {
|
|
251
|
+
const iso = startOfDay(date).toISOString();
|
|
252
|
+
const tag = dateMarkers.get(iso);
|
|
253
|
+
return tag ? { tag } : undefined;
|
|
254
|
+
},
|
|
255
|
+
[dateMarkers],
|
|
256
|
+
);
|
|
246
257
|
|
|
247
258
|
const [initialized, setInitialized] = useState(false);
|
|
248
259
|
useEffect(() => {
|
|
249
260
|
const index = getRowIndex(start, initialDate ?? today, weekStartsOn);
|
|
250
|
-
|
|
251
|
-
|
|
261
|
+
// Keep `scrollMargin` weeks of context above the target row.
|
|
262
|
+
listRef.current?.scrollToRow(Math.max(0, index - scrollMargin));
|
|
263
|
+
}, [initialized, start, today, initialDate, weekStartsOn, scrollMargin]);
|
|
252
264
|
|
|
253
265
|
useEffect(() => {
|
|
254
266
|
return event.on((event) => {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
break;
|
|
260
|
-
}
|
|
267
|
+
// `select` also sets the grid's selection (e.g. when the active event changes); the grid still
|
|
268
|
+
// owns selection — a user click sets it locally and isn't overwritten until the next `select`.
|
|
269
|
+
if (event.type === 'select') {
|
|
270
|
+
setSelected(event.date);
|
|
261
271
|
}
|
|
272
|
+
const index = getRowIndex(start, event.date, weekStartsOn);
|
|
273
|
+
listRef.current?.scrollToRow(Math.max(0, index - scrollMargin));
|
|
262
274
|
});
|
|
263
|
-
}, [event]);
|
|
264
|
-
|
|
265
|
-
const days = useMemo(() => {
|
|
266
|
-
const weekStart = startOfWeek(new Date(), { weekStartsOn });
|
|
267
|
-
return Array.from({ length: 7 }, (_, i) => {
|
|
268
|
-
const day = addDays(weekStart, i);
|
|
269
|
-
return format(day, 'EEE'); // Short day name (Mon, Tue, etc.)
|
|
270
|
-
});
|
|
271
|
-
}, []);
|
|
275
|
+
}, [event, start, weekStartsOn, scrollMargin, setSelected]);
|
|
272
276
|
|
|
273
277
|
//
|
|
274
278
|
// Selection refs.
|
|
@@ -575,33 +579,45 @@ const CalendarGrid = composable<HTMLDivElement, CalendarGridProps>(
|
|
|
575
579
|
<div className='grid grid-cols-7 bg-input-surface' style={{ gridTemplateColumns: `repeat(7, ${size}px)` }}>
|
|
576
580
|
{Array.from({ length: 7 }).map((_, i) => {
|
|
577
581
|
const date = getDate(start, index, i, weekStartsOn);
|
|
578
|
-
const
|
|
579
|
-
const
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
582
|
+
const marker = getMarker(date);
|
|
583
|
+
const isToday = isSameDay(date, today);
|
|
584
|
+
const isCurrent = isSameDay(date, selected);
|
|
585
|
+
const dateClassNames = isToday
|
|
586
|
+
? DATE_CLASS_NAMES.today
|
|
587
|
+
: marker?.tag === 'star'
|
|
588
|
+
? DATE_CLASS_NAMES.starred
|
|
589
|
+
: marker
|
|
590
|
+
? DATE_CLASS_NAMES.busy
|
|
585
591
|
: undefined;
|
|
586
592
|
|
|
593
|
+
const inRange = isInRange(date, activeRange);
|
|
594
|
+
|
|
587
595
|
return (
|
|
588
596
|
<div
|
|
589
597
|
key={i}
|
|
590
598
|
data-date={startOfDay(date).toISOString()}
|
|
591
|
-
className={mx(
|
|
592
|
-
'relative flex justify-center items-center cursor-pointer select-none',
|
|
593
|
-
getBgColor(date),
|
|
594
|
-
)}
|
|
599
|
+
className={mx('relative flex justify-center cursor-pointer select-none', getBgColor(date))}
|
|
595
600
|
onPointerDown={(ev) => handleDayPointerDown(date, ev)}
|
|
596
601
|
onPointerEnter={() => handleDayPointerEnter(date)}
|
|
597
602
|
onPointerUp={() => handleDayPointerUp(date)}
|
|
598
603
|
>
|
|
604
|
+
{/* Selection range */}
|
|
599
605
|
{inRange && <div className='absolute inset-0 bg-primary-500/20' />}
|
|
600
|
-
|
|
601
|
-
{!
|
|
606
|
+
{/* Month */}
|
|
607
|
+
{!dateClassNames && date.getDate() === 1 && (
|
|
602
608
|
<span className='absolute top-0 text-xs text-description'>{format(date, 'MMM')}</span>
|
|
603
609
|
)}
|
|
604
|
-
{
|
|
610
|
+
{/* Day + Marker */}
|
|
611
|
+
<div
|
|
612
|
+
className={mx(
|
|
613
|
+
'absolute inset-1 rounded-full flex justify-center items-center text-sm text-description',
|
|
614
|
+
dateClassNames,
|
|
615
|
+
)}
|
|
616
|
+
>
|
|
617
|
+
{date.getDate()}
|
|
618
|
+
</div>
|
|
619
|
+
{/* Current */}
|
|
620
|
+
{isCurrent && <div className={mx('absolute inset-0.5 rounded-full', DATE_CLASS_NAMES.current)} />}
|
|
605
621
|
</div>
|
|
606
622
|
);
|
|
607
623
|
})}
|
|
@@ -609,7 +625,7 @@ const CalendarGrid = composable<HTMLDivElement, CalendarGridProps>(
|
|
|
609
625
|
</div>
|
|
610
626
|
);
|
|
611
627
|
},
|
|
612
|
-
[activeRange, handleDayPointerDown, handleDayPointerEnter, handleDayPointerUp,
|
|
628
|
+
[activeRange, handleDayPointerDown, handleDayPointerEnter, handleDayPointerUp, getMarker, selected, weekStartsOn],
|
|
613
629
|
);
|
|
614
630
|
|
|
615
631
|
return (
|
|
@@ -630,12 +646,8 @@ const CalendarGrid = composable<HTMLDivElement, CalendarGridProps>(
|
|
|
630
646
|
onKeyDown={handleKeyDown}
|
|
631
647
|
>
|
|
632
648
|
{/* Day of week labels */}
|
|
633
|
-
<div
|
|
634
|
-
{
|
|
635
|
-
<div key={i} className='flex justify-center p-2 text-sm font-thin'>
|
|
636
|
-
{date}
|
|
637
|
-
</div>
|
|
638
|
-
))}
|
|
649
|
+
<div style={{ width: defaultWidth }}>
|
|
650
|
+
<Weekdays weekStartsOn={weekStartsOn} columnWidth={size} />
|
|
639
651
|
</div>
|
|
640
652
|
|
|
641
653
|
{/* Grid */}
|
|
@@ -669,6 +681,15 @@ export const Calendar = {
|
|
|
669
681
|
Root: CalendarRoot,
|
|
670
682
|
Toolbar: CalendarToolbar,
|
|
671
683
|
Grid: CalendarGrid,
|
|
684
|
+
Week: CalendarWeek,
|
|
672
685
|
};
|
|
673
686
|
|
|
674
|
-
export type {
|
|
687
|
+
export type {
|
|
688
|
+
CalendarController,
|
|
689
|
+
CalendarEvent,
|
|
690
|
+
CalendarGridProps,
|
|
691
|
+
CalendarRootProps,
|
|
692
|
+
CalendarToolbarProps,
|
|
693
|
+
CalendarWeekProps,
|
|
694
|
+
Range,
|
|
695
|
+
};
|