@jirawatpyk/aura-react 4.18.0 → 4.19.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.
@@ -0,0 +1,47 @@
1
+ 'use client';
2
+ import * as React from "react";
3
+ import { Button } from "./Button.js";
4
+ import { cx } from "./internal.js";
5
+ import { useStrings } from "./locale.js";
6
+ const ActionBar = React.forwardRef(function ActionBar2(props, ref) {
7
+ const t = useStrings();
8
+ const bulk = props.selected != null;
9
+ const idle = bulk && !props.selected;
10
+ const count = bulk && props.selected ? t.selectedCount(props.selected) : null;
11
+ const cameFrom = React.useRef(null);
12
+ const own = React.useRef(null);
13
+ function clear() {
14
+ props.onClearSelection();
15
+ setTimeout(function() {
16
+ const back = cameFrom.current;
17
+ const a = document.activeElement;
18
+ if ((!a || a === document.body || !a.isConnected) && back && back.isConnected) back.focus();
19
+ }, 0);
20
+ }
21
+ return /* @__PURE__ */ React.createElement(
22
+ "div",
23
+ {
24
+ ref: function(el) {
25
+ own.current = el;
26
+ if (typeof ref === "function") ref(el);
27
+ else if (ref) ref.current = el;
28
+ },
29
+ onFocus: function(e) {
30
+ const from = e.relatedTarget;
31
+ if (from && own.current && !own.current.contains(from)) cameFrom.current = from;
32
+ },
33
+ role: "region",
34
+ "aria-label": props.label || t.actions,
35
+ className: cx(
36
+ "aura-actionbar",
37
+ "aura-actionbar--" + (props.position || "viewport"),
38
+ idle && "is-idle",
39
+ props.className
40
+ )
41
+ },
42
+ /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__inner" }, /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__status", role: "status" }, count, count && props.status ? " \xB7 " : null, props.status), !idle ? /* @__PURE__ */ React.createElement("div", { className: "aura-actionbar__actions" }, count && props.onClearSelection ? /* @__PURE__ */ React.createElement(Button, { variant: "ghost", size: "sm", onClick: clear }, t.clear()) : null, props.children) : null)
43
+ );
44
+ });
45
+ export {
46
+ ActionBar
47
+ };
@@ -26,7 +26,7 @@ const AppShell = React.forwardRef(function AppShell2(props, ref) {
26
26
  collapsed: false,
27
27
  collapsible: false
28
28
  }) : props.nav;
29
- return /* @__PURE__ */ React.createElement("div", { ref, className: cx("aura-shell", props.className) }, props.nav ? /* @__PURE__ */ React.createElement("div", { className: "aura-shell__nav" }, props.nav) : null, props.nav ? /* @__PURE__ */ React.createElement(
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(
30
30
  Drawer,
31
31
  {
32
32
  open,
@@ -51,7 +51,7 @@ const AppShell = React.forwardRef(function AppShell2(props, ref) {
51
51
  },
52
52
  "aria-expanded": open
53
53
  }
54
- ) : null, /* @__PURE__ */ React.createElement("div", { className: "aura-shell__bar-content" }, props.header)) : null, /* @__PURE__ */ React.createElement("main", { className: "aura-shell__content", id: props.mainId || "main" }, props.children)));
54
+ ) : null, /* @__PURE__ */ React.createElement("div", { className: "aura-shell__bar-content" }, props.header)) : null, /* @__PURE__ */ React.createElement("main", { className: "aura-shell__content", id: props.mainId || "main" }, props.children), props.bottomNav || null));
55
55
  });
56
56
  export {
57
57
  AppShell
@@ -0,0 +1,45 @@
1
+ 'use client';
2
+ import * as React from "react";
3
+ import { Icon } from "./Icon.js";
4
+ import { cx, useMaybeControlled } from "./internal.js";
5
+ import { useLinkComponent, useStrings } from "./locale.js";
6
+ const BottomNav = React.forwardRef(function BottomNav2(props, ref) {
7
+ const t = useStrings();
8
+ const Link = useLinkComponent(props.linkComponent);
9
+ const st = useMaybeControlled(
10
+ props.value,
11
+ props.defaultValue,
12
+ props.onChange
13
+ );
14
+ const active = st[0];
15
+ const hide = props.hideFrom === false ? "always" : "below-" + (props.hideFrom || "lg");
16
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: cx("aura-bottomnav-spacer", "aura-bottomnav--" + hide), "aria-hidden": "true" }), /* @__PURE__ */ React.createElement(
17
+ "nav",
18
+ {
19
+ ref,
20
+ className: cx("aura-bottomnav", "aura-bottomnav--" + hide, props.className),
21
+ "aria-label": props.label || t.mainNav
22
+ },
23
+ /* @__PURE__ */ React.createElement("ul", { className: "aura-bottomnav__list" }, props.items.map(function(it) {
24
+ const on = active === it.id;
25
+ const count = it.count != null && it.count > 0 ? it.count > 99 ? "99+" : String(it.count) : null;
26
+ const common = {
27
+ className: cx("aura-bottomnav__item", on && "is-active"),
28
+ "aria-current": on ? "page" : void 0,
29
+ onClick: function(e) {
30
+ if (!it.href) e.preventDefault();
31
+ st[1](it.id);
32
+ }
33
+ };
34
+ const inner = [
35
+ /* @__PURE__ */ React.createElement("span", { key: "i", className: "aura-bottomnav__icon" }, /* @__PURE__ */ React.createElement(Icon, { name: it.icon, size: "md" }), count ? /* @__PURE__ */ React.createElement("span", { className: "aura-bottomnav__count", "aria-hidden": "true" }, count) : it.badge ? /* @__PURE__ */ React.createElement("span", { className: "aura-bottomnav__dot", "aria-hidden": "true" }) : null),
36
+ /* @__PURE__ */ React.createElement("span", { key: "l", className: "aura-bottomnav__label" }, it.label),
37
+ count || it.badge && it.badgeLabel ? /* @__PURE__ */ React.createElement("span", { key: "s", className: "aura-sr-only" }, " (" + (count || it.badgeLabel) + ")") : null
38
+ ];
39
+ return /* @__PURE__ */ React.createElement("li", { key: it.id, className: "aura-bottomnav__cell" }, it.href ? /* @__PURE__ */ React.createElement(Link, { href: it.href, ...common }, inner) : /* @__PURE__ */ React.createElement("button", { type: "button", ...common }, inner));
40
+ }))
41
+ ));
42
+ });
43
+ export {
44
+ BottomNav
45
+ };
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
  import * as React from "react";
3
+ import { createPortal } from "react-dom";
3
4
  import { useStrings, useLinkComponent } from "./locale.js";
4
5
  import { cx, useMaybeControlled, compare, useIsoLayoutEffect, useMergedRef } from "./internal.js";
5
6
  import { Icon } from "./Icon.js";
@@ -116,6 +117,29 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
116
117
  return px != null && boxWidth[0] < px;
117
118
  }
118
119
  const scrollRef = React.useRef(null);
120
+ const tipState = React.useState(null), tip = tipState[0], setTip = tipState[1];
121
+ function showFull(e) {
122
+ const el = e.target.closest ? e.target.closest(".aura-table__td, .aura-table__card-fields dd") : null;
123
+ if (!el || el.scrollWidth <= el.clientWidth + 1 || el.querySelector("button, input, .aura-pill"))
124
+ return setTip(null);
125
+ const r = el.getBoundingClientRect();
126
+ setTip({ text: (el.textContent || "").trim(), left: r.left, top: r.top });
127
+ }
128
+ function hideFull() {
129
+ setTip(null);
130
+ }
131
+ const tipEl = tip && typeof document !== "undefined" ? createPortal(
132
+ /* @__PURE__ */ React.createElement(
133
+ "div",
134
+ {
135
+ className: "aura-tooltip aura-tooltip--above",
136
+ "aria-hidden": "true",
137
+ style: { left: tip.left, top: tip.top - 6 }
138
+ },
139
+ tip.text
140
+ ),
141
+ document.body
142
+ ) : null;
119
143
  const rowH = React.useState(ROW_H_DEFAULT);
120
144
  const ROW_H = rowH[0];
121
145
  useIsoLayoutEffect(function() {
@@ -984,7 +1008,7 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
984
1008
  return /* @__PURE__ */ React.createElement("span", { key: c.key, className: "aura-table__card-actions" }, cellVal(c, r));
985
1009
  })),
986
1010
  rest.length ? /* @__PURE__ */ React.createElement("dl", { className: "aura-table__card-fields" }, rest.map(function(c) {
987
- return /* @__PURE__ */ React.createElement("div", { key: c.key }, /* @__PURE__ */ React.createElement("dt", null, c.label), /* @__PURE__ */ React.createElement("dd", { className: c.mono ? "aura-table__mono" : void 0 }, cellVal(c, r)));
1011
+ return /* @__PURE__ */ React.createElement("div", { key: c.key }, /* @__PURE__ */ React.createElement("dt", null, c.label), /* @__PURE__ */ React.createElement("dd", { className: cx(c.mono && "aura-table__mono", c.align === "end" && "is-end") }, cellVal(c, r)));
988
1012
  })) : null
989
1013
  );
990
1014
  }));
@@ -995,6 +1019,10 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
995
1019
  ref: wrapRefArg,
996
1020
  "data-density": props.density,
997
1021
  className: cx("aura-table aura-table--stacked", refreshing && "is-refreshing", props.className),
1022
+ onMouseOver: showFull,
1023
+ onMouseLeave: hideFull,
1024
+ onFocus: showFull,
1025
+ onBlur: hideFull,
998
1026
  role: "region",
999
1027
  "aria-label": props.label,
1000
1028
  "aria-busy": busy || void 0
@@ -1010,10 +1038,55 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
1010
1038
  }
1011
1039
  ), /* @__PURE__ */ React.createElement("span", null, nSel ? t.selectedCount(nSel) : t.selectAll)) : null,
1012
1040
  cardBody,
1013
- foot
1041
+ props.footer && rows.length && !loading ? /* @__PURE__ */ React.createElement("div", { className: "aura-table__card aura-table__card--total", role: "group", "aria-label": t.totals }, /* @__PURE__ */ React.createElement("dl", { className: "aura-table__card-fields" }, vis.filter(function(c) {
1042
+ return props.footer[c.key] != null;
1043
+ }).map(function(c) {
1044
+ return /* @__PURE__ */ React.createElement("div", { key: c.key }, /* @__PURE__ */ React.createElement("dt", null, c.label || t.totals), /* @__PURE__ */ React.createElement("dd", { className: cx(c.mono && "aura-table__mono", c.align === "end" && "is-end") }, props.footer[c.key]));
1045
+ }))) : null,
1046
+ foot,
1047
+ tipEl
1014
1048
  );
1015
1049
  }
1016
1050
  if (stacked) return renderStacked(wrapMerged);
1051
+ const totalRow = props.footer && rows.length && !loading ? /* @__PURE__ */ React.createElement(
1052
+ "div",
1053
+ {
1054
+ role: "row",
1055
+ "aria-rowindex": shownTotal + 2,
1056
+ "aria-label": t.totals,
1057
+ className: cx("aura-table__row aura-table__total", props.stickyFooter && "is-sticky"),
1058
+ style: rowStyle
1059
+ },
1060
+ /* @__PURE__ */ React.createElement("span", { className: "aura-table__gutter", "aria-hidden": true }),
1061
+ selectable ? /* @__PURE__ */ React.createElement("span", { className: cx("aura-table__sel", nPinned && "is-pinned"), "aria-hidden": true }) : null,
1062
+ vis.map(function(c, j) {
1063
+ const pin = isPinned(c);
1064
+ return /* @__PURE__ */ React.createElement(
1065
+ "span",
1066
+ {
1067
+ key: c.key,
1068
+ role: "gridcell",
1069
+ "aria-colindex": j + (selectable ? 2 : 1),
1070
+ className: cx(
1071
+ "aura-table__td",
1072
+ c.mono && "aura-table__mono",
1073
+ c.align === "end" && "is-end",
1074
+ pin && "is-pinned",
1075
+ pin && j === nPinned - 1 && "is-pin-edge"
1076
+ ),
1077
+ style: cellStyle(c, j)
1078
+ },
1079
+ props.footer[c.key]
1080
+ );
1081
+ }),
1082
+ /* @__PURE__ */ React.createElement(
1083
+ "span",
1084
+ {
1085
+ className: cx("aura-table__gutter aura-table__gutter--end", controls && "has-picker"),
1086
+ "aria-hidden": true
1087
+ }
1088
+ )
1089
+ ) : null;
1017
1090
  const scrollStyle = {
1018
1091
  scrollPaddingLeft: "calc(var(--aura-space-6)" + selW + " + " + acc + "px)",
1019
1092
  scrollPaddingTop: ROW_H + "px"
@@ -1035,11 +1108,15 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
1035
1108
  gridRef.current = el;
1036
1109
  },
1037
1110
  className: "aura-table__scroll",
1111
+ onMouseOver: showFull,
1112
+ onMouseLeave: hideFull,
1113
+ onFocus: showFull,
1114
+ onBlur: hideFull,
1038
1115
  style: scrollStyle,
1039
1116
  role: "grid",
1040
1117
  "aria-label": props.label,
1041
1118
  "aria-busy": busy || void 0,
1042
- "aria-rowcount": loading ? -1 : shownTotal + 1,
1119
+ "aria-rowcount": loading ? -1 : shownTotal + 1 + (totalRow ? 1 : 0),
1043
1120
  "aria-colcount": nCols,
1044
1121
  "aria-multiselectable": selectable || void 0,
1045
1122
  onKeyDown: onGridKey,
@@ -1053,7 +1130,8 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
1053
1130
  }
1054
1131
  },
1055
1132
  /* @__PURE__ */ React.createElement("div", { className: "aura-table__head", role: "row", "aria-rowindex": 1, style: rowStyle }, head),
1056
- body
1133
+ body,
1134
+ totalRow
1057
1135
  ),
1058
1136
  busy ? /* @__PURE__ */ React.createElement("span", { className: "aura-sr-only", role: "status" }, t.loadingRows) : null,
1059
1137
  controls ? /* @__PURE__ */ React.createElement("div", { className: "aura-table__picker" }, /* @__PURE__ */ React.createElement(
@@ -1076,7 +1154,8 @@ const DataTable = React.forwardRef(function DataTable2(props, ref) {
1076
1154
  label: menu.kind === "picker" ? t.columns : t.column(byKey[menu.key] && byKey[menu.key].label),
1077
1155
  items: menu.kind === "picker" ? pickerItems() : byKey[menu.key] ? columnMenuItems(byKey[menu.key]) : []
1078
1156
  }
1079
- ) : null
1157
+ ) : null,
1158
+ tipEl
1080
1159
  );
1081
1160
  if (!dual) return gridEl;
1082
1161
  return /* @__PURE__ */ React.createElement("div", { ref: wrapMerged, className: "aura-table-dual", "data-stack-below": props.stackBelow }, renderStacked(void 0), gridEl);
@@ -18,7 +18,8 @@ import {
18
18
  localeTag,
19
19
  parseDate,
20
20
  same,
21
- toISO
21
+ toISO,
22
+ todayIn
22
23
  } from "./dates.js";
23
24
  import { formatDate as formatDate2, parseDate as parseDate2 } from "./dates.js";
24
25
  function useFormatDate() {
@@ -40,9 +41,9 @@ function useFormatDate() {
40
41
  const Calendar = React.forwardRef(function Calendar2(props, ref) {
41
42
  const ctx = useAuraLocale(), locale = props.locale || ctx.locale || "en", calendar = props.calendar || ctx.calendar || defaultCalendar(locale), tag = localeTag(locale, calendar);
42
43
  const weekStart = props.weekStartsOn == null ? locale === "sv" ? 1 : 0 : props.weekStartsOn;
43
- let today = /* @__PURE__ */ new Date();
44
- today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
45
- const min = fromISO(props.min), max = fromISO(props.max);
44
+ const todayISO = props.today || todayIn(props.timeZone || ctx.timeZone);
45
+ const today = fromISO(todayISO);
46
+ const min = fromISO(props.min === "today" ? todayISO : props.min), max = fromISO(props.max === "today" ? todayISO : props.max);
46
47
  const start = fromISO(props.start), end = fromISO(props.end);
47
48
  const focusState = React.useState(fromISO(props.focus) || start || today);
48
49
  const focusDate = focusState[0], setFocus = focusState[1];
@@ -428,6 +429,8 @@ const DatePicker = React.forwardRef(function DatePicker2(props, ref) {
428
429
  weekStartsOn: props.weekStartsOn,
429
430
  min: props.min,
430
431
  max: props.max,
432
+ timeZone: props.timeZone,
433
+ today: props.today,
431
434
  isDateDisabled: props.isDateDisabled,
432
435
  start: st[0],
433
436
  focus: st[0],
@@ -544,6 +547,8 @@ const DateRangePicker = React.forwardRef(
544
547
  weekStartsOn: props.weekStartsOn,
545
548
  min: props.min,
546
549
  max: props.max,
550
+ timeZone: props.timeZone,
551
+ today: props.today,
547
552
  isDateDisabled: props.isDateDisabled,
548
553
  start: draft[0] || v.start,
549
554
  end: draft[0] ? null : v.end,
@@ -23,6 +23,7 @@ const DropdownMenu = React.forwardRef(function DropdownMenu2(props, ref) {
23
23
  anchor,
24
24
  label: props.label,
25
25
  items: props.items,
26
+ linkComponent: props.linkComponent,
26
27
  onClose: function(restore) {
27
28
  setAnchor(null);
28
29
  if (restore && typeof anchor.focus === "function") anchor.focus();
package/dist/esm/Menu.js CHANGED
@@ -3,12 +3,14 @@ import * as React from "react";
3
3
  import { createPortal } from "react-dom";
4
4
  import { cx, useIsoLayoutEffect, useMounted, useMergedRef } from "./internal.js";
5
5
  import { Icon } from "./Icon.js";
6
+ import { useLinkComponent } from "./locale.js";
6
7
  const Menu = React.forwardRef(function Menu2(props, ref) {
7
8
  const own = React.useRef(null), merged = useMergedRef(ref, own);
8
9
  const posState = React.useState(null);
9
10
  const pos = posState[0], setPos = posState[1];
10
11
  const items = props.items || [];
11
12
  const mounted = useMounted();
13
+ const Link = useLinkComponent(props.linkComponent);
12
14
  useIsoLayoutEffect(
13
15
  function() {
14
16
  const a = props.anchor, m = own.current;
@@ -69,6 +71,63 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
69
71
  }
70
72
  e.stopPropagation();
71
73
  }
74
+ function groupItems(list) {
75
+ const out = [];
76
+ list.forEach(function(it, i) {
77
+ const g = it.type === "radio" && it.group ? it.group : null;
78
+ const last = out[out.length - 1];
79
+ if (last && last.group === g && g !== null) last.items.push({ it, i });
80
+ else out.push({ group: g, items: [{ it, i }] });
81
+ });
82
+ return out;
83
+ }
84
+ function renderItem(it, i) {
85
+ if (it.separator) return /* @__PURE__ */ React.createElement("div", { key: "s" + i, role: "separator", className: "aura-menu__sep" });
86
+ const isRadio = it.type === "radio";
87
+ const isCheck = !isRadio && it.checked !== void 0;
88
+ const lead = isRadio ? /* @__PURE__ */ React.createElement("span", { className: cx("aura-menu__radio", it.checked && "is-on") }) : isCheck ? /* @__PURE__ */ React.createElement("span", { className: cx("aura-menu__check", it.checked && "is-on") }, it.checked ? /* @__PURE__ */ React.createElement(Icon, { name: "check", size: 12, strokeWidth: 3 }) : null) : it.icon ? /* @__PURE__ */ React.createElement(Icon, { name: it.icon }) : /* @__PURE__ */ React.createElement("span", { className: "aura-menu__blank" });
89
+ const body = [
90
+ /* @__PURE__ */ React.createElement(React.Fragment, { key: "l" }, lead),
91
+ /* @__PURE__ */ React.createElement("span", { key: "t", className: "aura-menu__label" }, it.label),
92
+ it.hint ? /* @__PURE__ */ React.createElement("span", { key: "h", className: "aura-menu__hint" }, it.hint) : null
93
+ ];
94
+ const cls = cx("aura-menu__item", it.tone === "danger" && "aura-menu__item--danger");
95
+ if (it.href && !it.disabled)
96
+ return /* @__PURE__ */ React.createElement(
97
+ Link,
98
+ {
99
+ key: i,
100
+ href: it.href,
101
+ target: it.target,
102
+ rel: it.target === "_blank" ? "noreferrer" : void 0,
103
+ tabIndex: -1,
104
+ role: "menuitem",
105
+ className: cls,
106
+ onClick: function() {
107
+ if (it.onSelect) it.onSelect();
108
+ props.onClose(false);
109
+ }
110
+ },
111
+ body
112
+ );
113
+ return /* @__PURE__ */ React.createElement(
114
+ "button",
115
+ {
116
+ key: i,
117
+ type: "button",
118
+ tabIndex: -1,
119
+ disabled: it.disabled,
120
+ role: isRadio ? "menuitemradio" : isCheck ? "menuitemcheckbox" : "menuitem",
121
+ "aria-checked": isRadio || isCheck ? !!it.checked : void 0,
122
+ className: cls,
123
+ onClick: function() {
124
+ if (it.onSelect) it.onSelect();
125
+ if (!it.keepOpen) props.onClose(true);
126
+ }
127
+ },
128
+ body
129
+ );
130
+ }
72
131
  const el = /* @__PURE__ */ React.createElement(
73
132
  "div",
74
133
  {
@@ -79,28 +138,11 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
79
138
  onKeyDown,
80
139
  style: { top: pos ? pos.top : -9999, left: pos ? pos.left : -9999 }
81
140
  },
82
- items.map(function(it, i) {
83
- if (it.separator) return /* @__PURE__ */ React.createElement("div", { key: "s" + i, role: "separator", className: "aura-menu__sep" });
84
- const isCheck = it.checked !== void 0;
85
- return /* @__PURE__ */ React.createElement(
86
- "button",
87
- {
88
- key: i,
89
- type: "button",
90
- tabIndex: -1,
91
- disabled: it.disabled,
92
- role: isCheck ? "menuitemcheckbox" : "menuitem",
93
- "aria-checked": isCheck ? !!it.checked : void 0,
94
- className: "aura-menu__item",
95
- onClick: function() {
96
- it.onSelect();
97
- if (!it.keepOpen) props.onClose(true);
98
- }
99
- },
100
- isCheck ? /* @__PURE__ */ React.createElement("span", { className: cx("aura-menu__check", it.checked && "is-on") }, it.checked ? /* @__PURE__ */ React.createElement(Icon, { name: "check", size: 12, strokeWidth: 3 }) : null) : it.icon ? /* @__PURE__ */ React.createElement(Icon, { name: it.icon }) : /* @__PURE__ */ React.createElement("span", { className: "aura-menu__blank" }),
101
- /* @__PURE__ */ React.createElement("span", { className: "aura-menu__label" }, it.label),
102
- it.hint ? /* @__PURE__ */ React.createElement("span", { className: "aura-menu__hint" }, it.hint) : null
103
- );
141
+ groupItems(items).map(function(block, bi) {
142
+ const rendered = block.items.map(function(x) {
143
+ return renderItem(x.it, x.i);
144
+ });
145
+ return block.group ? /* @__PURE__ */ React.createElement("div", { key: "g" + bi, role: "group", "aria-label": block.group, className: "aura-menu__group" }, rendered) : /* @__PURE__ */ React.createElement(React.Fragment, { key: "f" + bi }, rendered);
104
146
  })
105
147
  );
106
148
  return mounted ? createPortal(el, document.body) : null;
package/dist/esm/Tabs.js CHANGED
@@ -2,6 +2,7 @@
2
2
  import * as React from "react";
3
3
  import { Icon } from "./Icon.js";
4
4
  import { cx, uid, useMaybeControlled } from "./internal.js";
5
+ import { useLinkComponent } from "./locale.js";
5
6
  const Tabs = React.forwardRef(function Tabs2(props, ref) {
6
7
  const items = props.tabs || [], base = uid();
7
8
  const st = useMaybeControlled(
@@ -13,6 +14,40 @@ const Tabs = React.forwardRef(function Tabs2(props, ref) {
13
14
  const current = items.filter(function(t) {
14
15
  return t.id === st[0];
15
16
  })[0] || items[0];
17
+ const Link = useLinkComponent(props.linkComponent);
18
+ const asLinks = items.length > 0 && items.every(function(t) {
19
+ return !!t.href;
20
+ });
21
+ if (asLinks)
22
+ return /* @__PURE__ */ React.createElement(
23
+ "nav",
24
+ {
25
+ ref,
26
+ "aria-label": props.label,
27
+ className: cx("aura-tabs aura-tabs--links", props.className)
28
+ },
29
+ /* @__PURE__ */ React.createElement("div", { className: "aura-tabs__list" }, items.map(function(t) {
30
+ const on = current && t.id === current.id;
31
+ const inner = [
32
+ t.icon ? /* @__PURE__ */ React.createElement(Icon, { key: "i", name: t.icon }) : null,
33
+ t.label,
34
+ t.count != null ? /* @__PURE__ */ React.createElement("span", { key: "c", className: "aura-tab__count" }, t.count) : null
35
+ ];
36
+ return t.disabled ? /* @__PURE__ */ React.createElement("span", { key: t.id, className: "aura-tab is-disabled", "aria-disabled": true }, inner) : /* @__PURE__ */ React.createElement(
37
+ Link,
38
+ {
39
+ key: t.id,
40
+ href: t.href,
41
+ className: cx("aura-tab", on && "is-active"),
42
+ "aria-current": on ? "page" : void 0,
43
+ onClick: function() {
44
+ st[1](t.id);
45
+ }
46
+ },
47
+ inner
48
+ );
49
+ }))
50
+ );
16
51
  function go(i) {
17
52
  const enabled = items.filter(function(t2) {
18
53
  return !t2.disabled;
@@ -6,11 +6,19 @@ import { IconButton } from "./IconButton.js";
6
6
  import { cx, useMounted } from "./internal.js";
7
7
  import { useStrings } from "./locale.js";
8
8
  import { createPortal } from "react-dom";
9
+ const MAX_VISIBLE = 3;
9
10
  const toastState = {
10
11
  list: [],
12
+ queue: [],
11
13
  subs: [],
12
14
  n: 0
13
15
  };
16
+ function promote() {
17
+ while (toastState.list.length < MAX_VISIBLE && toastState.queue.length) {
18
+ toastState.list = toastState.list.concat([toastState.queue[0]]);
19
+ toastState.queue = toastState.queue.slice(1);
20
+ }
21
+ }
14
22
  function emitToasts() {
15
23
  toastState.subs.forEach(function(f) {
16
24
  f(toastState.list.slice());
@@ -18,18 +26,24 @@ function emitToasts() {
18
26
  }
19
27
  function show(opts) {
20
28
  const id = opts.id || "t" + ++toastState.n;
21
- const at = toastState.list.findIndex(function(t) {
29
+ const byId = function(t) {
22
30
  return t.id === id;
23
- });
31
+ };
32
+ const at = toastState.list.findIndex(byId), queued = toastState.queue.findIndex(byId);
33
+ const prev = at >= 0 ? toastState.list[at] : queued >= 0 ? toastState.queue[queued] : null;
24
34
  const entry = Object.assign({ tone: "info" }, opts, {
25
35
  id,
26
36
  loading: !!opts.loading,
27
- rev: at >= 0 ? toastState.list[at].rev + 1 : 0
37
+ rev: prev ? prev.rev + 1 : 0
28
38
  });
29
39
  if (at >= 0) {
30
40
  toastState.list = toastState.list.slice();
31
41
  toastState.list[at] = entry;
32
- } else toastState.list = toastState.list.concat([entry]).slice(-3);
42
+ } else if (queued >= 0) {
43
+ toastState.queue = toastState.queue.slice();
44
+ toastState.queue[queued] = entry;
45
+ } else if (toastState.list.length < MAX_VISIBLE) toastState.list = toastState.list.concat([entry]);
46
+ else toastState.queue = toastState.queue.concat([entry]);
33
47
  emitToasts();
34
48
  return id;
35
49
  }
@@ -51,9 +65,12 @@ toast.loading = function(title, opts) {
51
65
  );
52
66
  };
53
67
  toast.dismiss = function(id) {
54
- toastState.list = toastState.list.filter(function(t) {
68
+ const keep = function(t) {
55
69
  return t.id !== id;
56
- });
70
+ };
71
+ toastState.list = toastState.list.filter(keep);
72
+ toastState.queue = toastState.queue.filter(keep);
73
+ promote();
57
74
  emitToasts();
58
75
  };
59
76
  function ToastItem(props) {
package/dist/esm/dates.js CHANGED
@@ -141,6 +141,16 @@ function parseDate(text) {
141
141
  const dt = new Date(y, mo - 1, d);
142
142
  return dt.getMonth() === mo - 1 && dt.getDate() === d ? toISO(dt) : null;
143
143
  }
144
+ function todayIn(timeZone) {
145
+ const now = /* @__PURE__ */ new Date();
146
+ if (!timeZone) return toISO(now);
147
+ return new Intl.DateTimeFormat("en-CA", {
148
+ timeZone,
149
+ year: "numeric",
150
+ month: "2-digit",
151
+ day: "2-digit"
152
+ }).format(now);
153
+ }
144
154
  export {
145
155
  DATE_TEXT,
146
156
  ERA,
@@ -160,5 +170,6 @@ export {
160
170
  pad,
161
171
  parseDate,
162
172
  same,
163
- toISO
173
+ toISO,
174
+ todayIn
164
175
  };
package/dist/esm/index.js CHANGED
@@ -14,6 +14,7 @@ import { RadioGroup } from "./RadioGroup.js";
14
14
  import { Switch } from "./Switch.js";
15
15
  import { Combobox, defaultFilter } from "./Combobox.js";
16
16
  import { DatePicker, DateRangePicker, Calendar, formatDate, parseDate, useFormatDate } from "./DatePicker.js";
17
+ import { todayIn } from "./dates.js";
17
18
  import { Alert } from "./Alert.js";
18
19
  import { Toaster, toast } from "./Toaster.js";
19
20
  import { PasswordField } from "./PasswordField.js";
@@ -32,6 +33,8 @@ import { Stack } from "./Stack.js";
32
33
  import { Grid } from "./Grid.js";
33
34
  import { Container } from "./Container.js";
34
35
  import { AppShell } from "./AppShell.js";
36
+ import { ActionBar } from "./ActionBar.js";
37
+ import { BottomNav } from "./BottomNav.js";
35
38
  import { useBreakpoint, useResponsive, breakpoints } from "./responsive.js";
36
39
  import { Surface } from "./Surface.js";
37
40
  import { AuraProvider, useAuraLocale, useDensity, STRINGS } from "./locale.js";
@@ -54,11 +57,13 @@ import { Stepper } from "./Stepper.js";
54
57
  import { SegmentedControl } from "./SegmentedControl.js";
55
58
  export {
56
59
  Accordion,
60
+ ActionBar,
57
61
  Alert,
58
62
  AppShell,
59
63
  AuraProvider,
60
64
  Avatar,
61
65
  Badge,
66
+ BottomNav,
62
67
  Breadcrumb,
63
68
  Button,
64
69
  Calendar,
@@ -123,6 +128,7 @@ export {
123
128
  parseTime,
124
129
  statusTone,
125
130
  toast,
131
+ todayIn,
126
132
  useAuraLocale,
127
133
  useBreakpoint,
128
134
  useColorScheme,
@@ -5,6 +5,7 @@ const LocaleContext = React.createContext(null);
5
5
  function AuraProvider(props) {
6
6
  const outer = React.useContext(LocaleContext);
7
7
  const density = props.density || outer && outer.density || null;
8
+ const timeZone = props.timeZone || outer && outer.timeZone || null;
8
9
  const value = React.useMemo(
9
10
  function() {
10
11
  const base = props.locale && STRINGS[props.locale] || STRINGS.en;
@@ -13,10 +14,11 @@ function AuraProvider(props) {
13
14
  calendar: props.calendar || null,
14
15
  strings: props.strings ? Object.assign({}, base, props.strings) : base,
15
16
  linkComponent: props.linkComponent || null,
16
- density
17
+ density,
18
+ timeZone
17
19
  };
18
20
  },
19
- [props.locale, props.calendar, props.strings, props.linkComponent, density]
21
+ [props.locale, props.calendar, props.strings, props.linkComponent, density, timeZone]
20
22
  );
21
23
  return /* @__PURE__ */ React.createElement(LocaleContext.Provider, { value }, props.density ? /* @__PURE__ */ React.createElement("div", { className: "aura-density", "data-density": props.density }, props.children) : props.children);
22
24
  }
@@ -76,6 +76,7 @@ const STRINGS = {
76
76
  },
77
77
  prevPage: "Previous page",
78
78
  nextPage: "Next page",
79
+ totals: "Totals",
79
80
  rowCount: function(c) {
80
81
  return n(c) + " rows";
81
82
  },
@@ -189,6 +190,7 @@ const STRINGS = {
189
190
  },
190
191
  prevPage: "\u0E2B\u0E19\u0E49\u0E32\u0E01\u0E48\u0E2D\u0E19\u0E2B\u0E19\u0E49\u0E32",
191
192
  nextPage: "\u0E2B\u0E19\u0E49\u0E32\u0E16\u0E31\u0E14\u0E44\u0E1B",
193
+ totals: "\u0E23\u0E27\u0E21",
192
194
  rowCount: function(c) {
193
195
  return n(c) + " \u0E41\u0E16\u0E27";
194
196
  },
@@ -302,6 +304,7 @@ const STRINGS = {
302
304
  },
303
305
  prevPage: "F\xF6reg\xE5ende sida",
304
306
  nextPage: "N\xE4sta sida",
307
+ totals: "Summa",
305
308
  rowCount: function(c) {
306
309
  return nsv(c) + " rader";
307
310
  },