@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.js CHANGED
@@ -3066,6 +3066,21 @@ var fmt = (s) => {
3066
3066
  const d = parse(s);
3067
3067
  return d ? MONTHS[d.getMonth()].slice(0, 3) + " " + d.getDate() + ", " + d.getFullYear() : "";
3068
3068
  };
3069
+ var fullDateLabel = (d) => new Intl.DateTimeFormat(void 0, { dateStyle: "full" }).format(d);
3070
+ var monthYearLabel = (d) => new Intl.DateTimeFormat(void 0, { month: "long", year: "numeric" }).format(d);
3071
+ var weekdayLong = (i) => new Intl.DateTimeFormat(void 0, { weekday: "long" }).format(new Date(2023, 0, 1 + i));
3072
+ var daysInMonth = (y, m) => new Date(y, m + 1, 0).getDate();
3073
+ var addMonths = (d, n) => {
3074
+ const total = d.getFullYear() * 12 + d.getMonth() + n;
3075
+ const y = Math.floor(total / 12), m = (total % 12 + 12) % 12;
3076
+ return new Date(y, m, Math.min(d.getDate(), daysInMonth(y, m)));
3077
+ };
3078
+ var addYears = (d, n) => {
3079
+ const y = d.getFullYear() + n;
3080
+ return new Date(y, d.getMonth(), Math.min(d.getDate(), daysInMonth(y, d.getMonth())));
3081
+ };
3082
+ var addDays = (d, n) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
3083
+ var sameMonth = (d, y, m) => d.getFullYear() === y && d.getMonth() === m;
3069
3084
  function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3070
3085
  const today = /* @__PURE__ */ new Date();
3071
3086
  const sel = range ? value || {} : { start: value, end: value };
@@ -3080,8 +3095,38 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3080
3095
  const lo = s, hi = e || hoverEnd;
3081
3096
  return lo && hi && d > (lo < hi ? lo : hi) && d < (lo < hi ? hi : lo);
3082
3097
  };
3083
- const isEdge = (d) => s && iso(d) === iso(s) || e && iso(d) === iso(e);
3098
+ const isStart = (d) => !!s && iso(d) === iso(s);
3099
+ const isEnd = (d) => !!e && iso(d) === iso(e);
3100
+ const isEdge = (d) => isStart(d) || isEnd(d);
3101
+ const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
3102
+ const [activeDate, setActiveDate] = React23.useState(() => {
3103
+ if (s) return s;
3104
+ if (sameMonth(today, anchor.getFullYear(), anchor.getMonth())) return today;
3105
+ return new Date(anchor.getFullYear(), anchor.getMonth(), 1);
3106
+ });
3107
+ const calRef = React23.useRef(null);
3108
+ const pageToShow = (y, m) => {
3109
+ const idx = y * 12 + m, firstIdx = vy * 12 + vm, secondIdx = firstIdx + 1;
3110
+ if (idx === firstIdx || months > 1 && idx === secondIdx) return;
3111
+ if (idx < firstIdx || months === 1) {
3112
+ setVy(y);
3113
+ setVm(m);
3114
+ return;
3115
+ }
3116
+ const baseIdx = idx - 1;
3117
+ setVy(Math.floor(baseIdx / 12));
3118
+ setVm((baseIdx % 12 + 12) % 12);
3119
+ };
3120
+ const moveActive = (next) => {
3121
+ setActiveDate(next);
3122
+ pageToShow(next.getFullYear(), next.getMonth());
3123
+ };
3124
+ React23.useEffect(() => {
3125
+ const el = calRef.current?.querySelector('[data-iso="' + iso(activeDate) + '"]');
3126
+ if (el) el.focus({ preventScroll: true });
3127
+ }, [activeDate, vy, vm]);
3084
3128
  const clickDay = (d) => {
3129
+ setActiveDate(d);
3085
3130
  const v = iso(d);
3086
3131
  if (!range) {
3087
3132
  onPick(v);
@@ -3106,36 +3151,115 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3106
3151
  setVm(m);
3107
3152
  setVy(y);
3108
3153
  };
3154
+ const onGridKeyDown = (ev) => {
3155
+ const d = activeDate;
3156
+ switch (ev.key) {
3157
+ case "ArrowLeft":
3158
+ ev.preventDefault();
3159
+ moveActive(addDays(d, -1));
3160
+ return;
3161
+ case "ArrowRight":
3162
+ ev.preventDefault();
3163
+ moveActive(addDays(d, 1));
3164
+ return;
3165
+ case "ArrowUp":
3166
+ ev.preventDefault();
3167
+ moveActive(addDays(d, -7));
3168
+ return;
3169
+ case "ArrowDown":
3170
+ ev.preventDefault();
3171
+ moveActive(addDays(d, 7));
3172
+ return;
3173
+ case "Home":
3174
+ ev.preventDefault();
3175
+ moveActive(addDays(d, -d.getDay()));
3176
+ return;
3177
+ case "End":
3178
+ ev.preventDefault();
3179
+ moveActive(addDays(d, 6 - d.getDay()));
3180
+ return;
3181
+ case "PageUp":
3182
+ ev.preventDefault();
3183
+ moveActive(ev.shiftKey ? addYears(d, -1) : addMonths(d, -1));
3184
+ return;
3185
+ case "PageDown":
3186
+ ev.preventDefault();
3187
+ moveActive(ev.shiftKey ? addYears(d, 1) : addMonths(d, 1));
3188
+ return;
3189
+ case "Enter":
3190
+ case " ":
3191
+ ev.preventDefault();
3192
+ clickDay(d);
3193
+ return;
3194
+ default:
3195
+ return;
3196
+ }
3197
+ };
3198
+ const monthHeading = mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? String(vy) : vy - 5 + " \u2013 " + (vy + 6);
3199
+ 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);
3200
+ 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);
3109
3201
  const monthGrid = (y, m) => {
3110
3202
  const startPad = new Date(y, m, 1).getDay();
3203
+ const last = daysInMonth(y, m);
3111
3204
  const cells = [];
3112
- for (let i = 0; i < 42; i++) cells.push(new Date(y, m, i - startPad + 1));
3113
- return /* @__PURE__ */ jsxs37("div", { className: "fd-cal-grid", style: { width: months > 1 ? 252 : "auto", flex: "none" }, onMouseLeave: () => setHover(null), children: [
3114
- DOW.map((d) => /* @__PURE__ */ jsx44("span", { className: "fd-cal-dow", children: d }, d)),
3115
- cells.map((d, i) => /* @__PURE__ */ jsx44(
3116
- "button",
3117
- {
3118
- type: "button",
3119
- 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(" "),
3120
- onClick: () => clickDay(d),
3121
- onMouseEnter: () => range && setHover(iso(d)),
3122
- children: d.getDate()
3123
- },
3124
- i
3125
- ))
3126
- ] });
3205
+ for (let i = 0; i < 42; i++) {
3206
+ const dom = i - startPad + 1;
3207
+ cells.push(dom >= 1 && dom <= last ? new Date(y, m, dom) : null);
3208
+ }
3209
+ return /* @__PURE__ */ jsxs37(
3210
+ "div",
3211
+ {
3212
+ className: "fd-cal-grid",
3213
+ role: "grid",
3214
+ "aria-label": monthYearLabel(new Date(y, m, 1)),
3215
+ style: { width: months > 1 ? 252 : "auto", flex: "none" },
3216
+ onMouseLeave: () => setHover(null),
3217
+ children: [
3218
+ /* @__PURE__ */ jsx44("div", { className: "fd-cal-row", role: "row", children: DOW.map((d, i) => /* @__PURE__ */ jsx44("span", { className: "fd-cal-dow", role: "columnheader", "aria-label": weekdayLong(i), children: d }, d)) }),
3219
+ Array.from({ length: 6 }, (_, row) => /* @__PURE__ */ jsx44("div", { className: "fd-cal-row", role: "row", children: cells.slice(row * 7, row * 7 + 7).map((d, col) => {
3220
+ if (!d) return /* @__PURE__ */ jsx44("div", { className: "fd-cal-day is-empty", role: "presentation", "aria-hidden": "true" }, col);
3221
+ const today_ = iso(d) === iso(today);
3222
+ const start = isStart(d), end = isEnd(d), selected = isEdge(d);
3223
+ const bits = [];
3224
+ if (range && start) bits.push("start date");
3225
+ if (range && end) bits.push("end date");
3226
+ if (selected && !range) bits.push("selected");
3227
+ if (today_) bits.push("today");
3228
+ const name = bits.length ? fullDateLabel(d) + ", " + bits.join(", ") : fullDateLabel(d);
3229
+ return /* @__PURE__ */ jsx44(
3230
+ "div",
3231
+ {
3232
+ "data-iso": iso(d),
3233
+ role: "gridcell",
3234
+ tabIndex: iso(d) === iso(activeDate) ? 0 : -1,
3235
+ "aria-label": name,
3236
+ "aria-selected": selected,
3237
+ "aria-current": today_ ? "date" : void 0,
3238
+ className: ["fd-cal-day", today_ ? "is-today" : "", inRange(d) ? "in-range" : "", selected ? "is-edge" : ""].filter(Boolean).join(" "),
3239
+ onClick: () => clickDay(d),
3240
+ onMouseEnter: () => range && setHover(iso(d)),
3241
+ onKeyDown: onGridKeyDown,
3242
+ onFocus: () => setActiveDate(d),
3243
+ children: d.getDate()
3244
+ },
3245
+ col
3246
+ );
3247
+ }) }, row))
3248
+ ]
3249
+ }
3250
+ );
3127
3251
  };
3128
- const nextY = vm === 11 ? vy + 1 : vy, nextM = (vm + 1) % 12;
3129
- return /* @__PURE__ */ jsxs37("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, children: [
3252
+ return /* @__PURE__ */ jsxs37("div", { className: "fd-cal", style: { width: months > 1 && mode2 === "days" ? "auto" : void 0 }, ref: calRef, children: [
3130
3253
  /* @__PURE__ */ jsxs37("div", { className: "fd-cal-head", children: [
3131
- /* @__PURE__ */ jsx44("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__ */ jsx44("i", { className: "ph ph-caret-left" }) }),
3254
+ /* @__PURE__ */ jsx44("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__ */ jsx44("i", { className: "ph ph-caret-left" }) }),
3132
3255
  /* @__PURE__ */ jsxs37("button", { type: "button", className: "fd-cal-title", onClick: () => setMode(mode2 === "days" ? "months" : mode2 === "months" ? "years" : "days"), children: [
3133
- mode2 === "days" ? MONTHS[vm] + " " + vy : mode2 === "months" ? vy : vy - 5 + " \u2013 " + (vy + 6),
3256
+ monthHeading,
3134
3257
  /* @__PURE__ */ jsx44("i", { className: "ph ph-caret-down", style: { fontSize: 10, marginLeft: 6, color: "var(--text-muted)" } })
3135
3258
  ] }),
3136
3259
  months > 1 && mode2 === "days" ? /* @__PURE__ */ jsx44("span", { className: "fd-cal-title", style: { cursor: "default", background: "none" }, children: MONTHS[nextM] + " " + nextY }) : null,
3137
- /* @__PURE__ */ jsx44("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__ */ jsx44("i", { className: "ph ph-caret-right" }) })
3260
+ /* @__PURE__ */ jsx44("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__ */ jsx44("i", { className: "ph ph-caret-right" }) })
3138
3261
  ] }),
3262
+ /* @__PURE__ */ jsx44("span", { "aria-live": "polite", className: "fd-sr-only", children: monthHeading }),
3139
3263
  mode2 === "days" ? /* @__PURE__ */ jsxs37("div", { style: { display: "flex", gap: 18 }, children: [
3140
3264
  monthGrid(vy, vm),
3141
3265
  months > 1 ? monthGrid(nextY, nextM) : null
@@ -3175,6 +3299,7 @@ function Calendar({ value, range = false, onPick, initialMonth, months = 1 }) {
3175
3299
  setVy(today.getFullYear());
3176
3300
  setVm(today.getMonth());
3177
3301
  setMode("days");
3302
+ moveActive(today);
3178
3303
  },
3179
3304
  children: "Today"
3180
3305
  }