@reachweb/alpine-calendar 0.1.1
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 +645 -0
- package/dist/alpine-calendar.cdn.js +2 -0
- package/dist/alpine-calendar.cdn.js.map +1 -0
- package/dist/alpine-calendar.css +1 -0
- package/dist/alpine-calendar.es.js +2946 -0
- package/dist/alpine-calendar.es.js.map +1 -0
- package/dist/alpine-calendar.umd.js +2 -0
- package/dist/alpine-calendar.umd.js.map +1 -0
- package/dist/cdn.d.ts +6 -0
- package/dist/core/calendar-date.d.ts +58 -0
- package/dist/core/constraints.d.ts +193 -0
- package/dist/core/grid.d.ts +81 -0
- package/dist/core/presets.d.ts +84 -0
- package/dist/core/selection.d.ts +88 -0
- package/dist/index.d.ts +39 -0
- package/dist/input/formatter.d.ts +36 -0
- package/dist/input/mask.d.ts +62 -0
- package/dist/input/parser.d.ts +30 -0
- package/dist/plugin/calendar-component.d.ts +506 -0
- package/dist/plugin/template.d.ts +11 -0
- package/dist/positioning/popup.d.ts +52 -0
- package/package.json +86 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CalendarDate — a timezone-safe date value object.
|
|
3
|
+
*
|
|
4
|
+
* Stores year/month/day as plain integers. No internal `Date` object.
|
|
5
|
+
* The only place we touch native `Date` / `Intl.DateTimeFormat` is in
|
|
6
|
+
* `toNativeDate()`, `fromNativeDate()`, `today()`, and `format()`.
|
|
7
|
+
*/
|
|
8
|
+
export declare class CalendarDate {
|
|
9
|
+
readonly year: number;
|
|
10
|
+
readonly month: number;
|
|
11
|
+
readonly day: number;
|
|
12
|
+
constructor(year: number, month: number, day: number);
|
|
13
|
+
/** Resolve "today" in a given IANA timezone (fallback: browser default). */
|
|
14
|
+
static today(timezone?: string): CalendarDate;
|
|
15
|
+
/** Create from a native Date, interpreting it in the given timezone. */
|
|
16
|
+
static fromNativeDate(date: Date, timezone?: string): CalendarDate;
|
|
17
|
+
/** Create from an ISO string (YYYY-MM-DD). Returns null for invalid formats or out-of-range values. */
|
|
18
|
+
static fromISO(iso: string): CalendarDate | null;
|
|
19
|
+
/** Convert to a native Date (midnight local time). */
|
|
20
|
+
toNativeDate(): Date;
|
|
21
|
+
/** Serialize to ISO string YYYY-MM-DD. */
|
|
22
|
+
toISO(): string;
|
|
23
|
+
/** Unique string key for use in Sets/Maps. */
|
|
24
|
+
toKey(): string;
|
|
25
|
+
isSame(other: CalendarDate): boolean;
|
|
26
|
+
isBefore(other: CalendarDate): boolean;
|
|
27
|
+
isAfter(other: CalendarDate): boolean;
|
|
28
|
+
/** Inclusive range check: start <= this <= end. */
|
|
29
|
+
isBetween(start: CalendarDate, end: CalendarDate): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Number of days from this date to another.
|
|
32
|
+
* Positive when `other` is after `this`, negative when before.
|
|
33
|
+
* Uses UTC to avoid DST issues.
|
|
34
|
+
*/
|
|
35
|
+
diffDays(other: CalendarDate): number;
|
|
36
|
+
addDays(days: number): CalendarDate;
|
|
37
|
+
/** Add months with day clamping (e.g. Jan 31 + 1 month = Feb 28/29). */
|
|
38
|
+
addMonths(months: number): CalendarDate;
|
|
39
|
+
addYears(years: number): CalendarDate;
|
|
40
|
+
startOfMonth(): CalendarDate;
|
|
41
|
+
endOfMonth(): CalendarDate;
|
|
42
|
+
/**
|
|
43
|
+
* Format the date using Intl.DateTimeFormat options.
|
|
44
|
+
*
|
|
45
|
+
* @param options - Intl.DateTimeFormat options (e.g. { month: 'long', year: 'numeric' })
|
|
46
|
+
* @param locale - BCP 47 locale string (default: browser locale)
|
|
47
|
+
*/
|
|
48
|
+
format(options: Intl.DateTimeFormatOptions, locale?: string): string;
|
|
49
|
+
}
|
|
50
|
+
/** Return the number of days in a given month (1-12). */
|
|
51
|
+
export declare function daysInMonth(year: number, month: number): number;
|
|
52
|
+
/**
|
|
53
|
+
* Return the ISO 8601 week number for a given date.
|
|
54
|
+
*
|
|
55
|
+
* ISO weeks start on Monday. Week 1 is the week containing the year's first Thursday.
|
|
56
|
+
* Returns a number between 1 and 53.
|
|
57
|
+
*/
|
|
58
|
+
export declare function getISOWeekNumber(date: CalendarDate): number;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { CalendarDate } from './calendar-date';
|
|
2
|
+
/**
|
|
3
|
+
* Constraint properties that can be set globally or overridden per rule.
|
|
4
|
+
*
|
|
5
|
+
* All properties are optional — only specified constraints are enforced.
|
|
6
|
+
*/
|
|
7
|
+
export interface DateConstraintProperties {
|
|
8
|
+
/** Earliest selectable date (inclusive). */
|
|
9
|
+
minDate?: CalendarDate;
|
|
10
|
+
/** Latest selectable date (inclusive). */
|
|
11
|
+
maxDate?: CalendarDate;
|
|
12
|
+
/** Specific dates to disable (blacklist). */
|
|
13
|
+
disabledDates?: CalendarDate[];
|
|
14
|
+
/** Days of the week to disable (0 = Sunday, 1 = Monday, …, 6 = Saturday). */
|
|
15
|
+
disabledDaysOfWeek?: number[];
|
|
16
|
+
/** Specific dates to force-enable (overrides disabledDates and disabledDaysOfWeek). */
|
|
17
|
+
enabledDates?: CalendarDate[];
|
|
18
|
+
/** Days of the week to enable (whitelist — all other days are disabled). */
|
|
19
|
+
enabledDaysOfWeek?: number[];
|
|
20
|
+
/** Specific months to disable (1 = January, …, 12 = December). */
|
|
21
|
+
disabledMonths?: number[];
|
|
22
|
+
/** Months to enable (whitelist — all other months are disabled). */
|
|
23
|
+
enabledMonths?: number[];
|
|
24
|
+
/** Specific years to disable. */
|
|
25
|
+
disabledYears?: number[];
|
|
26
|
+
/** Years to enable (whitelist — all other years are disabled). */
|
|
27
|
+
enabledYears?: number[];
|
|
28
|
+
/** Minimum range length in days (inclusive). Only used in range mode. */
|
|
29
|
+
minRange?: number;
|
|
30
|
+
/** Maximum range length in days (inclusive). Only used in range mode. */
|
|
31
|
+
maxRange?: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A period-specific constraint rule that overrides global settings.
|
|
35
|
+
*
|
|
36
|
+
* When checking a date, matching rules are resolved by priority (highest wins).
|
|
37
|
+
* Among rules with equal priority, the first matching rule wins (array order).
|
|
38
|
+
* Unset properties inherit from the global configuration.
|
|
39
|
+
*
|
|
40
|
+
* Rules can match by date range (`from`/`to`) or by recurring months
|
|
41
|
+
* (`months`). If `months` is set, the rule applies to those months
|
|
42
|
+
* every year without needing explicit date ranges.
|
|
43
|
+
*/
|
|
44
|
+
export interface DateConstraintRule extends DateConstraintProperties {
|
|
45
|
+
/** Start of the period this rule applies to (inclusive). */
|
|
46
|
+
from?: CalendarDate;
|
|
47
|
+
/** End of the period this rule applies to (inclusive). */
|
|
48
|
+
to?: CalendarDate;
|
|
49
|
+
/** Recurring months this rule applies to (1=Jan, …, 12=Dec). Matches every year. */
|
|
50
|
+
months?: number[];
|
|
51
|
+
/** Priority for conflict resolution. Higher values win. Default: 0. */
|
|
52
|
+
priority?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Full constraint configuration with global defaults and optional period rules.
|
|
56
|
+
*
|
|
57
|
+
* Backward compatible: all original properties (minDate, maxDate,
|
|
58
|
+
* disabledDates, disabledDaysOfWeek) continue to work as before.
|
|
59
|
+
*/
|
|
60
|
+
export interface DateConstraintOptions extends DateConstraintProperties {
|
|
61
|
+
/** Period-specific constraint overrides. Highest priority matching rule wins; ties broken by array order. */
|
|
62
|
+
rules?: DateConstraintRule[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create a single `isDateDisabled` function from a set of constraint options.
|
|
66
|
+
*
|
|
67
|
+
* The returned function checks all configured constraints (including
|
|
68
|
+
* period-specific rules) and returns `true` if the date should be
|
|
69
|
+
* disabled (not selectable).
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* const isDisabled = createDateConstraint({
|
|
74
|
+
* minDate: new CalendarDate(2025, 1, 1),
|
|
75
|
+
* maxDate: new CalendarDate(2025, 12, 31),
|
|
76
|
+
* disabledDaysOfWeek: [0, 6],
|
|
77
|
+
* rules: [{
|
|
78
|
+
* from: new CalendarDate(2025, 6, 1),
|
|
79
|
+
* to: new CalendarDate(2025, 8, 31),
|
|
80
|
+
* enabledDaysOfWeek: [1, 2, 3, 4, 5], // weekdays only in summer
|
|
81
|
+
* }],
|
|
82
|
+
* })
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare function createDateConstraint(options: DateConstraintOptions): (date: CalendarDate) => boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Create a range validation function.
|
|
88
|
+
*
|
|
89
|
+
* Returns a function that checks whether a range [start, end] satisfies
|
|
90
|
+
* the minRange/maxRange constraints. Rule matching is based on the
|
|
91
|
+
* start date — the rule that contains the start date determines the
|
|
92
|
+
* applicable range limits.
|
|
93
|
+
*
|
|
94
|
+
* Range length is counted inclusively: a range from Jan 1 to Jan 3 is
|
|
95
|
+
* 3 days long.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* const isValid = createRangeValidator({
|
|
100
|
+
* minRange: 3,
|
|
101
|
+
* maxRange: 14,
|
|
102
|
+
* rules: [{
|
|
103
|
+
* from: new CalendarDate(2025, 5, 1),
|
|
104
|
+
* to: new CalendarDate(2025, 10, 31),
|
|
105
|
+
* minRange: 5, // stricter minimum in summer
|
|
106
|
+
* }],
|
|
107
|
+
* })
|
|
108
|
+
*
|
|
109
|
+
* isValid(new CalendarDate(2025, 3, 1), new CalendarDate(2025, 3, 3)) // true (3 >= 3)
|
|
110
|
+
* isValid(new CalendarDate(2025, 6, 1), new CalendarDate(2025, 6, 3)) // false (3 < 5)
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export declare function createRangeValidator(options: DateConstraintOptions): (start: CalendarDate, end: CalendarDate) => boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Create a single `isMonthDisabled` function from constraint options.
|
|
116
|
+
*
|
|
117
|
+
* A month is disabled when:
|
|
118
|
+
* 1. The entire month falls outside [minDate, maxDate].
|
|
119
|
+
* 2. The year is disabled (via disabledYears or not in enabledYears).
|
|
120
|
+
* 3. The month number is disabled (via disabledMonths or not in enabledMonths).
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```ts
|
|
124
|
+
* const isDisabled = createMonthConstraint({
|
|
125
|
+
* minDate: new CalendarDate(2025, 3, 1),
|
|
126
|
+
* disabledMonths: [1, 2], // no January or February
|
|
127
|
+
* })
|
|
128
|
+
* isDisabled(2025, 1) // true (January disabled)
|
|
129
|
+
* isDisabled(2025, 6) // false
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export declare function createMonthConstraint(options: DateConstraintOptions): (year: number, month: number) => boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Create a single `isYearDisabled` function from constraint options.
|
|
135
|
+
*
|
|
136
|
+
* A year is disabled when:
|
|
137
|
+
* 1. The entire year falls outside [minDate, maxDate].
|
|
138
|
+
* 2. The year is in disabledYears or not in enabledYears.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* const isDisabled = createYearConstraint({
|
|
143
|
+
* disabledYears: [2020, 2021],
|
|
144
|
+
* })
|
|
145
|
+
* isDisabled(2020) // true
|
|
146
|
+
* isDisabled(2025) // false
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export declare function createYearConstraint(options: DateConstraintOptions): (year: number) => boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Standalone check: is a date disabled by the given constraints?
|
|
152
|
+
*
|
|
153
|
+
* Convenience wrapper around `createDateConstraint` for one-off checks.
|
|
154
|
+
*/
|
|
155
|
+
export declare function isDateDisabled(date: CalendarDate, options: DateConstraintOptions): boolean;
|
|
156
|
+
/**
|
|
157
|
+
* Custom messages for each constraint reason. All properties are optional —
|
|
158
|
+
* defaults are used for any omitted keys.
|
|
159
|
+
*/
|
|
160
|
+
export interface ConstraintMessages {
|
|
161
|
+
beforeMinDate?: string;
|
|
162
|
+
afterMaxDate?: string;
|
|
163
|
+
disabledDate?: string;
|
|
164
|
+
disabledDayOfWeek?: string;
|
|
165
|
+
disabledMonth?: string;
|
|
166
|
+
disabledYear?: string;
|
|
167
|
+
notEnabledDate?: string;
|
|
168
|
+
notEnabledDayOfWeek?: string;
|
|
169
|
+
notEnabledMonth?: string;
|
|
170
|
+
notEnabledYear?: string;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Create a function that returns human-readable reasons why a date is
|
|
174
|
+
* disabled. Returns an empty array for enabled dates.
|
|
175
|
+
*
|
|
176
|
+
* Uses the same logic as `createDateConstraint` (including period-specific
|
|
177
|
+
* rules) but produces descriptive messages instead of a boolean.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* const getReasons = createDisabledReasons({
|
|
182
|
+
* minDate: new CalendarDate(2025, 3, 1),
|
|
183
|
+
* disabledDaysOfWeek: [0, 6],
|
|
184
|
+
* })
|
|
185
|
+
* getReasons(new CalendarDate(2025, 2, 28))
|
|
186
|
+
* // → ['Before the earliest available date']
|
|
187
|
+
* getReasons(new CalendarDate(2025, 3, 1))
|
|
188
|
+
* // → [] (enabled)
|
|
189
|
+
* getReasons(new CalendarDate(2025, 3, 2))
|
|
190
|
+
* // → ['This day of the week is not available'] (Sunday)
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
export declare function createDisabledReasons(options: DateConstraintOptions, messages?: ConstraintMessages): (date: CalendarDate) => string[];
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { CalendarDate } from './calendar-date';
|
|
2
|
+
/** Metadata for a single day cell in the calendar grid. */
|
|
3
|
+
export interface DayCell {
|
|
4
|
+
date: CalendarDate;
|
|
5
|
+
isCurrentMonth: boolean;
|
|
6
|
+
isToday: boolean;
|
|
7
|
+
isDisabled: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** A single month grid: always 6 rows × 7 cols. */
|
|
10
|
+
export interface MonthGrid {
|
|
11
|
+
year: number;
|
|
12
|
+
month: number;
|
|
13
|
+
rows: DayCell[][];
|
|
14
|
+
/** ISO 8601 week numbers — one per row (6 entries). */
|
|
15
|
+
weekNumbers: number[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Generate a 6×7 calendar grid for a given month.
|
|
19
|
+
*
|
|
20
|
+
* @param year - Full year (e.g. 2025)
|
|
21
|
+
* @param month - Month 1-12
|
|
22
|
+
* @param firstDayOfWeek - 0 = Sunday, 1 = Monday, …, 6 = Saturday
|
|
23
|
+
* @param today - Reference date for "isToday" marking (defaults to CalendarDate.today())
|
|
24
|
+
* @param isDisabled - Optional callback to mark dates as disabled
|
|
25
|
+
*/
|
|
26
|
+
export declare function generateMonth(year: number, month: number, firstDayOfWeek?: number, today?: CalendarDate, isDisabled?: (date: CalendarDate) => boolean): MonthGrid;
|
|
27
|
+
/** Metadata for a single month cell in the month picker view. */
|
|
28
|
+
export interface MonthCell {
|
|
29
|
+
/** Month number (1-12). */
|
|
30
|
+
month: number;
|
|
31
|
+
/** Year for this cell. */
|
|
32
|
+
year: number;
|
|
33
|
+
/** Localized short month label (e.g. "Jan"). */
|
|
34
|
+
label: string;
|
|
35
|
+
/** Whether this is the current month (today's month and year). */
|
|
36
|
+
isCurrentMonth: boolean;
|
|
37
|
+
/** Whether this entire month is outside the selectable range. */
|
|
38
|
+
isDisabled: boolean;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Generate a 3×4 grid of months for the month picker view.
|
|
42
|
+
*
|
|
43
|
+
* @param year - Year to display
|
|
44
|
+
* @param today - Reference date for "isCurrentMonth" marking
|
|
45
|
+
* @param locale - BCP 47 locale for month labels
|
|
46
|
+
* @param isMonthDisabled - Optional callback to check if a month should be disabled
|
|
47
|
+
*/
|
|
48
|
+
export declare function generateMonthGrid(year: number, today?: CalendarDate, locale?: string, isMonthDisabled?: (year: number, month: number) => boolean): MonthCell[][];
|
|
49
|
+
/** Metadata for a single year cell in the year picker view. */
|
|
50
|
+
export interface YearCell {
|
|
51
|
+
/** Full year number (e.g. 2026). */
|
|
52
|
+
year: number;
|
|
53
|
+
/** Year as string label. */
|
|
54
|
+
label: string;
|
|
55
|
+
/** Whether this is the current year (today's year). */
|
|
56
|
+
isCurrentYear: boolean;
|
|
57
|
+
/** Whether this entire year is outside the selectable range. */
|
|
58
|
+
isDisabled: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Generate a 3×4 grid of years for the year picker view.
|
|
62
|
+
*
|
|
63
|
+
* Shows 12 consecutive years in a block aligned to multiples of 12.
|
|
64
|
+
* For example, if centerYear is 2026, the grid shows 2016–2027.
|
|
65
|
+
*
|
|
66
|
+
* @param centerYear - Year to determine which 12-year block to display
|
|
67
|
+
* @param today - Reference date for "isCurrentYear" marking
|
|
68
|
+
* @param isYearDisabled - Optional callback to check if a year should be disabled
|
|
69
|
+
*/
|
|
70
|
+
export declare function generateYearGrid(centerYear: number, today?: CalendarDate, isYearDisabled?: (year: number) => boolean): YearCell[][];
|
|
71
|
+
/**
|
|
72
|
+
* Generate `count` consecutive month grids starting from year/month.
|
|
73
|
+
*
|
|
74
|
+
* @param year - Starting year
|
|
75
|
+
* @param month - Starting month (1-12)
|
|
76
|
+
* @param count - Number of months to generate (e.g. 1 or 2)
|
|
77
|
+
* @param firstDayOfWeek - 0 = Sunday, 1 = Monday, …
|
|
78
|
+
* @param today - Reference for "isToday"
|
|
79
|
+
* @param isDisabled - Optional disabled callback
|
|
80
|
+
*/
|
|
81
|
+
export declare function generateMonths(year: number, month: number, count: number, firstDayOfWeek?: number, today?: CalendarDate, isDisabled?: (date: CalendarDate) => boolean): MonthGrid[];
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { CalendarDate } from './calendar-date';
|
|
2
|
+
/**
|
|
3
|
+
* A predefined date range shortcut (e.g., "Today", "Last 7 Days").
|
|
4
|
+
*
|
|
5
|
+
* Re-exported from the component module for convenience — this is the
|
|
6
|
+
* canonical definition of the interface used by both core and plugin.
|
|
7
|
+
*/
|
|
8
|
+
export interface RangePreset {
|
|
9
|
+
/** Display label for the preset button. */
|
|
10
|
+
label: string;
|
|
11
|
+
/**
|
|
12
|
+
* Function that returns a `[start, end]` date pair.
|
|
13
|
+
* Called at click time so "Today", "Last 7 Days", etc. stay current.
|
|
14
|
+
*/
|
|
15
|
+
value: () => [CalendarDate, CalendarDate];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create a "Today" preset — selects today as a single-day range.
|
|
19
|
+
*
|
|
20
|
+
* @param label - Custom label (default: "Today")
|
|
21
|
+
* @param timezone - IANA timezone for resolving today
|
|
22
|
+
*/
|
|
23
|
+
export declare function presetToday(label?: string, timezone?: string): RangePreset;
|
|
24
|
+
/**
|
|
25
|
+
* Create a "Yesterday" preset — selects yesterday as a single-day range.
|
|
26
|
+
*
|
|
27
|
+
* @param label - Custom label (default: "Yesterday")
|
|
28
|
+
* @param timezone - IANA timezone for resolving today
|
|
29
|
+
*/
|
|
30
|
+
export declare function presetYesterday(label?: string, timezone?: string): RangePreset;
|
|
31
|
+
/**
|
|
32
|
+
* Create a "Last N Days" preset — selects from (today - N + 1) to today.
|
|
33
|
+
*
|
|
34
|
+
* @param days - Number of days (inclusive)
|
|
35
|
+
* @param label - Custom label (default: "Last {days} Days")
|
|
36
|
+
* @param timezone - IANA timezone for resolving today
|
|
37
|
+
*/
|
|
38
|
+
export declare function presetLastNDays(days: number, label?: string, timezone?: string): RangePreset;
|
|
39
|
+
/**
|
|
40
|
+
* Create a "This Week" preset — selects from the start of the current week to today.
|
|
41
|
+
* Weeks start on the given `firstDay` (0=Sun, 1=Mon, default: 1).
|
|
42
|
+
*
|
|
43
|
+
* @param label - Custom label (default: "This Week")
|
|
44
|
+
* @param firstDay - First day of the week (0=Sun, 1=Mon; default: 1)
|
|
45
|
+
* @param timezone - IANA timezone for resolving today
|
|
46
|
+
*/
|
|
47
|
+
export declare function presetThisWeek(label?: string, firstDay?: number, timezone?: string): RangePreset;
|
|
48
|
+
/**
|
|
49
|
+
* Create a "Last Week" preset — selects the full 7-day week before the current week.
|
|
50
|
+
* Weeks start on the given `firstDay` (0=Sun, 1=Mon, default: 1).
|
|
51
|
+
*
|
|
52
|
+
* @param label - Custom label (default: "Last Week")
|
|
53
|
+
* @param firstDay - First day of the week (0=Sun, 1=Mon; default: 1)
|
|
54
|
+
* @param timezone - IANA timezone for resolving today
|
|
55
|
+
*/
|
|
56
|
+
export declare function presetLastWeek(label?: string, firstDay?: number, timezone?: string): RangePreset;
|
|
57
|
+
/**
|
|
58
|
+
* Create a "This Month" preset — selects from the 1st of the current month to today.
|
|
59
|
+
*
|
|
60
|
+
* @param label - Custom label (default: "This Month")
|
|
61
|
+
* @param timezone - IANA timezone for resolving today
|
|
62
|
+
*/
|
|
63
|
+
export declare function presetThisMonth(label?: string, timezone?: string): RangePreset;
|
|
64
|
+
/**
|
|
65
|
+
* Create a "Last Month" preset — selects the full previous month.
|
|
66
|
+
*
|
|
67
|
+
* @param label - Custom label (default: "Last Month")
|
|
68
|
+
* @param timezone - IANA timezone for resolving today
|
|
69
|
+
*/
|
|
70
|
+
export declare function presetLastMonth(label?: string, timezone?: string): RangePreset;
|
|
71
|
+
/**
|
|
72
|
+
* Create a "This Year" preset — selects from January 1st of the current year to today.
|
|
73
|
+
*
|
|
74
|
+
* @param label - Custom label (default: "This Year")
|
|
75
|
+
* @param timezone - IANA timezone for resolving today
|
|
76
|
+
*/
|
|
77
|
+
export declare function presetThisYear(label?: string, timezone?: string): RangePreset;
|
|
78
|
+
/**
|
|
79
|
+
* Create a "Last Year" preset — selects the full previous year (Jan 1 – Dec 31).
|
|
80
|
+
*
|
|
81
|
+
* @param label - Custom label (default: "Last Year")
|
|
82
|
+
* @param timezone - IANA timezone for resolving today
|
|
83
|
+
*/
|
|
84
|
+
export declare function presetLastYear(label?: string, timezone?: string): RangePreset;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { CalendarDate } from './calendar-date';
|
|
2
|
+
/**
|
|
3
|
+
* Common interface for all selection models.
|
|
4
|
+
*
|
|
5
|
+
* Each model tracks which dates are selected and exposes a uniform API
|
|
6
|
+
* for querying, toggling, clearing, and serializing the selection.
|
|
7
|
+
*/
|
|
8
|
+
export interface Selection {
|
|
9
|
+
/** Check if a specific date is selected. */
|
|
10
|
+
isSelected(date: CalendarDate): boolean;
|
|
11
|
+
/** Toggle a date's selection state. */
|
|
12
|
+
toggle(date: CalendarDate): void;
|
|
13
|
+
/** Clear all selected dates. */
|
|
14
|
+
clear(): void;
|
|
15
|
+
/** Return selected dates as an array (sorted chronologically). */
|
|
16
|
+
toArray(): CalendarDate[];
|
|
17
|
+
/** Serialize the selection to a string value (for form inputs). */
|
|
18
|
+
toValue(): string;
|
|
19
|
+
}
|
|
20
|
+
/** Stores zero or one selected date. */
|
|
21
|
+
export declare class SingleSelection implements Selection {
|
|
22
|
+
private selected;
|
|
23
|
+
constructor(initial?: CalendarDate | null);
|
|
24
|
+
isSelected(date: CalendarDate): boolean;
|
|
25
|
+
/** Toggle: select the date, or deselect if it's already selected. */
|
|
26
|
+
toggle(date: CalendarDate): void;
|
|
27
|
+
clear(): void;
|
|
28
|
+
toArray(): CalendarDate[];
|
|
29
|
+
/** Returns the ISO string of the selected date, or empty string. */
|
|
30
|
+
toValue(): string;
|
|
31
|
+
/** Direct access to the current selection. */
|
|
32
|
+
getSelected(): CalendarDate | null;
|
|
33
|
+
}
|
|
34
|
+
/** Stores zero or more selected dates via a Set of ISO keys. */
|
|
35
|
+
export declare class MultipleSelection implements Selection {
|
|
36
|
+
private keys;
|
|
37
|
+
constructor(initial?: CalendarDate[]);
|
|
38
|
+
isSelected(date: CalendarDate): boolean;
|
|
39
|
+
/** Toggle: add the date if absent, remove if present. */
|
|
40
|
+
toggle(date: CalendarDate): void;
|
|
41
|
+
clear(): void;
|
|
42
|
+
/** Returns selected dates sorted chronologically. */
|
|
43
|
+
toArray(): CalendarDate[];
|
|
44
|
+
/** Returns comma-separated ISO strings, sorted chronologically. */
|
|
45
|
+
toValue(): string;
|
|
46
|
+
/** Number of currently selected dates. */
|
|
47
|
+
get count(): number;
|
|
48
|
+
}
|
|
49
|
+
/** Stores a date range (start → end), with support for partial state. */
|
|
50
|
+
export declare class RangeSelection implements Selection {
|
|
51
|
+
private start;
|
|
52
|
+
private end;
|
|
53
|
+
constructor(start?: CalendarDate | null, end?: CalendarDate | null);
|
|
54
|
+
isSelected(date: CalendarDate): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Toggle behavior for range selection:
|
|
57
|
+
* 1. Nothing selected → set as start
|
|
58
|
+
* 2. Only start selected → set as end (swap if before start)
|
|
59
|
+
* 3. Both selected → clear and set as new start
|
|
60
|
+
*/
|
|
61
|
+
toggle(date: CalendarDate): void;
|
|
62
|
+
/**
|
|
63
|
+
* Directly set both start and end of the range.
|
|
64
|
+
* Useful for programmatic assignment where `toggle()` semantics are undesirable
|
|
65
|
+
* (e.g., same-day ranges where toggling the same date would deselect).
|
|
66
|
+
*/
|
|
67
|
+
setRange(start: CalendarDate, end: CalendarDate): void;
|
|
68
|
+
clear(): void;
|
|
69
|
+
/** Returns [start, end] if both set, [start] if partial, or [] if empty. */
|
|
70
|
+
toArray(): CalendarDate[];
|
|
71
|
+
/** Returns "start – end" ISO strings, or just start, or empty string. */
|
|
72
|
+
toValue(): string;
|
|
73
|
+
/**
|
|
74
|
+
* Check if a date falls within the range (inclusive), with optional
|
|
75
|
+
* hover preview for visual feedback during range building.
|
|
76
|
+
*
|
|
77
|
+
* When only start is selected and the user hovers over a date,
|
|
78
|
+
* pass that date as `hoverDate` to preview the range.
|
|
79
|
+
*/
|
|
80
|
+
isInRange(date: CalendarDate, hoverDate?: CalendarDate): boolean;
|
|
81
|
+
/** Direct access to the range endpoints. */
|
|
82
|
+
getStart(): CalendarDate | null;
|
|
83
|
+
getEnd(): CalendarDate | null;
|
|
84
|
+
/** Whether the range is partially selected (start only, no end). */
|
|
85
|
+
isPartial(): boolean;
|
|
86
|
+
/** Whether the range is fully selected (both start and end). */
|
|
87
|
+
isComplete(): boolean;
|
|
88
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Alpine as AlpineType } from 'alpinejs';
|
|
2
|
+
import '../styles/calendar.css';
|
|
3
|
+
import type { CalendarConfig } from './plugin/calendar-component';
|
|
4
|
+
/**
|
|
5
|
+
* Alpine.js plugin that registers the `calendar` component.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* ```ts
|
|
9
|
+
* import Alpine from 'alpinejs'
|
|
10
|
+
* import { calendarPlugin } from '@reachgr/alpine-calendar'
|
|
11
|
+
*
|
|
12
|
+
* Alpine.plugin(calendarPlugin)
|
|
13
|
+
* Alpine.start()
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function calendarPlugin(Alpine: AlpineType): void;
|
|
17
|
+
export declare namespace calendarPlugin {
|
|
18
|
+
var defaults: (config: Partial<CalendarConfig>) => void;
|
|
19
|
+
var getDefaults: () => Partial<CalendarConfig>;
|
|
20
|
+
var resetDefaults: () => void;
|
|
21
|
+
}
|
|
22
|
+
export default calendarPlugin;
|
|
23
|
+
export { createCalendarData } from './plugin/calendar-component';
|
|
24
|
+
export type { CalendarConfig } from './plugin/calendar-component';
|
|
25
|
+
export { CalendarDate, daysInMonth, getISOWeekNumber } from './core/calendar-date';
|
|
26
|
+
export { generateMonth, generateMonths, generateMonthGrid, generateYearGrid } from './core/grid';
|
|
27
|
+
export type { DayCell, MonthGrid, MonthCell, YearCell } from './core/grid';
|
|
28
|
+
export { SingleSelection, MultipleSelection, RangeSelection } from './core/selection';
|
|
29
|
+
export type { Selection } from './core/selection';
|
|
30
|
+
export { createDateConstraint, createRangeValidator, createDisabledReasons, isDateDisabled, } from './core/constraints';
|
|
31
|
+
export type { DateConstraintOptions, DateConstraintProperties, DateConstraintRule, ConstraintMessages, } from './core/constraints';
|
|
32
|
+
export type { CalendarConfigRule, RangePreset } from './plugin/calendar-component';
|
|
33
|
+
export { presetToday, presetYesterday, presetLastNDays, presetThisWeek, presetLastWeek, presetThisMonth, presetLastMonth, presetThisYear, presetLastYear, } from './core/presets';
|
|
34
|
+
export { parseDate, parseDateRange, parseDateMultiple } from './input/parser';
|
|
35
|
+
export { formatDate, formatRange, formatMultiple } from './input/formatter';
|
|
36
|
+
export { createMask, createMaskHandlers, attachMask, parseFormatToSlots } from './input/mask';
|
|
37
|
+
export type { InputMask, MaskEventHandlers, MaskSlot } from './input/mask';
|
|
38
|
+
export { computePosition, autoUpdate } from './positioning/popup';
|
|
39
|
+
export type { Placement, PositionOptions, PositionResult } from './positioning/popup';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { CalendarDate } from '../core/calendar-date';
|
|
2
|
+
/**
|
|
3
|
+
* Format a CalendarDate according to a format string.
|
|
4
|
+
*
|
|
5
|
+
* Replaces format tokens with the corresponding date values.
|
|
6
|
+
* All non-token characters are passed through as literals.
|
|
7
|
+
*
|
|
8
|
+
* @param date - The CalendarDate to format
|
|
9
|
+
* @param format - The format string (e.g., "DD/MM/YYYY")
|
|
10
|
+
* @returns Formatted date string (e.g., "15/06/2025")
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatDate(date: CalendarDate, format: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format a date range as a display string.
|
|
15
|
+
*
|
|
16
|
+
* Uses en-dash (–) as the range separator.
|
|
17
|
+
*
|
|
18
|
+
* @param start - The range start date
|
|
19
|
+
* @param end - The range end date
|
|
20
|
+
* @param format - The format string for each date
|
|
21
|
+
* @returns Formatted range string (e.g., "01/06/2025 – 30/06/2025")
|
|
22
|
+
*/
|
|
23
|
+
export declare function formatRange(start: CalendarDate, end: CalendarDate, format: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Format multiple dates as a display string.
|
|
26
|
+
*
|
|
27
|
+
* When the number of dates exceeds `maxDisplay`, returns a count string
|
|
28
|
+
* instead of listing all dates (e.g., "3 dates selected").
|
|
29
|
+
*
|
|
30
|
+
* @param dates - Array of CalendarDates to format
|
|
31
|
+
* @param format - The format string for each date
|
|
32
|
+
* @param maxDisplay - Maximum number of dates to show before switching to count
|
|
33
|
+
* (default: no limit — always shows all dates)
|
|
34
|
+
* @returns Formatted string: comma-separated dates or count string
|
|
35
|
+
*/
|
|
36
|
+
export declare function formatMultiple(dates: readonly CalendarDate[], format: string, maxDisplay?: number): string;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight input mask engine for date format strings.
|
|
3
|
+
*
|
|
4
|
+
* Maps format tokens (DD, MM, YYYY, etc.) to digit slots and
|
|
5
|
+
* auto-inserts separator characters as the user types.
|
|
6
|
+
* No external dependencies.
|
|
7
|
+
*/
|
|
8
|
+
export interface MaskSlot {
|
|
9
|
+
type: 'digit' | 'literal';
|
|
10
|
+
char: string;
|
|
11
|
+
}
|
|
12
|
+
export interface InputMask {
|
|
13
|
+
/** Apply mask to a raw input string, returning the formatted string */
|
|
14
|
+
apply(rawInput: string): string;
|
|
15
|
+
/** The mask pattern, e.g. "99/99/9999" */
|
|
16
|
+
readonly pattern: string;
|
|
17
|
+
/** The format string used to create the mask */
|
|
18
|
+
readonly format: string;
|
|
19
|
+
/** Total character length of a fully-filled mask */
|
|
20
|
+
readonly length: number;
|
|
21
|
+
/** The slot definitions */
|
|
22
|
+
readonly slots: readonly MaskSlot[];
|
|
23
|
+
/** Maximum number of digit characters the mask accepts */
|
|
24
|
+
readonly maxDigits: number;
|
|
25
|
+
}
|
|
26
|
+
export interface MaskEventHandlers {
|
|
27
|
+
onInput: (e: Event) => void;
|
|
28
|
+
onKeyDown: (e: KeyboardEvent) => void;
|
|
29
|
+
onPaste: (e: ClipboardEvent) => void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Parse a format string into an array of mask slots.
|
|
33
|
+
*
|
|
34
|
+
* Each format token (DD, MM, YYYY, etc.) becomes digit slots,
|
|
35
|
+
* and all other characters become literal slots.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseFormatToSlots(format: string): MaskSlot[];
|
|
38
|
+
/**
|
|
39
|
+
* Create a mask from a date format string.
|
|
40
|
+
*
|
|
41
|
+
* @param format - The date format (e.g., "DD/MM/YYYY")
|
|
42
|
+
* @returns An InputMask object with apply() and metadata
|
|
43
|
+
*/
|
|
44
|
+
export declare function createMask(format: string): InputMask;
|
|
45
|
+
/**
|
|
46
|
+
* Create event handlers for masking an HTMLInputElement.
|
|
47
|
+
*
|
|
48
|
+
* Handles input, keydown (backspace/delete over separators), and paste.
|
|
49
|
+
*
|
|
50
|
+
* @param mask - The InputMask to use
|
|
51
|
+
* @returns Event handlers to attach to the input element
|
|
52
|
+
*/
|
|
53
|
+
export declare function createMaskHandlers(mask: InputMask): MaskEventHandlers;
|
|
54
|
+
/**
|
|
55
|
+
* Attach mask event handlers to an input element.
|
|
56
|
+
* Returns a detach function to remove the handlers.
|
|
57
|
+
*
|
|
58
|
+
* @param input - The HTML input element
|
|
59
|
+
* @param format - The date format string (e.g., "DD/MM/YYYY")
|
|
60
|
+
* @returns Detach function to remove event listeners
|
|
61
|
+
*/
|
|
62
|
+
export declare function attachMask(input: HTMLInputElement, format: string): () => void;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { CalendarDate } from '../core/calendar-date';
|
|
2
|
+
/**
|
|
3
|
+
* Parse a date string according to the given format.
|
|
4
|
+
*
|
|
5
|
+
* Parsing is lenient: single-digit day/month values are accepted even when
|
|
6
|
+
* the format specifies DD/MM (e.g., `1/3/2025` matches `DD/MM/YYYY`).
|
|
7
|
+
*
|
|
8
|
+
* @param input - The date string to parse (e.g., "15/06/2025")
|
|
9
|
+
* @param format - The format string (e.g., "DD/MM/YYYY")
|
|
10
|
+
* @returns The parsed CalendarDate, or null if parsing fails or date is invalid
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseDate(input: string, format: string): CalendarDate | null;
|
|
13
|
+
/**
|
|
14
|
+
* Parse a range string into two CalendarDates.
|
|
15
|
+
*
|
|
16
|
+
* Supported separators between the two dates: ` - `, ` – ` (en-dash), ` — ` (em-dash).
|
|
17
|
+
*
|
|
18
|
+
* @param input - The range string (e.g., "01/01/2025 - 07/01/2025")
|
|
19
|
+
* @param format - The format for each individual date
|
|
20
|
+
* @returns Tuple of [start, end], or null if parsing fails
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseDateRange(input: string, format: string): [CalendarDate, CalendarDate] | null;
|
|
23
|
+
/**
|
|
24
|
+
* Parse a comma-separated list of dates.
|
|
25
|
+
*
|
|
26
|
+
* @param input - The comma-separated string (e.g., "01/06/2025, 15/06/2025, 20/06/2025")
|
|
27
|
+
* @param format - The format for each individual date
|
|
28
|
+
* @returns Array of parsed CalendarDates (only valid dates included), or empty array
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseDateMultiple(input: string, format: string): CalendarDate[];
|