@marco.colia/react-fast-scheduler 3.1.0 → 4.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/README.md +234 -34
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +98 -6
- package/dist/index.d.ts +98 -6
- package/dist/index.js +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A lightweight React day scheduler for resource-based booking UIs.
|
|
|
8
8
|
- drag and resize interactions
|
|
9
9
|
- date navigation with a built-in toolbar and date picker
|
|
10
10
|
- customizable appointment rendering
|
|
11
|
-
- a simple adapter layer for your backend data
|
|
11
|
+
- a simple field adapter layer for your backend data
|
|
12
12
|
|
|
13
13
|

|
|
14
14
|
|
|
@@ -35,6 +35,45 @@ When you pass your own class strings through props like `resourceAppointmentClas
|
|
|
35
35
|
|
|
36
36
|
## Quick Start
|
|
37
37
|
|
|
38
|
+
If your appointments already use the field names `id`, `resourceId`, `start`, `end`, and `title`, you do not need an adapter:
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import { useState } from "react";
|
|
42
|
+
import { Scheduler, applySchedulerAppointmentChange } from "@marco.colia/react-fast-scheduler";
|
|
43
|
+
import "@marco.colia/react-fast-scheduler/styles.css";
|
|
44
|
+
|
|
45
|
+
const resources = [
|
|
46
|
+
{ id: 1, label: "Alice" },
|
|
47
|
+
{ id: 2, label: "Bob" },
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
export const MinimalScheduler = () => {
|
|
51
|
+
const [selectedDate, setSelectedDate] = useState(() => new Date());
|
|
52
|
+
const [appointments, setAppointments] = useState([
|
|
53
|
+
{ id: 1, resourceId: 1, title: "Haircut", start: "2026-03-27T09:00:00", end: "2026-03-27T10:00:00" },
|
|
54
|
+
]);
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Scheduler
|
|
58
|
+
resources={resources}
|
|
59
|
+
appointments={appointments}
|
|
60
|
+
selectedDate={selectedDate}
|
|
61
|
+
onSelectedDateChange={setSelectedDate}
|
|
62
|
+
onAppointmentChange={(change) =>
|
|
63
|
+
setAppointments((prev) =>
|
|
64
|
+
applySchedulerAppointmentChange(prev, change, {
|
|
65
|
+
dateValue: (date) => date.toISOString(),
|
|
66
|
+
})
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
onAppointmentClick={(appointment) => console.log("clicked", appointment)}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Full example with a backend
|
|
76
|
+
|
|
38
77
|
The scheduler is a controlled component:
|
|
39
78
|
|
|
40
79
|
- your app owns `selectedDate`
|
|
@@ -48,7 +87,7 @@ import {
|
|
|
48
87
|
Scheduler,
|
|
49
88
|
applySchedulerAppointmentChange,
|
|
50
89
|
type BaseSchedulerResource,
|
|
51
|
-
type
|
|
90
|
+
type SchedulerAppointmentChangeEvent,
|
|
52
91
|
} from "@marco.colia/react-fast-scheduler";
|
|
53
92
|
import "@marco.colia/react-fast-scheduler/styles.css";
|
|
54
93
|
|
|
@@ -103,13 +142,12 @@ export const SchedulerExample = () => {
|
|
|
103
142
|
};
|
|
104
143
|
|
|
105
144
|
const handleAppointmentChange = async (
|
|
106
|
-
change:
|
|
145
|
+
change: SchedulerAppointmentChangeEvent<Appointment, number>
|
|
107
146
|
) => {
|
|
147
|
+
// `id`, `start`, and `end` use the default names, so only `resourceId` needs mapping.
|
|
108
148
|
const optimisticAppointments = applySchedulerAppointmentChange(appointments, change, {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
setStart: (item, start) => ({ ...item, start: start.toISOString() }),
|
|
112
|
-
setEnd: (item, end) => ({ ...item, end: end.toISOString() }),
|
|
149
|
+
resourceId: "staffId",
|
|
150
|
+
dateValue: (date) => date.toISOString(),
|
|
113
151
|
});
|
|
114
152
|
|
|
115
153
|
setAppointments(optimisticAppointments);
|
|
@@ -144,11 +182,8 @@ export const SchedulerExample = () => {
|
|
|
144
182
|
selectedDate={selectedDate}
|
|
145
183
|
onSelectedDateChange={setSelectedDate}
|
|
146
184
|
adapter={{
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
getStart: (item) => item.start,
|
|
150
|
-
getEnd: (item) => item.end,
|
|
151
|
-
getTitle: (item) => `${item.customerName} - ${item.title}`,
|
|
185
|
+
resourceId: "staffId",
|
|
186
|
+
title: (item) => `${item.customerName} - ${item.title}`,
|
|
152
187
|
}}
|
|
153
188
|
onAppointmentChange={handleAppointmentChange}
|
|
154
189
|
dayStart="09:00"
|
|
@@ -210,7 +245,53 @@ Appointments stay in your own shape. The scheduler reads them through the `adapt
|
|
|
210
245
|
|
|
211
246
|
### `adapter`
|
|
212
247
|
|
|
213
|
-
The adapter
|
|
248
|
+
The adapter tells the scheduler which appointment fields to read. Every field has a default:
|
|
249
|
+
|
|
250
|
+
| Field | Default | Expected value |
|
|
251
|
+
| ------------ | -------------- | ------------------- |
|
|
252
|
+
| `id` | `"id"` | `string \| number` |
|
|
253
|
+
| `resourceId` | `"resourceId"` | the resource `id` |
|
|
254
|
+
| `start` | `"start"` | `Date \| string` |
|
|
255
|
+
| `end` | `"end"` | `Date \| string` |
|
|
256
|
+
| `title` | `"title"` | `string` |
|
|
257
|
+
|
|
258
|
+
If your appointments already use those names, omit `adapter` entirely. Otherwise map only the fields that differ:
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
adapter={{ resourceId: "staffId" }}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
TypeScript checks this: `adapter` (or a single field) is only optional when your appointment type has a matching field under the default name. Otherwise you get a compile error instead of empty cards at runtime.
|
|
265
|
+
|
|
266
|
+
You can still map every field by key:
|
|
267
|
+
|
|
268
|
+
```tsx
|
|
269
|
+
adapter={{
|
|
270
|
+
id: "id",
|
|
271
|
+
resourceId: "staffId",
|
|
272
|
+
start: "start",
|
|
273
|
+
end: "end",
|
|
274
|
+
title: "title",
|
|
275
|
+
}}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Each field can also be a function when you need to derive a value:
|
|
279
|
+
|
|
280
|
+
```tsx
|
|
281
|
+
adapter={{
|
|
282
|
+
id: "id",
|
|
283
|
+
resourceId: "staffId",
|
|
284
|
+
start: "start",
|
|
285
|
+
end: "end",
|
|
286
|
+
title: (item) => `${item.customerName} - ${item.title}`,
|
|
287
|
+
}}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Start and end fields can resolve to either a `Date` or a date string.
|
|
291
|
+
|
|
292
|
+
Key-based adapters can be written inline: the scheduler compares the field values, not the object identity, so an inline `adapter={{ ... }}` does not trigger extra recalculations. If you use function fields, keep them stable (define them outside the component or with `useCallback`).
|
|
293
|
+
|
|
294
|
+
The older getter adapter is still supported:
|
|
214
295
|
|
|
215
296
|
```tsx
|
|
216
297
|
adapter={{
|
|
@@ -222,8 +303,6 @@ adapter={{
|
|
|
222
303
|
}}
|
|
223
304
|
```
|
|
224
305
|
|
|
225
|
-
`getStart` and `getEnd` can return either a `Date` or a date string.
|
|
226
|
-
|
|
227
306
|
## Drag, Resize, and Persistence
|
|
228
307
|
|
|
229
308
|
Use `onAppointmentChange` as the main integration point for move and resize operations.
|
|
@@ -231,6 +310,8 @@ Use `onAppointmentChange` as the main integration point for move and resize oper
|
|
|
231
310
|
It receives:
|
|
232
311
|
|
|
233
312
|
- `appointment`: the original raw appointment
|
|
313
|
+
- `resourceId`, `start`, and `end`: the new values after drop
|
|
314
|
+
- `previousResourceId`, `previousStart`, and `previousEnd`: the values before drag or resize
|
|
234
315
|
- `previous`: the previous resource and time range
|
|
235
316
|
- `next`: the new resource and time range after drop
|
|
236
317
|
- `kind`: `"move"` or `"resize"`
|
|
@@ -240,12 +321,12 @@ Example:
|
|
|
240
321
|
```tsx
|
|
241
322
|
<Scheduler
|
|
242
323
|
// ...other props
|
|
243
|
-
onAppointmentChange={async ({ appointment,
|
|
324
|
+
onAppointmentChange={async ({ appointment, resourceId, start, end }) => {
|
|
244
325
|
const nextAppointment = {
|
|
245
326
|
...appointment,
|
|
246
|
-
staffId:
|
|
247
|
-
start:
|
|
248
|
-
end:
|
|
327
|
+
staffId: resourceId,
|
|
328
|
+
start: start.toISOString(),
|
|
329
|
+
end: end.toISOString(),
|
|
249
330
|
};
|
|
250
331
|
|
|
251
332
|
await fetch(`/api/appointments/${appointment.id}`, {
|
|
@@ -257,17 +338,25 @@ Example:
|
|
|
257
338
|
/>
|
|
258
339
|
```
|
|
259
340
|
|
|
260
|
-
If you want a small helper for optimistic local state updates, use `applySchedulerAppointmentChange
|
|
341
|
+
If you want a small helper for optimistic local state updates, use `applySchedulerAppointmentChange`. Like the adapter, it defaults to the `id`, `resourceId`, `start`, and `end` fields, so you only map what differs:
|
|
261
342
|
|
|
262
343
|
```tsx
|
|
344
|
+
// Appointments with the default field names, stored as Date objects
|
|
345
|
+
const nextAppointments = applySchedulerAppointmentChange(appointments, change);
|
|
346
|
+
|
|
347
|
+
// Different resource field, dates stored as ISO strings
|
|
263
348
|
const nextAppointments = applySchedulerAppointmentChange(appointments, change, {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
setStart: (item, start) => ({ ...item, start: start.toISOString() }),
|
|
267
|
-
setEnd: (item, end) => ({ ...item, end: end.toISOString() }),
|
|
349
|
+
resourceId: "staffId",
|
|
350
|
+
dateValue: (date) => date.toISOString(),
|
|
268
351
|
});
|
|
269
352
|
```
|
|
270
353
|
|
|
354
|
+
Without `dateValue`, `start` and `end` are written as `Date` objects. Pass `dateValue` when your data stores dates as strings.
|
|
355
|
+
|
|
356
|
+
Drops that would overlap another appointment on the same resource are rejected: the card is shown in red while dragging and `onAppointmentChange` is not called.
|
|
357
|
+
|
|
358
|
+
The previous setter-based helper options are still supported for non-object data or custom immutable updates.
|
|
359
|
+
|
|
271
360
|
`onPersistMoveResize` is still available as a legacy callback, but `onAppointmentChange` is the recommended API.
|
|
272
361
|
|
|
273
362
|
If you want to render the scheduler in read-only mode, use `editable={false}`:
|
|
@@ -281,6 +370,95 @@ If you want to render the scheduler in read-only mode, use `editable={false}`:
|
|
|
281
370
|
|
|
282
371
|
When `editable` is `false`, move and resize interactions are disabled.
|
|
283
372
|
|
|
373
|
+
## Clicking Appointments
|
|
374
|
+
|
|
375
|
+
Use `onAppointmentClick` to open a detail view or an edit form:
|
|
376
|
+
|
|
377
|
+
```tsx
|
|
378
|
+
<Scheduler
|
|
379
|
+
// ...other props
|
|
380
|
+
onAppointmentClick={(appointment, event) => {
|
|
381
|
+
setSelectedAppointment(appointment);
|
|
382
|
+
}}
|
|
383
|
+
/>
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
It receives your original appointment object and the click event. It is not called at the end of a drag or resize, and it works with both the built-in card and a custom `renderAppointment`. It also works when `editable` is `false`.
|
|
387
|
+
|
|
388
|
+
## Views
|
|
389
|
+
|
|
390
|
+
Besides the default resource grid (`"day"`), the scheduler has an `"agenda"` view: a compact table of the selected day with one row every 15 minutes and one column per resource. The times stay visible in a sidebar on the left while you scroll horizontally, and each cell lists the appointments that start in that 15-minute slot, ordered by start time.
|
|
391
|
+
|
|
392
|
+
Unlike the grid, cards are not sized by duration: each row grows to fit its appointments, so overlapping or short appointments stay readable.
|
|
393
|
+
|
|
394
|
+
Enable it with `views`. When more than one view is listed, the built-in toolbar shows a view switcher:
|
|
395
|
+
|
|
396
|
+
```tsx
|
|
397
|
+
<Scheduler
|
|
398
|
+
// ...other props
|
|
399
|
+
views={["day", "agenda"]}
|
|
400
|
+
/>
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
Without `views`, only the grid is available and no switcher is shown, exactly as before.
|
|
404
|
+
|
|
405
|
+
The agenda uses the same data as the grid, so your data loading does not change: the toolbar still moves one day at a time and calls `onSelectedDateChange`.
|
|
406
|
+
|
|
407
|
+
In the agenda:
|
|
408
|
+
|
|
409
|
+
- column headers use the same `renderResourceHeader` as the grid
|
|
410
|
+
- rows cover every 15-minute slot from `dayStart` to `dayEnd`, extended if an appointment starts outside that range
|
|
411
|
+
- rows use the same colors as the grid cards (see [Styling](#styling))
|
|
412
|
+
- `onAppointmentClick` works on each row
|
|
413
|
+
- move and resize are not available
|
|
414
|
+
- appointments whose `resourceId` does not match a resource are not shown, like in the grid
|
|
415
|
+
- when the whole day has no appointments, `agendaEmptyState` is shown instead of the columns
|
|
416
|
+
|
|
417
|
+
### Controlling the view
|
|
418
|
+
|
|
419
|
+
By default the scheduler keeps the current view in its own state. Use `defaultView` to choose the initial view, or `view` + `onViewChange` to control it from your app (for example to save it in the URL):
|
|
420
|
+
|
|
421
|
+
```tsx
|
|
422
|
+
const [view, setView] = useState<SchedulerView>("agenda");
|
|
423
|
+
|
|
424
|
+
<Scheduler
|
|
425
|
+
// ...other props
|
|
426
|
+
views={["day", "agenda"]}
|
|
427
|
+
view={view}
|
|
428
|
+
onViewChange={setView}
|
|
429
|
+
/>
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
### Labels and empty state
|
|
433
|
+
|
|
434
|
+
```tsx
|
|
435
|
+
<Scheduler
|
|
436
|
+
// ...other props
|
|
437
|
+
views={["day", "agenda"]}
|
|
438
|
+
viewLabels={{ day: "Giorno", agenda: "Agenda" }}
|
|
439
|
+
agendaEmptyState="Nessun appuntamento"
|
|
440
|
+
/>
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Custom agenda rows
|
|
444
|
+
|
|
445
|
+
Use `renderAgendaItem` to replace the content of each agenda row. It receives the normalized `appointment` (with `title`, `start`, `end`, and your original object in `raw`), the `resource` of its column, and the resolved `appointmentAppearance`:
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
<Scheduler
|
|
449
|
+
// ...other props
|
|
450
|
+
views={["day", "agenda"]}
|
|
451
|
+
renderAgendaItem={({ appointment, appointmentAppearance }) => (
|
|
452
|
+
<div className={`flex gap-3 rounded-md p-2 ${appointmentAppearance?.className ?? ""}`}>
|
|
453
|
+
<span>{appointment.start.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}</span>
|
|
454
|
+
<strong>{appointment.title}</strong>
|
|
455
|
+
</div>
|
|
456
|
+
)}
|
|
457
|
+
/>
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
With a custom row, `onAppointmentClick` is still called when the row is clicked. If the row should be reachable by keyboard, render a `<button>` inside it.
|
|
461
|
+
|
|
284
462
|
## Styling
|
|
285
463
|
|
|
286
464
|
The package ships precompiled CSS:
|
|
@@ -332,8 +510,25 @@ If you want semantic mapping, use `getResourceAppointmentColorToken` plus `appoi
|
|
|
332
510
|
/>
|
|
333
511
|
```
|
|
334
512
|
|
|
513
|
+
Built-in tokens (`slate`, `gray`, `zinc`, `neutral`, `stone`, `red`, `orange`, `amber`, `yellow`, `lime`, `green`, `emerald`, `teal`, `cyan`, `sky`, `blue`, `indigo`, `violet`, `purple`, `fuchsia`, `pink`, `rose`) ship with the packaged stylesheet, so they work without Tailwind in your app:
|
|
514
|
+
|
|
515
|
+
```tsx
|
|
516
|
+
<Scheduler
|
|
517
|
+
// ...other props
|
|
518
|
+
getResourceAppointmentColorToken={(resource) => (resource.id === 1 ? "blue" : "rose")}
|
|
519
|
+
/>
|
|
520
|
+
```
|
|
521
|
+
|
|
335
522
|
For full control, use `getResourceAppointmentAppearance`.
|
|
336
523
|
|
|
524
|
+
When a resource matches more than one option, the first match wins:
|
|
525
|
+
|
|
526
|
+
1. `resourceAppointmentClassMap`
|
|
527
|
+
2. `getResourceAppointmentAppearance`
|
|
528
|
+
3. `getResourceAppointmentColorToken` (+ `appointmentColorTokenClassMap`)
|
|
529
|
+
4. `getResourceAppointmentBackground` (legacy)
|
|
530
|
+
5. the built-in neutral background
|
|
531
|
+
|
|
337
532
|
## Custom Rendering
|
|
338
533
|
|
|
339
534
|
### Custom appointment card
|
|
@@ -349,7 +544,7 @@ The renderer also receives:
|
|
|
349
544
|
|
|
350
545
|
- `isDropInvalid`: `true` when the current drag position overlaps another appointment
|
|
351
546
|
- `onPointerDown`: attach this to your appointment root for move interactions
|
|
352
|
-
- `onResizePointerDown`: attach this to your resize handle
|
|
547
|
+
- `onResizePointerDown`: attach this to your resize handle; it already stops propagation, so the move handler does not fire
|
|
353
548
|
|
|
354
549
|
```tsx
|
|
355
550
|
<Scheduler
|
|
@@ -385,13 +580,7 @@ The renderer also receives:
|
|
|
385
580
|
<div
|
|
386
581
|
role="button"
|
|
387
582
|
aria-label="Resize appointment"
|
|
388
|
-
onPointerDown={
|
|
389
|
-
if (appointment.visualState === "ghost") {
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
event.stopPropagation();
|
|
393
|
-
onResizePointerDown(event);
|
|
394
|
-
}}
|
|
583
|
+
onPointerDown={onResizePointerDown}
|
|
395
584
|
className="absolute inset-x-1 bottom-1 h-2 cursor-ns-resize rounded-full bg-slate-300/90 hover:bg-slate-400"
|
|
396
585
|
/>
|
|
397
586
|
</div>
|
|
@@ -428,6 +617,8 @@ Use `renderToolbar` when you want to replace the whole header:
|
|
|
428
617
|
/>
|
|
429
618
|
```
|
|
430
619
|
|
|
620
|
+
`renderToolbar` also receives `view`, `views`, `onViewChange`, and `defaultViewSwitcher` (the built-in switcher, or `null` when fewer than two views are enabled). Render `{defaultViewSwitcher}` in your toolbar to keep the view switch, or build your own with `views` and `onViewChange`.
|
|
621
|
+
|
|
431
622
|
### Custom date picker slot
|
|
432
623
|
|
|
433
624
|
If you want to keep the default toolbar but swap the date picker UI, use `renderDatePicker`.
|
|
@@ -451,11 +642,12 @@ If you want to keep the default toolbar but swap the date picker UI, use `render
|
|
|
451
642
|
- `appointments`: array of raw appointment objects
|
|
452
643
|
- `selectedDate`: currently visible day
|
|
453
644
|
- `onSelectedDateChange`: controlled date change handler
|
|
454
|
-
- `adapter`: mapper between your appointment shape and scheduler fields
|
|
645
|
+
- `adapter`: key-based or getter-based mapper between your appointment shape and scheduler fields; optional when your appointments use the default field names (see [`adapter`](#adapter))
|
|
455
646
|
|
|
456
647
|
### Common optional props
|
|
457
648
|
|
|
458
|
-
- `onAppointmentChange`: async or sync handler for move and resize persistence
|
|
649
|
+
- `onAppointmentChange`: async or sync handler for move and resize persistence; receives both flat next values and the nested `previous`/`next` objects
|
|
650
|
+
- `onAppointmentClick`: called with the raw appointment and the click event on a plain click (not after a drag or resize)
|
|
459
651
|
- `editable`: enables or disables move and resize interactions, defaults to `true`
|
|
460
652
|
- `renderToolbar`: replace the full toolbar
|
|
461
653
|
- `renderDatePicker`: replace only the date picker slot used by the default toolbar
|
|
@@ -470,12 +662,20 @@ If you want to keep the default toolbar but swap the date picker UI, use `render
|
|
|
470
662
|
- `nextButtonLabel`: custom next button label
|
|
471
663
|
- `dayStart`: visible schedule start time, for example `"09:00"`
|
|
472
664
|
- `dayEnd`: visible schedule end time, for example `"18:00"`
|
|
665
|
+
- `views`: views offered by the switcher, for example `["day", "agenda"]`; defaults to `["day"]` (no switcher)
|
|
666
|
+
- `view`: controlled current view (`"day"` or `"agenda"`)
|
|
667
|
+
- `defaultView`: initial view when `view` is not controlled; defaults to the first entry of `views`
|
|
668
|
+
- `onViewChange`: called when the user picks a view in the switcher
|
|
669
|
+
- `viewLabels`: switcher labels, for example `{ day: "Giorno", agenda: "Agenda" }`
|
|
670
|
+
- `renderAgendaItem`: custom agenda row content
|
|
671
|
+
- `agendaEmptyState`: content shown in the agenda when the day has no appointments, defaults to `"No appointments"`
|
|
473
672
|
|
|
474
673
|
## Production Notes
|
|
475
674
|
|
|
476
675
|
- Keep `selectedDate` in application state and fetch data when it changes.
|
|
477
676
|
- Prefer formatting dates in local time for day-based API queries. `toISOString().slice(0, 10)` can shift the day around midnight because it uses UTC.
|
|
478
677
|
- If persistence fails after a drag or resize, either roll back local state or refetch the visible day.
|
|
678
|
+
- For large schedules, keep `resources`, `appointments`, adapter function fields, and render/click callbacks stable when their data has not changed so React can reuse scheduler calculations. Key-based adapters can stay inline.
|
|
479
679
|
- Import the package CSS once at app startup.
|
|
480
680
|
|
|
481
681
|
## Development
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var jsxRuntime=require('react/jsx-runtime'),dateFns=require('date-fns'),h=require('react');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var h__namespace=/*#__PURE__*/_interopNamespace(h);var it=e=>{let{isDropInvalid:t,description:r,title:o}=e;return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[t&&jsxRuntime.jsx("div",{className:"rfs:absolute rfs:right-1 rfs:top-1 rfs:flex rfs:h-4 rfs:w-4 rfs:items-center rfs:justify-center rfs:rounded-full rfs:bg-red-600 rfs:text-[10px] rfs:font-bold rfs:text-white",children:"X"}),jsxRuntime.jsx("div",{className:"rfs:text-xs rfs:font-semibold",children:o}),r&&jsxRuntime.jsx("div",{className:"rfs:mt-1 rfs:text-[10px] rfs:font-medium",children:r})]})},me=it;function oe({appointment:e,onResizePointerDown:t}){return jsxRuntime.jsx("div",{role:"button","aria-label":"Resize appointment",onPointerDown:r=>{e.visualState!=="ghost"&&(r.stopPropagation(),t(r));},className:"rfs:absolute rfs:inset-x-1 rfs:bottom-1 rfs:h-2 rfs:cursor-ns-resize rfs:rounded-full rfs:bg-border/90 rfs:transition-colors rfs:hover:bg-border"})}function G({appointment:e,isDropInvalid:t,onPointerDown:r,onResizePointerDown:o,appointmentAppearance:n,appointmentBackgroundColor:i}){let c=e.raw,a=typeof c.description=="string"?c.description:void 0,s=typeof i=="string"?i:void 0,d=n?.className??s??"rfs:bg-muted/40 rfs:dark:bg-muted/30",f=t?"rfs:bg-red-100/80 rfs:text-red-950 rfs:dark:bg-red-950/40 rfs:dark:text-red-100":"",l=e.visualState==="ghost"?"rfs:cursor-grab rfs:opacity-35":e.visualState==="dragging"?"rfs:cursor-grabbing rfs:opacity-55 rfs:shadow-xl":"rfs:cursor-grab",g=`rfs:relative rfs:h-full rfs:overflow-hidden rfs:rounded-md rfs:p-2 rfs:pb-5 rfs:text-foreground ${d} ${f} ${l}`;return jsxRuntime.jsxs("div",{onPointerDown:r,className:g,children:[jsxRuntime.jsx(me,{isDropInvalid:t,title:e.title,description:a}),jsxRuntime.jsx(oe,{onResizePointerDown:o,appointment:e})]})}function he(e){if(!e||typeof e!="object")return false;let t=e;return typeof t.firstName=="string"||typeof t.lastName=="string"}var Te={slate:"bg-slate-100 dark:bg-slate-900/40",gray:"bg-gray-100 dark:bg-gray-900/40",zinc:"bg-zinc-100 dark:bg-zinc-900/40",neutral:"bg-neutral-100 dark:bg-neutral-900/40",stone:"bg-stone-100 dark:bg-stone-900/40",red:"bg-red-100 dark:bg-red-950/40",orange:"bg-orange-100 dark:bg-orange-950/40",amber:"bg-amber-100 dark:bg-amber-950/40",yellow:"bg-yellow-100 dark:bg-yellow-950/40",lime:"bg-lime-100 dark:bg-lime-950/40",green:"bg-green-100 dark:bg-green-950/40",emerald:"bg-emerald-100 dark:bg-emerald-950/40",teal:"bg-teal-100 dark:bg-teal-950/40",cyan:"bg-cyan-100 dark:bg-cyan-950/40",sky:"bg-sky-100 dark:bg-sky-950/40",blue:"bg-blue-100 dark:bg-blue-950/40",indigo:"bg-indigo-100 dark:bg-indigo-950/40",violet:"bg-violet-100 dark:bg-violet-950/40",purple:"bg-purple-100 dark:bg-purple-950/40",fuchsia:"bg-fuchsia-100 dark:bg-fuchsia-950/40",pink:"bg-pink-100 dark:bg-pink-950/40",rose:"bg-rose-100 dark:bg-rose-950/40"};function D(e,t,r){return Math.max(t,Math.min(r,e))}function U(e,t=15){return Math.round(e/t)*t}function se(e){let[t,r]=e.split(":").map(Number);return t*60+r}function Ie(e){return `${e.firstName??""} ${e.lastName??""}`.trim()}function K(e){return dateFns.format(e,"yyyy-MM-dd")}function ie(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+t)}function z(e,t,r){let o=new Date(e.getFullYear(),e.getMonth(),e.getDate(),0,0,0,0),n=t+r,i=Math.floor(n/60),c=n%60;return o.setHours(i,c,0,0),o}function ae(e,t){return t.getHours()*60+t.getMinutes()-e}function ce(e,t){return e.startMin<t.endMin&&t.startMin<e.endMin}function Se(e){let t=[...e].sort((c,a)=>c.startMin-a.startMin||c.endMin-a.endMin),r=[],o=[],n=[];for(let c of t)o=o.filter(s=>s.endMin>c.startMin),!o.some(s=>ce(s,c))&&n.length>0&&(r.push(n),n=[]),n.push(c),o.push(c);n.length&&r.push(n);let i=[];for(let c of r){let a=[...c].sort((l,g)=>l.startMin-g.startMin||l.endMin-g.endMin),s=[],d=new Map;for(let l of a){let g=false;for(let p=0;p<s.length;p++)if(s[p]<=l.startMin){s[p]=l.endMin,d.set(l.id,p),g=true;break}g||(s.push(l.endMin),d.set(l.id,s.length-1));}let f=s.length;for(let l of a)i.push({...l,lane:d.get(l.id)??0,lanes:f});}return i}function ue({fallback:e,getValue:t,resources:r,toKey:o}){let n=new Map;for(let i of r)n.set(o(i),t(i)??e);return n}function be({adapter:e,appointments:t,dayMinutes:r,dayStartAbs:o,selectedISO:n}){return t.map(i=>{let c=new Date(e.getStart(i)),a=new Date(e.getEnd(i));return {raw:i,id:e.getId(i),resourceId:e.getResourceId(i),start:c,end:a,startMin:D(ae(o,c),0,r),endMin:D(ae(o,a),0,r),title:e.getTitle(i),renderKey:String(e.getId(i)),visualState:"normal"}}).filter(i=>K(i.start)===n)}function ye(e){return new Map(e.map(t=>[t.id,t]))}function Me(e,t,r,o){return t.kind==="none"||t.kind==="move"?e:e.map(n=>n.id!==t.appointmentId?n:{...n,resourceId:t.resourceId,startMin:t.startMin,endMin:t.endMin,start:z(r,o,t.startMin),end:z(r,o,t.endMin),visualState:"dragging"})}function Ae(e,t){let r=new Map;for(let n of t){let i=r.get(n.resourceId)??[];i.push(n),r.set(n.resourceId,i);}let o=new Map;for(let n of e)o.set(n.id,de(r.get(n.id)??[]));return o}function de(e){return Se(e.map(t=>({...t,appointmentId:t.id,id:t.renderKey}))).map(({appointmentId:t,...r})=>({...r,id:t}))}function Pe(e,t,r,o,n){let i=new Map;for(let c of e){let a=t?.[String(c.id)];if(a){i.set(c.id,{className:a});continue}let s=r?.(c);if(s){i.set(c.id,s);continue}let d=o.get(c.id);if(d){i.set(c.id,{className:d});continue}let f=n.get(c.id);i.set(c.id,f?{className:f}:void 0);}return i}function De({adapter:e,appointments:t,dayEnd:r="18:00",dayStart:o="09:00",resources:n,selectedDate:i}){let c=h__namespace.useMemo(()=>se(o),[o]),a=h__namespace.useMemo(()=>se(r),[r]),s=h__namespace.useMemo(()=>Math.max(0,a-c),[a,c]),d=h__namespace.useMemo(()=>12+s*2+24,[s]),f=h__namespace.useMemo(()=>72+Math.max(n.length,1)*420,[n.length]),l=h__namespace.useMemo(()=>K(i),[i]),g=h__namespace.useMemo(()=>be({adapter:e,appointments:t,dayMinutes:s,dayStartAbs:c,selectedISO:l}),[e,t,s,c,l]);return {appointmentMap:h__namespace.useMemo(()=>ye(g),[g]),dayEndAbs:a,dayMinutes:s,dayStartAbs:c,gridHeight:d,gridMinWidth:f,renderAppts:g}}var pt=4,ft=(e,t)=>{e(r=>r&&{...r,clientX:t.clientX,clientY:t.clientY});},mt=e=>{let{dragRef:t,pendingDragRef:r,pointer:o,setDrag:n,setMovePreview:i,suppressClickRef:c}=e,a=r.current;if(!a||a.drag.pointerId!==o.pointerId)return;let s=o.clientX-a.startClientX,d=o.clientY-a.startClientY;Math.hypot(s,d)<pt||(c.current=true,t.current=a.drag,n(a.drag),a.drag.kind==="move"&&i({appointment:a.appointment,clientX:o.clientX,clientY:o.clientY,width:a.width,height:a.height,offsetX:a.offsetX,offsetY:a.offsetY}),r.current=null);},Rt=(e,t,r,o,n)=>{let i=o(t.clientX,e.resourceId),a=n(i,t.clientY)-e.offsetMin,s=D(U(a),0,r-e.durationMin),d=s+e.durationMin;return s===e.startMin&&d===e.endMin&&i===e.resourceId?null:{...e,resourceId:i,startMin:s,endMin:d}},gt=(e,t,r,o)=>{let n=o(e.resourceId,t.clientY),i=D(U(n),e.startMin+15,r);return i===e.endMin?null:{...e,endMin:i}},we=e=>{let{dayMinutes:t,dragRef:r,latestPointerRef:o,pendingDragRef:n,pointerToMin:i,pointerToResourceId:c,setDrag:a,setMovePreview:s,suppressClickRef:d}=e,f=o.current;if(!f)return;let l=r.current;if(l.kind==="none"&&n.current){mt({pointer:f,pendingDragRef:n,setDrag:a,setMovePreview:s,dragRef:r,suppressClickRef:d});return}if(l.kind==="none")return;if(l.kind==="move"){ft(s,f);let p=Rt(l,f,t,c,i);p&&(d.current=true,r.current=p,a(p));return}let g=gt(l,f,t,i);g&&(d.current=true,r.current=g,a(g));},Ne=e=>{let{dragRef:t,frameRef:r,latestPointerRef:o,pendingDragRef:n,persistDrag:i,setDrag:c,setMovePreview:a,suppressClickRef:s}=e;r.current!==null&&(window.cancelAnimationFrame(r.current),r.current=null),o.current=null,n.current=null,a(null);let d=t.current;d.kind!=="none"&&(c({kind:"none"}),t.current={kind:"none"},s.current&&i(d));};var Ce=({appointmentMap:e,dayMinutes:t,dayStartAbs:r,onAppointmentChange:o,onPersistMoveResize:n,renderAppts:i,resources:c,selectedDate:a,editable:s})=>{let[d,f]=h__namespace.useState({kind:"none"}),[l,g]=h__namespace.useState(null),p=h__namespace.useRef({}),T=h__namespace.useRef(false),v=h__namespace.useRef({kind:"none"}),S=h__namespace.useRef(null),b=h__namespace.useRef(null),y=h__namespace.useRef(null);h__namespace.useEffect(()=>{v.current=d;},[d]),h__namespace.useEffect(()=>()=>{y.current!==null&&window.cancelAnimationFrame(y.current);},[]);let E=h__namespace.useCallback((u,m)=>{let R=p.current[String(u)];if(!R)return 0;let M=m-R.getBoundingClientRect().top-12;return D(U(M/2),0,t)},[t]),$=h__namespace.useCallback((u,m)=>{for(let R of c){let M=p.current[String(R.id)];if(!M)continue;let X=M.getBoundingClientRect();if(u>=X.left&&u<=X.right)return R.id}return m},[c]),O=h__namespace.useCallback((u,m,R,M)=>i.filter(k=>k.resourceId===m&&k.id!==u).some(k=>ce(k,{startMin:R,endMin:M})),[i]),Y=h__namespace.useMemo(()=>d.kind==="none"?false:O(d.appointmentId,d.resourceId,d.startMin,d.endMin),[d,O]),L=h__namespace.useCallback(async u=>{let m=e.get(u.appointmentId);if(!m||O(u.appointmentId,u.resourceId,u.startMin,u.endMin))return;let R={resourceId:u.resourceId,start:z(a,r,u.startMin),end:z(a,r,u.endMin)};if(o){await o({kind:u.kind,appointment:m.raw,previous:{resourceId:m.resourceId,start:m.start,end:m.end},next:R});return}n&&await n({appointment:m.raw,resourceId:R.resourceId,start:R.start,end:R.end});},[e,r,O,o,n,a]),F=h__namespace.useCallback((u,m)=>{if(!s||u.button!==0)return;u.stopPropagation(),T.current=false;let R=u.currentTarget.getBoundingClientRect(),M=E(m.resourceId,u.clientY);S.current={drag:{kind:"move",appointmentId:m.id,pointerId:u.pointerId,resourceId:m.resourceId,durationMin:Math.max(15,m.endMin-m.startMin),offsetMin:M-m.startMin,startMin:m.startMin,endMin:m.endMin},appointment:m,startClientX:u.clientX,startClientY:u.clientY,width:R.width,height:R.height,offsetX:u.clientX-R.left,offsetY:u.clientY-R.top};},[E,s]),j=h__namespace.useCallback((u,m)=>{s&&u.button===0&&(u.stopPropagation(),T.current=false,S.current={drag:{kind:"resize",appointmentId:m.id,pointerId:u.pointerId,resourceId:m.resourceId,startMin:m.startMin,endMin:m.endMin},appointment:m,startClientX:u.clientX,startClientY:u.clientY,width:0,height:0,offsetX:0,offsetY:0});},[s]),W=h__namespace.useCallback(u=>{b.current={clientX:u.clientX,clientY:u.clientY,pointerId:u.pointerId},y.current===null&&(y.current=window.requestAnimationFrame(()=>{y.current=null,we({dayMinutes:t,dragRef:v,latestPointerRef:b,pendingDragRef:S,pointerToMin:E,pointerToResourceId:$,setDrag:f,setMovePreview:g,suppressClickRef:T});}));},[t,E,$]),ee=h__namespace.useCallback(()=>{Ne({dragRef:v,frameRef:y,latestPointerRef:b,pendingDragRef:S,persistDrag:L,setDrag:f,setMovePreview:g,suppressClickRef:T});},[L]);return {colRefs:p,drag:d,isDropInvalid:Y,movePreview:l,onApptPointerDown:F,onGlobalPointerMove:W,onGlobalPointerUp:ee,onResizePointerDown:j,suppressClickRef:T}};function Be({appointmentColorTokenClassMap:e,dayStartAbs:t,drag:r,getResourceAppointmentAppearance:o,getResourceAppointmentBackground:n,getResourceAppointmentColorToken:i,renderAppts:c,resourceAppointmentClassMap:a,resources:s,selectedDate:d}){let f=h__namespace.useMemo(()=>Me(c,r,d,t),[t,r,c,d]),l=h__namespace.useMemo(()=>Ae(s,c),[c,s]),g=h__namespace.useMemo(()=>{if(r.kind!=="resize")return l;let S=new Map(l),b=f.filter(y=>y.resourceId===r.resourceId);return S.set(r.resourceId,de(b)),S},[l,r,f]),p=h__namespace.useMemo(()=>n?ue({fallback:void 0,getValue:n,resources:s,toKey:S=>S.id}):new Map,[n,s]),T=h__namespace.useMemo(()=>{if(!i)return new Map;let S={...Te,...e??{}};return ue({fallback:void 0,getValue:b=>{let y=i(b);return y?S[y]:void 0},resources:s,toKey:b=>b.id})},[e,i,s]);return {appointmentAppearanceByResource:h__namespace.useMemo(()=>Pe(s,a,o,T,p),[p,T,o,a,s]),appointmentBgByResource:p,effectiveAppts:f,laidOutByResource:g}}function Ee({dayMinutes:e,dayStartAbs:t,gridHeight:r}){return jsxRuntime.jsx("div",{className:"rfs-times rfs:border-border rfs:bg-card",style:{width:72,height:r},children:Array.from({length:Math.floor(e/60)+1}).map((o,n)=>jsxRuntime.jsxs("div",{className:"rfs-time-tick rfs:text-muted-foreground",style:{top:12+n*60*2},children:[String(Math.floor((t+n*60)/60)).padStart(2,"0"),":",String((t+n*60)%60).padStart(2,"0")]},`tick-${n}`))})}function Oe({resource:e}){return jsxRuntime.jsx("strong",{children:e.label})}function ze({resources:e,renderResourceHeader:t}){return jsxRuntime.jsxs("div",{className:"rfs-header rfs:border-border rfs:bg-card",children:[jsxRuntime.jsx("div",{className:"rfs-gutter rfs:border-border",style:{width:72}}),e.map(r=>jsxRuntime.jsxs("div",{className:"rfs-resource-header rfs:border-border rfs:bg-card rfs:text-foreground",style:{minWidth:420,flex:1},children:[(t??(o=>Oe({resource:o})))(r),he(r)?jsxRuntime.jsx("div",{className:"rfs-resource-subtitle rfs:text-muted-foreground",children:Ie(r)}):null]},String(r.id)))]})}var He=({resource:e,colRefs:t,gridHeight:r,dayMinutes:o,appointments:n,appointmentAppearance:i,appointmentBg:c,isDropInvalid:a,renderAppointment:s,onApptPointerDown:d,onResizePointerDown:f,drag:l,suppressClickRef:g})=>jsxRuntime.jsx("div",{className:"rfs-col rfs:border-border rfs:bg-card",style:{minWidth:420,flex:1},children:jsxRuntime.jsxs("div",{ref:p=>{t.current[String(e.id)]=p;},className:"rfs-col-inner rfs:bg-card",style:{height:r},children:[Array.from({length:Math.floor(o/60)+1}).map((p,T)=>jsxRuntime.jsx("div",{className:"rfs-hour-line rfs:border-border/70",style:{top:12+T*60*2}},`major-${T}`)),Array.from({length:Math.floor(o/15)+1}).map((p,T)=>jsxRuntime.jsx("div",{className:"rfs-slot-line rfs:border-border/50",style:{top:12+T*15*2}},`minor-${T}`)),n.map(p=>{let T=100/p.lanes,v=12+p.startMin*2,S=Math.max(30,(p.endMin-p.startMin)*2);return jsxRuntime.jsx("div",{className:`rfs-card-slot ${p.visualState==="ghost"?"rfs-card-slot--ghost":""} ${p.visualState==="dragging"?"rfs-card-slot--dragging":""}`,style:{top:v,left:`${T*p.lane}%`,width:`${T}%`,height:S},children:(s??G)({appointment:p,isDropInvalid:a&&l.kind==="resize"&&p.id===l.appointmentId,onPointerDown:b=>d(b,p),onResizePointerDown:b=>f(b,p),appointmentAppearance:i,appointmentBackgroundColor:c,drag:l,suppressClickRef:g})},p.renderKey)})]})});var bt=(e,t)=>[e.resource===t.resource,e.colRefs===t.colRefs,e.gridHeight===t.gridHeight,e.dayMinutes===t.dayMinutes,e.appointments===t.appointments,e.appointmentAppearance===t.appointmentAppearance,e.appointmentBg===t.appointmentBg,e.isDropInvalid===t.isDropInvalid,e.renderAppointment===t.renderAppointment,e.onApptPointerDown===t.onApptPointerDown,e.onResizePointerDown===t.onResizePointerDown,e.drag===t.drag,e.suppressClickRef===t.suppressClickRef].every(Boolean),Xe=h__namespace.memo(He,bt);function H(...e){return e.filter(Boolean).join(" ")}var yt={default:"rfs:bg-primary rfs:text-primary-foreground rfs:hover:bg-primary/90",outline:"rfs:border rfs:border-border rfs:bg-card rfs:text-foreground rfs:hover:bg-muted",ghost:"rfs:text-foreground rfs:hover:bg-muted"},Mt={default:"rfs:h-9 rfs:px-4 rfs:py-2",sm:"rfs:h-8 rfs:px-3 rfs:text-xs",icon:"rfs:h-8 rfs:w-8"},P=h__namespace.forwardRef(function({className:t,variant:r="default",size:o="default",type:n="button",...i},c){return jsxRuntime.jsx("button",{ref:c,type:n,className:H("rfs:inline-flex rfs:items-center rfs:justify-center rfs:gap-2 rfs:rounded-md rfs:text-sm rfs:font-medium rfs:whitespace-nowrap rfs:transition-colors rfs:focus-visible:outline-none rfs:focus-visible:ring-2 rfs:focus-visible:ring-ring rfs:focus-visible:ring-offset-2 rfs:disabled:pointer-events-none rfs:disabled:opacity-50",yt[r],Mt[o],t),...i})});function We({selected:e,onSelect:t}){let[r,o]=h__namespace.useState(e??new Date);h__namespace.useEffect(()=>{e&&o(e);},[e]);let n=dateFns.startOfMonth(r),i=dateFns.startOfWeek(n,{weekStartsOn:1}),c=dateFns.endOfWeek(dateFns.endOfMonth(r),{weekStartsOn:1}),a=[];for(let s=i;s<=c;s=dateFns.addDays(s,1))a.push(s);return jsxRuntime.jsxs("div",{className:"rfs:w-72 rfs:rounded-md rfs:bg-popover",children:[jsxRuntime.jsxs("div",{className:"rfs:mb-2 rfs:flex rfs:items-center rfs:justify-between",children:[jsxRuntime.jsx(P,{variant:"ghost",size:"icon","aria-label":"Previous month",onClick:()=>o(dateFns.addMonths(r,-1)),children:"<"}),jsxRuntime.jsx("div",{className:"rfs:text-sm rfs:font-medium",children:dateFns.format(r,"MMMM yyyy")}),jsxRuntime.jsx(P,{variant:"ghost",size:"icon","aria-label":"Next month",onClick:()=>o(dateFns.addMonths(r,1)),children:">"})]}),jsxRuntime.jsx("div",{className:"rfs:grid rfs:grid-cols-7 rfs:gap-1 rfs:text-center rfs:text-xs rfs:text-muted-foreground",children:["Mo","Tu","We","Th","Fr","Sa","Su"].map(s=>jsxRuntime.jsx("div",{className:"rfs:py-1",children:s},s))}),jsxRuntime.jsx("div",{className:"rfs:grid rfs:grid-cols-7 rfs:gap-1",children:a.map(s=>{let d=e?dateFns.isSameDay(s,e):false;return jsxRuntime.jsx(P,{variant:d?"default":"ghost",size:"icon",className:H("rfs:text-xs",!dateFns.isSameMonth(s,r)&&"rfs:text-muted-foreground rfs:opacity-60",dateFns.isToday(s)&&!d&&"rfs:border rfs:border-border"),onClick:()=>t?.(s),children:dateFns.format(s,"d")},s.toISOString())})})]})}var Ge=h__namespace.createContext(null);function Ke(){let e=h__namespace.useContext(Ge);if(!e)throw new Error("Popover components must be used within Popover.");return e}function qe({children:e,open:t,onOpenChange:r}){let[o,n]=h__namespace.useState(false),i=h__namespace.useRef(null),c=h__namespace.useRef(null),a=t??o,s=h__namespace.useCallback(d=>{let f=typeof d=="function"?d(a):d;t===void 0&&n(f),r?.(f);},[t,r,a]);return h__namespace.useEffect(()=>{if(!a)return;let d=l=>{let g=l.target;i.current?.contains(g)||c.current?.contains(g)||s(false);},f=l=>{l.key==="Escape"&&s(false);};return document.addEventListener("mousedown",d),document.addEventListener("keydown",f),()=>{document.removeEventListener("mousedown",d),document.removeEventListener("keydown",f);}},[a,s]),jsxRuntime.jsx(Ge.Provider,{value:{open:a,setOpen:s,triggerRef:i,contentRef:c},children:jsxRuntime.jsx("div",{className:"rfs:relative rfs:inline-flex",children:e})})}function Je({children:e,asChild:t=false}){let{open:r,setOpen:o,triggerRef:n}=Ke();if(t&&h__namespace.isValidElement(e)){let i=e;return h__namespace.cloneElement(i,{ref:n,"aria-expanded":r,onClick:c=>{i.props.onClick?.(c),o(a=>!a);}})}return jsxRuntime.jsx("button",{ref:n,type:"button","aria-expanded":r,onClick:()=>o(i=>!i),children:e})}function Qe({children:e,className:t,align:r="start"}){let{open:o,contentRef:n}=Ke();return o?jsxRuntime.jsx("div",{ref:n,className:H("rfs:absolute rfs:top-full rfs:z-50 rfs:mt-2 rfs:min-w-72 rfs:rounded-md rfs:border rfs:border-border rfs:bg-popover rfs:p-2 rfs:text-popover-foreground rfs:shadow-md rfs:outline-none",r==="start"&&"rfs:left-0",r==="center"&&"rfs:left-1/2 rfs:-translate-x-1/2",r==="end"&&"rfs:right-0",t),children:e}):null}function Ze({selectedDate:e,onSelectedDateChange:t}){return jsxRuntime.jsxs(qe,{children:[jsxRuntime.jsx(Je,{asChild:true,children:jsxRuntime.jsx(P,{variant:"outline",size:"sm",className:"rfs:min-w-40 rfs:justify-start rfs:text-left rfs:font-normal",children:dateFns.format(e,"PPP")})}),jsxRuntime.jsx(Qe,{className:"rfs:w-auto rfs:p-2",align:"center",children:jsxRuntime.jsx(We,{selected:e,onSelect:t})})]})}function je({goToPreviousDay:e,goToNextDay:t,defaultDatePicker:r,prevButtonLabel:o="Prev",nextButtonLabel:n="Next"}){return jsxRuntime.jsx("div",{className:"rfs-toolbar",children:jsxRuntime.jsxs("div",{className:"rfs:flex rfs:items-center rfs:gap-2 rfs:rounded-lg rfs:border rfs:border-border rfs:bg-card rfs:p-1 rfs:shadow-xs",children:[jsxRuntime.jsx(P,{variant:"outline",size:"sm",onClick:e,children:o}),r,jsxRuntime.jsx(P,{variant:"outline",size:"sm",onClick:t,children:n})]})})}function rt({selectedDate:e,onSelectedDateChange:t,prevButtonLabel:r,nextButtonLabel:o,renderToolbar:n,renderDatePicker:i}){let c=()=>t(ie(e,-1)),a=()=>t(ie(e,1)),s=(i??Ze)({selectedDate:e,onSelectedDateChange:t});return n?jsxRuntime.jsx(jsxRuntime.Fragment,{children:n({selectedDate:e,onSelectedDateChange:t,goToPreviousDay:c,goToNextDay:a,defaultDatePicker:s})}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:je({goToPreviousDay:c,goToNextDay:a,defaultDatePicker:s,prevButtonLabel:r,nextButtonLabel:o})})}var Lt={kind:"none"};function _t({resources:e,appointments:t,selectedDate:r,onSelectedDateChange:o,adapter:n,onPersistMoveResize:i,onAppointmentChange:c,renderResourceHeader:a,renderAppointment:s,resourceAppointmentClassMap:d,getResourceAppointmentAppearance:f,getResourceAppointmentColorToken:l,appointmentColorTokenClassMap:g,getResourceAppointmentBackground:p,renderToolbar:T,renderDatePicker:v,prevButtonLabel:S="Prev",nextButtonLabel:b="Next",dayStart:y="09:00",dayEnd:E="18:00",editable:$=true}){let{appointmentMap:O,dayMinutes:Y,dayStartAbs:L,gridHeight:F,gridMinWidth:j,renderAppts:W}=De({adapter:n,appointments:t,dayEnd:E,dayStart:y,resources:e,selectedDate:r}),{colRefs:ee,drag:u,isDropInvalid:m,movePreview:R,onApptPointerDown:M,onGlobalPointerMove:X,onGlobalPointerUp:k,onResizePointerDown:ot,suppressClickRef:fe}=Ce({appointmentMap:O,dayMinutes:Y,dayStartAbs:L,onAppointmentChange:c,onPersistMoveResize:i,renderAppts:W,resources:e,selectedDate:r,editable:$}),{appointmentAppearanceByResource:te,appointmentBgByResource:re,laidOutByResource:st}=Be({appointmentColorTokenClassMap:g,dayStartAbs:L,drag:u,getResourceAppointmentAppearance:f,getResourceAppointmentBackground:p,getResourceAppointmentColorToken:l,renderAppts:W,resourceAppointmentClassMap:d,resources:e,selectedDate:r}),x=h__namespace.useMemo(()=>u.kind!=="move"||!R?null:{appointment:{...R.appointment,resourceId:u.resourceId,startMin:u.startMin,endMin:u.endMin,visualState:"ghost",renderKey:`${R.appointment.renderKey}-overlay`,lane:0,lanes:1},appearance:te.get(u.resourceId),background:re.get(u.resourceId),left:R.clientX-R.offsetX,top:R.clientY-R.offsetY,width:R.width,height:R.height},[te,re,u,R]);return jsxRuntime.jsxs("section",{className:`rfs-root rfs:rounded-lg rfs:text-foreground ${u.kind==="move"?"rfs-root--drag-move":""} ${u.kind==="resize"?"rfs-root--drag-resize":""}`,onPointerMove:X,onPointerUp:k,onPointerCancel:k,children:[jsxRuntime.jsx(rt,{selectedDate:r,onSelectedDateChange:o,prevButtonLabel:S,nextButtonLabel:b,renderToolbar:T,renderDatePicker:v}),jsxRuntime.jsx("div",{className:"rfs-shell rfs:border-border rfs:bg-card",children:jsxRuntime.jsxs("div",{style:{minWidth:j},children:[jsxRuntime.jsx(ze,{resources:e,renderResourceHeader:a}),jsxRuntime.jsxs("div",{className:"rfs-body",children:[jsxRuntime.jsx(Ee,{dayMinutes:Y,dayStartAbs:L,gridHeight:F}),jsxRuntime.jsx("div",{className:"rfs-grid",children:e.map(_=>jsxRuntime.jsx(Xe,{resource:_,colRefs:ee,gridHeight:F,dayMinutes:Y,appointments:st.get(_.id)??[],appointmentAppearance:te.get(_.id),appointmentBg:re.get(_.id),isDropInvalid:m,renderAppointment:s,onApptPointerDown:M,onResizePointerDown:ot,drag:u.kind==="resize"&&u.resourceId===_.id?u:Lt,suppressClickRef:fe},String(_.id)))})]})]})}),x?jsxRuntime.jsx("div",{className:"rfs-drag-overlay",style:{left:x.left,top:x.top,width:x.width,height:x.height},children:(s??G)({appointment:x.appointment,isDropInvalid:m,onPointerDown:()=>{},onResizePointerDown:()=>{},appointmentAppearance:x.appearance,appointmentBackgroundColor:x.background,drag:u,suppressClickRef:fe})}):null]})}function zt(e,t,r){return e.map(o=>{if(r.getId(o)!==r.getId(t.appointment))return o;let n=r.setResourceId(o,t.next.resourceId),i=r.setStart(n,t.next.start);return r.setEnd(i,t.next.end)})}exports.Scheduler=_t;exports.applySchedulerAppointmentChange=zt;
|
|
1
|
+
'use strict';var jsxRuntime=require('react/jsx-runtime'),dateFns=require('date-fns'),I=require('react');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var I__namespace=/*#__PURE__*/_interopNamespace(I);var Et=e=>{let{isDropInvalid:t,description:r,title:o}=e;return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[t&&jsxRuntime.jsx("div",{className:"rfs:absolute rfs:right-1 rfs:top-1 rfs:flex rfs:h-4 rfs:w-4 rfs:items-center rfs:justify-center rfs:rounded-full rfs:bg-red-600 rfs:text-[10px] rfs:font-bold rfs:text-white",children:"X"}),jsxRuntime.jsx("div",{className:"rfs:text-xs rfs:font-semibold",children:o}),r&&jsxRuntime.jsx("div",{className:"rfs:mt-1 rfs:text-[10px] rfs:font-medium",children:r})]})},Ne=Et;function ge({appointment:e,onResizePointerDown:t}){return jsxRuntime.jsx("div",{role:"button","aria-label":"Resize appointment",onPointerDown:r=>{e.visualState!=="ghost"&&(r.stopPropagation(),t(r));},className:"rfs:absolute rfs:inset-x-1 rfs:bottom-1 rfs:h-2 rfs:cursor-ns-resize rfs:rounded-full rfs:bg-border/90 rfs:transition-colors rfs:hover:bg-border"})}function Q({appointment:e,isDropInvalid:t,onPointerDown:r,onResizePointerDown:o,appointmentAppearance:n,appointmentBackgroundColor:i}){let a=e.raw,d=typeof a.description=="string"?a.description:void 0,s=typeof i=="string"?i:void 0,c=n?.className??s??"rfs:bg-muted/40 rfs:dark:bg-muted/30",R=t?"rfs:bg-red-100/80 rfs:text-red-950 rfs:dark:bg-red-950/40 rfs:dark:text-red-100":"",f=e.visualState==="ghost"?"rfs:cursor-grab rfs:opacity-35":e.visualState==="dragging"?"rfs:cursor-grabbing rfs:opacity-55 rfs:shadow-xl":"rfs:cursor-grab",g=`rfs:relative rfs:h-full rfs:overflow-hidden rfs:rounded-md rfs:p-2 rfs:pb-5 rfs:text-foreground ${c} ${R} ${f}`;return jsxRuntime.jsxs("div",{onPointerDown:r,className:g,children:[jsxRuntime.jsx(Ne,{isDropInvalid:t,title:e.title,description:d}),jsxRuntime.jsx(ge,{onResizePointerDown:o,appointment:e})]})}var Ft={id:"id",resourceId:"resourceId",start:"start",end:"end",title:"title"},W=(e,t)=>typeof t=="function"?t(e):e[t],Te=e=>e&&"getId"in e?{id:e.getId,resourceId:e.getResourceId,start:e.getStart,end:e.getEnd,title:e.getTitle}:{...Ft,...e},Se=e=>{if(e&&"getId"in e)return e;let t=Te(e);return {getEnd:r=>W(r,t.end),getId:r=>W(r,t.id),getResourceId:r=>W(r,t.resourceId),getStart:r=>W(r,t.start),getTitle:r=>W(r,t.title)}};function Be(e){if(!e||typeof e!="object")return false;let t=e;return typeof t.firstName=="string"||typeof t.lastName=="string"}var Oe={slate:"rfs:bg-slate-100 rfs:dark:bg-slate-900/40",gray:"rfs:bg-gray-100 rfs:dark:bg-gray-900/40",zinc:"rfs:bg-zinc-100 rfs:dark:bg-zinc-900/40",neutral:"rfs:bg-neutral-100 rfs:dark:bg-neutral-900/40",stone:"rfs:bg-stone-100 rfs:dark:bg-stone-900/40",red:"rfs:bg-red-100 rfs:dark:bg-red-950/40",orange:"rfs:bg-orange-100 rfs:dark:bg-orange-950/40",amber:"rfs:bg-amber-100 rfs:dark:bg-amber-950/40",yellow:"rfs:bg-yellow-100 rfs:dark:bg-yellow-950/40",lime:"rfs:bg-lime-100 rfs:dark:bg-lime-950/40",green:"rfs:bg-green-100 rfs:dark:bg-green-950/40",emerald:"rfs:bg-emerald-100 rfs:dark:bg-emerald-950/40",teal:"rfs:bg-teal-100 rfs:dark:bg-teal-950/40",cyan:"rfs:bg-cyan-100 rfs:dark:bg-cyan-950/40",sky:"rfs:bg-sky-100 rfs:dark:bg-sky-950/40",blue:"rfs:bg-blue-100 rfs:dark:bg-blue-950/40",indigo:"rfs:bg-indigo-100 rfs:dark:bg-indigo-950/40",violet:"rfs:bg-violet-100 rfs:dark:bg-violet-950/40",purple:"rfs:bg-purple-100 rfs:dark:bg-purple-950/40",fuchsia:"rfs:bg-fuchsia-100 rfs:dark:bg-fuchsia-950/40",pink:"rfs:bg-pink-100 rfs:dark:bg-pink-950/40",rose:"rfs:bg-rose-100 rfs:dark:bg-rose-950/40"};function L(e,t,r){return Math.max(t,Math.min(r,e))}function K(e,t=15){return Math.round(e/t)*t}function Ae(e){let[t,r]=e.split(":").map(Number);return t*60+r}function Le(e){return `${e.firstName??""} ${e.lastName??""}`.trim()}function Z(e){return dateFns.format(e,"yyyy-MM-dd")}function Ie(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+t)}function $(e,t,r){let o=new Date(e.getFullYear(),e.getMonth(),e.getDate(),0,0,0,0),n=t+r,i=Math.floor(n/60),a=n%60;return o.setHours(i,a,0,0),o}function be(e,t){return t.getHours()*60+t.getMinutes()-e}function ye(e,t){return e.startMin<t.endMin&&t.startMin<e.endMin}function _e(e){let t=[...e].sort((a,d)=>a.startMin-d.startMin||a.endMin-d.endMin),r=[],o=[],n=[];for(let a of t)o=o.filter(s=>s.endMin>a.startMin),!o.some(s=>ye(s,a))&&n.length>0&&(r.push(n),n=[]),n.push(a),o.push(a);n.length&&r.push(n);let i=[];for(let a of r){let d=[...a].sort((f,g)=>f.startMin-g.startMin||f.endMin-g.endMin),s=[],c=new Map;for(let f of d){let g=false;for(let p=0;p<s.length;p++)if(s[p]<=f.startMin){s[p]=f.endMin,c.set(f.id,p),g=true;break}g||(s.push(f.endMin),c.set(f.id,s.length-1));}let R=s.length;for(let f of d)i.push({...f,lane:c.get(f.id)??0,lanes:R});}return i}function Me({fallback:e,getValue:t,resources:r,toKey:o}){let n=new Map;for(let i of r)n.set(o(i),t(i)??e);return n}function Fe({adapter:e,appointments:t,dayMinutes:r,dayStartAbs:o,selectedISO:n}){return t.map(i=>{let a=e.getId(i),d=new Date(e.getStart(i)),s=new Date(e.getEnd(i));return {raw:i,id:a,resourceId:e.getResourceId(i),start:d,end:s,startMin:L(be(o,d),0,r),endMin:L(be(o,s),0,r),title:e.getTitle(i),renderKey:String(a),visualState:"normal"}}).filter(i=>Z(i.start)===n)}function Ve(e){return new Map(e.map(t=>[t.id,t]))}function He(e,t,r,o){return t.kind==="none"||t.kind==="move"?e:e.map(n=>n.id!==t.appointmentId?n:{...n,resourceId:t.resourceId,startMin:t.startMin,endMin:t.endMin,start:$(r,o,t.startMin),end:$(r,o,t.endMin),visualState:"dragging"})}function ze(e,t){let r=new Map;for(let n of t){let i=r.get(n.resourceId)??[];i.push(n),r.set(n.resourceId,i);}let o=new Map;for(let n of e)o.set(n.id,ve(r.get(n.id)??[]));return o}function ve(e){return _e(e.map(t=>({...t,appointmentId:t.id,id:t.renderKey}))).map(({appointmentId:t,...r})=>({...r,id:t}))}function Ye(e,t,r,o,n){let i=new Map;for(let a of e){let d=t?.[String(a.id)];if(d){i.set(a.id,{className:d});continue}let s=r?.(a);if(s){i.set(a.id,s);continue}let c=o.get(a.id);if(c){i.set(a.id,{className:c});continue}let R=n.get(a.id);i.set(a.id,R?{className:R}:void 0);}return i}function Xe({adapter:e,appointments:t,dayEnd:r="18:00",dayStart:o="09:00",resources:n,selectedDate:i}){let a=I__namespace.useMemo(()=>Ae(o),[o]),d=I__namespace.useMemo(()=>Ae(r),[r]),s=I__namespace.useMemo(()=>Math.max(0,d-a),[d,a]),c=I__namespace.useMemo(()=>12+s*2+24,[s]),R=I__namespace.useMemo(()=>72+Math.max(n.length,1)*420,[n.length]),{id:f,resourceId:g,start:p,end:l,title:h}=Te(e),T=I__namespace.useMemo(()=>Se({id:f,resourceId:g,start:p,end:l,title:h}),[f,g,p,l,h]),b=I__namespace.useMemo(()=>Z(i),[i]),S=I__namespace.useMemo(()=>Fe({adapter:T,appointments:t,dayMinutes:s,dayStartAbs:a,selectedISO:b}),[t,s,a,T,b]);return {appointmentMap:I__namespace.useMemo(()=>Ve(S),[S]),dayEndAbs:d,dayMinutes:s,dayStartAbs:a,gridHeight:c,gridMinWidth:R,renderAppts:S}}var Ht=4,zt=(e,t)=>{e(r=>r&&{...r,clientX:t.clientX,clientY:t.clientY});},Yt=e=>{let{dragRef:t,pendingDragRef:r,pointer:o,setDrag:n,setMovePreview:i,suppressClickRef:a}=e,d=r.current;if(!d||d.drag.pointerId!==o.pointerId)return;let s=o.clientX-d.startClientX,c=o.clientY-d.startClientY;Math.hypot(s,c)<Ht||(a.current=true,t.current=d.drag,n(d.drag),d.drag.kind==="move"&&i({appointment:d.appointment,clientX:o.clientX,clientY:o.clientY,width:d.width,height:d.height,offsetX:d.offsetX,offsetY:d.offsetY}),r.current=null);},Xt=(e,t,r,o,n)=>{let i=o(t.clientX,e.resourceId),d=n(i,t.clientY)-e.offsetMin,s=L(K(d),0,r-e.durationMin),c=s+e.durationMin;return s===e.startMin&&c===e.endMin&&i===e.resourceId?null:{...e,resourceId:i,startMin:s,endMin:c}},Ut=(e,t,r,o)=>{let n=o(e.resourceId,t.clientY),i=L(K(n),e.startMin+15,r);return i===e.endMin?null:{...e,endMin:i}},$e=e=>{let{dayMinutes:t,dragRef:r,latestPointerRef:o,pendingDragRef:n,pointerToMin:i,pointerToResourceId:a,setDrag:d,setMovePreview:s,suppressClickRef:c}=e,R=o.current;if(!R)return;let f=r.current;if(f.kind==="none"&&n.current){Yt({pointer:R,pendingDragRef:n,setDrag:d,setMovePreview:s,dragRef:r,suppressClickRef:c});return}if(f.kind==="none")return;if(f.kind==="move"){zt(s,R);let p=Xt(f,R,t,a,i);p&&(c.current=true,r.current=p,d(p));return}let g=Ut(f,R,t,i);g&&(c.current=true,r.current=g,d(g));},We=e=>{let{dragRef:t,frameRef:r,latestPointerRef:o,pendingDragRef:n,persistDrag:i,setDrag:a,setMovePreview:d,suppressClickRef:s}=e;r.current!==null&&(window.cancelAnimationFrame(r.current),r.current=null),o.current=null,n.current=null,d(null);let c=t.current;c.kind!=="none"&&(a({kind:"none"}),t.current={kind:"none"},s.current&&i(c));};var Ke=({appointmentMap:e,dayMinutes:t,dayStartAbs:r,onAppointmentChange:o,onPersistMoveResize:n,renderAppts:i,resources:a,selectedDate:d,editable:s})=>{let[c,R]=I__namespace.useState({kind:"none"}),[f,g]=I__namespace.useState(null),p=I__namespace.useRef({}),l=I__namespace.useRef(false),h=I__namespace.useRef({kind:"none"}),T=I__namespace.useRef(null),b=I__namespace.useRef(null),S=I__namespace.useRef(null),X=I__namespace.useMemo(()=>{let u=new Map;for(let m of i){let A=u.get(m.resourceId)??[];A.push(m),u.set(m.resourceId,A);}return u},[i]);I__namespace.useEffect(()=>{h.current=c;},[c]),I__namespace.useEffect(()=>()=>{S.current!==null&&window.cancelAnimationFrame(S.current);},[]);let y=I__namespace.useCallback((u,m)=>{let A=p.current[String(u)];if(!A)return 0;let C=m-A.getBoundingClientRect().top-12;return L(K(C/2),0,t)},[t]),k=I__namespace.useCallback((u,m)=>{for(let A of a){let C=p.current[String(A.id)];if(!C)continue;let F=C.getBoundingClientRect();if(u>=F.left&&u<=F.right)return A.id}return m},[a]),w=I__namespace.useCallback((u,m,A,C)=>(X.get(m)??[]).some(V=>V.id!==u&&ye(V,{startMin:A,endMin:C})),[X]),ce=I__namespace.useMemo(()=>c.kind==="none"?false:w(c.appointmentId,c.resourceId,c.startMin,c.endMin),[c,w]),q=I__namespace.useCallback(async u=>{let m=e.get(u.appointmentId);if(!m||w(u.appointmentId,u.resourceId,u.startMin,u.endMin))return;let A={resourceId:u.resourceId,start:$(d,r,u.startMin),end:$(d,r,u.endMin)};if(o){await o({kind:u.kind,appointment:m.raw,resourceId:A.resourceId,start:A.start,end:A.end,previousResourceId:m.resourceId,previousStart:m.start,previousEnd:m.end,previous:{resourceId:m.resourceId,start:m.start,end:m.end},next:A});return}n&&await n({appointment:m.raw,resourceId:A.resourceId,start:A.start,end:A.end});},[e,r,w,o,n,d]),ue=I__namespace.useCallback((u,m)=>{if(l.current=false,!s||u.button!==0)return;u.stopPropagation();let A=u.currentTarget.getBoundingClientRect(),C=y(m.resourceId,u.clientY);T.current={drag:{kind:"move",appointmentId:m.id,pointerId:u.pointerId,resourceId:m.resourceId,durationMin:Math.max(15,m.endMin-m.startMin),offsetMin:C-m.startMin,startMin:m.startMin,endMin:m.endMin},appointment:m,startClientX:u.clientX,startClientY:u.clientY,width:A.width,height:A.height,offsetX:u.clientX-A.left,offsetY:u.clientY-A.top};},[y,s]),pe=I__namespace.useCallback((u,m)=>{l.current=false,s&&u.button===0&&(u.stopPropagation(),T.current={drag:{kind:"resize",appointmentId:m.id,pointerId:u.pointerId,resourceId:m.resourceId,startMin:m.startMin,endMin:m.endMin},appointment:m,startClientX:u.clientX,startClientY:u.clientY,width:0,height:0,offsetX:0,offsetY:0});},[s]),le=I__namespace.useCallback(u=>{b.current={clientX:u.clientX,clientY:u.clientY,pointerId:u.pointerId},S.current===null&&(S.current=window.requestAnimationFrame(()=>{S.current=null,$e({dayMinutes:t,dragRef:h,latestPointerRef:b,pendingDragRef:T,pointerToMin:y,pointerToResourceId:k,setDrag:R,setMovePreview:g,suppressClickRef:l});}));},[t,y,k]),fe=I__namespace.useCallback(()=>{We({dragRef:h,frameRef:S,latestPointerRef:b,pendingDragRef:T,persistDrag:q,setDrag:R,setMovePreview:g,suppressClickRef:l});},[q]);return {colRefs:p,drag:c,isDropInvalid:ce,movePreview:f,onApptPointerDown:ue,onGlobalPointerMove:le,onGlobalPointerUp:fe,onResizePointerDown:pe,suppressClickRef:l}};function Ge({appointmentColorTokenClassMap:e,dayStartAbs:t,drag:r,getResourceAppointmentAppearance:o,getResourceAppointmentBackground:n,getResourceAppointmentColorToken:i,renderAppts:a,resourceAppointmentClassMap:d,resources:s,selectedDate:c}){let R=I__namespace.useMemo(()=>He(a,r,c,t),[t,r,a,c]),f=I__namespace.useMemo(()=>ze(s,a),[a,s]),g=I__namespace.useMemo(()=>{if(r.kind!=="resize")return f;let T=new Map(f),b=R.filter(S=>S.resourceId===r.resourceId);return T.set(r.resourceId,ve(b)),T},[f,r,R]),p=I__namespace.useMemo(()=>n?Me({fallback:void 0,getValue:n,resources:s,toKey:T=>T.id}):new Map,[n,s]),l=I__namespace.useMemo(()=>{if(!i)return new Map;let T={...Oe,...e??{}};return Me({fallback:void 0,getValue:b=>{let S=i(b);return S?T[S]:void 0},resources:s,toKey:b=>b.id})},[e,i,s]);return {appointmentAppearanceByResource:I__namespace.useMemo(()=>Ye(s,d,o,l,p),[p,l,o,d,s]),appointmentBgByResource:p,effectiveAppts:R,laidOutByResource:g}}function qe({views:e,view:t,defaultView:r,onViewChange:o}){let[n,i]=I__namespace.useState(()=>r??(e.length>0?e[0]:"day")),a=I__namespace.useCallback(d=>{t===void 0&&i(d),o?.(d);},[t,o]);return [t??n,a]}function B(...e){return e.filter(Boolean).join(" ")}function Je({resource:e}){return jsxRuntime.jsx("strong",{children:e.label})}function re({resources:e,renderResourceHeader:t}){return jsxRuntime.jsxs("div",{className:"rfs-header rfs:border-border rfs:bg-card",children:[jsxRuntime.jsx("div",{className:"rfs-gutter rfs:border-border",style:{width:72}}),e.map(r=>jsxRuntime.jsxs("div",{className:"rfs-resource-header rfs:border-border rfs:bg-card rfs:text-foreground",style:{minWidth:420,flex:1},children:[(t??(o=>Je({resource:o})))(r),Be(r)?jsxRuntime.jsx("div",{className:"rfs-resource-subtitle rfs:text-muted-foreground",children:Le(r)}):null]},String(r.id)))]})}var je=e=>dateFns.format(e,"HH:mm"),et=e=>String(e).padStart(2,"0"),Kt=e=>`${et(Math.floor(e/60))}:${et(e%60)}`,tt=e=>Math.floor((e.getHours()*60+e.getMinutes())/15)*15,rt=(e,t)=>`${e}|${String(t)}`;function nt({appointment:e}){let t=e.raw,r=typeof t.description=="string"?t.description:void 0;return jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsxs("span",{className:"rfs:block rfs:text-xs rfs:font-medium rfs:tabular-nums",children:[je(e.start),"\u2013",je(e.end)]}),jsxRuntime.jsx("span",{className:"rfs:block rfs:text-xs rfs:font-semibold",children:e.title}),r&&jsxRuntime.jsx("span",{className:"rfs:block rfs:text-[10px] rfs:font-medium",children:r})]})}function st({appointments:e,resources:t,appointmentAppearanceByResource:r,dayStartAbs:o,dayEndAbs:n,onAppointmentClick:i,renderResourceHeader:a,renderAgendaItem:d,emptyState:s="No appointments"}){let{slots:c,cells:R}=I__namespace.useMemo(()=>{let p=new Set(t.map(y=>y.id)),l=e.filter(y=>p.has(y.resourceId)).sort((y,k)=>y.start.getTime()-k.start.getTime()),h=new Map;for(let y of l){let k=rt(tt(y.start),y.resourceId),w=h.get(k)??[];w.push(y),h.set(k,w);}let T=l.map(y=>tt(y.start)),b=Math.min(Math.floor(o/15)*15,...T),S=Math.max(Math.ceil(n/15)*15-15,...T);return {slots:Array.from({length:Math.max(0,(S-b)/15+1)},(y,k)=>b+k*15),cells:h}},[e,t,o,n]);if(!(R.size>0))return jsxRuntime.jsx("div",{className:"rfs-agenda rfs:rounded-lg rfs:border rfs:border-border rfs:bg-card rfs:p-6 rfs:text-center rfs:text-sm rfs:text-muted-foreground",children:s});let g=(p,l)=>{let h=r.get(l.id),T=i?S=>i(p.raw,S):void 0;if(d)return jsxRuntime.jsx("li",{onClick:T,children:d({appointment:p,resource:l,appointmentAppearance:h})},p.renderKey);let b=B("rfs:block rfs:w-full rfs:rounded-md rfs:px-3 rfs:py-2 rfs:text-left rfs:text-foreground",h?.className??"rfs:bg-muted/40 rfs:dark:bg-muted/30");return jsxRuntime.jsx("li",{children:T?jsxRuntime.jsx("button",{type:"button",className:B(b,"rfs:cursor-pointer"),onClick:T,children:jsxRuntime.jsx(nt,{appointment:p})}):jsxRuntime.jsx("div",{className:b,children:jsxRuntime.jsx(nt,{appointment:p})})},p.renderKey)};return jsxRuntime.jsx("div",{className:"rfs-agenda rfs-shell rfs:border-border rfs:bg-card",children:jsxRuntime.jsxs("div",{style:{minWidth:72+Math.max(t.length,1)*420},children:[jsxRuntime.jsx(re,{resources:t,renderResourceHeader:a}),c.map(p=>{let l=p%60===0,h=(p+15)%60===0?"var(--rfs-border)":"color-mix(in oklab, var(--rfs-border) 40%, transparent)";return jsxRuntime.jsxs("div",{className:"rfs:flex",children:[jsxRuntime.jsx("div",{className:B("rfs-gutter rfs:border-b rfs:px-2 rfs:py-1 rfs:text-xs rfs:tabular-nums",l?"rfs:text-foreground":"rfs:text-muted-foreground/70"),style:{width:72,borderBottomColor:h},children:Kt(p)}),t.map(T=>jsxRuntime.jsx("ul",{"aria-label":T.label,className:"rfs-col rfs:flex rfs:min-h-7 rfs:flex-col rfs:gap-1 rfs:border-b rfs:p-1",style:{minWidth:420,flex:1,borderBottomColor:h},children:(R.get(rt(p,T.id))??[]).map(b=>g(b,T))},String(T.id)))]},p)})]})})}function it({dayMinutes:e,dayStartAbs:t,gridHeight:r}){return jsxRuntime.jsx("div",{className:"rfs-times rfs:border-border rfs:bg-card",style:{width:72,height:r},children:Array.from({length:Math.floor(e/60)+1}).map((o,n)=>jsxRuntime.jsxs("div",{className:"rfs-time-tick rfs:text-muted-foreground",style:{top:12+n*60*2},children:[String(Math.floor((t+n*60)/60)).padStart(2,"0"),":",String((t+n*60)%60).padStart(2,"0")]},`tick-${n}`))})}var dt=({resource:e,colRefs:t,gridHeight:r,dayMinutes:o,appointments:n,appointmentAppearance:i,appointmentBg:a,isDropInvalid:d,renderAppointment:s,onAppointmentClick:c,onApptPointerDown:R,onResizePointerDown:f,drag:g,suppressClickRef:p})=>jsxRuntime.jsx("div",{className:"rfs-col rfs:border-border rfs:bg-card",style:{minWidth:420,flex:1},children:jsxRuntime.jsxs("div",{ref:l=>{t.current[String(e.id)]=l;},className:"rfs-col-inner rfs:bg-card",style:{height:r},children:[Array.from({length:Math.floor(o/60)+1}).map((l,h)=>jsxRuntime.jsx("div",{className:"rfs-hour-line rfs:border-border/70",style:{top:12+h*60*2}},`major-${h}`)),Array.from({length:Math.floor(o/15)+1}).map((l,h)=>jsxRuntime.jsx("div",{className:"rfs-slot-line rfs:border-border/50",style:{top:12+h*15*2}},`minor-${h}`)),n.map(l=>{let h=100/l.lanes,T=12+l.startMin*2,b=Math.max(30,(l.endMin-l.startMin)*2);return jsxRuntime.jsx("div",{className:`rfs-card-slot ${l.visualState==="ghost"?"rfs-card-slot--ghost":""} ${l.visualState==="dragging"?"rfs-card-slot--dragging":""}`,style:{top:T,left:`${h*l.lane}%`,width:`${h}%`,height:b},onClick:c?S=>{p.current||c(l.raw,S);}:void 0,children:(s??Q)({appointment:l,isDropInvalid:d&&g.kind==="resize"&&l.id===g.appointmentId,onPointerDown:S=>R(S,l),onResizePointerDown:S=>f(S,l),appointmentAppearance:i,appointmentBackgroundColor:a,drag:g,suppressClickRef:p})},l.renderKey)})]})});var Zt=(e,t)=>[e.resource===t.resource,e.colRefs===t.colRefs,e.gridHeight===t.gridHeight,e.dayMinutes===t.dayMinutes,e.appointments===t.appointments,e.appointmentAppearance===t.appointmentAppearance,e.appointmentBg===t.appointmentBg,e.isDropInvalid===t.isDropInvalid,e.renderAppointment===t.renderAppointment,e.onAppointmentClick===t.onAppointmentClick,e.onApptPointerDown===t.onApptPointerDown,e.onResizePointerDown===t.onResizePointerDown,e.drag===t.drag,e.suppressClickRef===t.suppressClickRef].every(Boolean),ct=I__namespace.memo(dt,Zt);var jt={default:"rfs:bg-primary rfs:text-primary-foreground rfs:hover:bg-primary/90",outline:"rfs:border rfs:border-border rfs:bg-card rfs:text-foreground rfs:hover:bg-muted",ghost:"rfs:text-foreground rfs:hover:bg-muted"},er={default:"rfs:h-9 rfs:px-4 rfs:py-2",sm:"rfs:h-8 rfs:px-3 rfs:text-xs",icon:"rfs:h-8 rfs:w-8"},D=I__namespace.forwardRef(function({className:t,variant:r="default",size:o="default",type:n="button",...i},a){return jsxRuntime.jsx("button",{ref:a,type:n,className:B("rfs:inline-flex rfs:items-center rfs:justify-center rfs:gap-2 rfs:rounded-md rfs:text-sm rfs:font-medium rfs:whitespace-nowrap rfs:transition-colors rfs:focus-visible:outline-none rfs:focus-visible:ring-2 rfs:focus-visible:ring-ring rfs:focus-visible:ring-offset-2 rfs:disabled:pointer-events-none rfs:disabled:opacity-50",jt[r],er[o],t),...i})});function mt({selected:e,onSelect:t}){let[r,o]=I__namespace.useState(e??new Date);I__namespace.useEffect(()=>{e&&o(e);},[e]);let n=dateFns.startOfMonth(r),i=dateFns.startOfWeek(n,{weekStartsOn:1}),a=dateFns.endOfWeek(dateFns.endOfMonth(r),{weekStartsOn:1}),d=[];for(let s=i;s<=a;s=dateFns.addDays(s,1))d.push(s);return jsxRuntime.jsxs("div",{className:"rfs:w-72 rfs:rounded-md rfs:bg-popover",children:[jsxRuntime.jsxs("div",{className:"rfs:mb-2 rfs:flex rfs:items-center rfs:justify-between",children:[jsxRuntime.jsx(D,{variant:"ghost",size:"icon","aria-label":"Previous month",onClick:()=>o(dateFns.addMonths(r,-1)),children:"<"}),jsxRuntime.jsx("div",{className:"rfs:text-sm rfs:font-medium",children:dateFns.format(r,"MMMM yyyy")}),jsxRuntime.jsx(D,{variant:"ghost",size:"icon","aria-label":"Next month",onClick:()=>o(dateFns.addMonths(r,1)),children:">"})]}),jsxRuntime.jsx("div",{className:"rfs:grid rfs:grid-cols-7 rfs:gap-1 rfs:text-center rfs:text-xs rfs:text-muted-foreground",children:["Mo","Tu","We","Th","Fr","Sa","Su"].map(s=>jsxRuntime.jsx("div",{className:"rfs:py-1",children:s},s))}),jsxRuntime.jsx("div",{className:"rfs:grid rfs:grid-cols-7 rfs:gap-1",children:d.map(s=>{let c=e?dateFns.isSameDay(s,e):false;return jsxRuntime.jsx(D,{variant:c?"default":"ghost",size:"icon",className:B("rfs:text-xs",!dateFns.isSameMonth(s,r)&&"rfs:text-muted-foreground rfs:opacity-60",dateFns.isToday(s)&&!c&&"rfs:border rfs:border-border"),onClick:()=>t?.(s),children:dateFns.format(s,"d")},s.toISOString())})})]})}var Rt=I__namespace.createContext(null);function ht(){let e=I__namespace.useContext(Rt);if(!e)throw new Error("Popover components must be used within Popover.");return e}function gt({children:e,open:t,onOpenChange:r}){let[o,n]=I__namespace.useState(false),i=I__namespace.useRef(null),a=I__namespace.useRef(null),d=t??o,s=I__namespace.useCallback(c=>{let R=typeof c=="function"?c(d):c;t===void 0&&n(R),r?.(R);},[t,r,d]);return I__namespace.useEffect(()=>{if(!d)return;let c=f=>{let g=f.target;i.current?.contains(g)||a.current?.contains(g)||s(false);},R=f=>{f.key==="Escape"&&s(false);};return document.addEventListener("mousedown",c),document.addEventListener("keydown",R),()=>{document.removeEventListener("mousedown",c),document.removeEventListener("keydown",R);}},[d,s]),jsxRuntime.jsx(Rt.Provider,{value:{open:d,setOpen:s,triggerRef:i,contentRef:a},children:jsxRuntime.jsx("div",{className:"rfs:relative rfs:inline-flex",children:e})})}function Tt({children:e,asChild:t=false}){let{open:r,setOpen:o,triggerRef:n}=ht();if(t&&I__namespace.isValidElement(e)){let i=e;return I__namespace.cloneElement(i,{ref:n,"aria-expanded":r,onClick:a=>{i.props.onClick?.(a),o(d=>!d);}})}return jsxRuntime.jsx("button",{ref:n,type:"button","aria-expanded":r,onClick:()=>o(i=>!i),children:e})}function St({children:e,className:t,align:r="start"}){let{open:o,contentRef:n}=ht();return o?jsxRuntime.jsx("div",{ref:n,className:B("rfs:absolute rfs:top-full rfs:z-50 rfs:mt-2 rfs:min-w-72 rfs:rounded-md rfs:border rfs:border-border rfs:bg-popover rfs:p-2 rfs:text-popover-foreground rfs:shadow-md rfs:outline-none",r==="start"&&"rfs:left-0",r==="center"&&"rfs:left-1/2 rfs:-translate-x-1/2",r==="end"&&"rfs:right-0",t),children:e}):null}function At({selectedDate:e,onSelectedDateChange:t}){return jsxRuntime.jsxs(gt,{children:[jsxRuntime.jsx(Tt,{asChild:true,children:jsxRuntime.jsx(D,{variant:"outline",size:"sm",className:"rfs:min-w-40 rfs:justify-start rfs:text-left rfs:font-normal",children:dateFns.format(e,"PPP")})}),jsxRuntime.jsx(St,{className:"rfs:w-auto rfs:p-2",align:"center",children:jsxRuntime.jsx(mt,{selected:e,onSelect:t})})]})}function bt({goToPreviousDay:e,goToNextDay:t,defaultDatePicker:r,defaultViewSwitcher:o,prevButtonLabel:n="Prev",nextButtonLabel:i="Next"}){return jsxRuntime.jsxs("div",{className:"rfs-toolbar",children:[jsxRuntime.jsxs("div",{className:"rfs:flex rfs:items-center rfs:gap-2 rfs:rounded-lg rfs:border rfs:border-border rfs:bg-card rfs:p-1 rfs:shadow-xs",children:[jsxRuntime.jsx(D,{variant:"outline",size:"sm",onClick:e,children:n}),r,jsxRuntime.jsx(D,{variant:"outline",size:"sm",onClick:t,children:i})]}),o&&jsxRuntime.jsx("div",{className:"rfs:ml-auto",children:o})]})}var lr={day:"Day",agenda:"Agenda"};function Mt({selectedDate:e,onSelectedDateChange:t,prevButtonLabel:r,nextButtonLabel:o,renderToolbar:n,renderDatePicker:i,view:a,views:d,onViewChange:s,viewLabels:c}){let R=()=>t(Ie(e,-1)),f=()=>t(Ie(e,1)),g=(i??At)({selectedDate:e,onSelectedDateChange:t}),p=d.length>1?jsxRuntime.jsx("div",{role:"group","aria-label":"View",className:"rfs:flex rfs:items-center rfs:gap-1 rfs:rounded-lg rfs:border rfs:border-border rfs:bg-card rfs:p-1 rfs:shadow-xs",children:d.map(h=>jsxRuntime.jsx(D,{variant:h===a?"default":"ghost",size:"sm","aria-pressed":h===a,onClick:()=>s(h),children:c?.[h]??lr[h]},h))}):null,l={selectedDate:e,onSelectedDateChange:t,goToPreviousDay:R,goToNextDay:f,defaultDatePicker:g,view:a,views:d,onViewChange:s,defaultViewSwitcher:p};return n?jsxRuntime.jsx(jsxRuntime.Fragment,{children:n(l)}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:bt({...l,prevButtonLabel:r,nextButtonLabel:o})})}var fr={kind:"none"},mr=["day"];function Rr({resources:e,appointments:t,selectedDate:r,onSelectedDateChange:o,adapter:n,onPersistMoveResize:i,onAppointmentChange:a,onAppointmentClick:d,renderResourceHeader:s,renderAppointment:c,resourceAppointmentClassMap:R,getResourceAppointmentAppearance:f,getResourceAppointmentColorToken:g,appointmentColorTokenClassMap:p,getResourceAppointmentBackground:l,renderToolbar:h,renderDatePicker:T,prevButtonLabel:b="Prev",nextButtonLabel:S="Next",dayStart:X="09:00",dayEnd:y="18:00",editable:k=true,views:w=mr,view:ce,defaultView:q,onViewChange:ue,viewLabels:pe,renderAgendaItem:le,agendaEmptyState:fe}){let[u,m]=qe({views:w,view:ce,defaultView:q,onViewChange:ue}),{appointmentMap:A,dayEndAbs:C,dayMinutes:F,dayStartAbs:V,gridHeight:ke,gridMinWidth:Pt,renderAppts:me}=Xe({adapter:n,appointments:t,dayEnd:y,dayStart:X,resources:e,selectedDate:r}),{colRefs:kt,drag:v,isDropInvalid:De,movePreview:N,onApptPointerDown:Dt,onGlobalPointerMove:wt,onGlobalPointerUp:we,onResizePointerDown:Ct,suppressClickRef:Ce}=Ke({appointmentMap:A,dayMinutes:F,dayStartAbs:V,onAppointmentChange:a,onPersistMoveResize:i,renderAppts:me,resources:e,selectedDate:r,editable:k}),{appointmentAppearanceByResource:J,appointmentBgByResource:Re,laidOutByResource:Nt}=Ge({appointmentColorTokenClassMap:p,dayStartAbs:V,drag:v,getResourceAppointmentAppearance:f,getResourceAppointmentBackground:l,getResourceAppointmentColorToken:g,renderAppts:me,resourceAppointmentClassMap:R,resources:e,selectedDate:r}),O=I__namespace.useMemo(()=>v.kind!=="move"||!N?null:{appointment:{...N.appointment,resourceId:v.resourceId,startMin:v.startMin,endMin:v.endMin,visualState:"ghost",renderKey:`${N.appointment.renderKey}-overlay`,lane:0,lanes:1},appearance:J.get(v.resourceId),background:Re.get(v.resourceId),left:N.clientX-N.offsetX,top:N.clientY-N.offsetY,width:N.width,height:N.height},[J,Re,v,N]);return jsxRuntime.jsxs("section",{className:`rfs-root rfs:rounded-lg rfs:text-foreground ${v.kind==="move"?"rfs-root--drag-move":""} ${v.kind==="resize"?"rfs-root--drag-resize":""}`,onPointerMove:wt,onPointerUp:we,onPointerCancel:we,children:[jsxRuntime.jsx(Mt,{selectedDate:r,onSelectedDateChange:o,prevButtonLabel:b,nextButtonLabel:S,renderToolbar:h,renderDatePicker:T,view:u,views:w,onViewChange:m,viewLabels:pe}),u==="agenda"?jsxRuntime.jsx(st,{appointments:me,resources:e,appointmentAppearanceByResource:J,dayStartAbs:V,dayEndAbs:C,onAppointmentClick:d,renderResourceHeader:s,renderAgendaItem:le,emptyState:fe}):jsxRuntime.jsx("div",{className:"rfs-shell rfs:border-border rfs:bg-card",children:jsxRuntime.jsxs("div",{style:{minWidth:Pt},children:[jsxRuntime.jsx(re,{resources:e,renderResourceHeader:s}),jsxRuntime.jsxs("div",{className:"rfs-body",children:[jsxRuntime.jsx(it,{dayMinutes:F,dayStartAbs:V,gridHeight:ke}),jsxRuntime.jsx("div",{className:"rfs-grid",children:e.map(U=>jsxRuntime.jsx(ct,{resource:U,colRefs:kt,gridHeight:ke,dayMinutes:F,appointments:Nt.get(U.id)??[],appointmentAppearance:J.get(U.id),appointmentBg:Re.get(U.id),isDropInvalid:De,renderAppointment:c,onAppointmentClick:d,onApptPointerDown:Dt,onResizePointerDown:Ct,drag:v.kind==="resize"&&v.resourceId===U.id?v:fr,suppressClickRef:Ce},String(U.id)))})]})]})}),O?jsxRuntime.jsx("div",{className:"rfs-drag-overlay",style:{left:O.left,top:O.top,width:O.width,height:O.height},children:(c??Q)({appointment:O.appointment,isDropInvalid:De,onPointerDown:()=>{},onResizePointerDown:()=>{},appointmentAppearance:O.appearance,appointmentBackgroundColor:O.background,drag:v,suppressClickRef:Ce})}):null]})}var hr={id:"id",resourceId:"resourceId",start:"start",end:"end"},xt=(e,t)=>typeof t=="function"?t(e):e[t],gr=e=>!("getId"in e),Tr=e=>({resourceId:e.resourceId??e.next.resourceId,start:e.start??e.next.start,end:e.end??e.next.end}),Sr=(e,t,...[r={}])=>{let o=Tr(t);return e.map(n=>{if(gr(r)){let d={...hr,...r};if(xt(n,d.id)!==xt(t.appointment,d.id))return n;let s=r.dateValue??(c=>c);return {...n,[d.resourceId]:o.resourceId,[d.start]:s(o.start),[d.end]:s(o.end)}}if(r.getId(n)!==r.getId(t.appointment))return n;let i=r.setResourceId(n,o.resourceId),a=r.setStart(i,o.start);return r.setEnd(a,o.end)})};exports.Scheduler=Rr;exports.applySchedulerAppointmentChange=Sr;exports.resolveSchedulerAppointmentAdapter=Se;
|
package/dist/index.d.cts
CHANGED
|
@@ -8,7 +8,33 @@ type SchedulerAppointmentAdapter<TAppointment, TResourceId extends string | numb
|
|
|
8
8
|
getEnd: (item: TAppointment) => Date | string;
|
|
9
9
|
getTitle: (item: TAppointment) => string;
|
|
10
10
|
};
|
|
11
|
+
type SchedulerAppointmentField<TAppointment, TValue> = Extract<keyof TAppointment, string | number> | ((item: TAppointment) => TValue);
|
|
12
|
+
type SchedulerAppointmentFieldAdapter<TAppointment, TResourceId extends string | number> = {
|
|
13
|
+
id: SchedulerAppointmentField<TAppointment, number | string>;
|
|
14
|
+
resourceId: SchedulerAppointmentField<TAppointment, TResourceId>;
|
|
15
|
+
start: SchedulerAppointmentField<TAppointment, Date | string>;
|
|
16
|
+
end: SchedulerAppointmentField<TAppointment, Date | string>;
|
|
17
|
+
title: SchedulerAppointmentField<TAppointment, string>;
|
|
18
|
+
};
|
|
19
|
+
type SchedulerAppointmentAdapterInput<TAppointment, TResourceId extends string | number> = SchedulerAppointmentAdapter<TAppointment, TResourceId> | SchedulerAppointmentFieldAdapter<TAppointment, TResourceId>;
|
|
11
20
|
type SchedulerId = string | number;
|
|
21
|
+
type SchedulerDefaultFieldValues<TResourceId extends SchedulerId> = {
|
|
22
|
+
id: SchedulerId;
|
|
23
|
+
resourceId: TResourceId;
|
|
24
|
+
start: Date | string;
|
|
25
|
+
end: Date | string;
|
|
26
|
+
title: string;
|
|
27
|
+
};
|
|
28
|
+
/** Adapter fields the appointment already exposes under the default name with a compatible type. */
|
|
29
|
+
type SchedulerDefaultedAppointmentField<TAppointment, TResourceId extends SchedulerId> = {
|
|
30
|
+
[K in keyof SchedulerDefaultFieldValues<TResourceId>]: K extends keyof TAppointment ? TAppointment[K] extends SchedulerDefaultFieldValues<TResourceId>[K] ? K : never : never;
|
|
31
|
+
}[keyof SchedulerDefaultFieldValues<TResourceId>];
|
|
32
|
+
/**
|
|
33
|
+
* Key-based adapter where fields matching the default names
|
|
34
|
+
* (`id`, `resourceId`, `start`, `end`, `title`) can be omitted.
|
|
35
|
+
*/
|
|
36
|
+
type SchedulerAppointmentPartialFieldAdapter<TAppointment, TResourceId extends SchedulerId> = Omit<SchedulerAppointmentFieldAdapter<TAppointment, TResourceId>, SchedulerDefaultedAppointmentField<TAppointment, TResourceId>> & Partial<Pick<SchedulerAppointmentFieldAdapter<TAppointment, TResourceId>, SchedulerDefaultedAppointmentField<TAppointment, TResourceId>>>;
|
|
37
|
+
type SchedulerAppointmentAdapterOption<TAppointment, TResourceId extends SchedulerId> = SchedulerAppointmentAdapter<TAppointment, TResourceId> | SchedulerAppointmentPartialFieldAdapter<TAppointment, TResourceId>;
|
|
12
38
|
type BaseSchedulerResource<TId extends SchedulerId = number> = {
|
|
13
39
|
id: TId;
|
|
14
40
|
label: string;
|
|
@@ -51,6 +77,12 @@ type RenderSchedulerAppt<TAppointment, TResourceId extends SchedulerId> = Schedu
|
|
|
51
77
|
type SchedulerAppointmentChangeArgs<TAppointment, TResourceId extends SchedulerId> = {
|
|
52
78
|
kind: "move" | "resize";
|
|
53
79
|
appointment: TAppointment;
|
|
80
|
+
resourceId?: TResourceId;
|
|
81
|
+
start?: Date;
|
|
82
|
+
end?: Date;
|
|
83
|
+
previousResourceId?: TResourceId;
|
|
84
|
+
previousStart?: Date;
|
|
85
|
+
previousEnd?: Date;
|
|
54
86
|
previous: {
|
|
55
87
|
resourceId: TResourceId;
|
|
56
88
|
start: Date;
|
|
@@ -62,31 +94,61 @@ type SchedulerAppointmentChangeArgs<TAppointment, TResourceId extends SchedulerI
|
|
|
62
94
|
end: Date;
|
|
63
95
|
};
|
|
64
96
|
};
|
|
97
|
+
type SchedulerAppointmentChangeEvent<TAppointment, TResourceId extends SchedulerId> = SchedulerAppointmentChangeArgs<TAppointment, TResourceId> & {
|
|
98
|
+
resourceId: TResourceId;
|
|
99
|
+
start: Date;
|
|
100
|
+
end: Date;
|
|
101
|
+
previousResourceId: TResourceId;
|
|
102
|
+
previousStart: Date;
|
|
103
|
+
previousEnd: Date;
|
|
104
|
+
};
|
|
65
105
|
type SchedulerAppointmentAppearance = {
|
|
66
106
|
className?: string;
|
|
67
107
|
};
|
|
68
108
|
type SchedulerAppointmentColorToken = string;
|
|
69
109
|
type SchedulerResourceClassMap = Partial<Record<string, string>>;
|
|
110
|
+
/** `"day"` is the resource grid; `"agenda"` is a time-ordered list of the selected day. */
|
|
111
|
+
type SchedulerView = "day" | "agenda";
|
|
112
|
+
type SchedulerAgendaItemRenderArgs<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId> = {
|
|
113
|
+
appointment: SchedulerEvent<TAppointment, TResourceId>;
|
|
114
|
+
resource: TResource;
|
|
115
|
+
appointmentAppearance?: SchedulerAppointmentAppearance;
|
|
116
|
+
};
|
|
70
117
|
type SchedulerToolbarRenderArgs = {
|
|
71
118
|
selectedDate: Date;
|
|
72
119
|
onSelectedDateChange: (date: Date) => void;
|
|
73
120
|
goToPreviousDay: () => void;
|
|
74
121
|
goToNextDay: () => void;
|
|
75
122
|
defaultDatePicker: React.ReactNode;
|
|
123
|
+
view: SchedulerView;
|
|
124
|
+
views: SchedulerView[];
|
|
125
|
+
onViewChange: (view: SchedulerView) => void;
|
|
126
|
+
/** Built-in view switcher, or `null` when fewer than two views are enabled. */
|
|
127
|
+
defaultViewSwitcher: React.ReactNode;
|
|
128
|
+
};
|
|
129
|
+
/** `adapter` is optional only when every field can fall back to its default name. */
|
|
130
|
+
type SchedulerAdapterProp<TAppointment, TResourceId extends SchedulerId> = [
|
|
131
|
+
Exclude<keyof SchedulerDefaultFieldValues<TResourceId>, SchedulerDefaultedAppointmentField<TAppointment, TResourceId>>
|
|
132
|
+
] extends [never] ? {
|
|
133
|
+
adapter?: SchedulerAppointmentAdapterOption<TAppointment, TResourceId>;
|
|
134
|
+
} : {
|
|
135
|
+
adapter: SchedulerAppointmentAdapterOption<TAppointment, TResourceId>;
|
|
76
136
|
};
|
|
77
|
-
type SchedulerProps<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId> =
|
|
137
|
+
type SchedulerProps<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId> = SchedulerCommonProps<TAppointment, TResource, TResourceId> & SchedulerAdapterProp<TAppointment, TResourceId>;
|
|
138
|
+
type SchedulerCommonProps<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId> = {
|
|
78
139
|
resources: TResource[];
|
|
79
140
|
appointments: TAppointment[];
|
|
80
141
|
selectedDate: Date;
|
|
81
142
|
onSelectedDateChange: (date: Date) => void;
|
|
82
|
-
|
|
143
|
+
/** Called on a plain click (not after a drag or resize). */
|
|
144
|
+
onAppointmentClick?: (appointment: TAppointment, event: React.MouseEvent<HTMLElement>) => void;
|
|
83
145
|
onPersistMoveResize?: (args: {
|
|
84
146
|
appointment: TAppointment;
|
|
85
147
|
resourceId: TResourceId;
|
|
86
148
|
start: Date;
|
|
87
149
|
end: Date;
|
|
88
150
|
}) => Promise<void> | void;
|
|
89
|
-
onAppointmentChange?: (args:
|
|
151
|
+
onAppointmentChange?: (args: SchedulerAppointmentChangeEvent<TAppointment, TResourceId>) => Promise<void> | void;
|
|
90
152
|
renderResourceHeader?: (resource: TResource) => React.ReactNode;
|
|
91
153
|
renderAppointment?: (args: {
|
|
92
154
|
appointment: SchedulerPresentationAppointment<TAppointment, TResourceId> & {
|
|
@@ -116,9 +178,22 @@ type SchedulerProps<TAppointment, TResource extends BaseSchedulerResource<TResou
|
|
|
116
178
|
dayStart?: string;
|
|
117
179
|
dayEnd?: string;
|
|
118
180
|
editable?: boolean;
|
|
181
|
+
/** Views offered by the built-in switcher. Defaults to `["day"]` (no switcher). */
|
|
182
|
+
views?: SchedulerView[];
|
|
183
|
+
/** Controlled view. */
|
|
184
|
+
view?: SchedulerView;
|
|
185
|
+
/** Initial view when `view` is not controlled. Defaults to the first entry of `views`. */
|
|
186
|
+
defaultView?: SchedulerView;
|
|
187
|
+
onViewChange?: (view: SchedulerView) => void;
|
|
188
|
+
viewLabels?: Partial<Record<SchedulerView, React.ReactNode>>;
|
|
189
|
+
renderAgendaItem?: (args: SchedulerAgendaItemRenderArgs<TAppointment, TResource, TResourceId>) => React.ReactNode;
|
|
190
|
+
/** Shown in the agenda view when the selected day has no appointments. */
|
|
191
|
+
agendaEmptyState?: React.ReactNode;
|
|
119
192
|
};
|
|
120
193
|
|
|
121
|
-
declare function Scheduler<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId>({ resources, appointments, selectedDate, onSelectedDateChange, adapter, onPersistMoveResize, onAppointmentChange, renderResourceHeader, renderAppointment, resourceAppointmentClassMap, getResourceAppointmentAppearance, getResourceAppointmentColorToken, appointmentColorTokenClassMap, getResourceAppointmentBackground, renderToolbar, renderDatePicker, prevButtonLabel, nextButtonLabel, dayStart, dayEnd, editable }: SchedulerProps<TAppointment, TResource, TResourceId>): react_jsx_runtime.JSX.Element;
|
|
194
|
+
declare function Scheduler<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId>({ resources, appointments, selectedDate, onSelectedDateChange, adapter, onPersistMoveResize, onAppointmentChange, onAppointmentClick, renderResourceHeader, renderAppointment, resourceAppointmentClassMap, getResourceAppointmentAppearance, getResourceAppointmentColorToken, appointmentColorTokenClassMap, getResourceAppointmentBackground, renderToolbar, renderDatePicker, prevButtonLabel, nextButtonLabel, dayStart, dayEnd, editable, views, view: controlledView, defaultView, onViewChange, viewLabels, renderAgendaItem, agendaEmptyState, }: SchedulerProps<TAppointment, TResource, TResourceId>): react_jsx_runtime.JSX.Element;
|
|
195
|
+
|
|
196
|
+
declare const resolveSchedulerAppointmentAdapter: <TAppointment, TResourceId extends string | number>(adapter?: SchedulerAppointmentAdapterInput<TAppointment, TResourceId> | SchedulerAppointmentAdapterOption<TAppointment, TResourceId>) => SchedulerAppointmentAdapter<TAppointment, TResourceId>;
|
|
122
197
|
|
|
123
198
|
type ApplySchedulerAppointmentChangeOptions<TAppointment, TResourceId extends SchedulerId> = {
|
|
124
199
|
getId: (appointment: TAppointment) => SchedulerId;
|
|
@@ -126,6 +201,23 @@ type ApplySchedulerAppointmentChangeOptions<TAppointment, TResourceId extends Sc
|
|
|
126
201
|
setStart: (appointment: TAppointment, start: Date) => TAppointment;
|
|
127
202
|
setEnd: (appointment: TAppointment, end: Date) => TAppointment;
|
|
128
203
|
};
|
|
129
|
-
|
|
204
|
+
type AppointmentKey<TAppointment> = Extract<keyof TAppointment, string | number>;
|
|
205
|
+
type ChangeFields<TAppointment> = {
|
|
206
|
+
id: SchedulerAppointmentField<TAppointment, SchedulerId>;
|
|
207
|
+
resourceId: AppointmentKey<TAppointment>;
|
|
208
|
+
start: AppointmentKey<TAppointment>;
|
|
209
|
+
end: AppointmentKey<TAppointment>;
|
|
210
|
+
};
|
|
211
|
+
/** Default field names the appointment actually has; those can be omitted from the options. */
|
|
212
|
+
type DefaultedChangeField<TAppointment> = Extract<keyof ChangeFields<TAppointment>, keyof TAppointment>;
|
|
213
|
+
/**
|
|
214
|
+
* Key-based options. `id`, `resourceId`, `start` and `end` default to the fields with the same name,
|
|
215
|
+
* so they are optional when the appointment has them.
|
|
216
|
+
*/
|
|
217
|
+
type ApplySchedulerAppointmentChangeFieldOptions<TAppointment> = Omit<ChangeFields<TAppointment>, DefaultedChangeField<TAppointment>> & Partial<Pick<ChangeFields<TAppointment>, DefaultedChangeField<TAppointment>>> & {
|
|
218
|
+
dateValue?: (date: Date) => unknown;
|
|
219
|
+
};
|
|
220
|
+
type ApplySchedulerAppointmentChangeInput<TAppointment, TResourceId extends SchedulerId> = ApplySchedulerAppointmentChangeOptions<TAppointment, TResourceId> | ApplySchedulerAppointmentChangeFieldOptions<TAppointment>;
|
|
221
|
+
declare const applySchedulerAppointmentChange: <TAppointment, TResourceId extends SchedulerId>(appointments: TAppointment[], change: SchedulerAppointmentChangeArgs<TAppointment, TResourceId>, ...[options]: [Exclude<keyof ChangeFields<TAppointment>, DefaultedChangeField<TAppointment>>] extends [never] ? [options?: ApplySchedulerAppointmentChangeInput<TAppointment, TResourceId>] : [options: ApplySchedulerAppointmentChangeInput<TAppointment, TResourceId>]) => TAppointment[];
|
|
130
222
|
|
|
131
|
-
export { type ApplySchedulerAppointmentChangeOptions, type BaseSchedulerResource, type RenderSchedulerAppt, Scheduler, type SchedulerAppointmentAdapter, type SchedulerAppointmentAppearance, type SchedulerAppointmentChangeArgs, type SchedulerAppointmentColorToken, type SchedulerAppointmentVisualState, type SchedulerDragState, type SchedulerEvent, type SchedulerId, type SchedulerPresentationAppointment, type SchedulerProps, type SchedulerResourceClassMap, type SchedulerToolbarRenderArgs, applySchedulerAppointmentChange };
|
|
223
|
+
export { type ApplySchedulerAppointmentChangeFieldOptions, type ApplySchedulerAppointmentChangeInput, type ApplySchedulerAppointmentChangeOptions, type BaseSchedulerResource, type RenderSchedulerAppt, Scheduler, type SchedulerAdapterProp, type SchedulerAgendaItemRenderArgs, type SchedulerAppointmentAdapter, type SchedulerAppointmentAdapterInput, type SchedulerAppointmentAdapterOption, type SchedulerAppointmentAppearance, type SchedulerAppointmentChangeArgs, type SchedulerAppointmentChangeEvent, type SchedulerAppointmentColorToken, type SchedulerAppointmentField, type SchedulerAppointmentFieldAdapter, type SchedulerAppointmentPartialFieldAdapter, type SchedulerAppointmentVisualState, type SchedulerCommonProps, type SchedulerDefaultedAppointmentField, type SchedulerDragState, type SchedulerEvent, type SchedulerId, type SchedulerPresentationAppointment, type SchedulerProps, type SchedulerResourceClassMap, type SchedulerToolbarRenderArgs, type SchedulerView, applySchedulerAppointmentChange, resolveSchedulerAppointmentAdapter };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,33 @@ type SchedulerAppointmentAdapter<TAppointment, TResourceId extends string | numb
|
|
|
8
8
|
getEnd: (item: TAppointment) => Date | string;
|
|
9
9
|
getTitle: (item: TAppointment) => string;
|
|
10
10
|
};
|
|
11
|
+
type SchedulerAppointmentField<TAppointment, TValue> = Extract<keyof TAppointment, string | number> | ((item: TAppointment) => TValue);
|
|
12
|
+
type SchedulerAppointmentFieldAdapter<TAppointment, TResourceId extends string | number> = {
|
|
13
|
+
id: SchedulerAppointmentField<TAppointment, number | string>;
|
|
14
|
+
resourceId: SchedulerAppointmentField<TAppointment, TResourceId>;
|
|
15
|
+
start: SchedulerAppointmentField<TAppointment, Date | string>;
|
|
16
|
+
end: SchedulerAppointmentField<TAppointment, Date | string>;
|
|
17
|
+
title: SchedulerAppointmentField<TAppointment, string>;
|
|
18
|
+
};
|
|
19
|
+
type SchedulerAppointmentAdapterInput<TAppointment, TResourceId extends string | number> = SchedulerAppointmentAdapter<TAppointment, TResourceId> | SchedulerAppointmentFieldAdapter<TAppointment, TResourceId>;
|
|
11
20
|
type SchedulerId = string | number;
|
|
21
|
+
type SchedulerDefaultFieldValues<TResourceId extends SchedulerId> = {
|
|
22
|
+
id: SchedulerId;
|
|
23
|
+
resourceId: TResourceId;
|
|
24
|
+
start: Date | string;
|
|
25
|
+
end: Date | string;
|
|
26
|
+
title: string;
|
|
27
|
+
};
|
|
28
|
+
/** Adapter fields the appointment already exposes under the default name with a compatible type. */
|
|
29
|
+
type SchedulerDefaultedAppointmentField<TAppointment, TResourceId extends SchedulerId> = {
|
|
30
|
+
[K in keyof SchedulerDefaultFieldValues<TResourceId>]: K extends keyof TAppointment ? TAppointment[K] extends SchedulerDefaultFieldValues<TResourceId>[K] ? K : never : never;
|
|
31
|
+
}[keyof SchedulerDefaultFieldValues<TResourceId>];
|
|
32
|
+
/**
|
|
33
|
+
* Key-based adapter where fields matching the default names
|
|
34
|
+
* (`id`, `resourceId`, `start`, `end`, `title`) can be omitted.
|
|
35
|
+
*/
|
|
36
|
+
type SchedulerAppointmentPartialFieldAdapter<TAppointment, TResourceId extends SchedulerId> = Omit<SchedulerAppointmentFieldAdapter<TAppointment, TResourceId>, SchedulerDefaultedAppointmentField<TAppointment, TResourceId>> & Partial<Pick<SchedulerAppointmentFieldAdapter<TAppointment, TResourceId>, SchedulerDefaultedAppointmentField<TAppointment, TResourceId>>>;
|
|
37
|
+
type SchedulerAppointmentAdapterOption<TAppointment, TResourceId extends SchedulerId> = SchedulerAppointmentAdapter<TAppointment, TResourceId> | SchedulerAppointmentPartialFieldAdapter<TAppointment, TResourceId>;
|
|
12
38
|
type BaseSchedulerResource<TId extends SchedulerId = number> = {
|
|
13
39
|
id: TId;
|
|
14
40
|
label: string;
|
|
@@ -51,6 +77,12 @@ type RenderSchedulerAppt<TAppointment, TResourceId extends SchedulerId> = Schedu
|
|
|
51
77
|
type SchedulerAppointmentChangeArgs<TAppointment, TResourceId extends SchedulerId> = {
|
|
52
78
|
kind: "move" | "resize";
|
|
53
79
|
appointment: TAppointment;
|
|
80
|
+
resourceId?: TResourceId;
|
|
81
|
+
start?: Date;
|
|
82
|
+
end?: Date;
|
|
83
|
+
previousResourceId?: TResourceId;
|
|
84
|
+
previousStart?: Date;
|
|
85
|
+
previousEnd?: Date;
|
|
54
86
|
previous: {
|
|
55
87
|
resourceId: TResourceId;
|
|
56
88
|
start: Date;
|
|
@@ -62,31 +94,61 @@ type SchedulerAppointmentChangeArgs<TAppointment, TResourceId extends SchedulerI
|
|
|
62
94
|
end: Date;
|
|
63
95
|
};
|
|
64
96
|
};
|
|
97
|
+
type SchedulerAppointmentChangeEvent<TAppointment, TResourceId extends SchedulerId> = SchedulerAppointmentChangeArgs<TAppointment, TResourceId> & {
|
|
98
|
+
resourceId: TResourceId;
|
|
99
|
+
start: Date;
|
|
100
|
+
end: Date;
|
|
101
|
+
previousResourceId: TResourceId;
|
|
102
|
+
previousStart: Date;
|
|
103
|
+
previousEnd: Date;
|
|
104
|
+
};
|
|
65
105
|
type SchedulerAppointmentAppearance = {
|
|
66
106
|
className?: string;
|
|
67
107
|
};
|
|
68
108
|
type SchedulerAppointmentColorToken = string;
|
|
69
109
|
type SchedulerResourceClassMap = Partial<Record<string, string>>;
|
|
110
|
+
/** `"day"` is the resource grid; `"agenda"` is a time-ordered list of the selected day. */
|
|
111
|
+
type SchedulerView = "day" | "agenda";
|
|
112
|
+
type SchedulerAgendaItemRenderArgs<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId> = {
|
|
113
|
+
appointment: SchedulerEvent<TAppointment, TResourceId>;
|
|
114
|
+
resource: TResource;
|
|
115
|
+
appointmentAppearance?: SchedulerAppointmentAppearance;
|
|
116
|
+
};
|
|
70
117
|
type SchedulerToolbarRenderArgs = {
|
|
71
118
|
selectedDate: Date;
|
|
72
119
|
onSelectedDateChange: (date: Date) => void;
|
|
73
120
|
goToPreviousDay: () => void;
|
|
74
121
|
goToNextDay: () => void;
|
|
75
122
|
defaultDatePicker: React.ReactNode;
|
|
123
|
+
view: SchedulerView;
|
|
124
|
+
views: SchedulerView[];
|
|
125
|
+
onViewChange: (view: SchedulerView) => void;
|
|
126
|
+
/** Built-in view switcher, or `null` when fewer than two views are enabled. */
|
|
127
|
+
defaultViewSwitcher: React.ReactNode;
|
|
128
|
+
};
|
|
129
|
+
/** `adapter` is optional only when every field can fall back to its default name. */
|
|
130
|
+
type SchedulerAdapterProp<TAppointment, TResourceId extends SchedulerId> = [
|
|
131
|
+
Exclude<keyof SchedulerDefaultFieldValues<TResourceId>, SchedulerDefaultedAppointmentField<TAppointment, TResourceId>>
|
|
132
|
+
] extends [never] ? {
|
|
133
|
+
adapter?: SchedulerAppointmentAdapterOption<TAppointment, TResourceId>;
|
|
134
|
+
} : {
|
|
135
|
+
adapter: SchedulerAppointmentAdapterOption<TAppointment, TResourceId>;
|
|
76
136
|
};
|
|
77
|
-
type SchedulerProps<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId> =
|
|
137
|
+
type SchedulerProps<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId> = SchedulerCommonProps<TAppointment, TResource, TResourceId> & SchedulerAdapterProp<TAppointment, TResourceId>;
|
|
138
|
+
type SchedulerCommonProps<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId> = {
|
|
78
139
|
resources: TResource[];
|
|
79
140
|
appointments: TAppointment[];
|
|
80
141
|
selectedDate: Date;
|
|
81
142
|
onSelectedDateChange: (date: Date) => void;
|
|
82
|
-
|
|
143
|
+
/** Called on a plain click (not after a drag or resize). */
|
|
144
|
+
onAppointmentClick?: (appointment: TAppointment, event: React.MouseEvent<HTMLElement>) => void;
|
|
83
145
|
onPersistMoveResize?: (args: {
|
|
84
146
|
appointment: TAppointment;
|
|
85
147
|
resourceId: TResourceId;
|
|
86
148
|
start: Date;
|
|
87
149
|
end: Date;
|
|
88
150
|
}) => Promise<void> | void;
|
|
89
|
-
onAppointmentChange?: (args:
|
|
151
|
+
onAppointmentChange?: (args: SchedulerAppointmentChangeEvent<TAppointment, TResourceId>) => Promise<void> | void;
|
|
90
152
|
renderResourceHeader?: (resource: TResource) => React.ReactNode;
|
|
91
153
|
renderAppointment?: (args: {
|
|
92
154
|
appointment: SchedulerPresentationAppointment<TAppointment, TResourceId> & {
|
|
@@ -116,9 +178,22 @@ type SchedulerProps<TAppointment, TResource extends BaseSchedulerResource<TResou
|
|
|
116
178
|
dayStart?: string;
|
|
117
179
|
dayEnd?: string;
|
|
118
180
|
editable?: boolean;
|
|
181
|
+
/** Views offered by the built-in switcher. Defaults to `["day"]` (no switcher). */
|
|
182
|
+
views?: SchedulerView[];
|
|
183
|
+
/** Controlled view. */
|
|
184
|
+
view?: SchedulerView;
|
|
185
|
+
/** Initial view when `view` is not controlled. Defaults to the first entry of `views`. */
|
|
186
|
+
defaultView?: SchedulerView;
|
|
187
|
+
onViewChange?: (view: SchedulerView) => void;
|
|
188
|
+
viewLabels?: Partial<Record<SchedulerView, React.ReactNode>>;
|
|
189
|
+
renderAgendaItem?: (args: SchedulerAgendaItemRenderArgs<TAppointment, TResource, TResourceId>) => React.ReactNode;
|
|
190
|
+
/** Shown in the agenda view when the selected day has no appointments. */
|
|
191
|
+
agendaEmptyState?: React.ReactNode;
|
|
119
192
|
};
|
|
120
193
|
|
|
121
|
-
declare function Scheduler<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId>({ resources, appointments, selectedDate, onSelectedDateChange, adapter, onPersistMoveResize, onAppointmentChange, renderResourceHeader, renderAppointment, resourceAppointmentClassMap, getResourceAppointmentAppearance, getResourceAppointmentColorToken, appointmentColorTokenClassMap, getResourceAppointmentBackground, renderToolbar, renderDatePicker, prevButtonLabel, nextButtonLabel, dayStart, dayEnd, editable }: SchedulerProps<TAppointment, TResource, TResourceId>): react_jsx_runtime.JSX.Element;
|
|
194
|
+
declare function Scheduler<TAppointment, TResource extends BaseSchedulerResource<TResourceId>, TResourceId extends SchedulerId>({ resources, appointments, selectedDate, onSelectedDateChange, adapter, onPersistMoveResize, onAppointmentChange, onAppointmentClick, renderResourceHeader, renderAppointment, resourceAppointmentClassMap, getResourceAppointmentAppearance, getResourceAppointmentColorToken, appointmentColorTokenClassMap, getResourceAppointmentBackground, renderToolbar, renderDatePicker, prevButtonLabel, nextButtonLabel, dayStart, dayEnd, editable, views, view: controlledView, defaultView, onViewChange, viewLabels, renderAgendaItem, agendaEmptyState, }: SchedulerProps<TAppointment, TResource, TResourceId>): react_jsx_runtime.JSX.Element;
|
|
195
|
+
|
|
196
|
+
declare const resolveSchedulerAppointmentAdapter: <TAppointment, TResourceId extends string | number>(adapter?: SchedulerAppointmentAdapterInput<TAppointment, TResourceId> | SchedulerAppointmentAdapterOption<TAppointment, TResourceId>) => SchedulerAppointmentAdapter<TAppointment, TResourceId>;
|
|
122
197
|
|
|
123
198
|
type ApplySchedulerAppointmentChangeOptions<TAppointment, TResourceId extends SchedulerId> = {
|
|
124
199
|
getId: (appointment: TAppointment) => SchedulerId;
|
|
@@ -126,6 +201,23 @@ type ApplySchedulerAppointmentChangeOptions<TAppointment, TResourceId extends Sc
|
|
|
126
201
|
setStart: (appointment: TAppointment, start: Date) => TAppointment;
|
|
127
202
|
setEnd: (appointment: TAppointment, end: Date) => TAppointment;
|
|
128
203
|
};
|
|
129
|
-
|
|
204
|
+
type AppointmentKey<TAppointment> = Extract<keyof TAppointment, string | number>;
|
|
205
|
+
type ChangeFields<TAppointment> = {
|
|
206
|
+
id: SchedulerAppointmentField<TAppointment, SchedulerId>;
|
|
207
|
+
resourceId: AppointmentKey<TAppointment>;
|
|
208
|
+
start: AppointmentKey<TAppointment>;
|
|
209
|
+
end: AppointmentKey<TAppointment>;
|
|
210
|
+
};
|
|
211
|
+
/** Default field names the appointment actually has; those can be omitted from the options. */
|
|
212
|
+
type DefaultedChangeField<TAppointment> = Extract<keyof ChangeFields<TAppointment>, keyof TAppointment>;
|
|
213
|
+
/**
|
|
214
|
+
* Key-based options. `id`, `resourceId`, `start` and `end` default to the fields with the same name,
|
|
215
|
+
* so they are optional when the appointment has them.
|
|
216
|
+
*/
|
|
217
|
+
type ApplySchedulerAppointmentChangeFieldOptions<TAppointment> = Omit<ChangeFields<TAppointment>, DefaultedChangeField<TAppointment>> & Partial<Pick<ChangeFields<TAppointment>, DefaultedChangeField<TAppointment>>> & {
|
|
218
|
+
dateValue?: (date: Date) => unknown;
|
|
219
|
+
};
|
|
220
|
+
type ApplySchedulerAppointmentChangeInput<TAppointment, TResourceId extends SchedulerId> = ApplySchedulerAppointmentChangeOptions<TAppointment, TResourceId> | ApplySchedulerAppointmentChangeFieldOptions<TAppointment>;
|
|
221
|
+
declare const applySchedulerAppointmentChange: <TAppointment, TResourceId extends SchedulerId>(appointments: TAppointment[], change: SchedulerAppointmentChangeArgs<TAppointment, TResourceId>, ...[options]: [Exclude<keyof ChangeFields<TAppointment>, DefaultedChangeField<TAppointment>>] extends [never] ? [options?: ApplySchedulerAppointmentChangeInput<TAppointment, TResourceId>] : [options: ApplySchedulerAppointmentChangeInput<TAppointment, TResourceId>]) => TAppointment[];
|
|
130
222
|
|
|
131
|
-
export { type ApplySchedulerAppointmentChangeOptions, type BaseSchedulerResource, type RenderSchedulerAppt, Scheduler, type SchedulerAppointmentAdapter, type SchedulerAppointmentAppearance, type SchedulerAppointmentChangeArgs, type SchedulerAppointmentColorToken, type SchedulerAppointmentVisualState, type SchedulerDragState, type SchedulerEvent, type SchedulerId, type SchedulerPresentationAppointment, type SchedulerProps, type SchedulerResourceClassMap, type SchedulerToolbarRenderArgs, applySchedulerAppointmentChange };
|
|
223
|
+
export { type ApplySchedulerAppointmentChangeFieldOptions, type ApplySchedulerAppointmentChangeInput, type ApplySchedulerAppointmentChangeOptions, type BaseSchedulerResource, type RenderSchedulerAppt, Scheduler, type SchedulerAdapterProp, type SchedulerAgendaItemRenderArgs, type SchedulerAppointmentAdapter, type SchedulerAppointmentAdapterInput, type SchedulerAppointmentAdapterOption, type SchedulerAppointmentAppearance, type SchedulerAppointmentChangeArgs, type SchedulerAppointmentChangeEvent, type SchedulerAppointmentColorToken, type SchedulerAppointmentField, type SchedulerAppointmentFieldAdapter, type SchedulerAppointmentPartialFieldAdapter, type SchedulerAppointmentVisualState, type SchedulerCommonProps, type SchedulerDefaultedAppointmentField, type SchedulerDragState, type SchedulerEvent, type SchedulerId, type SchedulerPresentationAppointment, type SchedulerProps, type SchedulerResourceClassMap, type SchedulerToolbarRenderArgs, type SchedulerView, applySchedulerAppointmentChange, resolveSchedulerAppointmentAdapter };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {format,startOfMonth,startOfWeek,endOfWeek,endOfMonth,addDays,addMonths,isSameDay,isToday,isSameMonth}from'date-fns';import*as h from'react';var it=e=>{let{isDropInvalid:t,description:r,title:o}=e;return jsxs(Fragment,{children:[t&&jsx("div",{className:"rfs:absolute rfs:right-1 rfs:top-1 rfs:flex rfs:h-4 rfs:w-4 rfs:items-center rfs:justify-center rfs:rounded-full rfs:bg-red-600 rfs:text-[10px] rfs:font-bold rfs:text-white",children:"X"}),jsx("div",{className:"rfs:text-xs rfs:font-semibold",children:o}),r&&jsx("div",{className:"rfs:mt-1 rfs:text-[10px] rfs:font-medium",children:r})]})},me=it;function oe({appointment:e,onResizePointerDown:t}){return jsx("div",{role:"button","aria-label":"Resize appointment",onPointerDown:r=>{e.visualState!=="ghost"&&(r.stopPropagation(),t(r));},className:"rfs:absolute rfs:inset-x-1 rfs:bottom-1 rfs:h-2 rfs:cursor-ns-resize rfs:rounded-full rfs:bg-border/90 rfs:transition-colors rfs:hover:bg-border"})}function G({appointment:e,isDropInvalid:t,onPointerDown:r,onResizePointerDown:o,appointmentAppearance:n,appointmentBackgroundColor:i}){let c=e.raw,a=typeof c.description=="string"?c.description:void 0,s=typeof i=="string"?i:void 0,d=n?.className??s??"rfs:bg-muted/40 rfs:dark:bg-muted/30",f=t?"rfs:bg-red-100/80 rfs:text-red-950 rfs:dark:bg-red-950/40 rfs:dark:text-red-100":"",l=e.visualState==="ghost"?"rfs:cursor-grab rfs:opacity-35":e.visualState==="dragging"?"rfs:cursor-grabbing rfs:opacity-55 rfs:shadow-xl":"rfs:cursor-grab",g=`rfs:relative rfs:h-full rfs:overflow-hidden rfs:rounded-md rfs:p-2 rfs:pb-5 rfs:text-foreground ${d} ${f} ${l}`;return jsxs("div",{onPointerDown:r,className:g,children:[jsx(me,{isDropInvalid:t,title:e.title,description:a}),jsx(oe,{onResizePointerDown:o,appointment:e})]})}function he(e){if(!e||typeof e!="object")return false;let t=e;return typeof t.firstName=="string"||typeof t.lastName=="string"}var Te={slate:"bg-slate-100 dark:bg-slate-900/40",gray:"bg-gray-100 dark:bg-gray-900/40",zinc:"bg-zinc-100 dark:bg-zinc-900/40",neutral:"bg-neutral-100 dark:bg-neutral-900/40",stone:"bg-stone-100 dark:bg-stone-900/40",red:"bg-red-100 dark:bg-red-950/40",orange:"bg-orange-100 dark:bg-orange-950/40",amber:"bg-amber-100 dark:bg-amber-950/40",yellow:"bg-yellow-100 dark:bg-yellow-950/40",lime:"bg-lime-100 dark:bg-lime-950/40",green:"bg-green-100 dark:bg-green-950/40",emerald:"bg-emerald-100 dark:bg-emerald-950/40",teal:"bg-teal-100 dark:bg-teal-950/40",cyan:"bg-cyan-100 dark:bg-cyan-950/40",sky:"bg-sky-100 dark:bg-sky-950/40",blue:"bg-blue-100 dark:bg-blue-950/40",indigo:"bg-indigo-100 dark:bg-indigo-950/40",violet:"bg-violet-100 dark:bg-violet-950/40",purple:"bg-purple-100 dark:bg-purple-950/40",fuchsia:"bg-fuchsia-100 dark:bg-fuchsia-950/40",pink:"bg-pink-100 dark:bg-pink-950/40",rose:"bg-rose-100 dark:bg-rose-950/40"};function D(e,t,r){return Math.max(t,Math.min(r,e))}function U(e,t=15){return Math.round(e/t)*t}function se(e){let[t,r]=e.split(":").map(Number);return t*60+r}function Ie(e){return `${e.firstName??""} ${e.lastName??""}`.trim()}function K(e){return format(e,"yyyy-MM-dd")}function ie(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+t)}function z(e,t,r){let o=new Date(e.getFullYear(),e.getMonth(),e.getDate(),0,0,0,0),n=t+r,i=Math.floor(n/60),c=n%60;return o.setHours(i,c,0,0),o}function ae(e,t){return t.getHours()*60+t.getMinutes()-e}function ce(e,t){return e.startMin<t.endMin&&t.startMin<e.endMin}function Se(e){let t=[...e].sort((c,a)=>c.startMin-a.startMin||c.endMin-a.endMin),r=[],o=[],n=[];for(let c of t)o=o.filter(s=>s.endMin>c.startMin),!o.some(s=>ce(s,c))&&n.length>0&&(r.push(n),n=[]),n.push(c),o.push(c);n.length&&r.push(n);let i=[];for(let c of r){let a=[...c].sort((l,g)=>l.startMin-g.startMin||l.endMin-g.endMin),s=[],d=new Map;for(let l of a){let g=false;for(let p=0;p<s.length;p++)if(s[p]<=l.startMin){s[p]=l.endMin,d.set(l.id,p),g=true;break}g||(s.push(l.endMin),d.set(l.id,s.length-1));}let f=s.length;for(let l of a)i.push({...l,lane:d.get(l.id)??0,lanes:f});}return i}function ue({fallback:e,getValue:t,resources:r,toKey:o}){let n=new Map;for(let i of r)n.set(o(i),t(i)??e);return n}function be({adapter:e,appointments:t,dayMinutes:r,dayStartAbs:o,selectedISO:n}){return t.map(i=>{let c=new Date(e.getStart(i)),a=new Date(e.getEnd(i));return {raw:i,id:e.getId(i),resourceId:e.getResourceId(i),start:c,end:a,startMin:D(ae(o,c),0,r),endMin:D(ae(o,a),0,r),title:e.getTitle(i),renderKey:String(e.getId(i)),visualState:"normal"}}).filter(i=>K(i.start)===n)}function ye(e){return new Map(e.map(t=>[t.id,t]))}function Me(e,t,r,o){return t.kind==="none"||t.kind==="move"?e:e.map(n=>n.id!==t.appointmentId?n:{...n,resourceId:t.resourceId,startMin:t.startMin,endMin:t.endMin,start:z(r,o,t.startMin),end:z(r,o,t.endMin),visualState:"dragging"})}function Ae(e,t){let r=new Map;for(let n of t){let i=r.get(n.resourceId)??[];i.push(n),r.set(n.resourceId,i);}let o=new Map;for(let n of e)o.set(n.id,de(r.get(n.id)??[]));return o}function de(e){return Se(e.map(t=>({...t,appointmentId:t.id,id:t.renderKey}))).map(({appointmentId:t,...r})=>({...r,id:t}))}function Pe(e,t,r,o,n){let i=new Map;for(let c of e){let a=t?.[String(c.id)];if(a){i.set(c.id,{className:a});continue}let s=r?.(c);if(s){i.set(c.id,s);continue}let d=o.get(c.id);if(d){i.set(c.id,{className:d});continue}let f=n.get(c.id);i.set(c.id,f?{className:f}:void 0);}return i}function De({adapter:e,appointments:t,dayEnd:r="18:00",dayStart:o="09:00",resources:n,selectedDate:i}){let c=h.useMemo(()=>se(o),[o]),a=h.useMemo(()=>se(r),[r]),s=h.useMemo(()=>Math.max(0,a-c),[a,c]),d=h.useMemo(()=>12+s*2+24,[s]),f=h.useMemo(()=>72+Math.max(n.length,1)*420,[n.length]),l=h.useMemo(()=>K(i),[i]),g=h.useMemo(()=>be({adapter:e,appointments:t,dayMinutes:s,dayStartAbs:c,selectedISO:l}),[e,t,s,c,l]);return {appointmentMap:h.useMemo(()=>ye(g),[g]),dayEndAbs:a,dayMinutes:s,dayStartAbs:c,gridHeight:d,gridMinWidth:f,renderAppts:g}}var pt=4,ft=(e,t)=>{e(r=>r&&{...r,clientX:t.clientX,clientY:t.clientY});},mt=e=>{let{dragRef:t,pendingDragRef:r,pointer:o,setDrag:n,setMovePreview:i,suppressClickRef:c}=e,a=r.current;if(!a||a.drag.pointerId!==o.pointerId)return;let s=o.clientX-a.startClientX,d=o.clientY-a.startClientY;Math.hypot(s,d)<pt||(c.current=true,t.current=a.drag,n(a.drag),a.drag.kind==="move"&&i({appointment:a.appointment,clientX:o.clientX,clientY:o.clientY,width:a.width,height:a.height,offsetX:a.offsetX,offsetY:a.offsetY}),r.current=null);},Rt=(e,t,r,o,n)=>{let i=o(t.clientX,e.resourceId),a=n(i,t.clientY)-e.offsetMin,s=D(U(a),0,r-e.durationMin),d=s+e.durationMin;return s===e.startMin&&d===e.endMin&&i===e.resourceId?null:{...e,resourceId:i,startMin:s,endMin:d}},gt=(e,t,r,o)=>{let n=o(e.resourceId,t.clientY),i=D(U(n),e.startMin+15,r);return i===e.endMin?null:{...e,endMin:i}},we=e=>{let{dayMinutes:t,dragRef:r,latestPointerRef:o,pendingDragRef:n,pointerToMin:i,pointerToResourceId:c,setDrag:a,setMovePreview:s,suppressClickRef:d}=e,f=o.current;if(!f)return;let l=r.current;if(l.kind==="none"&&n.current){mt({pointer:f,pendingDragRef:n,setDrag:a,setMovePreview:s,dragRef:r,suppressClickRef:d});return}if(l.kind==="none")return;if(l.kind==="move"){ft(s,f);let p=Rt(l,f,t,c,i);p&&(d.current=true,r.current=p,a(p));return}let g=gt(l,f,t,i);g&&(d.current=true,r.current=g,a(g));},Ne=e=>{let{dragRef:t,frameRef:r,latestPointerRef:o,pendingDragRef:n,persistDrag:i,setDrag:c,setMovePreview:a,suppressClickRef:s}=e;r.current!==null&&(window.cancelAnimationFrame(r.current),r.current=null),o.current=null,n.current=null,a(null);let d=t.current;d.kind!=="none"&&(c({kind:"none"}),t.current={kind:"none"},s.current&&i(d));};var Ce=({appointmentMap:e,dayMinutes:t,dayStartAbs:r,onAppointmentChange:o,onPersistMoveResize:n,renderAppts:i,resources:c,selectedDate:a,editable:s})=>{let[d,f]=h.useState({kind:"none"}),[l,g]=h.useState(null),p=h.useRef({}),T=h.useRef(false),v=h.useRef({kind:"none"}),S=h.useRef(null),b=h.useRef(null),y=h.useRef(null);h.useEffect(()=>{v.current=d;},[d]),h.useEffect(()=>()=>{y.current!==null&&window.cancelAnimationFrame(y.current);},[]);let E=h.useCallback((u,m)=>{let R=p.current[String(u)];if(!R)return 0;let M=m-R.getBoundingClientRect().top-12;return D(U(M/2),0,t)},[t]),$=h.useCallback((u,m)=>{for(let R of c){let M=p.current[String(R.id)];if(!M)continue;let X=M.getBoundingClientRect();if(u>=X.left&&u<=X.right)return R.id}return m},[c]),O=h.useCallback((u,m,R,M)=>i.filter(k=>k.resourceId===m&&k.id!==u).some(k=>ce(k,{startMin:R,endMin:M})),[i]),Y=h.useMemo(()=>d.kind==="none"?false:O(d.appointmentId,d.resourceId,d.startMin,d.endMin),[d,O]),L=h.useCallback(async u=>{let m=e.get(u.appointmentId);if(!m||O(u.appointmentId,u.resourceId,u.startMin,u.endMin))return;let R={resourceId:u.resourceId,start:z(a,r,u.startMin),end:z(a,r,u.endMin)};if(o){await o({kind:u.kind,appointment:m.raw,previous:{resourceId:m.resourceId,start:m.start,end:m.end},next:R});return}n&&await n({appointment:m.raw,resourceId:R.resourceId,start:R.start,end:R.end});},[e,r,O,o,n,a]),F=h.useCallback((u,m)=>{if(!s||u.button!==0)return;u.stopPropagation(),T.current=false;let R=u.currentTarget.getBoundingClientRect(),M=E(m.resourceId,u.clientY);S.current={drag:{kind:"move",appointmentId:m.id,pointerId:u.pointerId,resourceId:m.resourceId,durationMin:Math.max(15,m.endMin-m.startMin),offsetMin:M-m.startMin,startMin:m.startMin,endMin:m.endMin},appointment:m,startClientX:u.clientX,startClientY:u.clientY,width:R.width,height:R.height,offsetX:u.clientX-R.left,offsetY:u.clientY-R.top};},[E,s]),j=h.useCallback((u,m)=>{s&&u.button===0&&(u.stopPropagation(),T.current=false,S.current={drag:{kind:"resize",appointmentId:m.id,pointerId:u.pointerId,resourceId:m.resourceId,startMin:m.startMin,endMin:m.endMin},appointment:m,startClientX:u.clientX,startClientY:u.clientY,width:0,height:0,offsetX:0,offsetY:0});},[s]),W=h.useCallback(u=>{b.current={clientX:u.clientX,clientY:u.clientY,pointerId:u.pointerId},y.current===null&&(y.current=window.requestAnimationFrame(()=>{y.current=null,we({dayMinutes:t,dragRef:v,latestPointerRef:b,pendingDragRef:S,pointerToMin:E,pointerToResourceId:$,setDrag:f,setMovePreview:g,suppressClickRef:T});}));},[t,E,$]),ee=h.useCallback(()=>{Ne({dragRef:v,frameRef:y,latestPointerRef:b,pendingDragRef:S,persistDrag:L,setDrag:f,setMovePreview:g,suppressClickRef:T});},[L]);return {colRefs:p,drag:d,isDropInvalid:Y,movePreview:l,onApptPointerDown:F,onGlobalPointerMove:W,onGlobalPointerUp:ee,onResizePointerDown:j,suppressClickRef:T}};function Be({appointmentColorTokenClassMap:e,dayStartAbs:t,drag:r,getResourceAppointmentAppearance:o,getResourceAppointmentBackground:n,getResourceAppointmentColorToken:i,renderAppts:c,resourceAppointmentClassMap:a,resources:s,selectedDate:d}){let f=h.useMemo(()=>Me(c,r,d,t),[t,r,c,d]),l=h.useMemo(()=>Ae(s,c),[c,s]),g=h.useMemo(()=>{if(r.kind!=="resize")return l;let S=new Map(l),b=f.filter(y=>y.resourceId===r.resourceId);return S.set(r.resourceId,de(b)),S},[l,r,f]),p=h.useMemo(()=>n?ue({fallback:void 0,getValue:n,resources:s,toKey:S=>S.id}):new Map,[n,s]),T=h.useMemo(()=>{if(!i)return new Map;let S={...Te,...e??{}};return ue({fallback:void 0,getValue:b=>{let y=i(b);return y?S[y]:void 0},resources:s,toKey:b=>b.id})},[e,i,s]);return {appointmentAppearanceByResource:h.useMemo(()=>Pe(s,a,o,T,p),[p,T,o,a,s]),appointmentBgByResource:p,effectiveAppts:f,laidOutByResource:g}}function Ee({dayMinutes:e,dayStartAbs:t,gridHeight:r}){return jsx("div",{className:"rfs-times rfs:border-border rfs:bg-card",style:{width:72,height:r},children:Array.from({length:Math.floor(e/60)+1}).map((o,n)=>jsxs("div",{className:"rfs-time-tick rfs:text-muted-foreground",style:{top:12+n*60*2},children:[String(Math.floor((t+n*60)/60)).padStart(2,"0"),":",String((t+n*60)%60).padStart(2,"0")]},`tick-${n}`))})}function Oe({resource:e}){return jsx("strong",{children:e.label})}function ze({resources:e,renderResourceHeader:t}){return jsxs("div",{className:"rfs-header rfs:border-border rfs:bg-card",children:[jsx("div",{className:"rfs-gutter rfs:border-border",style:{width:72}}),e.map(r=>jsxs("div",{className:"rfs-resource-header rfs:border-border rfs:bg-card rfs:text-foreground",style:{minWidth:420,flex:1},children:[(t??(o=>Oe({resource:o})))(r),he(r)?jsx("div",{className:"rfs-resource-subtitle rfs:text-muted-foreground",children:Ie(r)}):null]},String(r.id)))]})}var He=({resource:e,colRefs:t,gridHeight:r,dayMinutes:o,appointments:n,appointmentAppearance:i,appointmentBg:c,isDropInvalid:a,renderAppointment:s,onApptPointerDown:d,onResizePointerDown:f,drag:l,suppressClickRef:g})=>jsx("div",{className:"rfs-col rfs:border-border rfs:bg-card",style:{minWidth:420,flex:1},children:jsxs("div",{ref:p=>{t.current[String(e.id)]=p;},className:"rfs-col-inner rfs:bg-card",style:{height:r},children:[Array.from({length:Math.floor(o/60)+1}).map((p,T)=>jsx("div",{className:"rfs-hour-line rfs:border-border/70",style:{top:12+T*60*2}},`major-${T}`)),Array.from({length:Math.floor(o/15)+1}).map((p,T)=>jsx("div",{className:"rfs-slot-line rfs:border-border/50",style:{top:12+T*15*2}},`minor-${T}`)),n.map(p=>{let T=100/p.lanes,v=12+p.startMin*2,S=Math.max(30,(p.endMin-p.startMin)*2);return jsx("div",{className:`rfs-card-slot ${p.visualState==="ghost"?"rfs-card-slot--ghost":""} ${p.visualState==="dragging"?"rfs-card-slot--dragging":""}`,style:{top:v,left:`${T*p.lane}%`,width:`${T}%`,height:S},children:(s??G)({appointment:p,isDropInvalid:a&&l.kind==="resize"&&p.id===l.appointmentId,onPointerDown:b=>d(b,p),onResizePointerDown:b=>f(b,p),appointmentAppearance:i,appointmentBackgroundColor:c,drag:l,suppressClickRef:g})},p.renderKey)})]})});var bt=(e,t)=>[e.resource===t.resource,e.colRefs===t.colRefs,e.gridHeight===t.gridHeight,e.dayMinutes===t.dayMinutes,e.appointments===t.appointments,e.appointmentAppearance===t.appointmentAppearance,e.appointmentBg===t.appointmentBg,e.isDropInvalid===t.isDropInvalid,e.renderAppointment===t.renderAppointment,e.onApptPointerDown===t.onApptPointerDown,e.onResizePointerDown===t.onResizePointerDown,e.drag===t.drag,e.suppressClickRef===t.suppressClickRef].every(Boolean),Xe=h.memo(He,bt);function H(...e){return e.filter(Boolean).join(" ")}var yt={default:"rfs:bg-primary rfs:text-primary-foreground rfs:hover:bg-primary/90",outline:"rfs:border rfs:border-border rfs:bg-card rfs:text-foreground rfs:hover:bg-muted",ghost:"rfs:text-foreground rfs:hover:bg-muted"},Mt={default:"rfs:h-9 rfs:px-4 rfs:py-2",sm:"rfs:h-8 rfs:px-3 rfs:text-xs",icon:"rfs:h-8 rfs:w-8"},P=h.forwardRef(function({className:t,variant:r="default",size:o="default",type:n="button",...i},c){return jsx("button",{ref:c,type:n,className:H("rfs:inline-flex rfs:items-center rfs:justify-center rfs:gap-2 rfs:rounded-md rfs:text-sm rfs:font-medium rfs:whitespace-nowrap rfs:transition-colors rfs:focus-visible:outline-none rfs:focus-visible:ring-2 rfs:focus-visible:ring-ring rfs:focus-visible:ring-offset-2 rfs:disabled:pointer-events-none rfs:disabled:opacity-50",yt[r],Mt[o],t),...i})});function We({selected:e,onSelect:t}){let[r,o]=h.useState(e??new Date);h.useEffect(()=>{e&&o(e);},[e]);let n=startOfMonth(r),i=startOfWeek(n,{weekStartsOn:1}),c=endOfWeek(endOfMonth(r),{weekStartsOn:1}),a=[];for(let s=i;s<=c;s=addDays(s,1))a.push(s);return jsxs("div",{className:"rfs:w-72 rfs:rounded-md rfs:bg-popover",children:[jsxs("div",{className:"rfs:mb-2 rfs:flex rfs:items-center rfs:justify-between",children:[jsx(P,{variant:"ghost",size:"icon","aria-label":"Previous month",onClick:()=>o(addMonths(r,-1)),children:"<"}),jsx("div",{className:"rfs:text-sm rfs:font-medium",children:format(r,"MMMM yyyy")}),jsx(P,{variant:"ghost",size:"icon","aria-label":"Next month",onClick:()=>o(addMonths(r,1)),children:">"})]}),jsx("div",{className:"rfs:grid rfs:grid-cols-7 rfs:gap-1 rfs:text-center rfs:text-xs rfs:text-muted-foreground",children:["Mo","Tu","We","Th","Fr","Sa","Su"].map(s=>jsx("div",{className:"rfs:py-1",children:s},s))}),jsx("div",{className:"rfs:grid rfs:grid-cols-7 rfs:gap-1",children:a.map(s=>{let d=e?isSameDay(s,e):false;return jsx(P,{variant:d?"default":"ghost",size:"icon",className:H("rfs:text-xs",!isSameMonth(s,r)&&"rfs:text-muted-foreground rfs:opacity-60",isToday(s)&&!d&&"rfs:border rfs:border-border"),onClick:()=>t?.(s),children:format(s,"d")},s.toISOString())})})]})}var Ge=h.createContext(null);function Ke(){let e=h.useContext(Ge);if(!e)throw new Error("Popover components must be used within Popover.");return e}function qe({children:e,open:t,onOpenChange:r}){let[o,n]=h.useState(false),i=h.useRef(null),c=h.useRef(null),a=t??o,s=h.useCallback(d=>{let f=typeof d=="function"?d(a):d;t===void 0&&n(f),r?.(f);},[t,r,a]);return h.useEffect(()=>{if(!a)return;let d=l=>{let g=l.target;i.current?.contains(g)||c.current?.contains(g)||s(false);},f=l=>{l.key==="Escape"&&s(false);};return document.addEventListener("mousedown",d),document.addEventListener("keydown",f),()=>{document.removeEventListener("mousedown",d),document.removeEventListener("keydown",f);}},[a,s]),jsx(Ge.Provider,{value:{open:a,setOpen:s,triggerRef:i,contentRef:c},children:jsx("div",{className:"rfs:relative rfs:inline-flex",children:e})})}function Je({children:e,asChild:t=false}){let{open:r,setOpen:o,triggerRef:n}=Ke();if(t&&h.isValidElement(e)){let i=e;return h.cloneElement(i,{ref:n,"aria-expanded":r,onClick:c=>{i.props.onClick?.(c),o(a=>!a);}})}return jsx("button",{ref:n,type:"button","aria-expanded":r,onClick:()=>o(i=>!i),children:e})}function Qe({children:e,className:t,align:r="start"}){let{open:o,contentRef:n}=Ke();return o?jsx("div",{ref:n,className:H("rfs:absolute rfs:top-full rfs:z-50 rfs:mt-2 rfs:min-w-72 rfs:rounded-md rfs:border rfs:border-border rfs:bg-popover rfs:p-2 rfs:text-popover-foreground rfs:shadow-md rfs:outline-none",r==="start"&&"rfs:left-0",r==="center"&&"rfs:left-1/2 rfs:-translate-x-1/2",r==="end"&&"rfs:right-0",t),children:e}):null}function Ze({selectedDate:e,onSelectedDateChange:t}){return jsxs(qe,{children:[jsx(Je,{asChild:true,children:jsx(P,{variant:"outline",size:"sm",className:"rfs:min-w-40 rfs:justify-start rfs:text-left rfs:font-normal",children:format(e,"PPP")})}),jsx(Qe,{className:"rfs:w-auto rfs:p-2",align:"center",children:jsx(We,{selected:e,onSelect:t})})]})}function je({goToPreviousDay:e,goToNextDay:t,defaultDatePicker:r,prevButtonLabel:o="Prev",nextButtonLabel:n="Next"}){return jsx("div",{className:"rfs-toolbar",children:jsxs("div",{className:"rfs:flex rfs:items-center rfs:gap-2 rfs:rounded-lg rfs:border rfs:border-border rfs:bg-card rfs:p-1 rfs:shadow-xs",children:[jsx(P,{variant:"outline",size:"sm",onClick:e,children:o}),r,jsx(P,{variant:"outline",size:"sm",onClick:t,children:n})]})})}function rt({selectedDate:e,onSelectedDateChange:t,prevButtonLabel:r,nextButtonLabel:o,renderToolbar:n,renderDatePicker:i}){let c=()=>t(ie(e,-1)),a=()=>t(ie(e,1)),s=(i??Ze)({selectedDate:e,onSelectedDateChange:t});return n?jsx(Fragment,{children:n({selectedDate:e,onSelectedDateChange:t,goToPreviousDay:c,goToNextDay:a,defaultDatePicker:s})}):jsx(Fragment,{children:je({goToPreviousDay:c,goToNextDay:a,defaultDatePicker:s,prevButtonLabel:r,nextButtonLabel:o})})}var Lt={kind:"none"};function _t({resources:e,appointments:t,selectedDate:r,onSelectedDateChange:o,adapter:n,onPersistMoveResize:i,onAppointmentChange:c,renderResourceHeader:a,renderAppointment:s,resourceAppointmentClassMap:d,getResourceAppointmentAppearance:f,getResourceAppointmentColorToken:l,appointmentColorTokenClassMap:g,getResourceAppointmentBackground:p,renderToolbar:T,renderDatePicker:v,prevButtonLabel:S="Prev",nextButtonLabel:b="Next",dayStart:y="09:00",dayEnd:E="18:00",editable:$=true}){let{appointmentMap:O,dayMinutes:Y,dayStartAbs:L,gridHeight:F,gridMinWidth:j,renderAppts:W}=De({adapter:n,appointments:t,dayEnd:E,dayStart:y,resources:e,selectedDate:r}),{colRefs:ee,drag:u,isDropInvalid:m,movePreview:R,onApptPointerDown:M,onGlobalPointerMove:X,onGlobalPointerUp:k,onResizePointerDown:ot,suppressClickRef:fe}=Ce({appointmentMap:O,dayMinutes:Y,dayStartAbs:L,onAppointmentChange:c,onPersistMoveResize:i,renderAppts:W,resources:e,selectedDate:r,editable:$}),{appointmentAppearanceByResource:te,appointmentBgByResource:re,laidOutByResource:st}=Be({appointmentColorTokenClassMap:g,dayStartAbs:L,drag:u,getResourceAppointmentAppearance:f,getResourceAppointmentBackground:p,getResourceAppointmentColorToken:l,renderAppts:W,resourceAppointmentClassMap:d,resources:e,selectedDate:r}),x=h.useMemo(()=>u.kind!=="move"||!R?null:{appointment:{...R.appointment,resourceId:u.resourceId,startMin:u.startMin,endMin:u.endMin,visualState:"ghost",renderKey:`${R.appointment.renderKey}-overlay`,lane:0,lanes:1},appearance:te.get(u.resourceId),background:re.get(u.resourceId),left:R.clientX-R.offsetX,top:R.clientY-R.offsetY,width:R.width,height:R.height},[te,re,u,R]);return jsxs("section",{className:`rfs-root rfs:rounded-lg rfs:text-foreground ${u.kind==="move"?"rfs-root--drag-move":""} ${u.kind==="resize"?"rfs-root--drag-resize":""}`,onPointerMove:X,onPointerUp:k,onPointerCancel:k,children:[jsx(rt,{selectedDate:r,onSelectedDateChange:o,prevButtonLabel:S,nextButtonLabel:b,renderToolbar:T,renderDatePicker:v}),jsx("div",{className:"rfs-shell rfs:border-border rfs:bg-card",children:jsxs("div",{style:{minWidth:j},children:[jsx(ze,{resources:e,renderResourceHeader:a}),jsxs("div",{className:"rfs-body",children:[jsx(Ee,{dayMinutes:Y,dayStartAbs:L,gridHeight:F}),jsx("div",{className:"rfs-grid",children:e.map(_=>jsx(Xe,{resource:_,colRefs:ee,gridHeight:F,dayMinutes:Y,appointments:st.get(_.id)??[],appointmentAppearance:te.get(_.id),appointmentBg:re.get(_.id),isDropInvalid:m,renderAppointment:s,onApptPointerDown:M,onResizePointerDown:ot,drag:u.kind==="resize"&&u.resourceId===_.id?u:Lt,suppressClickRef:fe},String(_.id)))})]})]})}),x?jsx("div",{className:"rfs-drag-overlay",style:{left:x.left,top:x.top,width:x.width,height:x.height},children:(s??G)({appointment:x.appointment,isDropInvalid:m,onPointerDown:()=>{},onResizePointerDown:()=>{},appointmentAppearance:x.appearance,appointmentBackgroundColor:x.background,drag:u,suppressClickRef:fe})}):null]})}function zt(e,t,r){return e.map(o=>{if(r.getId(o)!==r.getId(t.appointment))return o;let n=r.setResourceId(o,t.next.resourceId),i=r.setStart(n,t.next.start);return r.setEnd(i,t.next.end)})}export{_t as Scheduler,zt as applySchedulerAppointmentChange};
|
|
1
|
+
import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {format,startOfMonth,startOfWeek,endOfWeek,endOfMonth,addDays,addMonths,isSameDay,isToday,isSameMonth}from'date-fns';import*as I from'react';var Et=e=>{let{isDropInvalid:t,description:r,title:o}=e;return jsxs(Fragment,{children:[t&&jsx("div",{className:"rfs:absolute rfs:right-1 rfs:top-1 rfs:flex rfs:h-4 rfs:w-4 rfs:items-center rfs:justify-center rfs:rounded-full rfs:bg-red-600 rfs:text-[10px] rfs:font-bold rfs:text-white",children:"X"}),jsx("div",{className:"rfs:text-xs rfs:font-semibold",children:o}),r&&jsx("div",{className:"rfs:mt-1 rfs:text-[10px] rfs:font-medium",children:r})]})},Ne=Et;function ge({appointment:e,onResizePointerDown:t}){return jsx("div",{role:"button","aria-label":"Resize appointment",onPointerDown:r=>{e.visualState!=="ghost"&&(r.stopPropagation(),t(r));},className:"rfs:absolute rfs:inset-x-1 rfs:bottom-1 rfs:h-2 rfs:cursor-ns-resize rfs:rounded-full rfs:bg-border/90 rfs:transition-colors rfs:hover:bg-border"})}function Q({appointment:e,isDropInvalid:t,onPointerDown:r,onResizePointerDown:o,appointmentAppearance:n,appointmentBackgroundColor:i}){let a=e.raw,d=typeof a.description=="string"?a.description:void 0,s=typeof i=="string"?i:void 0,c=n?.className??s??"rfs:bg-muted/40 rfs:dark:bg-muted/30",R=t?"rfs:bg-red-100/80 rfs:text-red-950 rfs:dark:bg-red-950/40 rfs:dark:text-red-100":"",f=e.visualState==="ghost"?"rfs:cursor-grab rfs:opacity-35":e.visualState==="dragging"?"rfs:cursor-grabbing rfs:opacity-55 rfs:shadow-xl":"rfs:cursor-grab",g=`rfs:relative rfs:h-full rfs:overflow-hidden rfs:rounded-md rfs:p-2 rfs:pb-5 rfs:text-foreground ${c} ${R} ${f}`;return jsxs("div",{onPointerDown:r,className:g,children:[jsx(Ne,{isDropInvalid:t,title:e.title,description:d}),jsx(ge,{onResizePointerDown:o,appointment:e})]})}var Ft={id:"id",resourceId:"resourceId",start:"start",end:"end",title:"title"},W=(e,t)=>typeof t=="function"?t(e):e[t],Te=e=>e&&"getId"in e?{id:e.getId,resourceId:e.getResourceId,start:e.getStart,end:e.getEnd,title:e.getTitle}:{...Ft,...e},Se=e=>{if(e&&"getId"in e)return e;let t=Te(e);return {getEnd:r=>W(r,t.end),getId:r=>W(r,t.id),getResourceId:r=>W(r,t.resourceId),getStart:r=>W(r,t.start),getTitle:r=>W(r,t.title)}};function Be(e){if(!e||typeof e!="object")return false;let t=e;return typeof t.firstName=="string"||typeof t.lastName=="string"}var Oe={slate:"rfs:bg-slate-100 rfs:dark:bg-slate-900/40",gray:"rfs:bg-gray-100 rfs:dark:bg-gray-900/40",zinc:"rfs:bg-zinc-100 rfs:dark:bg-zinc-900/40",neutral:"rfs:bg-neutral-100 rfs:dark:bg-neutral-900/40",stone:"rfs:bg-stone-100 rfs:dark:bg-stone-900/40",red:"rfs:bg-red-100 rfs:dark:bg-red-950/40",orange:"rfs:bg-orange-100 rfs:dark:bg-orange-950/40",amber:"rfs:bg-amber-100 rfs:dark:bg-amber-950/40",yellow:"rfs:bg-yellow-100 rfs:dark:bg-yellow-950/40",lime:"rfs:bg-lime-100 rfs:dark:bg-lime-950/40",green:"rfs:bg-green-100 rfs:dark:bg-green-950/40",emerald:"rfs:bg-emerald-100 rfs:dark:bg-emerald-950/40",teal:"rfs:bg-teal-100 rfs:dark:bg-teal-950/40",cyan:"rfs:bg-cyan-100 rfs:dark:bg-cyan-950/40",sky:"rfs:bg-sky-100 rfs:dark:bg-sky-950/40",blue:"rfs:bg-blue-100 rfs:dark:bg-blue-950/40",indigo:"rfs:bg-indigo-100 rfs:dark:bg-indigo-950/40",violet:"rfs:bg-violet-100 rfs:dark:bg-violet-950/40",purple:"rfs:bg-purple-100 rfs:dark:bg-purple-950/40",fuchsia:"rfs:bg-fuchsia-100 rfs:dark:bg-fuchsia-950/40",pink:"rfs:bg-pink-100 rfs:dark:bg-pink-950/40",rose:"rfs:bg-rose-100 rfs:dark:bg-rose-950/40"};function L(e,t,r){return Math.max(t,Math.min(r,e))}function K(e,t=15){return Math.round(e/t)*t}function Ae(e){let[t,r]=e.split(":").map(Number);return t*60+r}function Le(e){return `${e.firstName??""} ${e.lastName??""}`.trim()}function Z(e){return format(e,"yyyy-MM-dd")}function Ie(e,t){return new Date(e.getFullYear(),e.getMonth(),e.getDate()+t)}function $(e,t,r){let o=new Date(e.getFullYear(),e.getMonth(),e.getDate(),0,0,0,0),n=t+r,i=Math.floor(n/60),a=n%60;return o.setHours(i,a,0,0),o}function be(e,t){return t.getHours()*60+t.getMinutes()-e}function ye(e,t){return e.startMin<t.endMin&&t.startMin<e.endMin}function _e(e){let t=[...e].sort((a,d)=>a.startMin-d.startMin||a.endMin-d.endMin),r=[],o=[],n=[];for(let a of t)o=o.filter(s=>s.endMin>a.startMin),!o.some(s=>ye(s,a))&&n.length>0&&(r.push(n),n=[]),n.push(a),o.push(a);n.length&&r.push(n);let i=[];for(let a of r){let d=[...a].sort((f,g)=>f.startMin-g.startMin||f.endMin-g.endMin),s=[],c=new Map;for(let f of d){let g=false;for(let p=0;p<s.length;p++)if(s[p]<=f.startMin){s[p]=f.endMin,c.set(f.id,p),g=true;break}g||(s.push(f.endMin),c.set(f.id,s.length-1));}let R=s.length;for(let f of d)i.push({...f,lane:c.get(f.id)??0,lanes:R});}return i}function Me({fallback:e,getValue:t,resources:r,toKey:o}){let n=new Map;for(let i of r)n.set(o(i),t(i)??e);return n}function Fe({adapter:e,appointments:t,dayMinutes:r,dayStartAbs:o,selectedISO:n}){return t.map(i=>{let a=e.getId(i),d=new Date(e.getStart(i)),s=new Date(e.getEnd(i));return {raw:i,id:a,resourceId:e.getResourceId(i),start:d,end:s,startMin:L(be(o,d),0,r),endMin:L(be(o,s),0,r),title:e.getTitle(i),renderKey:String(a),visualState:"normal"}}).filter(i=>Z(i.start)===n)}function Ve(e){return new Map(e.map(t=>[t.id,t]))}function He(e,t,r,o){return t.kind==="none"||t.kind==="move"?e:e.map(n=>n.id!==t.appointmentId?n:{...n,resourceId:t.resourceId,startMin:t.startMin,endMin:t.endMin,start:$(r,o,t.startMin),end:$(r,o,t.endMin),visualState:"dragging"})}function ze(e,t){let r=new Map;for(let n of t){let i=r.get(n.resourceId)??[];i.push(n),r.set(n.resourceId,i);}let o=new Map;for(let n of e)o.set(n.id,ve(r.get(n.id)??[]));return o}function ve(e){return _e(e.map(t=>({...t,appointmentId:t.id,id:t.renderKey}))).map(({appointmentId:t,...r})=>({...r,id:t}))}function Ye(e,t,r,o,n){let i=new Map;for(let a of e){let d=t?.[String(a.id)];if(d){i.set(a.id,{className:d});continue}let s=r?.(a);if(s){i.set(a.id,s);continue}let c=o.get(a.id);if(c){i.set(a.id,{className:c});continue}let R=n.get(a.id);i.set(a.id,R?{className:R}:void 0);}return i}function Xe({adapter:e,appointments:t,dayEnd:r="18:00",dayStart:o="09:00",resources:n,selectedDate:i}){let a=I.useMemo(()=>Ae(o),[o]),d=I.useMemo(()=>Ae(r),[r]),s=I.useMemo(()=>Math.max(0,d-a),[d,a]),c=I.useMemo(()=>12+s*2+24,[s]),R=I.useMemo(()=>72+Math.max(n.length,1)*420,[n.length]),{id:f,resourceId:g,start:p,end:l,title:h}=Te(e),T=I.useMemo(()=>Se({id:f,resourceId:g,start:p,end:l,title:h}),[f,g,p,l,h]),b=I.useMemo(()=>Z(i),[i]),S=I.useMemo(()=>Fe({adapter:T,appointments:t,dayMinutes:s,dayStartAbs:a,selectedISO:b}),[t,s,a,T,b]);return {appointmentMap:I.useMemo(()=>Ve(S),[S]),dayEndAbs:d,dayMinutes:s,dayStartAbs:a,gridHeight:c,gridMinWidth:R,renderAppts:S}}var Ht=4,zt=(e,t)=>{e(r=>r&&{...r,clientX:t.clientX,clientY:t.clientY});},Yt=e=>{let{dragRef:t,pendingDragRef:r,pointer:o,setDrag:n,setMovePreview:i,suppressClickRef:a}=e,d=r.current;if(!d||d.drag.pointerId!==o.pointerId)return;let s=o.clientX-d.startClientX,c=o.clientY-d.startClientY;Math.hypot(s,c)<Ht||(a.current=true,t.current=d.drag,n(d.drag),d.drag.kind==="move"&&i({appointment:d.appointment,clientX:o.clientX,clientY:o.clientY,width:d.width,height:d.height,offsetX:d.offsetX,offsetY:d.offsetY}),r.current=null);},Xt=(e,t,r,o,n)=>{let i=o(t.clientX,e.resourceId),d=n(i,t.clientY)-e.offsetMin,s=L(K(d),0,r-e.durationMin),c=s+e.durationMin;return s===e.startMin&&c===e.endMin&&i===e.resourceId?null:{...e,resourceId:i,startMin:s,endMin:c}},Ut=(e,t,r,o)=>{let n=o(e.resourceId,t.clientY),i=L(K(n),e.startMin+15,r);return i===e.endMin?null:{...e,endMin:i}},$e=e=>{let{dayMinutes:t,dragRef:r,latestPointerRef:o,pendingDragRef:n,pointerToMin:i,pointerToResourceId:a,setDrag:d,setMovePreview:s,suppressClickRef:c}=e,R=o.current;if(!R)return;let f=r.current;if(f.kind==="none"&&n.current){Yt({pointer:R,pendingDragRef:n,setDrag:d,setMovePreview:s,dragRef:r,suppressClickRef:c});return}if(f.kind==="none")return;if(f.kind==="move"){zt(s,R);let p=Xt(f,R,t,a,i);p&&(c.current=true,r.current=p,d(p));return}let g=Ut(f,R,t,i);g&&(c.current=true,r.current=g,d(g));},We=e=>{let{dragRef:t,frameRef:r,latestPointerRef:o,pendingDragRef:n,persistDrag:i,setDrag:a,setMovePreview:d,suppressClickRef:s}=e;r.current!==null&&(window.cancelAnimationFrame(r.current),r.current=null),o.current=null,n.current=null,d(null);let c=t.current;c.kind!=="none"&&(a({kind:"none"}),t.current={kind:"none"},s.current&&i(c));};var Ke=({appointmentMap:e,dayMinutes:t,dayStartAbs:r,onAppointmentChange:o,onPersistMoveResize:n,renderAppts:i,resources:a,selectedDate:d,editable:s})=>{let[c,R]=I.useState({kind:"none"}),[f,g]=I.useState(null),p=I.useRef({}),l=I.useRef(false),h=I.useRef({kind:"none"}),T=I.useRef(null),b=I.useRef(null),S=I.useRef(null),X=I.useMemo(()=>{let u=new Map;for(let m of i){let A=u.get(m.resourceId)??[];A.push(m),u.set(m.resourceId,A);}return u},[i]);I.useEffect(()=>{h.current=c;},[c]),I.useEffect(()=>()=>{S.current!==null&&window.cancelAnimationFrame(S.current);},[]);let y=I.useCallback((u,m)=>{let A=p.current[String(u)];if(!A)return 0;let C=m-A.getBoundingClientRect().top-12;return L(K(C/2),0,t)},[t]),k=I.useCallback((u,m)=>{for(let A of a){let C=p.current[String(A.id)];if(!C)continue;let F=C.getBoundingClientRect();if(u>=F.left&&u<=F.right)return A.id}return m},[a]),w=I.useCallback((u,m,A,C)=>(X.get(m)??[]).some(V=>V.id!==u&&ye(V,{startMin:A,endMin:C})),[X]),ce=I.useMemo(()=>c.kind==="none"?false:w(c.appointmentId,c.resourceId,c.startMin,c.endMin),[c,w]),q=I.useCallback(async u=>{let m=e.get(u.appointmentId);if(!m||w(u.appointmentId,u.resourceId,u.startMin,u.endMin))return;let A={resourceId:u.resourceId,start:$(d,r,u.startMin),end:$(d,r,u.endMin)};if(o){await o({kind:u.kind,appointment:m.raw,resourceId:A.resourceId,start:A.start,end:A.end,previousResourceId:m.resourceId,previousStart:m.start,previousEnd:m.end,previous:{resourceId:m.resourceId,start:m.start,end:m.end},next:A});return}n&&await n({appointment:m.raw,resourceId:A.resourceId,start:A.start,end:A.end});},[e,r,w,o,n,d]),ue=I.useCallback((u,m)=>{if(l.current=false,!s||u.button!==0)return;u.stopPropagation();let A=u.currentTarget.getBoundingClientRect(),C=y(m.resourceId,u.clientY);T.current={drag:{kind:"move",appointmentId:m.id,pointerId:u.pointerId,resourceId:m.resourceId,durationMin:Math.max(15,m.endMin-m.startMin),offsetMin:C-m.startMin,startMin:m.startMin,endMin:m.endMin},appointment:m,startClientX:u.clientX,startClientY:u.clientY,width:A.width,height:A.height,offsetX:u.clientX-A.left,offsetY:u.clientY-A.top};},[y,s]),pe=I.useCallback((u,m)=>{l.current=false,s&&u.button===0&&(u.stopPropagation(),T.current={drag:{kind:"resize",appointmentId:m.id,pointerId:u.pointerId,resourceId:m.resourceId,startMin:m.startMin,endMin:m.endMin},appointment:m,startClientX:u.clientX,startClientY:u.clientY,width:0,height:0,offsetX:0,offsetY:0});},[s]),le=I.useCallback(u=>{b.current={clientX:u.clientX,clientY:u.clientY,pointerId:u.pointerId},S.current===null&&(S.current=window.requestAnimationFrame(()=>{S.current=null,$e({dayMinutes:t,dragRef:h,latestPointerRef:b,pendingDragRef:T,pointerToMin:y,pointerToResourceId:k,setDrag:R,setMovePreview:g,suppressClickRef:l});}));},[t,y,k]),fe=I.useCallback(()=>{We({dragRef:h,frameRef:S,latestPointerRef:b,pendingDragRef:T,persistDrag:q,setDrag:R,setMovePreview:g,suppressClickRef:l});},[q]);return {colRefs:p,drag:c,isDropInvalid:ce,movePreview:f,onApptPointerDown:ue,onGlobalPointerMove:le,onGlobalPointerUp:fe,onResizePointerDown:pe,suppressClickRef:l}};function Ge({appointmentColorTokenClassMap:e,dayStartAbs:t,drag:r,getResourceAppointmentAppearance:o,getResourceAppointmentBackground:n,getResourceAppointmentColorToken:i,renderAppts:a,resourceAppointmentClassMap:d,resources:s,selectedDate:c}){let R=I.useMemo(()=>He(a,r,c,t),[t,r,a,c]),f=I.useMemo(()=>ze(s,a),[a,s]),g=I.useMemo(()=>{if(r.kind!=="resize")return f;let T=new Map(f),b=R.filter(S=>S.resourceId===r.resourceId);return T.set(r.resourceId,ve(b)),T},[f,r,R]),p=I.useMemo(()=>n?Me({fallback:void 0,getValue:n,resources:s,toKey:T=>T.id}):new Map,[n,s]),l=I.useMemo(()=>{if(!i)return new Map;let T={...Oe,...e??{}};return Me({fallback:void 0,getValue:b=>{let S=i(b);return S?T[S]:void 0},resources:s,toKey:b=>b.id})},[e,i,s]);return {appointmentAppearanceByResource:I.useMemo(()=>Ye(s,d,o,l,p),[p,l,o,d,s]),appointmentBgByResource:p,effectiveAppts:R,laidOutByResource:g}}function qe({views:e,view:t,defaultView:r,onViewChange:o}){let[n,i]=I.useState(()=>r??(e.length>0?e[0]:"day")),a=I.useCallback(d=>{t===void 0&&i(d),o?.(d);},[t,o]);return [t??n,a]}function B(...e){return e.filter(Boolean).join(" ")}function Je({resource:e}){return jsx("strong",{children:e.label})}function re({resources:e,renderResourceHeader:t}){return jsxs("div",{className:"rfs-header rfs:border-border rfs:bg-card",children:[jsx("div",{className:"rfs-gutter rfs:border-border",style:{width:72}}),e.map(r=>jsxs("div",{className:"rfs-resource-header rfs:border-border rfs:bg-card rfs:text-foreground",style:{minWidth:420,flex:1},children:[(t??(o=>Je({resource:o})))(r),Be(r)?jsx("div",{className:"rfs-resource-subtitle rfs:text-muted-foreground",children:Le(r)}):null]},String(r.id)))]})}var je=e=>format(e,"HH:mm"),et=e=>String(e).padStart(2,"0"),Kt=e=>`${et(Math.floor(e/60))}:${et(e%60)}`,tt=e=>Math.floor((e.getHours()*60+e.getMinutes())/15)*15,rt=(e,t)=>`${e}|${String(t)}`;function nt({appointment:e}){let t=e.raw,r=typeof t.description=="string"?t.description:void 0;return jsxs(Fragment,{children:[jsxs("span",{className:"rfs:block rfs:text-xs rfs:font-medium rfs:tabular-nums",children:[je(e.start),"\u2013",je(e.end)]}),jsx("span",{className:"rfs:block rfs:text-xs rfs:font-semibold",children:e.title}),r&&jsx("span",{className:"rfs:block rfs:text-[10px] rfs:font-medium",children:r})]})}function st({appointments:e,resources:t,appointmentAppearanceByResource:r,dayStartAbs:o,dayEndAbs:n,onAppointmentClick:i,renderResourceHeader:a,renderAgendaItem:d,emptyState:s="No appointments"}){let{slots:c,cells:R}=I.useMemo(()=>{let p=new Set(t.map(y=>y.id)),l=e.filter(y=>p.has(y.resourceId)).sort((y,k)=>y.start.getTime()-k.start.getTime()),h=new Map;for(let y of l){let k=rt(tt(y.start),y.resourceId),w=h.get(k)??[];w.push(y),h.set(k,w);}let T=l.map(y=>tt(y.start)),b=Math.min(Math.floor(o/15)*15,...T),S=Math.max(Math.ceil(n/15)*15-15,...T);return {slots:Array.from({length:Math.max(0,(S-b)/15+1)},(y,k)=>b+k*15),cells:h}},[e,t,o,n]);if(!(R.size>0))return jsx("div",{className:"rfs-agenda rfs:rounded-lg rfs:border rfs:border-border rfs:bg-card rfs:p-6 rfs:text-center rfs:text-sm rfs:text-muted-foreground",children:s});let g=(p,l)=>{let h=r.get(l.id),T=i?S=>i(p.raw,S):void 0;if(d)return jsx("li",{onClick:T,children:d({appointment:p,resource:l,appointmentAppearance:h})},p.renderKey);let b=B("rfs:block rfs:w-full rfs:rounded-md rfs:px-3 rfs:py-2 rfs:text-left rfs:text-foreground",h?.className??"rfs:bg-muted/40 rfs:dark:bg-muted/30");return jsx("li",{children:T?jsx("button",{type:"button",className:B(b,"rfs:cursor-pointer"),onClick:T,children:jsx(nt,{appointment:p})}):jsx("div",{className:b,children:jsx(nt,{appointment:p})})},p.renderKey)};return jsx("div",{className:"rfs-agenda rfs-shell rfs:border-border rfs:bg-card",children:jsxs("div",{style:{minWidth:72+Math.max(t.length,1)*420},children:[jsx(re,{resources:t,renderResourceHeader:a}),c.map(p=>{let l=p%60===0,h=(p+15)%60===0?"var(--rfs-border)":"color-mix(in oklab, var(--rfs-border) 40%, transparent)";return jsxs("div",{className:"rfs:flex",children:[jsx("div",{className:B("rfs-gutter rfs:border-b rfs:px-2 rfs:py-1 rfs:text-xs rfs:tabular-nums",l?"rfs:text-foreground":"rfs:text-muted-foreground/70"),style:{width:72,borderBottomColor:h},children:Kt(p)}),t.map(T=>jsx("ul",{"aria-label":T.label,className:"rfs-col rfs:flex rfs:min-h-7 rfs:flex-col rfs:gap-1 rfs:border-b rfs:p-1",style:{minWidth:420,flex:1,borderBottomColor:h},children:(R.get(rt(p,T.id))??[]).map(b=>g(b,T))},String(T.id)))]},p)})]})})}function it({dayMinutes:e,dayStartAbs:t,gridHeight:r}){return jsx("div",{className:"rfs-times rfs:border-border rfs:bg-card",style:{width:72,height:r},children:Array.from({length:Math.floor(e/60)+1}).map((o,n)=>jsxs("div",{className:"rfs-time-tick rfs:text-muted-foreground",style:{top:12+n*60*2},children:[String(Math.floor((t+n*60)/60)).padStart(2,"0"),":",String((t+n*60)%60).padStart(2,"0")]},`tick-${n}`))})}var dt=({resource:e,colRefs:t,gridHeight:r,dayMinutes:o,appointments:n,appointmentAppearance:i,appointmentBg:a,isDropInvalid:d,renderAppointment:s,onAppointmentClick:c,onApptPointerDown:R,onResizePointerDown:f,drag:g,suppressClickRef:p})=>jsx("div",{className:"rfs-col rfs:border-border rfs:bg-card",style:{minWidth:420,flex:1},children:jsxs("div",{ref:l=>{t.current[String(e.id)]=l;},className:"rfs-col-inner rfs:bg-card",style:{height:r},children:[Array.from({length:Math.floor(o/60)+1}).map((l,h)=>jsx("div",{className:"rfs-hour-line rfs:border-border/70",style:{top:12+h*60*2}},`major-${h}`)),Array.from({length:Math.floor(o/15)+1}).map((l,h)=>jsx("div",{className:"rfs-slot-line rfs:border-border/50",style:{top:12+h*15*2}},`minor-${h}`)),n.map(l=>{let h=100/l.lanes,T=12+l.startMin*2,b=Math.max(30,(l.endMin-l.startMin)*2);return jsx("div",{className:`rfs-card-slot ${l.visualState==="ghost"?"rfs-card-slot--ghost":""} ${l.visualState==="dragging"?"rfs-card-slot--dragging":""}`,style:{top:T,left:`${h*l.lane}%`,width:`${h}%`,height:b},onClick:c?S=>{p.current||c(l.raw,S);}:void 0,children:(s??Q)({appointment:l,isDropInvalid:d&&g.kind==="resize"&&l.id===g.appointmentId,onPointerDown:S=>R(S,l),onResizePointerDown:S=>f(S,l),appointmentAppearance:i,appointmentBackgroundColor:a,drag:g,suppressClickRef:p})},l.renderKey)})]})});var Zt=(e,t)=>[e.resource===t.resource,e.colRefs===t.colRefs,e.gridHeight===t.gridHeight,e.dayMinutes===t.dayMinutes,e.appointments===t.appointments,e.appointmentAppearance===t.appointmentAppearance,e.appointmentBg===t.appointmentBg,e.isDropInvalid===t.isDropInvalid,e.renderAppointment===t.renderAppointment,e.onAppointmentClick===t.onAppointmentClick,e.onApptPointerDown===t.onApptPointerDown,e.onResizePointerDown===t.onResizePointerDown,e.drag===t.drag,e.suppressClickRef===t.suppressClickRef].every(Boolean),ct=I.memo(dt,Zt);var jt={default:"rfs:bg-primary rfs:text-primary-foreground rfs:hover:bg-primary/90",outline:"rfs:border rfs:border-border rfs:bg-card rfs:text-foreground rfs:hover:bg-muted",ghost:"rfs:text-foreground rfs:hover:bg-muted"},er={default:"rfs:h-9 rfs:px-4 rfs:py-2",sm:"rfs:h-8 rfs:px-3 rfs:text-xs",icon:"rfs:h-8 rfs:w-8"},D=I.forwardRef(function({className:t,variant:r="default",size:o="default",type:n="button",...i},a){return jsx("button",{ref:a,type:n,className:B("rfs:inline-flex rfs:items-center rfs:justify-center rfs:gap-2 rfs:rounded-md rfs:text-sm rfs:font-medium rfs:whitespace-nowrap rfs:transition-colors rfs:focus-visible:outline-none rfs:focus-visible:ring-2 rfs:focus-visible:ring-ring rfs:focus-visible:ring-offset-2 rfs:disabled:pointer-events-none rfs:disabled:opacity-50",jt[r],er[o],t),...i})});function mt({selected:e,onSelect:t}){let[r,o]=I.useState(e??new Date);I.useEffect(()=>{e&&o(e);},[e]);let n=startOfMonth(r),i=startOfWeek(n,{weekStartsOn:1}),a=endOfWeek(endOfMonth(r),{weekStartsOn:1}),d=[];for(let s=i;s<=a;s=addDays(s,1))d.push(s);return jsxs("div",{className:"rfs:w-72 rfs:rounded-md rfs:bg-popover",children:[jsxs("div",{className:"rfs:mb-2 rfs:flex rfs:items-center rfs:justify-between",children:[jsx(D,{variant:"ghost",size:"icon","aria-label":"Previous month",onClick:()=>o(addMonths(r,-1)),children:"<"}),jsx("div",{className:"rfs:text-sm rfs:font-medium",children:format(r,"MMMM yyyy")}),jsx(D,{variant:"ghost",size:"icon","aria-label":"Next month",onClick:()=>o(addMonths(r,1)),children:">"})]}),jsx("div",{className:"rfs:grid rfs:grid-cols-7 rfs:gap-1 rfs:text-center rfs:text-xs rfs:text-muted-foreground",children:["Mo","Tu","We","Th","Fr","Sa","Su"].map(s=>jsx("div",{className:"rfs:py-1",children:s},s))}),jsx("div",{className:"rfs:grid rfs:grid-cols-7 rfs:gap-1",children:d.map(s=>{let c=e?isSameDay(s,e):false;return jsx(D,{variant:c?"default":"ghost",size:"icon",className:B("rfs:text-xs",!isSameMonth(s,r)&&"rfs:text-muted-foreground rfs:opacity-60",isToday(s)&&!c&&"rfs:border rfs:border-border"),onClick:()=>t?.(s),children:format(s,"d")},s.toISOString())})})]})}var Rt=I.createContext(null);function ht(){let e=I.useContext(Rt);if(!e)throw new Error("Popover components must be used within Popover.");return e}function gt({children:e,open:t,onOpenChange:r}){let[o,n]=I.useState(false),i=I.useRef(null),a=I.useRef(null),d=t??o,s=I.useCallback(c=>{let R=typeof c=="function"?c(d):c;t===void 0&&n(R),r?.(R);},[t,r,d]);return I.useEffect(()=>{if(!d)return;let c=f=>{let g=f.target;i.current?.contains(g)||a.current?.contains(g)||s(false);},R=f=>{f.key==="Escape"&&s(false);};return document.addEventListener("mousedown",c),document.addEventListener("keydown",R),()=>{document.removeEventListener("mousedown",c),document.removeEventListener("keydown",R);}},[d,s]),jsx(Rt.Provider,{value:{open:d,setOpen:s,triggerRef:i,contentRef:a},children:jsx("div",{className:"rfs:relative rfs:inline-flex",children:e})})}function Tt({children:e,asChild:t=false}){let{open:r,setOpen:o,triggerRef:n}=ht();if(t&&I.isValidElement(e)){let i=e;return I.cloneElement(i,{ref:n,"aria-expanded":r,onClick:a=>{i.props.onClick?.(a),o(d=>!d);}})}return jsx("button",{ref:n,type:"button","aria-expanded":r,onClick:()=>o(i=>!i),children:e})}function St({children:e,className:t,align:r="start"}){let{open:o,contentRef:n}=ht();return o?jsx("div",{ref:n,className:B("rfs:absolute rfs:top-full rfs:z-50 rfs:mt-2 rfs:min-w-72 rfs:rounded-md rfs:border rfs:border-border rfs:bg-popover rfs:p-2 rfs:text-popover-foreground rfs:shadow-md rfs:outline-none",r==="start"&&"rfs:left-0",r==="center"&&"rfs:left-1/2 rfs:-translate-x-1/2",r==="end"&&"rfs:right-0",t),children:e}):null}function At({selectedDate:e,onSelectedDateChange:t}){return jsxs(gt,{children:[jsx(Tt,{asChild:true,children:jsx(D,{variant:"outline",size:"sm",className:"rfs:min-w-40 rfs:justify-start rfs:text-left rfs:font-normal",children:format(e,"PPP")})}),jsx(St,{className:"rfs:w-auto rfs:p-2",align:"center",children:jsx(mt,{selected:e,onSelect:t})})]})}function bt({goToPreviousDay:e,goToNextDay:t,defaultDatePicker:r,defaultViewSwitcher:o,prevButtonLabel:n="Prev",nextButtonLabel:i="Next"}){return jsxs("div",{className:"rfs-toolbar",children:[jsxs("div",{className:"rfs:flex rfs:items-center rfs:gap-2 rfs:rounded-lg rfs:border rfs:border-border rfs:bg-card rfs:p-1 rfs:shadow-xs",children:[jsx(D,{variant:"outline",size:"sm",onClick:e,children:n}),r,jsx(D,{variant:"outline",size:"sm",onClick:t,children:i})]}),o&&jsx("div",{className:"rfs:ml-auto",children:o})]})}var lr={day:"Day",agenda:"Agenda"};function Mt({selectedDate:e,onSelectedDateChange:t,prevButtonLabel:r,nextButtonLabel:o,renderToolbar:n,renderDatePicker:i,view:a,views:d,onViewChange:s,viewLabels:c}){let R=()=>t(Ie(e,-1)),f=()=>t(Ie(e,1)),g=(i??At)({selectedDate:e,onSelectedDateChange:t}),p=d.length>1?jsx("div",{role:"group","aria-label":"View",className:"rfs:flex rfs:items-center rfs:gap-1 rfs:rounded-lg rfs:border rfs:border-border rfs:bg-card rfs:p-1 rfs:shadow-xs",children:d.map(h=>jsx(D,{variant:h===a?"default":"ghost",size:"sm","aria-pressed":h===a,onClick:()=>s(h),children:c?.[h]??lr[h]},h))}):null,l={selectedDate:e,onSelectedDateChange:t,goToPreviousDay:R,goToNextDay:f,defaultDatePicker:g,view:a,views:d,onViewChange:s,defaultViewSwitcher:p};return n?jsx(Fragment,{children:n(l)}):jsx(Fragment,{children:bt({...l,prevButtonLabel:r,nextButtonLabel:o})})}var fr={kind:"none"},mr=["day"];function Rr({resources:e,appointments:t,selectedDate:r,onSelectedDateChange:o,adapter:n,onPersistMoveResize:i,onAppointmentChange:a,onAppointmentClick:d,renderResourceHeader:s,renderAppointment:c,resourceAppointmentClassMap:R,getResourceAppointmentAppearance:f,getResourceAppointmentColorToken:g,appointmentColorTokenClassMap:p,getResourceAppointmentBackground:l,renderToolbar:h,renderDatePicker:T,prevButtonLabel:b="Prev",nextButtonLabel:S="Next",dayStart:X="09:00",dayEnd:y="18:00",editable:k=true,views:w=mr,view:ce,defaultView:q,onViewChange:ue,viewLabels:pe,renderAgendaItem:le,agendaEmptyState:fe}){let[u,m]=qe({views:w,view:ce,defaultView:q,onViewChange:ue}),{appointmentMap:A,dayEndAbs:C,dayMinutes:F,dayStartAbs:V,gridHeight:ke,gridMinWidth:Pt,renderAppts:me}=Xe({adapter:n,appointments:t,dayEnd:y,dayStart:X,resources:e,selectedDate:r}),{colRefs:kt,drag:v,isDropInvalid:De,movePreview:N,onApptPointerDown:Dt,onGlobalPointerMove:wt,onGlobalPointerUp:we,onResizePointerDown:Ct,suppressClickRef:Ce}=Ke({appointmentMap:A,dayMinutes:F,dayStartAbs:V,onAppointmentChange:a,onPersistMoveResize:i,renderAppts:me,resources:e,selectedDate:r,editable:k}),{appointmentAppearanceByResource:J,appointmentBgByResource:Re,laidOutByResource:Nt}=Ge({appointmentColorTokenClassMap:p,dayStartAbs:V,drag:v,getResourceAppointmentAppearance:f,getResourceAppointmentBackground:l,getResourceAppointmentColorToken:g,renderAppts:me,resourceAppointmentClassMap:R,resources:e,selectedDate:r}),O=I.useMemo(()=>v.kind!=="move"||!N?null:{appointment:{...N.appointment,resourceId:v.resourceId,startMin:v.startMin,endMin:v.endMin,visualState:"ghost",renderKey:`${N.appointment.renderKey}-overlay`,lane:0,lanes:1},appearance:J.get(v.resourceId),background:Re.get(v.resourceId),left:N.clientX-N.offsetX,top:N.clientY-N.offsetY,width:N.width,height:N.height},[J,Re,v,N]);return jsxs("section",{className:`rfs-root rfs:rounded-lg rfs:text-foreground ${v.kind==="move"?"rfs-root--drag-move":""} ${v.kind==="resize"?"rfs-root--drag-resize":""}`,onPointerMove:wt,onPointerUp:we,onPointerCancel:we,children:[jsx(Mt,{selectedDate:r,onSelectedDateChange:o,prevButtonLabel:b,nextButtonLabel:S,renderToolbar:h,renderDatePicker:T,view:u,views:w,onViewChange:m,viewLabels:pe}),u==="agenda"?jsx(st,{appointments:me,resources:e,appointmentAppearanceByResource:J,dayStartAbs:V,dayEndAbs:C,onAppointmentClick:d,renderResourceHeader:s,renderAgendaItem:le,emptyState:fe}):jsx("div",{className:"rfs-shell rfs:border-border rfs:bg-card",children:jsxs("div",{style:{minWidth:Pt},children:[jsx(re,{resources:e,renderResourceHeader:s}),jsxs("div",{className:"rfs-body",children:[jsx(it,{dayMinutes:F,dayStartAbs:V,gridHeight:ke}),jsx("div",{className:"rfs-grid",children:e.map(U=>jsx(ct,{resource:U,colRefs:kt,gridHeight:ke,dayMinutes:F,appointments:Nt.get(U.id)??[],appointmentAppearance:J.get(U.id),appointmentBg:Re.get(U.id),isDropInvalid:De,renderAppointment:c,onAppointmentClick:d,onApptPointerDown:Dt,onResizePointerDown:Ct,drag:v.kind==="resize"&&v.resourceId===U.id?v:fr,suppressClickRef:Ce},String(U.id)))})]})]})}),O?jsx("div",{className:"rfs-drag-overlay",style:{left:O.left,top:O.top,width:O.width,height:O.height},children:(c??Q)({appointment:O.appointment,isDropInvalid:De,onPointerDown:()=>{},onResizePointerDown:()=>{},appointmentAppearance:O.appearance,appointmentBackgroundColor:O.background,drag:v,suppressClickRef:Ce})}):null]})}var hr={id:"id",resourceId:"resourceId",start:"start",end:"end"},xt=(e,t)=>typeof t=="function"?t(e):e[t],gr=e=>!("getId"in e),Tr=e=>({resourceId:e.resourceId??e.next.resourceId,start:e.start??e.next.start,end:e.end??e.next.end}),Sr=(e,t,...[r={}])=>{let o=Tr(t);return e.map(n=>{if(gr(r)){let d={...hr,...r};if(xt(n,d.id)!==xt(t.appointment,d.id))return n;let s=r.dateValue??(c=>c);return {...n,[d.resourceId]:o.resourceId,[d.start]:s(o.start),[d.end]:s(o.end)}}if(r.getId(n)!==r.getId(t.appointment))return n;let i=r.setResourceId(n,o.resourceId),a=r.setStart(i,o.start);return r.setEnd(a,o.end)})};export{Rr as Scheduler,Sr as applySchedulerAppointmentChange,Se as resolveSchedulerAppointmentAdapter};
|
package/dist/styles.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){.rfs-root, .rfs-root *,.rfs-root :before,.rfs-root :after,.rfs-root::backdrop, .rfs-root ::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{.rfs-root,.rfs-root{--rfs-color-red-100:oklch(93.6% .032 17.717);--rfs-color-red-600:oklch(57.7% .245 27.325);--rfs-color-red-950:oklch(25.8% .092 26.042);--rfs-color-white:#fff;--rfs-spacing:.25rem;--rfs-text-xs:.75rem;--rfs-text-xs--line-height:calc(1 / .75);--rfs-text-sm:.875rem;--rfs-text-sm--line-height:calc(1.25 / .875);--rfs-font-weight-normal:400;--rfs-font-weight-medium:500;--rfs-font-weight-semibold:600;--rfs-font-weight-bold:700;--rfs-default-transition-duration:.15s;--rfs-default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--rfs-default-font-family:var(--font-sans);--rfs-default-mono-font-family:var(--font-mono)}}@layer base{.rfs-root, .rfs-root *,.rfs-root :after,.rfs-root :before,.rfs-root::backdrop, .rfs-root ::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}.rfs-root::file-selector-button, .rfs-root ::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}.rfs-root,.rfs-root{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--rfs-default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--rfs-default-font-feature-settings,normal);font-variation-settings:var(--rfs-default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}.rfs-root hr{height:0;color:inherit;border-top-width:1px}.rfs-root abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.rfs-root h1,.rfs-root h2,.rfs-root h3,.rfs-root h4,.rfs-root h5,.rfs-root h6{font-size:inherit;font-weight:inherit}.rfs-root a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}.rfs-root b,.rfs-root strong{font-weight:bolder}.rfs-root code,.rfs-root kbd,.rfs-root samp,.rfs-root pre{font-family:var(--rfs-default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--rfs-default-mono-font-feature-settings,normal);font-variation-settings:var(--rfs-default-mono-font-variation-settings,normal);font-size:1em}.rfs-root small{font-size:80%}.rfs-root sub,.rfs-root sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}.rfs-root sub{bottom:-.25em}.rfs-root sup{top:-.5em}.rfs-root table{text-indent:0;border-color:inherit;border-collapse:collapse}.rfs-root :-moz-focusring{outline:auto}.rfs-root progress{vertical-align:baseline}.rfs-root summary{display:list-item}.rfs-root ol,.rfs-root ul,.rfs-root menu{list-style:none}.rfs-root img,.rfs-root svg,.rfs-root video,.rfs-root canvas,.rfs-root audio,.rfs-root iframe,.rfs-root embed,.rfs-root object{vertical-align:middle;display:block}.rfs-root img,.rfs-root video{max-width:100%;height:auto}.rfs-root button,.rfs-root input,.rfs-root select,.rfs-root optgroup,.rfs-root textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}.rfs-root::file-selector-button, .rfs-root ::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}.rfs-root :where(select:is([multiple],[size])) optgroup{font-weight:bolder}.rfs-root :where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}.rfs-root::file-selector-button, .rfs-root ::file-selector-button{margin-inline-end:4px}.rfs-root::placeholder, .rfs-root ::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){.rfs-root::placeholder, .rfs-root ::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){.rfs-root::placeholder, .rfs-root ::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}.rfs-root textarea{resize:vertical}.rfs-root::-webkit-search-decoration, .rfs-root ::-webkit-search-decoration{-webkit-appearance:none}.rfs-root::-webkit-date-and-time-value, .rfs-root ::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}.rfs-root::-webkit-datetime-edit, .rfs-root ::-webkit-datetime-edit{display:inline-flex}.rfs-root::-webkit-datetime-edit-fields-wrapper, .rfs-root ::-webkit-datetime-edit-fields-wrapper{padding:0}.rfs-root::-webkit-datetime-edit, .rfs-root ::-webkit-datetime-edit{padding-block:0}.rfs-root::-webkit-datetime-edit-year-field, .rfs-root ::-webkit-datetime-edit-year-field{padding-block:0}.rfs-root::-webkit-datetime-edit-month-field, .rfs-root ::-webkit-datetime-edit-month-field{padding-block:0}.rfs-root::-webkit-datetime-edit-day-field, .rfs-root ::-webkit-datetime-edit-day-field{padding-block:0}.rfs-root::-webkit-datetime-edit-hour-field, .rfs-root ::-webkit-datetime-edit-hour-field{padding-block:0}.rfs-root::-webkit-datetime-edit-minute-field, .rfs-root ::-webkit-datetime-edit-minute-field{padding-block:0}.rfs-root::-webkit-datetime-edit-second-field, .rfs-root ::-webkit-datetime-edit-second-field{padding-block:0}.rfs-root::-webkit-datetime-edit-millisecond-field, .rfs-root ::-webkit-datetime-edit-millisecond-field{padding-block:0}.rfs-root::-webkit-datetime-edit-meridiem-field, .rfs-root ::-webkit-datetime-edit-meridiem-field{padding-block:0}.rfs-root::-webkit-calendar-picker-indicator, .rfs-root ::-webkit-calendar-picker-indicator{line-height:1}.rfs-root :-moz-ui-invalid{box-shadow:none}.rfs-root button,.rfs-root input:where([type=button],[type=reset],[type=submit]){appearance:button}.rfs-root::file-selector-button, .rfs-root ::file-selector-button{appearance:button}.rfs-root::-webkit-inner-spin-button, .rfs-root ::-webkit-inner-spin-button{height:auto}.rfs-root::-webkit-outer-spin-button, .rfs-root ::-webkit-outer-spin-button{height:auto}.rfs-root [hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.rfs-root.rfs\:absolute, .rfs-root .rfs\:absolute{position:absolute}.rfs-root.rfs\:relative, .rfs-root .rfs\:relative{position:relative}.rfs-root.rfs\:inset-x-1, .rfs-root .rfs\:inset-x-1{inset-inline:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:top-1, .rfs-root .rfs\:top-1{top:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:top-full, .rfs-root .rfs\:top-full{top:100%}.rfs-root.rfs\:right-0, .rfs-root .rfs\:right-0{right:calc(var(--rfs-spacing) * 0)}.rfs-root.rfs\:right-1, .rfs-root .rfs\:right-1{right:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:bottom-1, .rfs-root .rfs\:bottom-1{bottom:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:left-0, .rfs-root .rfs\:left-0{left:calc(var(--rfs-spacing) * 0)}.rfs-root.rfs\:left-1\/2, .rfs-root .rfs\:left-1\/2{left:50%}.rfs-root.rfs\:z-50, .rfs-root .rfs\:z-50{z-index:50}.rfs-root.rfs\:mt-1, .rfs-root .rfs\:mt-1{margin-top:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:mt-2, .rfs-root .rfs\:mt-2{margin-top:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:mb-2, .rfs-root .rfs\:mb-2{margin-bottom:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:flex, .rfs-root .rfs\:flex{display:flex}.rfs-root.rfs\:grid, .rfs-root .rfs\:grid{display:grid}.rfs-root.rfs\:inline-flex, .rfs-root .rfs\:inline-flex{display:inline-flex}.rfs-root.rfs\:h-2, .rfs-root .rfs\:h-2{height:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:h-4, .rfs-root .rfs\:h-4{height:calc(var(--rfs-spacing) * 4)}.rfs-root.rfs\:h-8, .rfs-root .rfs\:h-8{height:calc(var(--rfs-spacing) * 8)}.rfs-root.rfs\:h-9, .rfs-root .rfs\:h-9{height:calc(var(--rfs-spacing) * 9)}.rfs-root.rfs\:h-full, .rfs-root .rfs\:h-full{height:100%}.rfs-root.rfs\:w-4, .rfs-root .rfs\:w-4{width:calc(var(--rfs-spacing) * 4)}.rfs-root.rfs\:w-8, .rfs-root .rfs\:w-8{width:calc(var(--rfs-spacing) * 8)}.rfs-root.rfs\:w-72, .rfs-root .rfs\:w-72{width:calc(var(--rfs-spacing) * 72)}.rfs-root.rfs\:w-auto, .rfs-root .rfs\:w-auto{width:auto}.rfs-root.rfs\:min-w-40, .rfs-root .rfs\:min-w-40{min-width:calc(var(--rfs-spacing) * 40)}.rfs-root.rfs\:min-w-72, .rfs-root .rfs\:min-w-72{min-width:calc(var(--rfs-spacing) * 72)}.rfs-root.rfs\:-translate-x-1\/2, .rfs-root .rfs\:-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.rfs-root.rfs\:cursor-grab, .rfs-root .rfs\:cursor-grab{cursor:grab}.rfs-root.rfs\:cursor-grabbing, .rfs-root .rfs\:cursor-grabbing{cursor:grabbing}.rfs-root.rfs\:cursor-ns-resize, .rfs-root .rfs\:cursor-ns-resize{cursor:ns-resize}.rfs-root.rfs\:grid-cols-7, .rfs-root .rfs\:grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.rfs-root.rfs\:items-center, .rfs-root .rfs\:items-center{align-items:center}.rfs-root.rfs\:justify-between, .rfs-root .rfs\:justify-between{justify-content:space-between}.rfs-root.rfs\:justify-center, .rfs-root .rfs\:justify-center{justify-content:center}.rfs-root.rfs\:justify-start, .rfs-root .rfs\:justify-start{justify-content:flex-start}.rfs-root.rfs\:gap-1, .rfs-root .rfs\:gap-1{gap:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:gap-2, .rfs-root .rfs\:gap-2{gap:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:overflow-hidden, .rfs-root .rfs\:overflow-hidden{overflow:hidden}.rfs-root.rfs\:rounded-full, .rfs-root .rfs\:rounded-full{border-radius:3.40282e38px}.rfs-root.rfs\:rounded-lg, .rfs-root .rfs\:rounded-lg{border-radius:var(--radius)}.rfs-root.rfs\:rounded-md, .rfs-root .rfs\:rounded-md{border-radius:calc(var(--radius) - 2px)}.rfs-root.rfs\:border, .rfs-root .rfs\:border{border-style:var(--tw-border-style);border-width:1px}.rfs-root.rfs\:border-border, .rfs-root .rfs\:border-border,.rfs-root.rfs\:border-border\/50, .rfs-root .rfs\:border-border\/50{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:border-border\/50, .rfs-root .rfs\:border-border\/50{border-color:color-mix(in oklab, var(--border) 50%, transparent)}}.rfs-root.rfs\:border-border\/70, .rfs-root .rfs\:border-border\/70{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:border-border\/70, .rfs-root .rfs\:border-border\/70{border-color:color-mix(in oklab, var(--border) 70%, transparent)}}.rfs-root.rfs\:bg-border\/90, .rfs-root .rfs\:bg-border\/90{background-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:bg-border\/90, .rfs-root .rfs\:bg-border\/90{background-color:color-mix(in oklab, var(--border) 90%, transparent)}}.rfs-root.rfs\:bg-card, .rfs-root .rfs\:bg-card{background-color:var(--card)}.rfs-root.rfs\:bg-muted\/40, .rfs-root .rfs\:bg-muted\/40{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:bg-muted\/40, .rfs-root .rfs\:bg-muted\/40{background-color:color-mix(in oklab, var(--muted) 40%, transparent)}}.rfs-root.rfs\:bg-popover, .rfs-root .rfs\:bg-popover{background-color:var(--popover)}.rfs-root.rfs\:bg-primary, .rfs-root .rfs\:bg-primary{background-color:var(--primary)}.rfs-root.rfs\:bg-red-100\/80, .rfs-root .rfs\:bg-red-100\/80{background-color:var(--rfs-color-red-100)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:bg-red-100\/80, .rfs-root .rfs\:bg-red-100\/80{background-color:color-mix(in oklab, var(--rfs-color-red-100) 80%, transparent)}}.rfs-root.rfs\:bg-red-600, .rfs-root .rfs\:bg-red-600{background-color:var(--rfs-color-red-600)}.rfs-root.rfs\:p-1, .rfs-root .rfs\:p-1{padding:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:p-2, .rfs-root .rfs\:p-2{padding:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:px-3, .rfs-root .rfs\:px-3{padding-inline:calc(var(--rfs-spacing) * 3)}.rfs-root.rfs\:px-4, .rfs-root .rfs\:px-4{padding-inline:calc(var(--rfs-spacing) * 4)}.rfs-root.rfs\:py-1, .rfs-root .rfs\:py-1{padding-block:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:py-2, .rfs-root .rfs\:py-2{padding-block:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:pb-5, .rfs-root .rfs\:pb-5{padding-bottom:calc(var(--rfs-spacing) * 5)}.rfs-root.rfs\:text-center, .rfs-root .rfs\:text-center{text-align:center}.rfs-root.rfs\:text-left, .rfs-root .rfs\:text-left{text-align:left}.rfs-root.rfs\:text-sm, .rfs-root .rfs\:text-sm{font-size:var(--rfs-text-sm);line-height:var(--tw-leading,var(--rfs-text-sm--line-height))}.rfs-root.rfs\:text-xs, .rfs-root .rfs\:text-xs{font-size:var(--rfs-text-xs);line-height:var(--tw-leading,var(--rfs-text-xs--line-height))}.rfs-root.rfs\:text-\[10px\], .rfs-root .rfs\:text-\[10px\]{font-size:10px}.rfs-root.rfs\:font-bold, .rfs-root .rfs\:font-bold{--tw-font-weight:var(--rfs-font-weight-bold);font-weight:var(--rfs-font-weight-bold)}.rfs-root.rfs\:font-medium, .rfs-root .rfs\:font-medium{--tw-font-weight:var(--rfs-font-weight-medium);font-weight:var(--rfs-font-weight-medium)}.rfs-root.rfs\:font-normal, .rfs-root .rfs\:font-normal{--tw-font-weight:var(--rfs-font-weight-normal);font-weight:var(--rfs-font-weight-normal)}.rfs-root.rfs\:font-semibold, .rfs-root .rfs\:font-semibold{--tw-font-weight:var(--rfs-font-weight-semibold);font-weight:var(--rfs-font-weight-semibold)}.rfs-root.rfs\:whitespace-nowrap, .rfs-root .rfs\:whitespace-nowrap{white-space:nowrap}.rfs-root.rfs\:text-foreground, .rfs-root .rfs\:text-foreground{color:var(--foreground)}.rfs-root.rfs\:text-muted-foreground, .rfs-root .rfs\:text-muted-foreground{color:var(--muted-foreground)}.rfs-root.rfs\:text-popover-foreground, .rfs-root .rfs\:text-popover-foreground{color:var(--popover-foreground)}.rfs-root.rfs\:text-primary-foreground, .rfs-root .rfs\:text-primary-foreground{color:var(--primary-foreground)}.rfs-root.rfs\:text-red-950, .rfs-root .rfs\:text-red-950{color:var(--rfs-color-red-950)}.rfs-root.rfs\:text-white, .rfs-root .rfs\:text-white{color:var(--rfs-color-white)}.rfs-root.rfs\:opacity-35, .rfs-root .rfs\:opacity-35{opacity:.35}.rfs-root.rfs\:opacity-55, .rfs-root .rfs\:opacity-55{opacity:.55}.rfs-root.rfs\:opacity-60, .rfs-root .rfs\:opacity-60{opacity:.6}.rfs-root.rfs\:shadow-md, .rfs-root .rfs\:shadow-md{--tw-shadow:var(--shadow-md);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.rfs-root.rfs\:shadow-xl, .rfs-root .rfs\:shadow-xl{--tw-shadow:var(--shadow-xl);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.rfs-root.rfs\:shadow-xs, .rfs-root .rfs\:shadow-xs{--tw-shadow:var(--shadow-xs);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.rfs-root.rfs\:transition-colors, .rfs-root .rfs\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--rfs-default-transition-timing-function));transition-duration:var(--tw-duration,var(--rfs-default-transition-duration))}.rfs-root.rfs\:outline-none, .rfs-root .rfs\:outline-none{--tw-outline-style:none;outline-style:none}@media (hover:hover){.rfs-root.rfs\:hover\:bg-border:hover, .rfs-root .rfs\:hover\:bg-border:hover{background-color:var(--border)}.rfs-root.rfs\:hover\:bg-muted:hover, .rfs-root .rfs\:hover\:bg-muted:hover{background-color:var(--muted)}.rfs-root.rfs\:hover\:bg-primary\/90:hover, .rfs-root .rfs\:hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:hover\:bg-primary\/90:hover, .rfs-root .rfs\:hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--primary) 90%, transparent)}}}.rfs-root.rfs\:focus-visible\:ring-2:focus-visible, .rfs-root .rfs\:focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.rfs-root.rfs\:focus-visible\:ring-ring:focus-visible, .rfs-root .rfs\:focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--ring)}.rfs-root.rfs\:focus-visible\:ring-offset-2:focus-visible, .rfs-root .rfs\:focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.rfs-root.rfs\:focus-visible\:outline-none:focus-visible, .rfs-root .rfs\:focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.rfs-root.rfs\:disabled\:pointer-events-none:disabled, .rfs-root .rfs\:disabled\:pointer-events-none:disabled{pointer-events:none}.rfs-root.rfs\:disabled\:opacity-50:disabled, .rfs-root .rfs\:disabled\:opacity-50:disabled{opacity:.5}.rfs-root.rfs\:dark\:bg-muted\/30:is(.dark *), .rfs-root .rfs\:dark\:bg-muted\/30:is(.dark *){background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-muted\/30:is(.dark *), .rfs-root .rfs\:dark\:bg-muted\/30:is(.dark *){background-color:color-mix(in oklab, var(--muted) 30%, transparent)}}.rfs-root.rfs\:dark\:bg-red-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-red-950\/40:is(.dark *){background-color:var(--rfs-color-red-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-red-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-red-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-red-950) 40%, transparent)}}.rfs-root.rfs\:dark\:text-red-100:is(.dark *), .rfs-root .rfs\:dark\:text-red-100:is(.dark *){color:var(--rfs-color-red-100)}}.rfs-root{--topbar-h:39px;--header-h:87px;--footer-h:359px;--site-content-min-h:calc(100dvh - var(--topbar-h) - var(--header-h) - var(--footer-h));--background:oklch(100% 0 0);--foreground:oklch(21.93% .0122 145.145);--card:oklch(100% 0 0);--card-foreground:oklch(21.93% .0122 145.145);--popover:oklch(100% 0 0);--popover-foreground:oklch(21.93% .0122 145.145);--primary:oklch(72.56% .0713 141.056);--primary-foreground:oklch(100% 0 0);--secondary:oklch(96.07% .0112 141.263);--secondary-foreground:oklch(44.45% .0502 141.758);--muted:oklch(96.07% .0112 141.263);--muted-foreground:oklch(53.51% .0432 142.652);--accent:oklch(96.07% .0112 141.263);--accent-foreground:oklch(72.56% .0713 141.056);--destructive:oklch(68.07% .1129 109.059);--destructive-foreground:oklch(100% 0 0);--border:oklch(91% .021 140.896);--input:oklch(91% .021 140.896);--ring:oklch(72.56% .0713 141.056);--chart-1:oklch(72.56% .0713 141.056);--chart-2:oklch(60.42% .0688 140.724);--chart-3:oklch(84.06% .0531 141.655);--chart-4:oklch(49.29% .0598 141.478);--chart-5:oklch(91% .021 140.896);--sidebar:oklch(97.77% .0078 139.442);--sidebar-foreground:oklch(21.93% .0122 145.145);--sidebar-primary:oklch(72.56% .0713 141.056);--sidebar-primary-foreground:oklch(100% 0 0);--sidebar-accent:oklch(91% .021 140.896);--sidebar-accent-foreground:oklch(72.56% .0713 141.056);--sidebar-border:oklch(91% .021 140.896);--sidebar-ring:oklch(72.56% .0713 141.056);--font-sans:Geist, ui-sans-serif, sans-serif, system-ui;--font-serif:PT Serif, ui-serif, serif;--font-mono:Inconsolata, ui-monospace, monospace;--radius:.28rem;--shadow-x:0px;--shadow-y:4px;--shadow-blur:10px;--shadow-spread:0px;--shadow-opacity:.05;--shadow-color:0 0 0;--shadow-2xs:0px 4px 10px 0px #00000008;--shadow-xs:0px 4px 10px 0px #00000008;--shadow-sm:0px 4px 10px 0px #0000000d, 0px 1px 2px -1px #0000000d;--shadow:0px 4px 10px 0px #0000000d, 0px 1px 2px -1px #0000000d;--shadow-md:0px 4px 10px 0px #0000000d, 0px 2px 4px -1px #0000000d;--shadow-lg:0px 4px 10px 0px #0000000d, 0px 4px 6px -1px #0000000d;--shadow-xl:0px 4px 10px 0px #0000000d, 0px 8px 10px -1px #0000000d;--shadow-2xl:0px 4px 10px 0px #00000021;--tracking-normal:.01em;--spacing:.3rem;--rfs-bg:var(--background);--rfs-surface:var(--card);--rfs-border:var(--border);--rfs-text:var(--foreground);--rfs-muted:var(--muted-foreground)}.dark .rfs-root,.rfs-root.dark{--background:oklch(21.93% .0122 145.145);--foreground:oklch(96.07% .0112 141.263);--card:oklch(21.93% .0122 145.145);--card-foreground:oklch(96.07% .0112 141.263);--popover:oklch(21.93% .0122 145.145);--popover-foreground:oklch(96.07% .0112 141.263);--primary:oklch(72.56% .0713 141.056);--primary-foreground:oklch(21.93% .0122 145.145);--secondary:oklch(27.44% .0184 145.053);--secondary-foreground:oklch(84.06% .0531 141.655);--muted:oklch(27.44% .0184 145.053);--muted-foreground:oklch(60.42% .0688 140.724);--accent:oklch(27.44% .0184 145.053);--accent-foreground:oklch(72.56% .0713 141.056);--destructive:oklch(88.44% .1663 107.49);--destructive-foreground:oklch(100% 0 0);--border:oklch(27.44% .0184 145.053);--input:oklch(27.44% .0184 145.053);--ring:oklch(72.56% .0713 141.056);--chart-1:oklch(72.56% .0713 141.056);--chart-2:oklch(84.06% .0531 141.655);--chart-3:oklch(60.42% .0688 140.724);--chart-4:oklch(49.29% .0598 141.478);--chart-5:oklch(35.96% .0355 143.305);--sidebar:oklch(21.93% .0122 145.145);--sidebar-foreground:oklch(96.07% .0112 141.263);--sidebar-primary:oklch(72.56% .0713 141.056);--sidebar-primary-foreground:oklch(21.93% .0122 145.145);--sidebar-accent:oklch(27.44% .0184 145.053);--sidebar-accent-foreground:oklch(72.56% .0713 141.056);--sidebar-border:oklch(27.44% .0184 145.053);--sidebar-ring:oklch(72.56% .0713 141.056);--font-sans:Geist, ui-sans-serif, sans-serif, system-ui;--font-serif:PT Serif, ui-serif, serif;--font-mono:Inconsolata, ui-monospace, monospace;--radius:.28rem;--shadow-x:0px;--shadow-y:10px;--shadow-blur:20px;--shadow-spread:0px;--shadow-opacity:.4;--shadow-color:0 0 0;--shadow-2xs:0px 10px 20px 0px #0003;--shadow-xs:0px 10px 20px 0px #0003;--shadow-sm:0px 10px 20px 0px #0006, 0px 1px 2px -1px #0006;--shadow:0px 10px 20px 0px #0006, 0px 1px 2px -1px #0006;--shadow-md:0px 10px 20px 0px #0006, 0px 2px 4px -1px #0006;--shadow-lg:0px 10px 20px 0px #0006, 0px 4px 6px -1px #0006;--shadow-xl:0px 10px 20px 0px #0006, 0px 8px 10px -1px #0006;--shadow-2xl:0px 10px 20px 0px #000;--rfs-bg:var(--background);--rfs-surface:var(--card);--rfs-border:var(--border);--rfs-text:var(--foreground);--rfs-muted:var(--muted-foreground)}.rfs-root{font-size:var(--rfs-text-sm);line-height:var(--tw-leading,var(--rfs-text-sm--line-height));color:var(--rfs-text)}.rfs-root--drag-move{cursor:grabbing;-webkit-user-select:none;user-select:none}.rfs-root--drag-resize{cursor:ns-resize;-webkit-user-select:none;user-select:none}.rfs-root.rfs-card-slot--ghost, .rfs-root .rfs-card-slot--ghost{z-index:10;pointer-events:none}.rfs-root.rfs-card-slot--dragging, .rfs-root .rfs-card-slot--dragging{z-index:30}.rfs-root.rfs-drag-overlay, .rfs-root .rfs-drag-overlay{z-index:60;pointer-events:none;position:fixed}.rfs-root.rfs-toolbar, .rfs-root .rfs-toolbar{margin-bottom:calc(var(--rfs-spacing) * 3);align-items:center;gap:calc(var(--rfs-spacing) * 2);display:flex}.rfs-root.rfs-btn, .rfs-root .rfs-btn{border-radius:calc(var(--radius) - 2px);border-style:var(--tw-border-style);padding-inline:calc(var(--rfs-spacing) * 2);padding-block:calc(var(--rfs-spacing) * 1);font-size:var(--rfs-text-xs);line-height:var(--tw-leading,var(--rfs-text-xs--line-height));transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--rfs-default-transition-timing-function));transition-duration:var(--tw-duration,var(--rfs-default-transition-duration));background:var(--rfs-surface);border-width:1px}.rfs-root.rfs-btn:hover, .rfs-root .rfs-btn:hover{background:var(--rfs-bg)}.rfs-root.rfs-btn:disabled, .rfs-root .rfs-btn:disabled{cursor:not-allowed;opacity:.5}.rfs-root.rfs-date-label, .rfs-root .rfs-date-label{border-radius:calc(var(--radius) - 2px);border-style:var(--tw-border-style);padding-inline:calc(var(--rfs-spacing) * 2);padding-block:calc(var(--rfs-spacing) * 1);font-size:var(--rfs-text-xs);line-height:var(--tw-leading,var(--rfs-text-xs--line-height));--tw-font-weight:var(--rfs-font-weight-semibold);font-weight:var(--rfs-font-weight-semibold);border-width:1px;border-color:var(--rfs-border);background:var(--rfs-surface)}.rfs-root.rfs-shell, .rfs-root .rfs-shell{border-radius:var(--radius);border-style:var(--tw-border-style);background:var(--rfs-surface);border-width:1px;overflow-x:auto}.rfs-root.rfs-header, .rfs-root .rfs-header{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--rfs-border);display:flex}.rfs-root.rfs-gutter, .rfs-root .rfs-gutter{left:calc(var(--rfs-spacing) * 0);z-index:20;border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--rfs-border);background:var(--rfs-surface);flex-shrink:0;position:sticky}.rfs-root.rfs-resource-header, .rfs-root .rfs-resource-header{border-right-style:var(--tw-border-style);padding-inline:calc(var(--rfs-spacing) * 2);padding-block:calc(var(--rfs-spacing) * 2);border-right-width:1px;border-color:var(--rfs-border)}.rfs-root.rfs-resource-subtitle, .rfs-root .rfs-resource-subtitle{margin-top:calc(var(--rfs-spacing) * 1);font-size:var(--rfs-text-xs);line-height:var(--tw-leading,var(--rfs-text-xs--line-height));color:var(--rfs-muted)}.rfs-root.rfs-body, .rfs-root .rfs-body{display:flex}.rfs-root.rfs-times, .rfs-root .rfs-times{left:calc(var(--rfs-spacing) * 0);z-index:10;border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--rfs-border);background:var(--rfs-surface);flex-shrink:0;position:sticky;box-shadow:8px 0 12px -12px #0000002e}.rfs-root.rfs-time-tick, .rfs-root .rfs-time-tick{left:calc(var(--rfs-spacing) * 1);color:var(--rfs-muted);font-size:11px;position:absolute}.rfs-root.rfs-grid, .rfs-root .rfs-grid{flex:1;display:flex}.rfs-root.rfs-col, .rfs-root .rfs-col{border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--rfs-border)}.rfs-root.rfs-col-inner, .rfs-root .rfs-col-inner{position:relative}.rfs-root.rfs-hour-line, .rfs-root .rfs-hour-line,.rfs-root.rfs-slot-line, .rfs-root .rfs-slot-line{right:calc(var(--rfs-spacing) * 0);left:calc(var(--rfs-spacing) * 0);border-top-style:var(--tw-border-style);--tw-border-style:dotted;border-style:dotted;border-top-width:1px;border-color:var(--rfs-border);opacity:.5;position:absolute}.rfs-root.rfs-card-slot, .rfs-root .rfs-card-slot{padding:calc(var(--rfs-spacing) * .5);position:absolute}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){.rfs-root, .rfs-root *,.rfs-root :before,.rfs-root :after,.rfs-root::backdrop, .rfs-root ::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{.rfs-root,.rfs-root{--rfs-color-red-100:oklch(93.6% .032 17.717);--rfs-color-red-600:oklch(57.7% .245 27.325);--rfs-color-red-950:oklch(25.8% .092 26.042);--rfs-color-orange-100:oklch(95.4% .038 75.164);--rfs-color-orange-950:oklch(26.6% .079 36.259);--rfs-color-amber-100:oklch(96.2% .059 95.617);--rfs-color-amber-950:oklch(27.9% .077 45.635);--rfs-color-yellow-100:oklch(97.3% .071 103.193);--rfs-color-yellow-950:oklch(28.6% .066 53.813);--rfs-color-lime-100:oklch(96.7% .067 122.328);--rfs-color-lime-950:oklch(27.4% .072 132.109);--rfs-color-green-100:oklch(96.2% .044 156.743);--rfs-color-green-950:oklch(26.6% .065 152.934);--rfs-color-emerald-100:oklch(95% .052 163.051);--rfs-color-emerald-950:oklch(26.2% .051 172.552);--rfs-color-teal-100:oklch(95.3% .051 180.801);--rfs-color-teal-950:oklch(27.7% .046 192.524);--rfs-color-cyan-100:oklch(95.6% .045 203.388);--rfs-color-cyan-950:oklch(30.2% .056 229.695);--rfs-color-sky-100:oklch(95.1% .026 236.824);--rfs-color-sky-950:oklch(29.3% .066 243.157);--rfs-color-blue-100:oklch(93.2% .032 255.585);--rfs-color-blue-950:oklch(28.2% .091 267.935);--rfs-color-indigo-100:oklch(93% .034 272.788);--rfs-color-indigo-950:oklch(25.7% .09 281.288);--rfs-color-violet-100:oklch(94.3% .029 294.588);--rfs-color-violet-950:oklch(28.3% .141 291.089);--rfs-color-purple-100:oklch(94.6% .033 307.174);--rfs-color-purple-950:oklch(29.1% .149 302.717);--rfs-color-fuchsia-100:oklch(95.2% .037 318.852);--rfs-color-fuchsia-950:oklch(29.3% .136 325.661);--rfs-color-pink-100:oklch(94.8% .028 342.258);--rfs-color-pink-950:oklch(28.4% .109 3.907);--rfs-color-rose-100:oklch(94.1% .03 12.58);--rfs-color-rose-950:oklch(27.1% .105 12.094);--rfs-color-slate-100:oklch(96.8% .007 247.896);--rfs-color-slate-900:oklch(20.8% .042 265.755);--rfs-color-gray-100:oklch(96.7% .003 264.542);--rfs-color-gray-900:oklch(21% .034 264.665);--rfs-color-zinc-100:oklch(96.7% .001 286.375);--rfs-color-zinc-900:oklch(21% .006 285.885);--rfs-color-neutral-100:oklch(97% 0 0);--rfs-color-neutral-900:oklch(20.5% 0 0);--rfs-color-stone-100:oklch(97% .001 106.424);--rfs-color-stone-900:oklch(21.6% .006 56.043);--rfs-color-white:#fff;--rfs-spacing:.25rem;--rfs-text-xs:.75rem;--rfs-text-xs--line-height:calc(1 / .75);--rfs-text-sm:.875rem;--rfs-text-sm--line-height:calc(1.25 / .875);--rfs-font-weight-normal:400;--rfs-font-weight-medium:500;--rfs-font-weight-semibold:600;--rfs-font-weight-bold:700;--rfs-default-transition-duration:.15s;--rfs-default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--rfs-default-font-family:var(--font-sans);--rfs-default-mono-font-family:var(--font-mono)}}@layer base{.rfs-root, .rfs-root *,.rfs-root :after,.rfs-root :before,.rfs-root::backdrop, .rfs-root ::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}.rfs-root::file-selector-button, .rfs-root ::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}.rfs-root,.rfs-root{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--rfs-default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--rfs-default-font-feature-settings,normal);font-variation-settings:var(--rfs-default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}.rfs-root hr{height:0;color:inherit;border-top-width:1px}.rfs-root abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.rfs-root h1,.rfs-root h2,.rfs-root h3,.rfs-root h4,.rfs-root h5,.rfs-root h6{font-size:inherit;font-weight:inherit}.rfs-root a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}.rfs-root b,.rfs-root strong{font-weight:bolder}.rfs-root code,.rfs-root kbd,.rfs-root samp,.rfs-root pre{font-family:var(--rfs-default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--rfs-default-mono-font-feature-settings,normal);font-variation-settings:var(--rfs-default-mono-font-variation-settings,normal);font-size:1em}.rfs-root small{font-size:80%}.rfs-root sub,.rfs-root sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}.rfs-root sub{bottom:-.25em}.rfs-root sup{top:-.5em}.rfs-root table{text-indent:0;border-color:inherit;border-collapse:collapse}.rfs-root :-moz-focusring{outline:auto}.rfs-root progress{vertical-align:baseline}.rfs-root summary{display:list-item}.rfs-root ol,.rfs-root ul,.rfs-root menu{list-style:none}.rfs-root img,.rfs-root svg,.rfs-root video,.rfs-root canvas,.rfs-root audio,.rfs-root iframe,.rfs-root embed,.rfs-root object{vertical-align:middle;display:block}.rfs-root img,.rfs-root video{max-width:100%;height:auto}.rfs-root button,.rfs-root input,.rfs-root select,.rfs-root optgroup,.rfs-root textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}.rfs-root::file-selector-button, .rfs-root ::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}.rfs-root :where(select:is([multiple],[size])) optgroup{font-weight:bolder}.rfs-root :where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}.rfs-root::file-selector-button, .rfs-root ::file-selector-button{margin-inline-end:4px}.rfs-root::placeholder, .rfs-root ::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){.rfs-root::placeholder, .rfs-root ::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){.rfs-root::placeholder, .rfs-root ::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}.rfs-root textarea{resize:vertical}.rfs-root::-webkit-search-decoration, .rfs-root ::-webkit-search-decoration{-webkit-appearance:none}.rfs-root::-webkit-date-and-time-value, .rfs-root ::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}.rfs-root::-webkit-datetime-edit, .rfs-root ::-webkit-datetime-edit{display:inline-flex}.rfs-root::-webkit-datetime-edit-fields-wrapper, .rfs-root ::-webkit-datetime-edit-fields-wrapper{padding:0}.rfs-root::-webkit-datetime-edit, .rfs-root ::-webkit-datetime-edit{padding-block:0}.rfs-root::-webkit-datetime-edit-year-field, .rfs-root ::-webkit-datetime-edit-year-field{padding-block:0}.rfs-root::-webkit-datetime-edit-month-field, .rfs-root ::-webkit-datetime-edit-month-field{padding-block:0}.rfs-root::-webkit-datetime-edit-day-field, .rfs-root ::-webkit-datetime-edit-day-field{padding-block:0}.rfs-root::-webkit-datetime-edit-hour-field, .rfs-root ::-webkit-datetime-edit-hour-field{padding-block:0}.rfs-root::-webkit-datetime-edit-minute-field, .rfs-root ::-webkit-datetime-edit-minute-field{padding-block:0}.rfs-root::-webkit-datetime-edit-second-field, .rfs-root ::-webkit-datetime-edit-second-field{padding-block:0}.rfs-root::-webkit-datetime-edit-millisecond-field, .rfs-root ::-webkit-datetime-edit-millisecond-field{padding-block:0}.rfs-root::-webkit-datetime-edit-meridiem-field, .rfs-root ::-webkit-datetime-edit-meridiem-field{padding-block:0}.rfs-root::-webkit-calendar-picker-indicator, .rfs-root ::-webkit-calendar-picker-indicator{line-height:1}.rfs-root :-moz-ui-invalid{box-shadow:none}.rfs-root button,.rfs-root input:where([type=button],[type=reset],[type=submit]){appearance:button}.rfs-root::file-selector-button, .rfs-root ::file-selector-button{appearance:button}.rfs-root::-webkit-inner-spin-button, .rfs-root ::-webkit-inner-spin-button{height:auto}.rfs-root::-webkit-outer-spin-button, .rfs-root ::-webkit-outer-spin-button{height:auto}.rfs-root [hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.rfs-root.rfs\:absolute, .rfs-root .rfs\:absolute{position:absolute}.rfs-root.rfs\:relative, .rfs-root .rfs\:relative{position:relative}.rfs-root.rfs\:inset-x-1, .rfs-root .rfs\:inset-x-1{inset-inline:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:top-1, .rfs-root .rfs\:top-1{top:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:top-full, .rfs-root .rfs\:top-full{top:100%}.rfs-root.rfs\:right-0, .rfs-root .rfs\:right-0{right:calc(var(--rfs-spacing) * 0)}.rfs-root.rfs\:right-1, .rfs-root .rfs\:right-1{right:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:bottom-1, .rfs-root .rfs\:bottom-1{bottom:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:left-0, .rfs-root .rfs\:left-0{left:calc(var(--rfs-spacing) * 0)}.rfs-root.rfs\:left-1\/2, .rfs-root .rfs\:left-1\/2{left:50%}.rfs-root.rfs\:z-50, .rfs-root .rfs\:z-50{z-index:50}.rfs-root.rfs\:mt-1, .rfs-root .rfs\:mt-1{margin-top:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:mt-2, .rfs-root .rfs\:mt-2{margin-top:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:mb-2, .rfs-root .rfs\:mb-2{margin-bottom:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:ml-auto, .rfs-root .rfs\:ml-auto{margin-left:auto}.rfs-root.rfs\:block, .rfs-root .rfs\:block{display:block}.rfs-root.rfs\:flex, .rfs-root .rfs\:flex{display:flex}.rfs-root.rfs\:grid, .rfs-root .rfs\:grid{display:grid}.rfs-root.rfs\:inline-flex, .rfs-root .rfs\:inline-flex{display:inline-flex}.rfs-root.rfs\:h-2, .rfs-root .rfs\:h-2{height:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:h-4, .rfs-root .rfs\:h-4{height:calc(var(--rfs-spacing) * 4)}.rfs-root.rfs\:h-8, .rfs-root .rfs\:h-8{height:calc(var(--rfs-spacing) * 8)}.rfs-root.rfs\:h-9, .rfs-root .rfs\:h-9{height:calc(var(--rfs-spacing) * 9)}.rfs-root.rfs\:h-full, .rfs-root .rfs\:h-full{height:100%}.rfs-root.rfs\:min-h-7, .rfs-root .rfs\:min-h-7{min-height:calc(var(--rfs-spacing) * 7)}.rfs-root.rfs\:w-4, .rfs-root .rfs\:w-4{width:calc(var(--rfs-spacing) * 4)}.rfs-root.rfs\:w-8, .rfs-root .rfs\:w-8{width:calc(var(--rfs-spacing) * 8)}.rfs-root.rfs\:w-72, .rfs-root .rfs\:w-72{width:calc(var(--rfs-spacing) * 72)}.rfs-root.rfs\:w-auto, .rfs-root .rfs\:w-auto{width:auto}.rfs-root.rfs\:w-full, .rfs-root .rfs\:w-full{width:100%}.rfs-root.rfs\:min-w-40, .rfs-root .rfs\:min-w-40{min-width:calc(var(--rfs-spacing) * 40)}.rfs-root.rfs\:min-w-72, .rfs-root .rfs\:min-w-72{min-width:calc(var(--rfs-spacing) * 72)}.rfs-root.rfs\:-translate-x-1\/2, .rfs-root .rfs\:-translate-x-1\/2{--tw-translate-x:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.rfs-root.rfs\:cursor-grab, .rfs-root .rfs\:cursor-grab{cursor:grab}.rfs-root.rfs\:cursor-grabbing, .rfs-root .rfs\:cursor-grabbing{cursor:grabbing}.rfs-root.rfs\:cursor-ns-resize, .rfs-root .rfs\:cursor-ns-resize{cursor:ns-resize}.rfs-root.rfs\:cursor-pointer, .rfs-root .rfs\:cursor-pointer{cursor:pointer}.rfs-root.rfs\:grid-cols-7, .rfs-root .rfs\:grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.rfs-root.rfs\:flex-col, .rfs-root .rfs\:flex-col{flex-direction:column}.rfs-root.rfs\:items-center, .rfs-root .rfs\:items-center{align-items:center}.rfs-root.rfs\:justify-between, .rfs-root .rfs\:justify-between{justify-content:space-between}.rfs-root.rfs\:justify-center, .rfs-root .rfs\:justify-center{justify-content:center}.rfs-root.rfs\:justify-start, .rfs-root .rfs\:justify-start{justify-content:flex-start}.rfs-root.rfs\:gap-1, .rfs-root .rfs\:gap-1{gap:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:gap-2, .rfs-root .rfs\:gap-2{gap:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:overflow-hidden, .rfs-root .rfs\:overflow-hidden{overflow:hidden}.rfs-root.rfs\:rounded-full, .rfs-root .rfs\:rounded-full{border-radius:3.40282e38px}.rfs-root.rfs\:rounded-lg, .rfs-root .rfs\:rounded-lg{border-radius:var(--radius)}.rfs-root.rfs\:rounded-md, .rfs-root .rfs\:rounded-md{border-radius:calc(var(--radius) - 2px)}.rfs-root.rfs\:border, .rfs-root .rfs\:border{border-style:var(--tw-border-style);border-width:1px}.rfs-root.rfs\:border-b, .rfs-root .rfs\:border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.rfs-root.rfs\:border-border, .rfs-root .rfs\:border-border,.rfs-root.rfs\:border-border\/50, .rfs-root .rfs\:border-border\/50{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:border-border\/50, .rfs-root .rfs\:border-border\/50{border-color:color-mix(in oklab, var(--border) 50%, transparent)}}.rfs-root.rfs\:border-border\/70, .rfs-root .rfs\:border-border\/70{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:border-border\/70, .rfs-root .rfs\:border-border\/70{border-color:color-mix(in oklab, var(--border) 70%, transparent)}}.rfs-root.rfs\:bg-amber-100, .rfs-root .rfs\:bg-amber-100{background-color:var(--rfs-color-amber-100)}.rfs-root.rfs\:bg-blue-100, .rfs-root .rfs\:bg-blue-100{background-color:var(--rfs-color-blue-100)}.rfs-root.rfs\:bg-border\/90, .rfs-root .rfs\:bg-border\/90{background-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:bg-border\/90, .rfs-root .rfs\:bg-border\/90{background-color:color-mix(in oklab, var(--border) 90%, transparent)}}.rfs-root.rfs\:bg-card, .rfs-root .rfs\:bg-card{background-color:var(--card)}.rfs-root.rfs\:bg-cyan-100, .rfs-root .rfs\:bg-cyan-100{background-color:var(--rfs-color-cyan-100)}.rfs-root.rfs\:bg-emerald-100, .rfs-root .rfs\:bg-emerald-100{background-color:var(--rfs-color-emerald-100)}.rfs-root.rfs\:bg-fuchsia-100, .rfs-root .rfs\:bg-fuchsia-100{background-color:var(--rfs-color-fuchsia-100)}.rfs-root.rfs\:bg-gray-100, .rfs-root .rfs\:bg-gray-100{background-color:var(--rfs-color-gray-100)}.rfs-root.rfs\:bg-green-100, .rfs-root .rfs\:bg-green-100{background-color:var(--rfs-color-green-100)}.rfs-root.rfs\:bg-indigo-100, .rfs-root .rfs\:bg-indigo-100{background-color:var(--rfs-color-indigo-100)}.rfs-root.rfs\:bg-lime-100, .rfs-root .rfs\:bg-lime-100{background-color:var(--rfs-color-lime-100)}.rfs-root.rfs\:bg-muted\/40, .rfs-root .rfs\:bg-muted\/40{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:bg-muted\/40, .rfs-root .rfs\:bg-muted\/40{background-color:color-mix(in oklab, var(--muted) 40%, transparent)}}.rfs-root.rfs\:bg-neutral-100, .rfs-root .rfs\:bg-neutral-100{background-color:var(--rfs-color-neutral-100)}.rfs-root.rfs\:bg-orange-100, .rfs-root .rfs\:bg-orange-100{background-color:var(--rfs-color-orange-100)}.rfs-root.rfs\:bg-pink-100, .rfs-root .rfs\:bg-pink-100{background-color:var(--rfs-color-pink-100)}.rfs-root.rfs\:bg-popover, .rfs-root .rfs\:bg-popover{background-color:var(--popover)}.rfs-root.rfs\:bg-primary, .rfs-root .rfs\:bg-primary{background-color:var(--primary)}.rfs-root.rfs\:bg-purple-100, .rfs-root .rfs\:bg-purple-100{background-color:var(--rfs-color-purple-100)}.rfs-root.rfs\:bg-red-100, .rfs-root .rfs\:bg-red-100,.rfs-root.rfs\:bg-red-100\/80, .rfs-root .rfs\:bg-red-100\/80{background-color:var(--rfs-color-red-100)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:bg-red-100\/80, .rfs-root .rfs\:bg-red-100\/80{background-color:color-mix(in oklab, var(--rfs-color-red-100) 80%, transparent)}}.rfs-root.rfs\:bg-red-600, .rfs-root .rfs\:bg-red-600{background-color:var(--rfs-color-red-600)}.rfs-root.rfs\:bg-rose-100, .rfs-root .rfs\:bg-rose-100{background-color:var(--rfs-color-rose-100)}.rfs-root.rfs\:bg-sky-100, .rfs-root .rfs\:bg-sky-100{background-color:var(--rfs-color-sky-100)}.rfs-root.rfs\:bg-slate-100, .rfs-root .rfs\:bg-slate-100{background-color:var(--rfs-color-slate-100)}.rfs-root.rfs\:bg-stone-100, .rfs-root .rfs\:bg-stone-100{background-color:var(--rfs-color-stone-100)}.rfs-root.rfs\:bg-teal-100, .rfs-root .rfs\:bg-teal-100{background-color:var(--rfs-color-teal-100)}.rfs-root.rfs\:bg-violet-100, .rfs-root .rfs\:bg-violet-100{background-color:var(--rfs-color-violet-100)}.rfs-root.rfs\:bg-yellow-100, .rfs-root .rfs\:bg-yellow-100{background-color:var(--rfs-color-yellow-100)}.rfs-root.rfs\:bg-zinc-100, .rfs-root .rfs\:bg-zinc-100{background-color:var(--rfs-color-zinc-100)}.rfs-root.rfs\:p-1, .rfs-root .rfs\:p-1{padding:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:p-2, .rfs-root .rfs\:p-2{padding:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:p-6, .rfs-root .rfs\:p-6{padding:calc(var(--rfs-spacing) * 6)}.rfs-root.rfs\:px-2, .rfs-root .rfs\:px-2{padding-inline:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:px-3, .rfs-root .rfs\:px-3{padding-inline:calc(var(--rfs-spacing) * 3)}.rfs-root.rfs\:px-4, .rfs-root .rfs\:px-4{padding-inline:calc(var(--rfs-spacing) * 4)}.rfs-root.rfs\:py-1, .rfs-root .rfs\:py-1{padding-block:calc(var(--rfs-spacing) * 1)}.rfs-root.rfs\:py-2, .rfs-root .rfs\:py-2{padding-block:calc(var(--rfs-spacing) * 2)}.rfs-root.rfs\:pb-5, .rfs-root .rfs\:pb-5{padding-bottom:calc(var(--rfs-spacing) * 5)}.rfs-root.rfs\:text-center, .rfs-root .rfs\:text-center{text-align:center}.rfs-root.rfs\:text-left, .rfs-root .rfs\:text-left{text-align:left}.rfs-root.rfs\:text-sm, .rfs-root .rfs\:text-sm{font-size:var(--rfs-text-sm);line-height:var(--tw-leading,var(--rfs-text-sm--line-height))}.rfs-root.rfs\:text-xs, .rfs-root .rfs\:text-xs{font-size:var(--rfs-text-xs);line-height:var(--tw-leading,var(--rfs-text-xs--line-height))}.rfs-root.rfs\:text-\[10px\], .rfs-root .rfs\:text-\[10px\]{font-size:10px}.rfs-root.rfs\:font-bold, .rfs-root .rfs\:font-bold{--tw-font-weight:var(--rfs-font-weight-bold);font-weight:var(--rfs-font-weight-bold)}.rfs-root.rfs\:font-medium, .rfs-root .rfs\:font-medium{--tw-font-weight:var(--rfs-font-weight-medium);font-weight:var(--rfs-font-weight-medium)}.rfs-root.rfs\:font-normal, .rfs-root .rfs\:font-normal{--tw-font-weight:var(--rfs-font-weight-normal);font-weight:var(--rfs-font-weight-normal)}.rfs-root.rfs\:font-semibold, .rfs-root .rfs\:font-semibold{--tw-font-weight:var(--rfs-font-weight-semibold);font-weight:var(--rfs-font-weight-semibold)}.rfs-root.rfs\:whitespace-nowrap, .rfs-root .rfs\:whitespace-nowrap{white-space:nowrap}.rfs-root.rfs\:text-foreground, .rfs-root .rfs\:text-foreground{color:var(--foreground)}.rfs-root.rfs\:text-muted-foreground, .rfs-root .rfs\:text-muted-foreground,.rfs-root.rfs\:text-muted-foreground\/70, .rfs-root .rfs\:text-muted-foreground\/70{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:text-muted-foreground\/70, .rfs-root .rfs\:text-muted-foreground\/70{color:color-mix(in oklab, var(--muted-foreground) 70%, transparent)}}.rfs-root.rfs\:text-popover-foreground, .rfs-root .rfs\:text-popover-foreground{color:var(--popover-foreground)}.rfs-root.rfs\:text-primary-foreground, .rfs-root .rfs\:text-primary-foreground{color:var(--primary-foreground)}.rfs-root.rfs\:text-red-950, .rfs-root .rfs\:text-red-950{color:var(--rfs-color-red-950)}.rfs-root.rfs\:text-white, .rfs-root .rfs\:text-white{color:var(--rfs-color-white)}.rfs-root.rfs\:tabular-nums, .rfs-root .rfs\:tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.rfs-root.rfs\:opacity-35, .rfs-root .rfs\:opacity-35{opacity:.35}.rfs-root.rfs\:opacity-55, .rfs-root .rfs\:opacity-55{opacity:.55}.rfs-root.rfs\:opacity-60, .rfs-root .rfs\:opacity-60{opacity:.6}.rfs-root.rfs\:shadow-md, .rfs-root .rfs\:shadow-md{--tw-shadow:var(--shadow-md);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.rfs-root.rfs\:shadow-xl, .rfs-root .rfs\:shadow-xl{--tw-shadow:var(--shadow-xl);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.rfs-root.rfs\:shadow-xs, .rfs-root .rfs\:shadow-xs{--tw-shadow:var(--shadow-xs);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.rfs-root.rfs\:transition-colors, .rfs-root .rfs\:transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--rfs-default-transition-timing-function));transition-duration:var(--tw-duration,var(--rfs-default-transition-duration))}.rfs-root.rfs\:outline-none, .rfs-root .rfs\:outline-none{--tw-outline-style:none;outline-style:none}@media (hover:hover){.rfs-root.rfs\:hover\:bg-border:hover, .rfs-root .rfs\:hover\:bg-border:hover{background-color:var(--border)}.rfs-root.rfs\:hover\:bg-muted:hover, .rfs-root .rfs\:hover\:bg-muted:hover{background-color:var(--muted)}.rfs-root.rfs\:hover\:bg-primary\/90:hover, .rfs-root .rfs\:hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:hover\:bg-primary\/90:hover, .rfs-root .rfs\:hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--primary) 90%, transparent)}}}.rfs-root.rfs\:focus-visible\:ring-2:focus-visible, .rfs-root .rfs\:focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.rfs-root.rfs\:focus-visible\:ring-ring:focus-visible, .rfs-root .rfs\:focus-visible\:ring-ring:focus-visible{--tw-ring-color:var(--ring)}.rfs-root.rfs\:focus-visible\:ring-offset-2:focus-visible, .rfs-root .rfs\:focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.rfs-root.rfs\:focus-visible\:outline-none:focus-visible, .rfs-root .rfs\:focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.rfs-root.rfs\:disabled\:pointer-events-none:disabled, .rfs-root .rfs\:disabled\:pointer-events-none:disabled{pointer-events:none}.rfs-root.rfs\:disabled\:opacity-50:disabled, .rfs-root .rfs\:disabled\:opacity-50:disabled{opacity:.5}.rfs-root.rfs\:dark\:bg-amber-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-amber-950\/40:is(.dark *){background-color:var(--rfs-color-amber-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-amber-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-amber-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-amber-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-blue-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-blue-950\/40:is(.dark *){background-color:var(--rfs-color-blue-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-blue-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-blue-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-blue-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-cyan-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-cyan-950\/40:is(.dark *){background-color:var(--rfs-color-cyan-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-cyan-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-cyan-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-cyan-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-emerald-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-emerald-950\/40:is(.dark *){background-color:var(--rfs-color-emerald-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-emerald-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-emerald-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-emerald-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-fuchsia-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-fuchsia-950\/40:is(.dark *){background-color:var(--rfs-color-fuchsia-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-fuchsia-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-fuchsia-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-fuchsia-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-gray-900\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-gray-900\/40:is(.dark *){background-color:var(--rfs-color-gray-900)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-gray-900\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-gray-900\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-gray-900) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-green-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-green-950\/40:is(.dark *){background-color:var(--rfs-color-green-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-green-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-green-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-green-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-indigo-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-indigo-950\/40:is(.dark *){background-color:var(--rfs-color-indigo-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-indigo-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-indigo-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-indigo-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-lime-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-lime-950\/40:is(.dark *){background-color:var(--rfs-color-lime-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-lime-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-lime-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-lime-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-muted\/30:is(.dark *), .rfs-root .rfs\:dark\:bg-muted\/30:is(.dark *){background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-muted\/30:is(.dark *), .rfs-root .rfs\:dark\:bg-muted\/30:is(.dark *){background-color:color-mix(in oklab, var(--muted) 30%, transparent)}}.rfs-root.rfs\:dark\:bg-neutral-900\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-neutral-900\/40:is(.dark *){background-color:var(--rfs-color-neutral-900)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-neutral-900\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-neutral-900\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-neutral-900) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-orange-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-orange-950\/40:is(.dark *){background-color:var(--rfs-color-orange-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-orange-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-orange-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-orange-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-pink-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-pink-950\/40:is(.dark *){background-color:var(--rfs-color-pink-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-pink-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-pink-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-pink-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-purple-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-purple-950\/40:is(.dark *){background-color:var(--rfs-color-purple-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-purple-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-purple-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-purple-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-red-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-red-950\/40:is(.dark *){background-color:var(--rfs-color-red-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-red-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-red-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-red-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-rose-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-rose-950\/40:is(.dark *){background-color:var(--rfs-color-rose-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-rose-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-rose-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-rose-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-sky-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-sky-950\/40:is(.dark *){background-color:var(--rfs-color-sky-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-sky-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-sky-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-sky-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-slate-900\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-slate-900\/40:is(.dark *){background-color:var(--rfs-color-slate-900)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-slate-900\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-slate-900\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-slate-900) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-stone-900\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-stone-900\/40:is(.dark *){background-color:var(--rfs-color-stone-900)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-stone-900\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-stone-900\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-stone-900) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-teal-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-teal-950\/40:is(.dark *){background-color:var(--rfs-color-teal-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-teal-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-teal-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-teal-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-violet-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-violet-950\/40:is(.dark *){background-color:var(--rfs-color-violet-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-violet-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-violet-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-violet-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-yellow-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-yellow-950\/40:is(.dark *){background-color:var(--rfs-color-yellow-950)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-yellow-950\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-yellow-950\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-yellow-950) 40%, transparent)}}.rfs-root.rfs\:dark\:bg-zinc-900\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-zinc-900\/40:is(.dark *){background-color:var(--rfs-color-zinc-900)}@supports (color:color-mix(in lab, red, red)){.rfs-root.rfs\:dark\:bg-zinc-900\/40:is(.dark *), .rfs-root .rfs\:dark\:bg-zinc-900\/40:is(.dark *){background-color:color-mix(in oklab, var(--rfs-color-zinc-900) 40%, transparent)}}.rfs-root.rfs\:dark\:text-red-100:is(.dark *), .rfs-root .rfs\:dark\:text-red-100:is(.dark *){color:var(--rfs-color-red-100)}}.rfs-root{--topbar-h:39px;--header-h:87px;--footer-h:359px;--site-content-min-h:calc(100dvh - var(--topbar-h) - var(--header-h) - var(--footer-h));--background:oklch(100% 0 0);--foreground:oklch(21.93% .0122 145.145);--card:oklch(100% 0 0);--card-foreground:oklch(21.93% .0122 145.145);--popover:oklch(100% 0 0);--popover-foreground:oklch(21.93% .0122 145.145);--primary:oklch(72.56% .0713 141.056);--primary-foreground:oklch(100% 0 0);--secondary:oklch(96.07% .0112 141.263);--secondary-foreground:oklch(44.45% .0502 141.758);--muted:oklch(96.07% .0112 141.263);--muted-foreground:oklch(53.51% .0432 142.652);--accent:oklch(96.07% .0112 141.263);--accent-foreground:oklch(72.56% .0713 141.056);--destructive:oklch(68.07% .1129 109.059);--destructive-foreground:oklch(100% 0 0);--border:oklch(91% .021 140.896);--input:oklch(91% .021 140.896);--ring:oklch(72.56% .0713 141.056);--chart-1:oklch(72.56% .0713 141.056);--chart-2:oklch(60.42% .0688 140.724);--chart-3:oklch(84.06% .0531 141.655);--chart-4:oklch(49.29% .0598 141.478);--chart-5:oklch(91% .021 140.896);--sidebar:oklch(97.77% .0078 139.442);--sidebar-foreground:oklch(21.93% .0122 145.145);--sidebar-primary:oklch(72.56% .0713 141.056);--sidebar-primary-foreground:oklch(100% 0 0);--sidebar-accent:oklch(91% .021 140.896);--sidebar-accent-foreground:oklch(72.56% .0713 141.056);--sidebar-border:oklch(91% .021 140.896);--sidebar-ring:oklch(72.56% .0713 141.056);--font-sans:Geist, ui-sans-serif, sans-serif, system-ui;--font-serif:PT Serif, ui-serif, serif;--font-mono:Inconsolata, ui-monospace, monospace;--radius:.28rem;--shadow-x:0px;--shadow-y:4px;--shadow-blur:10px;--shadow-spread:0px;--shadow-opacity:.05;--shadow-color:0 0 0;--shadow-2xs:0px 4px 10px 0px #00000008;--shadow-xs:0px 4px 10px 0px #00000008;--shadow-sm:0px 4px 10px 0px #0000000d, 0px 1px 2px -1px #0000000d;--shadow:0px 4px 10px 0px #0000000d, 0px 1px 2px -1px #0000000d;--shadow-md:0px 4px 10px 0px #0000000d, 0px 2px 4px -1px #0000000d;--shadow-lg:0px 4px 10px 0px #0000000d, 0px 4px 6px -1px #0000000d;--shadow-xl:0px 4px 10px 0px #0000000d, 0px 8px 10px -1px #0000000d;--shadow-2xl:0px 4px 10px 0px #00000021;--tracking-normal:.01em;--spacing:.3rem;--rfs-bg:var(--background);--rfs-surface:var(--card);--rfs-border:var(--border);--rfs-text:var(--foreground);--rfs-muted:var(--muted-foreground)}.dark .rfs-root,.rfs-root.dark{--background:oklch(21.93% .0122 145.145);--foreground:oklch(96.07% .0112 141.263);--card:oklch(21.93% .0122 145.145);--card-foreground:oklch(96.07% .0112 141.263);--popover:oklch(21.93% .0122 145.145);--popover-foreground:oklch(96.07% .0112 141.263);--primary:oklch(72.56% .0713 141.056);--primary-foreground:oklch(21.93% .0122 145.145);--secondary:oklch(27.44% .0184 145.053);--secondary-foreground:oklch(84.06% .0531 141.655);--muted:oklch(27.44% .0184 145.053);--muted-foreground:oklch(60.42% .0688 140.724);--accent:oklch(27.44% .0184 145.053);--accent-foreground:oklch(72.56% .0713 141.056);--destructive:oklch(88.44% .1663 107.49);--destructive-foreground:oklch(100% 0 0);--border:oklch(27.44% .0184 145.053);--input:oklch(27.44% .0184 145.053);--ring:oklch(72.56% .0713 141.056);--chart-1:oklch(72.56% .0713 141.056);--chart-2:oklch(84.06% .0531 141.655);--chart-3:oklch(60.42% .0688 140.724);--chart-4:oklch(49.29% .0598 141.478);--chart-5:oklch(35.96% .0355 143.305);--sidebar:oklch(21.93% .0122 145.145);--sidebar-foreground:oklch(96.07% .0112 141.263);--sidebar-primary:oklch(72.56% .0713 141.056);--sidebar-primary-foreground:oklch(21.93% .0122 145.145);--sidebar-accent:oklch(27.44% .0184 145.053);--sidebar-accent-foreground:oklch(72.56% .0713 141.056);--sidebar-border:oklch(27.44% .0184 145.053);--sidebar-ring:oklch(72.56% .0713 141.056);--font-sans:Geist, ui-sans-serif, sans-serif, system-ui;--font-serif:PT Serif, ui-serif, serif;--font-mono:Inconsolata, ui-monospace, monospace;--radius:.28rem;--shadow-x:0px;--shadow-y:10px;--shadow-blur:20px;--shadow-spread:0px;--shadow-opacity:.4;--shadow-color:0 0 0;--shadow-2xs:0px 10px 20px 0px #0003;--shadow-xs:0px 10px 20px 0px #0003;--shadow-sm:0px 10px 20px 0px #0006, 0px 1px 2px -1px #0006;--shadow:0px 10px 20px 0px #0006, 0px 1px 2px -1px #0006;--shadow-md:0px 10px 20px 0px #0006, 0px 2px 4px -1px #0006;--shadow-lg:0px 10px 20px 0px #0006, 0px 4px 6px -1px #0006;--shadow-xl:0px 10px 20px 0px #0006, 0px 8px 10px -1px #0006;--shadow-2xl:0px 10px 20px 0px #000;--rfs-bg:var(--background);--rfs-surface:var(--card);--rfs-border:var(--border);--rfs-text:var(--foreground);--rfs-muted:var(--muted-foreground)}.rfs-root{font-size:var(--rfs-text-sm);line-height:var(--tw-leading,var(--rfs-text-sm--line-height));color:var(--rfs-text)}.rfs-root--drag-move{cursor:grabbing;-webkit-user-select:none;user-select:none}.rfs-root--drag-resize{cursor:ns-resize;-webkit-user-select:none;user-select:none}.rfs-root.rfs-card-slot--ghost, .rfs-root .rfs-card-slot--ghost{z-index:10;pointer-events:none}.rfs-root.rfs-card-slot--dragging, .rfs-root .rfs-card-slot--dragging{z-index:30}.rfs-root.rfs-drag-overlay, .rfs-root .rfs-drag-overlay{z-index:60;pointer-events:none;position:fixed}.rfs-root.rfs-toolbar, .rfs-root .rfs-toolbar{margin-bottom:calc(var(--rfs-spacing) * 3);align-items:center;gap:calc(var(--rfs-spacing) * 2);display:flex}.rfs-root.rfs-btn, .rfs-root .rfs-btn{border-radius:calc(var(--radius) - 2px);border-style:var(--tw-border-style);padding-inline:calc(var(--rfs-spacing) * 2);padding-block:calc(var(--rfs-spacing) * 1);font-size:var(--rfs-text-xs);line-height:var(--tw-leading,var(--rfs-text-xs--line-height));transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--rfs-default-transition-timing-function));transition-duration:var(--tw-duration,var(--rfs-default-transition-duration));background:var(--rfs-surface);border-width:1px}.rfs-root.rfs-btn:hover, .rfs-root .rfs-btn:hover{background:var(--rfs-bg)}.rfs-root.rfs-btn:disabled, .rfs-root .rfs-btn:disabled{cursor:not-allowed;opacity:.5}.rfs-root.rfs-date-label, .rfs-root .rfs-date-label{border-radius:calc(var(--radius) - 2px);border-style:var(--tw-border-style);padding-inline:calc(var(--rfs-spacing) * 2);padding-block:calc(var(--rfs-spacing) * 1);font-size:var(--rfs-text-xs);line-height:var(--tw-leading,var(--rfs-text-xs--line-height));--tw-font-weight:var(--rfs-font-weight-semibold);font-weight:var(--rfs-font-weight-semibold);border-width:1px;border-color:var(--rfs-border);background:var(--rfs-surface)}.rfs-root.rfs-shell, .rfs-root .rfs-shell{border-radius:var(--radius);border-style:var(--tw-border-style);background:var(--rfs-surface);border-width:1px;overflow-x:auto}.rfs-root.rfs-header, .rfs-root .rfs-header{border-bottom-style:var(--tw-border-style);border-bottom-width:1px;border-color:var(--rfs-border);display:flex}.rfs-root.rfs-gutter, .rfs-root .rfs-gutter{left:calc(var(--rfs-spacing) * 0);z-index:20;border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--rfs-border);background:var(--rfs-surface);flex-shrink:0;position:sticky}.rfs-root.rfs-resource-header, .rfs-root .rfs-resource-header{border-right-style:var(--tw-border-style);padding-inline:calc(var(--rfs-spacing) * 2);padding-block:calc(var(--rfs-spacing) * 2);border-right-width:1px;border-color:var(--rfs-border)}.rfs-root.rfs-resource-subtitle, .rfs-root .rfs-resource-subtitle{margin-top:calc(var(--rfs-spacing) * 1);font-size:var(--rfs-text-xs);line-height:var(--tw-leading,var(--rfs-text-xs--line-height));color:var(--rfs-muted)}.rfs-root.rfs-body, .rfs-root .rfs-body{display:flex}.rfs-root.rfs-times, .rfs-root .rfs-times{left:calc(var(--rfs-spacing) * 0);z-index:10;border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--rfs-border);background:var(--rfs-surface);flex-shrink:0;position:sticky;box-shadow:8px 0 12px -12px #0000002e}.rfs-root.rfs-time-tick, .rfs-root .rfs-time-tick{left:calc(var(--rfs-spacing) * 1);color:var(--rfs-muted);font-size:11px;position:absolute}.rfs-root.rfs-grid, .rfs-root .rfs-grid{flex:1;display:flex}.rfs-root.rfs-col, .rfs-root .rfs-col{border-right-style:var(--tw-border-style);border-right-width:1px;border-color:var(--rfs-border)}.rfs-root.rfs-col-inner, .rfs-root .rfs-col-inner{position:relative}.rfs-root.rfs-hour-line, .rfs-root .rfs-hour-line,.rfs-root.rfs-slot-line, .rfs-root .rfs-slot-line{right:calc(var(--rfs-spacing) * 0);left:calc(var(--rfs-spacing) * 0);border-top-style:var(--tw-border-style);--tw-border-style:dotted;border-style:dotted;border-top-width:1px;border-color:var(--rfs-border);opacity:.5;position:absolute}.rfs-root.rfs-card-slot, .rfs-root .rfs-card-slot{padding:calc(var(--rfs-spacing) * .5);position:absolute}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
|