@forcecalendar/interface 1.0.27 → 1.0.29
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 +9 -0
- package/dist/force-calendar-interface.esm.js +102 -55
- package/dist/force-calendar-interface.esm.js.map +1 -1
- package/dist/force-calendar-interface.umd.js.map +1 -1
- package/package.json +3 -1
- package/src/components/EventForm.js +180 -176
- package/src/components/ForceCalendar.js +416 -394
- package/src/core/BaseComponent.js +146 -144
- package/src/core/EventBus.js +197 -197
- package/src/core/StateManager.js +405 -399
- package/src/index.js +3 -3
- package/src/renderers/BaseViewRenderer.js +195 -193
- package/src/renderers/DayViewRenderer.js +133 -118
- package/src/renderers/MonthViewRenderer.js +74 -72
- package/src/renderers/WeekViewRenderer.js +118 -96
- package/src/utils/DOMUtils.js +277 -277
- package/src/utils/DateUtils.js +164 -164
- package/src/utils/StyleUtils.js +286 -249
package/src/utils/DateUtils.js
CHANGED
|
@@ -7,174 +7,174 @@
|
|
|
7
7
|
import { DateUtils as CoreDateUtils } from '@forcecalendar/core';
|
|
8
8
|
|
|
9
9
|
export class DateUtils extends CoreDateUtils {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Format date for display
|
|
12
|
+
*/
|
|
13
|
+
static formatDate(date, format = 'default', locale = 'en-US') {
|
|
14
|
+
if (!date) return '';
|
|
15
|
+
|
|
16
|
+
const formats = {
|
|
17
|
+
default: { year: 'numeric', month: 'long', day: 'numeric' },
|
|
18
|
+
short: { year: 'numeric', month: 'short', day: 'numeric' },
|
|
19
|
+
long: { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' },
|
|
20
|
+
month: { year: 'numeric', month: 'long' },
|
|
21
|
+
monthShort: { year: 'numeric', month: 'short' },
|
|
22
|
+
day: { weekday: 'long', day: 'numeric' },
|
|
23
|
+
dayShort: { weekday: 'short', day: 'numeric' },
|
|
24
|
+
time: { hour: 'numeric', minute: '2-digit' },
|
|
25
|
+
timeShort: { hour: 'numeric' },
|
|
26
|
+
datetime: {
|
|
27
|
+
year: 'numeric',
|
|
28
|
+
month: 'short',
|
|
29
|
+
day: 'numeric',
|
|
30
|
+
hour: 'numeric',
|
|
31
|
+
minute: '2-digit'
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const options = formats[format] || formats.default;
|
|
36
|
+
return new Intl.DateTimeFormat(locale, options).format(date);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Format time for display
|
|
41
|
+
*/
|
|
42
|
+
static formatTime(date, showMinutes = true, use24Hour = false, locale = 'en-US') {
|
|
43
|
+
if (!date) return '';
|
|
44
|
+
|
|
45
|
+
const options = {
|
|
46
|
+
hour: 'numeric',
|
|
47
|
+
minute: showMinutes ? '2-digit' : undefined,
|
|
48
|
+
hour12: !use24Hour
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return new Intl.DateTimeFormat(locale, options).format(date);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Format date range for display
|
|
56
|
+
*/
|
|
57
|
+
static formatDateRange(start, end, locale = 'en-US') {
|
|
58
|
+
if (!start) return '';
|
|
59
|
+
if (!end || this.isSameDay(start, end)) {
|
|
60
|
+
return this.formatDate(start, 'default', locale);
|
|
37
61
|
}
|
|
38
62
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
|
|
85
|
-
const diff = date - baseDate;
|
|
86
|
-
const diffInSeconds = Math.floor(diff / 1000);
|
|
87
|
-
const diffInMinutes = Math.floor(diffInSeconds / 60);
|
|
88
|
-
const diffInHours = Math.floor(diffInMinutes / 60);
|
|
89
|
-
const diffInDays = Math.floor(diffInHours / 24);
|
|
90
|
-
const diffInWeeks = Math.floor(diffInDays / 7);
|
|
91
|
-
const diffInMonths = Math.floor(diffInDays / 30);
|
|
92
|
-
const diffInYears = Math.floor(diffInDays / 365);
|
|
93
|
-
|
|
94
|
-
if (Math.abs(diffInSeconds) < 60) {
|
|
95
|
-
return rtf.format(diffInSeconds, 'second');
|
|
96
|
-
} else if (Math.abs(diffInMinutes) < 60) {
|
|
97
|
-
return rtf.format(diffInMinutes, 'minute');
|
|
98
|
-
} else if (Math.abs(diffInHours) < 24) {
|
|
99
|
-
return rtf.format(diffInHours, 'hour');
|
|
100
|
-
} else if (Math.abs(diffInDays) < 7) {
|
|
101
|
-
return rtf.format(diffInDays, 'day');
|
|
102
|
-
} else if (Math.abs(diffInWeeks) < 4) {
|
|
103
|
-
return rtf.format(diffInWeeks, 'week');
|
|
104
|
-
} else if (Math.abs(diffInMonths) < 12) {
|
|
105
|
-
return rtf.format(diffInMonths, 'month');
|
|
106
|
-
} else {
|
|
107
|
-
return rtf.format(diffInYears, 'year');
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Check if date is today
|
|
113
|
-
*/
|
|
114
|
-
static isToday(date) {
|
|
115
|
-
const today = new Date();
|
|
116
|
-
return this.isSameDay(date, today);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Check if date is in the past
|
|
121
|
-
*/
|
|
122
|
-
static isPast(date) {
|
|
123
|
-
return date < new Date();
|
|
63
|
+
const startFormat = this.isSameYear(start, end) ? 'short' : 'default';
|
|
64
|
+
return `${this.formatDate(start, startFormat, locale)} - ${this.formatDate(end, 'default', locale)}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Format time range for display
|
|
69
|
+
*/
|
|
70
|
+
static formatTimeRange(start, end, locale = 'en-US') {
|
|
71
|
+
if (!start) return '';
|
|
72
|
+
|
|
73
|
+
const startTime = this.formatTime(start, true, false, locale);
|
|
74
|
+
if (!end) return startTime;
|
|
75
|
+
|
|
76
|
+
const endTime = this.formatTime(end, true, false, locale);
|
|
77
|
+
return `${startTime} - ${endTime}`;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Get relative time string (e.g., "2 hours ago", "in 3 days")
|
|
82
|
+
*/
|
|
83
|
+
static getRelativeTime(date, baseDate = new Date(), locale = 'en-US') {
|
|
84
|
+
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: 'auto' });
|
|
85
|
+
const diff = date - baseDate;
|
|
86
|
+
const diffInSeconds = Math.floor(diff / 1000);
|
|
87
|
+
const diffInMinutes = Math.floor(diffInSeconds / 60);
|
|
88
|
+
const diffInHours = Math.floor(diffInMinutes / 60);
|
|
89
|
+
const diffInDays = Math.floor(diffInHours / 24);
|
|
90
|
+
const diffInWeeks = Math.floor(diffInDays / 7);
|
|
91
|
+
const diffInMonths = Math.floor(diffInDays / 30);
|
|
92
|
+
const diffInYears = Math.floor(diffInDays / 365);
|
|
93
|
+
|
|
94
|
+
if (Math.abs(diffInSeconds) < 60) {
|
|
95
|
+
return rtf.format(diffInSeconds, 'second');
|
|
96
|
+
} else if (Math.abs(diffInMinutes) < 60) {
|
|
97
|
+
return rtf.format(diffInMinutes, 'minute');
|
|
98
|
+
} else if (Math.abs(diffInHours) < 24) {
|
|
99
|
+
return rtf.format(diffInHours, 'hour');
|
|
100
|
+
} else if (Math.abs(diffInDays) < 7) {
|
|
101
|
+
return rtf.format(diffInDays, 'day');
|
|
102
|
+
} else if (Math.abs(diffInWeeks) < 4) {
|
|
103
|
+
return rtf.format(diffInWeeks, 'week');
|
|
104
|
+
} else if (Math.abs(diffInMonths) < 12) {
|
|
105
|
+
return rtf.format(diffInMonths, 'month');
|
|
106
|
+
} else {
|
|
107
|
+
return rtf.format(diffInYears, 'year');
|
|
124
108
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Check if date is today
|
|
113
|
+
*/
|
|
114
|
+
static isToday(date) {
|
|
115
|
+
const today = new Date();
|
|
116
|
+
return this.isSameDay(date, today);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Check if date is in the past
|
|
121
|
+
*/
|
|
122
|
+
static isPast(date) {
|
|
123
|
+
return date < new Date();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Check if date is in the future
|
|
128
|
+
*/
|
|
129
|
+
static isFuture(date) {
|
|
130
|
+
return date > new Date();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get calendar week number
|
|
135
|
+
*/
|
|
136
|
+
static getWeekNumber(date) {
|
|
137
|
+
const firstDayOfYear = new Date(date.getFullYear(), 0, 1);
|
|
138
|
+
const pastDaysOfYear = (date - firstDayOfYear) / 86400000;
|
|
139
|
+
return Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Get day abbreviation
|
|
144
|
+
*/
|
|
145
|
+
static getDayAbbreviation(dayIndex, locale = 'en-US') {
|
|
146
|
+
const date = new Date(2024, 0, 7 + dayIndex); // Jan 7, 2024 is a Sunday
|
|
147
|
+
return new Intl.DateTimeFormat(locale, { weekday: 'short' }).format(date);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Get month name
|
|
152
|
+
*/
|
|
153
|
+
static getMonthName(monthIndex, format = 'long', locale = 'en-US') {
|
|
154
|
+
const date = new Date(2024, monthIndex, 1);
|
|
155
|
+
return new Intl.DateTimeFormat(locale, { month: format }).format(date);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Parse time string (e.g., "14:30" or "2:30 PM")
|
|
160
|
+
*/
|
|
161
|
+
static parseTimeString(timeStr, baseDate = new Date()) {
|
|
162
|
+
const date = new Date(baseDate);
|
|
163
|
+
const [time, period] = timeStr.split(/\s+/);
|
|
164
|
+
const [hours, minutes] = time.split(':').map(Number);
|
|
165
|
+
|
|
166
|
+
let adjustedHours = hours;
|
|
167
|
+
if (period) {
|
|
168
|
+
if (period.toLowerCase() === 'pm' && hours < 12) {
|
|
169
|
+
adjustedHours = hours + 12;
|
|
170
|
+
} else if (period.toLowerCase() === 'am' && hours === 12) {
|
|
171
|
+
adjustedHours = 0;
|
|
172
|
+
}
|
|
140
173
|
}
|
|
141
174
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
static getDayAbbreviation(dayIndex, locale = 'en-US') {
|
|
146
|
-
const date = new Date(2024, 0, 7 + dayIndex); // Jan 7, 2024 is a Sunday
|
|
147
|
-
return new Intl.DateTimeFormat(locale, { weekday: 'short' }).format(date);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Get month name
|
|
152
|
-
*/
|
|
153
|
-
static getMonthName(monthIndex, format = 'long', locale = 'en-US') {
|
|
154
|
-
const date = new Date(2024, monthIndex, 1);
|
|
155
|
-
return new Intl.DateTimeFormat(locale, { month: format }).format(date);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Parse time string (e.g., "14:30" or "2:30 PM")
|
|
160
|
-
*/
|
|
161
|
-
static parseTimeString(timeStr, baseDate = new Date()) {
|
|
162
|
-
const date = new Date(baseDate);
|
|
163
|
-
const [time, period] = timeStr.split(/\s+/);
|
|
164
|
-
const [hours, minutes] = time.split(':').map(Number);
|
|
165
|
-
|
|
166
|
-
let adjustedHours = hours;
|
|
167
|
-
if (period) {
|
|
168
|
-
if (period.toLowerCase() === 'pm' && hours < 12) {
|
|
169
|
-
adjustedHours = hours + 12;
|
|
170
|
-
} else if (period.toLowerCase() === 'am' && hours === 12) {
|
|
171
|
-
adjustedHours = 0;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
date.setHours(adjustedHours, minutes || 0, 0, 0);
|
|
176
|
-
return date;
|
|
177
|
-
}
|
|
175
|
+
date.setHours(adjustedHours, minutes || 0, 0, 0);
|
|
176
|
+
return date;
|
|
177
|
+
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
export default DateUtils;
|
|
180
|
+
export default DateUtils;
|