/*! Fiesta 1.1.0 | MPL-2.0 | https://fiesta.rastrillo.org */
(function () {
"use strict";
var COMBINING = /[\u0300-\u036f]/g;
var LETTERISH = /[a-z\u00c0-\u024f\u0370-\u03ff\u0400-\u04ff\u0530-\u058f\u0590-\u05ff\u0600-\u06ff\u0900-\u097f\u0980-\u09ff\u0b80-\u0bff\u0e00-\u0e7f]/;
var BREAKS = /[\s,;\u060c\u061b\uff0c\u3001\u3002]/;
function pad(n) { return (n < 10 ? "0" : "") + n; }
function midnight(d) {
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
}
function shiftDays(d, n) {
var x = midnight(d);
x.setDate(x.getDate() + n);
return x;
}
function comingWeekday(now, target) {
var delta = (target - now.getDay() + 7) % 7;
return shiftDays(now, delta === 0 ? 7 : delta);
}
function lastWeekday(now, target) {
var delta = (now.getDay() - target + 7) % 7;
return shiftDays(now, -(delta === 0 ? 7 : delta));
}
function inferYear(now, mo, d) {
var y = now.getFullYear();
return new Date(y, mo, d) < midnight(now) ? y + 1 : y;
}
function makeDate(y, mo, d, h, mi) {
if (y < 1000) return null;
if (mo < 0 || mo > 11 || d < 1 || d > 31) return null;
if (h < 0 || h > 23 || mi < 0 || mi > 59) return null;
var dt = new Date(y, mo, d, h, mi, 0, 0);
if (dt.getMonth() !== mo || dt.getDate() !== d) return null;
return dt;
}
var NUMBERING = ["arab", "arabext", "beng", "deva"];
function foldDigits(nf, map) {
var i, parts, k, digit, add = {}, differs = false;
for (i = 0; i <= 9; i++) {
parts = nf.formatToParts(i);
digit = "";
for (k = 0; k < parts.length; k++) if (parts[k].type === "integer") digit = parts[k].value;
if (digit.length !== 1) return false;
if (add[digit] !== undefined) return false;
if (map[digit] !== undefined && map[digit] !== String(i)) return false;
if (digit !== String(i)) differs = true;
add[digit] = String(i);
}
for (digit in add) if (Object.prototype.hasOwnProperty.call(add, digit)) map[digit] = add[digit];
return differs;
}
function digitFolder(locale) {
var map = {}, differs = false, base, root, i;
try {
base = new Intl.NumberFormat(locale, { useGrouping: false });
} catch (e) {
return null;
}
if (foldDigits(base, map)) differs = true;
try {
root = base.resolvedOptions().locale.split("-u-")[0];
} catch (e) {
root = "";
}
for (i = 0; root && i < NUMBERING.length; i++) {
try {
if (foldDigits(new Intl.NumberFormat(root + "-u-nu-" + NUMBERING[i], { useGrouping: false }), map)) differs = true;
} catch (e) {
}
}
if (!differs) return null;
return function (s) {
var out = "", j;
for (j = 0; j < s.length; j++) out += map[s.charAt(j)] !== undefined ? map[s.charAt(j)] : s.charAt(j);
return out;
};
}
function makeFold(digits) {
return function (s) {
var out = String(s === null || s === undefined ? "" : s);
if (out.normalize) out = out.normalize("NFD").replace(COMBINING, "");
out = out.toLowerCase();
if (digits) out = digits(out);
return out.replace(/\s+/g, " ").trim();
};
}
function nameTable(locale, type, dates, fold) {
var widths = ["long", "short"], out = [], i, c, w, opts, fmt, parts, k, value;
var contexts = type === "month" ? [null, "numeric"] : [null];
for (i = 0; i < dates.length; i++) out.push([]);
for (c = 0; c < contexts.length; c++)
for (w = 0; w < widths.length; w++) {
opts = { timeZone: "UTC" };
opts[type] = widths[w];
if (contexts[c]) opts.day = contexts[c];
try {
fmt = new Intl.DateTimeFormat(locale, opts);
} catch (e) {
continue;
}
for (i = 0; i < dates.length; i++) {
parts = fmt.formatToParts(dates[i]);
value = "";
for (k = 0; k < parts.length; k++) if (parts[k].type === type) value = parts[k].value;
value = fold(value);
if (!value) continue;
if (!/[^\d\s.,\/\-]/.test(value)) continue;
if (out[i].indexOf(value) === -1) out[i].push(value);
if (value.charAt(value.length - 1) === "." && value.length > 1) {
value = value.slice(0, -1);
if (out[i].indexOf(value) === -1) out[i].push(value);
}
}
}
return out;
}
function displayOptions(kind) {
var opts = kind === "time"
? { hour: "numeric", minute: "2-digit" }
: { weekday: "short", day: "numeric", month: "short", year: "numeric" };
if (kind === "datetime") {
opts.hour = "numeric";
opts.minute = "2-digit";
}
return opts;
}
function displayTokens(locale, fold) {
var probes = [displayOptions("date"), displayOptions("datetime"), displayOptions("time"),
{ day: "numeric", month: "long" }, { day: "numeric", month: "short" }];
var when = [new Date(Date.UTC(2026, 11, 25, 15, 30)), new Date(Date.UTC(2026, 2, 3, 9, 5))];
var out = { literal: {}, am: {}, pm: {} }, p, i, fmt, parts, k, v, c, run;
function keep(bag, s) { s = fold(s); if (s) bag[s] = true; }
for (p = 0; p < probes.length; p++) {
probes[p].timeZone = "UTC";
try {
fmt = new Intl.DateTimeFormat(locale, probes[p]);
} catch (e) {
continue;
}
for (i = 0; i < when.length; i++) {
parts = fmt.formatToParts(when[i]);
for (k = 0; k < parts.length; k++) {
v = parts[k].value;
if (parts[k].type === "dayPeriod") {
keep(when[i].getUTCHours() < 12 ? out.am : out.pm, v);
continue;
}
if (parts[k].type !== "literal") continue;
for (c = 0, run = ""; c <= v.length; c++) {
if (c < v.length && letterish(v.charAt(c))) { run += v.charAt(c); continue; }
keep(out.literal, run);
run = "";
if (c < v.length && !BREAKS.test(v.charAt(c))) keep(out.literal, v.charAt(c));
}
}
}
}
return out;
}
var TABLES = {};
function tables(locale) {
var key = locale || "";
if (TABLES[key]) return TABLES[key];
var loc = locale || undefined;
var fold = makeFold(digitFolder(loc));
var monthDates = [], weekDates = [], i;
for (i = 0; i < 12; i++) monthDates.push(new Date(Date.UTC(2026, i, 15)));
for (i = 0; i < 7; i++) weekDates.push(new Date(Date.UTC(2026, 1, 1 + i)));
var t = {
locale: loc,
fold: fold,
months: nameTable(loc, "month", monthDates, fold),
weekdays: nameTable(loc, "weekday", weekDates, fold),
display: displayTokens(loc, fold)
};
t.namedMonths = false;
for (i = 0; i < t.months.length; i++) if (t.months[i].length) t.namedMonths = true;
TABLES[key] = t;
return t;
}
function index(vocab, tbl) {
var list = [], name, alts, i, m, k;
for (name in vocab) {
if (!Object.prototype.hasOwnProperty.call(vocab, name)) continue;
alts = String(vocab[name]).split("|");
for (i = 0; i < alts.length; i++) {
var text = tbl.fold(alts[i]);
if (text) list.push({ text: text, role: "word", kind: name, at: -1 });
}
}
var seen = ["literal", "am", "pm"], kind;
for (i = 0; i < seen.length; i++) {
kind = seen[i] === "literal" ? "ignore" : seen[i];
for (name in tbl.display[seen[i]])
if (Object.prototype.hasOwnProperty.call(tbl.display[seen[i]], name))
list.push({ text: name, role: "word", kind: kind, at: -1 });
}
for (m = 0; m < tbl.months.length; m++)
for (k = 0; k < tbl.months[m].length; k++)
list.push({ text: tbl.months[m][k], role: "month", kind: "", at: m });
for (m = 0; m < tbl.weekdays.length; m++)
for (k = 0; k < tbl.weekdays[m].length; k++)
list.push({ text: tbl.weekdays[m][k], role: "weekday", kind: "", at: m });
list.sort(function (a, b) { return b.text.length - a.text.length; });
return list;
}
function indexFor(vocab, tbl) {
var key = "", name;
for (name in vocab) if (Object.prototype.hasOwnProperty.call(vocab, name)) key += name + "=" + vocab[name] + "\u0000";
if (tbl.indexKey !== key) {
tbl.index = index(vocab, tbl);
tbl.indexKey = key;
}
return tbl.index;
}
function letterish(c) {
return !!c && !BREAKS.test(c) && LETTERISH.test(c);
}
function boundaryOK(s, from, to) {
if (from > 0 && letterish(s.charAt(from - 1)) && letterish(s.charAt(from))) return false;
if (to < s.length && letterish(s.charAt(to)) && letterish(s.charAt(to - 1))) return false;
return true;
}
function matchAt(s, pos, idx) {
var best = -1, tok = null, i, e;
for (i = 0; i < idx.length; i++) {
e = idx[i];
if (best >= 0 && e.text.length < best) break;
if (s.slice(pos, pos + e.text.length) !== e.text) continue;
if (!boundaryOK(s, pos, pos + e.text.length)) continue;
if (best < 0) {
best = e.text.length;
tok = { t: "word", kinds: {}, month: -1, weekday: -1 };
}
if (e.role === "word") tok.kinds[e.kind] = true;
else if (e.role === "month") tok.month = e.at;
else tok.weekday = e.at;
}
return tok ? { tok: tok, len: best } : null;
}
function scan(s, idx) {
var toks = [], pos = 0, n = s.length, m, hit, start, glued = false;
function push(tok, from, to) {
tok.glued = glued;
tok.from = from;
tok.to = to;
toks.push(tok);
glued = true;
}
while (pos < n) {
if (BREAKS.test(s.charAt(pos))) { pos++; glued = false; continue; }
m = /^(\d{1,2}):(\d{2})/.exec(s.slice(pos));
if (m) {
push({ t: "clock", h: +m[1], mi: +m[2] }, pos, pos + m[0].length);
pos += m[0].length;
continue;
}
m = /^(\d{1,2})[\/.\-](\d{1,2})[\/.\-](\d{4})(?!\d)/.exec(s.slice(pos));
if (m) {
push({ t: "ndate", d: +m[1], mo: +m[2], y: +m[3] }, pos, pos + m[0].length);
pos += m[0].length;
continue;
}
hit = matchAt(s, pos, idx);
if (hit) { push(hit.tok, pos, pos + hit.len); pos += hit.len; continue; }
m = /^\d+/.exec(s.slice(pos));
if (m) {
push({ t: "num", n: +m[0], digits: m[0].length }, pos, pos + m[0].length);
pos += m[0].length;
continue;
}
start = pos;
while (pos < n && !BREAKS.test(s.charAt(pos)) && !/\d/.test(s.charAt(pos))) {
if (pos > start && matchAt(s, pos, idx)) break;
pos++;
}
if (pos === start) pos++;
push({ t: "other", raw: s.slice(start, pos) }, start, pos);
}
return toks;
}
function parse(text, vocab, tbl, now, ctx) {
ctx = ctx || {};
var raw = tbl.fold(text);
if (!raw) return null;
var idx = indexFor(vocab, tbl);
var prev = ctx.prev || null;
var base = ctx.base || null;
var anchor = midnight(base || prev || now);
var own = midnight(prev || base || now);
var clockH = prev ? prev.getHours() : 9;
var clockM = prev ? prev.getMinutes() : 0;
var m, d;
m = /^(\d{4})-(\d{1,2})-(\d{1,2})(?:[t ](\d{1,2}):(\d{2})(?::\d{2})?)?$/.exec(raw);
if (m) {
d = makeDate(+m[1], +m[2] - 1, +m[3],
m[4] === undefined ? clockH : +m[4],
m[4] === undefined ? clockM : +m[5]);
return d ? { date: d, hasDate: true, hasTime: m[4] !== undefined } : null;
}
m = /^(\d{4})[\/.](\d{1,2})[\/.](\d{1,2})$/.exec(raw);
if (m) {
d = makeDate(+m[1], +m[2] - 1, +m[3], clockH, clockM);
return d ? { date: d, hasDate: true, hasTime: false } : null;
}
function dmy(day, mon, year) {
if (mon > 12 && day <= 12) { var swap = day; day = mon; mon = swap; }
return makeDate(year === undefined ? inferYear(now, mon - 1, day) : year < 100 ? 2000 + year : year,
mon - 1, day, clockH, clockM);
}
m = /^(\d{1,2})[\/.\-](\d{1,2})(?:[\/.\-](\d{2}|\d{4}))?$/.exec(raw);
if (m) {
d = dmy(+m[1], +m[2], m[3] === undefined ? undefined : +m[3]);
return d ? { date: d, hasDate: true, hasTime: false } : null;
}
var toks = scan(raw, idx), i;
if (!toks.length) return null;
for (i = 0; i < toks.length; i++) if (toks[i].t === "other") return null;
var used = [];
function find(kind) {
for (var k = 0; k < toks.length; k++)
if (!used[k] && toks[k].t === "word" && toks[k].kinds[kind]) return k;
return -1;
}
function findRole(role) {
for (var k = 0; k < toks.length; k++) {
if (used[k] || toks[k].t !== "word" || toks[k][role] < 0) continue;
if (role === "weekday" && k > 0 && toks[k].glued && isCounter(k, k - 1)) continue;
return k;
}
return -1;
}
function findKind(t) {
for (var k = 0; k < toks.length; k++) if (!used[k] && toks[k].t === t) return k;
return -1;
}
function after(k) {
return k + 1 < toks.length && !used[k + 1] ? k + 1 : -1;
}
function before(k) {
return k > 0 && !used[k - 1] ? k - 1 : -1;
}
function unit() {
var names = ["minute", "hour", "day", "week", "month"], k, at;
for (k = 0; k < names.length; k++) {
at = find(names[k]);
if (at >= 0) return { name: names[k], at: at };
}
return null;
}
function isCounter(k, p) {
if (toks[p].t === "num") return true;
if (toks[p].t !== "word") return false;
if (!toks[p].kinds.next && !toks[p].kinds.last) return false;
return !!(toks[k].kinds.day || toks[k].kinds.week || toks[k].kinds.month);
}
function isWord(k, kind) {
return k >= 0 && toks[k].t === "word" && !!toks[k].kinds[kind];
}
function claimCounter(at, kind) {
var nx = at >= 0 ? after(at) : -1;
if (nx < 0 || toks[nx].t !== "word" || !toks[nx].glued) return false;
if (!toks[nx].kinds[kind]) return false;
used[nx] = true;
return true;
}
function counterMonth() {
if (tbl.namedMonths) return -1;
for (var k = 0; k < toks.length; k++) {
if (used[k] || toks[k].t !== "num" || toks[k].digits > 2) continue;
var nx = after(k);
if (nx >= 0 && toks[nx].t === "word" && toks[nx].glued && toks[nx].kinds.month) return k;
}
return -1;
}
var date = null, hasDate = false, hasTime = false, h = 0, mi = 0;
var quantified = findKind("num") >= 0;
var into = find("in"), back = find("ago");
if (into >= 0 && back >= 0 && into !== back) return null;
if (quantified && (into >= 0 || back >= 0)) {
var u = unit();
if (u) {
var qi = findKind("num");
var qty = toks[qi].n, sign = back >= 0 ? -1 : 1;
used[qi] = true;
used[u.at] = true;
if (into >= 0) used[into] = true;
if (back >= 0) used[back] = true;
if (u.name === "minute" || u.name === "hour") {
date = new Date(now.getTime() + sign * qty * (u.name === "hour" ? 3600000 : 60000));
hasDate = true;
hasTime = true;
h = date.getHours();
mi = date.getMinutes();
} else {
date = midnight(now);
if (u.name === "day") date.setDate(date.getDate() + sign * qty);
else if (u.name === "week") date.setDate(date.getDate() + sign * qty * 7);
else date.setMonth(date.getMonth() + sign * qty);
hasDate = true;
}
}
}
if (!hasTime) {
var noon = find("noon"), mid = find("midnight");
if (noon >= 0) { h = 12; mi = 0; hasTime = true; used[noon] = true; }
else if (mid >= 0) { h = 0; mi = 0; hasTime = true; used[mid] = true; }
else {
var ci = findKind("clock");
if (ci >= 0) {
h = toks[ci].h;
mi = toks[ci].mi;
used[ci] = true;
hasTime = true;
} else {
for (i = 0; i < toks.length && !hasTime; i++) {
if (used[i] || toks[i].t !== "num") continue;
var nx = after(i), pv = before(i);
if (isWord(nx, "am") || isWord(nx, "pm") || isWord(pv, "am") || isWord(pv, "pm")) {
h = toks[i].n;
mi = 0;
used[i] = true;
hasTime = true;
if (isWord(nx, "hour")) {
used[nx] = true;
var mnx = after(nx);
if (mnx >= 0 && toks[mnx].t === "num" && (after(mnx) < 0 || isWord(after(mnx), "minute"))) {
mi = toks[mnx].n;
used[mnx] = true;
if (after(mnx) >= 0) used[after(mnx)] = true;
}
}
} else if (isWord(nx, "hour")) {
h = toks[i].n;
mi = 0;
used[i] = true;
used[nx] = true;
hasTime = true;
var mn = after(nx);
if (mn >= 0 && toks[mn].t === "num" && (after(mn) < 0 || isWord(after(mn), "minute"))) {
mi = toks[mn].n;
used[mn] = true;
if (after(mn) >= 0) used[after(mn)] = true;
}
} else if (isWord(pv, "at") || isWord(nx, "at")) {
h = toks[i].n;
mi = 0;
used[i] = true;
used[isWord(pv, "at") ? pv : nx] = true;
hasTime = true;
}
}
}
if (hasTime) {
var pm = find("pm"), am = find("am");
if (pm >= 0 || am >= 0) {
if (h < 0 || h > 12) return null;
if (pm >= 0) { used[pm] = true; h = (h % 12) + 12; }
else { used[am] = true; h = h % 12; }
}
}
}
if (hasTime && (h > 23 || mi > 59)) return null;
}
var nd = findKind("ndate");
if (!hasDate && nd >= 0) {
used[nd] = true;
if (findRole("weekday") >= 0) used[findRole("weekday")] = true;
date = dmy(toks[nd].d, toks[nd].mo, toks[nd].y);
if (!date) return null;
hasDate = true;
}
if (!hasDate) {
var tod = find("today"), tom = find("tomorrow"), yes = find("yesterday");
if (tom >= 0) { date = shiftDays(now, 1); used[tom] = true; hasDate = true; }
else if (yes >= 0) { date = shiftDays(now, -1); used[yes] = true; hasDate = true; }
else if (tod >= 0) { date = midnight(now); used[tod] = true; hasDate = true; }
}
if (!hasDate) {
var next = find("next"), last = find("last"), dup;
var cm = counterMonth();
var wi = findRole("weekday");
var mo = findRole("month");
if (wi >= 0 && mo >= 0) {
if (wi === mo) {
for (dup = wi + 1; dup < toks.length; dup++)
if (!used[dup] && toks[dup].t === "word" && toks[dup].month >= 0) { mo = dup; break; }
if (mo !== wi) { used[wi] = true; wi = -1; }
else if (findKind("num") >= 0) wi = -1;
else mo = -1;
} else {
used[wi] = true;
wi = -1;
}
} else if (wi >= 0 && cm >= 0) {
used[wi] = true;
wi = -1;
}
if (wi >= 0) {
used[wi] = true;
if (last >= 0) { used[last] = true; date = lastWeekday(now, toks[wi].weekday); }
else {
if (next >= 0) used[next] = true;
date = comingWeekday(now, toks[wi].weekday);
}
hasDate = true;
} else {
if (mo >= 0) {
used[mo] = true;
var dnum = -1, ynum = -1, dat = -1, k;
for (k = 0; k < toks.length; k++) {
if (used[k] || toks[k].t !== "num") continue;
if (toks[k].digits === 4) {
if (ynum >= 0) break;
ynum = toks[k].n;
used[k] = true;
} else if (dnum < 0) {
dnum = toks[k].n;
dat = k;
used[k] = true;
} else if (ynum < 0) {
ynum = toks[k].n < 100 ? 2000 + toks[k].n : toks[k].n;
used[k] = true;
} else break;
}
if (dnum < 0) return null;
claimCounter(dat, "day");
date = makeDate(ynum >= 0 ? ynum : inferYear(now, toks[mo].month, dnum),
toks[mo].month, dnum, 0, 0);
if (!date) return null;
hasDate = true;
} else if (cm >= 0) {
var cmon = toks[cm].n - 1, cday = -1, cyear = -1, ck;
used[cm] = true;
used[cm + 1] = true;
ck = after(cm + 1);
if (ck >= 0 && toks[ck].t === "num" && toks[ck].digits <= 2) {
cday = toks[ck].n;
used[ck] = true;
claimCounter(ck, "day");
}
if (cday < 0) return null;
for (ck = 0; ck < toks.length && cyear < 0; ck++) {
if (used[ck] || toks[ck].t !== "num" || toks[ck].digits !== 4) continue;
cyear = toks[ck].n;
used[ck] = true;
}
date = makeDate(cyear >= 0 ? cyear : inferYear(now, cmon, cday), cmon, cday, 0, 0);
if (!date) return null;
hasDate = true;
} else if (next >= 0 || last >= 0) {
var u2 = unit();
if (u2 && (u2.name === "day" || u2.name === "week" || u2.name === "month")) {
used[u2.at] = true;
var dir = last >= 0 ? -1 : 1;
used[last >= 0 ? last : next] = true;
date = midnight(now);
if (u2.name === "day") date.setDate(date.getDate() + dir);
else if (u2.name === "week") date.setDate(date.getDate() + 7 * dir);
else date.setMonth(date.getMonth() + dir);
hasDate = true;
}
}
}
}
if (!hasDate) {
var only = -1, count = 0;
for (i = 0; i < toks.length; i++) {
if (used[i] || toks[i].t !== "num") continue;
count++;
if (toks[i].digits === 4) only = i;
}
if (count === 1 && only >= 0 && toks[only].n >= 1000) {
used[only] = true;
date = new Date(own.getFullYear(), own.getMonth(), own.getDate());
date.setFullYear(toks[only].n);
hasDate = true;
}
}
for (i = 0; i < toks.length; i++) {
if (used[i]) continue;
if (toks[i].t !== "word") return null;
if (toks[i].month >= 0 || toks[i].weekday >= 0) return null;
for (var kind in toks[i].kinds) if (kind !== "at" && kind !== "ignore") return null;
}
if (!hasDate && !hasTime) return null;
var on = hasDate ? date : anchor;
var out = makeDate(on.getFullYear(), on.getMonth(), on.getDate(),
hasTime ? h : clockH, hasTime ? mi : clockM);
return out ? { date: out, hasDate: hasDate, hasTime: hasTime } : null;
}
var MAX_COMPLETIONS = 6;
function completionsFor(run, idx) {
var out = [], seen = {}, i, e;
if (!run) return out;
for (i = 0; i < idx.length; i++) {
e = idx[i];
if (e.role === "word" && (e.kind === "ignore" || e.kind === "at")) continue;
if (e.text.length <= run.length) continue;
if (e.text.slice(0, run.length) !== run) continue;
if (seen[e.text]) continue;
seen[e.text] = true;
out.push(e.text);
}
return out;
}
function parseAll(text, vocab, tbl, now, ctx) {
var exact = parse(text, vocab, tbl, now, ctx);
if (exact) return [exact];
var raw = tbl.fold(text);
if (!raw) return [];
var idx = indexFor(vocab, tbl);
var toks = scan(raw, idx), at = -1, i;
for (i = 0; i < toks.length; i++) {
if (toks[i].t !== "other") continue;
if (at >= 0) return [];
at = i;
}
if (at < 0) return [];
var names = completionsFor(toks[at].raw, idx), out = [], seen = {}, read, key;
for (i = 0; i < names.length; i++) {
read = parse(raw.slice(0, toks[at].from) + " " + names[i] + " " + raw.slice(toks[at].to),
vocab, tbl, now, ctx);
if (!read) continue;
key = String(read.date.getTime()) + (read.hasTime ? "t" : "");
if (seen[key]) continue;
seen[key] = true;
out.push(read);
}
out.sort(function (a, b) { return a.date - b.date; });
return out.slice(0, MAX_COMPLETIONS);
}
var ENGLISH_WORDS = {
ago: "ago", am: "am|a.m.", at: "at", day: "day|days", hour: "hour|hours|h", in: "in",
last: "last", midnight: "midnight", minute: "minute|minutes|min|mins|m",
month: "month|months", next: "next", noon: "noon|midday", pm: "pm|p.m.",
today: "today", tomorrow: "tomorrow", week: "week|weeks", yesterday: "yesterday"
};
var NO_ATTRIBUTE = { getAttribute: function () { return null; } };
function vocabulary(native) {
var words = fiestaWord(native, "date-words", ENGLISH_WORDS);
if (typeof words === "string") {
try {
words = JSON.parse(words);
} catch (e) {
words = fiestaWord(NO_ATTRIBUTE, "date-words", ENGLISH_WORDS);
}
}
return words || ENGLISH_WORDS;
}
if (typeof document !== "undefined") {
var resetsPending = new WeakMap(), resetsAccepted = new WeakMap();
function tally(map, form) { return (form && map.get(form)) || 0; }
function count(map, form, by) { if (form) map.set(form, tally(map, form) + by); }
document.addEventListener("reset", function (e) {
var form = e.target;
count(resetsPending, form, 1);
setTimeout(function () {
count(resetsPending, form, -1);
if (!e.defaultPrevented) count(resetsAccepted, form, 1);
}, 0);
});
var CAL_SVG = '';
var CLOCK_SVG = '';
var seq = 0;
function toWire(kind, d) {
var day = d.getFullYear() + "-" + pad(d.getMonth() + 1) + "-" + pad(d.getDate());
var clock = pad(d.getHours()) + ":" + pad(d.getMinutes());
if (kind === "date") return day;
if (kind === "time") return clock;
return day + "T" + clock;
}
function fromWire(kind, value, now) {
var s = String(value || ""), m;
if (kind === "time") {
m = /^(\d{2}):(\d{2})/.exec(s);
return m ? new Date(now.getFullYear(), now.getMonth(), now.getDate(), +m[1], +m[2]) : null;
}
m = /^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2}))?/.exec(s);
if (!m) return null;
return new Date(+m[1], +m[2] - 1, +m[3], m[4] ? +m[4] : 0, m[5] ? +m[5] : 0);
}
function formatter(locale, kind) {
try {
return new Intl.DateTimeFormat(locale, displayOptions(kind));
} catch (e) {
return null;
}
}
function canPick(el) { return !!el.showPicker; }
function enhance(native) {
if (native.dataset.rstEnhanced) return null;
native.dataset.rstEnhanced = "true";
var kind = native.type === "time" ? "time" : (native.type === "date" ? "date" : "datetime");
var locale = document.documentElement.getAttribute("lang") || undefined;
var tbl = tables(locale);
var fmt = formatter(locale, kind);
var vocab = vocabulary(native);
var id = native.id || "rst-dtp-" + ++seq;
var listId = id + "-listbox";
var setLabel = fiestaWord(native, "date-set", "Set");
var hintText = fiestaWord(native, "date-hint", "");
var pickLabel = fiestaWord(native, "date-pick", "Open the calendar");
var clockLabel = fiestaWord(native, "date-pick-time", "Open the clock");
var calLabel = fiestaWord(native, "date-calendar", "Calendar");
var prevLabel = fiestaWord(native, "date-prev-month", "Previous month");
var nextLabel = fiestaWord(native, "date-next-month", "Next month");
var manyFmt = fiestaWord(native, "date-results", "{n} suggestions");
var oneFmt = fiestaWord(native, "date-result-one", "1 suggestion");
var quick = {
today: fiestaWord(native, "date-quick-today", "Today"),
tomorrow: fiestaWord(native, "date-quick-tomorrow", "Tomorrow"),
nextWeek: fiestaWord(native, "date-quick-next-week", "In a week"),
plus1h: fiestaWord(native, "date-quick-plus-1h", "An hour later"),
plus2h: fiestaWord(native, "date-quick-plus-2h", "Two hours later"),
endOfDay: fiestaWord(native, "date-quick-end-of-day", "End of that day"),
nextDay: fiestaWord(native, "date-quick-next-day", "Same time next day")
};
var wrap = document.createElement("div");
wrap.setAttribute("rst-dtp", "");
var input = document.createElement("input");
input.type = "text";
input.setAttribute("rst-input", "");
input.setAttribute("rst-dtp-input", "");
input.id = id + "-combo";
input.autocomplete = "off";
input.spellcheck = false;
input.setAttribute("role", "combobox");
input.setAttribute("aria-expanded", "false");
input.setAttribute("aria-controls", listId);
input.setAttribute("aria-autocomplete", "list");
var list = document.createElement("ul");
list.setAttribute("rst-dtp-list", "");
list.id = listId;
list.hidden = true;
list.setAttribute("role", "listbox");
var status = document.createElement("p");
status.className = "rst-sr-only";
status.setAttribute("role", "status");
status.setAttribute("aria-live", "polite");
native.parentNode.insertBefore(wrap, native);
wrap.appendChild(input);
wrap.appendChild(list);
wrap.appendChild(status);
wrap.appendChild(native);
var label = native.id ? document.querySelector('label[for="' + native.id + '"]') : null;
if (label) label.setAttribute("for", input.id);
else if (native.getAttribute("aria-label")) input.setAttribute("aria-label", native.getAttribute("aria-label"));
if (native.getAttribute("aria-describedby"))
input.setAttribute("aria-describedby", native.getAttribute("aria-describedby"));
native.removeAttribute("rst-input");
native.classList.add("rst-sr-only");
native.setAttribute("tabindex", "-1");
native.setAttribute("aria-hidden", "true");
var rows = [];
var active = -1;
var baseOf = null;
var onCommit = null;
var isEnd = false;
var mine = false;
function current() { return fromWire(kind, native.value, new Date()); }
function show(d) { return fmt ? fmt.format(d) : toWire(kind, d); }
function paint() {
var d = current();
input.value = d ? show(d) : "";
}
function setActive(i) {
active = i;
for (var k = 0; k < rows.length; k++) rows[k].li.classList.toggle("is-active", k === i);
if (i >= 0) input.setAttribute("aria-activedescendant", rows[i].li.id);
else input.removeAttribute("aria-activedescendant");
}
function addRow(label, meta, date, hasTime, variant, extra) {
var li = document.createElement("li");
li.setAttribute("rst-dtp-row", variant || "");
if (extra) li.setAttribute(extra, "");
li.id = listId + "-" + rows.length;
li.setAttribute("role", "option");
li.setAttribute("aria-selected", toWire(kind, date) === native.value ? "true" : "false");
var main = document.createElement("span");
main.setAttribute("rst-dtp-label", "");
main.textContent = label;
li.appendChild(main);
if (meta) {
var m = document.createElement("span");
m.setAttribute("rst-dtp-set", "");
m.textContent = meta;
li.appendChild(m);
}
li.addEventListener("mousedown", function (e) {
e.preventDefault();
commit(date, hasTime);
});
list.appendChild(li);
rows.push({ li: li, date: date, hasTime: hasTime });
}
function picks(now) {
var start = baseOf ? baseOf() : null;
var out = [], at;
if (isEnd && start && kind !== "date") {
return [
{ label: quick.plus1h, date: new Date(start.getTime() + 3600000) },
{ label: quick.plus2h, date: new Date(start.getTime() + 7200000) },
{ label: quick.endOfDay, date: new Date(start.getFullYear(), start.getMonth(), start.getDate(), 23, 59) },
{ label: quick.nextDay, date: new Date(start.getTime() + 86400000) }
];
}
if (kind === "time") {
var from = current() || now;
return [
{ label: quick.plus1h, date: new Date(from.getTime() + 3600000) },
{ label: quick.plus2h, date: new Date(from.getTime() + 7200000) },
{ label: quick.endOfDay, date: new Date(from.getFullYear(), from.getMonth(), from.getDate(), 23, 59) }
];
}
at = function (d) { return new Date(d.getFullYear(), d.getMonth(), d.getDate(), 9, 0); };
out.push({ label: quick.today, date: at(now) });
out.push({ label: quick.tomorrow, date: at(shiftDays(now, 1)) });
out.push({ label: quick.nextWeek, date: at(shiftDays(now, 7)) });
return out;
}
function ctx() {
return { prev: current(), base: baseOf ? baseOf() : null };
}
function rebuild(query) {
var now = new Date();
list.textContent = "";
rows = [];
var text = String(query || "").trim();
var reads = text ? parseAll(text, vocab, tbl, now, ctx()) : [];
var i, skip = {}, wire;
for (i = 0; i < reads.length; i++) {
addRow(show(reads[i].date), i === 0 ? setLabel : "", reads[i].date, reads[i].hasTime,
i === 0 ? "set" : "alt");
skip[toWire(kind, reads[i].date)] = true;
}
var quickPicks = picks(now);
for (i = 0; i < quickPicks.length; i++) {
wire = toWire(kind, quickPicks[i].date);
if (skip[wire]) continue;
addRow(quickPicks[i].label, show(quickPicks[i].date), quickPicks[i].date, kind !== "date", "", "rst-dtp-quick");
}
if (hintText) {
var hint = document.createElement("li");
hint.setAttribute("rst-dtp-hint", "");
hint.setAttribute("aria-hidden", "true");
hint.textContent = hintText.replace("{example}", show(new Date(now.getFullYear(), now.getMonth(), now.getDate(), 9, 0)));
list.appendChild(hint);
}
status.textContent = rows.length === 1 ? oneFmt : manyFmt.replace("{n}", String(rows.length));
setActive(rows.length && (reads.length || !text) ? 0 : -1);
}
function bounds() {
var when = new Date();
var lo = fromWire(kind, native.getAttribute("min"), when);
var hi = fromWire(kind, native.getAttribute("max"), when);
var start = baseOf ? baseOf() : null;
if (isEnd && start && (!lo || start > lo)) lo = midnight(start);
return { min: lo, max: hi };
}
function previewOf(text) {
var t = String(text || "").trim();
if (!t) return null;
var reads = parseAll(t, vocab, tbl, new Date(), ctx());
return reads.length ? reads[0].date : null;
}
var makeCal = (typeof window !== "undefined" && window.fiestaCalendar) || null;
var cal = null;
if (makeCal && kind !== "time") {
cal = makeCal({
id: id,
locale: locale,
labels: { calendar: calLabel, prev: prevLabel, next: nextLabel },
value: current,
bounds: bounds,
onPick: function (day) {
var had = current();
commit(new Date(day.getFullYear(), day.getMonth(), day.getDate(),
had ? had.getHours() : 9, had ? had.getMinutes() : 0), kind !== "date");
},
onDismiss: function () {
closeAll();
input.focus();
}
});
cal.el.id = id + "-cal";
wrap.appendChild(cal.el);
}
var pick = null;
var ownsPopup = !!cal || kind === "time";
function pickExpanded(open) {
if (pick && ownsPopup) pick.setAttribute("aria-expanded", open ? "true" : "false");
}
if (cal || kind === "time" || canPick(native)) {
pick = document.createElement("button");
pick.type = "button";
pick.setAttribute("rst-dtp-pick", "");
pick.setAttribute("aria-label", kind === "time" ? clockLabel : pickLabel);
if (ownsPopup) {
pick.setAttribute("aria-expanded", "false");
pick.setAttribute("aria-haspopup", cal ? "dialog" : "listbox");
}
pick.innerHTML = kind === "time" ? CLOCK_SVG : CAL_SVG;
wrap.insertBefore(pick, list);
}
var mode = "";
function closeAll() {
mode = "";
list.hidden = true;
active = -1;
input.setAttribute("aria-expanded", "false");
input.setAttribute("aria-controls", listId);
input.removeAttribute("aria-activedescendant");
if (cal) cal.close();
pickExpanded(false);
wrap.classList.remove("is-above");
}
function place() {
var panel = mode === "cal" && cal ? cal.el : list;
wrap.classList.remove("is-above");
if (!panel || panel.hidden) return;
var box = wrap.getBoundingClientRect();
var need = panel.getBoundingClientRect().height;
if (need > window.innerHeight - box.bottom && box.top > need) {
wrap.classList.add("is-above");
}
}
function openList() {
if (locked()) return;
if (cal) cal.close();
mode = "list";
list.hidden = false;
input.setAttribute("aria-expanded", "true");
input.setAttribute("aria-controls", listId);
pickExpanded(false);
rebuild(input.value);
place();
}
function openCal() {
if (locked()) return;
list.hidden = true;
active = -1;
input.removeAttribute("aria-activedescendant");
mode = "cal";
cal.open(previewOf(input.value));
input.setAttribute("aria-expanded", "true");
input.setAttribute("aria-controls", cal.el.id);
pickExpanded(true);
place();
}
function openSlots() {
if (locked()) return;
var base = current() || new Date();
var day = midnight(base);
var want = base.getHours() * 60 + base.getMinutes();
var i, at, best = -1, near = 0, gap;
mode = "slots";
list.hidden = false;
list.textContent = "";
rows = [];
for (i = 0; i < 48; i++) {
at = new Date(day.getFullYear(), day.getMonth(), day.getDate(),
Math.floor(i / 2), (i % 2) * 30);
gap = Math.abs(at.getHours() * 60 + at.getMinutes() - want);
if (best < 0 || gap < best) { best = gap; near = rows.length; }
addRow(show(at), "", at, true, "", "rst-dtp-quick");
}
input.setAttribute("aria-expanded", "true");
input.setAttribute("aria-controls", listId);
pickExpanded(true);
status.textContent = manyFmt.replace("{n}", String(rows.length));
setActive(near);
place();
if (rows[near]) {
list.scrollTop = rows[near].li.offsetTop - Math.round(list.clientHeight / 2);
}
}
function locked() { return native.readOnly || native.matches(":disabled"); }
function follow() {
input.disabled = native.disabled;
input.readOnly = native.readOnly;
if (pick) pick.disabled = native.disabled || native.readOnly;
if (locked()) closeAll();
}
new MutationObserver(follow).observe(native, { attributes: true, attributeFilter: ["disabled", "readonly"] });
follow();
function commit(date, hasTime) {
if (locked()) { paint(); closeAll(); return; }
mine = true;
native.value = toWire(kind, date);
native.dispatchEvent(new Event("change", { bubbles: true }));
mine = false;
input.value = show(date);
closeAll();
if (onCommit) onCommit(date, hasTime);
}
function commitText() {
if (locked()) { paint(); return; }
var text = input.value.trim();
if (!text) {
input.value = "";
if (native.value) {
mine = true;
native.value = "";
native.dispatchEvent(new Event("change", { bubbles: true }));
mine = false;
}
return;
}
var reads = parseAll(text, vocab, tbl, new Date(), ctx());
if (reads.length) commit(reads[0].date, reads[0].hasTime);
else paint();
}
input.addEventListener("focus", function () {
input.select();
if (!mode) openList();
});
input.addEventListener("click", function () {
if (!mode) openList();
});
input.addEventListener("input", function () {
if (mode === "cal" && cal) return cal.show(previewOf(input.value));
openList();
});
input.addEventListener("keydown", function (e) {
switch (e.key) {
case "ArrowDown":
e.preventDefault();
if (mode === "cal" && cal) { cal.focusGrid(); break; }
if (!mode) { openList(); break; }
if (rows.length) setActive(Math.min(active + 1, rows.length - 1));
break;
case "ArrowUp":
e.preventDefault();
if (mode === "cal" && cal) { cal.focusGrid(); break; }
if (!mode) { openList(); break; }
if (rows.length) setActive(Math.max(active - 1, 0));
break;
case "Enter":
e.preventDefault();
if (mode !== "cal" && !list.hidden && active >= 0) commit(rows[active].date, rows[active].hasTime);
else { commitText(); closeAll(); }
break;
case "Escape":
e.preventDefault();
paint();
closeAll();
break;
}
});
input.addEventListener("keypress", function (e) {
if (e.key === "Enter") e.preventDefault();
});
wrap.addEventListener("focusout", function () {
var form = native.form, at = tally(resetsAccepted, form);
var settle = function () {
if (wrap.contains(document.activeElement)) return;
if (tally(resetsPending, form) > 0) { setTimeout(settle, 0); return; }
if (tally(resetsAccepted, form) !== at) return;
commitText();
closeAll();
};
setTimeout(settle, 0);
});
if (pick) {
pick.addEventListener("mousedown", function (e) { e.preventDefault(); });
pick.addEventListener("click", function () {
if (mode === "cal" || mode === "slots") {
closeAll();
input.focus();
return;
}
input.focus();
if (cal) return openCal();
if (kind === "time") return openSlots();
closeAll();
try {
native.showPicker();
} catch (err) {
}
});
}
native.addEventListener("change", function () {
if (mine) return;
if (mode && document.activeElement === input) return;
paint();
});
document.addEventListener("reset", function (e) {
if (e.target !== native.form) return;
setTimeout(function () {
if (e.defaultPrevented) return;
closeAll();
paint();
}, 0);
});
paint();
return {
get value() { return current(); },
commit: commit,
follow: function (fn) { baseOf = fn; isEnd = true; },
committed: function (fn) { onCommit = fn; }
};
}
function wireRange(wrapper, start, end) {
end.follow(function () { return start.value; });
if (wrapper.getAttribute("data-rst-range") !== "session") return;
start.committed(function (d) {
var have = end.value;
if (!have || have <= d) end.commit(new Date(d.getTime() + 3600000), true);
});
}
function scanPage(root) {
var armed = root.querySelectorAll("input[data-rst-date], input[data-rst-time]");
var made = [], i, k, wrappers, inside, pair;
for (i = 0; i < armed.length; i++) made.push([armed[i], enhance(armed[i])]);
wrappers = root.querySelectorAll("[data-rst-range]");
for (i = 0; i < wrappers.length; i++) {
inside = wrappers[i].querySelectorAll("input[data-rst-date], input[data-rst-time]");
pair = [];
for (k = 0; k < inside.length && pair.length < 2; k++) {
for (var j = 0; j < made.length; j++)
if (made[j][0] === inside[k] && made[j][1]) pair.push(made[j][1]);
}
if (pair.length === 2) wireRange(wrappers[i], pair[0], pair[1]);
}
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", function () { scanPage(document); });
} else {
scanPage(document);
}
}
function fiestaPickLang(tag, registry) {
var want = String(tag || "").toLowerCase();
if (!want) return null;
var keys = Object.keys(registry || {}), i;
for (i = 0; i < keys.length; i++) {
if (keys[i].toLowerCase() === want) return keys[i];
}
var primary = want.split("-")[0];
for (i = 0; i < keys.length; i++) {
if (keys[i].toLowerCase().split("-")[0] === primary) return keys[i];
}
return null;
}
function fiestaWord(el, key, fallback) {
var v = el.getAttribute("data-rst-" + key);
if (v !== null && v !== "") return v;
var registry = (typeof self !== "undefined" && self.fiestaStrings) || {};
var lang = fiestaPickLang(document.documentElement.lang, registry);
var table = lang ? registry[lang] : null;
return table && table[key] !== undefined && table[key] !== "" ? table[key] : fallback;
}
if (typeof module !== "undefined" && module && module.exports) {
module.exports = {
parse: parse,
parseAll: parseAll,
tables: tables,
displayOptions: displayOptions,
vocabulary: vocabulary,
fiestaPickLang: fiestaPickLang,
fiestaWord: fiestaWord
};
}
})();