@jirawatpyk/aura-react 5.37.0 → 5.38.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 CHANGED
@@ -186,6 +186,12 @@ 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.38 — Chamber-OS addenda 43–45
190
+
191
+ - **FilterBar and FilterSelect `touchHeight`** (#140): `true` makes the search (and its clear button) and every field-height control in the bar (FilterSelect, Select, Combobox, DatePicker and TimePicker with their buttons, SegmentedControl's options) 44px below 640px or on a coarse pointer — the same rule as Button's and TextField's `touchHeight` — and `'always'` at every width; `touchHeight` on one FilterSelect does the same for it alone. Without it nothing changes: the density's input height with a mouse, 44px on a coarse pointer. Buttons in `actions` take their own `touchHeight`. A SegmentedControl's track is 50px there (44px options plus its edge and padding), as with its own `touchHeight`. Opt-in rather than a new default, like every other `touchHeight`, so a narrow desktop window doesn't change size unasked.
192
+ - **`touchHeight` on Combobox, DatePicker, DateRangePicker, TimePicker and NumberField** (#141): the same values and rule as TextField's. The box is 44px and the buttons inside it (clear, chevron, calendar, steppers) take their touch-screen size — 44px wide, side by side, 40px tall — so none is a 32px target in a 44px box. A multiple Combobox now reserves room for both 44px buttons on touch screens too (chips used to run up to 24px under the clear button).
193
+ - **DataTable `rowProps`** (#142): `rowProps={(row) => ({ 'data-user-id': row.id, id: 'user-' + row.id })}` sets `data-*` attributes and an `id` on each row's element, in the grid and as a stacked card — for end-to-end hooks. Anything else it returns is ignored (a development warning names it) — `aria-*`, `role`, `className`, handlers, and `data-rc` (the table's own cell address) — so a row keeps its role, name, classes, selection and keyboard behaviour.
194
+
189
195
  ## 5.37 — DxT Monitor requests 17–18
190
196
 
191
197
  - **PageHeader `actionsFullWidthBelow`** (request 17): `'sm'`, `'md'` or `'lg'` — below 640px, 768px or 1024px the actions take the whole row under the text, 12px apart, and the buttons share each line in equal widths (unless a label needs more), so they reach the page's edge: three buttons on a phone fill two rows (two halves, then one across) when their labels don't fit on one, and a single button spans the row. A button inside a DropdownMenu, Tooltip or Popover fills its share too; an IconButton (bare, or as a menu's trigger) keeps its square size — so a line with only IconButtons on it doesn't reach the edge (one that wraps alone sits at the start); put them on the first line. Labels don't wrap: a label wider than the row overflows, as before — keep phone labels short, or give that one Button `fullWidth`. For a fixed arrangement, pass your own grid as the one child — it spans the row too. Wider than the breakpoint, the actions hug their content at the end, 8px apart, as before. A class on the root, so it works from `/server` too. Apps that stretched the actions with their own selector (e.g. `max-md:[&>:last-child]:w-full`) can drop it.
@@ -2501,18 +2501,30 @@ window.Aura = (() => {
2501
2501
  const nameId = id + "-name";
2502
2502
  const face = filter ? /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("span", { id: nameId, className: "aura-filterselect__name", "aria-hidden": true }, filter.name), /* @__PURE__ */ React16.createElement("span", { className: "aura-filterselect__value", "aria-hidden": shown[0].label !== shown[0].full || void 0 }, shown[0].label || " "), shown[0].label !== shown[0].full ? /* @__PURE__ */ React16.createElement("span", { className: "aura-sr-only" }, shown[0].full) : null, /* @__PURE__ */ React16.createElement(Icon, { name: /* @__PURE__ */ React16.createElement(IconChevronDown, null), className: "aura-filterselect__chevron" })) : null;
2503
2503
  if (!live && filter)
2504
- return /* @__PURE__ */ React16.createElement("div", { className: cx("aura-filterselect", props.disabled && "is-disabled", props.className) }, /* @__PURE__ */ React16.createElement("span", { className: "aura-filterselect__face", "aria-hidden": true, style: props.style }, face), h4(
2505
- "select",
2506
- Object.assign(extra, omit(rest, ["style"]), {
2507
- ref: selMerged,
2508
- id,
2509
- className: "aura-filterselect__native",
2510
- "aria-label": rest["aria-label"] || (rest["aria-labelledby"] ? void 0 : filter.name),
2511
- "aria-describedby": described
2512
- }),
2513
- opts,
2514
- props.children
2515
- ));
2504
+ return /* @__PURE__ */ React16.createElement(
2505
+ "div",
2506
+ {
2507
+ className: cx(
2508
+ "aura-filterselect",
2509
+ props.disabled && "is-disabled",
2510
+ touchClass(props.touchHeight),
2511
+ props.className
2512
+ )
2513
+ },
2514
+ /* @__PURE__ */ React16.createElement("span", { className: "aura-filterselect__face", "aria-hidden": true, style: props.style }, face),
2515
+ h4(
2516
+ "select",
2517
+ Object.assign(extra, omit(rest, ["style"]), {
2518
+ ref: selMerged,
2519
+ id,
2520
+ className: "aura-filterselect__native",
2521
+ "aria-label": rest["aria-label"] || (rest["aria-labelledby"] ? void 0 : filter.name),
2522
+ "aria-describedby": described
2523
+ }),
2524
+ opts,
2525
+ props.children
2526
+ )
2527
+ );
2516
2528
  if (!live)
2517
2529
  return field(
2518
2530
  /* @__PURE__ */ React16.createElement("div", { className: cx("aura-input aura-select", props.icon && "has-icon", ro && "is-readonly") }, props.icon ? /* @__PURE__ */ React16.createElement(Icon, { name: props.icon, className: "aura-input__icon" }) : null, h4(
@@ -2625,6 +2637,7 @@ window.Aura = (() => {
2625
2637
  ro && "is-readonly",
2626
2638
  open && "is-open",
2627
2639
  filter && props.disabled && "is-disabled",
2640
+ filter && touchClass(props.touchHeight),
2628
2641
  filter && props.className
2629
2642
  ),
2630
2643
  "data-invalid": props.error ? "" : void 0
@@ -3393,7 +3406,7 @@ window.Aura = (() => {
3393
3406
  required: props.required,
3394
3407
  optional: props.optional,
3395
3408
  disabled: props.disabled,
3396
- className: props.className,
3409
+ className: cx(touchClass(props.touchHeight), props.className),
3397
3410
  name: props.name,
3398
3411
  boxRef,
3399
3412
  inputRef: inputMerged,
@@ -3527,7 +3540,7 @@ window.Aura = (() => {
3527
3540
  required: props.required,
3528
3541
  optional: props.optional,
3529
3542
  disabled: props.disabled,
3530
- className: props.className,
3543
+ className: cx(touchClass(props.touchHeight), props.className),
3531
3544
  name: props.name,
3532
3545
  boxRef,
3533
3546
  inputRef: inputMerged,
@@ -4117,7 +4130,7 @@ window.Aura = (() => {
4117
4130
  required: props.required,
4118
4131
  optional: props.optional,
4119
4132
  disabled: props.disabled,
4120
- className: props.className
4133
+ className: cx(touchClass(props.touchHeight), props.className)
4121
4134
  },
4122
4135
  /* @__PURE__ */ React22.createElement("div", { ref: boxRef, className: cx("aura-input aura-combo has-icon", open && "is-open", multi && "is-multi") }, /* @__PURE__ */ React22.createElement(Icon, { name: props.icon || /* @__PURE__ */ React22.createElement(IconSearch, null), className: "aura-input__icon" }), multi && picked.length ? /* @__PURE__ */ React22.createElement("span", { className: "aura-combo__chips" }, picked.map(function(o) {
4123
4136
  return /* @__PURE__ */ React22.createElement("span", { key: o.value, className: "aura-combo__chip" }, /* @__PURE__ */ React22.createElement("span", { className: "aura-combo__chip-label" }, o.label), props.disabled || props.readOnly ? null : /* @__PURE__ */ React22.createElement(
@@ -4962,6 +4975,7 @@ window.Aura = (() => {
4962
4975
  props.searchGrow && "aura-filterbar--grow",
4963
4976
  props.controlsLayout === "fill" && "aura-filterbar--fill",
4964
4977
  props.stackBelow === "lg" && "aura-filterbar--stack-lg",
4978
+ touchClass(props.touchHeight),
4965
4979
  props.className
4966
4980
  )
4967
4981
  },
@@ -5529,6 +5543,19 @@ window.Aura = (() => {
5529
5543
  // src/DataTable.tsx
5530
5544
  var React33 = __toESM(require_react(), 1);
5531
5545
  var import_react_dom10 = __toESM(require_react_dom(), 1);
5546
+ function ownRowAttrs(p) {
5547
+ if (!p) return null;
5548
+ const out = {};
5549
+ Object.keys(p).forEach(function(k) {
5550
+ if (k === "id" || /^data-/.test(k) && k !== "data-rc") out[k] = p[k];
5551
+ else
5552
+ devWarnOnce(
5553
+ "datatable-rowprops-" + k,
5554
+ 'DataTable rowProps: "' + k + '" is ignored; only data-* (not data-rc) and id are set on a row.'
5555
+ );
5556
+ });
5557
+ return out;
5558
+ }
5532
5559
  var BP = { sm: 640, md: 768, lg: 1024, xl: 1280 };
5533
5560
  var DEFAULT_COLUMNS = [
5534
5561
  { key: "id", label: "ID", width: 96, mono: true },
@@ -6740,6 +6767,7 @@ window.Aura = (() => {
6740
6767
  (props.onRowActivate || rowHref) && "is-actionable"
6741
6768
  ),
6742
6769
  style: rowStyle,
6770
+ ...ownRowAttrs(props.rowProps ? props.rowProps(r2) : null),
6743
6771
  onClick: function(e) {
6744
6772
  const el = e.target;
6745
6773
  if (el.closest && el.closest(".aura-check, button, a, input")) return;
@@ -8832,7 +8860,7 @@ window.Aura = (() => {
8832
8860
  required: props.required,
8833
8861
  optional: props.optional,
8834
8862
  disabled: props.disabled,
8835
- className: props.className
8863
+ className: cx(touchClass(props.touchHeight), props.className)
8836
8864
  },
8837
8865
  /* @__PURE__ */ React54.createElement("div", { ref: boxRef, className: cx("aura-input aura-combo aura-time has-icon", open && "is-open") }, /* @__PURE__ */ React54.createElement(Icon, { name: /* @__PURE__ */ React54.createElement(IconClock, null), className: "aura-input__icon" }), /* @__PURE__ */ React54.createElement(
8838
8866
  "input",
@@ -10034,7 +10062,7 @@ window.Aura = (() => {
10034
10062
  required: props.required,
10035
10063
  optional: props.optional,
10036
10064
  disabled: props.disabled,
10037
- className: props.className
10065
+ className: cx(touchClass(props.touchHeight), props.className)
10038
10066
  },
10039
10067
  /* @__PURE__ */ React65.createElement("div", { className: cx("aura-input aura-number", stepper && "has-stepper") }, props.prefix != null ? /* @__PURE__ */ React65.createElement("span", { className: "aura-number__affix", "aria-hidden": true }, props.prefix) : null, /* @__PURE__ */ React65.createElement(
10040
10068
  "input",
@@ -2483,18 +2483,30 @@ var Select = React16.forwardRef(function Select2(props, ref) {
2483
2483
  const nameId = id + "-name";
2484
2484
  const face = filter ? /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement("span", { id: nameId, className: "aura-filterselect__name", "aria-hidden": true }, filter.name), /* @__PURE__ */ React16.createElement("span", { className: "aura-filterselect__value", "aria-hidden": shown[0].label !== shown[0].full || void 0 }, shown[0].label || " "), shown[0].label !== shown[0].full ? /* @__PURE__ */ React16.createElement("span", { className: "aura-sr-only" }, shown[0].full) : null, /* @__PURE__ */ React16.createElement(Icon, { name: /* @__PURE__ */ React16.createElement(IconChevronDown, null), className: "aura-filterselect__chevron" })) : null;
2485
2485
  if (!live && filter)
2486
- return /* @__PURE__ */ React16.createElement("div", { className: cx("aura-filterselect", props.disabled && "is-disabled", props.className) }, /* @__PURE__ */ React16.createElement("span", { className: "aura-filterselect__face", "aria-hidden": true, style: props.style }, face), h4(
2487
- "select",
2488
- Object.assign(extra, omit(rest, ["style"]), {
2489
- ref: selMerged,
2490
- id,
2491
- className: "aura-filterselect__native",
2492
- "aria-label": rest["aria-label"] || (rest["aria-labelledby"] ? void 0 : filter.name),
2493
- "aria-describedby": described
2494
- }),
2495
- opts,
2496
- props.children
2497
- ));
2486
+ return /* @__PURE__ */ React16.createElement(
2487
+ "div",
2488
+ {
2489
+ className: cx(
2490
+ "aura-filterselect",
2491
+ props.disabled && "is-disabled",
2492
+ touchClass(props.touchHeight),
2493
+ props.className
2494
+ )
2495
+ },
2496
+ /* @__PURE__ */ React16.createElement("span", { className: "aura-filterselect__face", "aria-hidden": true, style: props.style }, face),
2497
+ h4(
2498
+ "select",
2499
+ Object.assign(extra, omit(rest, ["style"]), {
2500
+ ref: selMerged,
2501
+ id,
2502
+ className: "aura-filterselect__native",
2503
+ "aria-label": rest["aria-label"] || (rest["aria-labelledby"] ? void 0 : filter.name),
2504
+ "aria-describedby": described
2505
+ }),
2506
+ opts,
2507
+ props.children
2508
+ )
2509
+ );
2498
2510
  if (!live)
2499
2511
  return field(
2500
2512
  /* @__PURE__ */ React16.createElement("div", { className: cx("aura-input aura-select", props.icon && "has-icon", ro && "is-readonly") }, props.icon ? /* @__PURE__ */ React16.createElement(Icon, { name: props.icon, className: "aura-input__icon" }) : null, h4(
@@ -2607,6 +2619,7 @@ var Select = React16.forwardRef(function Select2(props, ref) {
2607
2619
  ro && "is-readonly",
2608
2620
  open && "is-open",
2609
2621
  filter && props.disabled && "is-disabled",
2622
+ filter && touchClass(props.touchHeight),
2610
2623
  filter && props.className
2611
2624
  ),
2612
2625
  "data-invalid": props.error ? "" : void 0
@@ -3375,7 +3388,7 @@ var DatePicker = React18.forwardRef(function DatePicker2(props, ref) {
3375
3388
  required: props.required,
3376
3389
  optional: props.optional,
3377
3390
  disabled: props.disabled,
3378
- className: props.className,
3391
+ className: cx(touchClass(props.touchHeight), props.className),
3379
3392
  name: props.name,
3380
3393
  boxRef,
3381
3394
  inputRef: inputMerged,
@@ -3509,7 +3522,7 @@ var DateRangePicker = React18.forwardRef(
3509
3522
  required: props.required,
3510
3523
  optional: props.optional,
3511
3524
  disabled: props.disabled,
3512
- className: props.className,
3525
+ className: cx(touchClass(props.touchHeight), props.className),
3513
3526
  name: props.name,
3514
3527
  boxRef,
3515
3528
  inputRef: inputMerged,
@@ -4099,7 +4112,7 @@ var Combobox = React22.forwardRef(
4099
4112
  required: props.required,
4100
4113
  optional: props.optional,
4101
4114
  disabled: props.disabled,
4102
- className: props.className
4115
+ className: cx(touchClass(props.touchHeight), props.className)
4103
4116
  },
4104
4117
  /* @__PURE__ */ React22.createElement("div", { ref: boxRef, className: cx("aura-input aura-combo has-icon", open && "is-open", multi && "is-multi") }, /* @__PURE__ */ React22.createElement(Icon, { name: props.icon || /* @__PURE__ */ React22.createElement(IconSearch, null), className: "aura-input__icon" }), multi && picked.length ? /* @__PURE__ */ React22.createElement("span", { className: "aura-combo__chips" }, picked.map(function(o) {
4105
4118
  return /* @__PURE__ */ React22.createElement("span", { key: o.value, className: "aura-combo__chip" }, /* @__PURE__ */ React22.createElement("span", { className: "aura-combo__chip-label" }, o.label), props.disabled || props.readOnly ? null : /* @__PURE__ */ React22.createElement(
@@ -4944,6 +4957,7 @@ var FilterBar = React29.forwardRef(function FilterBar2(props, ref) {
4944
4957
  props.searchGrow && "aura-filterbar--grow",
4945
4958
  props.controlsLayout === "fill" && "aura-filterbar--fill",
4946
4959
  props.stackBelow === "lg" && "aura-filterbar--stack-lg",
4960
+ touchClass(props.touchHeight),
4947
4961
  props.className
4948
4962
  )
4949
4963
  },
@@ -5511,6 +5525,19 @@ var Drawer = React32.forwardRef(function Drawer2(props, ref) {
5511
5525
  // src/DataTable.tsx
5512
5526
  var React33 = __toESM(require("react"), 1);
5513
5527
  var import_react_dom10 = require("react-dom");
5528
+ function ownRowAttrs(p) {
5529
+ if (!p) return null;
5530
+ const out = {};
5531
+ Object.keys(p).forEach(function(k) {
5532
+ if (k === "id" || /^data-/.test(k) && k !== "data-rc") out[k] = p[k];
5533
+ else
5534
+ devWarnOnce(
5535
+ "datatable-rowprops-" + k,
5536
+ 'DataTable rowProps: "' + k + '" is ignored; only data-* (not data-rc) and id are set on a row.'
5537
+ );
5538
+ });
5539
+ return out;
5540
+ }
5514
5541
  var BP = { sm: 640, md: 768, lg: 1024, xl: 1280 };
5515
5542
  var DEFAULT_COLUMNS = [
5516
5543
  { key: "id", label: "ID", width: 96, mono: true },
@@ -6722,6 +6749,7 @@ var DataTableImpl = React33.forwardRef(function DataTable(props, ref) {
6722
6749
  (props.onRowActivate || rowHref) && "is-actionable"
6723
6750
  ),
6724
6751
  style: rowStyle,
6752
+ ...ownRowAttrs(props.rowProps ? props.rowProps(r2) : null),
6725
6753
  onClick: function(e) {
6726
6754
  const el = e.target;
6727
6755
  if (el.closest && el.closest(".aura-check, button, a, input")) return;
@@ -8814,7 +8842,7 @@ var TimePicker = React54.forwardRef(function TimePicker2(props, ref) {
8814
8842
  required: props.required,
8815
8843
  optional: props.optional,
8816
8844
  disabled: props.disabled,
8817
- className: props.className
8845
+ className: cx(touchClass(props.touchHeight), props.className)
8818
8846
  },
8819
8847
  /* @__PURE__ */ React54.createElement("div", { ref: boxRef, className: cx("aura-input aura-combo aura-time has-icon", open && "is-open") }, /* @__PURE__ */ React54.createElement(Icon, { name: /* @__PURE__ */ React54.createElement(IconClock, null), className: "aura-input__icon" }), /* @__PURE__ */ React54.createElement(
8820
8848
  "input",
@@ -10016,7 +10044,7 @@ var NumberField = React65.forwardRef(function NumberField2(props, ref) {
10016
10044
  required: props.required,
10017
10045
  optional: props.optional,
10018
10046
  disabled: props.disabled,
10019
- className: props.className
10047
+ className: cx(touchClass(props.touchHeight), props.className)
10020
10048
  },
10021
10049
  /* @__PURE__ */ React65.createElement("div", { className: cx("aura-input aura-number", stepper && "has-stepper") }, props.prefix != null ? /* @__PURE__ */ React65.createElement("span", { className: "aura-number__affix", "aria-hidden": true }, props.prefix) : null, /* @__PURE__ */ React65.createElement(
10022
10050
  "input",
@@ -2,7 +2,7 @@
2
2
  import * as React from "react";
3
3
  import { useStrings, useDensity } from "./locale.js";
4
4
  import { createPortal } from "react-dom";
5
- import { cx, uid, useMaybeControlled, useMounted, useIsoLayoutEffect, useMergedRef } from "./internal.js";
5
+ import { cx, uid, useMaybeControlled, useMounted, useIsoLayoutEffect, useMergedRef, touchClass } from "./internal.js";
6
6
  import { Icon } from "./Icon.js";
7
7
  import { Field } from "./Field.js";
8
8
  import { IconCheck, IconChevronDown, IconLoaderCircle, IconSearch, IconX } from "./icons.js";
@@ -313,7 +313,7 @@ const Combobox = React.forwardRef(
313
313
  required: props.required,
314
314
  optional: props.optional,
315
315
  disabled: props.disabled,
316
- className: props.className
316
+ className: cx(touchClass(props.touchHeight), props.className)
317
317
  },
318
318
  /* @__PURE__ */ React.createElement("div", { ref: boxRef, className: cx("aura-input aura-combo has-icon", open && "is-open", multi && "is-multi") }, /* @__PURE__ */ React.createElement(Icon, { name: props.icon || /* @__PURE__ */ React.createElement(IconSearch, null), className: "aura-input__icon" }), multi && picked.length ? /* @__PURE__ */ React.createElement("span", { className: "aura-combo__chips" }, picked.map(function(o) {
319
319
  return /* @__PURE__ */ React.createElement("span", { key: o.value, className: "aura-combo__chip" }, /* @__PURE__ */ React.createElement("span", { className: "aura-combo__chip-label" }, o.label), props.disabled || props.readOnly ? null : /* @__PURE__ */ React.createElement(
@@ -24,6 +24,19 @@ import {
24
24
  IconPinOff,
25
25
  IconRotateCcw
26
26
  } from "./icons.js";
27
+ function ownRowAttrs(p) {
28
+ if (!p) return null;
29
+ const out = {};
30
+ Object.keys(p).forEach(function(k) {
31
+ if (k === "id" || /^data-/.test(k) && k !== "data-rc") out[k] = p[k];
32
+ else
33
+ devWarnOnce(
34
+ "datatable-rowprops-" + k,
35
+ 'DataTable rowProps: "' + k + '" is ignored; only data-* (not data-rc) and id are set on a row.'
36
+ );
37
+ });
38
+ return out;
39
+ }
27
40
  const BP = { sm: 640, md: 768, lg: 1024, xl: 1280 };
28
41
  const DEFAULT_COLUMNS = [
29
42
  { key: "id", label: "ID", width: 96, mono: true },
@@ -1233,6 +1246,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
1233
1246
  (props.onRowActivate || rowHref) && "is-actionable"
1234
1247
  ),
1235
1248
  style: rowStyle,
1249
+ ...ownRowAttrs(props.rowProps ? props.rowProps(r) : null),
1236
1250
  onClick: function(e) {
1237
1251
  const el = e.target;
1238
1252
  if (el.closest && el.closest(".aura-check, button, a, input")) return;
@@ -2,7 +2,16 @@
2
2
  import * as React from "react";
3
3
  import { useAuraLocale } from "./locale.js";
4
4
  import { createPortal } from "react-dom";
5
- import { cx, uid, useMaybeControlled, useMounted, useIsoLayoutEffect, trapTab, useMergedRef } from "./internal.js";
5
+ import {
6
+ cx,
7
+ uid,
8
+ useMaybeControlled,
9
+ useMounted,
10
+ useIsoLayoutEffect,
11
+ trapTab,
12
+ useMergedRef,
13
+ touchClass
14
+ } from "./internal.js";
6
15
  import { Icon } from "./Icon.js";
7
16
  import { IconButton } from "./IconButton.js";
8
17
  import { Field } from "./Field.js";
@@ -499,7 +508,7 @@ const DatePicker = React.forwardRef(function DatePicker2(props, ref) {
499
508
  required: props.required,
500
509
  optional: props.optional,
501
510
  disabled: props.disabled,
502
- className: props.className,
511
+ className: cx(touchClass(props.touchHeight), props.className),
503
512
  name: props.name,
504
513
  boxRef,
505
514
  inputRef: inputMerged,
@@ -633,7 +642,7 @@ const DateRangePicker = React.forwardRef(
633
642
  required: props.required,
634
643
  optional: props.optional,
635
644
  disabled: props.disabled,
636
- className: props.className,
645
+ className: cx(touchClass(props.touchHeight), props.className),
637
646
  name: props.name,
638
647
  boxRef,
639
648
  inputRef: inputMerged,
@@ -3,7 +3,7 @@ import * as React from "react";
3
3
  import { Icon } from "./Icon.js";
4
4
  import { IconButton } from "./IconButton.js";
5
5
  import { Tag } from "./Tag.js";
6
- import { cx, uid } from "./internal.js";
6
+ import { cx, touchClass, uid } from "./internal.js";
7
7
  import { useStrings } from "./locale.js";
8
8
  import { IconSearch, IconX } from "./icons.js";
9
9
  const FilterBar = React.forwardRef(function FilterBar2(props, ref) {
@@ -60,6 +60,7 @@ const FilterBar = React.forwardRef(function FilterBar2(props, ref) {
60
60
  props.searchGrow && "aura-filterbar--grow",
61
61
  props.controlsLayout === "fill" && "aura-filterbar--fill",
62
62
  props.stackBelow === "lg" && "aura-filterbar--stack-lg",
63
+ touchClass(props.touchHeight),
63
64
  props.className
64
65
  )
65
66
  },
@@ -2,7 +2,7 @@
2
2
  import * as React from "react";
3
3
  import { Field, describedBy } from "./Field.js";
4
4
  import { Icon } from "./Icon.js";
5
- import { cx, uid, useMaybeControlled } from "./internal.js";
5
+ import { cx, uid, useMaybeControlled, touchClass } from "./internal.js";
6
6
  import { useStrings } from "./locale.js";
7
7
  import { IconMinus, IconPlus } from "./icons.js";
8
8
  function decimalsOf(n) {
@@ -87,7 +87,7 @@ const NumberField = React.forwardRef(function NumberField2(props, ref) {
87
87
  required: props.required,
88
88
  optional: props.optional,
89
89
  disabled: props.disabled,
90
- className: props.className
90
+ className: cx(touchClass(props.touchHeight), props.className)
91
91
  },
92
92
  /* @__PURE__ */ React.createElement("div", { className: cx("aura-input aura-number", stepper && "has-stepper") }, props.prefix != null ? /* @__PURE__ */ React.createElement("span", { className: "aura-number__affix", "aria-hidden": true }, props.prefix) : null, /* @__PURE__ */ React.createElement(
93
93
  "input",
@@ -425,18 +425,30 @@ const Select = React.forwardRef(function Select2(props, ref) {
425
425
  const nameId = id + "-name";
426
426
  const face = filter ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", { id: nameId, className: "aura-filterselect__name", "aria-hidden": true }, filter.name), /* @__PURE__ */ React.createElement("span", { className: "aura-filterselect__value", "aria-hidden": shown[0].label !== shown[0].full || void 0 }, shown[0].label || " "), shown[0].label !== shown[0].full ? /* @__PURE__ */ React.createElement("span", { className: "aura-sr-only" }, shown[0].full) : null, /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconChevronDown, null), className: "aura-filterselect__chevron" })) : null;
427
427
  if (!live && filter)
428
- return /* @__PURE__ */ React.createElement("div", { className: cx("aura-filterselect", props.disabled && "is-disabled", props.className) }, /* @__PURE__ */ React.createElement("span", { className: "aura-filterselect__face", "aria-hidden": true, style: props.style }, face), h(
429
- "select",
430
- Object.assign(extra, omit(rest, ["style"]), {
431
- ref: selMerged,
432
- id,
433
- className: "aura-filterselect__native",
434
- "aria-label": rest["aria-label"] || (rest["aria-labelledby"] ? void 0 : filter.name),
435
- "aria-describedby": described
436
- }),
437
- opts,
438
- props.children
439
- ));
428
+ return /* @__PURE__ */ React.createElement(
429
+ "div",
430
+ {
431
+ className: cx(
432
+ "aura-filterselect",
433
+ props.disabled && "is-disabled",
434
+ touchClass(props.touchHeight),
435
+ props.className
436
+ )
437
+ },
438
+ /* @__PURE__ */ React.createElement("span", { className: "aura-filterselect__face", "aria-hidden": true, style: props.style }, face),
439
+ h(
440
+ "select",
441
+ Object.assign(extra, omit(rest, ["style"]), {
442
+ ref: selMerged,
443
+ id,
444
+ className: "aura-filterselect__native",
445
+ "aria-label": rest["aria-label"] || (rest["aria-labelledby"] ? void 0 : filter.name),
446
+ "aria-describedby": described
447
+ }),
448
+ opts,
449
+ props.children
450
+ )
451
+ );
440
452
  if (!live)
441
453
  return field(
442
454
  /* @__PURE__ */ React.createElement("div", { className: cx("aura-input aura-select", props.icon && "has-icon", ro && "is-readonly") }, props.icon ? /* @__PURE__ */ React.createElement(Icon, { name: props.icon, className: "aura-input__icon" }) : null, h(
@@ -549,6 +561,7 @@ const Select = React.forwardRef(function Select2(props, ref) {
549
561
  ro && "is-readonly",
550
562
  open && "is-open",
551
563
  filter && props.disabled && "is-disabled",
564
+ filter && touchClass(props.touchHeight),
552
565
  filter && props.className
553
566
  ),
554
567
  "data-invalid": props.error ? "" : void 0
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import * as React from "react";
3
3
  import { createPortal } from "react-dom";
4
- import { cx, uid, useMaybeControlled, useMounted, useIsoLayoutEffect, useMergedRef } from "./internal.js";
4
+ import { cx, uid, useMaybeControlled, useMounted, useIsoLayoutEffect, useMergedRef, touchClass } from "./internal.js";
5
5
  import { useStrings } from "./locale.js";
6
6
  import { Icon } from "./Icon.js";
7
7
  import { Field } from "./Field.js";
@@ -236,7 +236,7 @@ const TimePicker = React.forwardRef(function TimePicker2(props, ref) {
236
236
  required: props.required,
237
237
  optional: props.optional,
238
238
  disabled: props.disabled,
239
- className: props.className
239
+ className: cx(touchClass(props.touchHeight), props.className)
240
240
  },
241
241
  /* @__PURE__ */ React.createElement("div", { ref: boxRef, className: cx("aura-input aura-combo aura-time has-icon", open && "is-open") }, /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconClock, null), className: "aura-input__icon" }), /* @__PURE__ */ React.createElement(
242
242
  "input",
package/dist/index.d.cts CHANGED
@@ -216,6 +216,10 @@ export interface DataTableProps<Row extends Record<string, any> = Record<string,
216
216
  linkComponent?: React$1.ElementType | undefined;
217
217
  /** Skeleton row count when there is no pageSize. Default 5. */
218
218
  skeletonRows?: number | undefined;
219
+ /** 5.38 (Chamber-OS 142): attributes of your own on each row's element — `data-*` (a test hook such as
220
+ * `data-user-id`) and `id` — in the table layout and as a stacked card. Anything else is ignored, so a row keeps
221
+ * its own role, classes and handlers. */
222
+ rowProps?: RowCallback<DataTableRowProps | null | undefined, Row> | undefined;
219
223
  /** Called on row click or Enter. */
220
224
  onRowActivate?: RowCallback<void, Row> | undefined;
221
225
  /** Fixed height in px: sticky header, and only the rows in view are rendered. */
@@ -496,6 +500,11 @@ export interface FilterBarProps {
496
500
  /** `fill`: the filter controls share their row in equal columns (at least 120px each, wrapping when they can't),
497
501
  * and the count and actions keep to the end (5.15, Chamber-OS 92). Default `auto`: each at its own width. */
498
502
  controlsLayout?: "auto" | "fill" | undefined;
503
+ /** 5.38 (Chamber-OS 140): 44px search and field-height controls in the bar (FilterSelect, Select, SegmentedControl…)
504
+ * — `true` below 640px or on a coarse pointer, as Button's and TextField's `touchHeight`; `'always'` at every
505
+ * width. Without it they follow the density's input height (44px on a coarse pointer). Buttons in `actions` take
506
+ * their own `touchHeight`. */
507
+ touchHeight?: TouchHeight | undefined;
499
508
  /** Below this width (the viewport's) the search takes a row of its own above the controls. Default `md` (768px);
500
509
  * `lg` (1024px) for bars with several filters (5.15, Chamber-OS 92). */
501
510
  stackBelow?: "md" | "lg" | undefined;
@@ -597,6 +606,9 @@ export interface FilterSelectProps extends Omit<React$1.SelectHTMLAttributes<HTM
597
606
  /** A shorter word the face shows while the first option is chosen ("All" for "All statuses"). The list and screen
598
607
  * readers keep the option's own text. */
599
608
  allLabel?: string | undefined;
609
+ /** 5.38 (Chamber-OS 140): a 44px face — `true` below 640px or on a coarse pointer (as Button's and TextField's
610
+ * `touchHeight`), `'always'` at every width. Without it: the density's input height, 44px on a coarse pointer. */
611
+ touchHeight?: TouchHeight | undefined;
600
612
  }
601
613
  /** A RadioGroup option. `description` is a second line under the label; since 5.26 the radio is named by `label`
602
614
  * alone and the description is read after it (`aria-describedby`), also when the option is disabled (Chamber-OS 125). */
@@ -927,6 +939,9 @@ export interface ComboboxMultipleProps extends Omit<ComboboxProps, "value" | "de
927
939
  max?: number | undefined;
928
940
  }
929
941
  export interface ComboboxProps extends FieldProps {
942
+ /** 5.38 (Chamber-OS 141): a 44px box, its buttons 44px wide — `true` below 640px or on a coarse pointer, as
943
+ * TextField's `touchHeight`; `'always'` at every width. Default: the density's input height. */
944
+ touchHeight?: TouchHeight | undefined;
930
945
  /** The options. Optional with `groups` (5.16). */
931
946
  options?: Array<ComboboxOption | string> | undefined;
932
947
  /** Selected option value (controlled). */
@@ -966,6 +981,9 @@ export interface ComboboxProps extends FieldProps {
966
981
  }
967
982
  /** Number input: thousands separators, +/− buttons, arrow keys, min/max/step, prefix/suffix (฿, %). */
968
983
  export interface NumberFieldProps extends FieldProps {
984
+ /** 5.38 (Chamber-OS 141): a 44px box, its buttons 44px wide — `true` below 640px or on a coarse pointer, as
985
+ * TextField's `touchHeight`; `'always'` at every width. Default: the density's input height. */
986
+ touchHeight?: TouchHeight | undefined;
969
987
  /** The number (controlled). `null` = empty. */
970
988
  value?: number | null | undefined;
971
989
  defaultValue?: number | null | undefined;
@@ -1077,6 +1095,9 @@ export interface CalendarProps extends DateDisplayOptions {
1077
1095
  autoFocus?: boolean | undefined;
1078
1096
  }
1079
1097
  export interface DateFieldProps extends FieldProps, DateDisplayOptions {
1098
+ /** 5.38 (Chamber-OS 141): a 44px box, its buttons 44px wide — `true` below 640px or on a coarse pointer, as
1099
+ * TextField's `touchHeight`; `'always'` at every width. Default: the density's input height. */
1100
+ touchHeight?: TouchHeight | undefined;
1080
1101
  id?: string | undefined;
1081
1102
  name?: string | undefined;
1082
1103
  placeholder?: string | undefined;
@@ -1146,6 +1167,10 @@ export interface DateRangePickerProps extends DateFieldProps {
1146
1167
  export type DataAttributes = {
1147
1168
  [key: `data-${string}`]: string | number | boolean | undefined;
1148
1169
  };
1170
+ /** What DataTable's `rowProps` may set on a row (5.38): `data-*` attributes and an `id`. */
1171
+ export type DataTableRowProps = DataAttributes & {
1172
+ id?: string | undefined;
1173
+ };
1149
1174
  /** Attributes for a button AURA renders for you (a Drawer's close button, a tab): `data-testid`, `aria-*`, `id`… */
1150
1175
  export type ButtonAttributes = React$1.ButtonHTMLAttributes<HTMLButtonElement> & DataAttributes;
1151
1176
  /** `id`, `data-*`, `aria-*`, `style`, `lang` and `dir` go on the `.aura-drawer` panel (5.9, Chamber-OS 70). */
@@ -1421,6 +1446,9 @@ export interface StatProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id
1421
1446
  className?: string | undefined;
1422
1447
  }
1423
1448
  export interface TimePickerProps extends FieldProps {
1449
+ /** 5.38 (Chamber-OS 141): a 44px box, its buttons 44px wide — `true` below 640px or on a coarse pointer, as
1450
+ * TextField's `touchHeight`; `'always'` at every width. Default: the density's input height. */
1451
+ touchHeight?: TouchHeight | undefined;
1424
1452
  /** "HH:mm", 24-hour. */
1425
1453
  value?: string | null | undefined;
1426
1454
  defaultValue?: string | null | undefined;
package/dist/index.d.ts CHANGED
@@ -216,6 +216,10 @@ export interface DataTableProps<Row extends Record<string, any> = Record<string,
216
216
  linkComponent?: React$1.ElementType | undefined;
217
217
  /** Skeleton row count when there is no pageSize. Default 5. */
218
218
  skeletonRows?: number | undefined;
219
+ /** 5.38 (Chamber-OS 142): attributes of your own on each row's element — `data-*` (a test hook such as
220
+ * `data-user-id`) and `id` — in the table layout and as a stacked card. Anything else is ignored, so a row keeps
221
+ * its own role, classes and handlers. */
222
+ rowProps?: RowCallback<DataTableRowProps | null | undefined, Row> | undefined;
219
223
  /** Called on row click or Enter. */
220
224
  onRowActivate?: RowCallback<void, Row> | undefined;
221
225
  /** Fixed height in px: sticky header, and only the rows in view are rendered. */
@@ -496,6 +500,11 @@ export interface FilterBarProps {
496
500
  /** `fill`: the filter controls share their row in equal columns (at least 120px each, wrapping when they can't),
497
501
  * and the count and actions keep to the end (5.15, Chamber-OS 92). Default `auto`: each at its own width. */
498
502
  controlsLayout?: "auto" | "fill" | undefined;
503
+ /** 5.38 (Chamber-OS 140): 44px search and field-height controls in the bar (FilterSelect, Select, SegmentedControl…)
504
+ * — `true` below 640px or on a coarse pointer, as Button's and TextField's `touchHeight`; `'always'` at every
505
+ * width. Without it they follow the density's input height (44px on a coarse pointer). Buttons in `actions` take
506
+ * their own `touchHeight`. */
507
+ touchHeight?: TouchHeight | undefined;
499
508
  /** Below this width (the viewport's) the search takes a row of its own above the controls. Default `md` (768px);
500
509
  * `lg` (1024px) for bars with several filters (5.15, Chamber-OS 92). */
501
510
  stackBelow?: "md" | "lg" | undefined;
@@ -597,6 +606,9 @@ export interface FilterSelectProps extends Omit<React$1.SelectHTMLAttributes<HTM
597
606
  /** A shorter word the face shows while the first option is chosen ("All" for "All statuses"). The list and screen
598
607
  * readers keep the option's own text. */
599
608
  allLabel?: string | undefined;
609
+ /** 5.38 (Chamber-OS 140): a 44px face — `true` below 640px or on a coarse pointer (as Button's and TextField's
610
+ * `touchHeight`), `'always'` at every width. Without it: the density's input height, 44px on a coarse pointer. */
611
+ touchHeight?: TouchHeight | undefined;
600
612
  }
601
613
  /** A RadioGroup option. `description` is a second line under the label; since 5.26 the radio is named by `label`
602
614
  * alone and the description is read after it (`aria-describedby`), also when the option is disabled (Chamber-OS 125). */
@@ -927,6 +939,9 @@ export interface ComboboxMultipleProps extends Omit<ComboboxProps, "value" | "de
927
939
  max?: number | undefined;
928
940
  }
929
941
  export interface ComboboxProps extends FieldProps {
942
+ /** 5.38 (Chamber-OS 141): a 44px box, its buttons 44px wide — `true` below 640px or on a coarse pointer, as
943
+ * TextField's `touchHeight`; `'always'` at every width. Default: the density's input height. */
944
+ touchHeight?: TouchHeight | undefined;
930
945
  /** The options. Optional with `groups` (5.16). */
931
946
  options?: Array<ComboboxOption | string> | undefined;
932
947
  /** Selected option value (controlled). */
@@ -966,6 +981,9 @@ export interface ComboboxProps extends FieldProps {
966
981
  }
967
982
  /** Number input: thousands separators, +/− buttons, arrow keys, min/max/step, prefix/suffix (฿, %). */
968
983
  export interface NumberFieldProps extends FieldProps {
984
+ /** 5.38 (Chamber-OS 141): a 44px box, its buttons 44px wide — `true` below 640px or on a coarse pointer, as
985
+ * TextField's `touchHeight`; `'always'` at every width. Default: the density's input height. */
986
+ touchHeight?: TouchHeight | undefined;
969
987
  /** The number (controlled). `null` = empty. */
970
988
  value?: number | null | undefined;
971
989
  defaultValue?: number | null | undefined;
@@ -1077,6 +1095,9 @@ export interface CalendarProps extends DateDisplayOptions {
1077
1095
  autoFocus?: boolean | undefined;
1078
1096
  }
1079
1097
  export interface DateFieldProps extends FieldProps, DateDisplayOptions {
1098
+ /** 5.38 (Chamber-OS 141): a 44px box, its buttons 44px wide — `true` below 640px or on a coarse pointer, as
1099
+ * TextField's `touchHeight`; `'always'` at every width. Default: the density's input height. */
1100
+ touchHeight?: TouchHeight | undefined;
1080
1101
  id?: string | undefined;
1081
1102
  name?: string | undefined;
1082
1103
  placeholder?: string | undefined;
@@ -1146,6 +1167,10 @@ export interface DateRangePickerProps extends DateFieldProps {
1146
1167
  export type DataAttributes = {
1147
1168
  [key: `data-${string}`]: string | number | boolean | undefined;
1148
1169
  };
1170
+ /** What DataTable's `rowProps` may set on a row (5.38): `data-*` attributes and an `id`. */
1171
+ export type DataTableRowProps = DataAttributes & {
1172
+ id?: string | undefined;
1173
+ };
1149
1174
  /** Attributes for a button AURA renders for you (a Drawer's close button, a tab): `data-testid`, `aria-*`, `id`… */
1150
1175
  export type ButtonAttributes = React$1.ButtonHTMLAttributes<HTMLButtonElement> & DataAttributes;
1151
1176
  /** `id`, `data-*`, `aria-*`, `style`, `lang` and `dir` go on the `.aura-drawer` panel (5.9, Chamber-OS 70). */
@@ -1421,6 +1446,9 @@ export interface StatProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id
1421
1446
  className?: string | undefined;
1422
1447
  }
1423
1448
  export interface TimePickerProps extends FieldProps {
1449
+ /** 5.38 (Chamber-OS 141): a 44px box, its buttons 44px wide — `true` below 640px or on a coarse pointer, as
1450
+ * TextField's `touchHeight`; `'always'` at every width. Default: the density's input height. */
1451
+ touchHeight?: TouchHeight | undefined;
1424
1452
  /** "HH:mm", 24-hour. */
1425
1453
  value?: string | null | undefined;
1426
1454
  defaultValue?: string | null | undefined;
package/dist/styles.css CHANGED
@@ -1617,6 +1617,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1617
1617
  }
1618
1618
  .aura-tag__remove { position: relative; }
1619
1619
  .aura-combo.is-multi .aura-combo__clear, .aura-combo.is-multi .aura-combo__toggle { top: calc((var(--aura-input-height) - 2px - 40px) / 2); }
1620
+ .aura-combo.is-multi { padding-right: calc(var(--aura-space-1) + 2 * var(--aura-touch-target)); } /* 5.38: room for both 44px buttons */
1620
1621
  }
1621
1622
 
1622
1623
  /* ---------- Small screens (< 640px) ---------- */
@@ -1665,6 +1666,25 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1665
1666
  .aura-check--labelled.is-touch-always .aura-check__input { top: calc((var(--aura-touch-target) - 20px) / 2 + 3px); }
1666
1667
  .aura-radio-group.is-touch-always .aura-radio-group__list { gap: 0; }
1667
1668
  .aura-radio-group.is-touch-always .aura-radio-group__list.is-horizontal { gap: 0 var(--aura-space-6); align-items: flex-start; }
1669
+ /* 5.38 (Chamber-OS 141): Combobox, DatePicker, TimePicker and NumberField take touchHeight too; their buttons inside
1670
+ * the box get the touch-screen sizes (44px wide, side by side) with the 44px box, so neither is a 32px target. A
1671
+ * FilterBar with touchHeight (Chamber-OS 140) does the same for those fields in it. */
1672
+ :is(.aura-field, .aura-filterbar).is-touch-always :is(.aura-combo__clear, .aura-combo__toggle, .aura-date__toggle) { width: var(--aura-touch-target); height: 40px; }
1673
+ :is(.aura-field, .aura-filterbar).is-touch-always :is(.aura-combo__toggle, .aura-date__toggle) { right: 0; }
1674
+ :is(.aura-field, .aura-filterbar).is-touch-always .aura-combo__clear { right: var(--aura-touch-target); }
1675
+ :is(.aura-field, .aura-filterbar).is-touch-always :is(.aura-combo, .aura-date) .aura-input__control { padding-right: calc(var(--aura-space-1) + 2 * var(--aura-touch-target)); }
1676
+ :is(.aura-field, .aura-filterbar).is-touch-always .aura-combo.is-multi { padding-right: calc(var(--aura-space-1) + 2 * var(--aura-touch-target)); }
1677
+ :is(.aura-field, .aura-filterbar).is-touch-always .aura-combo.is-multi :is(.aura-combo__clear, .aura-combo__toggle) { top: calc((var(--aura-input-height) - 2px - 40px) / 2); }
1678
+ :is(.aura-field, .aura-filterbar).is-touch-always .aura-number__step { width: var(--aura-touch-target); }
1679
+ @media (max-width: 639.98px), (pointer: coarse) {
1680
+ :is(.aura-field, .aura-filterbar).is-touch :is(.aura-combo__clear, .aura-combo__toggle, .aura-date__toggle) { width: var(--aura-touch-target); height: 40px; }
1681
+ :is(.aura-field, .aura-filterbar).is-touch :is(.aura-combo__toggle, .aura-date__toggle) { right: 0; }
1682
+ :is(.aura-field, .aura-filterbar).is-touch .aura-combo__clear { right: var(--aura-touch-target); }
1683
+ :is(.aura-field, .aura-filterbar).is-touch :is(.aura-combo, .aura-date) .aura-input__control { padding-right: calc(var(--aura-space-1) + 2 * var(--aura-touch-target)); }
1684
+ :is(.aura-field, .aura-filterbar).is-touch .aura-combo.is-multi { padding-right: calc(var(--aura-space-1) + 2 * var(--aura-touch-target)); }
1685
+ :is(.aura-field, .aura-filterbar).is-touch .aura-combo.is-multi :is(.aura-combo__clear, .aura-combo__toggle) { top: calc((var(--aura-input-height) - 2px - 40px) / 2); }
1686
+ :is(.aura-field, .aura-filterbar).is-touch .aura-number__step { width: var(--aura-touch-target); }
1687
+ }
1668
1688
  @media (max-width: 639.98px), (pointer: coarse) {
1669
1689
  .aura-field.is-touch { --aura-input-height: var(--aura-touch-target); }
1670
1690
  .aura-radio-group.is-touch .aura-choice, .aura-check--labelled.is-touch {
@@ -1788,6 +1808,18 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1788
1808
  .aura-filterselect__native { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; opacity: 0; font-size: 16px; cursor: pointer; appearance: none; }
1789
1809
  .aura-filterselect.is-disabled .aura-filterselect__face { background: var(--aura-bg-input-disabled); color: var(--aura-fg-secondary); border-color: var(--aura-border-default); cursor: not-allowed; }
1790
1810
  .aura-filterselect.is-disabled .aura-filterselect__native { cursor: not-allowed; }
1811
+ /* 5.38 (Chamber-OS 140): touchHeight on FilterBar (its search and field-height controls) or on one FilterSelect —
1812
+ * 44px below 640px or on a coarse pointer (is-touch), or always. */
1813
+ :is(.aura-filterbar, .aura-filterselect).is-touch-always { --aura-input-height: var(--aura-touch-target); }
1814
+ .aura-filterbar.is-touch-always .aura-segmented__option { height: var(--aura-touch-target); }
1815
+ .aura-filterbar.is-touch-always .aura-segmented__option.is-icon { width: var(--aura-touch-target); }
1816
+ .aura-filterbar.is-touch-always .aura-filterbar__clear-search { width: var(--aura-touch-target); height: 40px; margin-right: 0; }
1817
+ @media (max-width: 639.98px), (pointer: coarse) {
1818
+ :is(.aura-filterbar, .aura-filterselect).is-touch { --aura-input-height: var(--aura-touch-target); }
1819
+ .aura-filterbar.is-touch .aura-segmented__option { height: var(--aura-touch-target); }
1820
+ .aura-filterbar.is-touch .aura-segmented__option.is-icon { width: var(--aura-touch-target); }
1821
+ .aura-filterbar.is-touch .aura-filterbar__clear-search { width: var(--aura-touch-target); height: 40px; margin-right: 0; }
1822
+ }
1791
1823
  @media (forced-colors: active) { .aura-filterselect__face { border-color: ButtonText; } }
1792
1824
  /* 5.26 (Chamber-OS 128) FilterDateRange: presets beside the range calendar; above it on phones. */
1793
1825
  .aura-filterdate__pop { display: flex; gap: var(--aura-space-3); overflow-y: auto; }
@@ -1619,6 +1619,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1619
1619
  }
1620
1620
  .aura-tag__remove { position: relative; }
1621
1621
  .aura-combo.is-multi .aura-combo__clear, .aura-combo.is-multi .aura-combo__toggle { top: calc((var(--aura-input-height) - 2px - 40px) / 2); }
1622
+ .aura-combo.is-multi { padding-right: calc(var(--aura-space-1) + 2 * var(--aura-touch-target)); } /* 5.38: room for both 44px buttons */
1622
1623
  }
1623
1624
 
1624
1625
  /* ---------- Small screens (< 640px) ---------- */
@@ -1667,6 +1668,25 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1667
1668
  .aura-check--labelled.is-touch-always .aura-check__input { top: calc((var(--aura-touch-target) - 20px) / 2 + 3px); }
1668
1669
  .aura-radio-group.is-touch-always .aura-radio-group__list { gap: 0; }
1669
1670
  .aura-radio-group.is-touch-always .aura-radio-group__list.is-horizontal { gap: 0 var(--aura-space-6); align-items: flex-start; }
1671
+ /* 5.38 (Chamber-OS 141): Combobox, DatePicker, TimePicker and NumberField take touchHeight too; their buttons inside
1672
+ * the box get the touch-screen sizes (44px wide, side by side) with the 44px box, so neither is a 32px target. A
1673
+ * FilterBar with touchHeight (Chamber-OS 140) does the same for those fields in it. */
1674
+ :is(.aura-field, .aura-filterbar).is-touch-always :is(.aura-combo__clear, .aura-combo__toggle, .aura-date__toggle) { width: var(--aura-touch-target); height: 40px; }
1675
+ :is(.aura-field, .aura-filterbar).is-touch-always :is(.aura-combo__toggle, .aura-date__toggle) { right: 0; }
1676
+ :is(.aura-field, .aura-filterbar).is-touch-always .aura-combo__clear { right: var(--aura-touch-target); }
1677
+ :is(.aura-field, .aura-filterbar).is-touch-always :is(.aura-combo, .aura-date) .aura-input__control { padding-right: calc(var(--aura-space-1) + 2 * var(--aura-touch-target)); }
1678
+ :is(.aura-field, .aura-filterbar).is-touch-always .aura-combo.is-multi { padding-right: calc(var(--aura-space-1) + 2 * var(--aura-touch-target)); }
1679
+ :is(.aura-field, .aura-filterbar).is-touch-always .aura-combo.is-multi :is(.aura-combo__clear, .aura-combo__toggle) { top: calc((var(--aura-input-height) - 2px - 40px) / 2); }
1680
+ :is(.aura-field, .aura-filterbar).is-touch-always .aura-number__step { width: var(--aura-touch-target); }
1681
+ @media (max-width: 639.98px), (pointer: coarse) {
1682
+ :is(.aura-field, .aura-filterbar).is-touch :is(.aura-combo__clear, .aura-combo__toggle, .aura-date__toggle) { width: var(--aura-touch-target); height: 40px; }
1683
+ :is(.aura-field, .aura-filterbar).is-touch :is(.aura-combo__toggle, .aura-date__toggle) { right: 0; }
1684
+ :is(.aura-field, .aura-filterbar).is-touch .aura-combo__clear { right: var(--aura-touch-target); }
1685
+ :is(.aura-field, .aura-filterbar).is-touch :is(.aura-combo, .aura-date) .aura-input__control { padding-right: calc(var(--aura-space-1) + 2 * var(--aura-touch-target)); }
1686
+ :is(.aura-field, .aura-filterbar).is-touch .aura-combo.is-multi { padding-right: calc(var(--aura-space-1) + 2 * var(--aura-touch-target)); }
1687
+ :is(.aura-field, .aura-filterbar).is-touch .aura-combo.is-multi :is(.aura-combo__clear, .aura-combo__toggle) { top: calc((var(--aura-input-height) - 2px - 40px) / 2); }
1688
+ :is(.aura-field, .aura-filterbar).is-touch .aura-number__step { width: var(--aura-touch-target); }
1689
+ }
1670
1690
  @media (max-width: 639.98px), (pointer: coarse) {
1671
1691
  .aura-field.is-touch { --aura-input-height: var(--aura-touch-target); }
1672
1692
  .aura-radio-group.is-touch .aura-choice, .aura-check--labelled.is-touch {
@@ -1790,6 +1810,18 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1790
1810
  .aura-filterselect__native { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; opacity: 0; font-size: 16px; cursor: pointer; appearance: none; }
1791
1811
  .aura-filterselect.is-disabled .aura-filterselect__face { background: var(--aura-bg-input-disabled); color: var(--aura-fg-secondary); border-color: var(--aura-border-default); cursor: not-allowed; }
1792
1812
  .aura-filterselect.is-disabled .aura-filterselect__native { cursor: not-allowed; }
1813
+ /* 5.38 (Chamber-OS 140): touchHeight on FilterBar (its search and field-height controls) or on one FilterSelect —
1814
+ * 44px below 640px or on a coarse pointer (is-touch), or always. */
1815
+ :is(.aura-filterbar, .aura-filterselect).is-touch-always { --aura-input-height: var(--aura-touch-target); }
1816
+ .aura-filterbar.is-touch-always .aura-segmented__option { height: var(--aura-touch-target); }
1817
+ .aura-filterbar.is-touch-always .aura-segmented__option.is-icon { width: var(--aura-touch-target); }
1818
+ .aura-filterbar.is-touch-always .aura-filterbar__clear-search { width: var(--aura-touch-target); height: 40px; margin-right: 0; }
1819
+ @media (max-width: 639.98px), (pointer: coarse) {
1820
+ :is(.aura-filterbar, .aura-filterselect).is-touch { --aura-input-height: var(--aura-touch-target); }
1821
+ .aura-filterbar.is-touch .aura-segmented__option { height: var(--aura-touch-target); }
1822
+ .aura-filterbar.is-touch .aura-segmented__option.is-icon { width: var(--aura-touch-target); }
1823
+ .aura-filterbar.is-touch .aura-filterbar__clear-search { width: var(--aura-touch-target); height: 40px; margin-right: 0; }
1824
+ }
1793
1825
  @media (forced-colors: active) { .aura-filterselect__face { border-color: ButtonText; } }
1794
1826
  /* 5.26 (Chamber-OS 128) FilterDateRange: presets beside the range calendar; above it on phones. */
1795
1827
  .aura-filterdate__pop { display: flex; gap: var(--aura-space-3); overflow-y: auto; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.37.0",
3
+ "version": "5.38.0",
4
4
  "description": "AURA Design System — React components (Enterprise Standard, Human Creative). Thai-first: Buddhist-era dates, Thai collation.",
5
5
  "license": "MIT",
6
6
  "type": "module",