@jirawatpyk/aura-react 5.12.0 → 5.14.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/README.md +28 -0
- package/dist/aura.bundle.js +255 -115
- package/dist/cjs/index.cjs +255 -115
- package/dist/esm/AppShell.js +69 -24
- package/dist/esm/Avatar.js +4 -32
- package/dist/esm/Button.js +4 -2
- package/dist/esm/DataTable.js +82 -22
- package/dist/esm/Stat.js +2 -30
- package/dist/esm/Table.js +14 -6
- package/dist/esm/Tabs.js +1 -1
- package/dist/esm/display.js +95 -3
- package/dist/index.d.cts +36 -3
- package/dist/index.d.ts +36 -3
- package/dist/server/index.cjs +98 -2
- package/dist/server/index.d.cts +52 -2
- package/dist/server/index.d.ts +52 -2
- package/dist/server/index.js +98 -2
- package/dist/styles.css +64 -5
- package/dist/styles.layer.css +64 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -186,6 +186,34 @@ DataTable with sort and page in the URL (4.17): `onStateChange={({ sort, page })
|
|
|
186
186
|
- **Time zone**: `timeZone` on AuraProvider, DatePicker, DateRangePicker and Calendar decides "today" (the marker, `min`/`max="today"`, the first month shown); or pass `today` as an ISO date. `todayIn('Asia/Bangkok')` is exported from the root and `/server`.
|
|
187
187
|
- **Toasts** queue past three instead of dropping: six in a row all show, in order, three at a time.
|
|
188
188
|
|
|
189
|
+
## 5.14 — Chamber-OS addenda 15–16, the small items
|
|
190
|
+
|
|
191
|
+
- **EmptyState `headingLevel={false}`** (item 86): the title is a `<p>`, so an empty state inside a card or list adds nothing to the page's heading outline. EmptyState has no live-region role unless you pass `role`.
|
|
192
|
+
- **Stat from `/server`, with `headingLevel`** (item 88): `import { Stat } from '@jirawatpyk/aura-react/server'` renders the same HTML as the root Stat (no `onClick` there; `href` renders `linkComponent`, else `<a>`), `loading` included. `headingLevel={2}` makes the label a heading — on a link tile too; with `onClick` it stays a span (a heading can't sit in a button) and a dev notice says so.
|
|
193
|
+
- **Drawer body scroll padding** (item 91): a field scrolled into view in a Drawer (focus, a phone's keyboard) keeps 16px clear of the head and the foot, so its focus ring is never cut (WCAG 2.4.11).
|
|
194
|
+
- **AppShell `contentPadding={false}`** (item 97): `<main>` has no padding, for pages whose containers own the padding and column.
|
|
195
|
+
- **Button keeps a passed `aria-disabled`** (item 102): `<Button aria-disabled>` stays focusable and in the Tab order, is announced as unavailable, looks unavailable (disabled opacity, not-allowed cursor) and ignores clicks and Enter — a gated confirm. Hovering it changes nothing. `loading` still sets it. In tests, click such a button with `{ force: true }`. This is for buttons: a Button with `href` takes `disabled` (it drops the link and sets `aria-disabled` itself), and IconButton is unchanged.
|
|
196
|
+
- **Avatar from `/server`** (item 103): initials and colour, same HTML as the root Avatar. Falling back to initials when an image fails needs the client.
|
|
197
|
+
- **`--aura-shell-bar-height`** (item 104): the top bar's height on `.aura-shell`, for sticky offsets under it — `top: var(--aura-shell-bar-height)`. AppShell measures the bar, so a header that wraps to two lines on a phone gives its real height; the stylesheet's 56px covers the server's HTML until then. It is set inline on the shell, so read it rather than override it. It is 0 when there is no bar (no `header`, no `nav`), and from 1024px when the bar only held the menu button. The bar is now `box-sizing: border-box`, so it is 56px everywhere (it was 57px where no border-box reset applied).
|
|
198
|
+
- **`--aura-fg-warning`** (item 106): warning text on the page — amber-800 in light (7.1:1 on surface, 6.8:1 on canvas), amber-300 in dark (12.3:1, 13.9:1), checked in CI. `--aura-status-*-fg` are only for text on their pill's own fill; the warning one is near-black in dark mode.
|
|
199
|
+
- **DataTable cards start-align every field** (item 108): a column with `align: 'end'` is right-aligned in the grid and starts under its label in the stacked cards, with tabular figures in both. A visible change to cards with amount columns.
|
|
200
|
+
- **Tabs `current="location"`** (item 107): link tabs to sections of the same page mark the current one `aria-current="location"` (default `page`).
|
|
201
|
+
|
|
202
|
+
## 5.13 — Chamber-OS addendum 13 (board parity)
|
|
203
|
+
|
|
204
|
+
- **DataTable card options** (item 80): per column, `card: 'hide'` leaves it out of the stacked card (the grid keeps it), `card: 'title' | 'pill' | 'field'` places it (a declared title or pill replaces the automatic one; the automatic title is the first column without a `card` — normally the first column — skipping `actions` columns), and `cardOrder` orders the fields (lowest first; others sort by column index) without touching the grid's order. `hideSelectionInCards` drops the row boxes and the select-all line from the cards only; the selection is kept, and Space doesn't change it while cards show. Screen readers and arrow keys follow the grid's order and skip what the card leaves out (the tab stop too); each remaining field keeps its label; loading skeletons leave out the same columns. With `getRowHref`, the link is the first column's text, so hiding that column in cards leaves the card clickable but without a link to Tab to. All in CSS, so the server HTML is already right.
|
|
205
|
+
```tsx
|
|
206
|
+
<DataTable stackBelow={640} hideSelectionInCards columns={[{ key: 'company', label: 'COMPANY' }, { key: 'flag', label: 'COUNTRY', card: 'hide' }, { key: 'id', label: 'MEMBER NO.', cardOrder: 1 }, …]} />
|
|
207
|
+
```
|
|
208
|
+
- **Table `align="middle"` and `bordered={false}`** (item 81): `middle` centres body and footer cells on their row (default `top`); `bordered={false}` drops the frame and the outer cells' side padding, so a table inside a Card lines up with its heading. Stacked rows keep their layout. `Table`'s type no longer accepts the obsolete HTML `align` attribute (`left | center | right`).
|
|
209
|
+
- **EmptyState `tone="danger"`** (item 82): the danger tint, a danger-coloured icon and, with `bordered`, a solid danger frame — for "couldn't load". It stays quiet (no role); pass `role="alert"` to interrupt. EmptyState now passes `id`, `data-*`, `aria-*`, `role` and `style` to its root.
|
|
210
|
+
- **FilterBar search filling the row** (item 83): that is 5.12's `searchGrow`; nothing new was needed.
|
|
211
|
+
- **Td `card="title" | "action"`** (item 84; also on a row header, `Th scope="row"`): in a stacked Table row the title takes the first line without a label, the action sits at the end of that line at its natural size, and the other cells fall two to a line below. A long title wraps before the action. The desktop table is unchanged.
|
|
212
|
+
```tsx
|
|
213
|
+
<Tr><Td card="title">{company} <span className="aura-table__mono">{no}</span></Td><Td>{type}</Td><Td>{date}</Td>
|
|
214
|
+
<Td card="action"><Button size="sm" variant="secondary">Review</Button></Td></Tr>
|
|
215
|
+
```
|
|
216
|
+
|
|
189
217
|
## 5.12 — Chamber-OS addendum 12 (compact filters)
|
|
190
218
|
|
|
191
219
|
- **FilterSelect** (item 79): a filter for `FilterBar` drawn as one small button — "Status All ▾" — as wide as its words, so several filters and a toggle `Tag` share a row, three and a Tag even at 375px. It is Select underneath: it opens the same AURA list (on phones too, as Select does since 5.3), with the same keys (arrows, typing, Enter, Escape), `name` in a form and a real `<select>` before hydration (with JavaScript off a choice still posts with the form, but the face keeps the server's value). `onChange` gets the value, so with react-hook-form use a `Controller` (`render={({ field }) => <FilterSelect label="Plan" {...field} options={plans} />}`), not `register`. `label` is the filter's name and its accessible name; screen readers hear the chosen option as the value. The first option is the "all" choice: `allLabel` is the shorter word its face shows ("All" for "All statuses"). A long value ("Diamond Partnership") shows in full and the button moves to the next row instead of cutting it. Right to left, the list opens from the face's right edge.
|
package/dist/aura.bundle.js
CHANGED
|
@@ -674,12 +674,31 @@ window.Aura = (() => {
|
|
|
674
674
|
);
|
|
675
675
|
}
|
|
676
676
|
function emptyStateElement(props, ref) {
|
|
677
|
-
const HT = "h" + (props.headingLevel || 3);
|
|
677
|
+
const HT = props.headingLevel === false ? "p" : "h" + (props.headingLevel || 3);
|
|
678
|
+
const rest = omit(props, [
|
|
679
|
+
"title",
|
|
680
|
+
"description",
|
|
681
|
+
"icon",
|
|
682
|
+
"action",
|
|
683
|
+
"size",
|
|
684
|
+
"bordered",
|
|
685
|
+
"headingLevel",
|
|
686
|
+
"tone",
|
|
687
|
+
"className",
|
|
688
|
+
"children"
|
|
689
|
+
]);
|
|
678
690
|
return /* @__PURE__ */ React4.createElement(
|
|
679
691
|
"div",
|
|
680
692
|
{
|
|
693
|
+
...rest,
|
|
681
694
|
ref,
|
|
682
|
-
className: cx(
|
|
695
|
+
className: cx(
|
|
696
|
+
"aura-empty",
|
|
697
|
+
props.size === "sm" && "is-sm",
|
|
698
|
+
props.bordered && "is-bordered",
|
|
699
|
+
props.tone === "danger" && "is-danger",
|
|
700
|
+
props.className
|
|
701
|
+
)
|
|
683
702
|
},
|
|
684
703
|
/* @__PURE__ */ React4.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React4.createElement(Icon, { name: props.icon || /* @__PURE__ */ React4.createElement(IconInbox, null), size: props.size === "sm" ? "md" : "lg" })),
|
|
685
704
|
/* @__PURE__ */ React4.createElement(HT, { className: "aura-empty__title" }, props.title),
|
|
@@ -687,6 +706,66 @@ window.Aura = (() => {
|
|
|
687
706
|
props.action ? /* @__PURE__ */ React4.createElement("div", { className: "aura-empty__action" }, props.action) : null
|
|
688
707
|
);
|
|
689
708
|
}
|
|
709
|
+
function statElement(props, ref, Link) {
|
|
710
|
+
const ch = props.change;
|
|
711
|
+
const dir = ch && (ch.direction || "flat");
|
|
712
|
+
const tone2 = ch && (ch.tone || (dir === "up" ? "positive" : dir === "down" ? "negative" : "neutral"));
|
|
713
|
+
const v = props.value;
|
|
714
|
+
const numeric = typeof v === "number" || typeof v === "string" && /\d/.test(v) && /^[\s\d.,:+\-\u2212%()\u0E3F$\u20AC\u00A3\u00A5kKmMbB]+$/.test(v.replace(/\b[A-Z]{3}\b/g, ""));
|
|
715
|
+
const Tag3 = props.href ? Link : props.onClick ? "button" : "div";
|
|
716
|
+
const interactive = !!(props.href || props.onClick);
|
|
717
|
+
if (props.headingLevel && Tag3 === "button")
|
|
718
|
+
devWarnOnce(
|
|
719
|
+
"stat-heading-button",
|
|
720
|
+
"Stat `headingLevel` is ignored with `onClick`: a heading can\u2019t sit in a button. Use `href`, or put the heading outside."
|
|
721
|
+
);
|
|
722
|
+
const LabelTag = props.headingLevel && Tag3 !== "button" ? "h" + props.headingLevel : "span";
|
|
723
|
+
const HeadTag = LabelTag === "span" ? "span" : "div";
|
|
724
|
+
return /* @__PURE__ */ React4.createElement(
|
|
725
|
+
Tag3,
|
|
726
|
+
{
|
|
727
|
+
ref,
|
|
728
|
+
className: cx("aura-stat", interactive && "is-interactive", props.loading && "is-loading", props.className),
|
|
729
|
+
href: props.href,
|
|
730
|
+
onClick: props.onClick,
|
|
731
|
+
type: Tag3 === "button" ? "button" : void 0,
|
|
732
|
+
"aria-busy": props.loading || void 0
|
|
733
|
+
},
|
|
734
|
+
/* @__PURE__ */ React4.createElement(HeadTag, { className: "aura-stat__head" }, /* @__PURE__ */ React4.createElement(LabelTag, { className: "aura-stat__label" }, props.label), props.icon ? /* @__PURE__ */ React4.createElement("span", { className: "aura-stat__icon" }, /* @__PURE__ */ React4.createElement(Icon, { name: props.icon })) : null),
|
|
735
|
+
props.loading ? /* @__PURE__ */ React4.createElement("span", { className: "aura-stat__value" }, /* @__PURE__ */ React4.createElement("span", { className: "aura-skel aura-stat__skel" })) : /* @__PURE__ */ React4.createElement("span", { className: cx("aura-stat__value", numeric && "is-numeric") }, props.value, props.unit ? /* @__PURE__ */ React4.createElement("span", { className: "aura-stat__unit" }, props.unit) : null),
|
|
736
|
+
ch && !props.loading || props.caption ? /* @__PURE__ */ React4.createElement("span", { className: "aura-stat__foot" }, ch && !props.loading ? /* @__PURE__ */ React4.createElement("span", { className: cx("aura-stat__change", "is-" + tone2) }, /* @__PURE__ */ React4.createElement(
|
|
737
|
+
Icon,
|
|
738
|
+
{
|
|
739
|
+
name: dir === "up" ? /* @__PURE__ */ React4.createElement(IconTrendingUp, null) : dir === "down" ? /* @__PURE__ */ React4.createElement(IconTrendingDown, null) : /* @__PURE__ */ React4.createElement(IconMinus, null),
|
|
740
|
+
size: 14
|
|
741
|
+
}
|
|
742
|
+
), /* @__PURE__ */ React4.createElement("span", null, ch.value)) : null, ch && ch.label && !props.loading ? /* @__PURE__ */ React4.createElement("span", { className: "aura-stat__caption" }, ch.label) : null, props.caption ? /* @__PURE__ */ React4.createElement("span", { className: "aura-stat__caption" }, props.caption) : null) : null
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
var AVATAR_TONES = ["progress", "ready", "neutral", "warning"];
|
|
746
|
+
function initials(name) {
|
|
747
|
+
const parts = String(name || "?").trim().split(/\s+/);
|
|
748
|
+
return ((parts[0] || "?")[0] + (parts.length > 1 ? parts[parts.length - 1][0] : parts[0][1] || "")).toUpperCase();
|
|
749
|
+
}
|
|
750
|
+
function avatarElement(props, ref, broken, onError) {
|
|
751
|
+
const size = props.size || "md";
|
|
752
|
+
let hash = 0;
|
|
753
|
+
String(props.name || "").split("").forEach(function(ch) {
|
|
754
|
+
hash = hash * 31 + ch.charCodeAt(0) >>> 0;
|
|
755
|
+
});
|
|
756
|
+
const tone2 = AVATAR_TONES[hash % AVATAR_TONES.length];
|
|
757
|
+
return /* @__PURE__ */ React4.createElement(
|
|
758
|
+
"span",
|
|
759
|
+
{
|
|
760
|
+
ref,
|
|
761
|
+
className: cx("aura-avatar", "aura-avatar--" + size, "aura-avatar--" + tone2, props.className),
|
|
762
|
+
role: "img",
|
|
763
|
+
"aria-label": props.name + (props.status ? ", " + props.status : "")
|
|
764
|
+
},
|
|
765
|
+
props.src && broken !== props.src ? /* @__PURE__ */ React4.createElement("img", { key: props.src, src: props.src, alt: "", onError }) : /* @__PURE__ */ React4.createElement("span", { "aria-hidden": true }, initials(props.name)),
|
|
766
|
+
props.status === "online" ? /* @__PURE__ */ React4.createElement("span", { className: "aura-avatar__status", "aria-hidden": true }) : null
|
|
767
|
+
);
|
|
768
|
+
}
|
|
690
769
|
function buttonClass(opts = {}) {
|
|
691
770
|
return cx(
|
|
692
771
|
"aura-btn",
|
|
@@ -1175,6 +1254,8 @@ window.Aura = (() => {
|
|
|
1175
1254
|
const props = all;
|
|
1176
1255
|
const variant = props.variant || "primary";
|
|
1177
1256
|
const loading = !!props.loading;
|
|
1257
|
+
const ad = props["aria-disabled"];
|
|
1258
|
+
const blocked = loading || ad === true || ad === "true";
|
|
1178
1259
|
const rest = omit(props, [
|
|
1179
1260
|
"variant",
|
|
1180
1261
|
"className",
|
|
@@ -1201,8 +1282,8 @@ window.Aura = (() => {
|
|
|
1201
1282
|
className: props.className
|
|
1202
1283
|
}),
|
|
1203
1284
|
"aria-busy": loading || void 0,
|
|
1204
|
-
"aria-disabled":
|
|
1205
|
-
onClick:
|
|
1285
|
+
"aria-disabled": blocked || void 0,
|
|
1286
|
+
onClick: blocked ? function(e) {
|
|
1206
1287
|
e.preventDefault();
|
|
1207
1288
|
} : props.onClick
|
|
1208
1289
|
},
|
|
@@ -4811,6 +4892,7 @@ window.Aura = (() => {
|
|
|
4811
4892
|
[measure, levelShape]
|
|
4812
4893
|
);
|
|
4813
4894
|
const stacked = !!props.stackBelow && boxWidth[0] != null && below(boxWidth[0], props.stackBelow);
|
|
4895
|
+
const noCardSel = !!props.hideSelectionInCards && selectable;
|
|
4814
4896
|
useIsoLayoutEffect(
|
|
4815
4897
|
function() {
|
|
4816
4898
|
if (measure && wrapRef.current) boxWidth[1](wrapRef.current.getBoundingClientRect().width);
|
|
@@ -4911,9 +4993,38 @@ window.Aura = (() => {
|
|
|
4911
4993
|
const pillKey = (vis.filter(function(c, i) {
|
|
4912
4994
|
return i > 0 && c.pill;
|
|
4913
4995
|
})[0] || { key: "" }).key;
|
|
4914
|
-
|
|
4915
|
-
return
|
|
4996
|
+
const ownTitle = vis.some(function(c) {
|
|
4997
|
+
return c.card === "title";
|
|
4998
|
+
}), ownPill = vis.some(function(c) {
|
|
4999
|
+
return c.card === "pill";
|
|
5000
|
+
});
|
|
5001
|
+
let autoTitle = -1;
|
|
5002
|
+
if (!ownTitle) {
|
|
5003
|
+
for (let i = 0; i < vis.length; i++)
|
|
5004
|
+
if (!vis[i].card && (i === 0 || !vis[i].actions)) {
|
|
5005
|
+
autoTitle = i;
|
|
5006
|
+
break;
|
|
5007
|
+
}
|
|
4916
5008
|
}
|
|
5009
|
+
function cardPart(c, i) {
|
|
5010
|
+
if (c.card) return c.card;
|
|
5011
|
+
if (i === autoTitle) return "title";
|
|
5012
|
+
if (c.key === pillKey && !ownPill) return "pill";
|
|
5013
|
+
return c.actions ? "actions" : "field";
|
|
5014
|
+
}
|
|
5015
|
+
const cardRank = {};
|
|
5016
|
+
if (vis.some(function(c) {
|
|
5017
|
+
return c.cardOrder != null;
|
|
5018
|
+
}))
|
|
5019
|
+
vis.map(function(c, i) {
|
|
5020
|
+
return { c, i, o: c.cardOrder != null ? c.cardOrder : i };
|
|
5021
|
+
}).filter(function(x) {
|
|
5022
|
+
return cardPart(x.c, x.i) === "field";
|
|
5023
|
+
}).sort(function(a, b) {
|
|
5024
|
+
return a.o - b.o || a.i - b.i;
|
|
5025
|
+
}).forEach(function(x, n3) {
|
|
5026
|
+
cardRank[x.c.key] = n3;
|
|
5027
|
+
});
|
|
4917
5028
|
function cardAttrs(c, i) {
|
|
4918
5029
|
const part = cardPart(c, i), lv = hideLevel(c);
|
|
4919
5030
|
return {
|
|
@@ -4955,6 +5066,7 @@ window.Aura = (() => {
|
|
|
4955
5066
|
s["--aura-cell-w"] = w + "px";
|
|
4956
5067
|
}
|
|
4957
5068
|
if (isPinned(c)) s["--aura-cell-left"] = "calc(var(--aura-space-6)" + selW + " + " + pinOffsets[c.key] + ")";
|
|
5069
|
+
if (cardRank[c.key] != null) s["--aura-card-order"] = String(5 + cardRank[c.key]);
|
|
4958
5070
|
return s;
|
|
4959
5071
|
}
|
|
4960
5072
|
const sortCol = sort && sort.key ? byKey[sort.key] : void 0;
|
|
@@ -5095,9 +5207,37 @@ window.Aura = (() => {
|
|
|
5095
5207
|
function colAt(ci) {
|
|
5096
5208
|
return selectable ? ci === 0 ? null : vis[ci - 1] : vis[ci];
|
|
5097
5209
|
}
|
|
5210
|
+
const cardHidden = [];
|
|
5211
|
+
for (let ci = 0; ci < nCols; ci++) {
|
|
5212
|
+
const col = colAt(ci);
|
|
5213
|
+
cardHidden.push(stacked && (col ? cardPart(col, vis.indexOf(col)) === "hide" : noCardSel));
|
|
5214
|
+
}
|
|
5215
|
+
function nearestShown(c, dir, ok) {
|
|
5216
|
+
if (ok(c)) return c;
|
|
5217
|
+
for (let d = 1; d < nCols; d++) {
|
|
5218
|
+
const a = c + d * dir, b = c - d * dir;
|
|
5219
|
+
if (a >= 0 && a < nCols && ok(a)) return a;
|
|
5220
|
+
if (b >= 0 && b < nCols && ok(b)) return b;
|
|
5221
|
+
}
|
|
5222
|
+
return c;
|
|
5223
|
+
}
|
|
5224
|
+
const acShown = nearestShown(ac, 1, function(cc) {
|
|
5225
|
+
return !cardHidden[cc];
|
|
5226
|
+
});
|
|
5227
|
+
const lastFocus = React31.useRef(null);
|
|
5228
|
+
React31.useEffect(
|
|
5229
|
+
function() {
|
|
5230
|
+
const was = lastFocus.current, g = gridRef.current;
|
|
5231
|
+
if (!stacked || !was || !g || !g.contains(was) || was.getClientRects().length > 0) return;
|
|
5232
|
+
if (document.activeElement && document.activeElement !== document.body && document.activeElement !== was) return;
|
|
5233
|
+
const el = g.querySelector('[data-rc="' + Math.max(1, ar) + ":" + acShown + '"]');
|
|
5234
|
+
if (el && el.getClientRects().length > 0) el.focus();
|
|
5235
|
+
},
|
|
5236
|
+
[stacked]
|
|
5237
|
+
);
|
|
5098
5238
|
function tabFor(r, c) {
|
|
5099
5239
|
if (!activeRendered) return r === 0 && c === ac ? 0 : -1;
|
|
5100
|
-
return r === ar && c ===
|
|
5240
|
+
return r === ar && c === acShown ? 0 : -1;
|
|
5101
5241
|
}
|
|
5102
5242
|
React31.useEffect(function() {
|
|
5103
5243
|
const p = pending.current;
|
|
@@ -5121,26 +5261,17 @@ window.Aura = (() => {
|
|
|
5121
5261
|
el.focus();
|
|
5122
5262
|
}
|
|
5123
5263
|
});
|
|
5124
|
-
function focusCell(r, c) {
|
|
5264
|
+
function focusCell(r, c, dir) {
|
|
5125
5265
|
r = Math.max(0, Math.min(r, lastR));
|
|
5126
5266
|
c = Math.max(0, Math.min(c, nCols - 1));
|
|
5127
|
-
if (stacked && r === 0 && nRows > 0 && !(selectable && c === 0)) r = 1;
|
|
5128
|
-
if (gridRef.current && r === T && hasTotal) {
|
|
5267
|
+
if (stacked && r === 0 && nRows > 0 && (!(selectable && c === 0) || noCardSel)) r = 1;
|
|
5268
|
+
if (gridRef.current && (r === T && hasTotal || stacked)) {
|
|
5129
5269
|
const shown2 = function(cc) {
|
|
5270
|
+
if (cardHidden[cc]) return false;
|
|
5130
5271
|
const e = gridRef.current.querySelector('[data-rc="' + r + ":" + cc + '"]');
|
|
5131
5272
|
return !!e && e.getClientRects().length > 0;
|
|
5132
5273
|
};
|
|
5133
|
-
|
|
5134
|
-
for (let d = 1; d < nCols; d++) {
|
|
5135
|
-
if (c + d < nCols && shown2(c + d)) {
|
|
5136
|
-
c = c + d;
|
|
5137
|
-
break;
|
|
5138
|
-
}
|
|
5139
|
-
if (c - d >= 0 && shown2(c - d)) {
|
|
5140
|
-
c = c - d;
|
|
5141
|
-
break;
|
|
5142
|
-
}
|
|
5143
|
-
}
|
|
5274
|
+
c = nearestShown(c, dir || 1, shown2);
|
|
5144
5275
|
}
|
|
5145
5276
|
activeState[1]({ r, c });
|
|
5146
5277
|
pending.current = { r, c };
|
|
@@ -5400,7 +5531,7 @@ window.Aura = (() => {
|
|
|
5400
5531
|
} else if (r === 0 && col && (e.altKey && k === "ArrowDown" || k === "ContextMenu" || e.shiftKey && k === "F10") && controls)
|
|
5401
5532
|
openMenu("col", col.key, target, { r: 0, c });
|
|
5402
5533
|
else if (k === "ArrowRight") focusCell(r, c + 1);
|
|
5403
|
-
else if (k === "ArrowLeft") focusCell(r, c - 1);
|
|
5534
|
+
else if (k === "ArrowLeft") focusCell(r, c - 1, -1);
|
|
5404
5535
|
else if (k === "ArrowDown") {
|
|
5405
5536
|
if (r < lastR) focusCell(r + 1, c);
|
|
5406
5537
|
else if (pageSize && page < pageCount && goPage(page + 1, { r: 1, c })) activeState[1]({ r: 1, c });
|
|
@@ -5408,7 +5539,7 @@ window.Aura = (() => {
|
|
|
5408
5539
|
if (r > 1 || r === 1 && !(pageSize && page > 1)) focusCell(r - 1, c);
|
|
5409
5540
|
else if (r === 1 && goPage(page - 1, { r: pageSize, c })) activeState[1]({ r: pageSize, c });
|
|
5410
5541
|
} else if (k === "Home") focusCell(e.ctrlKey ? 1 : r, 0);
|
|
5411
|
-
else if (k === "End") focusCell(e.ctrlKey ? lastR : r, nCols - 1);
|
|
5542
|
+
else if (k === "End") focusCell(e.ctrlKey ? lastR : r, nCols - 1, -1);
|
|
5412
5543
|
else if (k === "PageDown") {
|
|
5413
5544
|
if (pageSize) {
|
|
5414
5545
|
if (goPage(page + 1, { r: 1, c })) activeState[1]({ r: 1, c });
|
|
@@ -5428,7 +5559,7 @@ window.Aura = (() => {
|
|
|
5428
5559
|
if (pageKeys.length) toggleAll();
|
|
5429
5560
|
} else if (r === 0 && col && col.sortable && canSortAny) sortBy(col.key);
|
|
5430
5561
|
else if (r > 0 && k === " " && selectable) {
|
|
5431
|
-
if (canSelect(row)) toggle(row[rowKey], !selSet[row[rowKey]]);
|
|
5562
|
+
if (canSelect(row) && !(stacked && noCardSel)) toggle(row[rowKey], !selSet[row[rowKey]]);
|
|
5432
5563
|
} else if (r > 0 && k === "Enter" && rowHref && !target.querySelector("button, a[href]:not(.aura-table__row-link), input, select, textarea"))
|
|
5433
5564
|
followRow(target.closest('[role="row"]'), e);
|
|
5434
5565
|
else if (r > 0 && k === "Enter" && target.querySelector("button, a[href], input, select, textarea"))
|
|
@@ -5488,6 +5619,7 @@ window.Aura = (() => {
|
|
|
5488
5619
|
"aria-colindex": ci + 1,
|
|
5489
5620
|
style: cellStyle(c, i),
|
|
5490
5621
|
"data-hide": hideLevel(c) ? String(hideLevel(c)) : void 0,
|
|
5622
|
+
"data-card": cardPart(c, i) === "hide" ? "hide" : void 0,
|
|
5491
5623
|
tabIndex: tabFor(0, ci),
|
|
5492
5624
|
"data-rc": "0:" + ci,
|
|
5493
5625
|
className: cx(
|
|
@@ -5853,7 +5985,7 @@ window.Aura = (() => {
|
|
|
5853
5985
|
),
|
|
5854
5986
|
style: cellStyle(c, j),
|
|
5855
5987
|
...cardAttrs(c, j),
|
|
5856
|
-
"data-label": j ===
|
|
5988
|
+
"data-label": cardPart(c, j) === "title" ? void 0 : c.label || t.totals
|
|
5857
5989
|
},
|
|
5858
5990
|
props.footer[c.key]
|
|
5859
5991
|
);
|
|
@@ -5881,6 +6013,7 @@ window.Aura = (() => {
|
|
|
5881
6013
|
className: cx(
|
|
5882
6014
|
"aura-table",
|
|
5883
6015
|
stacked && "aura-table--stacked",
|
|
6016
|
+
noCardSel && "aura-table--cards-nosel",
|
|
5884
6017
|
scrolledX[0] && "is-scrolled-x",
|
|
5885
6018
|
refreshing && "is-refreshing",
|
|
5886
6019
|
!levels.length && props.className
|
|
@@ -5898,8 +6031,16 @@ window.Aura = (() => {
|
|
|
5898
6031
|
className: "aura-table__scroll",
|
|
5899
6032
|
onMouseOver: showFull,
|
|
5900
6033
|
onMouseLeave: hideFull,
|
|
5901
|
-
onFocus:
|
|
5902
|
-
|
|
6034
|
+
onFocus: function(e) {
|
|
6035
|
+
lastFocus.current = e.target;
|
|
6036
|
+
showFull(e);
|
|
6037
|
+
},
|
|
6038
|
+
onBlur: function(e) {
|
|
6039
|
+
const to = e.relatedTarget;
|
|
6040
|
+
if ((!to || !e.currentTarget.contains(to)) && e.target.getClientRects().length > 0)
|
|
6041
|
+
lastFocus.current = null;
|
|
6042
|
+
hideFull();
|
|
6043
|
+
},
|
|
5903
6044
|
style: scrollStyle,
|
|
5904
6045
|
role: "grid",
|
|
5905
6046
|
"aria-label": props.label,
|
|
@@ -6058,7 +6199,7 @@ window.Aura = (() => {
|
|
|
6058
6199
|
key: t.id,
|
|
6059
6200
|
href: t.href,
|
|
6060
6201
|
className: tabCls(on, own.className),
|
|
6061
|
-
"aria-current": on ? "page" : void 0,
|
|
6202
|
+
"aria-current": on ? props.current || "page" : void 0,
|
|
6062
6203
|
onClick: function(e) {
|
|
6063
6204
|
if (own.onClick) own.onClick(e);
|
|
6064
6205
|
if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
@@ -6405,39 +6546,11 @@ window.Aura = (() => {
|
|
|
6405
6546
|
|
|
6406
6547
|
// src/Avatar.tsx
|
|
6407
6548
|
var React36 = __toESM(require_react(), 1);
|
|
6408
|
-
var AVATAR_TONES = ["progress", "ready", "neutral", "warning"];
|
|
6409
|
-
function initials(name) {
|
|
6410
|
-
const parts = String(name || "?").trim().split(/\s+/);
|
|
6411
|
-
return ((parts[0] || "?")[0] + (parts.length > 1 ? parts[parts.length - 1][0] : parts[0][1] || "")).toUpperCase();
|
|
6412
|
-
}
|
|
6413
6549
|
var Avatar = React36.forwardRef(function Avatar2(props, ref) {
|
|
6414
|
-
const
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
hash = hash * 31 + ch.charCodeAt(0) >>> 0;
|
|
6550
|
+
const errState = React36.useState(null);
|
|
6551
|
+
return avatarElement(props, ref, errState[0], function() {
|
|
6552
|
+
errState[1](props.src || null);
|
|
6418
6553
|
});
|
|
6419
|
-
const tone2 = AVATAR_TONES[hash % AVATAR_TONES.length];
|
|
6420
|
-
return /* @__PURE__ */ React36.createElement(
|
|
6421
|
-
"span",
|
|
6422
|
-
{
|
|
6423
|
-
ref,
|
|
6424
|
-
className: cx("aura-avatar", "aura-avatar--" + size, "aura-avatar--" + tone2, props.className),
|
|
6425
|
-
role: "img",
|
|
6426
|
-
"aria-label": props.name + (props.status ? ", " + props.status : "")
|
|
6427
|
-
},
|
|
6428
|
-
props.src && errState[0] !== props.src ? /* @__PURE__ */ React36.createElement(
|
|
6429
|
-
"img",
|
|
6430
|
-
{
|
|
6431
|
-
key: props.src,
|
|
6432
|
-
src: props.src,
|
|
6433
|
-
alt: "",
|
|
6434
|
-
onError: function() {
|
|
6435
|
-
errState[1](props.src || null);
|
|
6436
|
-
}
|
|
6437
|
-
}
|
|
6438
|
-
) : /* @__PURE__ */ React36.createElement("span", { "aria-hidden": true }, initials(props.name)),
|
|
6439
|
-
props.status === "online" ? /* @__PURE__ */ React36.createElement("span", { className: "aura-avatar__status", "aria-hidden": true }) : null
|
|
6440
|
-
);
|
|
6441
6554
|
});
|
|
6442
6555
|
|
|
6443
6556
|
// src/Stack.tsx
|
|
@@ -6558,6 +6671,27 @@ window.Aura = (() => {
|
|
|
6558
6671
|
if (shared) navState[1](id);
|
|
6559
6672
|
if (navEl && navEl.props.onChange) navEl.props.onChange(id);
|
|
6560
6673
|
}
|
|
6674
|
+
const rootRef = React41.useRef(null);
|
|
6675
|
+
const barRef = React41.useRef(null);
|
|
6676
|
+
const mergedRef = useMergedRef(ref, rootRef);
|
|
6677
|
+
const hasBar = !!(props.header || props.nav);
|
|
6678
|
+
useIsoLayoutEffect(
|
|
6679
|
+
function() {
|
|
6680
|
+
const root = rootRef.current, bar = barRef.current;
|
|
6681
|
+
if (!root || !bar) return;
|
|
6682
|
+
function sync() {
|
|
6683
|
+
root.style.setProperty("--aura-shell-bar-height", bar.getBoundingClientRect().height + "px");
|
|
6684
|
+
}
|
|
6685
|
+
sync();
|
|
6686
|
+
const ro = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(sync);
|
|
6687
|
+
if (ro) ro.observe(bar);
|
|
6688
|
+
return function() {
|
|
6689
|
+
if (ro) ro.disconnect();
|
|
6690
|
+
root.style.removeProperty("--aura-shell-bar-height");
|
|
6691
|
+
};
|
|
6692
|
+
},
|
|
6693
|
+
[hasBar]
|
|
6694
|
+
);
|
|
6561
6695
|
const deskNav = navEl && shared ? React41.cloneElement(navEl, { value: navState[0], onChange: onNav }) : props.nav;
|
|
6562
6696
|
const drawerNav = navEl ? React41.cloneElement(navEl, {
|
|
6563
6697
|
value: shared ? navState[0] : navEl.props.value,
|
|
@@ -6569,32 +6703,56 @@ window.Aura = (() => {
|
|
|
6569
6703
|
collapsed: false,
|
|
6570
6704
|
collapsible: false
|
|
6571
6705
|
}) : props.nav;
|
|
6572
|
-
return /* @__PURE__ */ React41.createElement(
|
|
6573
|
-
|
|
6706
|
+
return /* @__PURE__ */ React41.createElement(
|
|
6707
|
+
"div",
|
|
6574
6708
|
{
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6709
|
+
ref: mergedRef,
|
|
6710
|
+
className: cx(
|
|
6711
|
+
"aura-shell",
|
|
6712
|
+
props.bottomNav && "aura-shell--bottomnav",
|
|
6713
|
+
/* 5.14: no top bar at all, or one that only holds the menu button (gone from lg up): the bar-height token is 0. */
|
|
6714
|
+
!props.header && !props.nav && "aura-shell--no-bar",
|
|
6715
|
+
!props.header && props.nav && "aura-shell--menu-bar",
|
|
6716
|
+
props.className
|
|
6717
|
+
)
|
|
6583
6718
|
},
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6719
|
+
props.nav ? /* @__PURE__ */ React41.createElement("div", { className: "aura-shell__nav" }, deskNav) : null,
|
|
6720
|
+
props.nav ? /* @__PURE__ */ React41.createElement(
|
|
6721
|
+
Drawer,
|
|
6722
|
+
{
|
|
6723
|
+
open,
|
|
6724
|
+
onClose: function() {
|
|
6725
|
+
setOpen(false);
|
|
6726
|
+
},
|
|
6727
|
+
side: "left",
|
|
6728
|
+
size: "nav",
|
|
6729
|
+
"aria-label": props.navLabel || t.navigation,
|
|
6730
|
+
dismissible: true
|
|
6594
6731
|
},
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6732
|
+
drawerNav
|
|
6733
|
+
) : null,
|
|
6734
|
+
/* @__PURE__ */ React41.createElement("div", { className: "aura-shell__main" }, props.header || props.nav ? /* @__PURE__ */ React41.createElement("header", { ref: barRef, className: cx("aura-shell__bar", !props.header && "aura-shell__bar--menu-only") }, props.nav ? /* @__PURE__ */ React41.createElement(
|
|
6735
|
+
IconButton,
|
|
6736
|
+
{
|
|
6737
|
+
className: "aura-shell__menu",
|
|
6738
|
+
icon: /* @__PURE__ */ React41.createElement(IconMenu, null),
|
|
6739
|
+
label: props.menuLabel || t.openNav,
|
|
6740
|
+
size: "md",
|
|
6741
|
+
onClick: function() {
|
|
6742
|
+
setOpen(true);
|
|
6743
|
+
},
|
|
6744
|
+
"aria-expanded": open
|
|
6745
|
+
}
|
|
6746
|
+
) : null, /* @__PURE__ */ React41.createElement("div", { className: "aura-shell__bar-content" }, props.header)) : null, /* @__PURE__ */ React41.createElement(
|
|
6747
|
+
"main",
|
|
6748
|
+
{
|
|
6749
|
+
className: cx("aura-shell__content", props.contentPadding === false && "is-flush"),
|
|
6750
|
+
id: props.mainId || "main",
|
|
6751
|
+
tabIndex: -1
|
|
6752
|
+
},
|
|
6753
|
+
props.children
|
|
6754
|
+
), props.bottomNav || null)
|
|
6755
|
+
);
|
|
6598
6756
|
});
|
|
6599
6757
|
|
|
6600
6758
|
// src/ActionBar.tsx
|
|
@@ -6704,7 +6862,7 @@ window.Aura = (() => {
|
|
|
6704
6862
|
return out;
|
|
6705
6863
|
}
|
|
6706
6864
|
var Table = React44.forwardRef(function Table2(props, ref) {
|
|
6707
|
-
const { caption, captionHidden, density, stackBelow, className, children, ...rest } = props;
|
|
6865
|
+
const { caption, captionHidden, density, stackBelow, align, bordered, className, children, ...rest } = props;
|
|
6708
6866
|
const labels = stackBelow ? headerLabels(children) : null;
|
|
6709
6867
|
if (labels && !labels.length)
|
|
6710
6868
|
devWarnOnce(
|
|
@@ -6732,7 +6890,7 @@ window.Aura = (() => {
|
|
|
6732
6890
|
"div",
|
|
6733
6891
|
{
|
|
6734
6892
|
ref: wrap,
|
|
6735
|
-
className: cx("aura-tbl-wrap", stackBelow && "is-stackable"),
|
|
6893
|
+
className: cx("aura-tbl-wrap", stackBelow && "is-stackable", bordered === false && "is-flush"),
|
|
6736
6894
|
"data-density": density,
|
|
6737
6895
|
tabIndex: scrolls ? 0 : void 0,
|
|
6738
6896
|
role: scrolls && (caption != null || rest["aria-label"]) ? "region" : void 0,
|
|
@@ -6743,7 +6901,12 @@ window.Aura = (() => {
|
|
|
6743
6901
|
"table",
|
|
6744
6902
|
{
|
|
6745
6903
|
ref,
|
|
6746
|
-
className: cx(
|
|
6904
|
+
className: cx(
|
|
6905
|
+
"aura-tbl",
|
|
6906
|
+
stackBelow && "aura-tbl--stack-" + stackBelow,
|
|
6907
|
+
align === "middle" && "aura-tbl--middle",
|
|
6908
|
+
className
|
|
6909
|
+
),
|
|
6747
6910
|
role: stackBelow ? "table" : void 0,
|
|
6748
6911
|
...rest
|
|
6749
6912
|
},
|
|
@@ -6791,7 +6954,7 @@ window.Aura = (() => {
|
|
|
6791
6954
|
);
|
|
6792
6955
|
}
|
|
6793
6956
|
var Th = React44.forwardRef(function Th2(props, ref) {
|
|
6794
|
-
const { align, numeric, mono, className, scope, label, ...rest } = props;
|
|
6957
|
+
const { align, numeric, mono, className, scope, label, card, ...rest } = props;
|
|
6795
6958
|
const stacked = React44.useContext(StackLabels) != null;
|
|
6796
6959
|
return /* @__PURE__ */ React44.createElement(
|
|
6797
6960
|
"th",
|
|
@@ -6800,14 +6963,16 @@ window.Aura = (() => {
|
|
|
6800
6963
|
scope: scope || "col",
|
|
6801
6964
|
className: cellClass("aura-tbl__th", props),
|
|
6802
6965
|
role: stacked ? scope === "row" ? "rowheader" : "columnheader" : void 0,
|
|
6966
|
+
"data-card": stacked && (card === "title" || card === "action") ? card : void 0,
|
|
6803
6967
|
...rest
|
|
6804
6968
|
}
|
|
6805
6969
|
);
|
|
6806
6970
|
});
|
|
6807
6971
|
var Td = React44.forwardRef(function Td2(props, ref) {
|
|
6808
|
-
const { align, numeric, mono, className, scope, label, ...rest } = props;
|
|
6972
|
+
const { align, numeric, mono, className, scope, label, card, ...rest } = props;
|
|
6809
6973
|
const labels = React44.useContext(StackLabels), col = React44.useContext(ColumnIndex);
|
|
6810
|
-
const
|
|
6974
|
+
const slot = labels && (card === "title" || card === "action") ? card : void 0;
|
|
6975
|
+
const shown = labels && !slot ? label != null ? label : col >= 0 ? labels[col] : void 0 : void 0;
|
|
6811
6976
|
return /* @__PURE__ */ React44.createElement(
|
|
6812
6977
|
"td",
|
|
6813
6978
|
{
|
|
@@ -6815,6 +6980,7 @@ window.Aura = (() => {
|
|
|
6815
6980
|
className: cellClass("aura-tbl__td", props),
|
|
6816
6981
|
role: labels ? "cell" : void 0,
|
|
6817
6982
|
"data-label": shown || void 0,
|
|
6983
|
+
"data-card": slot,
|
|
6818
6984
|
...rest
|
|
6819
6985
|
}
|
|
6820
6986
|
);
|
|
@@ -6890,34 +7056,8 @@ window.Aura = (() => {
|
|
|
6890
7056
|
// src/Stat.tsx
|
|
6891
7057
|
var React47 = __toESM(require_react(), 1);
|
|
6892
7058
|
var Stat = React47.forwardRef(function Stat2(props, ref) {
|
|
6893
|
-
const ch = props.change;
|
|
6894
|
-
const dir = ch && (ch.direction || "flat");
|
|
6895
|
-
const tone2 = ch && (ch.tone || (dir === "up" ? "positive" : dir === "down" ? "negative" : "neutral"));
|
|
6896
7059
|
const Link = useLinkComponent(props.linkComponent);
|
|
6897
|
-
|
|
6898
|
-
const numeric = typeof v === "number" || typeof v === "string" && /\d/.test(v) && /^[\s\d.,:+\-\u2212%()\u0E3F$\u20AC\u00A3\u00A5kKmMbB]+$/.test(v.replace(/\b[A-Z]{3}\b/g, ""));
|
|
6899
|
-
const Tag3 = props.href ? Link : props.onClick ? "button" : "div";
|
|
6900
|
-
const interactive = !!(props.href || props.onClick);
|
|
6901
|
-
return /* @__PURE__ */ React47.createElement(
|
|
6902
|
-
Tag3,
|
|
6903
|
-
{
|
|
6904
|
-
ref,
|
|
6905
|
-
className: cx("aura-stat", interactive && "is-interactive", props.loading && "is-loading", props.className),
|
|
6906
|
-
href: props.href,
|
|
6907
|
-
onClick: props.onClick,
|
|
6908
|
-
type: Tag3 === "button" ? "button" : void 0,
|
|
6909
|
-
"aria-busy": props.loading || void 0
|
|
6910
|
-
},
|
|
6911
|
-
/* @__PURE__ */ React47.createElement("span", { className: "aura-stat__head" }, /* @__PURE__ */ React47.createElement("span", { className: "aura-stat__label" }, props.label), props.icon ? /* @__PURE__ */ React47.createElement("span", { className: "aura-stat__icon" }, /* @__PURE__ */ React47.createElement(Icon, { name: props.icon })) : null),
|
|
6912
|
-
props.loading ? /* @__PURE__ */ React47.createElement("span", { className: "aura-stat__value" }, /* @__PURE__ */ React47.createElement("span", { className: "aura-skel aura-stat__skel" })) : /* @__PURE__ */ React47.createElement("span", { className: cx("aura-stat__value", numeric && "is-numeric") }, props.value, props.unit ? /* @__PURE__ */ React47.createElement("span", { className: "aura-stat__unit" }, props.unit) : null),
|
|
6913
|
-
ch && !props.loading || props.caption ? /* @__PURE__ */ React47.createElement("span", { className: "aura-stat__foot" }, ch && !props.loading ? /* @__PURE__ */ React47.createElement("span", { className: cx("aura-stat__change", "is-" + tone2) }, /* @__PURE__ */ React47.createElement(
|
|
6914
|
-
Icon,
|
|
6915
|
-
{
|
|
6916
|
-
name: dir === "up" ? /* @__PURE__ */ React47.createElement(IconTrendingUp, null) : dir === "down" ? /* @__PURE__ */ React47.createElement(IconTrendingDown, null) : /* @__PURE__ */ React47.createElement(IconMinus, null),
|
|
6917
|
-
size: 14
|
|
6918
|
-
}
|
|
6919
|
-
), /* @__PURE__ */ React47.createElement("span", null, ch.value)) : null, ch && ch.label && !props.loading ? /* @__PURE__ */ React47.createElement("span", { className: "aura-stat__caption" }, ch.label) : null, props.caption ? /* @__PURE__ */ React47.createElement("span", { className: "aura-stat__caption" }, props.caption) : null) : null
|
|
6920
|
-
);
|
|
7060
|
+
return statElement(props, ref, Link);
|
|
6921
7061
|
});
|
|
6922
7062
|
|
|
6923
7063
|
// src/TimePicker.tsx
|