@jirawatpyk/aura-react 5.29.0 → 5.30.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 +40 -0
- package/dist/aura.bundle.js +115 -21
- package/dist/cjs/index.cjs +115 -21
- package/dist/esm/Checkbox.js +4 -2
- package/dist/esm/DataTable.js +36 -0
- package/dist/esm/Field.js +2 -1
- package/dist/esm/Menu.js +61 -14
- package/dist/esm/RadioGroup.js +7 -2
- package/dist/esm/Select.js +2 -2
- package/dist/esm/Tag.js +1 -1
- package/dist/esm/TextField.js +2 -2
- package/dist/esm/Textarea.js +2 -2
- package/dist/esm/classes.js +5 -1
- package/dist/esm/internal.js +2 -1
- package/dist/index.d.cts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/styles.css +128 -39
- package/dist/styles.layer.css +128 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -186,6 +186,46 @@ 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.30 — Visual polish (audit, Oct 2026) and Chamber-OS addenda 38–40
|
|
190
|
+
|
|
191
|
+
One release: everything below ships together in 5.30.0.
|
|
192
|
+
|
|
193
|
+
### Menus stay open on scroll; StatusPill weight (addenda 39–40)
|
|
194
|
+
|
|
195
|
+
- **An open menu follows its trigger** (item 136): DropdownMenu and every menu built on it (DataTable's row ⋯ and column menus) now move with the trigger on scroll and resize — a slight finger drag during a tap, the phone's address bar or keyboard no longer close it, as Popover already behaved. It closes once the trigger is wholly out of view (the page's, or a box around it that clips it — a fixed bar inside a scrolling wrapper isn't clipped by it, and `overflow-x: clip` only clips sideways), without taking focus back so the page doesn't jump; inside a Dialog or Drawer focus goes back to the trigger without scrolling, so it stays in the dialog. Escape, a pointerdown outside and choosing an item close it as before, with focus back on the trigger. No new prop.
|
|
196
|
+
- **StatusPill is 500 (medium)** (item 137) wherever it sits — before, it took its parent's weight (regular beside a heading, bold inside bold text). Badge stays 600, so the two stay distinct.
|
|
197
|
+
|
|
198
|
+
### 44px fields and choice rows (addendum 38)
|
|
199
|
+
|
|
200
|
+
- **`touchHeight` on TextField, Textarea, Select, RadioGroup and Checkbox** (item 135): `touchHeight="always"` gives a 44px input box and 44px choice rows at every width — also with a mouse and inside `density="compact"` — for a form whose spec asks for 44px targets everywhere (Chamber-OS's issue dialog: zero-rate radios, certificate number, typed phrase). `touchHeight` (`true`) does it only below 640px or on a coarse pointer, as Button's `touchHeight`; touch screens already had 44px fields and rows. A one-line option's label is centred in its row (a Checkbox row is 45px: its label sits on a 21px line); a row with a description grows. On a Checkbox it applies to a labelled box; a bare box uses `hitArea`. Textarea accepts it too, but is always at least 96px tall, so nothing changes there. In a horizontal RadioGroup each option keeps its own height (one-line options stay centred beside a taller one with a description).
|
|
201
|
+
- **How:** the field's root gets `is-touch-always` / `is-touch`, which sets its own `--aura-input-height` to `--aura-touch-target` (44px) — any control inside that reads the input height follows, whatever density is around it. Label, hint and error ids are unchanged; Button's `touchHeight` is unchanged.
|
|
202
|
+
|
|
203
|
+
### Visual polish, part 2
|
|
204
|
+
|
|
205
|
+
- **"Chosen" is violet everywhere** (audit item 4): a checked Checkbox or Radio, a Switch that is on, the active Tab's underline, the current Pagination page, the selected Calendar day and year, a completed Stepper step and a checked menu item use the new `--aura-control-checked-bg` / `-fg` (violet-700 with a white mark in light, violet-300 with a zinc-900 mark in dark). Buttons stay ink / off-white. A disabled Switch that is on keeps its whole violet track (faded, it fell under 3:1 from a disabled one that is off) and fades its thumb instead.
|
|
206
|
+
- **Tables say when they scroll** (item 9): a Table wider than its box shows a soft shadow at the edge with more to scroll (CSS only, `--aura-scroll-shadow`; body rows show it, the header band and totals rows cover it; set `--aura-tbl-bg` if you give the box another ground); a DataTable with columns past its end edge shows the same shadow over the grid's end edge, inside its scrollbars (`has-more-x`), until scrolled to the end. Stacking stays opt-in (`stackBelow`) — no layout changes by default.
|
|
207
|
+
- **Table columns are never squeezed to one letter** (item 8): from 640px a cell is at least 10ch wide; a longer word (an email, a URL) still breaks to fit rather than widening the table; numbers already stay on one line. Phones are unchanged (a table still fits its box): give a table that is too wide for a phone `stackBelow`.
|
|
208
|
+
- **Totals** (item 20): a 2px rule in the hairline colour over the totals (DataTable and Table), not the strong border that glared in dark; with several totals rows the last is 14px bold; a pinned DataTable totals row casts a soft shadow over the rows under it.
|
|
209
|
+
- **SegmentedControl** (items 11–12) is as tall as a field with a mouse (`--aura-input-height`: 44px, 36px in compact; `size="sm"` unchanged; icon-only options stay square; on touch screens each option is 44px, as before), and the selected option is 600 weight on its own thumb colour (`--aura-segmented-thumb-bg`), which is lighter than the track in dark instead of darker.
|
|
210
|
+
- **FilterSelect** (item 11): from 640px the face has a field's inset and 14px text, like the search box beside it; phones keep the tight face so three filters and a chip share a row.
|
|
211
|
+
- **Smaller fixes**: the show-password button is fg-secondary like a field's other icons (item 14); a removable Tag's × is 14px (item 17); a plain link (no class) inside a Card, Stat, Alert, EmptyState, field, tab panel, AppShell main, table or Dialog takes the accent colour, at zero specificity so your own link rules win (item 18).
|
|
212
|
+
- **Not changed, on purpose**: a ghost button that starts an ActionBar keeps its box at the bar's edge (Chamber-OS 116 relies on it); the Progress track keeps its 3:1 edge (WCAG 1.4.11); DatePicker's calendar button and TimePicker's clock stay where they are (one is a button, one a label icon).
|
|
213
|
+
- Size budgets: `styles.css` 32 kB, DataTable 21 kB, `aura.bundle.js` and the whole package 66 kB.
|
|
214
|
+
|
|
215
|
+
### Visual polish
|
|
216
|
+
|
|
217
|
+
A visual audit of every Storybook story in light, dark and at 390px. This release takes the system-wide fixes; colour hues and layout defaults are unchanged.
|
|
218
|
+
|
|
219
|
+
- **Dark mode:** the primary button, checked box, selected day, completed step, `bg-surface-strong` and `bg-inverted` (tooltips, counts) are off-white `zinc-200` instead of pure white, which was the brightest thing on a dark page. Primary hover is `zinc-100`.
|
|
220
|
+
- **Status fills:** Blocked is `red-800` in light (quieter in a long table, and further from the lime Ready fill); Warning is `amber-600` in dark too (amber-500 glowed). Ready, Warning and Blocked still differ by lightness, not only hue.
|
|
221
|
+
- **Neutral fills show on the light canvas:** `--aura-status-neutral-bg` is `zinc-200` (was `zinc-100` on a `zinc-50` page), so the neutral StatusPill, tab counts, Avatar and SideNav initials are one step darker in light. The neutral Badge and the EmptyState icon disc use it too.
|
|
222
|
+
- **DataTable header band** has its own token, `--aura-table-head-bg`: the canvas in light, `#111114` in dark — between the page and the card, so it no longer reads as a hole. Table's header and totals rows (also the totals card) and DataTable's totals row use it.
|
|
223
|
+
- **Disabled filled buttons** (primary, danger, creative) use new tokens `--aura-button-disabled-bg` / `-fg`: a grey fill with muted text at full opacity, not a faded copy (faded red read as pink, faded ink as a separate grey button); the creative shadow goes. Secondary, ghost and danger-secondary keep the fade. In forced colours every disabled button shows GrayText and the fade.
|
|
224
|
+
- **Buttons are always the AURA sans** (`font-family: var(--font-sans)`), also outside a root that sets the font. An app that sets its own font on `body` should set `--font-sans` too, or its buttons stay Inter.
|
|
225
|
+
- **Table caption** has 12px below it, so it no longer touches the header.
|
|
226
|
+
- **DataTable skeleton action bars** take the button's own shape (`--aura-button-radius`).
|
|
227
|
+
- **Thai:** where the language is Thai (`lang="th"` on the page or a part), StatusPill, Badge and tab counts are 12px (the loading pill matches), BottomNav labels 12px, Stepper descriptions 13px with a 1.6 line, SideNav labels on a 22px line, field labels, hints and errors on a 1.6 line, Radio and Checkbox descriptions 13px on a 1.6 line, and a stacked card's field labels 12px. A `lang="en"` part inside keeps the Latin sizes. These follow the `lang` attribute, not `AuraProvider locale`: set `<html lang="th">` (Next.js: the root layout's `<html lang>`), so portals (Dialog, Menu, Popover) get it too.
|
|
228
|
+
|
|
189
229
|
## 5.29 — Chamber-OS addendum 37
|
|
190
230
|
|
|
191
231
|
- **DataTable loading rows match the rows they stand in for** (item 134), so the layout doesn't jump when the rows arrive:
|
package/dist/aura.bundle.js
CHANGED
|
@@ -158,6 +158,9 @@ window.Aura = (() => {
|
|
|
158
158
|
out[k] = src[k];
|
|
159
159
|
return out;
|
|
160
160
|
}
|
|
161
|
+
function touchClass(t) {
|
|
162
|
+
return t === "always" ? "is-touch-always" : !!t && "is-touch";
|
|
163
|
+
}
|
|
161
164
|
var TONES = ["neutral", "accent", "success", "warning", "danger"];
|
|
162
165
|
function tone(t) {
|
|
163
166
|
return TONES.indexOf(t) >= 0 ? t : "neutral";
|
|
@@ -1364,6 +1367,39 @@ window.Aura = (() => {
|
|
|
1364
1367
|
var React8 = __toESM(require_react(), 1);
|
|
1365
1368
|
var import_react_dom = __toESM(require_react_dom(), 1);
|
|
1366
1369
|
var ITEMS = '[role^="menuitem"]';
|
|
1370
|
+
function makesBlock(s) {
|
|
1371
|
+
return s.transform !== "none" || s.translate !== "none" || s.rotate !== "none" || s.scale !== "none" || s.filter !== "none" || s.backdropFilter !== "none" || s.perspective !== "none" || s.contentVisibility === "auto" || /paint|layout|strict|content/.test(s.contain) || /transform|translate|rotate|scale|filter|perspective/.test(s.willChange);
|
|
1372
|
+
}
|
|
1373
|
+
function inView(el) {
|
|
1374
|
+
if (!el.isConnected) return false;
|
|
1375
|
+
const r = el.getBoundingClientRect();
|
|
1376
|
+
if (r.width === 0 && r.height === 0) return false;
|
|
1377
|
+
let top = r.top, bottom = r.bottom, left = r.left, right = r.right;
|
|
1378
|
+
let pos = getComputedStyle(el).position;
|
|
1379
|
+
for (let p = el.parentElement; p && p !== document.body && p !== document.documentElement; p = p.parentElement) {
|
|
1380
|
+
const s = getComputedStyle(p);
|
|
1381
|
+
const block = makesBlock(s);
|
|
1382
|
+
if (pos === "fixed" && !block) continue;
|
|
1383
|
+
if (pos === "absolute" && s.position === "static" && !block) continue;
|
|
1384
|
+
if (s.display !== "contents") {
|
|
1385
|
+
const b = p.getBoundingClientRect();
|
|
1386
|
+
if (s.overflowX !== "visible") {
|
|
1387
|
+
left = Math.max(left, b.left);
|
|
1388
|
+
right = Math.min(right, b.right);
|
|
1389
|
+
}
|
|
1390
|
+
if (s.overflowY !== "visible") {
|
|
1391
|
+
top = Math.max(top, b.top);
|
|
1392
|
+
bottom = Math.min(bottom, b.bottom);
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
pos = s.position === "fixed" || s.position === "absolute" ? s.position : "static";
|
|
1396
|
+
}
|
|
1397
|
+
top = Math.max(top, 0);
|
|
1398
|
+
left = Math.max(left, 0);
|
|
1399
|
+
bottom = Math.min(bottom, window.innerHeight);
|
|
1400
|
+
right = Math.min(right, window.innerWidth);
|
|
1401
|
+
return bottom > top && right > left;
|
|
1402
|
+
}
|
|
1367
1403
|
var Menu = React8.forwardRef(function Menu2(props, ref) {
|
|
1368
1404
|
const own = React8.useRef(null), merged = useMergedRef(ref, own);
|
|
1369
1405
|
const posState = React8.useState(null);
|
|
@@ -1373,21 +1409,30 @@ window.Aura = (() => {
|
|
|
1373
1409
|
const headerId = uid(), itemId = uid();
|
|
1374
1410
|
const hasHeader = props.header != null && props.header !== false && props.header !== "";
|
|
1375
1411
|
const Link = useLinkComponent(props.linkComponent);
|
|
1412
|
+
function place() {
|
|
1413
|
+
const a = props.anchor, m = own.current;
|
|
1414
|
+
if (!a || !m) return;
|
|
1415
|
+
const r = a.getBoundingClientRect(), mh = m.scrollHeight, mw = m.offsetWidth, below2 = window.innerHeight - r.bottom - 12, above = r.top - 12;
|
|
1416
|
+
let top = r.bottom + 4, maxHeight;
|
|
1417
|
+
if (mh > below2) {
|
|
1418
|
+
if (mh <= above) top = r.top - mh - 4;
|
|
1419
|
+
else if (above > below2) {
|
|
1420
|
+
maxHeight = above;
|
|
1421
|
+
top = r.top - above - 4;
|
|
1422
|
+
} else maxHeight = below2;
|
|
1423
|
+
}
|
|
1424
|
+
const left = Math.max(8, Math.min(r.right - mw, window.innerWidth - mw - 8));
|
|
1425
|
+
setPos(function(p) {
|
|
1426
|
+
return p && p.top === top && p.left === left && p.maxHeight === maxHeight ? p : { top, left, maxHeight };
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
const placeRef = React8.useRef(place);
|
|
1430
|
+
placeRef.current = place;
|
|
1431
|
+
const live = React8.useRef({ anchor: props.anchor, onClose: props.onClose });
|
|
1432
|
+
live.current = { anchor: props.anchor, onClose: props.onClose };
|
|
1376
1433
|
useIsoLayoutEffect(
|
|
1377
1434
|
function() {
|
|
1378
|
-
|
|
1379
|
-
if (!a || !m) return;
|
|
1380
|
-
const r = a.getBoundingClientRect(), mh = m.scrollHeight, mw = m.offsetWidth, below2 = window.innerHeight - r.bottom - 12, above = r.top - 12;
|
|
1381
|
-
let top = r.bottom + 4, maxHeight;
|
|
1382
|
-
if (mh > below2) {
|
|
1383
|
-
if (mh <= above) top = r.top - mh - 4;
|
|
1384
|
-
else if (above > below2) {
|
|
1385
|
-
maxHeight = above;
|
|
1386
|
-
top = r.top - above - 4;
|
|
1387
|
-
} else maxHeight = below2;
|
|
1388
|
-
}
|
|
1389
|
-
const left = Math.max(8, Math.min(r.right - mw, window.innerWidth - mw - 8));
|
|
1390
|
-
setPos({ top, left, maxHeight });
|
|
1435
|
+
place();
|
|
1391
1436
|
},
|
|
1392
1437
|
[props.anchor, mounted, hasHeader]
|
|
1393
1438
|
);
|
|
@@ -1417,7 +1462,12 @@ window.Aura = (() => {
|
|
|
1417
1462
|
props.onClose(false);
|
|
1418
1463
|
}
|
|
1419
1464
|
function onScroll(e) {
|
|
1420
|
-
if (own.current &&
|
|
1465
|
+
if (own.current && e.target instanceof Node && own.current.contains(e.target)) return;
|
|
1466
|
+
const a = live.current.anchor;
|
|
1467
|
+
if (a && !inView(a)) {
|
|
1468
|
+
live.current.onClose(false);
|
|
1469
|
+
if (a instanceof HTMLElement && a.closest('[aria-modal="true"]')) a.focus({ preventScroll: true });
|
|
1470
|
+
} else placeRef.current();
|
|
1421
1471
|
}
|
|
1422
1472
|
document.addEventListener("pointerdown", outside, true);
|
|
1423
1473
|
window.addEventListener("scroll", onScroll, true);
|
|
@@ -1627,7 +1677,8 @@ window.Aura = (() => {
|
|
|
1627
1677
|
"className",
|
|
1628
1678
|
"tabIndex",
|
|
1629
1679
|
"disabled",
|
|
1630
|
-
"hitArea"
|
|
1680
|
+
"hitArea",
|
|
1681
|
+
"touchHeight"
|
|
1631
1682
|
]);
|
|
1632
1683
|
const text2 = props.children;
|
|
1633
1684
|
const labelled = text2 != null && text2 !== "";
|
|
@@ -1646,6 +1697,7 @@ window.Aura = (() => {
|
|
|
1646
1697
|
className: cx(
|
|
1647
1698
|
"aura-check",
|
|
1648
1699
|
labelled && "aura-check--labelled",
|
|
1700
|
+
labelled && touchClass(props.touchHeight),
|
|
1649
1701
|
hit && "has-hit",
|
|
1650
1702
|
props.disabled && "is-disabled",
|
|
1651
1703
|
props.className
|
|
@@ -1721,7 +1773,8 @@ window.Aura = (() => {
|
|
|
1721
1773
|
"id",
|
|
1722
1774
|
"suffix",
|
|
1723
1775
|
"options",
|
|
1724
|
-
"placeholder"
|
|
1776
|
+
"placeholder",
|
|
1777
|
+
"touchHeight"
|
|
1725
1778
|
];
|
|
1726
1779
|
|
|
1727
1780
|
// src/TextField.tsx
|
|
@@ -1739,7 +1792,7 @@ window.Aura = (() => {
|
|
|
1739
1792
|
required: props.required,
|
|
1740
1793
|
optional: props.optional,
|
|
1741
1794
|
disabled: props.disabled,
|
|
1742
|
-
className: props.className
|
|
1795
|
+
className: cx(touchClass(props.touchHeight), props.className)
|
|
1743
1796
|
},
|
|
1744
1797
|
/* @__PURE__ */ React13.createElement("div", { className: cx("aura-input", props.icon && "has-icon", props.suffix && "has-suffix") }, props.icon ? /* @__PURE__ */ React13.createElement(Icon, { name: props.icon, className: "aura-input__icon" }) : null, /* @__PURE__ */ React13.createElement(
|
|
1745
1798
|
"input",
|
|
@@ -1773,7 +1826,7 @@ window.Aura = (() => {
|
|
|
1773
1826
|
required: props.required,
|
|
1774
1827
|
optional: props.optional,
|
|
1775
1828
|
disabled: props.disabled,
|
|
1776
|
-
className: props.className
|
|
1829
|
+
className: cx(touchClass(props.touchHeight), props.className)
|
|
1777
1830
|
},
|
|
1778
1831
|
/* @__PURE__ */ React14.createElement(
|
|
1779
1832
|
"textarea",
|
|
@@ -2207,7 +2260,7 @@ window.Aura = (() => {
|
|
|
2207
2260
|
required: props.required,
|
|
2208
2261
|
optional: props.optional,
|
|
2209
2262
|
disabled: props.disabled,
|
|
2210
|
-
className: props.className
|
|
2263
|
+
className: cx(touchClass(props.touchHeight), props.className)
|
|
2211
2264
|
},
|
|
2212
2265
|
child
|
|
2213
2266
|
);
|
|
@@ -3439,7 +3492,12 @@ window.Aura = (() => {
|
|
|
3439
3492
|
"fieldset",
|
|
3440
3493
|
{
|
|
3441
3494
|
ref: setRef,
|
|
3442
|
-
className: cx(
|
|
3495
|
+
className: cx(
|
|
3496
|
+
"aura-field aura-radio-group",
|
|
3497
|
+
props.error && "is-invalid",
|
|
3498
|
+
touchClass(props.touchHeight),
|
|
3499
|
+
props.className
|
|
3500
|
+
),
|
|
3443
3501
|
"aria-describedby": describedBy(id, props),
|
|
3444
3502
|
"aria-invalid": props.error ? true : void 0,
|
|
3445
3503
|
disabled: props.disabled
|
|
@@ -4607,7 +4665,7 @@ window.Aura = (() => {
|
|
|
4607
4665
|
"aria-label": props.removeLabel || t.remove(name),
|
|
4608
4666
|
onClick: props.onRemove
|
|
4609
4667
|
},
|
|
4610
|
-
/* @__PURE__ */ React27.createElement(Icon, { name: /* @__PURE__ */ React27.createElement(IconX, null), size:
|
|
4668
|
+
/* @__PURE__ */ React27.createElement(Icon, { name: /* @__PURE__ */ React27.createElement(IconX, null), size: 14 })
|
|
4611
4669
|
);
|
|
4612
4670
|
return /* @__PURE__ */ React27.createElement(Tooltip, { content: fullText, open: fullText ? void 0 : false }, btn);
|
|
4613
4671
|
}() : null);
|
|
@@ -5408,6 +5466,28 @@ window.Aura = (() => {
|
|
|
5408
5466
|
return px != null && below(boxWidth[0], px);
|
|
5409
5467
|
}
|
|
5410
5468
|
const scrollRef = React32.useRef(null);
|
|
5469
|
+
const edgeState = React32.useState("");
|
|
5470
|
+
const checkMoreX = function() {
|
|
5471
|
+
const el = scrollRef.current;
|
|
5472
|
+
if (!el) return;
|
|
5473
|
+
const more = Math.abs(el.scrollLeft) + el.clientWidth < el.scrollWidth - 1;
|
|
5474
|
+
const next = more ? [el.offsetTop, el.clientHeight, el.offsetWidth - el.clientWidth].join(" ") : "";
|
|
5475
|
+
if (next !== edgeState[0]) edgeState[1](next);
|
|
5476
|
+
};
|
|
5477
|
+
const checkRef = React32.useRef(checkMoreX);
|
|
5478
|
+
checkRef.current = checkMoreX;
|
|
5479
|
+
React32.useEffect(function() {
|
|
5480
|
+
const el = scrollRef.current;
|
|
5481
|
+
if (!el || typeof ResizeObserver === "undefined") return;
|
|
5482
|
+
const ro = new ResizeObserver(function() {
|
|
5483
|
+
checkRef.current();
|
|
5484
|
+
});
|
|
5485
|
+
ro.observe(el);
|
|
5486
|
+
if (el.firstElementChild) ro.observe(el.firstElementChild);
|
|
5487
|
+
return function() {
|
|
5488
|
+
ro.disconnect();
|
|
5489
|
+
};
|
|
5490
|
+
}, []);
|
|
5411
5491
|
const tipState = React32.useState(null), tip = tipState[0], setTip = tipState[1];
|
|
5412
5492
|
function showFull(e) {
|
|
5413
5493
|
const el = e.target.closest ? e.target.closest(".aura-table__td") : null;
|
|
@@ -6571,12 +6651,25 @@ window.Aura = (() => {
|
|
|
6571
6651
|
stacked && "aura-table--stacked",
|
|
6572
6652
|
noCardSel && "aura-table--cards-nosel",
|
|
6573
6653
|
scrolledX[0] && "is-scrolled-x",
|
|
6654
|
+
edgeState[0] && !stacked && "has-more-x",
|
|
6574
6655
|
refreshing && "is-refreshing",
|
|
6575
6656
|
!levels.length && props.className
|
|
6576
6657
|
),
|
|
6577
6658
|
style: levels.length ? { ["--aura-q-back"]: String(levels[levels.length - 1].px / Q) } : void 0
|
|
6578
6659
|
},
|
|
6579
6660
|
refreshing ? /* @__PURE__ */ React32.createElement("span", { className: "aura-table__busy-bar", "aria-hidden": true }) : null,
|
|
6661
|
+
edgeState[0] && !stacked ? /* @__PURE__ */ React32.createElement(
|
|
6662
|
+
"span",
|
|
6663
|
+
{
|
|
6664
|
+
className: "aura-table__edge",
|
|
6665
|
+
"aria-hidden": true,
|
|
6666
|
+
style: {
|
|
6667
|
+
"--aura-edge-top": edgeState[0].split(" ")[0] + "px",
|
|
6668
|
+
"--aura-edge-h": edgeState[0].split(" ")[1] + "px",
|
|
6669
|
+
"--aura-edge-sb": edgeState[0].split(" ")[2] + "px"
|
|
6670
|
+
}
|
|
6671
|
+
}
|
|
6672
|
+
) : null,
|
|
6580
6673
|
/* @__PURE__ */ React32.createElement(
|
|
6581
6674
|
"div",
|
|
6582
6675
|
{
|
|
@@ -6612,6 +6705,7 @@ window.Aura = (() => {
|
|
|
6612
6705
|
setScrollTop(t2.scrollTop);
|
|
6613
6706
|
const sx = t2.scrollLeft > 0;
|
|
6614
6707
|
if (sx !== scrolledX[0]) scrolledX[1](sx);
|
|
6708
|
+
checkMoreX();
|
|
6615
6709
|
}
|
|
6616
6710
|
},
|
|
6617
6711
|
/* @__PURE__ */ React32.createElement(
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -140,6 +140,9 @@ function omit(src, keys) {
|
|
|
140
140
|
out[k] = src[k];
|
|
141
141
|
return out;
|
|
142
142
|
}
|
|
143
|
+
function touchClass(t) {
|
|
144
|
+
return t === "always" ? "is-touch-always" : !!t && "is-touch";
|
|
145
|
+
}
|
|
143
146
|
var TONES = ["neutral", "accent", "success", "warning", "danger"];
|
|
144
147
|
function tone(t) {
|
|
145
148
|
return TONES.indexOf(t) >= 0 ? t : "neutral";
|
|
@@ -1346,6 +1349,39 @@ var IconButton = React7.forwardRef(function IconButton2(props, ref) {
|
|
|
1346
1349
|
var React8 = __toESM(require("react"), 1);
|
|
1347
1350
|
var import_react_dom = require("react-dom");
|
|
1348
1351
|
var ITEMS = '[role^="menuitem"]';
|
|
1352
|
+
function makesBlock(s) {
|
|
1353
|
+
return s.transform !== "none" || s.translate !== "none" || s.rotate !== "none" || s.scale !== "none" || s.filter !== "none" || s.backdropFilter !== "none" || s.perspective !== "none" || s.contentVisibility === "auto" || /paint|layout|strict|content/.test(s.contain) || /transform|translate|rotate|scale|filter|perspective/.test(s.willChange);
|
|
1354
|
+
}
|
|
1355
|
+
function inView(el) {
|
|
1356
|
+
if (!el.isConnected) return false;
|
|
1357
|
+
const r = el.getBoundingClientRect();
|
|
1358
|
+
if (r.width === 0 && r.height === 0) return false;
|
|
1359
|
+
let top = r.top, bottom = r.bottom, left = r.left, right = r.right;
|
|
1360
|
+
let pos = getComputedStyle(el).position;
|
|
1361
|
+
for (let p = el.parentElement; p && p !== document.body && p !== document.documentElement; p = p.parentElement) {
|
|
1362
|
+
const s = getComputedStyle(p);
|
|
1363
|
+
const block = makesBlock(s);
|
|
1364
|
+
if (pos === "fixed" && !block) continue;
|
|
1365
|
+
if (pos === "absolute" && s.position === "static" && !block) continue;
|
|
1366
|
+
if (s.display !== "contents") {
|
|
1367
|
+
const b = p.getBoundingClientRect();
|
|
1368
|
+
if (s.overflowX !== "visible") {
|
|
1369
|
+
left = Math.max(left, b.left);
|
|
1370
|
+
right = Math.min(right, b.right);
|
|
1371
|
+
}
|
|
1372
|
+
if (s.overflowY !== "visible") {
|
|
1373
|
+
top = Math.max(top, b.top);
|
|
1374
|
+
bottom = Math.min(bottom, b.bottom);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
pos = s.position === "fixed" || s.position === "absolute" ? s.position : "static";
|
|
1378
|
+
}
|
|
1379
|
+
top = Math.max(top, 0);
|
|
1380
|
+
left = Math.max(left, 0);
|
|
1381
|
+
bottom = Math.min(bottom, window.innerHeight);
|
|
1382
|
+
right = Math.min(right, window.innerWidth);
|
|
1383
|
+
return bottom > top && right > left;
|
|
1384
|
+
}
|
|
1349
1385
|
var Menu = React8.forwardRef(function Menu2(props, ref) {
|
|
1350
1386
|
const own = React8.useRef(null), merged = useMergedRef(ref, own);
|
|
1351
1387
|
const posState = React8.useState(null);
|
|
@@ -1355,21 +1391,30 @@ var Menu = React8.forwardRef(function Menu2(props, ref) {
|
|
|
1355
1391
|
const headerId = uid(), itemId = uid();
|
|
1356
1392
|
const hasHeader = props.header != null && props.header !== false && props.header !== "";
|
|
1357
1393
|
const Link = useLinkComponent(props.linkComponent);
|
|
1394
|
+
function place() {
|
|
1395
|
+
const a = props.anchor, m = own.current;
|
|
1396
|
+
if (!a || !m) return;
|
|
1397
|
+
const r = a.getBoundingClientRect(), mh = m.scrollHeight, mw = m.offsetWidth, below2 = window.innerHeight - r.bottom - 12, above = r.top - 12;
|
|
1398
|
+
let top = r.bottom + 4, maxHeight;
|
|
1399
|
+
if (mh > below2) {
|
|
1400
|
+
if (mh <= above) top = r.top - mh - 4;
|
|
1401
|
+
else if (above > below2) {
|
|
1402
|
+
maxHeight = above;
|
|
1403
|
+
top = r.top - above - 4;
|
|
1404
|
+
} else maxHeight = below2;
|
|
1405
|
+
}
|
|
1406
|
+
const left = Math.max(8, Math.min(r.right - mw, window.innerWidth - mw - 8));
|
|
1407
|
+
setPos(function(p) {
|
|
1408
|
+
return p && p.top === top && p.left === left && p.maxHeight === maxHeight ? p : { top, left, maxHeight };
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
1411
|
+
const placeRef = React8.useRef(place);
|
|
1412
|
+
placeRef.current = place;
|
|
1413
|
+
const live = React8.useRef({ anchor: props.anchor, onClose: props.onClose });
|
|
1414
|
+
live.current = { anchor: props.anchor, onClose: props.onClose };
|
|
1358
1415
|
useIsoLayoutEffect(
|
|
1359
1416
|
function() {
|
|
1360
|
-
|
|
1361
|
-
if (!a || !m) return;
|
|
1362
|
-
const r = a.getBoundingClientRect(), mh = m.scrollHeight, mw = m.offsetWidth, below2 = window.innerHeight - r.bottom - 12, above = r.top - 12;
|
|
1363
|
-
let top = r.bottom + 4, maxHeight;
|
|
1364
|
-
if (mh > below2) {
|
|
1365
|
-
if (mh <= above) top = r.top - mh - 4;
|
|
1366
|
-
else if (above > below2) {
|
|
1367
|
-
maxHeight = above;
|
|
1368
|
-
top = r.top - above - 4;
|
|
1369
|
-
} else maxHeight = below2;
|
|
1370
|
-
}
|
|
1371
|
-
const left = Math.max(8, Math.min(r.right - mw, window.innerWidth - mw - 8));
|
|
1372
|
-
setPos({ top, left, maxHeight });
|
|
1417
|
+
place();
|
|
1373
1418
|
},
|
|
1374
1419
|
[props.anchor, mounted, hasHeader]
|
|
1375
1420
|
);
|
|
@@ -1399,7 +1444,12 @@ var Menu = React8.forwardRef(function Menu2(props, ref) {
|
|
|
1399
1444
|
props.onClose(false);
|
|
1400
1445
|
}
|
|
1401
1446
|
function onScroll(e) {
|
|
1402
|
-
if (own.current &&
|
|
1447
|
+
if (own.current && e.target instanceof Node && own.current.contains(e.target)) return;
|
|
1448
|
+
const a = live.current.anchor;
|
|
1449
|
+
if (a && !inView(a)) {
|
|
1450
|
+
live.current.onClose(false);
|
|
1451
|
+
if (a instanceof HTMLElement && a.closest('[aria-modal="true"]')) a.focus({ preventScroll: true });
|
|
1452
|
+
} else placeRef.current();
|
|
1403
1453
|
}
|
|
1404
1454
|
document.addEventListener("pointerdown", outside, true);
|
|
1405
1455
|
window.addEventListener("scroll", onScroll, true);
|
|
@@ -1609,7 +1659,8 @@ var Checkbox = React10.forwardRef(function Checkbox2(props, ref) {
|
|
|
1609
1659
|
"className",
|
|
1610
1660
|
"tabIndex",
|
|
1611
1661
|
"disabled",
|
|
1612
|
-
"hitArea"
|
|
1662
|
+
"hitArea",
|
|
1663
|
+
"touchHeight"
|
|
1613
1664
|
]);
|
|
1614
1665
|
const text2 = props.children;
|
|
1615
1666
|
const labelled = text2 != null && text2 !== "";
|
|
@@ -1628,6 +1679,7 @@ var Checkbox = React10.forwardRef(function Checkbox2(props, ref) {
|
|
|
1628
1679
|
className: cx(
|
|
1629
1680
|
"aura-check",
|
|
1630
1681
|
labelled && "aura-check--labelled",
|
|
1682
|
+
labelled && touchClass(props.touchHeight),
|
|
1631
1683
|
hit && "has-hit",
|
|
1632
1684
|
props.disabled && "is-disabled",
|
|
1633
1685
|
props.className
|
|
@@ -1703,7 +1755,8 @@ var FIELD_KEYS = [
|
|
|
1703
1755
|
"id",
|
|
1704
1756
|
"suffix",
|
|
1705
1757
|
"options",
|
|
1706
|
-
"placeholder"
|
|
1758
|
+
"placeholder",
|
|
1759
|
+
"touchHeight"
|
|
1707
1760
|
];
|
|
1708
1761
|
|
|
1709
1762
|
// src/TextField.tsx
|
|
@@ -1721,7 +1774,7 @@ var TextField = React13.forwardRef(function TextField2(props, ref) {
|
|
|
1721
1774
|
required: props.required,
|
|
1722
1775
|
optional: props.optional,
|
|
1723
1776
|
disabled: props.disabled,
|
|
1724
|
-
className: props.className
|
|
1777
|
+
className: cx(touchClass(props.touchHeight), props.className)
|
|
1725
1778
|
},
|
|
1726
1779
|
/* @__PURE__ */ React13.createElement("div", { className: cx("aura-input", props.icon && "has-icon", props.suffix && "has-suffix") }, props.icon ? /* @__PURE__ */ React13.createElement(Icon, { name: props.icon, className: "aura-input__icon" }) : null, /* @__PURE__ */ React13.createElement(
|
|
1727
1780
|
"input",
|
|
@@ -1755,7 +1808,7 @@ var Textarea = React14.forwardRef(function Textarea2(props, ref) {
|
|
|
1755
1808
|
required: props.required,
|
|
1756
1809
|
optional: props.optional,
|
|
1757
1810
|
disabled: props.disabled,
|
|
1758
|
-
className: props.className
|
|
1811
|
+
className: cx(touchClass(props.touchHeight), props.className)
|
|
1759
1812
|
},
|
|
1760
1813
|
/* @__PURE__ */ React14.createElement(
|
|
1761
1814
|
"textarea",
|
|
@@ -2189,7 +2242,7 @@ var Select = React15.forwardRef(function Select2(props, ref) {
|
|
|
2189
2242
|
required: props.required,
|
|
2190
2243
|
optional: props.optional,
|
|
2191
2244
|
disabled: props.disabled,
|
|
2192
|
-
className: props.className
|
|
2245
|
+
className: cx(touchClass(props.touchHeight), props.className)
|
|
2193
2246
|
},
|
|
2194
2247
|
child
|
|
2195
2248
|
);
|
|
@@ -3421,7 +3474,12 @@ var RadioGroup = React19.forwardRef(function RadioGroup2(props, ref) {
|
|
|
3421
3474
|
"fieldset",
|
|
3422
3475
|
{
|
|
3423
3476
|
ref: setRef,
|
|
3424
|
-
className: cx(
|
|
3477
|
+
className: cx(
|
|
3478
|
+
"aura-field aura-radio-group",
|
|
3479
|
+
props.error && "is-invalid",
|
|
3480
|
+
touchClass(props.touchHeight),
|
|
3481
|
+
props.className
|
|
3482
|
+
),
|
|
3425
3483
|
"aria-describedby": describedBy(id, props),
|
|
3426
3484
|
"aria-invalid": props.error ? true : void 0,
|
|
3427
3485
|
disabled: props.disabled
|
|
@@ -4589,7 +4647,7 @@ var Tag = React27.forwardRef(function Tag2(props, ref) {
|
|
|
4589
4647
|
"aria-label": props.removeLabel || t.remove(name),
|
|
4590
4648
|
onClick: props.onRemove
|
|
4591
4649
|
},
|
|
4592
|
-
/* @__PURE__ */ React27.createElement(Icon, { name: /* @__PURE__ */ React27.createElement(IconX, null), size:
|
|
4650
|
+
/* @__PURE__ */ React27.createElement(Icon, { name: /* @__PURE__ */ React27.createElement(IconX, null), size: 14 })
|
|
4593
4651
|
);
|
|
4594
4652
|
return /* @__PURE__ */ React27.createElement(Tooltip, { content: fullText, open: fullText ? void 0 : false }, btn);
|
|
4595
4653
|
}() : null);
|
|
@@ -5390,6 +5448,28 @@ var DataTableImpl = React32.forwardRef(function DataTable(props, ref) {
|
|
|
5390
5448
|
return px != null && below(boxWidth[0], px);
|
|
5391
5449
|
}
|
|
5392
5450
|
const scrollRef = React32.useRef(null);
|
|
5451
|
+
const edgeState = React32.useState("");
|
|
5452
|
+
const checkMoreX = function() {
|
|
5453
|
+
const el = scrollRef.current;
|
|
5454
|
+
if (!el) return;
|
|
5455
|
+
const more = Math.abs(el.scrollLeft) + el.clientWidth < el.scrollWidth - 1;
|
|
5456
|
+
const next = more ? [el.offsetTop, el.clientHeight, el.offsetWidth - el.clientWidth].join(" ") : "";
|
|
5457
|
+
if (next !== edgeState[0]) edgeState[1](next);
|
|
5458
|
+
};
|
|
5459
|
+
const checkRef = React32.useRef(checkMoreX);
|
|
5460
|
+
checkRef.current = checkMoreX;
|
|
5461
|
+
React32.useEffect(function() {
|
|
5462
|
+
const el = scrollRef.current;
|
|
5463
|
+
if (!el || typeof ResizeObserver === "undefined") return;
|
|
5464
|
+
const ro = new ResizeObserver(function() {
|
|
5465
|
+
checkRef.current();
|
|
5466
|
+
});
|
|
5467
|
+
ro.observe(el);
|
|
5468
|
+
if (el.firstElementChild) ro.observe(el.firstElementChild);
|
|
5469
|
+
return function() {
|
|
5470
|
+
ro.disconnect();
|
|
5471
|
+
};
|
|
5472
|
+
}, []);
|
|
5393
5473
|
const tipState = React32.useState(null), tip = tipState[0], setTip = tipState[1];
|
|
5394
5474
|
function showFull(e) {
|
|
5395
5475
|
const el = e.target.closest ? e.target.closest(".aura-table__td") : null;
|
|
@@ -6553,12 +6633,25 @@ var DataTableImpl = React32.forwardRef(function DataTable(props, ref) {
|
|
|
6553
6633
|
stacked && "aura-table--stacked",
|
|
6554
6634
|
noCardSel && "aura-table--cards-nosel",
|
|
6555
6635
|
scrolledX[0] && "is-scrolled-x",
|
|
6636
|
+
edgeState[0] && !stacked && "has-more-x",
|
|
6556
6637
|
refreshing && "is-refreshing",
|
|
6557
6638
|
!levels.length && props.className
|
|
6558
6639
|
),
|
|
6559
6640
|
style: levels.length ? { ["--aura-q-back"]: String(levels[levels.length - 1].px / Q) } : void 0
|
|
6560
6641
|
},
|
|
6561
6642
|
refreshing ? /* @__PURE__ */ React32.createElement("span", { className: "aura-table__busy-bar", "aria-hidden": true }) : null,
|
|
6643
|
+
edgeState[0] && !stacked ? /* @__PURE__ */ React32.createElement(
|
|
6644
|
+
"span",
|
|
6645
|
+
{
|
|
6646
|
+
className: "aura-table__edge",
|
|
6647
|
+
"aria-hidden": true,
|
|
6648
|
+
style: {
|
|
6649
|
+
"--aura-edge-top": edgeState[0].split(" ")[0] + "px",
|
|
6650
|
+
"--aura-edge-h": edgeState[0].split(" ")[1] + "px",
|
|
6651
|
+
"--aura-edge-sb": edgeState[0].split(" ")[2] + "px"
|
|
6652
|
+
}
|
|
6653
|
+
}
|
|
6654
|
+
) : null,
|
|
6562
6655
|
/* @__PURE__ */ React32.createElement(
|
|
6563
6656
|
"div",
|
|
6564
6657
|
{
|
|
@@ -6594,6 +6687,7 @@ var DataTableImpl = React32.forwardRef(function DataTable(props, ref) {
|
|
|
6594
6687
|
setScrollTop(t2.scrollTop);
|
|
6595
6688
|
const sx = t2.scrollLeft > 0;
|
|
6596
6689
|
if (sx !== scrolledX[0]) scrolledX[1](sx);
|
|
6690
|
+
checkMoreX();
|
|
6597
6691
|
}
|
|
6598
6692
|
},
|
|
6599
6693
|
/* @__PURE__ */ React32.createElement(
|
package/dist/esm/Checkbox.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import { cx, devWarnOnce, omit, uid, useMergedRef, useMaybeControlled } from "./internal.js";
|
|
3
|
+
import { cx, devWarnOnce, omit, touchClass, uid, useMergedRef, useMaybeControlled } from "./internal.js";
|
|
4
4
|
import { Icon } from "./Icon.js";
|
|
5
5
|
import { IconCheck, IconMinus } from "./icons.js";
|
|
6
6
|
const Checkbox = React.forwardRef(function Checkbox2(props, ref) {
|
|
@@ -23,7 +23,8 @@ const Checkbox = React.forwardRef(function Checkbox2(props, ref) {
|
|
|
23
23
|
"className",
|
|
24
24
|
"tabIndex",
|
|
25
25
|
"disabled",
|
|
26
|
-
"hitArea"
|
|
26
|
+
"hitArea",
|
|
27
|
+
"touchHeight"
|
|
27
28
|
]);
|
|
28
29
|
const text = props.children;
|
|
29
30
|
const labelled = text != null && text !== "";
|
|
@@ -42,6 +43,7 @@ const Checkbox = React.forwardRef(function Checkbox2(props, ref) {
|
|
|
42
43
|
className: cx(
|
|
43
44
|
"aura-check",
|
|
44
45
|
labelled && "aura-check--labelled",
|
|
46
|
+
labelled && touchClass(props.touchHeight),
|
|
45
47
|
hit && "has-hit",
|
|
46
48
|
props.disabled && "is-disabled",
|
|
47
49
|
props.className
|
package/dist/esm/DataTable.js
CHANGED
|
@@ -194,6 +194,28 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
|
|
|
194
194
|
return px != null && below(boxWidth[0], px);
|
|
195
195
|
}
|
|
196
196
|
const scrollRef = React.useRef(null);
|
|
197
|
+
const edgeState = React.useState("");
|
|
198
|
+
const checkMoreX = function() {
|
|
199
|
+
const el = scrollRef.current;
|
|
200
|
+
if (!el) return;
|
|
201
|
+
const more = Math.abs(el.scrollLeft) + el.clientWidth < el.scrollWidth - 1;
|
|
202
|
+
const next = more ? [el.offsetTop, el.clientHeight, el.offsetWidth - el.clientWidth].join(" ") : "";
|
|
203
|
+
if (next !== edgeState[0]) edgeState[1](next);
|
|
204
|
+
};
|
|
205
|
+
const checkRef = React.useRef(checkMoreX);
|
|
206
|
+
checkRef.current = checkMoreX;
|
|
207
|
+
React.useEffect(function() {
|
|
208
|
+
const el = scrollRef.current;
|
|
209
|
+
if (!el || typeof ResizeObserver === "undefined") return;
|
|
210
|
+
const ro = new ResizeObserver(function() {
|
|
211
|
+
checkRef.current();
|
|
212
|
+
});
|
|
213
|
+
ro.observe(el);
|
|
214
|
+
if (el.firstElementChild) ro.observe(el.firstElementChild);
|
|
215
|
+
return function() {
|
|
216
|
+
ro.disconnect();
|
|
217
|
+
};
|
|
218
|
+
}, []);
|
|
197
219
|
const tipState = React.useState(null), tip = tipState[0], setTip = tipState[1];
|
|
198
220
|
function showFull(e) {
|
|
199
221
|
const el = e.target.closest ? e.target.closest(".aura-table__td") : null;
|
|
@@ -1357,12 +1379,25 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
|
|
|
1357
1379
|
stacked && "aura-table--stacked",
|
|
1358
1380
|
noCardSel && "aura-table--cards-nosel",
|
|
1359
1381
|
scrolledX[0] && "is-scrolled-x",
|
|
1382
|
+
edgeState[0] && !stacked && "has-more-x",
|
|
1360
1383
|
refreshing && "is-refreshing",
|
|
1361
1384
|
!levels.length && props.className
|
|
1362
1385
|
),
|
|
1363
1386
|
style: levels.length ? { ["--aura-q-back"]: String(levels[levels.length - 1].px / Q) } : void 0
|
|
1364
1387
|
},
|
|
1365
1388
|
refreshing ? /* @__PURE__ */ React.createElement("span", { className: "aura-table__busy-bar", "aria-hidden": true }) : null,
|
|
1389
|
+
edgeState[0] && !stacked ? /* @__PURE__ */ React.createElement(
|
|
1390
|
+
"span",
|
|
1391
|
+
{
|
|
1392
|
+
className: "aura-table__edge",
|
|
1393
|
+
"aria-hidden": true,
|
|
1394
|
+
style: {
|
|
1395
|
+
"--aura-edge-top": edgeState[0].split(" ")[0] + "px",
|
|
1396
|
+
"--aura-edge-h": edgeState[0].split(" ")[1] + "px",
|
|
1397
|
+
"--aura-edge-sb": edgeState[0].split(" ")[2] + "px"
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
) : null,
|
|
1366
1401
|
/* @__PURE__ */ React.createElement(
|
|
1367
1402
|
"div",
|
|
1368
1403
|
{
|
|
@@ -1398,6 +1433,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
|
|
|
1398
1433
|
setScrollTop(t2.scrollTop);
|
|
1399
1434
|
const sx = t2.scrollLeft > 0;
|
|
1400
1435
|
if (sx !== scrolledX[0]) scrolledX[1](sx);
|
|
1436
|
+
checkMoreX();
|
|
1401
1437
|
}
|
|
1402
1438
|
},
|
|
1403
1439
|
/* @__PURE__ */ React.createElement(
|