@super-calendar/dom 2.1.5 → 2.3.0
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/README.md +17 -0
- package/dist/index.d.mts +327 -12
- package/dist/index.d.ts +327 -12
- package/dist/index.js +1117 -286
- package/dist/index.mjs +1093 -289
- package/package.json +2 -2
- package/src/Agenda.tsx +77 -46
- package/src/Calendar.tsx +40 -4
- package/src/DateRangePicker.tsx +360 -0
- package/src/MonthList.tsx +43 -11
- package/src/MonthView.tsx +329 -130
- package/src/ResourceTimeline.tsx +431 -0
- package/src/TimeGrid.tsx +253 -148
- package/src/index.ts +37 -3
- package/src/slots.ts +87 -0
package/src/TimeGrid.tsx
CHANGED
|
@@ -16,7 +16,8 @@ import {
|
|
|
16
16
|
type CalendarMode,
|
|
17
17
|
cellRangeFromDrag,
|
|
18
18
|
closedHourBands,
|
|
19
|
-
eventAccessibilityLabel,
|
|
19
|
+
eventAccessibilityLabel as defaultEventAccessibilityLabel,
|
|
20
|
+
type EventAccessibilityLabeler,
|
|
20
21
|
eventChipLayout,
|
|
21
22
|
eventTimeLabel,
|
|
22
23
|
formatHour,
|
|
@@ -24,13 +25,40 @@ import {
|
|
|
24
25
|
getViewDays,
|
|
25
26
|
isAllDayEvent,
|
|
26
27
|
isSameCalendarDay,
|
|
28
|
+
isWeekend,
|
|
27
29
|
layoutDayEvents,
|
|
28
30
|
type TimeGridMode,
|
|
29
31
|
titleNumberOfLines,
|
|
32
|
+
type WeekdayFormat,
|
|
33
|
+
weekdayFormatToken,
|
|
30
34
|
type WeekStartsOn,
|
|
31
35
|
} from "@super-calendar/core";
|
|
36
|
+
import { createSlots, dataState, type ResolvedSlot, type SlotStyleProps } from "./slots";
|
|
32
37
|
import { type DomCalendarTheme, mergeDomTheme } from "./theme";
|
|
33
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Styleable parts of {@link TimeGrid}. Pass a class or inline style per slot via
|
|
41
|
+
* the `classNames` / `styles` props.
|
|
42
|
+
*/
|
|
43
|
+
export type TimeGridSlot =
|
|
44
|
+
| "header"
|
|
45
|
+
| "columnHeader"
|
|
46
|
+
| "columnHeaderWeekday"
|
|
47
|
+
| "columnHeaderDate"
|
|
48
|
+
| "allDayLane"
|
|
49
|
+
| "allDayLabel"
|
|
50
|
+
| "allDayColumn"
|
|
51
|
+
| "allDayEvent"
|
|
52
|
+
| "hourGutter"
|
|
53
|
+
| "hourLabel"
|
|
54
|
+
| "dayColumn"
|
|
55
|
+
| "gridLines"
|
|
56
|
+
| "businessHours"
|
|
57
|
+
| "event"
|
|
58
|
+
| "eventBox"
|
|
59
|
+
| "nowIndicator"
|
|
60
|
+
| "createGhost";
|
|
61
|
+
|
|
34
62
|
const HOURS = Array.from({ length: 24 }, (_, h) => h);
|
|
35
63
|
const GUTTER_WIDTH = 56;
|
|
36
64
|
const clamp = (v: number, lo: number, hi: number) => Math.min(hi, Math.max(lo, v));
|
|
@@ -59,7 +87,7 @@ export interface DomRenderEventArgs<T = unknown> {
|
|
|
59
87
|
export type DomRenderEvent<T = unknown> = ComponentType<DomRenderEventArgs<T>>;
|
|
60
88
|
|
|
61
89
|
/** Props for {@link TimeGrid}. */
|
|
62
|
-
export interface TimeGridProps<T = unknown> {
|
|
90
|
+
export interface TimeGridProps<T = unknown> extends SlotStyleProps<TimeGridSlot> {
|
|
63
91
|
/** Anchor date; the visible columns are derived from it and `mode`. */
|
|
64
92
|
date: Date;
|
|
65
93
|
/** Events to lay out on the grid. */
|
|
@@ -70,6 +98,8 @@ export interface TimeGridProps<T = unknown> {
|
|
|
70
98
|
numberOfDays?: number;
|
|
71
99
|
/** First day of the week. Sunday = 0 (default) ... Saturday = 6. */
|
|
72
100
|
weekStartsOn?: WeekStartsOn;
|
|
101
|
+
/** Column-header weekday label width: `narrow` ("M"), `short` ("Mon", default), or `long` ("Monday"). */
|
|
102
|
+
weekdayFormat?: WeekdayFormat;
|
|
73
103
|
/** Initial pixels per hour (default 48). */
|
|
74
104
|
hourHeight?: number;
|
|
75
105
|
/** Initial scroll position, in minutes from midnight (default 8:00). */
|
|
@@ -100,6 +130,13 @@ export interface TimeGridProps<T = unknown> {
|
|
|
100
130
|
height?: number | string;
|
|
101
131
|
/** Custom event renderer; falls back to the built-in event box. */
|
|
102
132
|
renderEvent?: DomRenderEvent<T>;
|
|
133
|
+
/**
|
|
134
|
+
* Override the screen-reader label for each event. Receives the event and a
|
|
135
|
+
* `{ mode, isAllDay, ampm }` context; return the full text to announce. Defaults
|
|
136
|
+
* to the title plus the time range (or "all day"), which the grid otherwise only
|
|
137
|
+
* conveys visually.
|
|
138
|
+
*/
|
|
139
|
+
eventAccessibilityLabel?: EventAccessibilityLabeler<T>;
|
|
103
140
|
/** Replace the hour-axis label. Receives the hour (0-23) and the `ampm` flag. */
|
|
104
141
|
hourComponent?: (hour: number, ampm: boolean) => ReactNode;
|
|
105
142
|
/** Tap an event. */
|
|
@@ -146,7 +183,8 @@ function DefaultDomEvent<T>({
|
|
|
146
183
|
boxHeight,
|
|
147
184
|
ampm = false,
|
|
148
185
|
theme,
|
|
149
|
-
|
|
186
|
+
boxProps,
|
|
187
|
+
}: DomRenderEventArgs<T> & { theme: DomCalendarTheme; boxProps?: ResolvedSlot }) {
|
|
150
188
|
const timeLabel = eventTimeLabel({
|
|
151
189
|
mode,
|
|
152
190
|
isAllDay,
|
|
@@ -168,19 +206,36 @@ function DefaultDomEvent<T>({
|
|
|
168
206
|
paddingYPx: DOM_BOX_PADDING_V,
|
|
169
207
|
});
|
|
170
208
|
const oneLine = titleNumberOfLines(mode, isAllDay) === 1;
|
|
209
|
+
// A chip reduced to a single title line (no time) centers it vertically, so a
|
|
210
|
+
// very short event reads balanced instead of hugging the top edge.
|
|
211
|
+
const centerLoneTitle = titleMaxLines === 1 && !showTime;
|
|
212
|
+
// Structural box metrics always apply; the card's look (colour, radius, type)
|
|
213
|
+
// is themed and yields to a `eventBox` class when one is supplied.
|
|
214
|
+
const boxBase: CSSProperties = {
|
|
215
|
+
height: "100%",
|
|
216
|
+
boxSizing: "border-box",
|
|
217
|
+
overflow: "hidden",
|
|
218
|
+
lineHeight: `${DOM_TITLE_LINE_HEIGHT}px`,
|
|
219
|
+
...(centerLoneTitle
|
|
220
|
+
? { display: "flex", flexDirection: "column", justifyContent: "center" }
|
|
221
|
+
: null),
|
|
222
|
+
};
|
|
223
|
+
const boxThemed: CSSProperties = {
|
|
224
|
+
padding: `${DOM_BOX_PADDING_V}px 6px`,
|
|
225
|
+
borderRadius: 6,
|
|
226
|
+
background: theme.eventBackground,
|
|
227
|
+
color: theme.eventText,
|
|
228
|
+
fontSize: 12,
|
|
229
|
+
};
|
|
171
230
|
return (
|
|
172
231
|
<div
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
color: theme.eventText,
|
|
181
|
-
fontSize: 12,
|
|
182
|
-
lineHeight: `${DOM_TITLE_LINE_HEIGHT}px`,
|
|
183
|
-
}}
|
|
232
|
+
className={boxProps?.className}
|
|
233
|
+
data-slot={boxProps?.["data-slot"]}
|
|
234
|
+
style={
|
|
235
|
+
boxProps?.className
|
|
236
|
+
? { ...boxBase, ...boxProps.style }
|
|
237
|
+
: { ...boxBase, ...boxThemed, ...boxProps?.style }
|
|
238
|
+
}
|
|
184
239
|
>
|
|
185
240
|
<div
|
|
186
241
|
style={{
|
|
@@ -226,6 +281,7 @@ export function TimeGrid<T = unknown>({
|
|
|
226
281
|
mode = "day",
|
|
227
282
|
numberOfDays = 1,
|
|
228
283
|
weekStartsOn = 0,
|
|
284
|
+
weekdayFormat = "short",
|
|
229
285
|
hourHeight: initialHourHeight = 48,
|
|
230
286
|
scrollOffsetMinutes = 8 * 60,
|
|
231
287
|
zoomable = true,
|
|
@@ -241,6 +297,7 @@ export function TimeGrid<T = unknown>({
|
|
|
241
297
|
theme: themeOverrides,
|
|
242
298
|
height = 600,
|
|
243
299
|
renderEvent,
|
|
300
|
+
eventAccessibilityLabel,
|
|
244
301
|
hourComponent,
|
|
245
302
|
onPressEvent,
|
|
246
303
|
onPressDateHeader,
|
|
@@ -250,8 +307,11 @@ export function TimeGrid<T = unknown>({
|
|
|
250
307
|
onDragEvent,
|
|
251
308
|
className,
|
|
252
309
|
style,
|
|
310
|
+
classNames,
|
|
311
|
+
styles,
|
|
253
312
|
}: TimeGridProps<T>): ReactElement {
|
|
254
313
|
const theme = useMemo(() => mergeDomTheme(themeOverrides), [themeOverrides]);
|
|
314
|
+
const slot = createSlots<TimeGridSlot>({ classNames, styles });
|
|
255
315
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
256
316
|
const dfns = locale ? { locale } : undefined;
|
|
257
317
|
const snapHours = dragStepMinutes / 60;
|
|
@@ -508,7 +568,12 @@ export function TimeGrid<T = unknown>({
|
|
|
508
568
|
}}
|
|
509
569
|
>
|
|
510
570
|
{/* Header */}
|
|
511
|
-
<div
|
|
571
|
+
<div
|
|
572
|
+
{...slot("header", {
|
|
573
|
+
base: { display: "flex" },
|
|
574
|
+
themed: { borderBottom: `1px solid ${theme.gridLine}` },
|
|
575
|
+
})}
|
|
576
|
+
>
|
|
512
577
|
<div style={{ width: GUTTER_WIDTH, flex: "none" }} />
|
|
513
578
|
{days.map((day) => {
|
|
514
579
|
const today = getIsToday(day);
|
|
@@ -519,34 +584,43 @@ export function TimeGrid<T = unknown>({
|
|
|
519
584
|
tabIndex={onPressDateHeader ? 0 : -1}
|
|
520
585
|
aria-hidden={onPressDateHeader ? undefined : true}
|
|
521
586
|
onClick={onPressDateHeader ? () => onPressDateHeader(day) : undefined}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
display: "flex",
|
|
531
|
-
flexDirection: "column",
|
|
532
|
-
alignItems: "center",
|
|
533
|
-
gap: 2,
|
|
534
|
-
}}
|
|
535
|
-
>
|
|
536
|
-
<span style={{ fontSize: 11, fontWeight: 600 }}>{format(day, "EEE", dfns)}</span>
|
|
537
|
-
<span
|
|
538
|
-
style={{
|
|
539
|
-
width: 28,
|
|
540
|
-
height: 28,
|
|
541
|
-
borderRadius: "50%",
|
|
587
|
+
{...dataState({ "data-today": today })}
|
|
588
|
+
{...slot("columnHeader", {
|
|
589
|
+
base: {
|
|
590
|
+
flex: 1,
|
|
591
|
+
border: "none",
|
|
592
|
+
background: "transparent",
|
|
593
|
+
font: "inherit",
|
|
594
|
+
cursor: onPressDateHeader ? "pointer" : "default",
|
|
542
595
|
display: "flex",
|
|
596
|
+
flexDirection: "column",
|
|
543
597
|
alignItems: "center",
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
598
|
+
gap: 2,
|
|
599
|
+
},
|
|
600
|
+
themed: { color: theme.textMuted, padding: "6px 0" },
|
|
601
|
+
})}
|
|
602
|
+
>
|
|
603
|
+
<span {...slot("columnHeaderWeekday", { themed: { fontSize: 11, fontWeight: 600 } })}>
|
|
604
|
+
{format(day, weekdayFormatToken(weekdayFormat), dfns)}
|
|
605
|
+
</span>
|
|
606
|
+
<span
|
|
607
|
+
{...dataState({ "data-today": today })}
|
|
608
|
+
{...slot("columnHeaderDate", {
|
|
609
|
+
base: {
|
|
610
|
+
width: 28,
|
|
611
|
+
height: 28,
|
|
612
|
+
borderRadius: "50%",
|
|
613
|
+
display: "flex",
|
|
614
|
+
alignItems: "center",
|
|
615
|
+
justifyContent: "center",
|
|
616
|
+
},
|
|
617
|
+
themed: {
|
|
618
|
+
fontSize: 15,
|
|
619
|
+
fontWeight: 600,
|
|
620
|
+
background: today ? theme.todayBackground : "transparent",
|
|
621
|
+
color: today ? theme.todayText : theme.text,
|
|
622
|
+
},
|
|
623
|
+
})}
|
|
550
624
|
>
|
|
551
625
|
{format(day, "d", dfns)}
|
|
552
626
|
</span>
|
|
@@ -557,16 +631,17 @@ export function TimeGrid<T = unknown>({
|
|
|
557
631
|
|
|
558
632
|
{/* All-day lane */}
|
|
559
633
|
{showAllDayEventCell && hasAllDay ? (
|
|
560
|
-
<div
|
|
634
|
+
<div
|
|
635
|
+
{...slot("allDayLane", {
|
|
636
|
+
base: { display: "flex" },
|
|
637
|
+
themed: { borderBottom: `1px solid ${theme.gridLine}` },
|
|
638
|
+
})}
|
|
639
|
+
>
|
|
561
640
|
<div
|
|
562
|
-
|
|
563
|
-
width: GUTTER_WIDTH,
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
color: theme.textMuted,
|
|
567
|
-
textAlign: "right",
|
|
568
|
-
padding: "4px 6px 0 0",
|
|
569
|
-
}}
|
|
641
|
+
{...slot("allDayLabel", {
|
|
642
|
+
base: { width: GUTTER_WIDTH, flex: "none", textAlign: "right" },
|
|
643
|
+
themed: { fontSize: 10, color: theme.textMuted, padding: "4px 6px 0 0" },
|
|
644
|
+
})}
|
|
570
645
|
>
|
|
571
646
|
all-day
|
|
572
647
|
</div>
|
|
@@ -576,18 +651,20 @@ export function TimeGrid<T = unknown>({
|
|
|
576
651
|
return (
|
|
577
652
|
<div
|
|
578
653
|
key={days[i].toISOString()}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
654
|
+
{...slot("allDayColumn", {
|
|
655
|
+
base: {
|
|
656
|
+
flex: 1,
|
|
657
|
+
minWidth: 0,
|
|
658
|
+
// Mirror the day column's geometry so the all-day chip lines up
|
|
659
|
+
// exactly with the timed events below it: a 1px left border (the
|
|
660
|
+
// grid line, transparent here) plus a 1px horizontal inset.
|
|
661
|
+
borderLeft: "1px solid transparent",
|
|
662
|
+
padding: "2px 1px",
|
|
663
|
+
display: "flex",
|
|
664
|
+
flexDirection: "column",
|
|
665
|
+
gap: 2,
|
|
666
|
+
},
|
|
667
|
+
})}
|
|
591
668
|
>
|
|
592
669
|
{list.map((event) => {
|
|
593
670
|
const args: DomRenderEventArgs<T> = {
|
|
@@ -606,26 +683,32 @@ export function TimeGrid<T = unknown>({
|
|
|
606
683
|
key={`${event.start.toISOString()}:${event.title}`}
|
|
607
684
|
type="button"
|
|
608
685
|
onClick={() => onPressEvent?.(event)}
|
|
609
|
-
aria-label={
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
686
|
+
aria-label={
|
|
687
|
+
eventAccessibilityLabel
|
|
688
|
+
? eventAccessibilityLabel(event, { mode, isAllDay: true, ampm })
|
|
689
|
+
: defaultEventAccessibilityLabel({
|
|
690
|
+
title: event.title,
|
|
691
|
+
isAllDay: true,
|
|
692
|
+
start: event.start,
|
|
693
|
+
end: event.end,
|
|
694
|
+
ampm,
|
|
695
|
+
})
|
|
696
|
+
}
|
|
697
|
+
{...slot("allDayEvent", {
|
|
698
|
+
base: {
|
|
699
|
+
border: "none",
|
|
700
|
+
padding: 0,
|
|
701
|
+
background: "transparent",
|
|
702
|
+
cursor: "pointer",
|
|
703
|
+
textAlign: "left",
|
|
704
|
+
height: 22,
|
|
705
|
+
},
|
|
615
706
|
})}
|
|
616
|
-
style={{
|
|
617
|
-
border: "none",
|
|
618
|
-
padding: 0,
|
|
619
|
-
background: "transparent",
|
|
620
|
-
cursor: "pointer",
|
|
621
|
-
textAlign: "left",
|
|
622
|
-
height: 22,
|
|
623
|
-
}}
|
|
624
707
|
>
|
|
625
708
|
{Renderer ? (
|
|
626
709
|
<Renderer {...args} />
|
|
627
710
|
) : (
|
|
628
|
-
<DefaultDomEvent {...args} theme={theme} />
|
|
711
|
+
<DefaultDomEvent {...args} theme={theme} boxProps={slot("eventBox")} />
|
|
629
712
|
)}
|
|
630
713
|
</button>
|
|
631
714
|
);
|
|
@@ -652,17 +735,18 @@ export function TimeGrid<T = unknown>({
|
|
|
652
735
|
>
|
|
653
736
|
<div style={{ display: "flex", height: totalHeight, position: "relative" }}>
|
|
654
737
|
{/* Hour gutter */}
|
|
655
|
-
<div
|
|
738
|
+
<div
|
|
739
|
+
{...slot("hourGutter", {
|
|
740
|
+
base: { width: GUTTER_WIDTH, flex: "none", position: "relative" },
|
|
741
|
+
})}
|
|
742
|
+
>
|
|
656
743
|
{HOURS.map((h) => (
|
|
657
744
|
<div
|
|
658
745
|
key={h}
|
|
659
|
-
|
|
660
|
-
position: "absolute",
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
fontSize: 10,
|
|
664
|
-
color: theme.textMuted,
|
|
665
|
-
}}
|
|
746
|
+
{...slot("hourLabel", {
|
|
747
|
+
base: { position: "absolute", top: h * hourHeight - 6, right: 6 },
|
|
748
|
+
themed: { fontSize: 10, color: theme.textMuted },
|
|
749
|
+
})}
|
|
666
750
|
>
|
|
667
751
|
{hourComponent ? hourComponent(h, ampm) : h === 0 ? "" : formatHour(h, { ampm })}
|
|
668
752
|
</div>
|
|
@@ -687,39 +771,43 @@ export function TimeGrid<T = unknown>({
|
|
|
687
771
|
onPointerMove={cellEnabled ? moveCreate : undefined}
|
|
688
772
|
onPointerUp={cellEnabled ? endCreate : undefined}
|
|
689
773
|
onPointerCancel={cellEnabled ? cancelCreate : undefined}
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
position: "relative",
|
|
693
|
-
|
|
694
|
-
|
|
774
|
+
{...dataState({ "data-today": getIsToday(day), "data-weekend": isWeekend(day) })}
|
|
775
|
+
{...slot("dayColumn", {
|
|
776
|
+
base: { flex: 1, position: "relative" },
|
|
777
|
+
// Weekend columns are tinted (matching the native renderer); the
|
|
778
|
+
// tint sits behind the grid lines, business-hours shade and events.
|
|
779
|
+
themed: {
|
|
780
|
+
borderLeft: `1px solid ${theme.gridLine}`,
|
|
781
|
+
...(isWeekend(day) ? { background: theme.weekendBackground } : null),
|
|
782
|
+
},
|
|
783
|
+
})}
|
|
695
784
|
>
|
|
696
785
|
{/* Business-hours shade, behind the grid lines and events. */}
|
|
697
786
|
{bands.map((b) => (
|
|
698
787
|
<div
|
|
699
788
|
key={b.start}
|
|
700
789
|
aria-hidden
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
790
|
+
{...slot("businessHours", {
|
|
791
|
+
base: {
|
|
792
|
+
position: "absolute",
|
|
793
|
+
left: 0,
|
|
794
|
+
right: 0,
|
|
795
|
+
top: b.start * hourHeight,
|
|
796
|
+
height: (b.end - b.start) * hourHeight,
|
|
797
|
+
pointerEvents: "none",
|
|
798
|
+
zIndex: 0,
|
|
799
|
+
},
|
|
800
|
+
themed: { background: theme.outsideHoursBackground },
|
|
801
|
+
})}
|
|
711
802
|
/>
|
|
712
803
|
))}
|
|
713
804
|
{/* Grid lines, painted over the shade so they stay visible. */}
|
|
714
805
|
<div
|
|
715
806
|
aria-hidden
|
|
716
|
-
|
|
717
|
-
position: "absolute",
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
zIndex: 0,
|
|
721
|
-
backgroundImage: gridLines,
|
|
722
|
-
}}
|
|
807
|
+
{...slot("gridLines", {
|
|
808
|
+
base: { position: "absolute", inset: 0, pointerEvents: "none", zIndex: 0 },
|
|
809
|
+
themed: { backgroundImage: gridLines },
|
|
810
|
+
})}
|
|
723
811
|
/>
|
|
724
812
|
{positioned.map((pe, idx) => {
|
|
725
813
|
const key = `${dayIndex}:${idx}`;
|
|
@@ -746,13 +834,17 @@ export function TimeGrid<T = unknown>({
|
|
|
746
834
|
key={idx}
|
|
747
835
|
role="button"
|
|
748
836
|
tabIndex={0}
|
|
749
|
-
aria-label={
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
837
|
+
aria-label={
|
|
838
|
+
eventAccessibilityLabel
|
|
839
|
+
? eventAccessibilityLabel(pe.event, { mode, isAllDay: false, ampm })
|
|
840
|
+
: defaultEventAccessibilityLabel({
|
|
841
|
+
title: pe.event.title,
|
|
842
|
+
isAllDay: false,
|
|
843
|
+
start: pe.event.start,
|
|
844
|
+
end: pe.event.end,
|
|
845
|
+
ampm,
|
|
846
|
+
})
|
|
847
|
+
}
|
|
756
848
|
onKeyDown={(e) => {
|
|
757
849
|
if (e.key === "Enter" || e.key === " ") {
|
|
758
850
|
e.preventDefault();
|
|
@@ -771,22 +863,29 @@ export function TimeGrid<T = unknown>({
|
|
|
771
863
|
}
|
|
772
864
|
onPointerCancel={draggable ? cancelDrag : undefined}
|
|
773
865
|
onClick={draggable ? undefined : onPress}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
866
|
+
{...dataState({ "data-dragging": !!active })}
|
|
867
|
+
{...slot("event", {
|
|
868
|
+
base: {
|
|
869
|
+
position: "absolute",
|
|
870
|
+
top,
|
|
871
|
+
// Height is the event's duration, so it always tracks the
|
|
872
|
+
// grid's hour scale (zoom/resize). Content that doesn't fit
|
|
873
|
+
// is the renderer's concern: the built-in one clamps, and a
|
|
874
|
+
// custom renderer should adapt to the `boxHeight` it's given.
|
|
875
|
+
height: boxHeight,
|
|
876
|
+
left: `calc(${pe.column * widthPct}% + 1px)`,
|
|
877
|
+
width: `calc(${widthPct}% - 2px)`,
|
|
878
|
+
cursor: draggable ? "grab" : "pointer",
|
|
879
|
+
touchAction: draggable ? "none" : "auto",
|
|
880
|
+
zIndex: active ? 3 : 1,
|
|
881
|
+
opacity: active ? 0.85 : 1,
|
|
882
|
+
},
|
|
883
|
+
})}
|
|
785
884
|
>
|
|
786
885
|
{Renderer ? (
|
|
787
886
|
<Renderer {...args} />
|
|
788
887
|
) : (
|
|
789
|
-
<DefaultDomEvent {...args} theme={theme} />
|
|
888
|
+
<DefaultDomEvent {...args} theme={theme} boxProps={slot("eventBox")} />
|
|
790
889
|
)}
|
|
791
890
|
{draggable ? (
|
|
792
891
|
<div
|
|
@@ -810,15 +909,17 @@ export function TimeGrid<T = unknown>({
|
|
|
810
909
|
})}
|
|
811
910
|
{showNow ? (
|
|
812
911
|
<div
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
912
|
+
{...slot("nowIndicator", {
|
|
913
|
+
base: {
|
|
914
|
+
position: "absolute",
|
|
915
|
+
top: nowTop,
|
|
916
|
+
left: 0,
|
|
917
|
+
right: 0,
|
|
918
|
+
height: 0,
|
|
919
|
+
zIndex: 2,
|
|
920
|
+
pointerEvents: "none",
|
|
921
|
+
},
|
|
922
|
+
})}
|
|
822
923
|
>
|
|
823
924
|
<div style={{ height: 2, background: theme.nowIndicator }} />
|
|
824
925
|
<div
|
|
@@ -837,19 +938,23 @@ export function TimeGrid<T = unknown>({
|
|
|
837
938
|
{ghost ? (
|
|
838
939
|
<div
|
|
839
940
|
aria-hidden
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
941
|
+
{...slot("createGhost", {
|
|
942
|
+
base: {
|
|
943
|
+
position: "absolute",
|
|
944
|
+
left: 1,
|
|
945
|
+
right: 1,
|
|
946
|
+
top: ghost.topPx,
|
|
947
|
+
height: Math.max(ghost.heightPx, 2),
|
|
948
|
+
opacity: 0.7,
|
|
949
|
+
pointerEvents: "none",
|
|
950
|
+
zIndex: 2,
|
|
951
|
+
},
|
|
952
|
+
themed: {
|
|
953
|
+
background: theme.rangeBackground,
|
|
954
|
+
border: `1px solid ${theme.selectedBackground}`,
|
|
955
|
+
borderRadius: 6,
|
|
956
|
+
},
|
|
957
|
+
})}
|
|
853
958
|
/>
|
|
854
959
|
) : null}
|
|
855
960
|
</div>
|
package/src/index.ts
CHANGED
|
@@ -19,21 +19,44 @@
|
|
|
19
19
|
*
|
|
20
20
|
* @module
|
|
21
21
|
*/
|
|
22
|
-
export {
|
|
23
|
-
|
|
22
|
+
export {
|
|
23
|
+
Agenda,
|
|
24
|
+
type AgendaProps,
|
|
25
|
+
type AgendaSlot,
|
|
26
|
+
type DomAgendaEvent,
|
|
27
|
+
type DomAgendaEventArgs,
|
|
28
|
+
} from "./Agenda";
|
|
29
|
+
export { Calendar, type CalendarProps, type CalendarSlot } from "./Calendar";
|
|
30
|
+
export {
|
|
31
|
+
DatePicker,
|
|
32
|
+
type DatePickerProps,
|
|
33
|
+
type DatePickerSlot,
|
|
34
|
+
DateRangePicker,
|
|
35
|
+
type DateRangePickerProps,
|
|
36
|
+
} from "./DateRangePicker";
|
|
24
37
|
export {
|
|
25
38
|
type DomMonthEvent,
|
|
26
39
|
type DomMonthEventArgs,
|
|
27
40
|
MonthView,
|
|
28
41
|
type MonthViewProps,
|
|
42
|
+
type MonthViewSlot,
|
|
29
43
|
} from "./MonthView";
|
|
30
|
-
export { MonthList, type MonthListProps } from "./MonthList";
|
|
44
|
+
export { MonthList, type MonthListProps, type MonthListSlot } from "./MonthList";
|
|
45
|
+
export {
|
|
46
|
+
type Resource,
|
|
47
|
+
type ResourceEventArgs,
|
|
48
|
+
ResourceTimeline,
|
|
49
|
+
type ResourceTimelineProps,
|
|
50
|
+
type ResourceTimelineSlot,
|
|
51
|
+
} from "./ResourceTimeline";
|
|
31
52
|
export {
|
|
32
53
|
TimeGrid,
|
|
33
54
|
type TimeGridProps,
|
|
55
|
+
type TimeGridSlot,
|
|
34
56
|
type DomRenderEvent,
|
|
35
57
|
type DomRenderEventArgs,
|
|
36
58
|
} from "./TimeGrid";
|
|
59
|
+
export { type ResolvedSlot, type SlotDefault, type SlotStyleProps } from "./slots";
|
|
37
60
|
export { type DomCalendarTheme, darkDomTheme, defaultDomTheme, mergeDomTheme } from "./theme";
|
|
38
61
|
export {
|
|
39
62
|
type BusinessHours,
|
|
@@ -42,11 +65,20 @@ export {
|
|
|
42
65
|
type DateRange,
|
|
43
66
|
type DateSelectionConstraints,
|
|
44
67
|
type DaySelectionState,
|
|
68
|
+
type EventAccessibilityLabelContext,
|
|
69
|
+
type EventAccessibilityLabeler,
|
|
45
70
|
type ICalendarEvent,
|
|
71
|
+
type ICalEvent,
|
|
72
|
+
parseICalendar,
|
|
73
|
+
toICalendar,
|
|
74
|
+
type ToICalendarOptions,
|
|
46
75
|
type PositionedEvent,
|
|
47
76
|
type TimeGridMode,
|
|
48
77
|
type UseDateRangeOptions,
|
|
49
78
|
type WeekStartsOn,
|
|
79
|
+
type RecurrenceRule,
|
|
80
|
+
type RecurrenceFrequency,
|
|
81
|
+
expandRecurringEvents,
|
|
50
82
|
getViewDays,
|
|
51
83
|
isAllDayEvent,
|
|
52
84
|
layoutDayEvents,
|
|
@@ -58,9 +90,11 @@ export {
|
|
|
58
90
|
useDateRange,
|
|
59
91
|
useMonthGrid,
|
|
60
92
|
buildMonthGrid,
|
|
93
|
+
weekdayFormatToken,
|
|
61
94
|
type MonthGrid,
|
|
62
95
|
type MonthGridDay,
|
|
63
96
|
type MonthGridWeek,
|
|
64
97
|
type MonthGridWeekday,
|
|
65
98
|
type UseMonthGridOptions,
|
|
99
|
+
type WeekdayFormat,
|
|
66
100
|
} from "@super-calendar/core";
|