@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/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,47 @@ 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({
|
|
1222
|
+
"data-today": (0, _super_calendar_core.getIsToday)(day),
|
|
1223
|
+
"data-weekend": (0, _super_calendar_core.isWeekend)(day)
|
|
1224
|
+
}),
|
|
1225
|
+
...slot("dayColumn", {
|
|
1226
|
+
base: {
|
|
1227
|
+
flex: 1,
|
|
1228
|
+
position: "relative"
|
|
1229
|
+
},
|
|
1230
|
+
themed: {
|
|
1231
|
+
borderLeft: `1px solid ${theme.gridLine}`,
|
|
1232
|
+
...(0, _super_calendar_core.isWeekend)(day) ? { background: theme.weekendBackground } : null
|
|
1233
|
+
}
|
|
1234
|
+
}),
|
|
1020
1235
|
children: [
|
|
1021
1236
|
bands.map((b) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1022
1237
|
"aria-hidden": true,
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1238
|
+
...slot("businessHours", {
|
|
1239
|
+
base: {
|
|
1240
|
+
position: "absolute",
|
|
1241
|
+
left: 0,
|
|
1242
|
+
right: 0,
|
|
1243
|
+
top: b.start * hourHeight,
|
|
1244
|
+
height: (b.end - b.start) * hourHeight,
|
|
1245
|
+
pointerEvents: "none",
|
|
1246
|
+
zIndex: 0
|
|
1247
|
+
},
|
|
1248
|
+
themed: { background: theme.outsideHoursBackground }
|
|
1249
|
+
})
|
|
1033
1250
|
}, b.start)),
|
|
1034
1251
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1035
1252
|
"aria-hidden": true,
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1253
|
+
...slot("gridLines", {
|
|
1254
|
+
base: {
|
|
1255
|
+
position: "absolute",
|
|
1256
|
+
inset: 0,
|
|
1257
|
+
pointerEvents: "none",
|
|
1258
|
+
zIndex: 0
|
|
1259
|
+
},
|
|
1260
|
+
themed: { backgroundImage: gridLines }
|
|
1261
|
+
})
|
|
1043
1262
|
}),
|
|
1044
1263
|
positioned.map((pe, idx) => {
|
|
1045
1264
|
const key = `${dayIndex}:${idx}`;
|
|
@@ -1064,7 +1283,11 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1064
1283
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1065
1284
|
role: "button",
|
|
1066
1285
|
tabIndex: 0,
|
|
1067
|
-
"aria-label": (
|
|
1286
|
+
"aria-label": eventAccessibilityLabel ? eventAccessibilityLabel(pe.event, {
|
|
1287
|
+
mode,
|
|
1288
|
+
isAllDay: false,
|
|
1289
|
+
ampm
|
|
1290
|
+
}) : (0, _super_calendar_core.eventAccessibilityLabel)({
|
|
1068
1291
|
title: pe.event.title,
|
|
1069
1292
|
isAllDay: false,
|
|
1070
1293
|
start: pe.event.start,
|
|
@@ -1082,7 +1305,8 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1082
1305
|
onPointerUp: draggable ? (e) => endDrag(e, day, pe.event, onPress) : void 0,
|
|
1083
1306
|
onPointerCancel: draggable ? cancelDrag : void 0,
|
|
1084
1307
|
onClick: draggable ? void 0 : onPress,
|
|
1085
|
-
|
|
1308
|
+
...dataState({ "data-dragging": !!active }),
|
|
1309
|
+
...slot("event", { base: {
|
|
1086
1310
|
position: "absolute",
|
|
1087
1311
|
top,
|
|
1088
1312
|
height: boxHeight,
|
|
@@ -1092,10 +1316,11 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1092
1316
|
touchAction: draggable ? "none" : "auto",
|
|
1093
1317
|
zIndex: active ? 3 : 1,
|
|
1094
1318
|
opacity: active ? .85 : 1
|
|
1095
|
-
},
|
|
1319
|
+
} }),
|
|
1096
1320
|
children: [Renderer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, { ...args }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultDomEvent, {
|
|
1097
1321
|
...args,
|
|
1098
|
-
theme
|
|
1322
|
+
theme,
|
|
1323
|
+
boxProps: slot("eventBox")
|
|
1099
1324
|
}), draggable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1100
1325
|
onPointerDown: (e) => {
|
|
1101
1326
|
e.stopPropagation();
|
|
@@ -1114,7 +1339,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1114
1339
|
}, idx);
|
|
1115
1340
|
}),
|
|
1116
1341
|
showNow ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1117
|
-
|
|
1342
|
+
...slot("nowIndicator", { base: {
|
|
1118
1343
|
position: "absolute",
|
|
1119
1344
|
top: nowTop,
|
|
1120
1345
|
left: 0,
|
|
@@ -1122,7 +1347,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1122
1347
|
height: 0,
|
|
1123
1348
|
zIndex: 2,
|
|
1124
1349
|
pointerEvents: "none"
|
|
1125
|
-
},
|
|
1350
|
+
} }),
|
|
1126
1351
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
|
|
1127
1352
|
height: 2,
|
|
1128
1353
|
background: theme.nowIndicator
|
|
@@ -1138,19 +1363,23 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1138
1363
|
}) : null,
|
|
1139
1364
|
ghost ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1140
1365
|
"aria-hidden": true,
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1366
|
+
...slot("createGhost", {
|
|
1367
|
+
base: {
|
|
1368
|
+
position: "absolute",
|
|
1369
|
+
left: 1,
|
|
1370
|
+
right: 1,
|
|
1371
|
+
top: ghost.topPx,
|
|
1372
|
+
height: Math.max(ghost.heightPx, 2),
|
|
1373
|
+
opacity: .7,
|
|
1374
|
+
pointerEvents: "none",
|
|
1375
|
+
zIndex: 2
|
|
1376
|
+
},
|
|
1377
|
+
themed: {
|
|
1378
|
+
background: theme.rangeBackground,
|
|
1379
|
+
border: `1px solid ${theme.selectedBackground}`,
|
|
1380
|
+
borderRadius: 6
|
|
1381
|
+
}
|
|
1382
|
+
})
|
|
1154
1383
|
}) : null
|
|
1155
1384
|
]
|
|
1156
1385
|
}, day.toISOString());
|
|
@@ -1173,7 +1402,7 @@ function TimeGrid({ date, events = [], mode = "day", numberOfDays = 1, weekStart
|
|
|
1173
1402
|
* <Calendar mode="week" date={new Date()} events={events} />
|
|
1174
1403
|
* ```
|
|
1175
1404
|
*/
|
|
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 }) {
|
|
1405
|
+
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
1406
|
if (mode === "schedule") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Agenda, {
|
|
1178
1407
|
events: events ?? [],
|
|
1179
1408
|
locale,
|
|
@@ -1183,7 +1412,10 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1183
1412
|
activeDate: date,
|
|
1184
1413
|
className,
|
|
1185
1414
|
style,
|
|
1415
|
+
classNames,
|
|
1416
|
+
styles,
|
|
1186
1417
|
renderEvent: renderScheduleEvent,
|
|
1418
|
+
eventAccessibilityLabel,
|
|
1187
1419
|
onPressEvent,
|
|
1188
1420
|
onPressDay
|
|
1189
1421
|
});
|
|
@@ -1191,10 +1423,13 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1191
1423
|
date,
|
|
1192
1424
|
events: events ?? [],
|
|
1193
1425
|
weekStartsOn,
|
|
1426
|
+
weekdayFormat,
|
|
1194
1427
|
locale,
|
|
1195
1428
|
theme,
|
|
1196
1429
|
className,
|
|
1197
1430
|
style,
|
|
1431
|
+
classNames,
|
|
1432
|
+
styles,
|
|
1198
1433
|
maxVisibleEventCount,
|
|
1199
1434
|
moreLabel,
|
|
1200
1435
|
showAdjacentMonths,
|
|
@@ -1206,21 +1441,26 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1206
1441
|
isDateDisabled,
|
|
1207
1442
|
keyboardDayNavigation,
|
|
1208
1443
|
onPressDay,
|
|
1444
|
+
onCreateEvent,
|
|
1209
1445
|
onPressEvent,
|
|
1210
1446
|
onPressMore,
|
|
1211
|
-
renderEvent: renderMonthEvent
|
|
1447
|
+
renderEvent: renderMonthEvent,
|
|
1448
|
+
eventAccessibilityLabel
|
|
1212
1449
|
});
|
|
1213
1450
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TimeGrid, {
|
|
1214
1451
|
date,
|
|
1215
1452
|
mode,
|
|
1216
1453
|
events,
|
|
1217
1454
|
weekStartsOn,
|
|
1455
|
+
weekdayFormat,
|
|
1218
1456
|
numberOfDays,
|
|
1219
1457
|
locale,
|
|
1220
1458
|
theme,
|
|
1221
1459
|
height,
|
|
1222
1460
|
className,
|
|
1223
1461
|
style,
|
|
1462
|
+
classNames,
|
|
1463
|
+
styles,
|
|
1224
1464
|
ampm,
|
|
1225
1465
|
hourHeight,
|
|
1226
1466
|
scrollOffsetMinutes,
|
|
@@ -1236,6 +1476,7 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1236
1476
|
onDragEvent,
|
|
1237
1477
|
onPressDateHeader,
|
|
1238
1478
|
renderEvent: renderTimeEvent,
|
|
1479
|
+
eventAccessibilityLabel,
|
|
1239
1480
|
hourComponent
|
|
1240
1481
|
});
|
|
1241
1482
|
}
|
|
@@ -1246,8 +1487,12 @@ function Calendar({ mode = "week", date, events, weekStartsOn = 0, numberOfDays,
|
|
|
1246
1487
|
* Legend List's DOM renderer and the library's headless grid logic. Selection is
|
|
1247
1488
|
* controlled, pass `selectedRange` (or `selectedDates`) and handle `onPressDay`.
|
|
1248
1489
|
*/
|
|
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 }) {
|
|
1490
|
+
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
1491
|
const theme = (0, react.useMemo)(() => mergeDomTheme(themeOverrides), [themeOverrides]);
|
|
1492
|
+
const slot = createSlots({
|
|
1493
|
+
classNames,
|
|
1494
|
+
styles
|
|
1495
|
+
});
|
|
1251
1496
|
const months = (0, react.useMemo)(() => {
|
|
1252
1497
|
const first = (0, date_fns.startOfMonth)((0, date_fns.addMonths)(date, -pastMonths));
|
|
1253
1498
|
const count = pastMonths + futureMonths + 1;
|
|
@@ -1259,10 +1504,12 @@ function MonthList({ date, pastMonths = 1, futureMonths = 12, weekStartsOn = 0,
|
|
|
1259
1504
|
]);
|
|
1260
1505
|
const weekdays = (0, react.useMemo)(() => (0, _super_calendar_core.buildMonthGrid)(date, {
|
|
1261
1506
|
weekStartsOn,
|
|
1507
|
+
weekdayFormat,
|
|
1262
1508
|
locale
|
|
1263
1509
|
}).weekdays, [
|
|
1264
1510
|
date,
|
|
1265
1511
|
weekStartsOn,
|
|
1512
|
+
weekdayFormat,
|
|
1266
1513
|
locale
|
|
1267
1514
|
]);
|
|
1268
1515
|
const eventsByDay = (0, react.useMemo)(() => {
|
|
@@ -1288,19 +1535,23 @@ function MonthList({ date, pastMonths = 1, futureMonths = 12, weekStartsOn = 0,
|
|
|
1288
1535
|
...style
|
|
1289
1536
|
},
|
|
1290
1537
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1538
|
+
...slot("weekdays", {
|
|
1539
|
+
base: {
|
|
1540
|
+
display: "grid",
|
|
1541
|
+
gridTemplateColumns: "repeat(7, minmax(0, 1fr))"
|
|
1542
|
+
},
|
|
1543
|
+
themed: {
|
|
1544
|
+
borderBottom: `1px solid ${theme.gridLine}`,
|
|
1545
|
+
padding: "8px 0"
|
|
1546
|
+
}
|
|
1547
|
+
}),
|
|
1297
1548
|
children: weekdays.map((wd) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1298
|
-
|
|
1549
|
+
...slot("weekday", { themed: {
|
|
1299
1550
|
textAlign: "center",
|
|
1300
1551
|
fontSize: 12,
|
|
1301
1552
|
fontWeight: 600,
|
|
1302
1553
|
color: theme.textMuted
|
|
1303
|
-
},
|
|
1554
|
+
} }),
|
|
1304
1555
|
children: wd.label
|
|
1305
1556
|
}, wd.label))
|
|
1306
1557
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_legendapp_list_react.LegendList, {
|
|
@@ -1320,6 +1571,7 @@ function MonthList({ date, pastMonths = 1, futureMonths = 12, weekStartsOn = 0,
|
|
|
1320
1571
|
events,
|
|
1321
1572
|
eventsByDay,
|
|
1322
1573
|
renderEvent,
|
|
1574
|
+
eventAccessibilityLabel,
|
|
1323
1575
|
maxVisibleEventCount,
|
|
1324
1576
|
moreLabel,
|
|
1325
1577
|
onPressEvent,
|
|
@@ -1335,16 +1587,571 @@ function MonthList({ date, pastMonths = 1, futureMonths = 12, weekStartsOn = 0,
|
|
|
1335
1587
|
maxDate,
|
|
1336
1588
|
isDateDisabled,
|
|
1337
1589
|
keyboardDayNavigation,
|
|
1338
|
-
onPressDay
|
|
1590
|
+
onPressDay,
|
|
1591
|
+
classNames,
|
|
1592
|
+
styles
|
|
1593
|
+
})
|
|
1594
|
+
})]
|
|
1595
|
+
});
|
|
1596
|
+
}
|
|
1597
|
+
//#endregion
|
|
1598
|
+
//#region src/DateRangePicker.tsx
|
|
1599
|
+
const triggerDefault = {
|
|
1600
|
+
display: "inline-flex",
|
|
1601
|
+
alignItems: "center",
|
|
1602
|
+
justifyContent: "space-between",
|
|
1603
|
+
gap: 8,
|
|
1604
|
+
minWidth: 220,
|
|
1605
|
+
padding: "8px 12px",
|
|
1606
|
+
borderRadius: 8,
|
|
1607
|
+
cursor: "pointer",
|
|
1608
|
+
font: "inherit",
|
|
1609
|
+
textAlign: "left"
|
|
1610
|
+
};
|
|
1611
|
+
const popoverDefault = {
|
|
1612
|
+
position: "absolute",
|
|
1613
|
+
zIndex: 20,
|
|
1614
|
+
marginTop: 6,
|
|
1615
|
+
overflow: "hidden",
|
|
1616
|
+
borderRadius: 12,
|
|
1617
|
+
minWidth: 300
|
|
1618
|
+
};
|
|
1619
|
+
/**
|
|
1620
|
+
* The shared popover shell: a trigger button and a calendar panel that closes on
|
|
1621
|
+
* outside-click and Escape, and returns focus to the trigger. `renderCalendar`
|
|
1622
|
+
* gets a close callback so a single-date pick can dismiss immediately.
|
|
1623
|
+
*/
|
|
1624
|
+
function usePopover() {
|
|
1625
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
1626
|
+
const rootRef = (0, react.useRef)(null);
|
|
1627
|
+
const triggerRef = (0, react.useRef)(null);
|
|
1628
|
+
(0, react.useEffect)(() => {
|
|
1629
|
+
if (!open) return;
|
|
1630
|
+
const onDown = (e) => {
|
|
1631
|
+
if (!rootRef.current?.contains(e.target)) setOpen(false);
|
|
1632
|
+
};
|
|
1633
|
+
const onKey = (e) => {
|
|
1634
|
+
if (e.key === "Escape") {
|
|
1635
|
+
setOpen(false);
|
|
1636
|
+
triggerRef.current?.focus();
|
|
1637
|
+
}
|
|
1638
|
+
};
|
|
1639
|
+
document.addEventListener("mousedown", onDown);
|
|
1640
|
+
document.addEventListener("keydown", onKey);
|
|
1641
|
+
return () => {
|
|
1642
|
+
document.removeEventListener("mousedown", onDown);
|
|
1643
|
+
document.removeEventListener("keydown", onKey);
|
|
1644
|
+
};
|
|
1645
|
+
}, [open]);
|
|
1646
|
+
return {
|
|
1647
|
+
open,
|
|
1648
|
+
setOpen,
|
|
1649
|
+
rootRef,
|
|
1650
|
+
triggerRef
|
|
1651
|
+
};
|
|
1652
|
+
}
|
|
1653
|
+
function PickerShell({ open, setOpen, rootRef, triggerRef, theme, slot, label, hasValue, placeholder, disabled, className, style, ariaLabel, children }) {
|
|
1654
|
+
const dialogId = (0, react.useId)();
|
|
1655
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1656
|
+
ref: rootRef,
|
|
1657
|
+
className,
|
|
1658
|
+
style: {
|
|
1659
|
+
position: "relative",
|
|
1660
|
+
display: "inline-block",
|
|
1661
|
+
fontFamily: theme.fontFamily,
|
|
1662
|
+
...style
|
|
1663
|
+
},
|
|
1664
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1665
|
+
ref: triggerRef,
|
|
1666
|
+
type: "button",
|
|
1667
|
+
disabled,
|
|
1668
|
+
"aria-haspopup": "dialog",
|
|
1669
|
+
"aria-expanded": open,
|
|
1670
|
+
"aria-controls": open ? dialogId : void 0,
|
|
1671
|
+
onClick: () => setOpen(!open),
|
|
1672
|
+
...slot("trigger", {
|
|
1673
|
+
base: triggerDefault,
|
|
1674
|
+
themed: {
|
|
1675
|
+
border: `1px solid ${theme.gridLine}`,
|
|
1676
|
+
background: theme.eventBackground,
|
|
1677
|
+
color: hasValue ? theme.text : theme.textMuted,
|
|
1678
|
+
opacity: disabled ? .5 : 1
|
|
1679
|
+
}
|
|
1680
|
+
}),
|
|
1681
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: hasValue ? label : placeholder }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1682
|
+
"aria-hidden": true,
|
|
1683
|
+
children: "▾"
|
|
1684
|
+
})]
|
|
1685
|
+
}), open ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1686
|
+
id: dialogId,
|
|
1687
|
+
role: "dialog",
|
|
1688
|
+
"aria-label": ariaLabel,
|
|
1689
|
+
...slot("popover", {
|
|
1690
|
+
base: popoverDefault,
|
|
1691
|
+
themed: {
|
|
1692
|
+
background: theme.eventBackground,
|
|
1693
|
+
border: `1px solid ${theme.gridLine}`
|
|
1694
|
+
}
|
|
1695
|
+
}),
|
|
1696
|
+
children
|
|
1697
|
+
}) : null]
|
|
1698
|
+
});
|
|
1699
|
+
}
|
|
1700
|
+
/**
|
|
1701
|
+
* A single-date input with a popover calendar. Controlled via `value` / `onChange`.
|
|
1702
|
+
* Composed from {@link MonthList}; forward calendar slots (e.g. `dayBadge`) through
|
|
1703
|
+
* `classNames` to restyle the popover.
|
|
1704
|
+
*
|
|
1705
|
+
* @example
|
|
1706
|
+
* ```tsx
|
|
1707
|
+
* const [value, setValue] = useState<Date | null>(null);
|
|
1708
|
+
* <DatePicker value={value} onChange={setValue} />
|
|
1709
|
+
* ```
|
|
1710
|
+
*/
|
|
1711
|
+
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 }) {
|
|
1712
|
+
const theme = mergeDomTheme(themeOverrides);
|
|
1713
|
+
const slot = createSlots({
|
|
1714
|
+
classNames,
|
|
1715
|
+
styles
|
|
1716
|
+
});
|
|
1717
|
+
const { open, setOpen, rootRef, triggerRef } = usePopover();
|
|
1718
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PickerShell, {
|
|
1719
|
+
open,
|
|
1720
|
+
setOpen,
|
|
1721
|
+
rootRef,
|
|
1722
|
+
triggerRef,
|
|
1723
|
+
theme,
|
|
1724
|
+
slot,
|
|
1725
|
+
label: value ? formatLabel(value) : "",
|
|
1726
|
+
hasValue: !!value,
|
|
1727
|
+
placeholder,
|
|
1728
|
+
disabled,
|
|
1729
|
+
className,
|
|
1730
|
+
style,
|
|
1731
|
+
ariaLabel: "Choose a date",
|
|
1732
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MonthList, {
|
|
1733
|
+
date: value ?? /* @__PURE__ */ new Date(),
|
|
1734
|
+
weekStartsOn,
|
|
1735
|
+
selectedDates: value ? [value] : [],
|
|
1736
|
+
minDate,
|
|
1737
|
+
maxDate,
|
|
1738
|
+
isDateDisabled,
|
|
1739
|
+
onPressDay: (day) => {
|
|
1740
|
+
onChange(day);
|
|
1741
|
+
setOpen(false);
|
|
1742
|
+
triggerRef.current?.focus();
|
|
1743
|
+
},
|
|
1744
|
+
height,
|
|
1745
|
+
classNames,
|
|
1746
|
+
styles
|
|
1747
|
+
})
|
|
1748
|
+
});
|
|
1749
|
+
}
|
|
1750
|
+
function defaultRangeLabel(range) {
|
|
1751
|
+
const start = (0, date_fns.format)(range.start, "d MMM yyyy");
|
|
1752
|
+
return range.end ? `${start} – ${(0, date_fns.format)(range.end, "d MMM yyyy")}` : `${start} – …`;
|
|
1753
|
+
}
|
|
1754
|
+
/**
|
|
1755
|
+
* A date-range input with a popover calendar. Controlled via `value` / `onChange`;
|
|
1756
|
+
* each pick advances the range through {@link nextDateRange} (start, then end), and
|
|
1757
|
+
* the popover closes once both ends are set.
|
|
1758
|
+
*
|
|
1759
|
+
* @example
|
|
1760
|
+
* ```tsx
|
|
1761
|
+
* const [range, setRange] = useState<DateRange | null>(null);
|
|
1762
|
+
* <DateRangePicker value={range} onChange={setRange} />
|
|
1763
|
+
* ```
|
|
1764
|
+
*/
|
|
1765
|
+
function DateRangePicker({ value, onChange, formatLabel = defaultRangeLabel, weekStartsOn = 0, height = 320, placeholder = "Select dates", disabled, theme: themeOverrides, className, style, classNames, styles, minDate, maxDate, isDateDisabled }) {
|
|
1766
|
+
const theme = mergeDomTheme(themeOverrides);
|
|
1767
|
+
const slot = createSlots({
|
|
1768
|
+
classNames,
|
|
1769
|
+
styles
|
|
1770
|
+
});
|
|
1771
|
+
const { open, setOpen, rootRef, triggerRef } = usePopover();
|
|
1772
|
+
const constraints = {
|
|
1773
|
+
minDate,
|
|
1774
|
+
maxDate,
|
|
1775
|
+
isDateDisabled
|
|
1776
|
+
};
|
|
1777
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(PickerShell, {
|
|
1778
|
+
open,
|
|
1779
|
+
setOpen,
|
|
1780
|
+
rootRef,
|
|
1781
|
+
triggerRef,
|
|
1782
|
+
theme,
|
|
1783
|
+
slot,
|
|
1784
|
+
label: value ? formatLabel(value) : "",
|
|
1785
|
+
hasValue: !!value,
|
|
1786
|
+
placeholder,
|
|
1787
|
+
disabled,
|
|
1788
|
+
className,
|
|
1789
|
+
style,
|
|
1790
|
+
ariaLabel: "Choose a date range",
|
|
1791
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MonthList, {
|
|
1792
|
+
date: value?.start ?? /* @__PURE__ */ new Date(),
|
|
1793
|
+
weekStartsOn,
|
|
1794
|
+
selectedRange: value ?? void 0,
|
|
1795
|
+
minDate,
|
|
1796
|
+
maxDate,
|
|
1797
|
+
isDateDisabled,
|
|
1798
|
+
onPressDay: (day) => {
|
|
1799
|
+
const next = (0, _super_calendar_core.nextDateRange)(value, day, constraints);
|
|
1800
|
+
onChange(next);
|
|
1801
|
+
if (next?.end) {
|
|
1802
|
+
setOpen(false);
|
|
1803
|
+
triggerRef.current?.focus();
|
|
1804
|
+
}
|
|
1805
|
+
},
|
|
1806
|
+
height,
|
|
1807
|
+
classNames,
|
|
1808
|
+
styles
|
|
1809
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1810
|
+
...slot("footer", {
|
|
1811
|
+
base: {
|
|
1812
|
+
display: "flex",
|
|
1813
|
+
justifyContent: "flex-end",
|
|
1814
|
+
padding: "8px 10px"
|
|
1815
|
+
},
|
|
1816
|
+
themed: { borderTop: `1px solid ${theme.gridLine}` }
|
|
1817
|
+
}),
|
|
1818
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1819
|
+
type: "button",
|
|
1820
|
+
onClick: () => onChange(null),
|
|
1821
|
+
...slot("clear", {
|
|
1822
|
+
base: {
|
|
1823
|
+
border: "none",
|
|
1824
|
+
background: "transparent",
|
|
1825
|
+
cursor: "pointer",
|
|
1826
|
+
font: "inherit"
|
|
1827
|
+
},
|
|
1828
|
+
themed: { color: theme.textMuted }
|
|
1829
|
+
}),
|
|
1830
|
+
children: "Clear"
|
|
1339
1831
|
})
|
|
1340
1832
|
})]
|
|
1341
1833
|
});
|
|
1342
1834
|
}
|
|
1343
1835
|
//#endregion
|
|
1836
|
+
//#region src/ResourceTimeline.tsx
|
|
1837
|
+
const clamp = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
1838
|
+
function DefaultBar({ event, boxProps, theme }) {
|
|
1839
|
+
const time = (0, _super_calendar_core.eventTimeLabel)({
|
|
1840
|
+
mode: "day",
|
|
1841
|
+
isAllDay: false,
|
|
1842
|
+
start: event.start,
|
|
1843
|
+
end: event.end,
|
|
1844
|
+
ampm: false,
|
|
1845
|
+
showTime: true
|
|
1846
|
+
});
|
|
1847
|
+
const base = {
|
|
1848
|
+
height: "100%",
|
|
1849
|
+
boxSizing: "border-box",
|
|
1850
|
+
overflow: "hidden"
|
|
1851
|
+
};
|
|
1852
|
+
const themed = {
|
|
1853
|
+
padding: "2px 6px",
|
|
1854
|
+
borderRadius: 6,
|
|
1855
|
+
background: theme.eventBackground,
|
|
1856
|
+
color: theme.eventText,
|
|
1857
|
+
fontSize: 12
|
|
1858
|
+
};
|
|
1859
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1860
|
+
className: boxProps.className,
|
|
1861
|
+
"data-slot": boxProps["data-slot"],
|
|
1862
|
+
style: boxProps.className ? {
|
|
1863
|
+
...base,
|
|
1864
|
+
...boxProps.style
|
|
1865
|
+
} : {
|
|
1866
|
+
...base,
|
|
1867
|
+
...themed,
|
|
1868
|
+
...boxProps.style
|
|
1869
|
+
},
|
|
1870
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1871
|
+
style: {
|
|
1872
|
+
fontWeight: 600,
|
|
1873
|
+
whiteSpace: "nowrap",
|
|
1874
|
+
overflow: "hidden",
|
|
1875
|
+
textOverflow: "ellipsis"
|
|
1876
|
+
},
|
|
1877
|
+
children: event.title
|
|
1878
|
+
}), time ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1879
|
+
style: {
|
|
1880
|
+
opacity: .75,
|
|
1881
|
+
fontSize: 11
|
|
1882
|
+
},
|
|
1883
|
+
children: time
|
|
1884
|
+
}) : null]
|
|
1885
|
+
});
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* A horizontal resource timeline: rows are resources (rooms, people, machines)
|
|
1889
|
+
* and the x-axis is one day's hours. Events sit in their resource's row, and
|
|
1890
|
+
* overlapping events in the same row stack into sub-lanes (via the shared
|
|
1891
|
+
* `layoutDayEvents`). Pass `onDragEvent` to enable drag-to-move and edge-resize
|
|
1892
|
+
* along the axis.
|
|
1893
|
+
*
|
|
1894
|
+
* @example
|
|
1895
|
+
* ```tsx
|
|
1896
|
+
* <ResourceTimeline
|
|
1897
|
+
* date={new Date()}
|
|
1898
|
+
* resources={[{ id: "a", title: "Room A" }, { id: "b", title: "Room B" }]}
|
|
1899
|
+
* events={events} // each event carries a `resourceId`
|
|
1900
|
+
* />
|
|
1901
|
+
* ```
|
|
1902
|
+
*/
|
|
1903
|
+
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 }) {
|
|
1904
|
+
const theme = (0, react.useMemo)(() => mergeDomTheme(themeOverrides), [themeOverrides]);
|
|
1905
|
+
const slot = createSlots({
|
|
1906
|
+
classNames,
|
|
1907
|
+
styles
|
|
1908
|
+
});
|
|
1909
|
+
const Renderer = renderEvent;
|
|
1910
|
+
const snapHours = dragStepMinutes / 60;
|
|
1911
|
+
const [drag, setDrag] = (0, react.useState)(null);
|
|
1912
|
+
const dragRef = (0, react.useRef)(null);
|
|
1913
|
+
const origin = (0, react.useRef)(null);
|
|
1914
|
+
const applyDrag = (next) => {
|
|
1915
|
+
dragRef.current = next;
|
|
1916
|
+
setDrag(next);
|
|
1917
|
+
};
|
|
1918
|
+
const beginDrag = (e, key, kind, startHours, durationHours) => {
|
|
1919
|
+
if (!onDragEvent) return;
|
|
1920
|
+
e.stopPropagation();
|
|
1921
|
+
try {
|
|
1922
|
+
e.target.setPointerCapture?.(e.pointerId);
|
|
1923
|
+
} catch {}
|
|
1924
|
+
origin.current = {
|
|
1925
|
+
x: e.clientX,
|
|
1926
|
+
startHours,
|
|
1927
|
+
durationHours
|
|
1928
|
+
};
|
|
1929
|
+
applyDrag({
|
|
1930
|
+
key,
|
|
1931
|
+
kind,
|
|
1932
|
+
startHours,
|
|
1933
|
+
durationHours,
|
|
1934
|
+
moved: false
|
|
1935
|
+
});
|
|
1936
|
+
};
|
|
1937
|
+
const moveDrag = (e) => {
|
|
1938
|
+
const d = dragRef.current;
|
|
1939
|
+
if (!d || !origin.current) return;
|
|
1940
|
+
const dHours = (e.clientX - origin.current.x) / hourWidth;
|
|
1941
|
+
const snap = (v) => Math.round(v / snapHours) * snapHours;
|
|
1942
|
+
if (d.kind === "move") {
|
|
1943
|
+
const startHours = clamp(snap(origin.current.startHours + dHours), startHour, endHour - d.durationHours);
|
|
1944
|
+
applyDrag({
|
|
1945
|
+
...d,
|
|
1946
|
+
startHours,
|
|
1947
|
+
moved: true
|
|
1948
|
+
});
|
|
1949
|
+
} else {
|
|
1950
|
+
const durationHours = clamp(snap(origin.current.durationHours + dHours), snapHours, endHour - d.startHours);
|
|
1951
|
+
applyDrag({
|
|
1952
|
+
...d,
|
|
1953
|
+
durationHours,
|
|
1954
|
+
moved: true
|
|
1955
|
+
});
|
|
1956
|
+
}
|
|
1957
|
+
};
|
|
1958
|
+
const endDrag = (e, event, onPress) => {
|
|
1959
|
+
const d = dragRef.current;
|
|
1960
|
+
if (!d) return;
|
|
1961
|
+
try {
|
|
1962
|
+
e.target.releasePointerCapture?.(e.pointerId);
|
|
1963
|
+
} catch {}
|
|
1964
|
+
if (!d.moved) {
|
|
1965
|
+
applyDrag(null);
|
|
1966
|
+
onPress();
|
|
1967
|
+
return;
|
|
1968
|
+
}
|
|
1969
|
+
const base = (0, date_fns.startOfDay)(date);
|
|
1970
|
+
const start = (0, date_fns.addMinutes)(base, Math.round(d.startHours * 60));
|
|
1971
|
+
const end = (0, date_fns.addMinutes)(base, Math.round((d.startHours + d.durationHours) * 60));
|
|
1972
|
+
onDragEvent?.(event, start, end);
|
|
1973
|
+
applyDrag(null);
|
|
1974
|
+
origin.current = null;
|
|
1975
|
+
};
|
|
1976
|
+
const cancelDrag = () => {
|
|
1977
|
+
applyDrag(null);
|
|
1978
|
+
origin.current = null;
|
|
1979
|
+
};
|
|
1980
|
+
const hours = (0, react.useMemo)(() => Array.from({ length: Math.max(0, endHour - startHour) }, (_, i) => startHour + i), [startHour, endHour]);
|
|
1981
|
+
const trackWidth = (endHour - startHour) * hourWidth;
|
|
1982
|
+
const byResource = (0, react.useMemo)(() => {
|
|
1983
|
+
const map = /* @__PURE__ */ new Map();
|
|
1984
|
+
for (const resource of resources) {
|
|
1985
|
+
const own = events.filter((e) => resourceId(e) === resource.id);
|
|
1986
|
+
map.set(resource.id, (0, _super_calendar_core.layoutDayEvents)(own, date));
|
|
1987
|
+
}
|
|
1988
|
+
return map;
|
|
1989
|
+
}, [
|
|
1990
|
+
resources,
|
|
1991
|
+
events,
|
|
1992
|
+
resourceId,
|
|
1993
|
+
date
|
|
1994
|
+
]);
|
|
1995
|
+
const gridLines = `repeating-linear-gradient(to right, transparent 0, transparent ${hourWidth - 1}px, ${theme.gridLine} ${hourWidth - 1}px, ${theme.gridLine} ${hourWidth}px)`;
|
|
1996
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1997
|
+
className,
|
|
1998
|
+
style: {
|
|
1999
|
+
fontFamily: theme.fontFamily,
|
|
2000
|
+
color: theme.text,
|
|
2001
|
+
overflowX: "auto",
|
|
2002
|
+
...style
|
|
2003
|
+
},
|
|
2004
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2005
|
+
style: { minWidth: labelWidth + trackWidth },
|
|
2006
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2007
|
+
...slot("header", {
|
|
2008
|
+
base: { display: "flex" },
|
|
2009
|
+
themed: { borderBottom: `1px solid ${theme.gridLine}` }
|
|
2010
|
+
}),
|
|
2011
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { ...slot("corner", { base: {
|
|
2012
|
+
width: labelWidth,
|
|
2013
|
+
flex: "none"
|
|
2014
|
+
} }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2015
|
+
...slot("timeAxis", { base: {
|
|
2016
|
+
position: "relative",
|
|
2017
|
+
height: 24,
|
|
2018
|
+
width: trackWidth
|
|
2019
|
+
} }),
|
|
2020
|
+
children: hours.map((h) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2021
|
+
...slot("hourTick", {
|
|
2022
|
+
base: {
|
|
2023
|
+
position: "absolute",
|
|
2024
|
+
left: (h - startHour) * hourWidth,
|
|
2025
|
+
top: 4
|
|
2026
|
+
},
|
|
2027
|
+
themed: {
|
|
2028
|
+
fontSize: 10,
|
|
2029
|
+
color: theme.textMuted
|
|
2030
|
+
}
|
|
2031
|
+
}),
|
|
2032
|
+
children: (0, _super_calendar_core.formatHour)(h, { ampm })
|
|
2033
|
+
}, h))
|
|
2034
|
+
})]
|
|
2035
|
+
}), resources.map((resource) => {
|
|
2036
|
+
const positioned = byResource.get(resource.id) ?? [];
|
|
2037
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2038
|
+
...slot("row", {
|
|
2039
|
+
base: {
|
|
2040
|
+
display: "flex",
|
|
2041
|
+
height: rowHeight
|
|
2042
|
+
},
|
|
2043
|
+
themed: { borderBottom: `1px solid ${theme.gridLine}` }
|
|
2044
|
+
}),
|
|
2045
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2046
|
+
...slot("resourceLabel", {
|
|
2047
|
+
base: {
|
|
2048
|
+
width: labelWidth,
|
|
2049
|
+
flex: "none",
|
|
2050
|
+
display: "flex",
|
|
2051
|
+
alignItems: "center",
|
|
2052
|
+
padding: "0 10px",
|
|
2053
|
+
boxSizing: "border-box"
|
|
2054
|
+
},
|
|
2055
|
+
themed: {
|
|
2056
|
+
fontSize: 13,
|
|
2057
|
+
fontWeight: 600,
|
|
2058
|
+
borderRight: `1px solid ${theme.gridLine}`
|
|
2059
|
+
}
|
|
2060
|
+
}),
|
|
2061
|
+
children: resource.title ?? resource.id
|
|
2062
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2063
|
+
...slot("track", { base: {
|
|
2064
|
+
position: "relative",
|
|
2065
|
+
width: trackWidth
|
|
2066
|
+
} }),
|
|
2067
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2068
|
+
"aria-hidden": true,
|
|
2069
|
+
...slot("gridLines", {
|
|
2070
|
+
base: {
|
|
2071
|
+
position: "absolute",
|
|
2072
|
+
inset: 0,
|
|
2073
|
+
pointerEvents: "none"
|
|
2074
|
+
},
|
|
2075
|
+
themed: { backgroundImage: gridLines }
|
|
2076
|
+
})
|
|
2077
|
+
}), positioned.map((pe, idx) => {
|
|
2078
|
+
const key = `${resource.id}:${idx}`;
|
|
2079
|
+
const active = drag?.key === key ? drag : null;
|
|
2080
|
+
const startH = active ? active.startHours : pe.startHours;
|
|
2081
|
+
const durH = active ? active.durationHours : pe.durationHours;
|
|
2082
|
+
const left = clamp(startH - startHour, 0, endHour - startHour) * hourWidth;
|
|
2083
|
+
const right = clamp(startH + durH - startHour, 0, endHour - startHour) * hourWidth;
|
|
2084
|
+
const width = Math.max(right - left, 2);
|
|
2085
|
+
const laneHeight = rowHeight / pe.columns;
|
|
2086
|
+
const onPress = () => onPressEvent?.(pe.event);
|
|
2087
|
+
const args = {
|
|
2088
|
+
event: pe.event,
|
|
2089
|
+
width,
|
|
2090
|
+
onPress
|
|
2091
|
+
};
|
|
2092
|
+
const draggable = !!onDragEvent;
|
|
2093
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
2094
|
+
type: "button",
|
|
2095
|
+
onClick: draggable ? void 0 : onPress,
|
|
2096
|
+
"aria-label": pe.event.title,
|
|
2097
|
+
...dataState({ "data-dragging": !!active }),
|
|
2098
|
+
onPointerDown: draggable ? (e) => beginDrag(e, key, "move", pe.startHours, pe.durationHours) : void 0,
|
|
2099
|
+
onPointerMove: draggable ? moveDrag : void 0,
|
|
2100
|
+
onPointerUp: draggable ? (e) => endDrag(e, pe.event, onPress) : void 0,
|
|
2101
|
+
onPointerCancel: draggable ? cancelDrag : void 0,
|
|
2102
|
+
...slot("event", { base: {
|
|
2103
|
+
position: "absolute",
|
|
2104
|
+
left,
|
|
2105
|
+
width,
|
|
2106
|
+
top: pe.column * laneHeight,
|
|
2107
|
+
height: laneHeight,
|
|
2108
|
+
padding: 1,
|
|
2109
|
+
border: "none",
|
|
2110
|
+
background: "transparent",
|
|
2111
|
+
cursor: draggable ? "grab" : "pointer",
|
|
2112
|
+
touchAction: draggable ? "none" : "auto",
|
|
2113
|
+
font: "inherit",
|
|
2114
|
+
textAlign: "left",
|
|
2115
|
+
boxSizing: "border-box",
|
|
2116
|
+
zIndex: active ? 3 : 1,
|
|
2117
|
+
opacity: active ? .85 : 1
|
|
2118
|
+
} }),
|
|
2119
|
+
children: [Renderer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Renderer, { ...args }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultBar, {
|
|
2120
|
+
...args,
|
|
2121
|
+
theme,
|
|
2122
|
+
boxProps: slot("eventBox")
|
|
2123
|
+
}), draggable ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2124
|
+
"aria-hidden": true,
|
|
2125
|
+
onPointerDown: (e) => {
|
|
2126
|
+
e.stopPropagation();
|
|
2127
|
+
beginDrag(e, key, "resize", pe.startHours, pe.durationHours);
|
|
2128
|
+
},
|
|
2129
|
+
style: {
|
|
2130
|
+
position: "absolute",
|
|
2131
|
+
top: 0,
|
|
2132
|
+
bottom: 0,
|
|
2133
|
+
right: 0,
|
|
2134
|
+
width: 8,
|
|
2135
|
+
cursor: "ew-resize",
|
|
2136
|
+
touchAction: "none"
|
|
2137
|
+
}
|
|
2138
|
+
}) : null]
|
|
2139
|
+
}, idx);
|
|
2140
|
+
})]
|
|
2141
|
+
})]
|
|
2142
|
+
}, resource.id);
|
|
2143
|
+
})]
|
|
2144
|
+
})
|
|
2145
|
+
});
|
|
2146
|
+
}
|
|
2147
|
+
//#endregion
|
|
1344
2148
|
exports.Agenda = Agenda;
|
|
1345
2149
|
exports.Calendar = Calendar;
|
|
2150
|
+
exports.DatePicker = DatePicker;
|
|
2151
|
+
exports.DateRangePicker = DateRangePicker;
|
|
1346
2152
|
exports.MonthList = MonthList;
|
|
1347
2153
|
exports.MonthView = MonthView;
|
|
2154
|
+
exports.ResourceTimeline = ResourceTimeline;
|
|
1348
2155
|
exports.TimeGrid = TimeGrid;
|
|
1349
2156
|
Object.defineProperty(exports, "buildMonthGrid", {
|
|
1350
2157
|
enumerable: true,
|
|
@@ -1360,6 +2167,12 @@ Object.defineProperty(exports, "daySelectionState", {
|
|
|
1360
2167
|
}
|
|
1361
2168
|
});
|
|
1362
2169
|
exports.defaultDomTheme = defaultDomTheme;
|
|
2170
|
+
Object.defineProperty(exports, "expandRecurringEvents", {
|
|
2171
|
+
enumerable: true,
|
|
2172
|
+
get: function() {
|
|
2173
|
+
return _super_calendar_core.expandRecurringEvents;
|
|
2174
|
+
}
|
|
2175
|
+
});
|
|
1363
2176
|
Object.defineProperty(exports, "getViewDays", {
|
|
1364
2177
|
enumerable: true,
|
|
1365
2178
|
get: function() {
|
|
@@ -1403,6 +2216,18 @@ Object.defineProperty(exports, "nextDateRange", {
|
|
|
1403
2216
|
return _super_calendar_core.nextDateRange;
|
|
1404
2217
|
}
|
|
1405
2218
|
});
|
|
2219
|
+
Object.defineProperty(exports, "parseICalendar", {
|
|
2220
|
+
enumerable: true,
|
|
2221
|
+
get: function() {
|
|
2222
|
+
return _super_calendar_core.parseICalendar;
|
|
2223
|
+
}
|
|
2224
|
+
});
|
|
2225
|
+
Object.defineProperty(exports, "toICalendar", {
|
|
2226
|
+
enumerable: true,
|
|
2227
|
+
get: function() {
|
|
2228
|
+
return _super_calendar_core.toICalendar;
|
|
2229
|
+
}
|
|
2230
|
+
});
|
|
1406
2231
|
Object.defineProperty(exports, "useDateRange", {
|
|
1407
2232
|
enumerable: true,
|
|
1408
2233
|
get: function() {
|
|
@@ -1415,3 +2240,9 @@ Object.defineProperty(exports, "useMonthGrid", {
|
|
|
1415
2240
|
return _super_calendar_core.useMonthGrid;
|
|
1416
2241
|
}
|
|
1417
2242
|
});
|
|
2243
|
+
Object.defineProperty(exports, "weekdayFormatToken", {
|
|
2244
|
+
enumerable: true,
|
|
2245
|
+
get: function() {
|
|
2246
|
+
return _super_calendar_core.weekdayFormatToken;
|
|
2247
|
+
}
|
|
2248
|
+
});
|