@jirawatpyk/aura-react 5.29.0 → 5.31.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.
@@ -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
- const a = props.anchor, m = own.current;
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 && !own.current.contains(e.target)) props.onClose(false);
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
@@ -1685,6 +1737,7 @@ var Field = React12.forwardRef(function Field2(props, ref) {
1685
1737
  props.required ? /* @__PURE__ */ React12.createElement("span", { className: "aura-field__req", "aria-hidden": true }, " *") : null,
1686
1738
  props.optional ? /* @__PURE__ */ React12.createElement("span", { className: "aura-field__opt" }, " (" + t.optional + ")") : null
1687
1739
  ) : null,
1740
+ hasAddon(props.labelAddon) ? /* @__PURE__ */ React12.createElement("div", { className: "aura-field__addon", id: props.id + "-addon" }, props.labelAddon) : null,
1688
1741
  props.children,
1689
1742
  props.error ? /* @__PURE__ */ React12.createElement("p", { className: "aura-field__error", id: props.id + "-error" }, /* @__PURE__ */ React12.createElement(Icon, { name: /* @__PURE__ */ React12.createElement(IconCircleAlert, null), size: 14 }), props.error) : props.hint ? /* @__PURE__ */ React12.createElement("p", { className: "aura-field__hint", id: props.id + "-hint" }, props.hint) : null
1690
1743
  );
@@ -1692,6 +1745,20 @@ var Field = React12.forwardRef(function Field2(props, ref) {
1692
1745
  function describedBy(id, p) {
1693
1746
  return p.error ? id + "-error" : p.hint ? id + "-hint" : void 0;
1694
1747
  }
1748
+ function hasAddon(n3) {
1749
+ return n3 != null && typeof n3 !== "boolean" && n3 !== "";
1750
+ }
1751
+ function joinDescribedBy(id, p, own) {
1752
+ const ids = [
1753
+ hasAddon(p.labelAddon) && p.labelAddonDescribes !== false ? id + "-addon" : "",
1754
+ describedBy(id, p) || ""
1755
+ ].concat(typeof own === "string" ? own.split(/\s+/) : []);
1756
+ const out = [];
1757
+ ids.forEach(function(x) {
1758
+ if (x && out.indexOf(x) < 0) out.push(x);
1759
+ });
1760
+ return out.join(" ") || void 0;
1761
+ }
1695
1762
  var FIELD_KEYS = [
1696
1763
  "label",
1697
1764
  "hint",
@@ -1703,7 +1770,10 @@ var FIELD_KEYS = [
1703
1770
  "id",
1704
1771
  "suffix",
1705
1772
  "options",
1706
- "placeholder"
1773
+ "placeholder",
1774
+ "touchHeight",
1775
+ "labelAddon",
1776
+ "labelAddonDescribes"
1707
1777
  ];
1708
1778
 
1709
1779
  // src/TextField.tsx
@@ -1720,8 +1790,9 @@ var TextField = React13.forwardRef(function TextField2(props, ref) {
1720
1790
  error: props.error,
1721
1791
  required: props.required,
1722
1792
  optional: props.optional,
1793
+ labelAddon: props.labelAddon,
1723
1794
  disabled: props.disabled,
1724
- className: props.className
1795
+ className: cx(touchClass(props.touchHeight), props.className)
1725
1796
  },
1726
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(
1727
1798
  "input",
@@ -1734,7 +1805,7 @@ var TextField = React13.forwardRef(function TextField2(props, ref) {
1734
1805
  placeholder: props.placeholder,
1735
1806
  required: props.required,
1736
1807
  "aria-invalid": props.error ? true : rest["aria-invalid"],
1737
- "aria-describedby": [describedBy(id, props), rest["aria-describedby"]].filter(Boolean).join(" ") || void 0
1808
+ "aria-describedby": joinDescribedBy(id, props, rest["aria-describedby"])
1738
1809
  }
1739
1810
  ), props.suffix ? /* @__PURE__ */ React13.createElement("span", { className: "aura-input__suffix" }, props.suffix) : null)
1740
1811
  );
@@ -1754,8 +1825,9 @@ var Textarea = React14.forwardRef(function Textarea2(props, ref) {
1754
1825
  error: props.error,
1755
1826
  required: props.required,
1756
1827
  optional: props.optional,
1828
+ labelAddon: props.labelAddon,
1757
1829
  disabled: props.disabled,
1758
- className: props.className
1830
+ className: cx(touchClass(props.touchHeight), props.className)
1759
1831
  },
1760
1832
  /* @__PURE__ */ React14.createElement(
1761
1833
  "textarea",
@@ -1768,7 +1840,7 @@ var Textarea = React14.forwardRef(function Textarea2(props, ref) {
1768
1840
  placeholder: props.placeholder,
1769
1841
  required: props.required,
1770
1842
  "aria-invalid": props.error ? true : rest["aria-invalid"],
1771
- "aria-describedby": [describedBy(id, props), rest["aria-describedby"]].filter(Boolean).join(" ") || void 0
1843
+ "aria-describedby": joinDescribedBy(id, props, rest["aria-describedby"])
1772
1844
  }
1773
1845
  )
1774
1846
  );
@@ -2189,7 +2261,7 @@ var Select = React15.forwardRef(function Select2(props, ref) {
2189
2261
  required: props.required,
2190
2262
  optional: props.optional,
2191
2263
  disabled: props.disabled,
2192
- className: props.className
2264
+ className: cx(touchClass(props.touchHeight), props.className)
2193
2265
  },
2194
2266
  child
2195
2267
  );
@@ -3421,7 +3493,12 @@ var RadioGroup = React19.forwardRef(function RadioGroup2(props, ref) {
3421
3493
  "fieldset",
3422
3494
  {
3423
3495
  ref: setRef,
3424
- className: cx("aura-field aura-radio-group", props.error && "is-invalid", props.className),
3496
+ className: cx(
3497
+ "aura-field aura-radio-group",
3498
+ props.error && "is-invalid",
3499
+ touchClass(props.touchHeight),
3500
+ props.className
3501
+ ),
3425
3502
  "aria-describedby": describedBy(id, props),
3426
3503
  "aria-invalid": props.error ? true : void 0,
3427
3504
  disabled: props.disabled
@@ -4589,7 +4666,7 @@ var Tag = React27.forwardRef(function Tag2(props, ref) {
4589
4666
  "aria-label": props.removeLabel || t.remove(name),
4590
4667
  onClick: props.onRemove
4591
4668
  },
4592
- /* @__PURE__ */ React27.createElement(Icon, { name: /* @__PURE__ */ React27.createElement(IconX, null), size: 12 })
4669
+ /* @__PURE__ */ React27.createElement(Icon, { name: /* @__PURE__ */ React27.createElement(IconX, null), size: 14 })
4593
4670
  );
4594
4671
  return /* @__PURE__ */ React27.createElement(Tooltip, { content: fullText, open: fullText ? void 0 : false }, btn);
4595
4672
  }() : null);
@@ -5390,6 +5467,28 @@ var DataTableImpl = React32.forwardRef(function DataTable(props, ref) {
5390
5467
  return px != null && below(boxWidth[0], px);
5391
5468
  }
5392
5469
  const scrollRef = React32.useRef(null);
5470
+ const edgeState = React32.useState("");
5471
+ const checkMoreX = function() {
5472
+ const el = scrollRef.current;
5473
+ if (!el) return;
5474
+ const more = Math.abs(el.scrollLeft) + el.clientWidth < el.scrollWidth - 1;
5475
+ const next = more ? [el.offsetTop, el.clientHeight, el.offsetWidth - el.clientWidth].join(" ") : "";
5476
+ if (next !== edgeState[0]) edgeState[1](next);
5477
+ };
5478
+ const checkRef = React32.useRef(checkMoreX);
5479
+ checkRef.current = checkMoreX;
5480
+ React32.useEffect(function() {
5481
+ const el = scrollRef.current;
5482
+ if (!el || typeof ResizeObserver === "undefined") return;
5483
+ const ro = new ResizeObserver(function() {
5484
+ checkRef.current();
5485
+ });
5486
+ ro.observe(el);
5487
+ if (el.firstElementChild) ro.observe(el.firstElementChild);
5488
+ return function() {
5489
+ ro.disconnect();
5490
+ };
5491
+ }, []);
5393
5492
  const tipState = React32.useState(null), tip = tipState[0], setTip = tipState[1];
5394
5493
  function showFull(e) {
5395
5494
  const el = e.target.closest ? e.target.closest(".aura-table__td") : null;
@@ -6553,12 +6652,25 @@ var DataTableImpl = React32.forwardRef(function DataTable(props, ref) {
6553
6652
  stacked && "aura-table--stacked",
6554
6653
  noCardSel && "aura-table--cards-nosel",
6555
6654
  scrolledX[0] && "is-scrolled-x",
6655
+ edgeState[0] && !stacked && "has-more-x",
6556
6656
  refreshing && "is-refreshing",
6557
6657
  !levels.length && props.className
6558
6658
  ),
6559
6659
  style: levels.length ? { ["--aura-q-back"]: String(levels[levels.length - 1].px / Q) } : void 0
6560
6660
  },
6561
6661
  refreshing ? /* @__PURE__ */ React32.createElement("span", { className: "aura-table__busy-bar", "aria-hidden": true }) : null,
6662
+ edgeState[0] && !stacked ? /* @__PURE__ */ React32.createElement(
6663
+ "span",
6664
+ {
6665
+ className: "aura-table__edge",
6666
+ "aria-hidden": true,
6667
+ style: {
6668
+ "--aura-edge-top": edgeState[0].split(" ")[0] + "px",
6669
+ "--aura-edge-h": edgeState[0].split(" ")[1] + "px",
6670
+ "--aura-edge-sb": edgeState[0].split(" ")[2] + "px"
6671
+ }
6672
+ }
6673
+ ) : null,
6562
6674
  /* @__PURE__ */ React32.createElement(
6563
6675
  "div",
6564
6676
  {
@@ -6594,6 +6706,7 @@ var DataTableImpl = React32.forwardRef(function DataTable(props, ref) {
6594
6706
  setScrollTop(t2.scrollTop);
6595
6707
  const sx = t2.scrollLeft > 0;
6596
6708
  if (sx !== scrolledX[0]) scrolledX[1](sx);
6709
+ checkMoreX();
6597
6710
  }
6598
6711
  },
6599
6712
  /* @__PURE__ */ React32.createElement(
@@ -8470,6 +8583,13 @@ function createTheme(opts) {
8470
8583
  D["accent-lime"] = s[200];
8471
8584
  D["mesh-to"] = s[200];
8472
8585
  }
8586
+ function onFill(bg) {
8587
+ return contrast(ZINC[0], bg) >= contrast(INK, bg) ? ZINC[0] : INK;
8588
+ }
8589
+ L["control-checked-bg"] = L["accent-violet"];
8590
+ L["control-checked-fg"] = onFill(L["control-checked-bg"]);
8591
+ D["control-checked-bg"] = fit(b[300], darkGrounds, 3, 1);
8592
+ D["control-checked-fg"] = onFill(D["control-checked-bg"]);
8473
8593
  const shadowLight = INK, shadowDark = D["accent-violet"];
8474
8594
  if (o.primary === "brand") {
8475
8595
  L["button-primary-bg"] = fit(b[600], [ZINC[0]], 4.5, -1);
@@ -8552,6 +8672,30 @@ function createTheme(opts) {
8552
8672
  );
8553
8673
  }
8554
8674
  if (s) check("light", "ink", "accent-lime (signal)", 4.5, INK, s[200]);
8675
+ [
8676
+ [
8677
+ "light",
8678
+ L,
8679
+ [
8680
+ ["bg-surface", ZINC[0]],
8681
+ ["bg-canvas", ZINC[50]]
8682
+ ]
8683
+ ],
8684
+ [
8685
+ "dark",
8686
+ D,
8687
+ [
8688
+ ["bg-surface", ZINC[900]],
8689
+ ["bg-canvas", ZINC[950]]
8690
+ ]
8691
+ ]
8692
+ ].forEach(function(g) {
8693
+ const t = g[0], m = g[1];
8694
+ g[2].forEach(function(gr) {
8695
+ check(t, "control-checked-bg", gr[0], 3, m["control-checked-bg"], gr[1]);
8696
+ });
8697
+ check(t, "control-checked-fg", "control-checked-bg", 4.5, m["control-checked-fg"], m["control-checked-bg"]);
8698
+ });
8555
8699
  function css(selector) {
8556
8700
  if (selector !== void 0 && /[<{};@\r\n]|\/\*|\*\//.test(selector))
8557
8701
  throw new Error('createTheme: "' + selector + '" is not a plain CSS selector');
@@ -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
@@ -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(
package/dist/esm/Field.js CHANGED
@@ -20,6 +20,7 @@ const Field = React.forwardRef(function Field2(props, ref) {
20
20
  props.required ? /* @__PURE__ */ React.createElement("span", { className: "aura-field__req", "aria-hidden": true }, " *") : null,
21
21
  props.optional ? /* @__PURE__ */ React.createElement("span", { className: "aura-field__opt" }, " (" + t.optional + ")") : null
22
22
  ) : null,
23
+ hasAddon(props.labelAddon) ? /* @__PURE__ */ React.createElement("div", { className: "aura-field__addon", id: props.id + "-addon" }, props.labelAddon) : null,
23
24
  props.children,
24
25
  props.error ? /* @__PURE__ */ React.createElement("p", { className: "aura-field__error", id: props.id + "-error" }, /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconCircleAlert, null), size: 14 }), props.error) : props.hint ? /* @__PURE__ */ React.createElement("p", { className: "aura-field__hint", id: props.id + "-hint" }, props.hint) : null
25
26
  );
@@ -27,6 +28,20 @@ const Field = React.forwardRef(function Field2(props, ref) {
27
28
  function describedBy(id, p) {
28
29
  return p.error ? id + "-error" : p.hint ? id + "-hint" : void 0;
29
30
  }
31
+ function hasAddon(n) {
32
+ return n != null && typeof n !== "boolean" && n !== "";
33
+ }
34
+ function joinDescribedBy(id, p, own) {
35
+ const ids = [
36
+ hasAddon(p.labelAddon) && p.labelAddonDescribes !== false ? id + "-addon" : "",
37
+ describedBy(id, p) || ""
38
+ ].concat(typeof own === "string" ? own.split(/\s+/) : []);
39
+ const out = [];
40
+ ids.forEach(function(x) {
41
+ if (x && out.indexOf(x) < 0) out.push(x);
42
+ });
43
+ return out.join(" ") || void 0;
44
+ }
30
45
  const FIELD_KEYS = [
31
46
  "label",
32
47
  "hint",
@@ -38,10 +53,15 @@ const FIELD_KEYS = [
38
53
  "id",
39
54
  "suffix",
40
55
  "options",
41
- "placeholder"
56
+ "placeholder",
57
+ "touchHeight",
58
+ "labelAddon",
59
+ "labelAddonDescribes"
42
60
  ];
43
61
  export {
44
62
  FIELD_KEYS,
45
63
  Field,
46
- describedBy
64
+ describedBy,
65
+ hasAddon,
66
+ joinDescribedBy
47
67
  };
package/dist/esm/Menu.js CHANGED
@@ -6,6 +6,39 @@ import { Icon } from "./Icon.js";
6
6
  import { useLinkComponent } from "./locale.js";
7
7
  import { IconCheck } from "./icons.js";
8
8
  const ITEMS = '[role^="menuitem"]';
9
+ function makesBlock(s) {
10
+ 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);
11
+ }
12
+ function inView(el) {
13
+ if (!el.isConnected) return false;
14
+ const r = el.getBoundingClientRect();
15
+ if (r.width === 0 && r.height === 0) return false;
16
+ let top = r.top, bottom = r.bottom, left = r.left, right = r.right;
17
+ let pos = getComputedStyle(el).position;
18
+ for (let p = el.parentElement; p && p !== document.body && p !== document.documentElement; p = p.parentElement) {
19
+ const s = getComputedStyle(p);
20
+ const block = makesBlock(s);
21
+ if (pos === "fixed" && !block) continue;
22
+ if (pos === "absolute" && s.position === "static" && !block) continue;
23
+ if (s.display !== "contents") {
24
+ const b = p.getBoundingClientRect();
25
+ if (s.overflowX !== "visible") {
26
+ left = Math.max(left, b.left);
27
+ right = Math.min(right, b.right);
28
+ }
29
+ if (s.overflowY !== "visible") {
30
+ top = Math.max(top, b.top);
31
+ bottom = Math.min(bottom, b.bottom);
32
+ }
33
+ }
34
+ pos = s.position === "fixed" || s.position === "absolute" ? s.position : "static";
35
+ }
36
+ top = Math.max(top, 0);
37
+ left = Math.max(left, 0);
38
+ bottom = Math.min(bottom, window.innerHeight);
39
+ right = Math.min(right, window.innerWidth);
40
+ return bottom > top && right > left;
41
+ }
9
42
  const Menu = React.forwardRef(function Menu2(props, ref) {
10
43
  const own = React.useRef(null), merged = useMergedRef(ref, own);
11
44
  const posState = React.useState(null);
@@ -15,21 +48,30 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
15
48
  const headerId = uid(), itemId = uid();
16
49
  const hasHeader = props.header != null && props.header !== false && props.header !== "";
17
50
  const Link = useLinkComponent(props.linkComponent);
51
+ function place() {
52
+ const a = props.anchor, m = own.current;
53
+ if (!a || !m) return;
54
+ const r = a.getBoundingClientRect(), mh = m.scrollHeight, mw = m.offsetWidth, below = window.innerHeight - r.bottom - 12, above = r.top - 12;
55
+ let top = r.bottom + 4, maxHeight;
56
+ if (mh > below) {
57
+ if (mh <= above) top = r.top - mh - 4;
58
+ else if (above > below) {
59
+ maxHeight = above;
60
+ top = r.top - above - 4;
61
+ } else maxHeight = below;
62
+ }
63
+ const left = Math.max(8, Math.min(r.right - mw, window.innerWidth - mw - 8));
64
+ setPos(function(p) {
65
+ return p && p.top === top && p.left === left && p.maxHeight === maxHeight ? p : { top, left, maxHeight };
66
+ });
67
+ }
68
+ const placeRef = React.useRef(place);
69
+ placeRef.current = place;
70
+ const live = React.useRef({ anchor: props.anchor, onClose: props.onClose });
71
+ live.current = { anchor: props.anchor, onClose: props.onClose };
18
72
  useIsoLayoutEffect(
19
73
  function() {
20
- const a = props.anchor, m = own.current;
21
- if (!a || !m) return;
22
- const r = a.getBoundingClientRect(), mh = m.scrollHeight, mw = m.offsetWidth, below = window.innerHeight - r.bottom - 12, above = r.top - 12;
23
- let top = r.bottom + 4, maxHeight;
24
- if (mh > below) {
25
- if (mh <= above) top = r.top - mh - 4;
26
- else if (above > below) {
27
- maxHeight = above;
28
- top = r.top - above - 4;
29
- } else maxHeight = below;
30
- }
31
- const left = Math.max(8, Math.min(r.right - mw, window.innerWidth - mw - 8));
32
- setPos({ top, left, maxHeight });
74
+ place();
33
75
  },
34
76
  [props.anchor, mounted, hasHeader]
35
77
  );
@@ -59,7 +101,12 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
59
101
  props.onClose(false);
60
102
  }
61
103
  function onScroll(e) {
62
- if (own.current && !own.current.contains(e.target)) props.onClose(false);
104
+ if (own.current && e.target instanceof Node && own.current.contains(e.target)) return;
105
+ const a = live.current.anchor;
106
+ if (a && !inView(a)) {
107
+ live.current.onClose(false);
108
+ if (a instanceof HTMLElement && a.closest('[aria-modal="true"]')) a.focus({ preventScroll: true });
109
+ } else placeRef.current();
63
110
  }
64
111
  document.addEventListener("pointerdown", outside, true);
65
112
  window.addEventListener("scroll", onScroll, true);
@@ -2,7 +2,7 @@
2
2
  import * as React from "react";
3
3
  import { describedBy } from "./Field.js";
4
4
  import { Icon } from "./Icon.js";
5
- import { cx, uid, useMaybeControlled } from "./internal.js";
5
+ import { cx, touchClass, uid, useMaybeControlled } from "./internal.js";
6
6
  import { IconCircleAlert } from "./icons.js";
7
7
  const RadioGroup = React.forwardRef(function RadioGroup2(props, ref) {
8
8
  const auto = uid(), id = props.id || auto;
@@ -28,7 +28,12 @@ const RadioGroup = React.forwardRef(function RadioGroup2(props, ref) {
28
28
  "fieldset",
29
29
  {
30
30
  ref: setRef,
31
- className: cx("aura-field aura-radio-group", props.error && "is-invalid", props.className),
31
+ className: cx(
32
+ "aura-field aura-radio-group",
33
+ props.error && "is-invalid",
34
+ touchClass(props.touchHeight),
35
+ props.className
36
+ ),
32
37
  "aria-describedby": describedBy(id, props),
33
38
  "aria-invalid": props.error ? true : void 0,
34
39
  disabled: props.disabled
@@ -4,7 +4,7 @@ import { createPortal } from "react-dom";
4
4
  import { FIELD_KEYS, Field, describedBy } from "./Field.js";
5
5
  import { Icon } from "./Icon.js";
6
6
  import { useDensity } from "./locale.js";
7
- import { cx, devWarnOnce, omit, uid, useIsoLayoutEffect, useMergedRef, useMounted } from "./internal.js";
7
+ import { cx, devWarnOnce, omit, touchClass, uid, useIsoLayoutEffect, useMergedRef, useMounted } from "./internal.js";
8
8
  import { IconCheck, IconChevronDown } from "./icons.js";
9
9
  const h = React.createElement;
10
10
  const FILTER_KEY = "__auraFilter";
@@ -418,7 +418,7 @@ const Select = React.forwardRef(function Select2(props, ref) {
418
418
  required: props.required,
419
419
  optional: props.optional,
420
420
  disabled: props.disabled,
421
- className: props.className
421
+ className: cx(touchClass(props.touchHeight), props.className)
422
422
  },
423
423
  child
424
424
  );
package/dist/esm/Tag.js CHANGED
@@ -90,7 +90,7 @@ const Tag = React.forwardRef(function Tag2(props, ref) {
90
90
  "aria-label": props.removeLabel || t.remove(name),
91
91
  onClick: props.onRemove
92
92
  },
93
- /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconX, null), size: 12 })
93
+ /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconX, null), size: 14 })
94
94
  );
95
95
  return /* @__PURE__ */ React.createElement(Tooltip, { content: fullText, open: fullText ? void 0 : false }, btn);
96
96
  }() : null);
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import * as React from "react";
3
- import { FIELD_KEYS, Field, describedBy } from "./Field.js";
3
+ import { FIELD_KEYS, Field, joinDescribedBy } from "./Field.js";
4
4
  import { Icon } from "./Icon.js";
5
- import { cx, omit, uid } from "./internal.js";
5
+ import { cx, omit, touchClass, uid } from "./internal.js";
6
6
  const TextField = React.forwardRef(function TextField2(props, ref) {
7
7
  const auto = uid(), id = props.id || auto;
8
8
  const rest = omit(props, FIELD_KEYS);
@@ -15,8 +15,9 @@ const TextField = React.forwardRef(function TextField2(props, ref) {
15
15
  error: props.error,
16
16
  required: props.required,
17
17
  optional: props.optional,
18
+ labelAddon: props.labelAddon,
18
19
  disabled: props.disabled,
19
- className: props.className
20
+ className: cx(touchClass(props.touchHeight), props.className)
20
21
  },
21
22
  /* @__PURE__ */ React.createElement("div", { className: cx("aura-input", props.icon && "has-icon", props.suffix && "has-suffix") }, props.icon ? /* @__PURE__ */ React.createElement(Icon, { name: props.icon, className: "aura-input__icon" }) : null, /* @__PURE__ */ React.createElement(
22
23
  "input",
@@ -29,7 +30,7 @@ const TextField = React.forwardRef(function TextField2(props, ref) {
29
30
  placeholder: props.placeholder,
30
31
  required: props.required,
31
32
  "aria-invalid": props.error ? true : rest["aria-invalid"],
32
- "aria-describedby": [describedBy(id, props), rest["aria-describedby"]].filter(Boolean).join(" ") || void 0
33
+ "aria-describedby": joinDescribedBy(id, props, rest["aria-describedby"])
33
34
  }
34
35
  ), props.suffix ? /* @__PURE__ */ React.createElement("span", { className: "aura-input__suffix" }, props.suffix) : null)
35
36
  );