@marco.colia/react-fast-scheduler 1.0.2 → 2.1.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 CHANGED
@@ -21,7 +21,6 @@ import type { BaseSchedulerResource } from "@marco.colia/react-fast-scheduler";
21
21
  type Staff = BaseSchedulerResource<number> & {
22
22
  firstName: string;
23
23
  lastName: string;
24
- appointmentColorClass?: string;
25
24
  };
26
25
 
27
26
  type Appointment = {
@@ -35,8 +34,8 @@ type Appointment = {
35
34
  };
36
35
 
37
36
  const initialStaff: Staff[] = [
38
- { id: 1, label: "Room A", firstName: "Anna", lastName: "Rossi", appointmentColorClass: "bg-amber-100" },
39
- { id: 2, label: "Room B", firstName: "Luca", lastName: "Bianchi", appointmentColorClass: "bg-blue-100" }
37
+ { id: 1, label: "Room A", firstName: "Anna", lastName: "Rossi" },
38
+ { id: 2, label: "Room B", firstName: "Luca", lastName: "Bianchi" }
40
39
  ];
41
40
 
42
41
  const initialAppointments: Appointment[] = [
@@ -70,13 +69,6 @@ export function SchedulerExample() {
70
69
  getEnd: (a) => a.end,
71
70
  getTitle: (a) => `${a.customerName} - ${a.title}`
72
71
  }}
73
- renderDatePicker={({ selectedDate: value, onSelectedDateChange }) => (
74
- <input
75
- type="date"
76
- value={value.toISOString().slice(0, 10)}
77
- onChange={(event) => onSelectedDateChange(new Date(`${event.target.value}T00:00:00`))}
78
- />
79
- )}
80
72
  onAppointmentChange={async ({ appointment, next }) => {
81
73
  setAppointments((prev) =>
82
74
  prev.map((a) =>
@@ -86,30 +78,10 @@ export function SchedulerExample() {
86
78
  )
87
79
  );
88
80
  }}
89
- getResourceAppointmentBackground={(resource) => resource.appointmentColorClass}
90
- renderResourceHeader={(resource) => <strong>{resource.label}</strong>}
91
- renderAppointment={({ appointment, onPointerDown, onResizePointerDown, appointmentBackgroundColor }) => (
92
- <div
93
- onPointerDown={onPointerDown}
94
- className={`relative h-full cursor-grab overflow-hidden rounded-md border border-slate-300 p-2 pb-5 ${appointmentBackgroundColor ?? "bg-slate-100"}`}
95
- >
96
- <div className="text-xs font-semibold">{appointment.title}</div>
97
- {appointment.raw.description ? (
98
- <div className="mt-1 text-[10px] font-medium text-slate-500">
99
- {appointment.raw.description}
100
- </div>
101
- ) : null}
102
- <div
103
- role="button"
104
- aria-label="Resize appointment"
105
- onPointerDown={(e) => {
106
- e.stopPropagation();
107
- onResizePointerDown(e);
108
- }}
109
- className="absolute inset-x-1 bottom-1 h-2 cursor-ns-resize rounded-full bg-slate-300/90 hover:bg-slate-400"
110
- />
111
- </div>
112
- )}
81
+ resourceAppointmentClassMap={{
82
+ "1": "bg-amber-100 dark:bg-amber-950/40",
83
+ "2": "bg-blue-100 dark:bg-blue-950/40"
84
+ }}
113
85
  dayStart="09:00"
114
86
  dayEnd="18:00"
115
87
  />
@@ -117,16 +89,80 @@ export function SchedulerExample() {
117
89
  }
118
90
  ```
119
91
 
92
+ `renderAppointment` is optional. If you omit it, the scheduler uses the built-in appointment card with light/dark mode support.
93
+ `renderDatePicker` is optional. If you omit it, the scheduler uses a built-in native date input.
94
+ `onAppointmentChange` is a simple callback: use it to update your state and run your own side effects.
95
+
120
96
  Main props you need to pass:
121
97
  - `resources`: your columns (staff, rooms, etc), each with at least `{ id, label }`.
122
98
  - `appointments`: raw items from your backend.
123
99
  - `adapter`: functions that map your raw appointment shape to scheduler fields.
124
100
  - `onAppointmentChange`: optional generic callback fired after move/resize drop.
125
101
  - `onPersistMoveResize`: optional legacy persistence callback (used if `onAppointmentChange` is not provided).
126
- - `getResourceAppointmentBackground`: optional function to provide appointment background color per resource.
102
+ - `resourceAppointmentClassMap`: optional map of `resourceId -> className` for per-resource appointment colors/styles.
103
+ - `getResourceAppointmentColorToken`: optional function to provide a semantic color token per resource (for example `"amber"`).
104
+ - `appointmentColorTokenClassMap`: optional map to override token -> class resolution.
105
+ - `getResourceAppointmentAppearance`: optional low-level function to provide appointment `className` per resource.
106
+ - `getResourceAppointmentBackground`: legacy optional function to provide appointment background as a string.
127
107
  - `prevButtonLabel` and `nextButtonLabel`: custom labels for toolbar navigation buttons.
128
- - `renderDatePicker`: inject your own date picker UI (for example shadcn calendar).
129
- - `renderResourceHeader`, `renderAppointment`: rendering hooks for your UI.
108
+ - `renderDatePicker`: optional render hook for a custom date picker UI (for example shadcn calendar).
109
+ - `renderResourceHeader`: optional render hook for resource column headers.
110
+ - `renderAppointment`: optional render hook to fully customize appointment cards.
111
+
112
+ ### Resource classes by id (recommended)
113
+
114
+ ```tsx
115
+ <Scheduler
116
+ // ...other props
117
+ resourceAppointmentClassMap={{
118
+ "room-a": "bg-yellow-100 dark:bg-yellow-950/40",
119
+ "room-b": "bg-rose-100 dark:bg-rose-950/40"
120
+ }}
121
+ />
122
+ ```
123
+
124
+ ### Resource color tokens (optional)
125
+
126
+ ```tsx
127
+ <Scheduler
128
+ // ...other props
129
+ getResourceAppointmentColorToken={(resource) => resource.category}
130
+ appointmentColorTokenClassMap={{
131
+ vip: "bg-yellow-100 dark:bg-yellow-950/40",
132
+ urgent: "bg-rose-100 dark:bg-rose-950/40"
133
+ }}
134
+ />
135
+ ```
136
+
137
+ ### Custom appointment renderer (optional)
138
+
139
+ ```tsx
140
+ <Scheduler
141
+ // ...other props
142
+ renderAppointment={({ appointment, onPointerDown, onResizePointerDown, appointmentAppearance, appointmentBackgroundColor }) => (
143
+ <div
144
+ onPointerDown={onPointerDown}
145
+ className={`relative h-full cursor-grab overflow-hidden rounded-md border border-slate-300 p-2 pb-5 ${
146
+ appointmentAppearance?.className ?? appointmentBackgroundColor ?? "bg-slate-100"
147
+ }`}
148
+ >
149
+ <div className="text-xs font-semibold">{appointment.title}</div>
150
+ {appointment.raw.description ? (
151
+ <div className="mt-1 text-[10px] font-medium text-slate-500">{appointment.raw.description}</div>
152
+ ) : null}
153
+ <div
154
+ role="button"
155
+ aria-label="Resize appointment"
156
+ onPointerDown={(e) => {
157
+ e.stopPropagation();
158
+ onResizePointerDown(e);
159
+ }}
160
+ className="absolute inset-x-1 bottom-1 h-2 cursor-ns-resize rounded-full bg-slate-300/90 hover:bg-slate-400"
161
+ />
162
+ </div>
163
+ )}
164
+ />
165
+ ```
130
166
 
131
167
  ### shadcn Calendar Date Picker
132
168