@jirawatpyk/aura-react 5.1.0 → 5.1.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.
Files changed (42) hide show
  1. package/dist/aura.bundle.js +418 -148
  2. package/dist/cjs/index.cjs +418 -148
  3. package/dist/esm/AppShell.js +10 -2
  4. package/dist/esm/Avatar.js +4 -3
  5. package/dist/esm/BottomNav.js +2 -1
  6. package/dist/esm/Checkbox.js +3 -2
  7. package/dist/esm/Combobox.js +19 -19
  8. package/dist/esm/Command.js +1 -0
  9. package/dist/esm/DataTable.js +44 -14
  10. package/dist/esm/DatePicker.js +81 -18
  11. package/dist/esm/DropdownMenu.js +12 -0
  12. package/dist/esm/FileUpload.js +15 -0
  13. package/dist/esm/FormErrorSummary.js +19 -4
  14. package/dist/esm/Menu.js +20 -7
  15. package/dist/esm/NumberField.js +3 -1
  16. package/dist/esm/Pagination.js +3 -3
  17. package/dist/esm/Popover.js +11 -1
  18. package/dist/esm/RadioGroup.js +14 -1
  19. package/dist/esm/SideNav.js +2 -1
  20. package/dist/esm/Switch.js +1 -1
  21. package/dist/esm/Table.js +3 -2
  22. package/dist/esm/Tabs.js +11 -7
  23. package/dist/esm/TextField.js +2 -2
  24. package/dist/esm/Textarea.js +2 -2
  25. package/dist/esm/ThemeStyle.js +13 -3
  26. package/dist/esm/Toaster.js +1 -0
  27. package/dist/esm/Tooltip.js +54 -29
  28. package/dist/esm/colorScheme.js +7 -3
  29. package/dist/esm/colorSchemeScript.js +3 -3
  30. package/dist/esm/dates.js +6 -3
  31. package/dist/esm/internal.js +18 -7
  32. package/dist/esm/locale.js +6 -5
  33. package/dist/esm/theme.js +3 -1
  34. package/dist/esm/useModal.js +31 -8
  35. package/dist/index.d.cts +1508 -0
  36. package/dist/index.d.ts +1 -1
  37. package/dist/server/index.cjs +6 -4
  38. package/dist/server/index.d.cts +176 -0
  39. package/dist/server/index.js +6 -4
  40. package/dist/styles.css +19 -3
  41. package/dist/styles.layer.css +19 -3
  42. package/package.json +19 -8
@@ -17,16 +17,24 @@ const AppShell = React.forwardRef(function AppShell2(props, ref) {
17
17
  [wide]
18
18
  );
19
19
  const navEl = props.nav && React.isValidElement(props.nav) ? props.nav : null;
20
+ const shared = !!navEl && navEl.props.value === void 0 && (navEl.props.defaultValue !== void 0 || navEl.props.sections !== void 0 || navEl.props.items !== void 0);
21
+ const navState = React.useState(navEl ? navEl.props.defaultValue : void 0);
22
+ function onNav(id) {
23
+ if (shared) navState[1](id);
24
+ if (navEl && navEl.props.onChange) navEl.props.onChange(id);
25
+ }
26
+ const deskNav = navEl && shared ? React.cloneElement(navEl, { value: navState[0], onChange: onNav }) : props.nav;
20
27
  const drawerNav = navEl ? React.cloneElement(navEl, {
28
+ value: shared ? navState[0] : navEl.props.value,
21
29
  onChange: function(id) {
22
- if (navEl.props.onChange) navEl.props.onChange(id);
30
+ onNav(id);
23
31
  setOpen(false);
24
32
  },
25
33
  className: cx(navEl.props.className, "is-in-drawer"),
26
34
  collapsed: false,
27
35
  collapsible: false
28
36
  }) : props.nav;
29
- return /* @__PURE__ */ React.createElement("div", { ref, className: cx("aura-shell", props.bottomNav && "aura-shell--bottomnav", props.className) }, props.nav ? /* @__PURE__ */ React.createElement("div", { className: "aura-shell__nav" }, props.nav) : null, props.nav ? /* @__PURE__ */ React.createElement(
37
+ return /* @__PURE__ */ React.createElement("div", { ref, className: cx("aura-shell", props.bottomNav && "aura-shell--bottomnav", props.className) }, props.nav ? /* @__PURE__ */ React.createElement("div", { className: "aura-shell__nav" }, deskNav) : null, props.nav ? /* @__PURE__ */ React.createElement(
30
38
  Drawer,
31
39
  {
32
40
  open,
@@ -7,7 +7,7 @@ function initials(name) {
7
7
  return ((parts[0] || "?")[0] + (parts.length > 1 ? parts[parts.length - 1][0] : parts[0][1] || "")).toUpperCase();
8
8
  }
9
9
  const Avatar = React.forwardRef(function Avatar2(props, ref) {
10
- const size = props.size || "md", errState = React.useState(false);
10
+ const size = props.size || "md", errState = React.useState(null);
11
11
  let hash = 0;
12
12
  String(props.name || "").split("").forEach(function(ch) {
13
13
  hash = hash * 31 + ch.charCodeAt(0) >>> 0;
@@ -21,13 +21,14 @@ const Avatar = React.forwardRef(function Avatar2(props, ref) {
21
21
  role: "img",
22
22
  "aria-label": props.name + (props.status ? ", " + props.status : "")
23
23
  },
24
- props.src && !errState[0] ? /* @__PURE__ */ React.createElement(
24
+ props.src && errState[0] !== props.src ? /* @__PURE__ */ React.createElement(
25
25
  "img",
26
26
  {
27
+ key: props.src,
27
28
  src: props.src,
28
29
  alt: "",
29
30
  onError: function() {
30
- errState[1](true);
31
+ errState[1](props.src || null);
31
32
  }
32
33
  }
33
34
  ) : /* @__PURE__ */ React.createElement("span", { "aria-hidden": true }, initials(props.name)),
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import * as React from "react";
3
3
  import { Icon } from "./Icon.js";
4
- import { cx, useMaybeControlled } from "./internal.js";
4
+ import { cx, plainClick, useMaybeControlled } from "./internal.js";
5
5
  import { useLinkComponent, useStrings } from "./locale.js";
6
6
  const BottomNav = React.forwardRef(function BottomNav2(props, ref) {
7
7
  const t = useStrings();
@@ -28,6 +28,7 @@ const BottomNav = React.forwardRef(function BottomNav2(props, ref) {
28
28
  "aria-current": on ? "page" : void 0,
29
29
  onClick: function(e) {
30
30
  if (!it.href) e.preventDefault();
31
+ else if (!plainClick(e)) return;
31
32
  st[1](it.id);
32
33
  }
33
34
  };
@@ -1,11 +1,12 @@
1
1
  'use client';
2
2
  import * as React from "react";
3
- import { cx, devWarnOnce, omit, useMergedRef, useMaybeControlled } from "./internal.js";
3
+ import { cx, devWarnOnce, omit, uid, useMergedRef, useMaybeControlled } from "./internal.js";
4
4
  import { Icon } from "./Icon.js";
5
5
  const Checkbox = React.forwardRef(function Checkbox2(props, ref) {
6
6
  const own = React.useRef(null), merged = useMergedRef(ref, own);
7
7
  const st = useMaybeControlled(props.checked, !!props.defaultChecked, props.onChange);
8
8
  const on = !!st[0];
9
+ const auto = uid();
9
10
  React.useEffect(function() {
10
11
  if (own.current) own.current.indeterminate = !!props.indeterminate;
11
12
  });
@@ -29,7 +30,7 @@ const Checkbox = React.forwardRef(function Checkbox2(props, ref) {
29
30
  "checkbox-label",
30
31
  "Checkbox `label` is only the accessible name: it is not shown. In 6.0 it will be shown beside the box, like Switch and TextField. For visible text now pass it as children; for a bare box (a table row) add `hideLabel`."
31
32
  );
32
- const descId = props.description && props.id ? props.id + "-desc" : void 0;
33
+ const descId = props.description ? (props.id || auto) + "-desc" : void 0;
33
34
  return /* @__PURE__ */ React.createElement(
34
35
  "label",
35
36
  {
@@ -82,7 +82,7 @@ const Combobox = React.forwardRef(
82
82
  function() {
83
83
  if (open) place();
84
84
  },
85
- [open, shown.length]
85
+ [open, shown.length, values.length]
86
86
  );
87
87
  React.useEffect(
88
88
  function() {
@@ -114,6 +114,7 @@ const Combobox = React.forwardRef(
114
114
  },
115
115
  [activeIdx, open]
116
116
  );
117
+ const live = props.loading ? [] : shown;
117
118
  function openList() {
118
119
  if (!open && !props.disabled && !props.readOnly) {
119
120
  setOpen(true);
@@ -149,7 +150,7 @@ const Combobox = React.forwardRef(
149
150
  if (k === "ArrowDown") {
150
151
  e.preventDefault();
151
152
  if (!open) openList();
152
- else setActive(Math.min(activeIdx + 1, shown.length - 1));
153
+ else setActive(Math.max(0, Math.min(activeIdx + 1, live.length - 1)));
153
154
  } else if (k === "ArrowUp") {
154
155
  e.preventDefault();
155
156
  if (!open) openList();
@@ -159,21 +160,22 @@ const Combobox = React.forwardRef(
159
160
  setActive(0);
160
161
  } else if (k === "End" && open) {
161
162
  e.preventDefault();
162
- setActive(shown.length - 1);
163
+ setActive(Math.max(0, live.length - 1));
163
164
  } else if (k === "Enter") {
164
- if (open && shown[activeIdx]) {
165
+ if (e.nativeEvent.isComposing || e.keyCode === 229) return;
166
+ if (open && live[activeIdx]) {
165
167
  e.preventDefault();
166
- choose(shown[activeIdx]);
168
+ choose(live[activeIdx]);
167
169
  }
168
170
  } else if (k === "Escape") {
169
171
  if (open) {
170
172
  e.preventDefault();
171
173
  e.stopPropagation();
172
174
  close();
173
- } else if (!multi && props.clearable !== false && value != null && query == null) {
175
+ } else if (!multi && !props.readOnly && props.clearable !== false && value != null && query == null) {
174
176
  setValue(null);
175
177
  }
176
- } else if (k === "Backspace" && multi && !text && values.length) {
178
+ } else if (k === "Backspace" && multi && !props.readOnly && !text && values.length) {
177
179
  setValues(values.slice(0, -1));
178
180
  } else if (k === "Tab") {
179
181
  if (open) close();
@@ -185,7 +187,7 @@ const Combobox = React.forwardRef(
185
187
  return id + "-opt-" + i;
186
188
  };
187
189
  const list = open && mounted && posState[0] ? createPortal(
188
- /* @__PURE__ */ React.createElement("div", { ref: listRef, className: "aura-combo__popover", style: posState[0] }, /* @__PURE__ */ React.createElement(
190
+ /* @__PURE__ */ React.createElement("div", { ref: listRef, className: "aura-combo__popover", style: posState[0] }, live.length ? /* @__PURE__ */ React.createElement(
189
191
  "ul",
190
192
  {
191
193
  id: listId,
@@ -194,7 +196,7 @@ const Combobox = React.forwardRef(
194
196
  "aria-multiselectable": multi || void 0,
195
197
  className: "aura-combo__list"
196
198
  },
197
- props.loading ? /* @__PURE__ */ React.createElement("li", { className: "aura-combo__note", role: "presentation" }, /* @__PURE__ */ React.createElement(Icon, { name: "loader-circle", className: "aura-spin" }), props.loadingText || t.searching) : !shown.length ? /* @__PURE__ */ React.createElement("li", { className: "aura-combo__note", role: "presentation" }, props.emptyText || t.noMatches) : shown.map(function(o, i) {
199
+ live.map(function(o, i) {
198
200
  const isSel = multi ? isPicked(o.value) : !!selected && o.value === selected.value;
199
201
  const blocked = o.disabled || multi && full && !isSel;
200
202
  return /* @__PURE__ */ React.createElement(
@@ -226,9 +228,8 @@ const Combobox = React.forwardRef(
226
228
  /* @__PURE__ */ React.createElement("span", { className: "aura-combo__text" }, /* @__PURE__ */ React.createElement("span", { className: "aura-combo__label" }, o.label), o.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-combo__desc" }, o.description) : null),
227
229
  isSel ? /* @__PURE__ */ React.createElement(Icon, { name: "check", className: "aura-combo__check" }) : null
228
230
  );
229
- }),
230
- more && !props.loading ? /* @__PURE__ */ React.createElement("li", { className: "aura-combo__note", role: "presentation" }, t.keepTyping((props.options || []).length)) : null
231
- )),
231
+ })
232
+ ) : null, props.loading || !live.length || more ? /* @__PURE__ */ React.createElement("div", { className: "aura-combo__list", role: "status" }, props.loading ? /* @__PURE__ */ React.createElement("div", { className: "aura-combo__note" }, /* @__PURE__ */ React.createElement(Icon, { name: "loader-circle", className: "aura-spin" }), props.loadingText || t.searching) : !live.length ? /* @__PURE__ */ React.createElement("div", { className: "aura-combo__note" }, props.emptyText || t.noMatches) : /* @__PURE__ */ React.createElement("div", { className: "aura-combo__note" }, t.keepTyping((props.options || []).length))) : null),
232
233
  document.body
233
234
  ) : null;
234
235
  return /* @__PURE__ */ React.createElement(
@@ -267,9 +268,9 @@ const Combobox = React.forwardRef(
267
268
  ));
268
269
  })) : null, multi ? /* @__PURE__ */ React.createElement("span", { id: summaryId, className: "aura-sr-only" }, picked.length ? t.selectedCount(picked.length) + ": " + picked.map(function(o) {
269
270
  return o.label;
270
- }).join(", ") : "") : null, multi && props.name ? values.map(function(v) {
271
+ }).join(", ") : "") : null, props.name ? multi ? values.map(function(v) {
271
272
  return /* @__PURE__ */ React.createElement("input", { key: v, type: "hidden", name: props.name, value: v });
272
- }) : null, /* @__PURE__ */ React.createElement(
273
+ }) : /* @__PURE__ */ React.createElement("input", { type: "hidden", name: props.name, value: value == null ? "" : value }) : null, /* @__PURE__ */ React.createElement(
273
274
  "input",
274
275
  {
275
276
  ref: inputMerged,
@@ -278,17 +279,16 @@ const Combobox = React.forwardRef(
278
279
  role: "combobox",
279
280
  className: "aura-input__control",
280
281
  autoComplete: "off",
281
- "aria-expanded": open,
282
- "aria-controls": listId,
282
+ "aria-expanded": open && live.length > 0,
283
+ "aria-controls": open && live.length ? listId : void 0,
283
284
  "aria-autocomplete": "list",
284
- "aria-activedescendant": open && shown[activeIdx] ? optId(activeIdx) : void 0,
285
+ "aria-activedescendant": open && live[activeIdx] ? optId(activeIdx) : void 0,
285
286
  "aria-invalid": props.error ? true : void 0,
286
287
  "aria-describedby": [props.error ? id + "-error" : props.hint ? id + "-hint" : "", multi && picked.length ? summaryId : ""].filter(Boolean).join(" ") || void 0,
287
288
  placeholder: multi && values.length ? void 0 : props.placeholder,
288
289
  disabled: props.disabled,
289
290
  readOnly: props.readOnly,
290
291
  required: props.required && (!multi || !values.length),
291
- name: multi ? void 0 : props.name,
292
292
  value: text,
293
293
  onChange: function(e) {
294
294
  setQuery(e.target.value);
@@ -306,7 +306,7 @@ const Combobox = React.forwardRef(
306
306
  }, 0);
307
307
  }
308
308
  }
309
- ), props.clearable !== false && values.length && !props.disabled ? /* @__PURE__ */ React.createElement(
309
+ ), props.clearable !== false && values.length && !props.disabled && !props.readOnly ? /* @__PURE__ */ React.createElement(
310
310
  "button",
311
311
  {
312
312
  type: "button",
@@ -120,6 +120,7 @@ function Command(props) {
120
120
  e.preventDefault();
121
121
  move("last");
122
122
  } else if (e.key === "Enter") {
123
+ if (e.nativeEvent.isComposing || e.keyCode === 229) return;
123
124
  e.preventDefault();
124
125
  if (active >= 0) run(flat[active]);
125
126
  }
@@ -35,7 +35,7 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
35
35
  byKey[c.key] = c;
36
36
  });
37
37
  const rows = props.rows || [];
38
- const rowKey = props.rowKey || columns[0].key;
38
+ const rowKey = props.rowKey || (columns[0] ? columns[0].key : "id");
39
39
  const manual = !!props.manual;
40
40
  const Link = useLinkComponent(props.linkComponent);
41
41
  const busy = !!props.loading;
@@ -265,6 +265,7 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
265
265
  if (isPinned(c)) s["--aura-cell-left"] = "calc(var(--aura-space-6)" + selW + " + " + pinOffsets[c.key] + "px)";
266
266
  return s;
267
267
  }
268
+ const sortCol = sort && sort.key ? byKey[sort.key] : void 0;
268
269
  const view = React.useMemo(
269
270
  function() {
270
271
  if (manual || !sort || !sort.key || !byKey[sort.key]) return rows;
@@ -283,7 +284,16 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
283
284
  return p[0];
284
285
  });
285
286
  },
286
- [rows, manual, sort && sort.key, sort && sort.dir]
287
+ [
288
+ rows,
289
+ manual,
290
+ sort && sort.key,
291
+ sort && sort.dir,
292
+ !!sortCol,
293
+ sortCol && sortCol.sortValue,
294
+ sortCol && sortCol.pill,
295
+ sortCol && sortCol.tones
296
+ ]
287
297
  );
288
298
  function nextSort(key) {
289
299
  if (!sort || sort.key !== key) return { key, dir: "asc" };
@@ -292,14 +302,23 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
292
302
  }
293
303
  const pageSize = props.pageSize || 0;
294
304
  const total = manual ? props.totalRows != null ? props.totalRows : (Math.max(1, pageState[0] || 1) - 1) * pageSize + rows.length + (pageSize && rows.length >= pageSize ? 1 : 0) : view.length;
295
- const pageCount = pageSize ? Math.max(1, Math.ceil(total / pageSize)) : 1;
305
+ const pageCount = pageSize ? Math.max(1, Math.ceil(total / pageSize), manual && props.totalRows == null ? pageState[0] || 1 : 1) : 1;
296
306
  const page = Math.min(Math.max(1, pageState[0] || 1), pageCount);
297
307
  const first = pageSize ? (page - 1) * pageSize : 0;
298
308
  const pageRows = pageSize && !manual ? view.slice(first, first + pageSize) : view;
299
309
  const canSortAny = !busy && (manual ? total > 1 : rows.length > 1);
300
310
  const shownTotal = manual && props.totalRows == null ? first + rows.length : total;
301
311
  const linkPaging = !!props.getPageHref && !props.onPageChange && !oneCallback;
302
- const prevLink = React.useRef(null), nextLink = React.useRef(null);
312
+ const prevLink = React.useRef(null), nextLink = React.useRef(null), jumpLink = React.useRef(null);
313
+ const jumpState = React.useState(null);
314
+ React.useEffect(
315
+ function() {
316
+ if (jumpState[0] == null) return;
317
+ if (jumpLink.current) jumpLink.current.click();
318
+ jumpState[1](null);
319
+ },
320
+ [jumpState[0]]
321
+ );
303
322
  function emit(s, p) {
304
323
  if (props.onStateChange) props.onStateChange({ sort: s, page: p });
305
324
  }
@@ -310,6 +329,7 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
310
329
  if (linkPaging) {
311
330
  const a = next === page - 1 ? prevLink.current : next === page + 1 ? nextLink.current : null;
312
331
  if (a) a.click();
332
+ else jumpState[1](next);
313
333
  return false;
314
334
  }
315
335
  if (focus) pending.current = focus;
@@ -346,7 +366,8 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
346
366
  }
347
367
  const height = props.height || 0;
348
368
  const virtual = !!height && !loading && pageRows.length > 0 && !stacked;
349
- const bodyH = Math.max(ROW_H, height - ROW_H);
369
+ const stickyTotal = !!(props.footer && props.stickyFooter && rows.length && !loading);
370
+ const bodyH = Math.max(ROW_H, height - ROW_H - (stickyTotal ? ROW_H : 0));
350
371
  let start = 0, end = pageRows.length;
351
372
  if (virtual) {
352
373
  start = Math.max(0, Math.floor(scrollTop / ROW_H) - OVERSCAN);
@@ -376,6 +397,11 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
376
397
  });
377
398
  c = at >= 0 ? at + (selectable ? 1 : 0) : Math.min(p.c || 0, nCols - 1);
378
399
  }
400
+ const ae = document.activeElement;
401
+ if (ae && ae !== document.body && !gridRef.current.contains(ae)) {
402
+ pending.current = null;
403
+ return;
404
+ }
379
405
  const el = gridRef.current.querySelector('[data-rc="' + p.r + ":" + c + '"]');
380
406
  if (el) {
381
407
  pending.current = null;
@@ -405,26 +431,28 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
405
431
  });
406
432
  const selSet = {};
407
433
  selected.forEach(function(k) {
408
- selSet[k] = true;
434
+ selSet[String(k)] = true;
409
435
  });
410
436
  const nSel = pageKeys.filter(function(k) {
411
- return selSet[k];
437
+ return selSet[String(k)];
412
438
  }).length;
413
439
  const all = nSel > 0 && nSel === pageKeys.length;
414
440
  function toggle(k, on) {
415
441
  setSelected(
416
442
  on ? selected.concat([k]) : selected.filter(function(x) {
417
- return x !== k;
443
+ return String(x) !== String(k);
418
444
  })
419
445
  );
420
446
  }
421
447
  function toggleAll() {
422
448
  setSelected(
423
449
  all ? selected.filter(function(k) {
424
- return pageKeys.indexOf(k) < 0;
450
+ return !pageKeys.some(function(p) {
451
+ return String(p) === String(k);
452
+ });
425
453
  }) : selected.concat(
426
454
  pageKeys.filter(function(k) {
427
- return !selSet[k];
455
+ return !selSet[String(k)];
428
456
  })
429
457
  )
430
458
  );
@@ -1025,7 +1053,7 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
1025
1053
  }
1026
1054
  );
1027
1055
  }
1028
- if (pageSize && (rows.length || busy)) {
1056
+ if (pageSize && (rows.length || busy || page > 1)) {
1029
1057
  const from = rows.length ? first + 1 : 0, to = manual ? first + rows.length : Math.min(first + pageSize, view.length);
1030
1058
  foot = /* @__PURE__ */ React.createElement("div", { className: "aura-table__foot" }, /* @__PURE__ */ React.createElement("span", { "aria-live": "polite" }, busy ? t.loading : t.range(from, to, shownTotal)), /* @__PURE__ */ React.createElement("span", { className: "aura-table__pager" }, /* @__PURE__ */ React.createElement("span", null, t.page(page, pageCount)), pagerButton(-1), pagerButton(1)));
1031
1059
  } else if (height && rows.length && !loading) {
@@ -1076,7 +1104,8 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
1076
1104
  ) : null;
1077
1105
  const scrollStyle = {
1078
1106
  scrollPaddingLeft: "calc(var(--aura-space-6)" + selW + " + " + acc + "px)",
1079
- scrollPaddingTop: ROW_H + "px"
1107
+ scrollPaddingTop: ROW_H + "px",
1108
+ scrollPaddingBottom: stickyTotal ? ROW_H + "px" : void 0
1080
1109
  };
1081
1110
  if (height) scrollStyle["--aura-table-h"] = height + "px";
1082
1111
  const gridEl = /* @__PURE__ */ React.createElement(
@@ -1110,7 +1139,7 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
1110
1139
  role: "grid",
1111
1140
  "aria-label": props.label,
1112
1141
  "aria-busy": busy || void 0,
1113
- "aria-rowcount": loading ? -1 : shownTotal + 1 + (totalRow ? 1 : 0),
1142
+ "aria-rowcount": loading || manual && props.totalRows == null && pageSize && rows.length >= pageSize ? -1 : shownTotal + 1 + (totalRow ? 1 : 0),
1114
1143
  "aria-colcount": nCols,
1115
1144
  "aria-multiselectable": selectable || void 0,
1116
1145
  onKeyDown: onGridKey,
@@ -1158,7 +1187,8 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
1158
1187
  items: menu.kind === "picker" ? pickerItems() : byKey[menu.key] ? columnMenuItems(byKey[menu.key]) : []
1159
1188
  }
1160
1189
  ) : null,
1161
- tipEl
1190
+ tipEl,
1191
+ jumpState[0] != null && props.getPageHref ? /* @__PURE__ */ React.createElement(Link, { ref: jumpLink, href: props.getPageHref(jumpState[0]), hidden: true, tabIndex: -1, "aria-hidden": true }) : null
1162
1192
  );
1163
1193
  if (!levels.length) return gridEl;
1164
1194
  let out = gridEl;
@@ -38,14 +38,37 @@ function useFormatDate() {
38
38
  [locale, calendar]
39
39
  );
40
40
  }
41
+ function allowedDate(iso, o) {
42
+ const t = o.min === "today" || o.max === "today" ? o.today && fromISO(o.today) ? o.today : todayIn(o.timeZone) : "";
43
+ const lo = o.min === "today" ? t : o.min, hi = o.max === "today" ? t : o.max;
44
+ if (lo && fromISO(lo) && iso < lo) return false;
45
+ if (hi && fromISO(hi) && iso > hi) return false;
46
+ return !(o.isDateDisabled && o.isDateDisabled(iso));
47
+ }
41
48
  const Calendar = React.forwardRef(function Calendar2(props, ref) {
42
49
  const ctx = useAuraLocale(), locale = props.locale || ctx.locale || "en", calendar = props.calendar || ctx.calendar || defaultCalendar(locale), tag = localeTag(locale, calendar);
43
50
  const weekStart = props.weekStartsOn == null ? locale === "sv" ? 1 : 0 : props.weekStartsOn;
44
- const todayISO = (props.today && fromISO(props.today) ? props.today : null) || todayIn(props.timeZone || ctx.timeZone);
51
+ const given = props.today && fromISO(props.today) ? props.today : null, zone = props.timeZone || ctx.timeZone;
52
+ const todayISO = given || todayIn(zone);
45
53
  const today = fromISO(todayISO);
54
+ const mounted = useMounted(), gridKey = given || mounted ? "client" : "server";
46
55
  const min = fromISO(props.min === "today" ? todayISO : props.min), max = fromISO(props.max === "today" ? todayISO : props.max);
47
56
  const start = fromISO(props.start), end = fromISO(props.end);
48
- const focusState = React.useState(fromISO(props.focus) || start || today);
57
+ function disabledAt(d) {
58
+ return !!(min && d < min || max && d > max || props.isDateDisabled && props.isDateDisabled(toISO(d)));
59
+ }
60
+ function select(iso) {
61
+ if (props.onSelect) props.onSelect(iso);
62
+ }
63
+ const focusState = React.useState(function() {
64
+ const d0 = fromISO(props.focus) || start || today;
65
+ if (!disabledAt(d0)) return d0;
66
+ for (let i = 1; i <= 366; i++) {
67
+ if (!disabledAt(addDays(d0, i))) return addDays(d0, i);
68
+ if (!disabledAt(addDays(d0, -i))) return addDays(d0, -i);
69
+ }
70
+ return d0;
71
+ });
49
72
  const focusDate = focusState[0], setFocus = focusState[1];
50
73
  const viewState = React.useState("days"), view = viewState[0], setView = viewState[1];
51
74
  const hoverState = React.useState(null);
@@ -53,7 +76,7 @@ const Calendar = React.forwardRef(function Calendar2(props, ref) {
53
76
  const th = locale === "th";
54
77
  const dt = dateText(locale);
55
78
  function disabled(d) {
56
- return !!(min && d < min || max && d > max || props.isDateDisabled && props.isDateDisabled(toISO(d)));
79
+ return disabledAt(d);
57
80
  }
58
81
  React.useEffect(function() {
59
82
  if (!moved.current) return;
@@ -61,11 +84,14 @@ const Calendar = React.forwardRef(function Calendar2(props, ref) {
61
84
  const el = gridRef.current && gridRef.current.querySelector('[data-date="' + toISO(focusDate) + '"]');
62
85
  if (el) el.focus();
63
86
  });
64
- React.useEffect(function() {
65
- if (props.autoFocus === false) return;
66
- const el = gridRef.current && gridRef.current.querySelector('[tabindex="0"]');
67
- if (el) el.focus();
68
- }, []);
87
+ React.useEffect(
88
+ function() {
89
+ if (props.autoFocus === false) return;
90
+ const el = gridRef.current && gridRef.current.querySelector('[tabindex="0"]');
91
+ if (el) el.focus();
92
+ },
93
+ [gridKey]
94
+ );
69
95
  function move(d) {
70
96
  moved.current = true;
71
97
  setFocus(d);
@@ -90,7 +116,7 @@ const Calendar = React.forwardRef(function Calendar2(props, ref) {
90
116
  else if (k === "PageDown") n = addMonths(d, e.shiftKey ? 12 : 1);
91
117
  else if (k === "Enter" || k === " ") {
92
118
  e.preventDefault();
93
- if (!disabled(d)) props.onSelect(toISO(d));
119
+ if (!disabled(d)) select(toISO(d));
94
120
  return;
95
121
  }
96
122
  if (n) {
@@ -113,7 +139,7 @@ const Calendar = React.forwardRef(function Calendar2(props, ref) {
113
139
  const yr = focusDate.getFullYear(), base = yr - yr % 12;
114
140
  const years = [];
115
141
  for (let y = base; y < base + 12; y++) years.push(y);
116
- return /* @__PURE__ */ React.createElement("div", { className: "aura-cal", ref: gridMerged }, /* @__PURE__ */ React.createElement("div", { className: "aura-cal__head" }, /* @__PURE__ */ React.createElement(
142
+ return /* @__PURE__ */ React.createElement("div", { className: "aura-cal", ref: gridMerged, key: gridKey }, /* @__PURE__ */ React.createElement("div", { className: "aura-cal__head" }, /* @__PURE__ */ React.createElement(
117
143
  IconButton,
118
144
  {
119
145
  icon: "chevron-left",
@@ -160,7 +186,7 @@ const Calendar = React.forwardRef(function Calendar2(props, ref) {
160
186
  );
161
187
  })));
162
188
  }
163
- return /* @__PURE__ */ React.createElement("div", { className: "aura-cal", ref: gridMerged }, /* @__PURE__ */ React.createElement("div", { className: "aura-cal__head" }, /* @__PURE__ */ React.createElement(
189
+ return /* @__PURE__ */ React.createElement("div", { className: "aura-cal", ref: gridMerged, key: gridKey }, /* @__PURE__ */ React.createElement("div", { className: "aura-cal__head" }, /* @__PURE__ */ React.createElement(
164
190
  IconButton,
165
191
  {
166
192
  icon: "chevron-left",
@@ -222,7 +248,7 @@ const Calendar = React.forwardRef(function Calendar2(props, ref) {
222
248
  type: "button",
223
249
  "data-date": iso,
224
250
  tabIndex: same(d, focusDate) ? 0 : -1,
225
- disabled: dis,
251
+ "aria-disabled": dis || void 0,
226
252
  "aria-label": fmt(tag, { weekday: "long", day: "numeric", month: "long", year: "numeric" }, d),
227
253
  suppressHydrationWarning: true,
228
254
  "aria-current": same(d, today) ? "date" : void 0,
@@ -235,7 +261,7 @@ const Calendar = React.forwardRef(function Calendar2(props, ref) {
235
261
  ),
236
262
  onClick: function() {
237
263
  setFocus(d);
238
- props.onSelect(iso);
264
+ if (!dis) select(iso);
239
265
  },
240
266
  onKeyDown: function(e) {
241
267
  onKey(e, d);
@@ -257,7 +283,7 @@ const Calendar = React.forwardRef(function Calendar2(props, ref) {
257
283
  disabled: disabled(today),
258
284
  onClick: function() {
259
285
  move(today);
260
- props.onSelect(toISO(today));
286
+ select(toISO(today));
261
287
  }
262
288
  },
263
289
  dt.today
@@ -391,13 +417,30 @@ const DatePicker = React.forwardRef(function DatePicker2(props, ref) {
391
417
  );
392
418
  const boxRef = React.useRef(null), inputRef = React.useRef(null), inputMerged = useMergedRef(ref, inputRef);
393
419
  const pop = useCalendarPopover(boxRef);
420
+ const limits = {
421
+ min: props.min,
422
+ max: props.max,
423
+ today: props.today,
424
+ timeZone: props.timeZone || ctx.timeZone,
425
+ isDateDisabled: props.isDateDisabled
426
+ };
427
+ const bad = React.useState(null);
428
+ React.useEffect(
429
+ function() {
430
+ bad[1](null);
431
+ },
432
+ [st[0]]
433
+ );
394
434
  function commit(text) {
435
+ bad[1](null);
395
436
  if (!text.trim()) {
396
437
  st[1](null);
397
438
  return;
398
439
  }
399
440
  const iso = parseDate(text);
400
- if (iso) st[1](iso);
441
+ if (!iso) return;
442
+ if (allowedDate(iso, limits)) st[1](iso);
443
+ else bad[1](dt.dateUnavailable);
401
444
  }
402
445
  function close() {
403
446
  pop.setOpen(false);
@@ -435,6 +478,7 @@ const DatePicker = React.forwardRef(function DatePicker2(props, ref) {
435
478
  start: st[0],
436
479
  focus: st[0],
437
480
  onSelect: function(iso) {
481
+ bad[1](null);
438
482
  st[1](iso);
439
483
  close();
440
484
  }
@@ -450,7 +494,7 @@ const DatePicker = React.forwardRef(function DatePicker2(props, ref) {
450
494
  dialogId,
451
495
  label: props.label,
452
496
  hint: props.hint,
453
- error: props.error,
497
+ error: bad[0] || props.error,
454
498
  required: props.required,
455
499
  optional: props.optional,
456
500
  disabled: props.disabled,
@@ -464,6 +508,7 @@ const DatePicker = React.forwardRef(function DatePicker2(props, ref) {
464
508
  hasValue: st[0] != null,
465
509
  clearable: props.clearable,
466
510
  onClear: function() {
511
+ bad[1](null);
467
512
  st[1](null);
468
513
  inputRef.current && inputRef.current.focus();
469
514
  },
@@ -490,20 +535,36 @@ const DateRangePicker = React.forwardRef(
490
535
  const draft = React.useState(null);
491
536
  const boxRef = React.useRef(null), inputRef = React.useRef(null), inputMerged = useMergedRef(ref, inputRef);
492
537
  const pop = useCalendarPopover(boxRef);
538
+ const limits = {
539
+ min: props.min,
540
+ max: props.max,
541
+ today: props.today,
542
+ timeZone: props.timeZone || ctx.timeZone,
543
+ isDateDisabled: props.isDateDisabled
544
+ };
493
545
  const o = { locale, calendar };
494
546
  function show(r) {
495
547
  if (!r.start) return "";
496
548
  if (!r.end) return formatDateBase(r.start, o) + " \u2013";
497
549
  return formatDateBase(r.start, o) + " \u2013 " + formatDateBase(r.end, o);
498
550
  }
551
+ const bad = React.useState(null);
552
+ React.useEffect(
553
+ function() {
554
+ bad[1](null);
555
+ },
556
+ [v.start, v.end]
557
+ );
499
558
  function commit(text) {
559
+ bad[1](null);
500
560
  const parts = String(text).split(/\s[–-]\s|\s*–\s*/);
501
561
  if (!text.trim()) {
502
562
  st[1]({ start: null, end: null });
503
563
  return;
504
564
  }
505
565
  const a = parseDate(parts[0]), b = parseDate(parts[1] || "");
506
- if (a && b) st[1](a <= b ? { start: a, end: b } : { start: b, end: a });
566
+ if (a && b && !(allowedDate(a, limits) && allowedDate(b, limits))) bad[1](dt.dateUnavailable);
567
+ else if (a && b) st[1](a <= b ? { start: a, end: b } : { start: b, end: a });
507
568
  }
508
569
  function close() {
509
570
  pop.setOpen(false);
@@ -516,6 +577,7 @@ const DateRangePicker = React.forwardRef(
516
577
  return;
517
578
  }
518
579
  const a = draft[0], b = iso;
580
+ bad[1](null);
519
581
  st[1](a <= b ? { start: a, end: b } : { start: b, end: a });
520
582
  close();
521
583
  }
@@ -566,7 +628,7 @@ const DateRangePicker = React.forwardRef(
566
628
  dialogId,
567
629
  label: props.label,
568
630
  hint: props.hint,
569
- error: props.error,
631
+ error: bad[0] || props.error,
570
632
  required: props.required,
571
633
  optional: props.optional,
572
634
  disabled: props.disabled,
@@ -580,6 +642,7 @@ const DateRangePicker = React.forwardRef(
580
642
  hasValue: v.start != null,
581
643
  clearable: props.clearable,
582
644
  onClear: function() {
645
+ bad[1](null);
583
646
  st[1]({ start: null, end: null });
584
647
  inputRef.current && inputRef.current.focus();
585
648
  },
@@ -6,6 +6,16 @@ const DropdownMenu = React.forwardRef(function DropdownMenu2(props, ref) {
6
6
  const st = React.useState(null), anchor = st[0], setAnchor = st[1];
7
7
  const wrap = React.useRef(null), wrapMerged = useMergedRef(ref, wrap);
8
8
  const child = React.Children.only(props.trigger);
9
+ const menuRef = React.useRef(null), toLast = React.useRef(false);
10
+ React.useEffect(
11
+ function() {
12
+ if (!anchor || !toLast.current || !menuRef.current) return;
13
+ toLast.current = false;
14
+ const list = menuRef.current.querySelectorAll('[role^="menuitem"]:not([disabled])');
15
+ if (list.length) list[list.length - 1].focus();
16
+ },
17
+ [anchor]
18
+ );
9
19
  function toggle(e) {
10
20
  if (child.props.onClick) child.props.onClick(e);
11
21
  const el = wrap.current && (wrap.current.querySelector('button, [role="button"], a') || wrap.current);
@@ -14,12 +24,14 @@ const DropdownMenu = React.forwardRef(function DropdownMenu2(props, ref) {
14
24
  function onKeyDown(e) {
15
25
  if ((e.key === "ArrowDown" || e.key === "ArrowUp") && !anchor) {
16
26
  e.preventDefault();
27
+ toLast.current = e.key === "ArrowUp";
17
28
  setAnchor(wrap.current.querySelector('button, [role="button"], a') || wrap.current);
18
29
  }
19
30
  }
20
31
  return /* @__PURE__ */ React.createElement("span", { ref: wrapMerged, className: "aura-dropdown", onKeyDown }, React.cloneElement(child, { onClick: toggle, "aria-haspopup": "menu", "aria-expanded": anchor ? true : false }), anchor ? /* @__PURE__ */ React.createElement(
21
32
  Menu,
22
33
  {
34
+ ref: menuRef,
23
35
  anchor,
24
36
  label: props.label,
25
37
  items: props.items,