@lekoala/date-picker 0.1.1 → 0.3.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/src/intl.js CHANGED
@@ -51,6 +51,41 @@ export function formatMonthYear(value, locale = "") {
51
51
  }).format(toIntlDate(`${value.slice(0, 7)}-15`));
52
52
  }
53
53
 
54
+ /**
55
+ * Locale order of the visible month/year controls, derived from `Intl` so no
56
+ * `showMonthAfterYear`-style option is needed. Year-like parts cover the
57
+ * `relatedYear` / `yearName` variants some calendars expose; anything
58
+ * unrecognized falls back to month-then-year. This is independent of `dir`:
59
+ * the locale decides the linguistic order, direction only mirrors the layout.
60
+ * @param {string} [locale] @returns {["month", "year"] | ["year", "month"]}
61
+ */
62
+ export function monthYearOrder(locale = "") {
63
+ const resolved = resolveLocale(locale);
64
+ try {
65
+ const parts = new Intl.DateTimeFormat(resolved, {
66
+ calendar: "gregory",
67
+ year: "numeric",
68
+ month: "long",
69
+ timeZone: "UTC",
70
+ }).formatToParts(toIntlDate("2026-09-15"));
71
+ let monthIndex = -1;
72
+ let yearIndex = -1;
73
+ parts.forEach((part, index) => {
74
+ const type = /** @type {string} */ (part.type);
75
+ if (type === "month") {
76
+ if (monthIndex < 0) monthIndex = index;
77
+ } else if (type === "year" || type === "relatedYear" || type === "yearName") {
78
+ if (yearIndex < 0) yearIndex = index;
79
+ }
80
+ });
81
+ if (monthIndex >= 0 && yearIndex >= 0)
82
+ return yearIndex < monthIndex ? ["year", "month"] : ["month", "year"];
83
+ } catch {
84
+ // Fall through to the default below.
85
+ }
86
+ return ["month", "year"];
87
+ }
88
+
54
89
  /** @param {string} [locale] @param {"long"|"short"} [style] */
55
90
  export function monthNames(locale = "", style = "long") {
56
91
  const resolved = resolveLocale(locale);
package/src/time.js ADDED
@@ -0,0 +1,39 @@
1
+ const TIME_RE = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?$/;
2
+
3
+ /**
4
+ * Parse one canonical HTML time value (`HH:MM`, `HH:MM:SS`, `HH:MM:SS.fff`).
5
+ * @param {string} value
6
+ * @returns {{hour:number, minute:number, second:number, millisecond:number} | null}
7
+ */
8
+ function parseTimeParts(value) {
9
+ const match = TIME_RE.exec(String(value || ""));
10
+ if (!match) return null;
11
+ const hour = Number(match[1]);
12
+ const minute = Number(match[2]);
13
+ const second = match[3] === undefined ? 0 : Number(match[3]);
14
+ const millisecond = match[4] === undefined ? 0 : Number(match[4].padEnd(3, "0"));
15
+ if (hour > 23 || minute > 59 || second > 59 || millisecond > 999) return null;
16
+ return { hour, minute, second, millisecond };
17
+ }
18
+
19
+ /** Civil time check for canonical `input[type=time]` values. @param {string} value */
20
+ export function isTime(value) {
21
+ return parseTimeParts(value) !== null;
22
+ }
23
+
24
+ /** @param {{hour:number, minute:number, second:number, millisecond:number}} parts */
25
+ function toMillis(parts) {
26
+ return ((parts.hour * 60 + parts.minute) * 60 + parts.second) * 1000 + parts.millisecond;
27
+ }
28
+
29
+ /**
30
+ * Compare two canonical time values. `09:30` equals `09:30:00`.
31
+ * @param {string} a @param {string} b
32
+ */
33
+ export function compareTimes(a, b) {
34
+ const left = parseTimeParts(a);
35
+ const right = parseTimeParts(b);
36
+ if (!left || !right) throw new TypeError("compareTimes() expects HH:MM values");
37
+ const diff = toMillis(left) - toMillis(right);
38
+ return diff === 0 ? 0 : diff < 0 ? -1 : 1;
39
+ }