resourcenest 1.2.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/CHANGELOG.md +41 -0
- package/LICENSE +21 -0
- package/README.md +324 -0
- package/dist/resourcenest.js +586 -0
- package/dist/resourcenest.umd.cjs +304 -0
- package/package.json +69 -0
- package/src/ResourceNest.js +845 -0
- package/src/index.js +10 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# @dennisthln/resourcenest
|
|
2
|
+
|
|
3
|
+
## 1.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`e7b83b6`](https://github.com/dennisthln/resourcenest/commit/e7b83b6af5a454061a6c7ddbdd01f6ad0b80a88c) - Initial release of ResourceNest - Professional Resource Calendar UI
|
|
8
|
+
|
|
9
|
+
Features:
|
|
10
|
+
|
|
11
|
+
- Timeline calendar with day, 3-day, and week views
|
|
12
|
+
- Multi-resource display for rooms, staff, and equipment
|
|
13
|
+
- Interactive time slot clicking
|
|
14
|
+
- Current time indicator
|
|
15
|
+
- Professional built-in styling
|
|
16
|
+
- Zero dependencies
|
|
17
|
+
- Framework-agnostic (Vue, React, Angular, Svelte, vanilla JS)
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- [`e7b83b6`](https://github.com/dennisthln/resourcenest/commit/e7b83b6af5a454061a6c7ddbdd01f6ad0b80a88c) - Initial changes
|
|
22
|
+
|
|
23
|
+
## 1.1.0
|
|
24
|
+
|
|
25
|
+
### Minor Changes
|
|
26
|
+
|
|
27
|
+
- [`2353fe3`](https://github.com/dennisthln/resourcenest/commit/2353fe3e2d287e92d77660bcde5b7e343b064e80) - Initial release of ResourceNest - Professional Resource Calendar UI
|
|
28
|
+
|
|
29
|
+
Features:
|
|
30
|
+
|
|
31
|
+
- Timeline calendar with day, 3-day, and week views
|
|
32
|
+
- Multi-resource display for rooms, staff, and equipment
|
|
33
|
+
- Interactive time slot clicking
|
|
34
|
+
- Current time indicator
|
|
35
|
+
- Professional built-in styling
|
|
36
|
+
- Zero dependencies
|
|
37
|
+
- Framework-agnostic (Vue, React, Angular, Svelte, vanilla JS)
|
|
38
|
+
|
|
39
|
+
### Patch Changes
|
|
40
|
+
|
|
41
|
+
- [`2353fe3`](https://github.com/dennisthln/resourcenest/commit/2353fe3e2d287e92d77660bcde5b7e343b064e80) - Initial changes
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 dennisthln
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# ResourceNest
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@dennisthln/resourcenest)
|
|
4
|
+
[](https://www.npmjs.com/package/@dennisthln/resourcenest)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://github.com/dennisthln/resourcenest)
|
|
7
|
+
|
|
8
|
+
**Resource Calendar UI** - Professional timeline interface for displaying and managing room bookings, staff schedules, equipment allocation & appointments. Beautiful, responsive, framework-agnostic calendar for your resource planning system.
|
|
9
|
+
|
|
10
|
+
Works with **any framework**: Vue, React, Angular, Svelte, or plain HTML.
|
|
11
|
+
|
|
12
|
+
**[📖 Demo & Documentation](https://dennisthln.github.io/resourcenest)** | **[📦 npm Package](https://www.npmjs.com/package/@dennisthln/resourcenest)** | **[🐙 GitHub](https://github.com/dennisthln/resourcenest)**
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 📌 About ResourceNest
|
|
17
|
+
|
|
18
|
+
**ResourceNest is the visual layer** for your resource management system. It's a beautiful, professional calendar UI that displays scheduling data and provides an interface for interactions.
|
|
19
|
+
|
|
20
|
+
### ✅ What ResourceNest Does
|
|
21
|
+
- 📅 Displays resources and bookings in an intuitive timeline format
|
|
22
|
+
- 🎯 Provides visual feedback for time slots and events
|
|
23
|
+
- 📍 Captures user interactions (clicks on slots, events, navigation)
|
|
24
|
+
- 🎨 Handles responsive design and styling
|
|
25
|
+
- 🔌 Works seamlessly with your backend scheduling logic
|
|
26
|
+
|
|
27
|
+
### ❌ What ResourceNest Does NOT Do
|
|
28
|
+
- 🤖 It doesn't schedule or plan resources (your backend does that)
|
|
29
|
+
- 🚫 It doesn't detect conflicts automatically (your system validates that)
|
|
30
|
+
- 💡 It doesn't optimize allocations (that's your algorithm)
|
|
31
|
+
- 🔄 It doesn't manage complex scheduling rules
|
|
32
|
+
|
|
33
|
+
**Think of it as:** The beautiful dashboard/UI that displays *your* scheduling system's results.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
- 📅 **Professional Timeline Views** - Day, 3-day, and week views for resource scheduling
|
|
40
|
+
- 👥 **Multi-Resource Display** - Show rooms, staff, equipment as timeline rows
|
|
41
|
+
- 🏢 **Event Visualization** - Display bookings, appointments, and assignments with custom styling
|
|
42
|
+
- 📍 **Interactive Slots** - Click on timeline to trigger custom actions (create booking, etc.)
|
|
43
|
+
- ⏰ **Current Time Indicator** - Visual red line showing current time for context
|
|
44
|
+
- 🎨 **Built-in Professional Styling** - Beautiful calendar out of the box, fully customizable CSS
|
|
45
|
+
- 📱 **Responsive & Touch-Ready** - Perfect on desktop, tablet, and mobile devices
|
|
46
|
+
- 🚀 **Zero Dependencies** - Lightweight, fast vanilla JavaScript
|
|
47
|
+
- 🌐 **Framework-Agnostic** - Works with Vue, React, Angular, Svelte, or plain HTML
|
|
48
|
+
- ⚙️ **Easy Integration** - Simple API to connect with your backend scheduling logic
|
|
49
|
+
- 💼 **Perfect For** - Meeting room displays, team schedules, appointment calendars, resource management dashboards
|
|
50
|
+
|
|
51
|
+
## Installation
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
yarn add @dennisthln/resourcenest
|
|
55
|
+
# or
|
|
56
|
+
npm install @dennisthln/resourcenest
|
|
57
|
+
# or
|
|
58
|
+
bun add @dennisthln/resourcenest
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
63
|
+
### Plain HTML / Vanilla JS
|
|
64
|
+
|
|
65
|
+
```html
|
|
66
|
+
<!DOCTYPE html>
|
|
67
|
+
<html>
|
|
68
|
+
<head>
|
|
69
|
+
<title>Timeline Calendar</title>
|
|
70
|
+
</head>
|
|
71
|
+
<body>
|
|
72
|
+
<div id="calendar"></div>
|
|
73
|
+
|
|
74
|
+
<script type="module">
|
|
75
|
+
import createResourceNest from '@dennisthln/resourcenest';
|
|
76
|
+
|
|
77
|
+
const calendar = createResourceNest('#calendar', {
|
|
78
|
+
resources: [
|
|
79
|
+
{ id: 'room-1', name: 'Conference Room A' },
|
|
80
|
+
{ id: 'room-2', name: 'Conference Room B' },
|
|
81
|
+
],
|
|
82
|
+
events: [
|
|
83
|
+
{
|
|
84
|
+
id: '1',
|
|
85
|
+
resourceId: 'room-1',
|
|
86
|
+
from: '2024-01-15T10:00:00',
|
|
87
|
+
to: '2024-01-15T11:30:00',
|
|
88
|
+
label: 'Team Meeting',
|
|
89
|
+
guestCount: 5,
|
|
90
|
+
status: 'Confirmed'
|
|
91
|
+
}
|
|
92
|
+
],
|
|
93
|
+
onEventClick: (event) => {
|
|
94
|
+
console.log('Event clicked:', event);
|
|
95
|
+
},
|
|
96
|
+
onTimeClick: ({ time, resource }) => {
|
|
97
|
+
console.log('Book time slot at:', time, 'for resource:', resource);
|
|
98
|
+
},
|
|
99
|
+
onDateChange: (dateStr) => {
|
|
100
|
+
console.log('Date changed to:', dateStr);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
</script>
|
|
104
|
+
</body>
|
|
105
|
+
</html>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Vue 3
|
|
109
|
+
|
|
110
|
+
Create a wrapper component:
|
|
111
|
+
|
|
112
|
+
```vue
|
|
113
|
+
<script setup>
|
|
114
|
+
import { ref, onMounted, onUnmounted, watch } from 'vue';
|
|
115
|
+
import createTimelineCalendar from '@kleverweb/timeline-calendar/src';
|
|
116
|
+
|
|
117
|
+
const props = defineProps({
|
|
118
|
+
events: { type: Array, default: () => [] },
|
|
119
|
+
resources: { type: Array, default: () => [] },
|
|
120
|
+
loading: { type: Boolean, default: false },
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const emit = defineEmits(['event-click', 'time-click', 'date-change']);
|
|
124
|
+
|
|
125
|
+
const containerRef = ref(null);
|
|
126
|
+
let calendar = null;
|
|
127
|
+
|
|
128
|
+
onMounted(() => {
|
|
129
|
+
calendar = createTimelineCalendar(containerRef.value, {
|
|
130
|
+
events: props.events,
|
|
131
|
+
resources: props.resources,
|
|
132
|
+
onEventClick: (event) => emit('event-click', event),
|
|
133
|
+
onTimeClick: (data) => emit('time-click', data),
|
|
134
|
+
onDateChange: (date) => emit('date-change', date),
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
onUnmounted(() => calendar?.destroy());
|
|
139
|
+
|
|
140
|
+
watch(() => props.events, (v) => calendar?.setEvents(v), { deep: true });
|
|
141
|
+
watch(() => props.resources, (v) => calendar?.setResources(v), { deep: true });
|
|
142
|
+
watch(() => props.loading, (v) => calendar?.setLoading(v));
|
|
143
|
+
</script>
|
|
144
|
+
|
|
145
|
+
<template>
|
|
146
|
+
<div ref="containerRef"></div>
|
|
147
|
+
</template>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### React
|
|
151
|
+
|
|
152
|
+
```jsx
|
|
153
|
+
import { useEffect, useRef } from 'react';
|
|
154
|
+
import createTimelineCalendar from '@kleverweb/timeline-calendar';
|
|
155
|
+
|
|
156
|
+
function TimelineCalendar({ events, resources, onEventClick, onTimeClick, onDateChange }) {
|
|
157
|
+
const containerRef = useRef(null);
|
|
158
|
+
const calendarRef = useRef(null);
|
|
159
|
+
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
calendarRef.current = createTimelineCalendar(containerRef.current, {
|
|
162
|
+
events,
|
|
163
|
+
resources,
|
|
164
|
+
onEventClick,
|
|
165
|
+
onTimeClick,
|
|
166
|
+
onDateChange,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
return () => calendarRef.current?.destroy();
|
|
170
|
+
}, []);
|
|
171
|
+
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
calendarRef.current?.setEvents(events);
|
|
174
|
+
}, [events]);
|
|
175
|
+
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
calendarRef.current?.setResources(resources);
|
|
178
|
+
}, [resources]);
|
|
179
|
+
|
|
180
|
+
return <div ref={containerRef} />;
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## API
|
|
185
|
+
|
|
186
|
+
### `createTimelineCalendar(selector, options)`
|
|
187
|
+
|
|
188
|
+
Creates a new calendar instance.
|
|
189
|
+
|
|
190
|
+
**Parameters:**
|
|
191
|
+
- `selector` - CSS selector string or DOM element
|
|
192
|
+
- `options` - Configuration object (see below)
|
|
193
|
+
|
|
194
|
+
**Returns:** Calendar instance with methods
|
|
195
|
+
|
|
196
|
+
### Options
|
|
197
|
+
|
|
198
|
+
| Option | Type | Default | Description |
|
|
199
|
+
|--------|------|---------|-------------|
|
|
200
|
+
| `events` | `Array` | `[]` | Array of event objects |
|
|
201
|
+
| `resources` | `Array` | `[]` | Array of resource objects (rows) |
|
|
202
|
+
| `startHour` | `Number` | `8` | First hour to display (0-23) |
|
|
203
|
+
| `endHour` | `Number` | `22` | Last hour to display (0-23) |
|
|
204
|
+
| `dateFormat` | `String` | `'DD.MM.YYYY'` | Date format for header |
|
|
205
|
+
| `todayLabel` | `String` | `'Heute'` | Label for today button |
|
|
206
|
+
| `loadingLabel` | `String` | `'Laden...'` | Loading overlay text |
|
|
207
|
+
| `showNavigation` | `Boolean` | `true` | Show navigation buttons |
|
|
208
|
+
| `showNowIndicator` | `Boolean` | `true` | Show current time line |
|
|
209
|
+
| `eventClickable` | `Boolean` | `true` | Enable event click |
|
|
210
|
+
| `timeClickable` | `Boolean` | `true` | Enable time slot click |
|
|
211
|
+
| `onEventClick` | `Function` | `null` | Callback when event is clicked |
|
|
212
|
+
| `onTimeClick` | `Function` | `null` | Callback when time slot is clicked |
|
|
213
|
+
| `onDateChange` | `Function` | `null` | Callback when date changes |
|
|
214
|
+
|
|
215
|
+
### Event Object
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
{
|
|
219
|
+
id: 'unique-id',
|
|
220
|
+
resourceId: 'resource-id', // or serviceResourceId
|
|
221
|
+
from: '2024-01-15T10:00:00', // ISO string or Date
|
|
222
|
+
to: '2024-01-15T11:30:00',
|
|
223
|
+
label: 'Event Title',
|
|
224
|
+
guestCount: 5, // optional
|
|
225
|
+
status: 'Confirmed' // 'Confirmed', 'Cancelled', or custom
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Resource Object
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
{
|
|
233
|
+
id: 'resource-id',
|
|
234
|
+
name: 'Resource Name'
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Instance Methods
|
|
239
|
+
|
|
240
|
+
```js
|
|
241
|
+
const calendar = createTimelineCalendar('#calendar', options);
|
|
242
|
+
|
|
243
|
+
// Navigation
|
|
244
|
+
calendar.goToToday();
|
|
245
|
+
calendar.nextDay();
|
|
246
|
+
calendar.prevDay();
|
|
247
|
+
calendar.setDate('2024-06-15');
|
|
248
|
+
calendar.getDate(); // Returns current Date
|
|
249
|
+
|
|
250
|
+
// Data
|
|
251
|
+
calendar.setEvents([...]);
|
|
252
|
+
calendar.setResources([...]);
|
|
253
|
+
|
|
254
|
+
// UI
|
|
255
|
+
calendar.setLoading(true);
|
|
256
|
+
calendar.scrollToNow();
|
|
257
|
+
calendar.refresh();
|
|
258
|
+
|
|
259
|
+
// Callbacks (chainable)
|
|
260
|
+
calendar.onEventClick(callback);
|
|
261
|
+
calendar.onTimeClick(callback);
|
|
262
|
+
calendar.onDateChange(callback);
|
|
263
|
+
|
|
264
|
+
// Cleanup
|
|
265
|
+
calendar.destroy();
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Callback Signatures
|
|
269
|
+
|
|
270
|
+
```js
|
|
271
|
+
onEventClick(originalEvent, normalizedEvent)
|
|
272
|
+
// originalEvent: Your original event data
|
|
273
|
+
// normalizedEvent: { id, resourceId, from, to, label, guestCount, status, data }
|
|
274
|
+
|
|
275
|
+
onTimeClick({ time, date, resource })
|
|
276
|
+
// time: ISO string of clicked time
|
|
277
|
+
// date: Date object
|
|
278
|
+
// resource: The resource object for the clicked row
|
|
279
|
+
|
|
280
|
+
onDateChange(dateString, date)
|
|
281
|
+
// dateString: 'YYYY-MM-DD' format
|
|
282
|
+
// date: Date object
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Styling
|
|
286
|
+
|
|
287
|
+
The calendar includes built-in styles. To customize, override CSS classes:
|
|
288
|
+
|
|
289
|
+
```css
|
|
290
|
+
/* Primary color for events */
|
|
291
|
+
.kw-event {
|
|
292
|
+
background: #your-color;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/* Confirmed events */
|
|
296
|
+
.kw-event.status-confirmed {
|
|
297
|
+
background: #10b981;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/* Cancelled events */
|
|
301
|
+
.kw-event.status-cancelled {
|
|
302
|
+
background: #ef4444;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* Current time indicator */
|
|
306
|
+
.kw-now-indicator {
|
|
307
|
+
background: #ef4444;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/* Current hour highlight */
|
|
311
|
+
.kw-hour-cell.is-current,
|
|
312
|
+
.kw-timeline-cell.is-current {
|
|
313
|
+
background: #dbeafe;
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## Browser Support
|
|
318
|
+
|
|
319
|
+
Works in all modern browsers (Chrome, Firefox, Safari, Edge).
|
|
320
|
+
|
|
321
|
+
## License
|
|
322
|
+
|
|
323
|
+
MIT
|
|
324
|
+
|