@super-calendar/dom 2.1.4 → 2.2.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 +18 -1
- package/dist/index.d.mts +327 -12
- package/dist/index.d.ts +327 -12
- package/dist/index.js +1111 -286
- package/dist/index.mjs +1087 -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 +247 -148
- package/src/index.ts +37 -3
- package/src/slots.ts +87 -0
package/dist/index.js
CHANGED
|
@@ -4,6 +4,43 @@ let date_fns = require("date-fns");
|
|
|
4
4
|
let react = require("react");
|
|
5
5
|
let _super_calendar_core = require("@super-calendar/core");
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
+
//#region src/slots.ts
|
|
8
|
+
/** Join truthy class names (a dependency-free clsx-lite). */
|
|
9
|
+
function cn(...parts) {
|
|
10
|
+
return parts.filter(Boolean).join(" ") || void 0;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Build a slot resolver for one render. `slot(name, defaults)` returns the props to
|
|
14
|
+
* spread on that element: a merged `className`, the resolved inline `style`, and a
|
|
15
|
+
* stable `data-slot` hook for CSS/testing.
|
|
16
|
+
*/
|
|
17
|
+
function createSlots({ classNames, styles }) {
|
|
18
|
+
return (name, defaults) => {
|
|
19
|
+
const slotClass = classNames?.[name];
|
|
20
|
+
const override = styles?.[name];
|
|
21
|
+
const style = {
|
|
22
|
+
...defaults?.base,
|
|
23
|
+
...slotClass ? void 0 : defaults?.themed,
|
|
24
|
+
...override
|
|
25
|
+
};
|
|
26
|
+
return {
|
|
27
|
+
className: cn(slotClass),
|
|
28
|
+
style: Object.keys(style).length ? style : void 0,
|
|
29
|
+
"data-slot": name
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Turn a map of boolean state flags into present/absent `data-*` attributes, so
|
|
35
|
+
* consumers can target state with CSS/Tailwind variants (e.g. `data-[today]:...`).
|
|
36
|
+
* A true flag renders the attribute (empty value); a false/undefined one omits it.
|
|
37
|
+
*/
|
|
38
|
+
function dataState(flags) {
|
|
39
|
+
const out = {};
|
|
40
|
+
for (const key in flags) if (flags[key]) out[key] = "";
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
7
44
|
//#region src/theme.ts
|
|
8
45
|
const METRICS = {
|
|
9
46
|
cellHeight: 48,
|
|
@@ -30,7 +67,7 @@ function mergeDomTheme(overrides, base = defaultDomTheme) {
|
|
|
30
67
|
}
|
|
31
68
|
//#endregion
|
|
32
69
|
//#region src/Agenda.tsx
|
|
33
|
-
function DefaultAgendaRow({ event, isAllDay, ampm = false,
|
|
70
|
+
function DefaultAgendaRow({ event, isAllDay, ampm = false, cardProps }) {
|
|
34
71
|
const time = (0, _super_calendar_core.eventTimeLabel)({
|
|
35
72
|
mode: "schedule",
|
|
36
73
|
isAllDay,
|
|
@@ -40,12 +77,7 @@ function DefaultAgendaRow({ event, isAllDay, ampm = false, theme }) {
|
|
|
40
77
|
showTime: true
|
|
41
78
|
}) ?? "";
|
|
42
79
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
43
|
-
|
|
44
|
-
padding: "6px 10px",
|
|
45
|
-
borderRadius: 8,
|
|
46
|
-
background: theme.eventBackground,
|
|
47
|
-
color: theme.eventText
|
|
48
|
-
},
|
|
80
|
+
...cardProps,
|
|
49
81
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
50
82
|
style: {
|
|
51
83
|
fontWeight: 600,
|
|
@@ -72,8 +104,12 @@ function DefaultAgendaRow({ event, isAllDay, ampm = false, theme }) {
|
|
|
72
104
|
* <Agenda events={events} onPressEvent={(e) => console.log(e.title)} />
|
|
73
105
|
* ```
|
|
74
106
|
*/
|
|
75
|
-
function Agenda({ events, locale, ampm = false, activeDate, theme: themeOverrides, height = 480, renderEvent, onPressEvent, onPressDay, className, style }) {
|
|
107
|
+
function Agenda({ events, locale, ampm = false, activeDate, theme: themeOverrides, height = 480, renderEvent, eventAccessibilityLabel, onPressEvent, onPressDay, className, style, classNames, styles }) {
|
|
76
108
|
const theme = (0, react.useMemo)(() => mergeDomTheme(themeOverrides), [themeOverrides]);
|
|
109
|
+
const slot = createSlots({
|
|
110
|
+
classNames,
|
|
111
|
+
styles
|
|
112
|
+
});
|
|
77
113
|
const Renderer = renderEvent;
|
|
78
114
|
const rows = (0, react.useMemo)(() => {
|
|
79
115
|
const sorted = [...events].sort((a, b) => a.start.getTime() - b.start.getTime());
|
|
@@ -117,24 +153,33 @@ function Agenda({ events, locale, ampm = false, activeDate, theme: themeOverride
|
|
|
117
153
|
const highlighted = activeDate ? (0, date_fns.isSameDay)(item.date, activeDate) : (0, _super_calendar_core.getIsToday)(item.date);
|
|
118
154
|
const label = (0, date_fns.format)(item.date, "EEEE, d LLLL", locale ? { locale } : void 0);
|
|
119
155
|
const color = highlighted ? theme.todayBackground : theme.textMuted;
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
...headerStyle,
|
|
125
|
-
color,
|
|
156
|
+
const headerProps = slot("dayHeader", {
|
|
157
|
+
base: onPressDay ? {
|
|
158
|
+
display: "block",
|
|
159
|
+
width: "100%",
|
|
126
160
|
border: "none",
|
|
127
161
|
background: "transparent",
|
|
128
162
|
cursor: "pointer",
|
|
129
163
|
font: "inherit",
|
|
130
164
|
textAlign: "left"
|
|
165
|
+
} : {
|
|
166
|
+
display: "block",
|
|
167
|
+
width: "100%"
|
|
131
168
|
},
|
|
169
|
+
themed: {
|
|
170
|
+
padding: "12px 12px 4px",
|
|
171
|
+
fontSize: 13,
|
|
172
|
+
fontWeight: 600,
|
|
173
|
+
color
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
return onPressDay ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
177
|
+
type: "button",
|
|
178
|
+
onClick: () => onPressDay(item.date),
|
|
179
|
+
...headerProps,
|
|
132
180
|
children: label
|
|
133
181
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
134
|
-
|
|
135
|
-
...headerStyle,
|
|
136
|
-
color
|
|
137
|
-
},
|
|
182
|
+
...headerProps,
|
|
138
183
|
children: label
|
|
139
184
|
});
|
|
140
185
|
}
|
|
@@ -151,68 +196,78 @@ function Agenda({ events, locale, ampm = false, activeDate, theme: themeOverride
|
|
|
151
196
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
152
197
|
type: "button",
|
|
153
198
|
onClick: onPress,
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
199
|
+
"aria-label": eventAccessibilityLabel ? eventAccessibilityLabel(event, {
|
|
200
|
+
mode: "schedule",
|
|
201
|
+
isAllDay,
|
|
202
|
+
ampm
|
|
203
|
+
}) : void 0,
|
|
204
|
+
...slot("eventRow", {
|
|
205
|
+
base: {
|
|
206
|
+
display: "block",
|
|
207
|
+
width: "100%",
|
|
208
|
+
textAlign: "left",
|
|
209
|
+
border: "none",
|
|
210
|
+
background: "transparent",
|
|
211
|
+
cursor: "pointer",
|
|
212
|
+
font: "inherit"
|
|
213
|
+
},
|
|
214
|
+
themed: { padding: "2px 12px" }
|
|
215
|
+
}),
|
|
164
216
|
children: Renderer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, { ...args }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultAgendaRow, {
|
|
165
217
|
...args,
|
|
166
|
-
|
|
218
|
+
cardProps: slot("event", { themed: {
|
|
219
|
+
padding: "6px 10px",
|
|
220
|
+
borderRadius: 8,
|
|
221
|
+
background: theme.eventBackground,
|
|
222
|
+
color: theme.eventText
|
|
223
|
+
} })
|
|
167
224
|
})
|
|
168
225
|
});
|
|
169
226
|
}
|
|
170
227
|
}), rows.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
171
|
-
|
|
228
|
+
...slot("empty", { themed: {
|
|
172
229
|
padding: "16px 12px",
|
|
173
230
|
color: theme.textMuted,
|
|
174
231
|
fontSize: 14
|
|
175
|
-
},
|
|
232
|
+
} }),
|
|
176
233
|
children: "No events"
|
|
177
234
|
}) : null]
|
|
178
235
|
});
|
|
179
236
|
}
|
|
180
|
-
const headerStyle = {
|
|
181
|
-
display: "block",
|
|
182
|
-
width: "100%",
|
|
183
|
-
padding: "12px 12px 4px",
|
|
184
|
-
fontSize: 13,
|
|
185
|
-
fontWeight: 600
|
|
186
|
-
};
|
|
187
237
|
//#endregion
|
|
188
238
|
//#region src/MonthView.tsx
|
|
189
239
|
const DATE_ROW = 24;
|
|
190
240
|
const CHIP_HEIGHT = 18;
|
|
191
241
|
const CHIP_GAP = 2;
|
|
192
242
|
const CELL_PAD = 4;
|
|
193
|
-
function
|
|
243
|
+
function dayCellDefault(day, theme) {
|
|
194
244
|
return {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
245
|
+
base: {
|
|
246
|
+
position: "relative",
|
|
247
|
+
height: theme.cellHeight,
|
|
248
|
+
border: "none",
|
|
249
|
+
font: "inherit",
|
|
250
|
+
cursor: day.isDisabled ? "default" : "pointer",
|
|
251
|
+
display: "flex",
|
|
252
|
+
alignItems: "center",
|
|
253
|
+
justifyContent: "center",
|
|
254
|
+
padding: 0,
|
|
255
|
+
WebkitTapHighlightColor: "transparent"
|
|
256
|
+
},
|
|
257
|
+
themed: {
|
|
258
|
+
background: day.isWeekend && !day.isInRange ? theme.weekendBackground : "transparent",
|
|
259
|
+
fontSize: 15,
|
|
260
|
+
color: day.isDisabled ? theme.textDisabled : theme.text
|
|
261
|
+
}
|
|
208
262
|
};
|
|
209
263
|
}
|
|
210
264
|
/**
|
|
211
265
|
* The range band behind a day, rendered as its own layer so it can be a centered
|
|
212
266
|
* rounded strip (the default) or fill the whole cell (`fillCell`). Returns null
|
|
213
|
-
* for days with no band. Endpoints get the leading/trailing pill rounding.
|
|
267
|
+
* for days with no band. Endpoints get the leading/trailing pill rounding. Its
|
|
268
|
+
* geometry is structural; only the fill colour is themed.
|
|
214
269
|
*/
|
|
215
|
-
function
|
|
270
|
+
function rangeBandDefault(day, theme, fillCell) {
|
|
216
271
|
const kind = (0, _super_calendar_core.rangeBandKind)(day, fillCell);
|
|
217
272
|
if (kind === "none") return null;
|
|
218
273
|
const fill = kind === "fill";
|
|
@@ -220,80 +275,94 @@ function rangeBandStyle(day, theme, fillCell) {
|
|
|
220
275
|
const radius = fill ? 0 : theme.rangeBandHeight / 2;
|
|
221
276
|
const rounding = (0, _super_calendar_core.bandRounding)(kind);
|
|
222
277
|
const cap = `calc(50% - ${theme.dayBadgeSize / 2}px)`;
|
|
223
|
-
const
|
|
278
|
+
const base = {
|
|
224
279
|
position: "absolute",
|
|
225
280
|
left: rounding.start ? cap : 0,
|
|
226
281
|
right: rounding.end ? cap : 0,
|
|
227
282
|
top: inset,
|
|
228
283
|
bottom: inset,
|
|
229
|
-
background: theme.rangeBackground,
|
|
230
284
|
zIndex: 0
|
|
231
285
|
};
|
|
232
286
|
if (rounding.start) {
|
|
233
|
-
|
|
234
|
-
|
|
287
|
+
base.borderTopLeftRadius = radius;
|
|
288
|
+
base.borderBottomLeftRadius = radius;
|
|
235
289
|
}
|
|
236
290
|
if (rounding.end) {
|
|
237
|
-
|
|
238
|
-
|
|
291
|
+
base.borderTopRightRadius = radius;
|
|
292
|
+
base.borderBottomRightRadius = radius;
|
|
239
293
|
}
|
|
240
|
-
return
|
|
294
|
+
return {
|
|
295
|
+
base,
|
|
296
|
+
themed: { background: theme.rangeBackground }
|
|
297
|
+
};
|
|
241
298
|
}
|
|
242
|
-
function
|
|
299
|
+
function badgeDefault(day, theme, hovered) {
|
|
243
300
|
const badge = (0, _super_calendar_core.dayBadgeKind)(day, day.isToday);
|
|
244
301
|
const filled = badge !== "none";
|
|
245
302
|
const background = filled ? badge === "today" ? theme.todayBackground : theme.selectedBackground : hovered ? theme.hoverBackground : "transparent";
|
|
246
303
|
return {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
304
|
+
base: {
|
|
305
|
+
position: "relative",
|
|
306
|
+
zIndex: 1,
|
|
307
|
+
width: theme.dayBadgeSize,
|
|
308
|
+
height: theme.dayBadgeSize,
|
|
309
|
+
borderRadius: "50%",
|
|
310
|
+
display: "flex",
|
|
311
|
+
alignItems: "center",
|
|
312
|
+
justifyContent: "center"
|
|
313
|
+
},
|
|
314
|
+
themed: {
|
|
315
|
+
background,
|
|
316
|
+
color: filled ? day.isToday ? theme.todayText : theme.selectedText : "inherit"
|
|
317
|
+
}
|
|
257
318
|
};
|
|
258
319
|
}
|
|
259
|
-
function
|
|
320
|
+
function eventCellDefault(day, theme, height) {
|
|
260
321
|
return {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
322
|
+
base: {
|
|
323
|
+
position: "relative",
|
|
324
|
+
minHeight: height,
|
|
325
|
+
minWidth: 0,
|
|
326
|
+
border: "none",
|
|
327
|
+
cursor: day.isDisabled ? "default" : "pointer",
|
|
328
|
+
display: "flex",
|
|
329
|
+
flexDirection: "column",
|
|
330
|
+
gap: CHIP_GAP,
|
|
331
|
+
padding: CELL_PAD,
|
|
332
|
+
boxSizing: "border-box",
|
|
333
|
+
textAlign: "left",
|
|
334
|
+
WebkitTapHighlightColor: "transparent"
|
|
335
|
+
},
|
|
336
|
+
themed: {
|
|
337
|
+
borderTop: `1px solid ${theme.gridLine}`,
|
|
338
|
+
background: day.isWeekend && !day.isInRange ? theme.weekendBackground : "transparent",
|
|
339
|
+
color: day.isDisabled ? theme.textDisabled : theme.text
|
|
340
|
+
}
|
|
276
341
|
};
|
|
277
342
|
}
|
|
278
|
-
function
|
|
343
|
+
function compactBadgeDefault(day, theme) {
|
|
279
344
|
const badge = (0, _super_calendar_core.dayBadgeKind)(day, day.isToday);
|
|
280
345
|
const filled = badge !== "none";
|
|
281
346
|
return {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
347
|
+
base: {
|
|
348
|
+
position: "relative",
|
|
349
|
+
zIndex: 1,
|
|
350
|
+
alignSelf: "flex-end",
|
|
351
|
+
width: DATE_ROW - 2,
|
|
352
|
+
height: DATE_ROW - 2,
|
|
353
|
+
borderRadius: "50%",
|
|
354
|
+
display: "flex",
|
|
355
|
+
alignItems: "center",
|
|
356
|
+
justifyContent: "center"
|
|
357
|
+
},
|
|
358
|
+
themed: {
|
|
359
|
+
fontSize: 13,
|
|
360
|
+
background: filled ? badge === "today" ? theme.todayBackground : theme.selectedBackground : "transparent",
|
|
361
|
+
color: filled ? day.isToday ? theme.todayText : theme.selectedText : "inherit"
|
|
362
|
+
}
|
|
294
363
|
};
|
|
295
364
|
}
|
|
296
|
-
const
|
|
365
|
+
const chipButtonDefault = { base: {
|
|
297
366
|
position: "relative",
|
|
298
367
|
zIndex: 1,
|
|
299
368
|
border: "none",
|
|
@@ -303,38 +372,46 @@ const chipButtonStyle = {
|
|
|
303
372
|
cursor: "pointer",
|
|
304
373
|
textAlign: "left",
|
|
305
374
|
fontFamily: "inherit"
|
|
306
|
-
};
|
|
307
|
-
function
|
|
375
|
+
} };
|
|
376
|
+
function chipDefault(theme) {
|
|
308
377
|
return {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
378
|
+
base: {
|
|
379
|
+
display: "block",
|
|
380
|
+
height: CHIP_HEIGHT,
|
|
381
|
+
lineHeight: `${CHIP_HEIGHT}px`,
|
|
382
|
+
whiteSpace: "nowrap",
|
|
383
|
+
overflow: "hidden",
|
|
384
|
+
textOverflow: "ellipsis"
|
|
385
|
+
},
|
|
386
|
+
themed: {
|
|
387
|
+
padding: "0 6px",
|
|
388
|
+
borderRadius: 4,
|
|
389
|
+
background: theme.eventBackground,
|
|
390
|
+
color: theme.eventText,
|
|
391
|
+
fontSize: 11,
|
|
392
|
+
fontWeight: 600
|
|
393
|
+
}
|
|
321
394
|
};
|
|
322
395
|
}
|
|
323
|
-
function
|
|
396
|
+
function moreButtonDefault(theme) {
|
|
324
397
|
return {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
398
|
+
base: {
|
|
399
|
+
position: "relative",
|
|
400
|
+
zIndex: 1,
|
|
401
|
+
border: "none",
|
|
402
|
+
background: "transparent",
|
|
403
|
+
cursor: "pointer",
|
|
404
|
+
textAlign: "left",
|
|
405
|
+
height: CHIP_HEIGHT,
|
|
406
|
+
lineHeight: `${CHIP_HEIGHT}px`,
|
|
407
|
+
fontFamily: "inherit"
|
|
408
|
+
},
|
|
409
|
+
themed: {
|
|
410
|
+
padding: "0 6px",
|
|
411
|
+
fontSize: 11,
|
|
412
|
+
fontWeight: 600,
|
|
413
|
+
color: theme.textMuted
|
|
414
|
+
}
|
|
338
415
|
};
|
|
339
416
|
}
|
|
340
417
|
/**
|
|
@@ -345,8 +422,12 @@ function moreButtonStyle(theme) {
|
|
|
345
422
|
* <MonthView date={new Date()} events={events} onPressDay={(d) => setDate(d)} />
|
|
346
423
|
* ```
|
|
347
424
|
*/
|
|
348
|
-
function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayProp, renderEvent, maxVisibleEventCount = 3, moreLabel = "{moreCount} More", onPressEvent, onPressMore, selectedRange, selectedDates, showAdjacentMonths = true, fillCellOnSelection = false, showTitle = true, showWeekdays = true, locale, theme: themeOverrides, minDate, maxDate, isDateDisabled, onPressDay, keyboardDayNavigation = false, className, style }) {
|
|
425
|
+
function MonthView({ date, weekStartsOn = 0, weekdayFormat = "short", events, eventsByDay: eventsByDayProp, renderEvent, eventAccessibilityLabel, maxVisibleEventCount = 3, moreLabel = "{moreCount} More", onPressEvent, onPressMore, selectedRange, selectedDates, showAdjacentMonths = true, fillCellOnSelection = false, showTitle = true, showWeekdays = true, locale, theme: themeOverrides, minDate, maxDate, isDateDisabled, onPressDay, onCreateEvent, keyboardDayNavigation = false, className, style, classNames, styles }) {
|
|
349
426
|
const theme = (0, react.useMemo)(() => mergeDomTheme(themeOverrides), [themeOverrides]);
|
|
427
|
+
const slot = createSlots({
|
|
428
|
+
classNames,
|
|
429
|
+
styles
|
|
430
|
+
});
|
|
350
431
|
const eventsMode = events !== void 0;
|
|
351
432
|
const dayRoving = !eventsMode || keyboardDayNavigation;
|
|
352
433
|
const eventsByDay = (0, react.useMemo)(() => {
|
|
@@ -359,6 +440,7 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
359
440
|
const eventRowHeight = 32 + maxVisibleEventCount * 20;
|
|
360
441
|
const { weeks, weekdays } = (0, react.useMemo)(() => (0, _super_calendar_core.buildMonthGrid)(date, {
|
|
361
442
|
weekStartsOn,
|
|
443
|
+
weekdayFormat,
|
|
362
444
|
selectedRange,
|
|
363
445
|
selectedDates,
|
|
364
446
|
minDate,
|
|
@@ -368,6 +450,7 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
368
450
|
}), [
|
|
369
451
|
date,
|
|
370
452
|
weekStartsOn,
|
|
453
|
+
weekdayFormat,
|
|
371
454
|
selectedRange,
|
|
372
455
|
selectedDates,
|
|
373
456
|
minDate,
|
|
@@ -394,6 +477,46 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
394
477
|
const [hoveredKey, setHoveredKey] = (0, react.useState)(null);
|
|
395
478
|
const gridRef = (0, react.useRef)(null);
|
|
396
479
|
const focusKey = (0, date_fns.format)(focusedDate, "yyyy-MM-dd");
|
|
480
|
+
const [creating, setCreating] = (0, react.useState)(null);
|
|
481
|
+
const creatingRef = (0, react.useRef)(creating);
|
|
482
|
+
creatingRef.current = creating;
|
|
483
|
+
const movedRef = (0, react.useRef)(false);
|
|
484
|
+
const suppressClickRef = (0, react.useRef)(false);
|
|
485
|
+
const beginCreate = (day) => {
|
|
486
|
+
if (!onCreateEvent) return;
|
|
487
|
+
const t = (0, date_fns.startOfDay)(day).getTime();
|
|
488
|
+
movedRef.current = false;
|
|
489
|
+
setCreating({
|
|
490
|
+
anchor: t,
|
|
491
|
+
hover: t
|
|
492
|
+
});
|
|
493
|
+
};
|
|
494
|
+
const extendCreate = (day) => {
|
|
495
|
+
if (!creatingRef.current) return;
|
|
496
|
+
const t = (0, date_fns.startOfDay)(day).getTime();
|
|
497
|
+
if (t !== creatingRef.current.hover) {
|
|
498
|
+
movedRef.current = true;
|
|
499
|
+
setCreating((c) => c ? {
|
|
500
|
+
...c,
|
|
501
|
+
hover: t
|
|
502
|
+
} : c);
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
const isCreating = creating !== null;
|
|
506
|
+
(0, react.useEffect)(() => {
|
|
507
|
+
if (!isCreating) return;
|
|
508
|
+
const finish = () => {
|
|
509
|
+
const c = creatingRef.current;
|
|
510
|
+
setCreating(null);
|
|
511
|
+
if (!c || !movedRef.current) return;
|
|
512
|
+
suppressClickRef.current = true;
|
|
513
|
+
const lo = Math.min(c.anchor, c.hover);
|
|
514
|
+
const hi = Math.max(c.anchor, c.hover);
|
|
515
|
+
onCreateEvent?.(new Date(lo), (0, date_fns.addDays)(new Date(hi), 1));
|
|
516
|
+
};
|
|
517
|
+
window.addEventListener("pointerup", finish);
|
|
518
|
+
return () => window.removeEventListener("pointerup", finish);
|
|
519
|
+
}, [isCreating, onCreateEvent]);
|
|
397
520
|
const onKeyDown = (e) => {
|
|
398
521
|
let next = null;
|
|
399
522
|
if (e.key === "ArrowLeft") next = (0, date_fns.addDays)(focusedDate, -1);
|
|
@@ -418,27 +541,31 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
418
541
|
},
|
|
419
542
|
children: [
|
|
420
543
|
showTitle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
421
|
-
|
|
544
|
+
...slot("title", { themed: {
|
|
422
545
|
fontSize: 17,
|
|
423
546
|
fontWeight: 700,
|
|
424
547
|
padding: "10px 14px 6px"
|
|
425
|
-
},
|
|
548
|
+
} }),
|
|
426
549
|
children: (0, date_fns.format)(date, "MMMM yyyy", locale ? { locale } : void 0)
|
|
427
550
|
}) : null,
|
|
428
551
|
showWeekdays ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
552
|
+
...slot("weekdays", {
|
|
553
|
+
base: {
|
|
554
|
+
display: "grid",
|
|
555
|
+
gridTemplateColumns: "repeat(7, minmax(0, 1fr))"
|
|
556
|
+
},
|
|
557
|
+
themed: {
|
|
558
|
+
borderBottom: `1px solid ${theme.gridLine}`,
|
|
559
|
+
padding: "6px 0"
|
|
560
|
+
}
|
|
561
|
+
}),
|
|
435
562
|
children: weekdays.map((wd) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
436
|
-
|
|
563
|
+
...slot("weekday", { themed: {
|
|
437
564
|
textAlign: "center",
|
|
438
565
|
fontSize: 12,
|
|
439
566
|
fontWeight: 600,
|
|
440
567
|
color: theme.textMuted
|
|
441
|
-
},
|
|
568
|
+
} }),
|
|
442
569
|
children: wd.label
|
|
443
570
|
}, wd.label))
|
|
444
571
|
}) : null,
|
|
@@ -447,12 +574,13 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
447
574
|
role: "grid",
|
|
448
575
|
"aria-label": (0, date_fns.format)(date, "MMMM yyyy", locale ? { locale } : void 0),
|
|
449
576
|
onKeyDown: dayRoving ? onKeyDown : void 0,
|
|
577
|
+
...slot("grid"),
|
|
450
578
|
children: weeks.map((week) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
451
579
|
role: "row",
|
|
452
|
-
|
|
580
|
+
...slot("week", { base: {
|
|
453
581
|
display: "grid",
|
|
454
582
|
gridTemplateColumns: "repeat(7, minmax(0, 1fr))"
|
|
455
|
-
},
|
|
583
|
+
} }),
|
|
456
584
|
children: week.days.map((day) => {
|
|
457
585
|
const hidden = !showAdjacentMonths && !day.isCurrentMonth;
|
|
458
586
|
const cellHeight = eventsMode ? eventRowHeight : theme.cellHeight;
|
|
@@ -461,8 +589,19 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
461
589
|
"aria-hidden": true,
|
|
462
590
|
style: { height: cellHeight }
|
|
463
591
|
}, day.id);
|
|
464
|
-
const band =
|
|
592
|
+
const band = rangeBandDefault(day, theme, fillCellOnSelection);
|
|
465
593
|
const label = (0, date_fns.format)(day.date, "EEEE, d MMMM yyyy", locale ? { locale } : void 0);
|
|
594
|
+
const dayTime = (0, date_fns.startOfDay)(day.date).getTime();
|
|
595
|
+
const inCreate = creating != null && dayTime >= Math.min(creating.anchor, creating.hover) && dayTime <= Math.max(creating.anchor, creating.hover);
|
|
596
|
+
const dayData = dataState({
|
|
597
|
+
"data-today": day.isToday,
|
|
598
|
+
"data-selected": day.isSelected,
|
|
599
|
+
"data-range": day.isInRange,
|
|
600
|
+
"data-weekend": day.isWeekend,
|
|
601
|
+
"data-outside": !day.isCurrentMonth,
|
|
602
|
+
"data-disabled": day.isDisabled,
|
|
603
|
+
"data-creating": inCreate
|
|
604
|
+
});
|
|
466
605
|
if (eventsMode) {
|
|
467
606
|
const dayEvents = eventsByDay.get((0, date_fns.startOfDay)(day.date).toISOString()) ?? [];
|
|
468
607
|
const visible = (0, _super_calendar_core.monthVisibleCount)(dayEvents.length, {
|
|
@@ -473,14 +612,30 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
473
612
|
const rest = dayEvents.slice(visible);
|
|
474
613
|
const overflow = rest.length > 0;
|
|
475
614
|
const dayLabel = (0, date_fns.format)(day.date, "d MMMM", locale ? { locale } : void 0);
|
|
615
|
+
const dayCellProps = slot("day", eventCellDefault(day, theme, cellHeight));
|
|
476
616
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
477
617
|
role: "gridcell",
|
|
478
618
|
"data-day": day.id,
|
|
619
|
+
...dayData,
|
|
479
620
|
tabIndex: keyboardDayNavigation ? day.id === focusKey ? 0 : -1 : void 0,
|
|
480
621
|
"aria-disabled": day.isDisabled || void 0,
|
|
481
622
|
"aria-label": label,
|
|
482
|
-
|
|
483
|
-
|
|
623
|
+
...dayCellProps,
|
|
624
|
+
style: onCreateEvent ? {
|
|
625
|
+
...dayCellProps.style,
|
|
626
|
+
touchAction: "none"
|
|
627
|
+
} : dayCellProps.style,
|
|
628
|
+
onPointerDown: onCreateEvent && !day.isDisabled ? (e) => {
|
|
629
|
+
if (e.button === 0) beginCreate(day.date);
|
|
630
|
+
} : void 0,
|
|
631
|
+
onPointerEnter: onCreateEvent ? () => extendCreate(day.date) : void 0,
|
|
632
|
+
onClick: day.isDisabled ? void 0 : () => {
|
|
633
|
+
if (suppressClickRef.current) {
|
|
634
|
+
suppressClickRef.current = false;
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
onPressDay?.(day.date);
|
|
638
|
+
},
|
|
484
639
|
onKeyDown: keyboardDayNavigation && !day.isDisabled ? (e) => {
|
|
485
640
|
if (e.target !== e.currentTarget) return;
|
|
486
641
|
if (e.key === "Enter" || e.key === " ") {
|
|
@@ -492,18 +647,19 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
492
647
|
band ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
493
648
|
"data-band": true,
|
|
494
649
|
"aria-hidden": true,
|
|
495
|
-
|
|
650
|
+
...slot("rangeBand", band)
|
|
496
651
|
}) : null,
|
|
497
652
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
498
|
-
|
|
653
|
+
...dayData,
|
|
654
|
+
...slot("dayBadge", compactBadgeDefault(day, theme)),
|
|
499
655
|
children: day.label
|
|
500
656
|
}),
|
|
501
657
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
502
|
-
|
|
658
|
+
...slot("events", { base: {
|
|
503
659
|
display: "flex",
|
|
504
660
|
flexDirection: "column",
|
|
505
661
|
gap: CHIP_GAP
|
|
506
|
-
},
|
|
662
|
+
} }),
|
|
507
663
|
children: [shown.map((event) => {
|
|
508
664
|
const onPress = () => onPressEvent?.(event);
|
|
509
665
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -512,14 +668,18 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
512
668
|
e.stopPropagation();
|
|
513
669
|
onPress();
|
|
514
670
|
},
|
|
515
|
-
|
|
671
|
+
...slot("chipButton", chipButtonDefault),
|
|
516
672
|
title: event.title,
|
|
517
|
-
"aria-label":
|
|
673
|
+
"aria-label": eventAccessibilityLabel ? eventAccessibilityLabel(event, {
|
|
674
|
+
mode: "month",
|
|
675
|
+
isAllDay: (0, _super_calendar_core.isAllDayEvent)(event),
|
|
676
|
+
ampm: false
|
|
677
|
+
}) : `${event.title}, ${dayLabel}`,
|
|
518
678
|
children: Chip ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Chip, {
|
|
519
679
|
event,
|
|
520
680
|
onPress
|
|
521
681
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
522
|
-
|
|
682
|
+
...slot("chip", chipDefault(theme)),
|
|
523
683
|
children: event.title
|
|
524
684
|
})
|
|
525
685
|
}, `${event.start.toISOString()}:${event.title}`);
|
|
@@ -529,7 +689,7 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
529
689
|
e.stopPropagation();
|
|
530
690
|
onPressMore?.(rest, day.date);
|
|
531
691
|
},
|
|
532
|
-
|
|
692
|
+
...slot("more", moreButtonDefault(theme)),
|
|
533
693
|
"aria-label": `${rest.length} more events, ${dayLabel}`,
|
|
534
694
|
children: moreLabel.replace("{moreCount}", String(rest.length))
|
|
535
695
|
}) : null]
|
|
@@ -541,20 +701,22 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
541
701
|
type: "button",
|
|
542
702
|
role: "gridcell",
|
|
543
703
|
"data-day": day.id,
|
|
704
|
+
...dayData,
|
|
544
705
|
tabIndex: day.id === focusKey ? 0 : -1,
|
|
545
706
|
"aria-disabled": day.isDisabled || void 0,
|
|
546
707
|
"aria-label": label,
|
|
547
708
|
"aria-pressed": day.isSelected || day.isInRange,
|
|
548
|
-
|
|
709
|
+
...slot("day", dayCellDefault(day, theme)),
|
|
549
710
|
onClick: day.isDisabled ? void 0 : () => onPressDay?.(day.date),
|
|
550
711
|
onMouseEnter: day.isDisabled ? void 0 : () => setHoveredKey(day.id),
|
|
551
712
|
onMouseLeave: () => setHoveredKey((k) => k === day.id ? null : k),
|
|
552
713
|
children: [band ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
553
714
|
"data-band": true,
|
|
554
715
|
"aria-hidden": true,
|
|
555
|
-
|
|
716
|
+
...slot("rangeBand", band)
|
|
556
717
|
}) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
557
|
-
|
|
718
|
+
...dayData,
|
|
719
|
+
...slot("dayBadge", badgeDefault(day, theme, hoveredKey === day.id)),
|
|
558
720
|
children: day.label
|
|
559
721
|
})]
|
|
560
722
|
}, day.id);
|
|
@@ -568,11 +730,11 @@ function MonthView({ date, weekStartsOn = 0, events, eventsByDay: eventsByDayPro
|
|
|
568
730
|
//#region src/TimeGrid.tsx
|
|
569
731
|
const HOURS = Array.from({ length: 24 }, (_, h) => h);
|
|
570
732
|
const GUTTER_WIDTH = 56;
|
|
571
|
-
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
733
|
+
const clamp$1 = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
572
734
|
const DOM_TITLE_LINE_HEIGHT = 16;
|
|
573
735
|
const DOM_TIME_LINE_HEIGHT = 30;
|
|
574
736
|
const DOM_BOX_PADDING_V = 2;
|
|
575
|
-
function DefaultDomEvent({ event, mode, isAllDay, boxHeight, ampm = false, theme }) {
|
|
737
|
+
function DefaultDomEvent({ event, mode, isAllDay, boxHeight, ampm = false, theme, boxProps }) {
|
|
576
738
|
const timeLabel = (0, _super_calendar_core.eventTimeLabel)({
|
|
577
739
|
mode,
|
|
578
740
|
isAllDay,
|
|
@@ -590,17 +752,34 @@ function DefaultDomEvent({ event, mode, isAllDay, boxHeight, ampm = false, theme
|
|
|
590
752
|
paddingYPx: DOM_BOX_PADDING_V
|
|
591
753
|
});
|
|
592
754
|
const oneLine = (0, _super_calendar_core.titleNumberOfLines)(mode, isAllDay) === 1;
|
|
755
|
+
const boxBase = {
|
|
756
|
+
height: "100%",
|
|
757
|
+
boxSizing: "border-box",
|
|
758
|
+
overflow: "hidden",
|
|
759
|
+
lineHeight: `${DOM_TITLE_LINE_HEIGHT}px`,
|
|
760
|
+
...titleMaxLines === 1 && !showTime ? {
|
|
761
|
+
display: "flex",
|
|
762
|
+
flexDirection: "column",
|
|
763
|
+
justifyContent: "center"
|
|
764
|
+
} : null
|
|
765
|
+
};
|
|
766
|
+
const boxThemed = {
|
|
767
|
+
padding: `${DOM_BOX_PADDING_V}px 6px`,
|
|
768
|
+
borderRadius: 6,
|
|
769
|
+
background: theme.eventBackground,
|
|
770
|
+
color: theme.eventText,
|
|
771
|
+
fontSize: 12
|
|
772
|
+
};
|
|
593
773
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
lineHeight: `${DOM_TITLE_LINE_HEIGHT}px`
|
|
774
|
+
className: boxProps?.className,
|
|
775
|
+
"data-slot": boxProps?.["data-slot"],
|
|
776
|
+
style: boxProps?.className ? {
|
|
777
|
+
...boxBase,
|
|
778
|
+
...boxProps.style
|
|
779
|
+
} : {
|
|
780
|
+
...boxBase,
|
|
781
|
+
...boxThemed,
|
|
782
|
+
...boxProps?.style
|
|
604
783
|
},
|
|
605
784
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
606
785
|
style: {
|
|
@@ -633,8 +812,12 @@ function DefaultDomEvent({ event, mode, isAllDay, boxHeight, ampm = false, theme
|
|
|
633
812
|
* <TimeGrid mode="week" date={new Date()} events={events} />
|
|
634
813
|
* ```
|
|
635
814
|
*/
|
|
636
|
-
function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStartsOn = 0, hourHeight: initialHourHeight = 48, scrollOffsetMinutes = 480, zoomable = true, minHourHeight = 24, maxHourHeight = 160, dragStepMinutes = 15, ampm = false, timeslots = 1, businessHours, showNowIndicator = true, showAllDayEventCell = true, locale, theme: themeOverrides, height = 600, renderEvent, hourComponent, onPressEvent, onPressDateHeader, onPressCell, onCreateEvent, onDragStart, onDragEvent, className, style }) {
|
|
815
|
+
function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStartsOn = 0, weekdayFormat = "short", hourHeight: initialHourHeight = 48, scrollOffsetMinutes = 480, zoomable = true, minHourHeight = 24, maxHourHeight = 160, dragStepMinutes = 15, ampm = false, timeslots = 1, businessHours, showNowIndicator = true, showAllDayEventCell = true, locale, theme: themeOverrides, height = 600, renderEvent, eventAccessibilityLabel, hourComponent, onPressEvent, onPressDateHeader, onPressCell, onCreateEvent, onDragStart, onDragEvent, className, style, classNames, styles }) {
|
|
637
816
|
const theme = (0, react.useMemo)(() => mergeDomTheme(themeOverrides), [themeOverrides]);
|
|
817
|
+
const slot = createSlots({
|
|
818
|
+
classNames,
|
|
819
|
+
styles
|
|
820
|
+
});
|
|
638
821
|
const scrollRef = (0, react.useRef)(null);
|
|
639
822
|
const dfns = locale ? { locale } : void 0;
|
|
640
823
|
const snapHours = dragStepMinutes / 60;
|
|
@@ -673,7 +856,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
673
856
|
const onWheel = (e) => {
|
|
674
857
|
if (!e.ctrlKey && !e.metaKey) return;
|
|
675
858
|
e.preventDefault();
|
|
676
|
-
setHourHeight((h) => clamp(h * (1 - e.deltaY * .0015), minHourHeight, maxHourHeight));
|
|
859
|
+
setHourHeight((h) => clamp$1(h * (1 - e.deltaY * .0015), minHourHeight, maxHourHeight));
|
|
677
860
|
};
|
|
678
861
|
el.addEventListener("wheel", onWheel, { passive: false });
|
|
679
862
|
return () => el.removeEventListener("wheel", onWheel);
|
|
@@ -701,7 +884,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
701
884
|
if (pinch.current.size === 2 && pinchBase.current) {
|
|
702
885
|
const ys = [...pinch.current.values()];
|
|
703
886
|
const ratio = Math.abs(ys[0] - ys[1]) / (pinchBase.current.dist || 1);
|
|
704
|
-
setHourHeight(clamp(pinchBase.current.height * ratio, minHourHeight, maxHourHeight));
|
|
887
|
+
setHourHeight(clamp$1(pinchBase.current.height * ratio, minHourHeight, maxHourHeight));
|
|
705
888
|
}
|
|
706
889
|
};
|
|
707
890
|
const onBodyPointerUp = (e) => {
|
|
@@ -740,14 +923,14 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
740
923
|
const dHours = (e.clientY - dragOrigin.current.pointerY) / hourHeightRef.current;
|
|
741
924
|
const snap = (v) => Math.round(v / snapHours) * snapHours;
|
|
742
925
|
if (d.kind === "move") {
|
|
743
|
-
const startHours = clamp(snap(dragOrigin.current.startHours + dHours), 0, 24 - d.durationHours);
|
|
926
|
+
const startHours = clamp$1(snap(dragOrigin.current.startHours + dHours), 0, 24 - d.durationHours);
|
|
744
927
|
applyDrag({
|
|
745
928
|
...d,
|
|
746
929
|
startHours,
|
|
747
930
|
moved: true
|
|
748
931
|
});
|
|
749
932
|
} else {
|
|
750
|
-
const durationHours = clamp(snap(dragOrigin.current.durationHours + dHours), snapHours, 24 - d.startHours);
|
|
933
|
+
const durationHours = clamp$1(snap(dragOrigin.current.durationHours + dHours), snapHours, 24 - d.startHours);
|
|
751
934
|
applyDrag({
|
|
752
935
|
...d,
|
|
753
936
|
durationHours,
|
|
@@ -850,10 +1033,10 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
850
1033
|
},
|
|
851
1034
|
children: [
|
|
852
1035
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
853
|
-
|
|
854
|
-
display: "flex",
|
|
855
|
-
borderBottom: `1px solid ${theme.gridLine}`
|
|
856
|
-
},
|
|
1036
|
+
...slot("header", {
|
|
1037
|
+
base: { display: "flex" },
|
|
1038
|
+
themed: { borderBottom: `1px solid ${theme.gridLine}` }
|
|
1039
|
+
}),
|
|
857
1040
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
|
|
858
1041
|
width: GUTTER_WIDTH,
|
|
859
1042
|
flex: "none"
|
|
@@ -864,63 +1047,77 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
864
1047
|
tabIndex: onPressDateHeader ? 0 : -1,
|
|
865
1048
|
"aria-hidden": onPressDateHeader ? void 0 : true,
|
|
866
1049
|
onClick: onPressDateHeader ? () => onPressDateHeader(day) : void 0,
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
1050
|
+
...dataState({ "data-today": today }),
|
|
1051
|
+
...slot("columnHeader", {
|
|
1052
|
+
base: {
|
|
1053
|
+
flex: 1,
|
|
1054
|
+
border: "none",
|
|
1055
|
+
background: "transparent",
|
|
1056
|
+
font: "inherit",
|
|
1057
|
+
cursor: onPressDateHeader ? "pointer" : "default",
|
|
1058
|
+
display: "flex",
|
|
1059
|
+
flexDirection: "column",
|
|
1060
|
+
alignItems: "center",
|
|
1061
|
+
gap: 2
|
|
1062
|
+
},
|
|
1063
|
+
themed: {
|
|
1064
|
+
color: theme.textMuted,
|
|
1065
|
+
padding: "6px 0"
|
|
1066
|
+
}
|
|
1067
|
+
}),
|
|
880
1068
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
881
|
-
|
|
1069
|
+
...slot("columnHeaderWeekday", { themed: {
|
|
882
1070
|
fontSize: 11,
|
|
883
1071
|
fontWeight: 600
|
|
884
|
-
},
|
|
885
|
-
children: (0, date_fns.format)(day,
|
|
1072
|
+
} }),
|
|
1073
|
+
children: (0, date_fns.format)(day, (0, _super_calendar_core.weekdayFormatToken)(weekdayFormat), dfns)
|
|
886
1074
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
1075
|
+
...dataState({ "data-today": today }),
|
|
1076
|
+
...slot("columnHeaderDate", {
|
|
1077
|
+
base: {
|
|
1078
|
+
width: 28,
|
|
1079
|
+
height: 28,
|
|
1080
|
+
borderRadius: "50%",
|
|
1081
|
+
display: "flex",
|
|
1082
|
+
alignItems: "center",
|
|
1083
|
+
justifyContent: "center"
|
|
1084
|
+
},
|
|
1085
|
+
themed: {
|
|
1086
|
+
fontSize: 15,
|
|
1087
|
+
fontWeight: 600,
|
|
1088
|
+
background: today ? theme.todayBackground : "transparent",
|
|
1089
|
+
color: today ? theme.todayText : theme.text
|
|
1090
|
+
}
|
|
1091
|
+
}),
|
|
899
1092
|
children: (0, date_fns.format)(day, "d", dfns)
|
|
900
1093
|
})]
|
|
901
1094
|
}, day.toISOString());
|
|
902
1095
|
})]
|
|
903
1096
|
}),
|
|
904
1097
|
showAllDayEventCell && hasAllDay ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
905
|
-
|
|
906
|
-
display: "flex",
|
|
907
|
-
borderBottom: `1px solid ${theme.gridLine}`
|
|
908
|
-
},
|
|
1098
|
+
...slot("allDayLane", {
|
|
1099
|
+
base: { display: "flex" },
|
|
1100
|
+
themed: { borderBottom: `1px solid ${theme.gridLine}` }
|
|
1101
|
+
}),
|
|
909
1102
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
1103
|
+
...slot("allDayLabel", {
|
|
1104
|
+
base: {
|
|
1105
|
+
width: GUTTER_WIDTH,
|
|
1106
|
+
flex: "none",
|
|
1107
|
+
textAlign: "right"
|
|
1108
|
+
},
|
|
1109
|
+
themed: {
|
|
1110
|
+
fontSize: 10,
|
|
1111
|
+
color: theme.textMuted,
|
|
1112
|
+
padding: "4px 6px 0 0"
|
|
1113
|
+
}
|
|
1114
|
+
}),
|
|
918
1115
|
children: "all-day"
|
|
919
1116
|
}), allDayByDay.map((list, i) => {
|
|
920
1117
|
const dayStart = (0, date_fns.startOfDay)(days[i]);
|
|
921
1118
|
const dayEnd = (0, date_fns.addDays)(dayStart, 1);
|
|
922
1119
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
923
|
-
|
|
1120
|
+
...slot("allDayColumn", { base: {
|
|
924
1121
|
flex: 1,
|
|
925
1122
|
minWidth: 0,
|
|
926
1123
|
borderLeft: "1px solid transparent",
|
|
@@ -928,7 +1125,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
928
1125
|
display: "flex",
|
|
929
1126
|
flexDirection: "column",
|
|
930
1127
|
gap: 2
|
|
931
|
-
},
|
|
1128
|
+
} }),
|
|
932
1129
|
children: list.map((event) => {
|
|
933
1130
|
const args = {
|
|
934
1131
|
event,
|
|
@@ -942,24 +1139,29 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
942
1139
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
943
1140
|
type: "button",
|
|
944
1141
|
onClick: () => onPressEvent?.(event),
|
|
945
|
-
"aria-label": (
|
|
1142
|
+
"aria-label": eventAccessibilityLabel ? eventAccessibilityLabel(event, {
|
|
1143
|
+
mode,
|
|
1144
|
+
isAllDay: true,
|
|
1145
|
+
ampm
|
|
1146
|
+
}) : (0, _super_calendar_core.eventAccessibilityLabel)({
|
|
946
1147
|
title: event.title,
|
|
947
1148
|
isAllDay: true,
|
|
948
1149
|
start: event.start,
|
|
949
1150
|
end: event.end,
|
|
950
1151
|
ampm
|
|
951
1152
|
}),
|
|
952
|
-
|
|
1153
|
+
...slot("allDayEvent", { base: {
|
|
953
1154
|
border: "none",
|
|
954
1155
|
padding: 0,
|
|
955
1156
|
background: "transparent",
|
|
956
1157
|
cursor: "pointer",
|
|
957
1158
|
textAlign: "left",
|
|
958
1159
|
height: 22
|
|
959
|
-
},
|
|
1160
|
+
} }),
|
|
960
1161
|
children: Renderer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, { ...args }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultDomEvent, {
|
|
961
1162
|
...args,
|
|
962
|
-
theme
|
|
1163
|
+
theme,
|
|
1164
|
+
boxProps: slot("eventBox")
|
|
963
1165
|
})
|
|
964
1166
|
}, `${event.start.toISOString()}:${event.title}`);
|
|
965
1167
|
})
|
|
@@ -985,19 +1187,23 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
985
1187
|
position: "relative"
|
|
986
1188
|
},
|
|
987
1189
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
988
|
-
|
|
1190
|
+
...slot("hourGutter", { base: {
|
|
989
1191
|
width: GUTTER_WIDTH,
|
|
990
1192
|
flex: "none",
|
|
991
1193
|
position: "relative"
|
|
992
|
-
},
|
|
1194
|
+
} }),
|
|
993
1195
|
children: HOURS.map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1196
|
+
...slot("hourLabel", {
|
|
1197
|
+
base: {
|
|
1198
|
+
position: "absolute",
|
|
1199
|
+
top: h * hourHeight - 6,
|
|
1200
|
+
right: 6
|
|
1201
|
+
},
|
|
1202
|
+
themed: {
|
|
1203
|
+
fontSize: 10,
|
|
1204
|
+
color: theme.textMuted
|
|
1205
|
+
}
|
|
1206
|
+
}),
|
|
1001
1207
|
children: hourComponent ? hourComponent(h, ampm) : h === 0 ? "" : (0, _super_calendar_core.formatHour)(h, { ampm })
|
|
1002
1208
|
}, h))
|
|
1003
1209
|
}), days.map((day, dayIndex) => {
|
|
@@ -1012,34 +1218,41 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1012
1218
|
onPointerMove: cellEnabled ? moveCreate : void 0,
|
|
1013
1219
|
onPointerUp: cellEnabled ? endCreate : void 0,
|
|
1014
1220
|
onPointerCancel: cellEnabled ? cancelCreate : void 0,
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1221
|
+
...dataState({ "data-today": (0, _super_calendar_core.getIsToday)(day) }),
|
|
1222
|
+
...slot("dayColumn", {
|
|
1223
|
+
base: {
|
|
1224
|
+
flex: 1,
|
|
1225
|
+
position: "relative"
|
|
1226
|
+
},
|
|
1227
|
+
themed: { borderLeft: `1px solid ${theme.gridLine}` }
|
|
1228
|
+
}),
|
|
1020
1229
|
children: [
|
|
1021
1230
|
bands.map((b) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1022
1231
|
"aria-hidden": true,
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1232
|
+
...slot("businessHours", {
|
|
1233
|
+
base: {
|
|
1234
|
+
position: "absolute",
|
|
1235
|
+
left: 0,
|
|
1236
|
+
right: 0,
|
|
1237
|
+
top: b.start * hourHeight,
|
|
1238
|
+
height: (b.end - b.start) * hourHeight,
|
|
1239
|
+
pointerEvents: "none",
|
|
1240
|
+
zIndex: 0
|
|
1241
|
+
},
|
|
1242
|
+
themed: { background: theme.outsideHoursBackground }
|
|
1243
|
+
})
|
|
1033
1244
|
}, b.start)),
|
|
1034
1245
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1035
1246
|
"aria-hidden": true,
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1247
|
+
...slot("gridLines", {
|
|
1248
|
+
base: {
|
|
1249
|
+
position: "absolute",
|
|
1250
|
+
inset: 0,
|
|
1251
|
+
pointerEvents: "none",
|
|
1252
|
+
zIndex: 0
|
|
1253
|
+
},
|
|
1254
|
+
themed: { backgroundImage: gridLines }
|
|
1255
|
+
})
|
|
1043
1256
|
}),
|
|
1044
1257
|
positioned.map((pe, idx) => {
|
|
1045
1258
|
const key = `${dayIndex}:${idx}`;
|
|
@@ -1064,7 +1277,11 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1064
1277
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1065
1278
|
role: "button",
|
|
1066
1279
|
tabIndex: 0,
|
|
1067
|
-
"aria-label": (
|
|
1280
|
+
"aria-label": eventAccessibilityLabel ? eventAccessibilityLabel(pe.event, {
|
|
1281
|
+
mode,
|
|
1282
|
+
isAllDay: false,
|
|
1283
|
+
ampm
|
|
1284
|
+
}) : (0, _super_calendar_core.eventAccessibilityLabel)({
|
|
1068
1285
|
title: pe.event.title,
|
|
1069
1286
|
isAllDay: false,
|
|
1070
1287
|
start: pe.event.start,
|
|
@@ -1082,7 +1299,8 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1082
1299
|
onPointerUp: draggable ? (e) => endDrag(e, day, pe.event, onPress) : void 0,
|
|
1083
1300
|
onPointerCancel: draggable ? cancelDrag : void 0,
|
|
1084
1301
|
onClick: draggable ? void 0 : onPress,
|
|
1085
|
-
|
|
1302
|
+
...dataState({ "data-dragging": !!active }),
|
|
1303
|
+
...slot("event", { base: {
|
|
1086
1304
|
position: "absolute",
|
|
1087
1305
|
top,
|
|
1088
1306
|
height: boxHeight,
|
|
@@ -1092,10 +1310,11 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1092
1310
|
touchAction: draggable ? "none" : "auto",
|
|
1093
1311
|
zIndex: active ? 3 : 1,
|
|
1094
1312
|
opacity: active ? .85 : 1
|
|
1095
|
-
},
|
|
1313
|
+
} }),
|
|
1096
1314
|
children: [Renderer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, { ...args }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultDomEvent, {
|
|
1097
1315
|
...args,
|
|
1098
|
-
theme
|
|
1316
|
+
theme,
|
|
1317
|
+
boxProps: slot("eventBox")
|
|
1099
1318
|
}), draggable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1100
1319
|
onPointerDown: (e) => {
|
|
1101
1320
|
e.stopPropagation();
|
|
@@ -1114,7 +1333,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1114
1333
|
}, idx);
|
|
1115
1334
|
}),
|
|
1116
1335
|
showNow ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1117
|
-
|
|
1336
|
+
...slot("nowIndicator", { base: {
|
|
1118
1337
|
position: "absolute",
|
|
1119
1338
|
top: nowTop,
|
|
1120
1339
|
left: 0,
|
|
@@ -1122,7 +1341,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1122
1341
|
height: 0,
|
|
1123
1342
|
zIndex: 2,
|
|
1124
1343
|
pointerEvents: "none"
|
|
1125
|
-
},
|
|
1344
|
+
} }),
|
|
1126
1345
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
|
|
1127
1346
|
height: 2,
|
|
1128
1347
|
background: theme.nowIndicator
|
|
@@ -1138,19 +1357,23 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1138
1357
|
}) : null,
|
|
1139
1358
|
ghost ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1140
1359
|
"aria-hidden": true,
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1360
|
+
...slot("createGhost", {
|
|
1361
|
+
base: {
|
|
1362
|
+
position: "absolute",
|
|
1363
|
+
left: 1,
|
|
1364
|
+
right: 1,
|
|
1365
|
+
top: ghost.topPx,
|
|
1366
|
+
height: Math.max(ghost.heightPx, 2),
|
|
1367
|
+
opacity: .7,
|
|
1368
|
+
pointerEvents: "none",
|
|
1369
|
+
zIndex: 2
|
|
1370
|
+
},
|
|
1371
|
+
themed: {
|
|
1372
|
+
background: theme.rangeBackground,
|
|
1373
|
+
border: `1px solid ${theme.selectedBackground}`,
|
|
1374
|
+
borderRadius: 6
|
|
1375
|
+
}
|
|
1376
|
+
})
|
|
1154
1377
|
}) : null
|
|
1155
1378
|
]
|
|
1156
1379
|
}, day.toISOString());
|
|
@@ -1173,7 +1396,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1173
1396
|
* <Calendar mode="week" date={new Date()} events={events} />
|
|
1174
1397
|
* ```
|
|
1175
1398
|
*/
|
|
1176
|
-
function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays, locale, theme, height, className, style, onPressEvent, ampm, hourHeight, scrollOffsetMinutes, timeslots, businessHours, showNowIndicator, showAllDayEventCell, dragStepMinutes, onPressCell, onCreateEvent, onDragStart, onDragEvent, onPressDateHeader, renderTimeEvent, hourComponent, maxVisibleEventCount, moreLabel, showAdjacentMonths, fillCellOnSelection, selectedRange, selectedDates, minDate, maxDate, isDateDisabled, keyboardDayNavigation, onPressDay, onPressMore, renderMonthEvent, renderScheduleEvent }) {
|
|
1399
|
+
function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays, locale, theme, height, className, style, onPressEvent, eventAccessibilityLabel, ampm, hourHeight, scrollOffsetMinutes, timeslots, businessHours, showNowIndicator, showAllDayEventCell, dragStepMinutes, onPressCell, onCreateEvent, onDragStart, onDragEvent, onPressDateHeader, renderTimeEvent, hourComponent, maxVisibleEventCount, moreLabel, showAdjacentMonths, weekdayFormat, fillCellOnSelection, selectedRange, selectedDates, minDate, maxDate, isDateDisabled, keyboardDayNavigation, onPressDay, onPressMore, renderMonthEvent, renderScheduleEvent, classNames, styles }) {
|
|
1177
1400
|
if (mode === "schedule") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Agenda, {
|
|
1178
1401
|
events: events ?? [],
|
|
1179
1402
|
locale,
|
|
@@ -1183,7 +1406,10 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1183
1406
|
activeDate: date,
|
|
1184
1407
|
className,
|
|
1185
1408
|
style,
|
|
1409
|
+
classNames,
|
|
1410
|
+
styles,
|
|
1186
1411
|
renderEvent: renderScheduleEvent,
|
|
1412
|
+
eventAccessibilityLabel,
|
|
1187
1413
|
onPressEvent,
|
|
1188
1414
|
onPressDay
|
|
1189
1415
|
});
|
|
@@ -1191,10 +1417,13 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1191
1417
|
date,
|
|
1192
1418
|
events: events ?? [],
|
|
1193
1419
|
weekStartsOn,
|
|
1420
|
+
weekdayFormat,
|
|
1194
1421
|
locale,
|
|
1195
1422
|
theme,
|
|
1196
1423
|
className,
|
|
1197
1424
|
style,
|
|
1425
|
+
classNames,
|
|
1426
|
+
styles,
|
|
1198
1427
|
maxVisibleEventCount,
|
|
1199
1428
|
moreLabel,
|
|
1200
1429
|
showAdjacentMonths,
|
|
@@ -1206,21 +1435,26 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1206
1435
|
isDateDisabled,
|
|
1207
1436
|
keyboardDayNavigation,
|
|
1208
1437
|
onPressDay,
|
|
1438
|
+
onCreateEvent,
|
|
1209
1439
|
onPressEvent,
|
|
1210
1440
|
onPressMore,
|
|
1211
|
-
renderEvent: renderMonthEvent
|
|
1441
|
+
renderEvent: renderMonthEvent,
|
|
1442
|
+
eventAccessibilityLabel
|
|
1212
1443
|
});
|
|
1213
1444
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimeGrid, {
|
|
1214
1445
|
date,
|
|
1215
1446
|
mode,
|
|
1216
1447
|
events,
|
|
1217
1448
|
weekStartsOn,
|
|
1449
|
+
weekdayFormat,
|
|
1218
1450
|
numberOfDays,
|
|
1219
1451
|
locale,
|
|
1220
1452
|
theme,
|
|
1221
1453
|
height,
|
|
1222
1454
|
className,
|
|
1223
1455
|
style,
|
|
1456
|
+
classNames,
|
|
1457
|
+
styles,
|
|
1224
1458
|
ampm,
|
|
1225
1459
|
hourHeight,
|
|
1226
1460
|
scrollOffsetMinutes,
|
|
@@ -1236,6 +1470,7 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1236
1470
|
onDragEvent,
|
|
1237
1471
|
onPressDateHeader,
|
|
1238
1472
|
renderEvent: renderTimeEvent,
|
|
1473
|
+
eventAccessibilityLabel,
|
|
1239
1474
|
hourComponent
|
|
1240
1475
|
});
|
|
1241
1476
|
}
|
|
@@ -1246,8 +1481,12 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1246
1481
|
* Legend List's DOM renderer and the library's headless grid logic. Selection is
|
|
1247
1482
|
* controlled, pass `selectedRange` (or `selectedDates`) and handle `onPressDay`.
|
|
1248
1483
|
*/
|
|
1249
|
-
function MonthList({ date, pastMonths = 1, futureMonths = 12, weekStartsOn = 0, events, renderEvent, maxVisibleEventCount, moreLabel, onPressEvent, onPressMore, selectedRange, selectedDates, fillCellOnSelection = false, locale, theme: themeOverrides, height = 480, minDate, maxDate, isDateDisabled, keyboardDayNavigation, onPressDay, className, style }) {
|
|
1484
|
+
function MonthList({ date, pastMonths = 1, futureMonths = 12, weekdayFormat = "short", weekStartsOn = 0, events, renderEvent, eventAccessibilityLabel, maxVisibleEventCount, moreLabel, onPressEvent, onPressMore, selectedRange, selectedDates, fillCellOnSelection = false, locale, theme: themeOverrides, height = 480, minDate, maxDate, isDateDisabled, keyboardDayNavigation, onPressDay, className, style, classNames, styles }) {
|
|
1250
1485
|
const theme = (0, react.useMemo)(() => mergeDomTheme(themeOverrides), [themeOverrides]);
|
|
1486
|
+
const slot = createSlots({
|
|
1487
|
+
classNames,
|
|
1488
|
+
styles
|
|
1489
|
+
});
|
|
1251
1490
|
const months = (0, react.useMemo)(() => {
|
|
1252
1491
|
const first = (0, date_fns.startOfMonth)((0, date_fns.addMonths)(date, -pastMonths));
|
|
1253
1492
|
const count = pastMonths + futureMonths + 1;
|
|
@@ -1259,10 +1498,12 @@ function MonthList({ date, pastMonths = 1, futureMonths = 12, weekStartsOn = 0,
|
|
|
1259
1498
|
]);
|
|
1260
1499
|
const weekdays = (0, react.useMemo)(() => (0, _super_calendar_core.buildMonthGrid)(date, {
|
|
1261
1500
|
weekStartsOn,
|
|
1501
|
+
weekdayFormat,
|
|
1262
1502
|
locale
|
|
1263
1503
|
}).weekdays, [
|
|
1264
1504
|
date,
|
|
1265
1505
|
weekStartsOn,
|
|
1506
|
+
weekdayFormat,
|
|
1266
1507
|
locale
|
|
1267
1508
|
]);
|
|
1268
1509
|
const eventsByDay = (0, react.useMemo)(() => {
|
|
@@ -1288,19 +1529,23 @@ function MonthList({ date, pastMonths = 1, futureMonths = 12, weekStartsOn = 0,
|
|
|
1288
1529
|
...style
|
|
1289
1530
|
},
|
|
1290
1531
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1532
|
+
...slot("weekdays", {
|
|
1533
|
+
base: {
|
|
1534
|
+
display: "grid",
|
|
1535
|
+
gridTemplateColumns: "repeat(7, minmax(0, 1fr))"
|
|
1536
|
+
},
|
|
1537
|
+
themed: {
|
|
1538
|
+
borderBottom: `1px solid ${theme.gridLine}`,
|
|
1539
|
+
padding: "8px 0"
|
|
1540
|
+
}
|
|
1541
|
+
}),
|
|
1297
1542
|
children: weekdays.map((wd) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1298
|
-
|
|
1543
|
+
...slot("weekday", { themed: {
|
|
1299
1544
|
textAlign: "center",
|
|
1300
1545
|
fontSize: 12,
|
|
1301
1546
|
fontWeight: 600,
|
|
1302
1547
|
color: theme.textMuted
|
|
1303
|
-
},
|
|
1548
|
+
} }),
|
|
1304
1549
|
children: wd.label
|
|
1305
1550
|
}, wd.label))
|
|
1306
1551
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react.LegendList, {
|
|
@@ -1320,6 +1565,7 @@ function MonthList({ date, pastMonths = 1, futureMonths = 12, weekStartsOn = 0,
|
|
|
1320
1565
|
events,
|
|
1321
1566
|
eventsByDay,
|
|
1322
1567
|
renderEvent,
|
|
1568
|
+
eventAccessibilityLabel,
|
|
1323
1569
|
maxVisibleEventCount,
|
|
1324
1570
|
moreLabel,
|
|
1325
1571
|
onPressEvent,
|
|
@@ -1335,16 +1581,571 @@ function MonthList({ date, pastMonths = 1, futureMonths = 12, weekStartsOn = 0,
|
|
|
1335
1581
|
maxDate,
|
|
1336
1582
|
isDateDisabled,
|
|
1337
1583
|
keyboardDayNavigation,
|
|
1338
|
-
onPressDay
|
|
1584
|
+
onPressDay,
|
|
1585
|
+
classNames,
|
|
1586
|
+
styles
|
|
1587
|
+
})
|
|
1588
|
+
})]
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
//#endregion
|
|
1592
|
+
//#region src/DateRangePicker.tsx
|
|
1593
|
+
const triggerDefault = {
|
|
1594
|
+
display: "inline-flex",
|
|
1595
|
+
alignItems: "center",
|
|
1596
|
+
justifyContent: "space-between",
|
|
1597
|
+
gap: 8,
|
|
1598
|
+
minWidth: 220,
|
|
1599
|
+
padding: "8px 12px",
|
|
1600
|
+
borderRadius: 8,
|
|
1601
|
+
cursor: "pointer",
|
|
1602
|
+
font: "inherit",
|
|
1603
|
+
textAlign: "left"
|
|
1604
|
+
};
|
|
1605
|
+
const popoverDefault = {
|
|
1606
|
+
position: "absolute",
|
|
1607
|
+
zIndex: 20,
|
|
1608
|
+
marginTop: 6,
|
|
1609
|
+
overflow: "hidden",
|
|
1610
|
+
borderRadius: 12,
|
|
1611
|
+
minWidth: 300
|
|
1612
|
+
};
|
|
1613
|
+
/**
|
|
1614
|
+
* The shared popover shell: a trigger button and a calendar panel that closes on
|
|
1615
|
+
* outside-click and Escape, and returns focus to the trigger. `renderCalendar`
|
|
1616
|
+
* gets a close callback so a single-date pick can dismiss immediately.
|
|
1617
|
+
*/
|
|
1618
|
+
function usePopover() {
|
|
1619
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
1620
|
+
const rootRef = (0, react.useRef)(null);
|
|
1621
|
+
const triggerRef = (0, react.useRef)(null);
|
|
1622
|
+
(0, react.useEffect)(() => {
|
|
1623
|
+
if (!open) return;
|
|
1624
|
+
const onDown = (e) => {
|
|
1625
|
+
if (!rootRef.current?.contains(e.target)) setOpen(false);
|
|
1626
|
+
};
|
|
1627
|
+
const onKey = (e) => {
|
|
1628
|
+
if (e.key === "Escape") {
|
|
1629
|
+
setOpen(false);
|
|
1630
|
+
triggerRef.current?.focus();
|
|
1631
|
+
}
|
|
1632
|
+
};
|
|
1633
|
+
document.addEventListener("mousedown", onDown);
|
|
1634
|
+
document.addEventListener("keydown", onKey);
|
|
1635
|
+
return () => {
|
|
1636
|
+
document.removeEventListener("mousedown", onDown);
|
|
1637
|
+
document.removeEventListener("keydown", onKey);
|
|
1638
|
+
};
|
|
1639
|
+
}, [open]);
|
|
1640
|
+
return {
|
|
1641
|
+
open,
|
|
1642
|
+
setOpen,
|
|
1643
|
+
rootRef,
|
|
1644
|
+
triggerRef
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1647
|
+
function PickerShell({ open, setOpen, rootRef, triggerRef, theme, slot, label, hasValue, placeholder, disabled, className, style, ariaLabel, children }) {
|
|
1648
|
+
const dialogId = (0, react.useId)();
|
|
1649
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1650
|
+
ref: rootRef,
|
|
1651
|
+
className,
|
|
1652
|
+
style: {
|
|
1653
|
+
position: "relative",
|
|
1654
|
+
display: "inline-block",
|
|
1655
|
+
fontFamily: theme.fontFamily,
|
|
1656
|
+
...style
|
|
1657
|
+
},
|
|
1658
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1659
|
+
ref: triggerRef,
|
|
1660
|
+
type: "button",
|
|
1661
|
+
disabled,
|
|
1662
|
+
"aria-haspopup": "dialog",
|
|
1663
|
+
"aria-expanded": open,
|
|
1664
|
+
"aria-controls": open ? dialogId : void 0,
|
|
1665
|
+
onClick: () => setOpen(!open),
|
|
1666
|
+
...slot("trigger", {
|
|
1667
|
+
base: triggerDefault,
|
|
1668
|
+
themed: {
|
|
1669
|
+
border: `1px solid ${theme.gridLine}`,
|
|
1670
|
+
background: theme.eventBackground,
|
|
1671
|
+
color: hasValue ? theme.text : theme.textMuted,
|
|
1672
|
+
opacity: disabled ? .5 : 1
|
|
1673
|
+
}
|
|
1674
|
+
}),
|
|
1675
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: hasValue ? label : placeholder }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1676
|
+
"aria-hidden": true,
|
|
1677
|
+
children: "▾"
|
|
1678
|
+
})]
|
|
1679
|
+
}), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1680
|
+
id: dialogId,
|
|
1681
|
+
role: "dialog",
|
|
1682
|
+
"aria-label": ariaLabel,
|
|
1683
|
+
...slot("popover", {
|
|
1684
|
+
base: popoverDefault,
|
|
1685
|
+
themed: {
|
|
1686
|
+
background: theme.eventBackground,
|
|
1687
|
+
border: `1px solid ${theme.gridLine}`
|
|
1688
|
+
}
|
|
1689
|
+
}),
|
|
1690
|
+
children
|
|
1691
|
+
}) : null]
|
|
1692
|
+
});
|
|
1693
|
+
}
|
|
1694
|
+
/**
|
|
1695
|
+
* A single-date input with a popover calendar. Controlled via `value` / `onChange`.
|
|
1696
|
+
* Composed from {@link MonthList}; forward calendar slots (e.g. `dayBadge`) through
|
|
1697
|
+
* `classNames` to restyle the popover.
|
|
1698
|
+
*
|
|
1699
|
+
* @example
|
|
1700
|
+
* ```tsx
|
|
1701
|
+
* const [value, setValue] = useState<Date | null>(null);
|
|
1702
|
+
* <DatePicker value={value} onChange={setValue} />
|
|
1703
|
+
* ```
|
|
1704
|
+
*/
|
|
1705
|
+
function DatePicker({ value, onChange, formatLabel = (d) => (0, date_fns.format)(d, "d MMM yyyy"), weekStartsOn = 0, height = 320, placeholder = "Select a date", disabled, theme: themeOverrides, className, style, classNames, styles, minDate, maxDate, isDateDisabled }) {
|
|
1706
|
+
const theme = mergeDomTheme(themeOverrides);
|
|
1707
|
+
const slot = createSlots({
|
|
1708
|
+
classNames,
|
|
1709
|
+
styles
|
|
1710
|
+
});
|
|
1711
|
+
const { open, setOpen, rootRef, triggerRef } = usePopover();
|
|
1712
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PickerShell, {
|
|
1713
|
+
open,
|
|
1714
|
+
setOpen,
|
|
1715
|
+
rootRef,
|
|
1716
|
+
triggerRef,
|
|
1717
|
+
theme,
|
|
1718
|
+
slot,
|
|
1719
|
+
label: value ? formatLabel(value) : "",
|
|
1720
|
+
hasValue: !!value,
|
|
1721
|
+
placeholder,
|
|
1722
|
+
disabled,
|
|
1723
|
+
className,
|
|
1724
|
+
style,
|
|
1725
|
+
ariaLabel: "Choose a date",
|
|
1726
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MonthList, {
|
|
1727
|
+
date: value ?? /* @__PURE__ */ new Date(),
|
|
1728
|
+
weekStartsOn,
|
|
1729
|
+
selectedDates: value ? [value] : [],
|
|
1730
|
+
minDate,
|
|
1731
|
+
maxDate,
|
|
1732
|
+
isDateDisabled,
|
|
1733
|
+
onPressDay: (day) => {
|
|
1734
|
+
onChange(day);
|
|
1735
|
+
setOpen(false);
|
|
1736
|
+
triggerRef.current?.focus();
|
|
1737
|
+
},
|
|
1738
|
+
height,
|
|
1739
|
+
classNames,
|
|
1740
|
+
styles
|
|
1741
|
+
})
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1744
|
+
function defaultRangeLabel(range) {
|
|
1745
|
+
const start = (0, date_fns.format)(range.start, "d MMM yyyy");
|
|
1746
|
+
return range.end ? `${start} – ${(0, date_fns.format)(range.end, "d MMM yyyy")}` : `${start} – …`;
|
|
1747
|
+
}
|
|
1748
|
+
/**
|
|
1749
|
+
* A date-range input with a popover calendar. Controlled via `value` / `onChange`;
|
|
1750
|
+
* each pick advances the range through {@link nextDateRange} (start, then end), and
|
|
1751
|
+
* the popover closes once both ends are set.
|
|
1752
|
+
*
|
|
1753
|
+
* @example
|
|
1754
|
+
* ```tsx
|
|
1755
|
+
* const [range, setRange] = useState<DateRange | null>(null);
|
|
1756
|
+
* <DateRangePicker value={range} onChange={setRange} />
|
|
1757
|
+
* ```
|
|
1758
|
+
*/
|
|
1759
|
+
function DateRangePicker({ value, onChange, formatLabel = defaultRangeLabel, weekStartsOn = 0, height = 320, placeholder = "Select dates", disabled, theme: themeOverrides, className, style, classNames, styles, minDate, maxDate, isDateDisabled }) {
|
|
1760
|
+
const theme = mergeDomTheme(themeOverrides);
|
|
1761
|
+
const slot = createSlots({
|
|
1762
|
+
classNames,
|
|
1763
|
+
styles
|
|
1764
|
+
});
|
|
1765
|
+
const { open, setOpen, rootRef, triggerRef } = usePopover();
|
|
1766
|
+
const constraints = {
|
|
1767
|
+
minDate,
|
|
1768
|
+
maxDate,
|
|
1769
|
+
isDateDisabled
|
|
1770
|
+
};
|
|
1771
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(PickerShell, {
|
|
1772
|
+
open,
|
|
1773
|
+
setOpen,
|
|
1774
|
+
rootRef,
|
|
1775
|
+
triggerRef,
|
|
1776
|
+
theme,
|
|
1777
|
+
slot,
|
|
1778
|
+
label: value ? formatLabel(value) : "",
|
|
1779
|
+
hasValue: !!value,
|
|
1780
|
+
placeholder,
|
|
1781
|
+
disabled,
|
|
1782
|
+
className,
|
|
1783
|
+
style,
|
|
1784
|
+
ariaLabel: "Choose a date range",
|
|
1785
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MonthList, {
|
|
1786
|
+
date: value?.start ?? /* @__PURE__ */ new Date(),
|
|
1787
|
+
weekStartsOn,
|
|
1788
|
+
selectedRange: value ?? void 0,
|
|
1789
|
+
minDate,
|
|
1790
|
+
maxDate,
|
|
1791
|
+
isDateDisabled,
|
|
1792
|
+
onPressDay: (day) => {
|
|
1793
|
+
const next = (0, _super_calendar_core.nextDateRange)(value, day, constraints);
|
|
1794
|
+
onChange(next);
|
|
1795
|
+
if (next?.end) {
|
|
1796
|
+
setOpen(false);
|
|
1797
|
+
triggerRef.current?.focus();
|
|
1798
|
+
}
|
|
1799
|
+
},
|
|
1800
|
+
height,
|
|
1801
|
+
classNames,
|
|
1802
|
+
styles
|
|
1803
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1804
|
+
...slot("footer", {
|
|
1805
|
+
base: {
|
|
1806
|
+
display: "flex",
|
|
1807
|
+
justifyContent: "flex-end",
|
|
1808
|
+
padding: "8px 10px"
|
|
1809
|
+
},
|
|
1810
|
+
themed: { borderTop: `1px solid ${theme.gridLine}` }
|
|
1811
|
+
}),
|
|
1812
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1813
|
+
type: "button",
|
|
1814
|
+
onClick: () => onChange(null),
|
|
1815
|
+
...slot("clear", {
|
|
1816
|
+
base: {
|
|
1817
|
+
border: "none",
|
|
1818
|
+
background: "transparent",
|
|
1819
|
+
cursor: "pointer",
|
|
1820
|
+
font: "inherit"
|
|
1821
|
+
},
|
|
1822
|
+
themed: { color: theme.textMuted }
|
|
1823
|
+
}),
|
|
1824
|
+
children: "Clear"
|
|
1339
1825
|
})
|
|
1340
1826
|
})]
|
|
1341
1827
|
});
|
|
1342
1828
|
}
|
|
1343
1829
|
//#endregion
|
|
1830
|
+
//#region src/ResourceTimeline.tsx
|
|
1831
|
+
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
1832
|
+
function DefaultBar({ event, boxProps, theme }) {
|
|
1833
|
+
const time = (0, _super_calendar_core.eventTimeLabel)({
|
|
1834
|
+
mode: "day",
|
|
1835
|
+
isAllDay: false,
|
|
1836
|
+
start: event.start,
|
|
1837
|
+
end: event.end,
|
|
1838
|
+
ampm: false,
|
|
1839
|
+
showTime: true
|
|
1840
|
+
});
|
|
1841
|
+
const base = {
|
|
1842
|
+
height: "100%",
|
|
1843
|
+
boxSizing: "border-box",
|
|
1844
|
+
overflow: "hidden"
|
|
1845
|
+
};
|
|
1846
|
+
const themed = {
|
|
1847
|
+
padding: "2px 6px",
|
|
1848
|
+
borderRadius: 6,
|
|
1849
|
+
background: theme.eventBackground,
|
|
1850
|
+
color: theme.eventText,
|
|
1851
|
+
fontSize: 12
|
|
1852
|
+
};
|
|
1853
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1854
|
+
className: boxProps.className,
|
|
1855
|
+
"data-slot": boxProps["data-slot"],
|
|
1856
|
+
style: boxProps.className ? {
|
|
1857
|
+
...base,
|
|
1858
|
+
...boxProps.style
|
|
1859
|
+
} : {
|
|
1860
|
+
...base,
|
|
1861
|
+
...themed,
|
|
1862
|
+
...boxProps.style
|
|
1863
|
+
},
|
|
1864
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1865
|
+
style: {
|
|
1866
|
+
fontWeight: 600,
|
|
1867
|
+
whiteSpace: "nowrap",
|
|
1868
|
+
overflow: "hidden",
|
|
1869
|
+
textOverflow: "ellipsis"
|
|
1870
|
+
},
|
|
1871
|
+
children: event.title
|
|
1872
|
+
}), time ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1873
|
+
style: {
|
|
1874
|
+
opacity: .75,
|
|
1875
|
+
fontSize: 11
|
|
1876
|
+
},
|
|
1877
|
+
children: time
|
|
1878
|
+
}) : null]
|
|
1879
|
+
});
|
|
1880
|
+
}
|
|
1881
|
+
/**
|
|
1882
|
+
* A horizontal resource timeline: rows are resources (rooms, people, machines)
|
|
1883
|
+
* and the x-axis is one day's hours. Events sit in their resource's row, and
|
|
1884
|
+
* overlapping events in the same row stack into sub-lanes (via the shared
|
|
1885
|
+
* `layoutDayEvents`). Pass `onDragEvent` to enable drag-to-move and edge-resize
|
|
1886
|
+
* along the axis.
|
|
1887
|
+
*
|
|
1888
|
+
* @example
|
|
1889
|
+
* ```tsx
|
|
1890
|
+
* <ResourceTimeline
|
|
1891
|
+
* date={new Date()}
|
|
1892
|
+
* resources={[{ id: "a", title: "Room A" }, { id: "b", title: "Room B" }]}
|
|
1893
|
+
* events={events} // each event carries a `resourceId`
|
|
1894
|
+
* />
|
|
1895
|
+
* ```
|
|
1896
|
+
*/
|
|
1897
|
+
function ResourceTimeline({ date, resources, events, resourceId = (event) => event.resourceId, startHour = 0, endHour = 24, hourWidth = 80, rowHeight = 56, labelWidth = 140, ampm = false, theme: themeOverrides, renderEvent, onPressEvent, onDragEvent, dragStepMinutes = 15, className, style, classNames, styles }) {
|
|
1898
|
+
const theme = (0, react.useMemo)(() => mergeDomTheme(themeOverrides), [themeOverrides]);
|
|
1899
|
+
const slot = createSlots({
|
|
1900
|
+
classNames,
|
|
1901
|
+
styles
|
|
1902
|
+
});
|
|
1903
|
+
const Renderer = renderEvent;
|
|
1904
|
+
const snapHours = dragStepMinutes / 60;
|
|
1905
|
+
const [drag, setDrag] = (0, react.useState)(null);
|
|
1906
|
+
const dragRef = (0, react.useRef)(null);
|
|
1907
|
+
const origin = (0, react.useRef)(null);
|
|
1908
|
+
const applyDrag = (next) => {
|
|
1909
|
+
dragRef.current = next;
|
|
1910
|
+
setDrag(next);
|
|
1911
|
+
};
|
|
1912
|
+
const beginDrag = (e, key, kind, startHours, durationHours) => {
|
|
1913
|
+
if (!onDragEvent) return;
|
|
1914
|
+
e.stopPropagation();
|
|
1915
|
+
try {
|
|
1916
|
+
e.target.setPointerCapture?.(e.pointerId);
|
|
1917
|
+
} catch {}
|
|
1918
|
+
origin.current = {
|
|
1919
|
+
x: e.clientX,
|
|
1920
|
+
startHours,
|
|
1921
|
+
durationHours
|
|
1922
|
+
};
|
|
1923
|
+
applyDrag({
|
|
1924
|
+
key,
|
|
1925
|
+
kind,
|
|
1926
|
+
startHours,
|
|
1927
|
+
durationHours,
|
|
1928
|
+
moved: false
|
|
1929
|
+
});
|
|
1930
|
+
};
|
|
1931
|
+
const moveDrag = (e) => {
|
|
1932
|
+
const d = dragRef.current;
|
|
1933
|
+
if (!d || !origin.current) return;
|
|
1934
|
+
const dHours = (e.clientX - origin.current.x) / hourWidth;
|
|
1935
|
+
const snap = (v) => Math.round(v / snapHours) * snapHours;
|
|
1936
|
+
if (d.kind === "move") {
|
|
1937
|
+
const startHours = clamp(snap(origin.current.startHours + dHours), startHour, endHour - d.durationHours);
|
|
1938
|
+
applyDrag({
|
|
1939
|
+
...d,
|
|
1940
|
+
startHours,
|
|
1941
|
+
moved: true
|
|
1942
|
+
});
|
|
1943
|
+
} else {
|
|
1944
|
+
const durationHours = clamp(snap(origin.current.durationHours + dHours), snapHours, endHour - d.startHours);
|
|
1945
|
+
applyDrag({
|
|
1946
|
+
...d,
|
|
1947
|
+
durationHours,
|
|
1948
|
+
moved: true
|
|
1949
|
+
});
|
|
1950
|
+
}
|
|
1951
|
+
};
|
|
1952
|
+
const endDrag = (e, event, onPress) => {
|
|
1953
|
+
const d = dragRef.current;
|
|
1954
|
+
if (!d) return;
|
|
1955
|
+
try {
|
|
1956
|
+
e.target.releasePointerCapture?.(e.pointerId);
|
|
1957
|
+
} catch {}
|
|
1958
|
+
if (!d.moved) {
|
|
1959
|
+
applyDrag(null);
|
|
1960
|
+
onPress();
|
|
1961
|
+
return;
|
|
1962
|
+
}
|
|
1963
|
+
const base = (0, date_fns.startOfDay)(date);
|
|
1964
|
+
const start = (0, date_fns.addMinutes)(base, Math.round(d.startHours * 60));
|
|
1965
|
+
const end = (0, date_fns.addMinutes)(base, Math.round((d.startHours + d.durationHours) * 60));
|
|
1966
|
+
onDragEvent?.(event, start, end);
|
|
1967
|
+
applyDrag(null);
|
|
1968
|
+
origin.current = null;
|
|
1969
|
+
};
|
|
1970
|
+
const cancelDrag = () => {
|
|
1971
|
+
applyDrag(null);
|
|
1972
|
+
origin.current = null;
|
|
1973
|
+
};
|
|
1974
|
+
const hours = (0, react.useMemo)(() => Array.from({ length: Math.max(0, endHour - startHour) }, (_, i) => startHour + i), [startHour, endHour]);
|
|
1975
|
+
const trackWidth = (endHour - startHour) * hourWidth;
|
|
1976
|
+
const byResource = (0, react.useMemo)(() => {
|
|
1977
|
+
const map = /* @__PURE__ */ new Map();
|
|
1978
|
+
for (const resource of resources) {
|
|
1979
|
+
const own = events.filter((e) => resourceId(e) === resource.id);
|
|
1980
|
+
map.set(resource.id, (0, _super_calendar_core.layoutDayEvents)(own, date));
|
|
1981
|
+
}
|
|
1982
|
+
return map;
|
|
1983
|
+
}, [
|
|
1984
|
+
resources,
|
|
1985
|
+
events,
|
|
1986
|
+
resourceId,
|
|
1987
|
+
date
|
|
1988
|
+
]);
|
|
1989
|
+
const gridLines = `repeating-linear-gradient(to right, transparent 0, transparent ${hourWidth - 1}px, ${theme.gridLine} ${hourWidth - 1}px, ${theme.gridLine} ${hourWidth}px)`;
|
|
1990
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1991
|
+
className,
|
|
1992
|
+
style: {
|
|
1993
|
+
fontFamily: theme.fontFamily,
|
|
1994
|
+
color: theme.text,
|
|
1995
|
+
overflowX: "auto",
|
|
1996
|
+
...style
|
|
1997
|
+
},
|
|
1998
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1999
|
+
style: { minWidth: labelWidth + trackWidth },
|
|
2000
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2001
|
+
...slot("header", {
|
|
2002
|
+
base: { display: "flex" },
|
|
2003
|
+
themed: { borderBottom: `1px solid ${theme.gridLine}` }
|
|
2004
|
+
}),
|
|
2005
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { ...slot("corner", { base: {
|
|
2006
|
+
width: labelWidth,
|
|
2007
|
+
flex: "none"
|
|
2008
|
+
} }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2009
|
+
...slot("timeAxis", { base: {
|
|
2010
|
+
position: "relative",
|
|
2011
|
+
height: 24,
|
|
2012
|
+
width: trackWidth
|
|
2013
|
+
} }),
|
|
2014
|
+
children: hours.map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2015
|
+
...slot("hourTick", {
|
|
2016
|
+
base: {
|
|
2017
|
+
position: "absolute",
|
|
2018
|
+
left: (h - startHour) * hourWidth,
|
|
2019
|
+
top: 4
|
|
2020
|
+
},
|
|
2021
|
+
themed: {
|
|
2022
|
+
fontSize: 10,
|
|
2023
|
+
color: theme.textMuted
|
|
2024
|
+
}
|
|
2025
|
+
}),
|
|
2026
|
+
children: (0, _super_calendar_core.formatHour)(h, { ampm })
|
|
2027
|
+
}, h))
|
|
2028
|
+
})]
|
|
2029
|
+
}), resources.map((resource) => {
|
|
2030
|
+
const positioned = byResource.get(resource.id) ?? [];
|
|
2031
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2032
|
+
...slot("row", {
|
|
2033
|
+
base: {
|
|
2034
|
+
display: "flex",
|
|
2035
|
+
height: rowHeight
|
|
2036
|
+
},
|
|
2037
|
+
themed: { borderBottom: `1px solid ${theme.gridLine}` }
|
|
2038
|
+
}),
|
|
2039
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2040
|
+
...slot("resourceLabel", {
|
|
2041
|
+
base: {
|
|
2042
|
+
width: labelWidth,
|
|
2043
|
+
flex: "none",
|
|
2044
|
+
display: "flex",
|
|
2045
|
+
alignItems: "center",
|
|
2046
|
+
padding: "0 10px",
|
|
2047
|
+
boxSizing: "border-box"
|
|
2048
|
+
},
|
|
2049
|
+
themed: {
|
|
2050
|
+
fontSize: 13,
|
|
2051
|
+
fontWeight: 600,
|
|
2052
|
+
borderRight: `1px solid ${theme.gridLine}`
|
|
2053
|
+
}
|
|
2054
|
+
}),
|
|
2055
|
+
children: resource.title ?? resource.id
|
|
2056
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2057
|
+
...slot("track", { base: {
|
|
2058
|
+
position: "relative",
|
|
2059
|
+
width: trackWidth
|
|
2060
|
+
} }),
|
|
2061
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2062
|
+
"aria-hidden": true,
|
|
2063
|
+
...slot("gridLines", {
|
|
2064
|
+
base: {
|
|
2065
|
+
position: "absolute",
|
|
2066
|
+
inset: 0,
|
|
2067
|
+
pointerEvents: "none"
|
|
2068
|
+
},
|
|
2069
|
+
themed: { backgroundImage: gridLines }
|
|
2070
|
+
})
|
|
2071
|
+
}), positioned.map((pe, idx) => {
|
|
2072
|
+
const key = `${resource.id}:${idx}`;
|
|
2073
|
+
const active = drag?.key === key ? drag : null;
|
|
2074
|
+
const startH = active ? active.startHours : pe.startHours;
|
|
2075
|
+
const durH = active ? active.durationHours : pe.durationHours;
|
|
2076
|
+
const left = clamp(startH - startHour, 0, endHour - startHour) * hourWidth;
|
|
2077
|
+
const right = clamp(startH + durH - startHour, 0, endHour - startHour) * hourWidth;
|
|
2078
|
+
const width = Math.max(right - left, 2);
|
|
2079
|
+
const laneHeight = rowHeight / pe.columns;
|
|
2080
|
+
const onPress = () => onPressEvent?.(pe.event);
|
|
2081
|
+
const args = {
|
|
2082
|
+
event: pe.event,
|
|
2083
|
+
width,
|
|
2084
|
+
onPress
|
|
2085
|
+
};
|
|
2086
|
+
const draggable = !!onDragEvent;
|
|
2087
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2088
|
+
type: "button",
|
|
2089
|
+
onClick: draggable ? void 0 : onPress,
|
|
2090
|
+
"aria-label": pe.event.title,
|
|
2091
|
+
...dataState({ "data-dragging": !!active }),
|
|
2092
|
+
onPointerDown: draggable ? (e) => beginDrag(e, key, "move", pe.startHours, pe.durationHours) : void 0,
|
|
2093
|
+
onPointerMove: draggable ? moveDrag : void 0,
|
|
2094
|
+
onPointerUp: draggable ? (e) => endDrag(e, pe.event, onPress) : void 0,
|
|
2095
|
+
onPointerCancel: draggable ? cancelDrag : void 0,
|
|
2096
|
+
...slot("event", { base: {
|
|
2097
|
+
position: "absolute",
|
|
2098
|
+
left,
|
|
2099
|
+
width,
|
|
2100
|
+
top: pe.column * laneHeight,
|
|
2101
|
+
height: laneHeight,
|
|
2102
|
+
padding: 1,
|
|
2103
|
+
border: "none",
|
|
2104
|
+
background: "transparent",
|
|
2105
|
+
cursor: draggable ? "grab" : "pointer",
|
|
2106
|
+
touchAction: draggable ? "none" : "auto",
|
|
2107
|
+
font: "inherit",
|
|
2108
|
+
textAlign: "left",
|
|
2109
|
+
boxSizing: "border-box",
|
|
2110
|
+
zIndex: active ? 3 : 1,
|
|
2111
|
+
opacity: active ? .85 : 1
|
|
2112
|
+
} }),
|
|
2113
|
+
children: [Renderer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, { ...args }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultBar, {
|
|
2114
|
+
...args,
|
|
2115
|
+
theme,
|
|
2116
|
+
boxProps: slot("eventBox")
|
|
2117
|
+
}), draggable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2118
|
+
"aria-hidden": true,
|
|
2119
|
+
onPointerDown: (e) => {
|
|
2120
|
+
e.stopPropagation();
|
|
2121
|
+
beginDrag(e, key, "resize", pe.startHours, pe.durationHours);
|
|
2122
|
+
},
|
|
2123
|
+
style: {
|
|
2124
|
+
position: "absolute",
|
|
2125
|
+
top: 0,
|
|
2126
|
+
bottom: 0,
|
|
2127
|
+
right: 0,
|
|
2128
|
+
width: 8,
|
|
2129
|
+
cursor: "ew-resize",
|
|
2130
|
+
touchAction: "none"
|
|
2131
|
+
}
|
|
2132
|
+
}) : null]
|
|
2133
|
+
}, idx);
|
|
2134
|
+
})]
|
|
2135
|
+
})]
|
|
2136
|
+
}, resource.id);
|
|
2137
|
+
})]
|
|
2138
|
+
})
|
|
2139
|
+
});
|
|
2140
|
+
}
|
|
2141
|
+
//#endregion
|
|
1344
2142
|
exports.Agenda = Agenda;
|
|
1345
2143
|
exports.Calendar = Calendar;
|
|
2144
|
+
exports.DatePicker = DatePicker;
|
|
2145
|
+
exports.DateRangePicker = DateRangePicker;
|
|
1346
2146
|
exports.MonthList = MonthList;
|
|
1347
2147
|
exports.MonthView = MonthView;
|
|
2148
|
+
exports.ResourceTimeline = ResourceTimeline;
|
|
1348
2149
|
exports.TimeGrid = TimeGrid;
|
|
1349
2150
|
Object.defineProperty(exports, "buildMonthGrid", {
|
|
1350
2151
|
enumerable: true,
|
|
@@ -1360,6 +2161,12 @@ Object.defineProperty(exports, "daySelectionState", {
|
|
|
1360
2161
|
}
|
|
1361
2162
|
});
|
|
1362
2163
|
exports.defaultDomTheme = defaultDomTheme;
|
|
2164
|
+
Object.defineProperty(exports, "expandRecurringEvents", {
|
|
2165
|
+
enumerable: true,
|
|
2166
|
+
get: function() {
|
|
2167
|
+
return _super_calendar_core.expandRecurringEvents;
|
|
2168
|
+
}
|
|
2169
|
+
});
|
|
1363
2170
|
Object.defineProperty(exports, "getViewDays", {
|
|
1364
2171
|
enumerable: true,
|
|
1365
2172
|
get: function() {
|
|
@@ -1403,6 +2210,18 @@ Object.defineProperty(exports, "nextDateRange", {
|
|
|
1403
2210
|
return _super_calendar_core.nextDateRange;
|
|
1404
2211
|
}
|
|
1405
2212
|
});
|
|
2213
|
+
Object.defineProperty(exports, "parseICalendar", {
|
|
2214
|
+
enumerable: true,
|
|
2215
|
+
get: function() {
|
|
2216
|
+
return _super_calendar_core.parseICalendar;
|
|
2217
|
+
}
|
|
2218
|
+
});
|
|
2219
|
+
Object.defineProperty(exports, "toICalendar", {
|
|
2220
|
+
enumerable: true,
|
|
2221
|
+
get: function() {
|
|
2222
|
+
return _super_calendar_core.toICalendar;
|
|
2223
|
+
}
|
|
2224
|
+
});
|
|
1406
2225
|
Object.defineProperty(exports, "useDateRange", {
|
|
1407
2226
|
enumerable: true,
|
|
1408
2227
|
get: function() {
|
|
@@ -1415,3 +2234,9 @@ Object.defineProperty(exports, "useMonthGrid", {
|
|
|
1415
2234
|
return _super_calendar_core.useMonthGrid;
|
|
1416
2235
|
}
|
|
1417
2236
|
});
|
|
2237
|
+
Object.defineProperty(exports, "weekdayFormatToken", {
|
|
2238
|
+
enumerable: true,
|
|
2239
|
+
get: function() {
|
|
2240
|
+
return _super_calendar_core.weekdayFormatToken;
|
|
2241
|
+
}
|
|
2242
|
+
});
|