@flytedan/flytebot-design-system 0.46.0 → 0.47.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/dist/index.cjs CHANGED
@@ -3309,6 +3309,21 @@ var fmt = (s) => {
3309
3309
  const d = parse(s);
3310
3310
  return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
3311
3311
  };
3312
+ var fullDateLabel = (d) => new Intl.DateTimeFormat(void 0, { dateStyle: "full" }).format(d);
3313
+ var monthYearLabel = (d) => new Intl.DateTimeFormat(void 0, { month: "long", year: "numeric" }).format(d);
3314
+ var weekdayLong = (i) => new Intl.DateTimeFormat(void 0, { weekday: "long" }).format(new Date(2023, 0, 1 + i));
3315
+ var daysInMonth = (y, m) => new Date(y, m + 1, 0).getDate();
3316
+ var addMonths = (d, n) => {
3317
+ const total = d.getFullYear() * 12 + d.getMonth() + n;
3318
+ const y = Math.floor(total / 12), m = (total % 12 + 12) % 12;
3319
+ return new Date(y, m, Math.min(d.getDate(), daysInMonth(y, m)));
3320
+ };
3321
+ var addYears = (d, n) => {
3322
+ const y = d.getFullYear() + n;
3323
+ return new Date(y, d.getMonth(), Math.min(d.getDate(), daysInMonth(y, d.getMonth())));
3324
+ };
3325
+ var addDays = (d, n) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
3326
+ var sameMonth = (d, y, m) => d.getFullYear() === y && d.getMonth() === m;
3312
3327
  function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3313
3328
  const today = /* @__PURE__ */ new Date();
3314
3329
  const sel = range ? value || {} : { start: value, end: value };
@@ -3323,8 +3338,38 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3323
3338
  const lo = s, hi = e || hoverEnd;
3324
3339
  return lo && hi && d > (lo < hi ? lo : hi) && d < (lo < hi ? hi : lo);
3325
3340
  };
3326
- const isEdge = (d) => s && iso(d) === iso(s) || e && iso(d) === iso(e);
3341
+ const isStart = (d) => !!s && iso(d) === iso(s);
3342
+ const isEnd = (d) => !!e && iso(d) === iso(e);
3343
+ const isEdge = (d) => isStart(d) || isEnd(d);
3344
+ const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
3345
+ const [activeDate, setActiveDate] = React23.useState(() => {
3346
+ if (s) return s;
3347
+ if (sameMonth(today, anchor.getFullYear(), anchor.getMonth())) return today;
3348
+ return new Date(anchor.getFullYear(), anchor.getMonth(), 1);
3349
+ });
3350
+ const calRef = React23.useRef(null);
3351
+ const pageToShow = (y, m) => {
3352
+ const idx = y * 12 + m, firstIdx = vy * 12 + vm, secondIdx = firstIdx + 1;
3353
+ if (idx === firstIdx || months > 1 && idx === secondIdx) return;
3354
+ if (idx < firstIdx || months === 1) {
3355
+ setVy(y);
3356
+ setVm(m);
3357
+ return;
3358
+ }
3359
+ const baseIdx = idx - 1;
3360
+ setVy(Math.floor(baseIdx / 12));
3361
+ setVm((baseIdx % 12 + 12) % 12);
3362
+ };
3363
+ const moveActive = (next) => {
3364
+ setActiveDate(next);
3365
+ pageToShow(next.getFullYear(), next.getMonth());
3366
+ };
3367
+ React23.useEffect(() => {
3368
+ const el = calRef.current?.querySelector('[data-iso="' + iso(activeDate) + '"]');
3369
+ if (el) el.focus({ preventScroll: true });
3370
+ }, [activeDate, vy, vm]);
3327
3371
  const clickDay = (d) => {
3372
+ setActiveDate(d);
3328
3373
  const v = iso(d);
3329
3374
  if (!range) {
3330
3375
  onPick(v);
@@ -3349,36 +3394,115 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3349
3394
  setVm(m);
3350
3395
  setVy(y);
3351
3396
  };
3397
+ const onGridKeyDown = (ev) => {
3398
+ const d = activeDate;
3399
+ switch (ev.key) {
3400
+ case "ArrowLeft":
3401
+ ev.preventDefault();
3402
+ moveActive(addDays(d, -1));
3403
+ return;
3404
+ case "ArrowRight":
3405
+ ev.preventDefault();
3406
+ moveActive(addDays(d, 1));
3407
+ return;
3408
+ case "ArrowUp":
3409
+ ev.preventDefault();
3410
+ moveActive(addDays(d, -7));
3411
+ return;
3412
+ case "ArrowDown":
3413
+ ev.preventDefault();
3414
+ moveActive(addDays(d, 7));
3415
+ return;
3416
+ case "Home":
3417
+ ev.preventDefault();
3418
+ moveActive(addDays(d, -d.getDay()));
3419
+ return;
3420
+ case "End":
3421
+ ev.preventDefault();
3422
+ moveActive(addDays(d, 6 - d.getDay()));
3423
+ return;
3424
+ case "PageUp":
3425
+ ev.preventDefault();
3426
+ moveActive(ev.shiftKey ? addYears(d, -1) : addMonths(d, -1));
3427
+ return;
3428
+ case "PageDown":
3429
+ ev.preventDefault();
3430
+ moveActive(ev.shiftKey ? addYears(d, 1) : addMonths(d, 1));
3431
+ return;
3432
+ case "Enter":
3433
+ case " ":
3434
+ ev.preventDefault();
3435
+ clickDay(d);
3436
+ return;
3437
+ default:
3438
+ return;
3439
+ }
3440
+ };
3441
+ const monthHeading = mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? String(vy) : vy - 5 + " \u2013 " + (vy + 6);
3442
+ const prevLabel = mode2 === "days" ? "Previous month, " + monthYearLabel(new Date(vy, vm - 1, 1)) : mode2 === "months" ? "Previous year, " + (vy - 1) : "Previous years, " + (vy - 17) + " \u2013 " + (vy - 6);
3443
+ const nextLabel = mode2 === "days" ? "Next month, " + monthYearLabel(new Date(vy, vm + 1, 1)) : mode2 === "months" ? "Next year, " + (vy + 1) : "Next years, " + (vy + 7) + " \u2013 " + (vy + 18);
3352
3444
  const monthGrid = (y, m) => {
3353
3445
  const startPad = new Date(y, m, 1).getDay();
3446
+ const last = daysInMonth(y, m);
3354
3447
  const cells = [];
3355
- for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
3356
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
3357
- DOW.map((d) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-cal-dow", children: d }, d)),
3358
- cells.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3359
- "button",
3360
- {
3361
- type: "button",
3362
- className: ["fd-cal-day", d.getMonth() !== m ? "is-out" : "", iso(d) === iso(today) ? "is-today" : "", inRange(d) ? "in-range" : "", isEdge(d) ? "is-edge" : ""].filter(Boolean).join(" "),
3363
- onClick: () => clickDay(d),
3364
- onMouseEnter: () => range && setHover(iso(d)),
3365
- children: d.getDate()
3366
- },
3367
- i
3368
- ))
3369
- ] });
3448
+ for (let i = 0; i < 42; i++) {
3449
+ const dom = i - startPad + 1;
3450
+ cells.push(dom >= 1 && dom <= last ? new Date(y, m, dom) : null);
3451
+ }
3452
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
3453
+ "div",
3454
+ {
3455
+ className: "fd-cal-grid",
3456
+ role: "grid",
3457
+ "aria-label": monthYearLabel(new Date(y, m, 1)),
3458
+ style: { width: months > 1 ? 252 : "auto", flex: "none" },
3459
+ onMouseLeave: () => setHover(null),
3460
+ children: [
3461
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-cal-row", role: "row", children: DOW.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-cal-dow", role: "columnheader", "aria-label": weekdayLong(i), children: d }, d)) }),
3462
+ Array.from({ length: 6 }, (_, row) => /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-cal-row", role: "row", children: cells.slice(row * 7, row * 7 + 7).map((d, col) => {
3463
+ if (!d) return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "fd-cal-day is-empty", role: "presentation", "aria-hidden": "true" }, col);
3464
+ const today_ = iso(d) === iso(today);
3465
+ const start = isStart(d), end = isEnd(d), selected = isEdge(d);
3466
+ const bits = [];
3467
+ if (range && start) bits.push("start date");
3468
+ if (range && end) bits.push("end date");
3469
+ if (selected && !range) bits.push("selected");
3470
+ if (today_) bits.push("today");
3471
+ const name = bits.length ? fullDateLabel(d) + ", " + bits.join(", ") : fullDateLabel(d);
3472
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
3473
+ "div",
3474
+ {
3475
+ "data-iso": iso(d),
3476
+ role: "gridcell",
3477
+ tabIndex: iso(d) === iso(activeDate) ? 0 : -1,
3478
+ "aria-label": name,
3479
+ "aria-selected": selected,
3480
+ "aria-current": today_ ? "date" : void 0,
3481
+ className: ["fd-cal-day", today_ ? "is-today" : "", inRange(d) ? "in-range" : "", selected ? "is-edge" : ""].filter(Boolean).join(" "),
3482
+ onClick: () => clickDay(d),
3483
+ onMouseEnter: () => range && setHover(iso(d)),
3484
+ onKeyDown: onGridKeyDown,
3485
+ onFocus: () => setActiveDate(d),
3486
+ children: d.getDate()
3487
+ },
3488
+ col
3489
+ );
3490
+ }) }, row))
3491
+ ]
3492
+ }
3493
+ );
3370
3494
  };
3371
- const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
3372
- return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
3495
+ return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, ref: calRef, children: [
3373
3496
  /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "fd-cal-head", children: [
3374
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Previous", onClick: () => mode2 === "years" ? setVy(vy - 12) : mode2 === "months" ? setVy(vy - 1) : nav(-1), children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-caret-left" }) }),
3497
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": prevLabel, onClick: () => mode2 === "years" ? setVy(vy - 12) : mode2 === "months" ? setVy(vy - 1) : nav(-1), children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-caret-left" }) }),
3375
3498
  /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
3376
- mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
3499
+ monthHeading,
3377
3500
  /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
3378
3501
  ] }),
3379
3502
  months > 1 && mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
3380
- /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": "Next", onClick: () => mode2 === "years" ? setVy(vy + 12) : mode2 === "months" ? setVy(vy + 1) : nav(1), children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-caret-right" }) })
3503
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: "fd-btn-icon", "aria-label": nextLabel, onClick: () => mode2 === "years" ? setVy(vy + 12) : mode2 === "months" ? setVy(vy + 1) : nav(1), children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("i", { className: "ph ph-caret-right" }) })
3381
3504
  ] }),
3505
+ /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { "aria-live": "polite", className: "fd-sr-only", children: monthHeading }),
3382
3506
  mode2 === "days" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { style: { display: "flex", gap: 18 }, children: [
3383
3507
  monthGrid(vy, vm),
3384
3508
  months > 1 ? monthGrid(nextY, nextM) : null
@@ -3418,6 +3542,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3418
3542
  setVy(today.getFullYear());
3419
3543
  setVm(today.getMonth());
3420
3544
  setMode("days");
3545
+ moveActive(today);
3421
3546
  },
3422
3547
  children: "Today"
3423
3548
  }