@marco.colia/react-fast-scheduler 1.0.0 → 2.0.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/LICENSE +22 -22
- package/README.md +251 -213
- package/dist/index.cjs +255 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -18
- package/dist/index.d.ts +37 -18
- package/dist/index.js +255 -67
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +86 -86
package/dist/index.cjs
CHANGED
|
@@ -127,6 +127,46 @@ function isNameLike(resource) {
|
|
|
127
127
|
const maybe = resource;
|
|
128
128
|
return typeof maybe.firstName === "string" || typeof maybe.lastName === "string";
|
|
129
129
|
}
|
|
130
|
+
function toInputDateValue(date) {
|
|
131
|
+
const year = date.getFullYear();
|
|
132
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
133
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
134
|
+
return `${year}-${month}-${day}`;
|
|
135
|
+
}
|
|
136
|
+
function fromInputDateValue(value) {
|
|
137
|
+
const [yearRaw, monthRaw, dayRaw] = value.split("-");
|
|
138
|
+
const year = Number(yearRaw);
|
|
139
|
+
const month = Number(monthRaw);
|
|
140
|
+
const day = Number(dayRaw);
|
|
141
|
+
if (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day)) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
return new Date(year, month - 1, day);
|
|
145
|
+
}
|
|
146
|
+
var DEFAULT_APPOINTMENT_COLOR_TOKEN_CLASS_MAP = {
|
|
147
|
+
slate: "bg-slate-100 dark:bg-slate-900/40",
|
|
148
|
+
gray: "bg-gray-100 dark:bg-gray-900/40",
|
|
149
|
+
zinc: "bg-zinc-100 dark:bg-zinc-900/40",
|
|
150
|
+
neutral: "bg-neutral-100 dark:bg-neutral-900/40",
|
|
151
|
+
stone: "bg-stone-100 dark:bg-stone-900/40",
|
|
152
|
+
red: "bg-red-100 dark:bg-red-950/40",
|
|
153
|
+
orange: "bg-orange-100 dark:bg-orange-950/40",
|
|
154
|
+
amber: "bg-amber-100 dark:bg-amber-950/40",
|
|
155
|
+
yellow: "bg-yellow-100 dark:bg-yellow-950/40",
|
|
156
|
+
lime: "bg-lime-100 dark:bg-lime-950/40",
|
|
157
|
+
green: "bg-green-100 dark:bg-green-950/40",
|
|
158
|
+
emerald: "bg-emerald-100 dark:bg-emerald-950/40",
|
|
159
|
+
teal: "bg-teal-100 dark:bg-teal-950/40",
|
|
160
|
+
cyan: "bg-cyan-100 dark:bg-cyan-950/40",
|
|
161
|
+
sky: "bg-sky-100 dark:bg-sky-950/40",
|
|
162
|
+
blue: "bg-blue-100 dark:bg-blue-950/40",
|
|
163
|
+
indigo: "bg-indigo-100 dark:bg-indigo-950/40",
|
|
164
|
+
violet: "bg-violet-100 dark:bg-violet-950/40",
|
|
165
|
+
purple: "bg-purple-100 dark:bg-purple-950/40",
|
|
166
|
+
fuchsia: "bg-fuchsia-100 dark:bg-fuchsia-950/40",
|
|
167
|
+
pink: "bg-pink-100 dark:bg-pink-950/40",
|
|
168
|
+
rose: "bg-rose-100 dark:bg-rose-950/40"
|
|
169
|
+
};
|
|
130
170
|
function Scheduler({
|
|
131
171
|
resources,
|
|
132
172
|
appointments,
|
|
@@ -137,6 +177,10 @@ function Scheduler({
|
|
|
137
177
|
onAppointmentChange,
|
|
138
178
|
renderResourceHeader,
|
|
139
179
|
renderAppointment,
|
|
180
|
+
resourceAppointmentClassMap,
|
|
181
|
+
getResourceAppointmentAppearance,
|
|
182
|
+
getResourceAppointmentColorToken,
|
|
183
|
+
appointmentColorTokenClassMap,
|
|
140
184
|
getResourceAppointmentBackground,
|
|
141
185
|
renderDatePicker,
|
|
142
186
|
prevButtonLabel = "Prev",
|
|
@@ -208,6 +252,48 @@ function Scheduler({
|
|
|
208
252
|
}
|
|
209
253
|
return map;
|
|
210
254
|
}, [getResourceAppointmentBackground, resources]);
|
|
255
|
+
const appointmentColorTokenClassByResource = React__namespace.useMemo(() => {
|
|
256
|
+
const map = /* @__PURE__ */ new Map();
|
|
257
|
+
const mergedClassMap = {
|
|
258
|
+
...DEFAULT_APPOINTMENT_COLOR_TOKEN_CLASS_MAP,
|
|
259
|
+
...appointmentColorTokenClassMap ?? {}
|
|
260
|
+
};
|
|
261
|
+
if (!getResourceAppointmentColorToken) {
|
|
262
|
+
return map;
|
|
263
|
+
}
|
|
264
|
+
for (const resource of resources) {
|
|
265
|
+
const token = getResourceAppointmentColorToken(resource);
|
|
266
|
+
map.set(resource.id, token ? mergedClassMap[token] : void 0);
|
|
267
|
+
}
|
|
268
|
+
return map;
|
|
269
|
+
}, [appointmentColorTokenClassMap, getResourceAppointmentColorToken, resources]);
|
|
270
|
+
const appointmentAppearanceByResource = React__namespace.useMemo(() => {
|
|
271
|
+
const map = /* @__PURE__ */ new Map();
|
|
272
|
+
for (const resource of resources) {
|
|
273
|
+
const classFromIdMap = resourceAppointmentClassMap?.[String(resource.id)];
|
|
274
|
+
if (classFromIdMap) {
|
|
275
|
+
map.set(resource.id, { className: classFromIdMap });
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
const appearance = getResourceAppointmentAppearance?.(resource);
|
|
279
|
+
if (appearance) {
|
|
280
|
+
map.set(resource.id, appearance);
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
const tokenClass = appointmentColorTokenClassByResource.get(resource.id);
|
|
284
|
+
if (tokenClass) {
|
|
285
|
+
map.set(resource.id, { className: tokenClass });
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
const legacyBackground = appointmentBgByResource.get(resource.id);
|
|
289
|
+
if (!legacyBackground) {
|
|
290
|
+
map.set(resource.id, void 0);
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
map.set(resource.id, { className: legacyBackground });
|
|
294
|
+
}
|
|
295
|
+
return map;
|
|
296
|
+
}, [appointmentBgByResource, appointmentColorTokenClassByResource, getResourceAppointmentAppearance, resourceAppointmentClassMap, resources]);
|
|
211
297
|
const pointerToMin = (resourceId, clientY) => {
|
|
212
298
|
const col = colRefs.current[String(resourceId)];
|
|
213
299
|
if (!col) {
|
|
@@ -342,88 +428,178 @@ function Scheduler({
|
|
|
342
428
|
void persistDrag(current);
|
|
343
429
|
}
|
|
344
430
|
};
|
|
431
|
+
const defaultRenderAppointment = ({
|
|
432
|
+
appointment,
|
|
433
|
+
onPointerDown,
|
|
434
|
+
onResizePointerDown: onResizePointerDown2,
|
|
435
|
+
appointmentAppearance,
|
|
436
|
+
appointmentBackgroundColor
|
|
437
|
+
}) => {
|
|
438
|
+
const rawMaybe = appointment.raw;
|
|
439
|
+
const description = typeof rawMaybe.description === "string" ? rawMaybe.description : void 0;
|
|
440
|
+
const legacyClassName = typeof appointmentBackgroundColor === "string" ? appointmentBackgroundColor : void 0;
|
|
441
|
+
const backgroundClassName = appointmentAppearance?.className ?? legacyClassName ?? "bg-muted/40 dark:bg-muted/30";
|
|
442
|
+
const className = `relative h-full cursor-grab overflow-hidden rounded-md border border-border p-2 pb-5 text-foreground ${backgroundClassName}`;
|
|
443
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { onPointerDown, className, children: [
|
|
444
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-semibold", children: appointment.title }),
|
|
445
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-[10px] font-medium text-muted-foreground", children: description }) : null,
|
|
446
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
447
|
+
"div",
|
|
448
|
+
{
|
|
449
|
+
role: "button",
|
|
450
|
+
"aria-label": "Resize appointment",
|
|
451
|
+
onPointerDown: (event) => {
|
|
452
|
+
event.stopPropagation();
|
|
453
|
+
onResizePointerDown2(event);
|
|
454
|
+
},
|
|
455
|
+
className: "absolute inset-x-1 bottom-1 h-2 cursor-ns-resize rounded-full bg-border/90 transition-colors hover:bg-border"
|
|
456
|
+
}
|
|
457
|
+
)
|
|
458
|
+
] });
|
|
459
|
+
};
|
|
460
|
+
const defaultRenderDatePicker = ({
|
|
461
|
+
selectedDate: value,
|
|
462
|
+
onSelectedDateChange: onDateChange
|
|
463
|
+
}) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
464
|
+
"input",
|
|
465
|
+
{
|
|
466
|
+
type: "date",
|
|
467
|
+
value: toInputDateValue(value),
|
|
468
|
+
onChange: (event) => {
|
|
469
|
+
const nextDate = fromInputDateValue(event.target.value);
|
|
470
|
+
if (nextDate) {
|
|
471
|
+
onDateChange(nextDate);
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
className: "h-7 rounded-md border border-border bg-card px-2 text-xs text-foreground",
|
|
475
|
+
"aria-label": "Select date"
|
|
476
|
+
}
|
|
477
|
+
);
|
|
478
|
+
const defaultRenderResourceHeader = (resource) => /* @__PURE__ */ jsxRuntime.jsx("strong", { children: resource.label });
|
|
345
479
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
346
480
|
"section",
|
|
347
481
|
{
|
|
348
|
-
className: `rfs-root ${drag.kind === "move" ? "rfs-root--drag-move" : ""} ${drag.kind === "resize" ? "rfs-root--drag-resize" : ""}`,
|
|
482
|
+
className: `rfs-root rounded-lg bg-background text-foreground ${drag.kind === "move" ? "rfs-root--drag-move" : ""} ${drag.kind === "resize" ? "rfs-root--drag-resize" : ""}`,
|
|
349
483
|
onPointerMove: onGlobalPointerMove,
|
|
350
484
|
onPointerUp: onGlobalPointerUp,
|
|
351
485
|
onPointerCancel: onGlobalPointerUp,
|
|
352
486
|
children: [
|
|
353
487
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rfs-toolbar", children: [
|
|
354
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
355
|
-
|
|
356
|
-
|
|
488
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
489
|
+
"button",
|
|
490
|
+
{
|
|
491
|
+
className: "rfs-btn border-border bg-card text-foreground hover:bg-muted",
|
|
492
|
+
type: "button",
|
|
493
|
+
onClick: () => onSelectedDateChange(shiftDays(selectedDate, -1)),
|
|
494
|
+
children: prevButtonLabel
|
|
495
|
+
}
|
|
496
|
+
),
|
|
497
|
+
(renderDatePicker ?? defaultRenderDatePicker)({ selectedDate, onSelectedDateChange }),
|
|
498
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
499
|
+
"button",
|
|
500
|
+
{
|
|
501
|
+
className: "rfs-btn border-border bg-card text-foreground hover:bg-muted",
|
|
502
|
+
type: "button",
|
|
503
|
+
onClick: () => onSelectedDateChange(shiftDays(selectedDate, 1)),
|
|
504
|
+
children: nextButtonLabel
|
|
505
|
+
}
|
|
506
|
+
)
|
|
357
507
|
] }),
|
|
358
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rfs-shell", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minWidth: gridMinWidth }, children: [
|
|
359
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rfs-header", children: [
|
|
360
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rfs-gutter", style: { width: GUTTER_W } }),
|
|
361
|
-
resources.map((resource) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
508
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rfs-shell border-border bg-card", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { minWidth: gridMinWidth }, children: [
|
|
509
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rfs-header border-border bg-card", children: [
|
|
510
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rfs-gutter border-border", style: { width: GUTTER_W } }),
|
|
511
|
+
resources.map((resource) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
512
|
+
"div",
|
|
513
|
+
{
|
|
514
|
+
className: "rfs-resource-header border-border bg-card text-foreground",
|
|
515
|
+
style: { minWidth: RESOURCE_MIN_W, flex: 1 },
|
|
516
|
+
children: [
|
|
517
|
+
(renderResourceHeader ?? defaultRenderResourceHeader)(resource),
|
|
518
|
+
isNameLike(resource) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rfs-resource-subtitle text-muted-foreground", children: fullName(resource) }) : null
|
|
519
|
+
]
|
|
520
|
+
},
|
|
521
|
+
String(resource.id)
|
|
522
|
+
))
|
|
365
523
|
] }),
|
|
366
524
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rfs-body", children: [
|
|
367
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rfs-times", style: { width: GUTTER_W, height: gridHeight }, children: Array.from({ length: Math.floor(dayMinutes / 60) + 1 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
368
|
-
String(Math.floor((dayStartAbs + i * 60) / 60)).padStart(2, "0"),
|
|
369
|
-
":",
|
|
370
|
-
String((dayStartAbs + i * 60) % 60).padStart(2, "0")
|
|
371
|
-
] }, `tick-${i}`)) }),
|
|
372
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rfs-grid", children: resources.map((resource) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rfs-col", style: { minWidth: RESOURCE_MIN_W, flex: 1 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
525
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rfs-times border-border bg-card", style: { width: GUTTER_W, height: gridHeight }, children: Array.from({ length: Math.floor(dayMinutes / 60) + 1 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
373
526
|
"div",
|
|
374
527
|
{
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
},
|
|
378
|
-
className: "rfs-col-inner",
|
|
379
|
-
style: { height: gridHeight },
|
|
528
|
+
className: "rfs-time-tick text-muted-foreground",
|
|
529
|
+
style: { top: TOP_PAD + i * 60 * PX_PER_MIN },
|
|
380
530
|
children: [
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
531
|
+
String(Math.floor((dayStartAbs + i * 60) / 60)).padStart(2, "0"),
|
|
532
|
+
":",
|
|
533
|
+
String((dayStartAbs + i * 60) % 60).padStart(2, "0")
|
|
534
|
+
]
|
|
535
|
+
},
|
|
536
|
+
`tick-${i}`
|
|
537
|
+
)) }),
|
|
538
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rfs-grid", children: resources.map((resource) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
539
|
+
"div",
|
|
540
|
+
{
|
|
541
|
+
className: "rfs-col border-border bg-card",
|
|
542
|
+
style: { minWidth: RESOURCE_MIN_W, flex: 1 },
|
|
543
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
544
|
+
"div",
|
|
545
|
+
{
|
|
546
|
+
ref: (el) => {
|
|
547
|
+
colRefs.current[String(resource.id)] = el;
|
|
394
548
|
},
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
"div",
|
|
404
|
-
{
|
|
405
|
-
className: "rfs-card-slot",
|
|
406
|
-
style: {
|
|
407
|
-
top,
|
|
408
|
-
left: `${laneWidthPct * appointment.lane}%`,
|
|
409
|
-
width: `${laneWidthPct}%`,
|
|
410
|
-
height
|
|
549
|
+
className: "rfs-col-inner bg-card",
|
|
550
|
+
style: { height: gridHeight },
|
|
551
|
+
children: [
|
|
552
|
+
Array.from({ length: Math.floor(dayMinutes / 60) + 1 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
553
|
+
"div",
|
|
554
|
+
{
|
|
555
|
+
className: "rfs-hour-line border-border/70",
|
|
556
|
+
style: { top: TOP_PAD + i * 60 * PX_PER_MIN }
|
|
411
557
|
},
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
558
|
+
`major-${String(resource.id)}-${i}`
|
|
559
|
+
)),
|
|
560
|
+
Array.from({ length: Math.floor(dayMinutes / STEP_MIN) + 1 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
561
|
+
"div",
|
|
562
|
+
{
|
|
563
|
+
className: "rfs-slot-line border-border/50",
|
|
564
|
+
style: { top: TOP_PAD + i * STEP_MIN * PX_PER_MIN }
|
|
565
|
+
},
|
|
566
|
+
`minor-${String(resource.id)}-${i}`
|
|
567
|
+
)),
|
|
568
|
+
(laidOutByResource.get(resource.id) ?? []).map((appointment) => {
|
|
569
|
+
const laneWidthPct = 100 / appointment.lanes;
|
|
570
|
+
const top = TOP_PAD + appointment.startMin * PX_PER_MIN;
|
|
571
|
+
const height = Math.max(MIN_EVENT_MIN * PX_PER_MIN, (appointment.endMin - appointment.startMin) * PX_PER_MIN);
|
|
572
|
+
const appointmentAppearance = appointmentAppearanceByResource.get(resource.id);
|
|
573
|
+
const appointmentBackgroundColor = appointmentBgByResource.get(resource.id);
|
|
574
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
575
|
+
"div",
|
|
576
|
+
{
|
|
577
|
+
className: "rfs-card-slot",
|
|
578
|
+
style: {
|
|
579
|
+
top,
|
|
580
|
+
left: `${laneWidthPct * appointment.lane}%`,
|
|
581
|
+
width: `${laneWidthPct}%`,
|
|
582
|
+
height
|
|
583
|
+
},
|
|
584
|
+
children: (renderAppointment ?? defaultRenderAppointment)({
|
|
585
|
+
appointment,
|
|
586
|
+
onPointerDown: (event) => onApptPointerDown(event, appointment),
|
|
587
|
+
onResizePointerDown: (event) => onResizePointerDown(event, appointment),
|
|
588
|
+
appointmentAppearance,
|
|
589
|
+
appointmentBackgroundColor,
|
|
590
|
+
drag,
|
|
591
|
+
suppressClickRef
|
|
592
|
+
})
|
|
593
|
+
},
|
|
594
|
+
String(appointment.id)
|
|
595
|
+
);
|
|
596
|
+
})
|
|
597
|
+
]
|
|
598
|
+
}
|
|
599
|
+
)
|
|
600
|
+
},
|
|
601
|
+
String(resource.id)
|
|
602
|
+
)) })
|
|
427
603
|
] })
|
|
428
604
|
] }) })
|
|
429
605
|
]
|
|
@@ -431,6 +607,19 @@ function Scheduler({
|
|
|
431
607
|
);
|
|
432
608
|
}
|
|
433
609
|
|
|
610
|
+
// src/appointment-change.ts
|
|
611
|
+
function applySchedulerAppointmentChange(appointments, change, options) {
|
|
612
|
+
return appointments.map((item) => {
|
|
613
|
+
if (options.getId(item) !== options.getId(change.appointment)) {
|
|
614
|
+
return item;
|
|
615
|
+
}
|
|
616
|
+
const withResource = options.setResourceId(item, change.next.resourceId);
|
|
617
|
+
const withStart = options.setStart(withResource, change.next.start);
|
|
618
|
+
return options.setEnd(withStart, change.next.end);
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
|
|
434
622
|
exports.Scheduler = Scheduler;
|
|
623
|
+
exports.applySchedulerAppointmentChange = applySchedulerAppointmentChange;
|
|
435
624
|
//# sourceMappingURL=index.cjs.map
|
|
436
625
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/constants.ts","../src/components/utils.ts","../src/components/Scheduler.tsx"],"names":["format","React","pointerMin","nextEndMin","jsxs","jsx"],"mappings":"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","file":"index.cjs","sourcesContent":["const OPEN_TIME = '09:00';\nconst CLOSE_TIME = '18:00';\n\nconst STEP_MIN = 15;\nconst MIN_EVENT_MIN = 15;\nconst DEFAULT_CREATE_MIN = 30;\n\nconst PX_PER_MIN = 2; // visual scale\nconst HEADER_H = 56;\nconst GUTTER_W = 72;\nconst TOP_PAD = 12;\nconst BOTTOM_PAD = 24;\n\nconst RESOURCE_MIN_W = 420; // columns expand to fill available width; min width enables x-scroll when needed\nconst RESOURCE_MIN_W_TW = 'min-w-[400px] lg:w-full'; // columns expand to fill available width; min width enables x-scroll when needed\nconst LANE_GAP = 6;\n\nexport {\n OPEN_TIME,\n CLOSE_TIME,\n STEP_MIN,\n MIN_EVENT_MIN,\n DEFAULT_CREATE_MIN,\n PX_PER_MIN,\n HEADER_H,\n GUTTER_W,\n TOP_PAD,\n BOTTOM_PAD,\n RESOURCE_MIN_W,\n LANE_GAP,\n RESOURCE_MIN_W_TW,\n}","import { format } from \"date-fns\";\nimport { STEP_MIN } from \"./constants\";\n\ntype NameLike = {\n firstName?: string | null;\n lastName?: string | null;\n};\n\ntype TimeBlockLike<TId extends string | number = string | number> = {\n id: TId;\n startMin: number;\n endMin: number;\n};\n\ntype LaidOut<T extends TimeBlockLike> = T & {\n lane: number;\n lanes: number;\n};\n\nconst clamp = (n: number, min: number, max: number) => {\n return Math.max(min, Math.min(max, n));\n};\n\nconst snap = (mins: number, stepMin = STEP_MIN) => {\n return Math.round(mins / stepMin) * stepMin;\n};\n\nconst parseHHMM = (hhmm: string) => {\n const [h, m] = hhmm.split(\":\").map(Number);\n return h * 60 + m;\n};\n\nconst fullName = <T extends NameLike>(u: T) => {\n return `${u.firstName ?? \"\"} ${u.lastName ?? \"\"}`.trim();\n};\n\nconst dayISO = (d: Date) => {\n return format(d, \"yyyy-MM-dd\");\n};\n\nconst shiftDays = (d: Date, delta: number) => {\n return new Date(d.getFullYear(), d.getMonth(), d.getDate() + delta);\n};\n\nconst dateAtMinute = (\n selectedDate: Date,\n dayStartAbs: number,\n minuteFromStart: number\n) => {\n const base = new Date(\n selectedDate.getFullYear(),\n selectedDate.getMonth(),\n selectedDate.getDate(),\n 0,\n 0,\n 0,\n 0\n );\n const abs = dayStartAbs + minuteFromStart;\n const hh = Math.floor(abs / 60);\n const mm = abs % 60;\n base.setHours(hh, mm, 0, 0);\n return base;\n};\n\nconst minutesFromDayStart = (dayStartAbs: number, dt: Date) => {\n return dt.getHours() * 60 + dt.getMinutes() - dayStartAbs;\n};\n\nconst overlaps = (a: TimeBlockLike, b: TimeBlockLike) => {\n return a.startMin < b.endMin && b.startMin < a.endMin;\n};\n\nconst layoutOverlaps = <T extends TimeBlockLike>(blocks: T[]): LaidOut<T>[] => {\n const sorted = [...blocks].sort((a, b) => a.startMin - b.startMin || a.endMin - b.endMin);\n\n const groups: T[][] = [];\n let active: T[] = [];\n let current: T[] = [];\n\n for (const e of sorted) {\n active = active.filter((x) => x.endMin > e.startMin);\n const conflicts = active.some((x) => overlaps(x, e));\n\n if (!conflicts && current.length > 0) {\n groups.push(current);\n current = [];\n }\n current.push(e);\n active.push(e);\n }\n if (current.length) {\n groups.push(current);\n }\n\n const out: LaidOut<T>[] = [];\n\n for (const group of groups) {\n const g = [...group].sort((a, b) => a.startMin - b.startMin || a.endMin - b.endMin);\n const laneEnd: number[] = [];\n const laneOf = new Map<T[\"id\"], number>();\n\n for (const e of g) {\n let placed = false;\n for (let i = 0; i < laneEnd.length; i++) {\n if (laneEnd[i] <= e.startMin) {\n laneEnd[i] = e.endMin;\n laneOf.set(e.id, i);\n placed = true;\n break;\n }\n }\n if (!placed) {\n laneEnd.push(e.endMin);\n laneOf.set(e.id, laneEnd.length - 1);\n }\n }\n\n const lanes = laneEnd.length;\n for (const e of g) {\n out.push({ ...e, lane: laneOf.get(e.id) ?? 0, lanes });\n }\n }\n\n return out;\n};\n\nexport {\n clamp,\n snap,\n parseHHMM,\n fullName,\n dayISO,\n shiftDays,\n dateAtMinute,\n minutesFromDayStart,\n overlaps,\n layoutOverlaps,\n};\n","import * as React from \"react\";\nimport { BOTTOM_PAD, GUTTER_W, MIN_EVENT_MIN, PX_PER_MIN, RESOURCE_MIN_W, STEP_MIN, TOP_PAD } from \"./constants\";\nimport { clamp, dateAtMinute, dayISO, fullName, layoutOverlaps, minutesFromDayStart, overlaps, parseHHMM, shiftDays, snap } from \"./utils\";\nimport type { BaseSchedulerResource, SchedulerDragState, SchedulerEvent, SchedulerId, SchedulerProps } from \"../types/scheduler\";\n\nfunction isNameLike(resource: unknown): resource is { firstName?: string | null; lastName?: string | null } {\n if (!resource || typeof resource !== \"object\") {\n return false;\n }\n const maybe = resource as { firstName?: unknown; lastName?: unknown };\n return typeof maybe.firstName === \"string\" || typeof maybe.lastName === \"string\";\n}\n\nexport function Scheduler<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId>({\n resources,\n appointments,\n selectedDate,\n onSelectedDateChange,\n adapter,\n onPersistMoveResize,\n onAppointmentChange,\n renderResourceHeader,\n renderAppointment,\n getResourceAppointmentBackground,\n renderDatePicker,\n prevButtonLabel = \"Prev\",\n nextButtonLabel = \"Next\",\n dayStart = \"09:00\",\n dayEnd = \"18:00\"\n}: SchedulerProps<TAppointment, TResource, TResourceId>) {\n const [drag, setDrag] = React.useState<SchedulerDragState<TResourceId>>({ kind: \"none\" });\n const colRefs = React.useRef<Record<string, HTMLDivElement | null>>({});\n const suppressClickRef = React.useRef(false);\n\n const dayStartAbs = parseHHMM(dayStart);\n const dayEndAbs = parseHHMM(dayEnd);\n const dayMinutes = Math.max(0, dayEndAbs - dayStartAbs);\n const gridHeight = TOP_PAD + dayMinutes * PX_PER_MIN + BOTTOM_PAD;\n const gridMinWidth = GUTTER_W + Math.max(resources.length, 1) * RESOURCE_MIN_W;\n const selectedISO = React.useMemo(() => dayISO(selectedDate), [selectedDate]);\n\n const renderAppts = React.useMemo<SchedulerEvent<TAppointment, TResourceId>[]>(() => {\n return appointments\n .map((appointment) => {\n const start = new Date(adapter.getStart(appointment));\n const end = new Date(adapter.getEnd(appointment));\n return {\n raw: appointment,\n id: adapter.getId(appointment),\n resourceId: adapter.getResourceId(appointment),\n start,\n end,\n startMin: clamp(minutesFromDayStart(dayStartAbs, start), 0, dayMinutes),\n endMin: clamp(minutesFromDayStart(dayStartAbs, end), 0, dayMinutes),\n title: adapter.getTitle(appointment)\n };\n })\n .filter((appointment) => dayISO(appointment.start) === selectedISO);\n }, [appointments, adapter, dayStartAbs, dayMinutes, selectedISO]);\n\n const appointmentMap = React.useMemo(() => {\n return new Map(renderAppts.map((appointment) => [appointment.id, appointment]));\n }, [renderAppts]);\n\n const effectiveAppts = React.useMemo<SchedulerEvent<TAppointment, TResourceId>[]>(() => {\n if (drag.kind === \"none\") {\n return renderAppts;\n }\n return renderAppts.map((appointment) => {\n if (appointment.id !== drag.appointmentId) {\n return appointment;\n }\n return {\n ...appointment,\n resourceId: drag.resourceId,\n startMin: drag.startMin,\n endMin: drag.endMin,\n start: dateAtMinute(selectedDate, dayStartAbs, drag.startMin),\n end: dateAtMinute(selectedDate, dayStartAbs, drag.endMin)\n };\n });\n }, [drag, renderAppts, selectedDate, dayStartAbs]);\n\n const laidOutByResource = React.useMemo(() => {\n const byResource = new Map<TResourceId, ReturnType<typeof layoutOverlaps<SchedulerEvent<TAppointment, TResourceId>>>>();\n for (const resource of resources) {\n const events = effectiveAppts.filter((appointment) => appointment.resourceId === resource.id);\n byResource.set(resource.id, layoutOverlaps(events));\n }\n return byResource;\n }, [effectiveAppts, resources]);\n\n const appointmentBgByResource = React.useMemo(() => {\n const map = new Map<TResourceId, string | undefined>();\n if (!getResourceAppointmentBackground) {\n return map;\n }\n for (const resource of resources) {\n map.set(resource.id, getResourceAppointmentBackground(resource));\n }\n return map;\n }, [getResourceAppointmentBackground, resources]);\n\n const pointerToMin = (resourceId: TResourceId, clientY: number) => {\n const col = colRefs.current[String(resourceId)];\n if (!col) {\n return 0;\n }\n const y = clientY - col.getBoundingClientRect().top - TOP_PAD;\n return clamp(snap(y / PX_PER_MIN), 0, dayMinutes);\n };\n\n const pointerToResourceId = (clientX: number, fallbackResourceId: TResourceId) => {\n for (const resource of resources) {\n const col = colRefs.current[String(resource.id)];\n if (!col) {\n continue;\n }\n const rect = col.getBoundingClientRect();\n if (clientX >= rect.left && clientX <= rect.right) {\n return resource.id;\n }\n }\n return fallbackResourceId;\n };\n\n const hasOverlap = (appointmentId: SchedulerId, resourceId: TResourceId, startMin: number, endMin: number) => {\n const events = renderAppts.filter((appointment) => appointment.resourceId === resourceId && appointment.id !== appointmentId);\n return events.some((appointment) => overlaps(appointment, { id: appointmentId, startMin, endMin }));\n };\n\n const persistDrag = async (state: Exclude<SchedulerDragState<TResourceId>, { kind: \"none\" }>) => {\n const target = appointmentMap.get(state.appointmentId);\n if (!target) {\n return;\n }\n if (hasOverlap(state.appointmentId, state.resourceId, state.startMin, state.endMin)) {\n return;\n }\n const next = {\n resourceId: state.resourceId,\n start: dateAtMinute(selectedDate, dayStartAbs, state.startMin),\n end: dateAtMinute(selectedDate, dayStartAbs, state.endMin)\n };\n\n if (onAppointmentChange) {\n await onAppointmentChange({\n kind: state.kind,\n appointment: target.raw,\n previous: {\n resourceId: target.resourceId,\n start: target.start,\n end: target.end\n },\n next\n });\n return;\n }\n\n if (onPersistMoveResize) {\n await onPersistMoveResize({\n appointment: target.raw,\n resourceId: next.resourceId,\n start: next.start,\n end: next.end\n });\n }\n };\n\n const onApptPointerDown = (event: React.PointerEvent, appointment: SchedulerEvent<TAppointment, TResourceId>) => {\n if (event.button !== 0) {\n return;\n }\n event.stopPropagation();\n suppressClickRef.current = false;\n const pointerMin = pointerToMin(appointment.resourceId, event.clientY);\n setDrag({\n kind: \"move\",\n appointmentId: appointment.id,\n pointerId: event.pointerId,\n resourceId: appointment.resourceId,\n durationMin: Math.max(MIN_EVENT_MIN, appointment.endMin - appointment.startMin),\n offsetMin: pointerMin - appointment.startMin,\n startMin: appointment.startMin,\n endMin: appointment.endMin\n });\n };\n\n const onResizePointerDown = (event: React.PointerEvent, appointment: SchedulerEvent<TAppointment, TResourceId>) => {\n if (event.button !== 0) {\n return;\n }\n event.stopPropagation();\n suppressClickRef.current = false;\n setDrag({\n kind: \"resize\",\n appointmentId: appointment.id,\n pointerId: event.pointerId,\n resourceId: appointment.resourceId,\n startMin: appointment.startMin,\n endMin: appointment.endMin\n });\n };\n\n const onGlobalPointerMove = (event: React.PointerEvent<HTMLElement>) => {\n if (drag.kind === \"none\") {\n return;\n }\n\n if (drag.kind === \"move\") {\n const nextResourceId = pointerToResourceId(event.clientX, drag.resourceId);\n const pointerMin = pointerToMin(nextResourceId, event.clientY);\n const rawStart = pointerMin - drag.offsetMin;\n const nextStartMin = clamp(snap(rawStart), 0, dayMinutes - drag.durationMin);\n const nextEndMin = nextStartMin + drag.durationMin;\n if (nextStartMin !== drag.startMin || nextEndMin !== drag.endMin || nextResourceId !== drag.resourceId) {\n suppressClickRef.current = true;\n setDrag({\n ...drag,\n resourceId: nextResourceId,\n startMin: nextStartMin,\n endMin: nextEndMin\n });\n }\n return;\n }\n\n const pointerMin = pointerToMin(drag.resourceId, event.clientY);\n const nextEndMin = clamp(snap(pointerMin), drag.startMin + MIN_EVENT_MIN, dayMinutes);\n if (nextEndMin !== drag.endMin) {\n suppressClickRef.current = true;\n setDrag({\n ...drag,\n endMin: nextEndMin\n });\n }\n };\n\n const onGlobalPointerUp = () => {\n if (drag.kind === \"none\") {\n return;\n }\n const current = drag;\n setDrag({ kind: \"none\" });\n if (suppressClickRef.current) {\n void persistDrag(current);\n }\n };\n\n return (\n <section\n className={`rfs-root ${drag.kind === \"move\" ? \"rfs-root--drag-move\" : \"\"} ${drag.kind === \"resize\" ? \"rfs-root--drag-resize\" : \"\"}`}\n onPointerMove={onGlobalPointerMove}\n onPointerUp={onGlobalPointerUp}\n onPointerCancel={onGlobalPointerUp}\n >\n <div className=\"rfs-toolbar\">\n <button className=\"rfs-btn\" type=\"button\" onClick={() => onSelectedDateChange(shiftDays(selectedDate, -1))}>\n {prevButtonLabel}\n </button>\n {renderDatePicker ? (\n renderDatePicker({ selectedDate, onSelectedDateChange })\n ) : (\n <strong className=\"rfs-date-label\">{selectedISO}</strong>\n )}\n <button className=\"rfs-btn\" type=\"button\" onClick={() => onSelectedDateChange(shiftDays(selectedDate, 1))}>\n {nextButtonLabel}\n </button>\n </div>\n\n <div className=\"rfs-shell\">\n <div style={{ minWidth: gridMinWidth }}>\n <div className=\"rfs-header\">\n <div className=\"rfs-gutter\" style={{ width: GUTTER_W }} />\n {resources.map((resource) => (\n <div key={String(resource.id)} className=\"rfs-resource-header\" style={{ minWidth: RESOURCE_MIN_W, flex: 1 }}>\n {renderResourceHeader(resource)}\n {isNameLike(resource) ? <div className=\"rfs-resource-subtitle\">{fullName(resource)}</div> : null}\n </div>\n ))}\n </div>\n <div className=\"rfs-body\">\n <div className=\"rfs-times\" style={{ width: GUTTER_W, height: gridHeight }}>\n {Array.from({ length: Math.floor(dayMinutes / 60) + 1 }).map((_, i) => (\n <div key={`tick-${i}`} className=\"rfs-time-tick\" style={{ top: TOP_PAD + i * 60 * PX_PER_MIN }}>\n {String(Math.floor((dayStartAbs + i * 60) / 60)).padStart(2, \"0\")}:\n {String((dayStartAbs + i * 60) % 60).padStart(2, \"0\")}\n </div>\n ))}\n </div>\n <div className=\"rfs-grid\">\n {resources.map((resource) => (\n <div key={String(resource.id)} className=\"rfs-col\" style={{ minWidth: RESOURCE_MIN_W, flex: 1 }}>\n <div\n ref={(el) => {\n colRefs.current[String(resource.id)] = el;\n }}\n className=\"rfs-col-inner\"\n style={{ height: gridHeight }}\n >\n {Array.from({ length: Math.floor(dayMinutes / 60) + 1 }).map((_, i) => (\n <div\n key={`major-${String(resource.id)}-${i}`}\n className=\"rfs-hour-line\"\n style={{ top: TOP_PAD + i * 60 * PX_PER_MIN }}\n />\n ))}\n {Array.from({ length: Math.floor(dayMinutes / STEP_MIN) + 1 }).map((_, i) => (\n <div\n key={`minor-${String(resource.id)}-${i}`}\n className=\"rfs-slot-line\"\n style={{ top: TOP_PAD + i * STEP_MIN * PX_PER_MIN }}\n />\n ))}\n {(laidOutByResource.get(resource.id) ?? []).map((appointment) => {\n const laneWidthPct = 100 / appointment.lanes;\n const top = TOP_PAD + appointment.startMin * PX_PER_MIN;\n const height = Math.max(MIN_EVENT_MIN * PX_PER_MIN, (appointment.endMin - appointment.startMin) * PX_PER_MIN);\n const appointmentBackgroundColor = appointmentBgByResource.get(resource.id);\n return (\n <div\n key={String(appointment.id)}\n className=\"rfs-card-slot\"\n style={{\n top,\n left: `${laneWidthPct * appointment.lane}%`,\n width: `${laneWidthPct}%`,\n height\n }}\n >\n {renderAppointment({\n appointment,\n onPointerDown: (event) => onApptPointerDown(event, appointment),\n onResizePointerDown: (event) => onResizePointerDown(event, appointment),\n appointmentBackgroundColor,\n drag,\n suppressClickRef\n })}\n </div>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n </section>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/constants.ts","../src/components/utils.ts","../src/components/Scheduler.tsx","../src/appointment-change.ts"],"names":["format","React","pointerMin","nextEndMin","onResizePointerDown","jsxs","jsx"],"mappings":"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","file":"index.cjs","sourcesContent":["const OPEN_TIME = '09:00';\r\nconst CLOSE_TIME = '18:00';\r\n\r\nconst STEP_MIN = 15;\r\nconst MIN_EVENT_MIN = 15;\r\nconst DEFAULT_CREATE_MIN = 30;\r\n\r\nconst PX_PER_MIN = 2; // visual scale\r\nconst HEADER_H = 56;\r\nconst GUTTER_W = 72;\r\nconst TOP_PAD = 12;\r\nconst BOTTOM_PAD = 24;\r\n\r\nconst RESOURCE_MIN_W = 420; // columns expand to fill available width; min width enables x-scroll when needed\r\nconst RESOURCE_MIN_W_TW = 'min-w-[400px] lg:w-full'; // columns expand to fill available width; min width enables x-scroll when needed\r\nconst LANE_GAP = 6;\r\n\r\nexport {\r\n OPEN_TIME,\r\n CLOSE_TIME,\r\n STEP_MIN,\r\n MIN_EVENT_MIN,\r\n DEFAULT_CREATE_MIN,\r\n PX_PER_MIN,\r\n HEADER_H,\r\n GUTTER_W,\r\n TOP_PAD,\r\n BOTTOM_PAD,\r\n RESOURCE_MIN_W,\r\n LANE_GAP,\r\n RESOURCE_MIN_W_TW,\r\n}","import { format } from \"date-fns\";\r\nimport { STEP_MIN } from \"./constants\";\r\n\r\ntype NameLike = {\r\n firstName?: string | null;\r\n lastName?: string | null;\r\n};\r\n\r\ntype TimeBlockLike<TId extends string | number = string | number> = {\r\n id: TId;\r\n startMin: number;\r\n endMin: number;\r\n};\r\n\r\ntype LaidOut<T extends TimeBlockLike> = T & {\r\n lane: number;\r\n lanes: number;\r\n};\r\n\r\nconst clamp = (n: number, min: number, max: number) => {\r\n return Math.max(min, Math.min(max, n));\r\n};\r\n\r\nconst snap = (mins: number, stepMin = STEP_MIN) => {\r\n return Math.round(mins / stepMin) * stepMin;\r\n};\r\n\r\nconst parseHHMM = (hhmm: string) => {\r\n const [h, m] = hhmm.split(\":\").map(Number);\r\n return h * 60 + m;\r\n};\r\n\r\nconst fullName = <T extends NameLike>(u: T) => {\r\n return `${u.firstName ?? \"\"} ${u.lastName ?? \"\"}`.trim();\r\n};\r\n\r\nconst dayISO = (d: Date) => {\r\n return format(d, \"yyyy-MM-dd\");\r\n};\r\n\r\nconst shiftDays = (d: Date, delta: number) => {\r\n return new Date(d.getFullYear(), d.getMonth(), d.getDate() + delta);\r\n};\r\n\r\nconst dateAtMinute = (\r\n selectedDate: Date,\r\n dayStartAbs: number,\r\n minuteFromStart: number\r\n) => {\r\n const base = new Date(\r\n selectedDate.getFullYear(),\r\n selectedDate.getMonth(),\r\n selectedDate.getDate(),\r\n 0,\r\n 0,\r\n 0,\r\n 0\r\n );\r\n const abs = dayStartAbs + minuteFromStart;\r\n const hh = Math.floor(abs / 60);\r\n const mm = abs % 60;\r\n base.setHours(hh, mm, 0, 0);\r\n return base;\r\n};\r\n\r\nconst minutesFromDayStart = (dayStartAbs: number, dt: Date) => {\r\n return dt.getHours() * 60 + dt.getMinutes() - dayStartAbs;\r\n};\r\n\r\nconst overlaps = (a: TimeBlockLike, b: TimeBlockLike) => {\r\n return a.startMin < b.endMin && b.startMin < a.endMin;\r\n};\r\n\r\nconst layoutOverlaps = <T extends TimeBlockLike>(blocks: T[]): LaidOut<T>[] => {\r\n const sorted = [...blocks].sort((a, b) => a.startMin - b.startMin || a.endMin - b.endMin);\r\n\r\n const groups: T[][] = [];\r\n let active: T[] = [];\r\n let current: T[] = [];\r\n\r\n for (const e of sorted) {\r\n active = active.filter((x) => x.endMin > e.startMin);\r\n const conflicts = active.some((x) => overlaps(x, e));\r\n\r\n if (!conflicts && current.length > 0) {\r\n groups.push(current);\r\n current = [];\r\n }\r\n current.push(e);\r\n active.push(e);\r\n }\r\n if (current.length) {\r\n groups.push(current);\r\n }\r\n\r\n const out: LaidOut<T>[] = [];\r\n\r\n for (const group of groups) {\r\n const g = [...group].sort((a, b) => a.startMin - b.startMin || a.endMin - b.endMin);\r\n const laneEnd: number[] = [];\r\n const laneOf = new Map<T[\"id\"], number>();\r\n\r\n for (const e of g) {\r\n let placed = false;\r\n for (let i = 0; i < laneEnd.length; i++) {\r\n if (laneEnd[i] <= e.startMin) {\r\n laneEnd[i] = e.endMin;\r\n laneOf.set(e.id, i);\r\n placed = true;\r\n break;\r\n }\r\n }\r\n if (!placed) {\r\n laneEnd.push(e.endMin);\r\n laneOf.set(e.id, laneEnd.length - 1);\r\n }\r\n }\r\n\r\n const lanes = laneEnd.length;\r\n for (const e of g) {\r\n out.push({ ...e, lane: laneOf.get(e.id) ?? 0, lanes });\r\n }\r\n }\r\n\r\n return out;\r\n};\r\n\r\nexport {\r\n clamp,\r\n snap,\r\n parseHHMM,\r\n fullName,\r\n dayISO,\r\n shiftDays,\r\n dateAtMinute,\r\n minutesFromDayStart,\r\n overlaps,\r\n layoutOverlaps,\r\n};\r\n","import * as React from \"react\";\r\nimport { BOTTOM_PAD, GUTTER_W, MIN_EVENT_MIN, PX_PER_MIN, RESOURCE_MIN_W, STEP_MIN, TOP_PAD } from \"./constants\";\r\nimport { clamp, dateAtMinute, dayISO, fullName, layoutOverlaps, minutesFromDayStart, overlaps, parseHHMM, shiftDays, snap } from \"./utils\";\r\nimport type {\r\n BaseSchedulerResource,\r\n SchedulerAppointmentAppearance,\r\n SchedulerAppointmentColorToken,\r\n SchedulerDragState,\r\n SchedulerEvent,\r\n SchedulerId,\r\n SchedulerProps\r\n} from \"../types/scheduler\";\r\n\r\nfunction isNameLike(resource: unknown): resource is { firstName?: string | null; lastName?: string | null } {\r\n if (!resource || typeof resource !== \"object\") {\r\n return false;\r\n }\r\n const maybe = resource as { firstName?: unknown; lastName?: unknown };\r\n return typeof maybe.firstName === \"string\" || typeof maybe.lastName === \"string\";\r\n}\r\n\r\nfunction toInputDateValue(date: Date): string {\r\n const year = date.getFullYear();\r\n const month = String(date.getMonth() + 1).padStart(2, \"0\");\r\n const day = String(date.getDate()).padStart(2, \"0\");\r\n return `${year}-${month}-${day}`;\r\n}\r\n\r\nfunction fromInputDateValue(value: string): Date | null {\r\n const [yearRaw, monthRaw, dayRaw] = value.split(\"-\");\r\n const year = Number(yearRaw);\r\n const month = Number(monthRaw);\r\n const day = Number(dayRaw);\r\n if (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day)) {\r\n return null;\r\n }\r\n return new Date(year, month - 1, day);\r\n}\r\n\r\nconst DEFAULT_APPOINTMENT_COLOR_TOKEN_CLASS_MAP: Record<SchedulerAppointmentColorToken, string> = {\r\n slate: \"bg-slate-100 dark:bg-slate-900/40\",\r\n gray: \"bg-gray-100 dark:bg-gray-900/40\",\r\n zinc: \"bg-zinc-100 dark:bg-zinc-900/40\",\r\n neutral: \"bg-neutral-100 dark:bg-neutral-900/40\",\r\n stone: \"bg-stone-100 dark:bg-stone-900/40\",\r\n red: \"bg-red-100 dark:bg-red-950/40\",\r\n orange: \"bg-orange-100 dark:bg-orange-950/40\",\r\n amber: \"bg-amber-100 dark:bg-amber-950/40\",\r\n yellow: \"bg-yellow-100 dark:bg-yellow-950/40\",\r\n lime: \"bg-lime-100 dark:bg-lime-950/40\",\r\n green: \"bg-green-100 dark:bg-green-950/40\",\r\n emerald: \"bg-emerald-100 dark:bg-emerald-950/40\",\r\n teal: \"bg-teal-100 dark:bg-teal-950/40\",\r\n cyan: \"bg-cyan-100 dark:bg-cyan-950/40\",\r\n sky: \"bg-sky-100 dark:bg-sky-950/40\",\r\n blue: \"bg-blue-100 dark:bg-blue-950/40\",\r\n indigo: \"bg-indigo-100 dark:bg-indigo-950/40\",\r\n violet: \"bg-violet-100 dark:bg-violet-950/40\",\r\n purple: \"bg-purple-100 dark:bg-purple-950/40\",\r\n fuchsia: \"bg-fuchsia-100 dark:bg-fuchsia-950/40\",\r\n pink: \"bg-pink-100 dark:bg-pink-950/40\",\r\n rose: \"bg-rose-100 dark:bg-rose-950/40\"\r\n};\r\n\r\nexport function Scheduler<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId>({\r\n resources,\r\n appointments,\r\n selectedDate,\r\n onSelectedDateChange,\r\n adapter,\r\n onPersistMoveResize,\r\n onAppointmentChange,\r\n renderResourceHeader,\r\n renderAppointment,\r\n resourceAppointmentClassMap,\r\n getResourceAppointmentAppearance,\r\n getResourceAppointmentColorToken,\r\n appointmentColorTokenClassMap,\r\n getResourceAppointmentBackground,\r\n renderDatePicker,\r\n prevButtonLabel = \"Prev\",\r\n nextButtonLabel = \"Next\",\r\n dayStart = \"09:00\",\r\n dayEnd = \"18:00\"\r\n}: SchedulerProps<TAppointment, TResource, TResourceId>) {\r\n const [drag, setDrag] = React.useState<SchedulerDragState<TResourceId>>({ kind: \"none\" });\r\n const colRefs = React.useRef<Record<string, HTMLDivElement | null>>({});\r\n const suppressClickRef = React.useRef(false);\r\n\r\n const dayStartAbs = parseHHMM(dayStart);\r\n const dayEndAbs = parseHHMM(dayEnd);\r\n const dayMinutes = Math.max(0, dayEndAbs - dayStartAbs);\r\n const gridHeight = TOP_PAD + dayMinutes * PX_PER_MIN + BOTTOM_PAD;\r\n const gridMinWidth = GUTTER_W + Math.max(resources.length, 1) * RESOURCE_MIN_W;\r\n const selectedISO = React.useMemo(() => dayISO(selectedDate), [selectedDate]);\r\n\r\n const renderAppts = React.useMemo<SchedulerEvent<TAppointment, TResourceId>[]>(() => {\r\n return appointments\r\n .map((appointment) => {\r\n const start = new Date(adapter.getStart(appointment));\r\n const end = new Date(adapter.getEnd(appointment));\r\n return {\r\n raw: appointment,\r\n id: adapter.getId(appointment),\r\n resourceId: adapter.getResourceId(appointment),\r\n start,\r\n end,\r\n startMin: clamp(minutesFromDayStart(dayStartAbs, start), 0, dayMinutes),\r\n endMin: clamp(minutesFromDayStart(dayStartAbs, end), 0, dayMinutes),\r\n title: adapter.getTitle(appointment)\r\n };\r\n })\r\n .filter((appointment) => dayISO(appointment.start) === selectedISO);\r\n }, [appointments, adapter, dayStartAbs, dayMinutes, selectedISO]);\r\n\r\n const appointmentMap = React.useMemo(() => {\r\n return new Map(renderAppts.map((appointment) => [appointment.id, appointment]));\r\n }, [renderAppts]);\r\n\r\n const effectiveAppts = React.useMemo<SchedulerEvent<TAppointment, TResourceId>[]>(() => {\r\n if (drag.kind === \"none\") {\r\n return renderAppts;\r\n }\r\n return renderAppts.map((appointment) => {\r\n if (appointment.id !== drag.appointmentId) {\r\n return appointment;\r\n }\r\n return {\r\n ...appointment,\r\n resourceId: drag.resourceId,\r\n startMin: drag.startMin,\r\n endMin: drag.endMin,\r\n start: dateAtMinute(selectedDate, dayStartAbs, drag.startMin),\r\n end: dateAtMinute(selectedDate, dayStartAbs, drag.endMin)\r\n };\r\n });\r\n }, [drag, renderAppts, selectedDate, dayStartAbs]);\r\n\r\n const laidOutByResource = React.useMemo(() => {\r\n const byResource = new Map<TResourceId, ReturnType<typeof layoutOverlaps<SchedulerEvent<TAppointment, TResourceId>>>>();\r\n for (const resource of resources) {\r\n const events = effectiveAppts.filter((appointment) => appointment.resourceId === resource.id);\r\n byResource.set(resource.id, layoutOverlaps(events));\r\n }\r\n return byResource;\r\n }, [effectiveAppts, resources]);\r\n\r\n const appointmentBgByResource = React.useMemo(() => {\r\n const map = new Map<TResourceId, string | undefined>();\r\n if (!getResourceAppointmentBackground) {\r\n return map;\r\n }\r\n for (const resource of resources) {\r\n map.set(resource.id, getResourceAppointmentBackground(resource));\r\n }\r\n return map;\r\n }, [getResourceAppointmentBackground, resources]);\r\n\r\n const appointmentColorTokenClassByResource = React.useMemo(() => {\r\n const map = new Map<TResourceId, string | undefined>();\r\n const mergedClassMap = {\r\n ...DEFAULT_APPOINTMENT_COLOR_TOKEN_CLASS_MAP,\r\n ...(appointmentColorTokenClassMap ?? {})\r\n };\r\n if (!getResourceAppointmentColorToken) {\r\n return map;\r\n }\r\n for (const resource of resources) {\r\n const token = getResourceAppointmentColorToken(resource);\r\n map.set(resource.id, token ? mergedClassMap[token] : undefined);\r\n }\r\n return map;\r\n }, [appointmentColorTokenClassMap, getResourceAppointmentColorToken, resources]);\r\n\r\n const appointmentAppearanceByResource = React.useMemo(() => {\r\n const map = new Map<TResourceId, SchedulerAppointmentAppearance | undefined>();\r\n for (const resource of resources) {\r\n const classFromIdMap = resourceAppointmentClassMap?.[String(resource.id)];\r\n if (classFromIdMap) {\r\n map.set(resource.id, { className: classFromIdMap });\r\n continue;\r\n }\r\n const appearance = getResourceAppointmentAppearance?.(resource);\r\n if (appearance) {\r\n map.set(resource.id, appearance);\r\n continue;\r\n }\r\n const tokenClass = appointmentColorTokenClassByResource.get(resource.id);\r\n if (tokenClass) {\r\n map.set(resource.id, { className: tokenClass });\r\n continue;\r\n }\r\n const legacyBackground = appointmentBgByResource.get(resource.id);\r\n if (!legacyBackground) {\r\n map.set(resource.id, undefined);\r\n continue;\r\n }\r\n map.set(resource.id, { className: legacyBackground });\r\n }\r\n return map;\r\n }, [appointmentBgByResource, appointmentColorTokenClassByResource, getResourceAppointmentAppearance, resourceAppointmentClassMap, resources]);\r\n\r\n const pointerToMin = (resourceId: TResourceId, clientY: number) => {\r\n const col = colRefs.current[String(resourceId)];\r\n if (!col) {\r\n return 0;\r\n }\r\n const y = clientY - col.getBoundingClientRect().top - TOP_PAD;\r\n return clamp(snap(y / PX_PER_MIN), 0, dayMinutes);\r\n };\r\n\r\n const pointerToResourceId = (clientX: number, fallbackResourceId: TResourceId) => {\r\n for (const resource of resources) {\r\n const col = colRefs.current[String(resource.id)];\r\n if (!col) {\r\n continue;\r\n }\r\n const rect = col.getBoundingClientRect();\r\n if (clientX >= rect.left && clientX <= rect.right) {\r\n return resource.id;\r\n }\r\n }\r\n return fallbackResourceId;\r\n };\r\n\r\n const hasOverlap = (appointmentId: SchedulerId, resourceId: TResourceId, startMin: number, endMin: number) => {\r\n const events = renderAppts.filter((appointment) => appointment.resourceId === resourceId && appointment.id !== appointmentId);\r\n return events.some((appointment) => overlaps(appointment, { id: appointmentId, startMin, endMin }));\r\n };\r\n\r\n const persistDrag = async (state: Exclude<SchedulerDragState<TResourceId>, { kind: \"none\" }>) => {\r\n const target = appointmentMap.get(state.appointmentId);\r\n if (!target) {\r\n return;\r\n }\r\n if (hasOverlap(state.appointmentId, state.resourceId, state.startMin, state.endMin)) {\r\n return;\r\n }\r\n const next = {\r\n resourceId: state.resourceId,\r\n start: dateAtMinute(selectedDate, dayStartAbs, state.startMin),\r\n end: dateAtMinute(selectedDate, dayStartAbs, state.endMin)\r\n };\r\n\r\n if (onAppointmentChange) {\r\n await onAppointmentChange({\r\n kind: state.kind,\r\n appointment: target.raw,\r\n previous: {\r\n resourceId: target.resourceId,\r\n start: target.start,\r\n end: target.end\r\n },\r\n next\r\n });\r\n return;\r\n }\r\n\r\n if (onPersistMoveResize) {\r\n await onPersistMoveResize({\r\n appointment: target.raw,\r\n resourceId: next.resourceId,\r\n start: next.start,\r\n end: next.end\r\n });\r\n }\r\n };\r\n\r\n const onApptPointerDown = (event: React.PointerEvent, appointment: SchedulerEvent<TAppointment, TResourceId>) => {\r\n if (event.button !== 0) {\r\n return;\r\n }\r\n event.stopPropagation();\r\n suppressClickRef.current = false;\r\n const pointerMin = pointerToMin(appointment.resourceId, event.clientY);\r\n setDrag({\r\n kind: \"move\",\r\n appointmentId: appointment.id,\r\n pointerId: event.pointerId,\r\n resourceId: appointment.resourceId,\r\n durationMin: Math.max(MIN_EVENT_MIN, appointment.endMin - appointment.startMin),\r\n offsetMin: pointerMin - appointment.startMin,\r\n startMin: appointment.startMin,\r\n endMin: appointment.endMin\r\n });\r\n };\r\n\r\n const onResizePointerDown = (event: React.PointerEvent, appointment: SchedulerEvent<TAppointment, TResourceId>) => {\r\n if (event.button !== 0) {\r\n return;\r\n }\r\n event.stopPropagation();\r\n suppressClickRef.current = false;\r\n setDrag({\r\n kind: \"resize\",\r\n appointmentId: appointment.id,\r\n pointerId: event.pointerId,\r\n resourceId: appointment.resourceId,\r\n startMin: appointment.startMin,\r\n endMin: appointment.endMin\r\n });\r\n };\r\n\r\n const onGlobalPointerMove = (event: React.PointerEvent<HTMLElement>) => {\r\n if (drag.kind === \"none\") {\r\n return;\r\n }\r\n\r\n if (drag.kind === \"move\") {\r\n const nextResourceId = pointerToResourceId(event.clientX, drag.resourceId);\r\n const pointerMin = pointerToMin(nextResourceId, event.clientY);\r\n const rawStart = pointerMin - drag.offsetMin;\r\n const nextStartMin = clamp(snap(rawStart), 0, dayMinutes - drag.durationMin);\r\n const nextEndMin = nextStartMin + drag.durationMin;\r\n if (nextStartMin !== drag.startMin || nextEndMin !== drag.endMin || nextResourceId !== drag.resourceId) {\r\n suppressClickRef.current = true;\r\n setDrag({\r\n ...drag,\r\n resourceId: nextResourceId,\r\n startMin: nextStartMin,\r\n endMin: nextEndMin\r\n });\r\n }\r\n return;\r\n }\r\n\r\n const pointerMin = pointerToMin(drag.resourceId, event.clientY);\r\n const nextEndMin = clamp(snap(pointerMin), drag.startMin + MIN_EVENT_MIN, dayMinutes);\r\n if (nextEndMin !== drag.endMin) {\r\n suppressClickRef.current = true;\r\n setDrag({\r\n ...drag,\r\n endMin: nextEndMin\r\n });\r\n }\r\n };\r\n\r\n const onGlobalPointerUp = () => {\r\n if (drag.kind === \"none\") {\r\n return;\r\n }\r\n const current = drag;\r\n setDrag({ kind: \"none\" });\r\n if (suppressClickRef.current) {\r\n void persistDrag(current);\r\n }\r\n };\r\n\r\n const defaultRenderAppointment = ({\r\n appointment,\r\n onPointerDown,\r\n onResizePointerDown,\r\n appointmentAppearance,\r\n appointmentBackgroundColor\r\n }: {\r\n appointment: SchedulerEvent<TAppointment, TResourceId> & { lane: number; lanes: number };\r\n onPointerDown: (e: React.PointerEvent) => void;\r\n onResizePointerDown: (e: React.PointerEvent) => void;\r\n appointmentAppearance?: SchedulerAppointmentAppearance;\r\n appointmentBackgroundColor?: string;\r\n drag: SchedulerDragState<TResourceId>;\r\n suppressClickRef: React.RefObject<boolean>;\r\n }) => {\r\n const rawMaybe = appointment.raw as { description?: unknown };\r\n const description = typeof rawMaybe.description === \"string\" ? rawMaybe.description : undefined;\r\n const legacyClassName = typeof appointmentBackgroundColor === \"string\" ? appointmentBackgroundColor : undefined;\r\n const backgroundClassName = appointmentAppearance?.className ?? legacyClassName ?? \"bg-muted/40 dark:bg-muted/30\";\r\n const className = `relative h-full cursor-grab overflow-hidden rounded-md border border-border p-2 pb-5 text-foreground ${backgroundClassName}`;\r\n\r\n return (\r\n <div onPointerDown={onPointerDown} className={className}>\r\n <div className=\"text-xs font-semibold\">{appointment.title}</div>\r\n {description ? <div className=\"mt-1 text-[10px] font-medium text-muted-foreground\">{description}</div> : null}\r\n <div\r\n role=\"button\"\r\n aria-label=\"Resize appointment\"\r\n onPointerDown={(event) => {\r\n event.stopPropagation();\r\n onResizePointerDown(event);\r\n }}\r\n className=\"absolute inset-x-1 bottom-1 h-2 cursor-ns-resize rounded-full bg-border/90 transition-colors hover:bg-border\"\r\n />\r\n </div>\r\n );\r\n };\r\n\r\n const defaultRenderDatePicker = ({\r\n selectedDate: value,\r\n onSelectedDateChange: onDateChange\r\n }: {\r\n selectedDate: Date;\r\n onSelectedDateChange: (date: Date) => void;\r\n }) => (\r\n <input\r\n type=\"date\"\r\n value={toInputDateValue(value)}\r\n onChange={(event) => {\r\n const nextDate = fromInputDateValue(event.target.value);\r\n if (nextDate) {\r\n onDateChange(nextDate);\r\n }\r\n }}\r\n className=\"h-7 rounded-md border border-border bg-card px-2 text-xs text-foreground\"\r\n aria-label=\"Select date\"\r\n />\r\n );\r\n\r\n const defaultRenderResourceHeader = (resource: TResource) => <strong>{resource.label}</strong>;\r\n\r\n return (\r\n <section\r\n className={`rfs-root rounded-lg bg-background text-foreground ${drag.kind === \"move\" ? \"rfs-root--drag-move\" : \"\"} ${drag.kind === \"resize\" ? \"rfs-root--drag-resize\" : \"\"}`}\r\n onPointerMove={onGlobalPointerMove}\r\n onPointerUp={onGlobalPointerUp}\r\n onPointerCancel={onGlobalPointerUp}\r\n >\r\n <div className=\"rfs-toolbar\">\r\n <button\r\n className=\"rfs-btn border-border bg-card text-foreground hover:bg-muted\"\r\n type=\"button\"\r\n onClick={() => onSelectedDateChange(shiftDays(selectedDate, -1))}\r\n >\r\n {prevButtonLabel}\r\n </button>\r\n {(renderDatePicker ?? defaultRenderDatePicker)({ selectedDate, onSelectedDateChange })}\r\n <button\r\n className=\"rfs-btn border-border bg-card text-foreground hover:bg-muted\"\r\n type=\"button\"\r\n onClick={() => onSelectedDateChange(shiftDays(selectedDate, 1))}\r\n >\r\n {nextButtonLabel}\r\n </button>\r\n </div>\r\n\r\n <div className=\"rfs-shell border-border bg-card\">\r\n <div style={{ minWidth: gridMinWidth }}>\r\n <div className=\"rfs-header border-border bg-card\">\r\n <div className=\"rfs-gutter border-border\" style={{ width: GUTTER_W }} />\r\n {resources.map((resource) => (\r\n <div\r\n key={String(resource.id)}\r\n className=\"rfs-resource-header border-border bg-card text-foreground\"\r\n style={{ minWidth: RESOURCE_MIN_W, flex: 1 }}\r\n >\r\n {(renderResourceHeader ?? defaultRenderResourceHeader)(resource)}\r\n {isNameLike(resource) ? <div className=\"rfs-resource-subtitle text-muted-foreground\">{fullName(resource)}</div> : null}\r\n </div>\r\n ))}\r\n </div>\r\n <div className=\"rfs-body\">\r\n <div className=\"rfs-times border-border bg-card\" style={{ width: GUTTER_W, height: gridHeight }}>\r\n {Array.from({ length: Math.floor(dayMinutes / 60) + 1 }).map((_, i) => (\r\n <div\r\n key={`tick-${i}`}\r\n className=\"rfs-time-tick text-muted-foreground\"\r\n style={{ top: TOP_PAD + i * 60 * PX_PER_MIN }}\r\n >\r\n {String(Math.floor((dayStartAbs + i * 60) / 60)).padStart(2, \"0\")}:\r\n {String((dayStartAbs + i * 60) % 60).padStart(2, \"0\")}\r\n </div>\r\n ))}\r\n </div>\r\n <div className=\"rfs-grid\">\r\n {resources.map((resource) => (\r\n <div\r\n key={String(resource.id)}\r\n className=\"rfs-col border-border bg-card\"\r\n style={{ minWidth: RESOURCE_MIN_W, flex: 1 }}\r\n >\r\n <div\r\n ref={(el) => {\r\n colRefs.current[String(resource.id)] = el;\r\n }}\r\n className=\"rfs-col-inner bg-card\"\r\n style={{ height: gridHeight }}\r\n >\r\n {Array.from({ length: Math.floor(dayMinutes / 60) + 1 }).map((_, i) => (\r\n <div\r\n key={`major-${String(resource.id)}-${i}`}\r\n className=\"rfs-hour-line border-border/70\"\r\n style={{ top: TOP_PAD + i * 60 * PX_PER_MIN }}\r\n />\r\n ))}\r\n {Array.from({ length: Math.floor(dayMinutes / STEP_MIN) + 1 }).map((_, i) => (\r\n <div\r\n key={`minor-${String(resource.id)}-${i}`}\r\n className=\"rfs-slot-line border-border/50\"\r\n style={{ top: TOP_PAD + i * STEP_MIN * PX_PER_MIN }}\r\n />\r\n ))}\r\n {(laidOutByResource.get(resource.id) ?? []).map((appointment) => {\r\n const laneWidthPct = 100 / appointment.lanes;\r\n const top = TOP_PAD + appointment.startMin * PX_PER_MIN;\r\n const height = Math.max(MIN_EVENT_MIN * PX_PER_MIN, (appointment.endMin - appointment.startMin) * PX_PER_MIN);\r\n const appointmentAppearance = appointmentAppearanceByResource.get(resource.id);\r\n const appointmentBackgroundColor = appointmentBgByResource.get(resource.id);\r\n return (\r\n <div\r\n key={String(appointment.id)}\r\n className=\"rfs-card-slot\"\r\n style={{\r\n top,\r\n left: `${laneWidthPct * appointment.lane}%`,\r\n width: `${laneWidthPct}%`,\r\n height\r\n }}\r\n >\r\n {(renderAppointment ?? defaultRenderAppointment)({\r\n appointment,\r\n onPointerDown: (event) => onApptPointerDown(event, appointment),\r\n onResizePointerDown: (event) => onResizePointerDown(event, appointment),\r\n appointmentAppearance,\r\n appointmentBackgroundColor,\r\n drag,\r\n suppressClickRef\r\n })}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </section>\r\n );\r\n}\r\n","import type { SchedulerAppointmentChangeArgs, SchedulerId } from \"./types\";\r\n\r\nexport type ApplySchedulerAppointmentChangeOptions<TAppointment, TResourceId extends SchedulerId> = {\r\n getId: (appointment: TAppointment) => SchedulerId;\r\n setResourceId: (appointment: TAppointment, resourceId: TResourceId) => TAppointment;\r\n setStart: (appointment: TAppointment, start: Date) => TAppointment;\r\n setEnd: (appointment: TAppointment, end: Date) => TAppointment;\r\n};\r\n\r\nexport function applySchedulerAppointmentChange<TAppointment, TResourceId extends SchedulerId>(\r\n appointments: TAppointment[],\r\n change: SchedulerAppointmentChangeArgs<TAppointment, TResourceId>,\r\n options: ApplySchedulerAppointmentChangeOptions<TAppointment, TResourceId>\r\n): TAppointment[] {\r\n return appointments.map((item) => {\r\n if (options.getId(item) !== options.getId(change.appointment)) {\r\n return item;\r\n }\r\n const withResource = options.setResourceId(item, change.next.resourceId);\r\n const withStart = options.setStart(withResource, change.next.start);\r\n return options.setEnd(withStart, change.next.end);\r\n });\r\n}\r\n"]}
|