@hectorbliss/denik-calendar 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,7 +24,6 @@ function App() {
24
24
  <Calendar
25
25
  events={events}
26
26
  onEventMove={(eventId, newStart) => {
27
- // Handle event move
28
27
  setEvents(prev =>
29
28
  prev.map(e => (e.id === eventId ? { ...e, start: newStart } : e))
30
29
  );
@@ -43,74 +42,152 @@ function App() {
43
42
  }
44
43
  ```
45
44
 
46
- ## Headless Hook
45
+ ## Resource Mode (Day View)
47
46
 
48
- Use the calendar logic without the UI:
47
+ Display resources (courts, rooms, employees) as columns instead of weekdays:
49
48
 
50
49
  ```tsx
51
- import { useCalendarEvents } from "@hectorbliss/denik-calendar";
50
+ import { Calendar, useCalendarControls } from "@hectorbliss/denik-calendar";
51
+
52
+ const courts = [
53
+ { id: "court-1", name: "Cancha 1", icon: <PadelIcon /> },
54
+ { id: "court-2", name: "Cancha 2", icon: <PadelIcon /> },
55
+ { id: "court-3", name: "Cancha 3", icon: <TennisIcon /> },
56
+ { id: "court-4", name: "Cancha 4", icon: <TennisIcon /> },
57
+ ];
58
+
59
+ // Events with resourceId
60
+ const events = [
61
+ { id: "1", start: new Date(), duration: 90, title: "Match", resourceId: "court-1" },
62
+ { id: "2", start: new Date(), duration: 60, title: "Training", resourceId: "court-2" },
63
+ ];
64
+
65
+ function CourtSchedule() {
66
+ return (
67
+ <Calendar
68
+ events={events}
69
+ date={selectedDay}
70
+ resources={courts}
71
+ />
72
+ );
73
+ }
74
+ ```
75
+
76
+ ## Navigation Controls
52
77
 
53
- function MyCustomCalendar({ events }) {
54
- const {
55
- canMove,
56
- hasOverlap,
57
- findConflicts,
58
- getEventsForDay,
59
- getEventsForWeek,
60
- findAvailableSlots
61
- } = useCalendarEvents(events);
62
-
63
- const handleDrop = (eventId, newStart) => {
64
- if (canMove(eventId, newStart)) {
65
- updateEvent(eventId, newStart);
66
- } else {
67
- toast.error("Time slot occupied");
68
- }
69
- };
70
-
71
- // Get available 60-min slots for today (8am-6pm)
72
- const slots = findAvailableSlots(new Date(), 60);
78
+ Use the headless hook for complete control:
79
+
80
+ ```tsx
81
+ import { Calendar, useCalendarControls, CalendarControls } from "@hectorbliss/denik-calendar";
82
+
83
+ function App() {
84
+ const controls = useCalendarControls();
85
+
86
+ return (
87
+ <>
88
+ {/* Pre-built controls */}
89
+ <CalendarControls controls={controls} />
90
+
91
+ {/* Or build your own */}
92
+ <div>
93
+ <button onClick={controls.goToToday}>HOY</button>
94
+ <button onClick={controls.goToPrev}>←</button>
95
+ <button onClick={controls.goToNext}>→</button>
96
+ <span>{controls.label}</span>
97
+ <button onClick={controls.toggleView}>
98
+ {controls.view === "week" ? "DÍA" : "SEMANA"}
99
+ </button>
100
+ </div>
101
+
102
+ <Calendar
103
+ date={controls.date}
104
+ events={events}
105
+ resources={controls.view === "day" ? courts : undefined}
106
+ />
107
+ </>
108
+ );
73
109
  }
74
110
  ```
75
111
 
112
+ ## Visual Overlaps
113
+
114
+ Events at the same time are displayed side-by-side automatically.
115
+
116
+ ## Headless Hooks
117
+
118
+ ### useCalendarEvents
119
+
120
+ ```tsx
121
+ import { useCalendarEvents } from "@hectorbliss/denik-calendar";
122
+
123
+ const {
124
+ canMove, // Check if event can move to new time
125
+ hasOverlap, // Check if time slot has conflicts
126
+ findConflicts, // Get all conflicting events
127
+ getEventsForDay, // Filter events by day
128
+ getEventsForWeek, // Filter events by week
129
+ findAvailableSlots // Get available time slots
130
+ } = useCalendarEvents(events);
131
+ ```
132
+
133
+ ### useCalendarControls
134
+
135
+ ```tsx
136
+ import { useCalendarControls } from "@hectorbliss/denik-calendar";
137
+
138
+ const {
139
+ date, // Current date
140
+ view, // "week" | "day"
141
+ week, // Array of 7 dates (Mon-Sun)
142
+ label, // Formatted date label
143
+ isToday, // Boolean
144
+ goToToday, // Navigate to today
145
+ goToPrev, // Navigate back (7 days or 1 day)
146
+ goToNext, // Navigate forward
147
+ toggleView, // Switch between week/day
148
+ setDate, // Set specific date
149
+ setView, // Set specific view
150
+ } = useCalendarControls({ locale: "es-MX" });
151
+ ```
152
+
76
153
  ## Props
77
154
 
78
155
  ### Calendar
79
156
 
80
157
  | Prop | Type | Description |
81
158
  |------|------|-------------|
82
- | `events` | `CalendarEvent[]` | Array of events to display |
83
- | `date` | `Date` | Current week to display (default: today) |
84
- | `onEventMove` | `(eventId, newStart) => void` | Called when event is dragged |
85
- | `onAddBlock` | `(start) => void` | Called when creating a block |
86
- | `onRemoveBlock` | `(eventId) => void` | Called when removing a block |
87
- | `onEventClick` | `(event) => void` | Called when clicking an event |
88
- | `onNewEvent` | `(start) => void` | Called when clicking empty slot |
89
- | `config` | `CalendarConfig` | Configuration options |
90
-
91
- ### CalendarEvent
159
+ | `events` | `CalendarEvent[]` | Array of events |
160
+ | `date` | `Date` | Current date (default: today) |
161
+ | `resources` | `Resource[]` | Resources for day view mode |
162
+ | `onEventMove` | `(eventId, newStart) => void` | Drag handler |
163
+ | `onAddBlock` | `(start) => void` | Block creation |
164
+ | `onRemoveBlock` | `(eventId) => void` | Block removal |
165
+ | `onEventClick` | `(event) => void` | Click handler |
166
+ | `onNewEvent` | `(start) => void` | Empty slot click |
167
+ | `config` | `CalendarConfig` | Configuration |
168
+
169
+ ### Types
92
170
 
93
171
  ```typescript
94
172
  interface CalendarEvent {
95
173
  id: string;
96
174
  start: Date;
97
- duration: number; // minutes
175
+ duration: number; // minutes
98
176
  title?: string;
99
177
  type?: "BLOCK" | "EVENT";
178
+ resourceId?: string; // For resource mode
100
179
  service?: { name: string };
101
180
  }
102
- ```
103
181
 
104
- ### CalendarConfig
182
+ interface Resource {
183
+ id: string;
184
+ name: string;
185
+ icon?: ReactNode;
186
+ }
105
187
 
106
- ```typescript
107
188
  interface CalendarConfig {
108
- locale?: string; // default: "es-MX"
109
- icons?: {
110
- trash?: ReactNode;
111
- edit?: ReactNode;
112
- close?: ReactNode;
113
- };
189
+ locale?: string;
190
+ icons?: { trash?, edit?, close? };
114
191
  renderColumnHeader?: (props: ColumnHeaderProps) => ReactNode;
115
192
  }
116
193
 
@@ -119,62 +196,21 @@ interface ColumnHeaderProps {
119
196
  index: number;
120
197
  isToday: boolean;
121
198
  locale: string;
199
+ resource?: Resource;
122
200
  }
123
201
  ```
124
202
 
125
- ## Custom Column Headers
126
-
127
- Transform the calendar from weekdays to any resource type:
128
-
129
- ```tsx
130
- // Padel courts booking
131
- <Calendar
132
- events={courtEvents}
133
- config={{
134
- renderColumnHeader: ({ index }) => (
135
- <div className="text-center font-semibold">
136
- Court {index + 1}
137
- </div>
138
- )
139
- }}
140
- />
141
-
142
- // Meeting rooms
143
- <Calendar
144
- events={roomEvents}
145
- config={{
146
- renderColumnHeader: ({ index }) => {
147
- const rooms = ["Sala A", "Sala B", "Sala C", "Sala D", "Sala E", "Sala F", "Sala G"];
148
- return <span>{rooms[index]}</span>;
149
- }
150
- }}
151
- />
152
-
153
- // Employees schedule
154
- <Calendar
155
- events={shifts}
156
- config={{
157
- renderColumnHeader: ({ index }) => {
158
- const team = ["Ana", "Carlos", "María", "Pedro", "Laura", "Diego", "Sofia"];
159
- return (
160
- <div className="flex flex-col items-center">
161
- <img src={`/avatars/${index}.jpg`} className="w-8 h-8 rounded-full" />
162
- <span className="text-sm">{team[index]}</span>
163
- </div>
164
- );
165
- }
166
- }}
167
- />
168
- ```
169
-
170
203
  ## Features
171
204
 
172
- - Drag & drop events between time slots
173
- - Automatic overlap detection
205
+ - Drag & drop events
206
+ - Visual overlap rendering
207
+ - Resource/day view mode
208
+ - Week view mode
209
+ - Navigation controls (hook + component)
174
210
  - Block time slots
175
- - Week navigation
176
211
  - Auto-scroll to current hour
177
- - Custom column headers (resources, courts, rooms, employees)
212
+ - Custom column headers
213
+ - Horizontal scroll for many resources
178
214
  - Customizable icons
179
215
  - Locale support
180
216
  - TypeScript support