@evinvest/uikit 0.17.0 → 0.17.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 CHANGED
@@ -188,8 +188,10 @@ measuring needs host-only `web-sys`). Known gaps:
188
188
  at day granularity (days outside render `disabled` + `data-disabled="true"`);
189
189
  `disabled` freezes the whole grid and the nav the same way; the nav buttons
190
190
  take label overrides. TS-only `locale` renders the caption and weekday headers through
191
- `Intl` (Monday-first); Rust has no `Intl`, so its captions stay English. Rust
192
- does manual date math; TS uses the built-in `Date`.
191
+ `Intl` (Monday-first): `weekday: "short"`, falling back to `"narrow"` for a
192
+ locale whose short form contains whitespace (vi's "Thứ 2" → "T2", he's
193
+ "יום ב׳" → "ב׳") as long as narrow still yields seven distinct labels. Rust has no `Intl`, so its captions
194
+ stay English. Rust does manual date math; TS uses the built-in `Date`.
193
195
  - **date-time-picker:** the kit's own bricks only — an outline trigger, a
194
196
  `Popover` with the `Calendar` and two numeric 24-hour hours/minutes fields (no
195
197
  native `datetime-local` / `time` input, so the browser's locale popup never
package/dist/index.js CHANGED
@@ -234,9 +234,19 @@ function useFloating(opts) {
234
234
 
235
235
  // src/primitives/focus-scope.tsx
236
236
  import * as React6 from "react";
237
- var FOCUSABLE = 'a[href],button:not([disabled]),textarea:not([disabled]),input:not([disabled]),select:not([disabled]),[tabindex]:not([tabindex="-1"])';
237
+ var FOCUSABLE = [
238
+ "a[href]",
239
+ "button:not([disabled])",
240
+ "textarea:not([disabled])",
241
+ "input:not([disabled])",
242
+ "select:not([disabled])",
243
+ "[tabindex]"
244
+ ].map((sel) => `${sel}:not([tabindex="-1"])`).join(",");
245
+ function focusCandidates(root) {
246
+ return Array.from(root.querySelectorAll(FOCUSABLE));
247
+ }
238
248
  function focusable(root) {
239
- return Array.from(root.querySelectorAll(FOCUSABLE)).filter(
249
+ return focusCandidates(root).filter(
240
250
  (el) => el.offsetWidth > 0 || el.offsetHeight > 0 || el === document.activeElement
241
251
  );
242
252
  }
@@ -6970,7 +6980,7 @@ var CALENDAR_NAV = "flex items-center justify-between gap-1 w-full px-1";
6970
6980
  var CALENDAR_CAPTION = "text-sm font-medium select-none";
6971
6981
  var CALENDAR_GRID = "w-full border-collapse mt-4";
6972
6982
  var CALENDAR_WEEKDAY_ROW = "flex";
6973
- var CALENDAR_WEEKDAY = "text-ink-soft rounded-md w-9 shrink-0 font-normal text-[0.8rem] select-none";
6983
+ var CALENDAR_WEEKDAY = "text-ink-soft rounded-md w-9 shrink-0 font-normal text-[0.8rem] select-none whitespace-nowrap";
6974
6984
  var CALENDAR_WEEK = "flex w-full mt-2";
6975
6985
  var CALENDAR_DAY_EMPTY = "relative size-9 shrink-0 p-0 select-none";
6976
6986
  var CALENDAR_DAY_CELL = "relative size-9 shrink-0 p-0 text-center select-none";
@@ -7033,13 +7043,19 @@ function outOfRange(day, min, max) {
7033
7043
  return !!min && t < startOfDay(min).getTime() || !!max && t > startOfDay(max).getTime();
7034
7044
  }
7035
7045
  var MONDAY = new Date(2024, 0, 1);
7036
- function localisedWeekdays(locale) {
7037
- const fmt = new Intl.DateTimeFormat(locale, { weekday: "short" });
7046
+ function formatWeekdays(locale, weekday) {
7047
+ const fmt = new Intl.DateTimeFormat(locale, { weekday });
7038
7048
  return Array.from(
7039
7049
  { length: 7 },
7040
7050
  (_, i) => fmt.format(new Date(MONDAY.getFullYear(), MONDAY.getMonth(), MONDAY.getDate() + i))
7041
7051
  );
7042
7052
  }
7053
+ function localisedWeekdays(locale) {
7054
+ const short = formatWeekdays(locale, "short");
7055
+ if (!short.some((label) => /\s/.test(label))) return short;
7056
+ const narrow = formatWeekdays(locale, "narrow");
7057
+ return new Set(narrow).size === narrow.length ? narrow : short;
7058
+ }
7043
7059
  function Calendar({
7044
7060
  selected,
7045
7061
  onSelect,
@@ -7289,6 +7305,7 @@ function DateTimePicker({
7289
7305
  });
7290
7306
  const rootRef = React67.useRef(null);
7291
7307
  const hoursRef = React67.useRef(null);
7308
+ const focusTrigger = () => rootRef.current?.querySelector("[data-slot=date-time-picker-trigger]")?.focus();
7292
7309
  React67.useEffect(() => {
7293
7310
  if (!isOpen) return;
7294
7311
  hoursRef.current?.focus();
@@ -7296,9 +7313,7 @@ function DateTimePicker({
7296
7313
  const active = document.activeElement;
7297
7314
  const content = hoursRef.current?.closest("[data-slot=date-time-picker-content]");
7298
7315
  const lost = !active || active === document.body || !!content?.contains(active);
7299
- if (lost) {
7300
- rootRef.current?.querySelector("[data-slot=date-time-picker-trigger]")?.focus();
7301
- }
7316
+ if (lost) focusTrigger();
7302
7317
  };
7303
7318
  }, [isOpen]);
7304
7319
  const emit = (next) => setValue(clampMoment(atMinute(next), min, max));
@@ -7330,6 +7345,15 @@ function DateTimePicker({
7330
7345
  setValue(null);
7331
7346
  setOpen(false);
7332
7347
  };
7348
+ const onContentKeyDown = (e) => {
7349
+ if (e.key !== "Tab") return;
7350
+ const items = focusCandidates(e.currentTarget);
7351
+ const edge = e.shiftKey ? items[0] : items[items.length - 1];
7352
+ if (!edge || e.target !== edge) return;
7353
+ e.preventDefault();
7354
+ setOpen(false);
7355
+ focusTrigger();
7356
+ };
7333
7357
  const onContentBlur = (e) => {
7334
7358
  const next = e.relatedTarget;
7335
7359
  if (!(next instanceof Node)) return;
@@ -7383,6 +7407,7 @@ function DateTimePicker({
7383
7407
  "aria-label": labels.dialog ?? "Choose date and time",
7384
7408
  align,
7385
7409
  onBlur: onContentBlur,
7410
+ onKeyDown: onContentKeyDown,
7386
7411
  className: DATE_TIME_PICKER_CONTENT,
7387
7412
  children: [
7388
7413
  /* @__PURE__ */ jsx57(