@jirawatpyk/aura-react 5.64.0 → 5.66.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,15 @@ 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.66 — Chamber-OS addenda 82–83 (#181, #182)
190
+
191
+ - **A checkable menu item keeps its icon** (#181): an item with `icon` and `checked` (a `menuitemcheckbox`) now shows its icon at the start and its state as a check mark at the end — after the `hint`, in the checked colour, its 16px slot kept when unchecked so the hints of such items line up — instead of replacing the icon with a check box. An item with no icon keeps the leading check box (avoid mixing the two in one menu); `checkPlacement: 'start'` on an item keeps the 5.65 look. Radio items still draw their circle in place of an icon. `role` and `aria-checked` are unchanged; in forced colours the mark takes the text colour.
192
+ - **Combobox takes `invalid` and `aria-describedby`** (#182), as TextField has since 5.50: `invalid` gives the danger border and `aria-invalid="true"` without AURA's message line, and `aria-describedby` adds your ids (a `role="alert"` message beside the picker) after the input's own (the hint or the error, the chip summary), each id once. `error` still wins.
193
+
194
+ ## 5.65 — Chamber-OS addendum 81 (#180)
195
+
196
+ - **A pressed IconButton looks on:** an IconButton with `aria-pressed="true"` — or the new `pressed` prop, which sets `aria-pressed` for you — draws the selected fill (`aura-bg-selected`, as a selected Tag or nav item) with an accent icon (`aura-fg-accent`, at least 3:1 on it in light and dark); `tone` is ignored while pressed. Hover still shows on a pressed one (an accent hairline inside), an `outline` toggle takes an accent border, a pressed menu trigger stays on while its menu is open, and the focus ring is unchanged. In forced colours a pressed toggle is Highlight with a CanvasText focus ring. `pressed={false}`, no prop and `aria-pressed="mixed"` draw as before. Inside a field the reveal eye of PasswordField (which uses `aria-pressed`) stays quiet. On a selected DataTable row, which has the same fill, only the accent icon shows it. For an editor toolbar's Bold / Italic / lists; drop `aria-pressed:bg-… aria-pressed:text-…` stand-ins.
197
+
189
198
  ## 5.64 — Chamber-OS addendum 80 (#179)
190
199
 
191
200
  - **Progress `legend` — a key for the reserved part:** `legend={{ value: 'Used', secondary: 'Reserved (in review or scheduled)' }}` draws a key under the bar (above the `hint`): a swatch in the bar's tone for each part (`value` is optional), the second striped like the reserved segment, so it follows `tone="danger"`. It shows only while the reserved segment is drawn and wraps on a phone. It is `aria-hidden`, so while it shows the bar reads both counts ("2 of 6 used, 1 reserved") even when you pass a `valueLabel` — pass `valueText` to word it yourself. In forced colours the bar and the swatches use Highlight in every tone (before 5.64 a toned bar kept its colour). Drop a hand-drawn key that copies the stripe.
@@ -1649,7 +1649,7 @@ window.Aura = (() => {
1649
1649
 
1650
1650
  // src/IconButton.tsx
1651
1651
  var IconButton = React8.forwardRef(function IconButton2(props, ref) {
1652
- const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant"]);
1652
+ const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant", "pressed"]);
1653
1653
  useAutoTip();
1654
1654
  const own = props.title !== void 0;
1655
1655
  return /* @__PURE__ */ React8.createElement(
@@ -1659,6 +1659,7 @@ window.Aura = (() => {
1659
1659
  ref,
1660
1660
  type: props.type || "button",
1661
1661
  "aria-label": props.label,
1662
+ "aria-pressed": props.pressed != null ? props.pressed : props["aria-pressed"],
1662
1663
  "data-aura-tip": own ? void 0 : props.label,
1663
1664
  className: cx(
1664
1665
  "aura-icon-btn",
@@ -1834,11 +1835,13 @@ window.Aura = (() => {
1834
1835
  if (it.separator) return /* @__PURE__ */ React9.createElement("div", { key: "s" + i, role: "separator", className: "aura-menu__sep" });
1835
1836
  const isRadio = it.type === "radio";
1836
1837
  const isCheck = !isRadio && it.checked !== void 0;
1837
- const lead = isRadio ? /* @__PURE__ */ React9.createElement("span", { className: cx("aura-menu__radio", it.checked && "is-on") }) : isCheck ? /* @__PURE__ */ React9.createElement("span", { className: cx("aura-menu__check", it.checked && "is-on") }, it.checked ? /* @__PURE__ */ React9.createElement(Icon, { name: /* @__PURE__ */ React9.createElement(IconCheck, null), size: 12, strokeWidth: 3 }) : null) : it.icon ? /* @__PURE__ */ React9.createElement(Icon, { name: it.icon }) : /* @__PURE__ */ React9.createElement("span", { className: "aura-menu__blank" });
1838
+ const checkAtEnd = isCheck && !!it.icon && it.checkPlacement !== "start";
1839
+ const lead = isRadio ? /* @__PURE__ */ React9.createElement("span", { className: cx("aura-menu__radio", it.checked && "is-on") }) : isCheck && !checkAtEnd ? /* @__PURE__ */ React9.createElement("span", { className: cx("aura-menu__check", it.checked && "is-on") }, it.checked ? /* @__PURE__ */ React9.createElement(Icon, { name: /* @__PURE__ */ React9.createElement(IconCheck, null), size: 12, strokeWidth: 3 }) : null) : it.icon ? /* @__PURE__ */ React9.createElement(Icon, { name: it.icon }) : /* @__PURE__ */ React9.createElement("span", { className: "aura-menu__blank" });
1838
1840
  const body = [
1839
1841
  /* @__PURE__ */ React9.createElement(React9.Fragment, { key: "l" }, lead),
1840
1842
  /* @__PURE__ */ React9.createElement("span", { key: "t", className: "aura-menu__label" }, it.label),
1841
- it.hint ? /* @__PURE__ */ React9.createElement("span", { key: "h", className: "aura-menu__hint" }, it.hint) : null
1843
+ it.hint ? /* @__PURE__ */ React9.createElement("span", { key: "h", className: "aura-menu__hint" }, it.hint) : null,
1844
+ checkAtEnd ? /* @__PURE__ */ React9.createElement("span", { key: "c", className: cx("aura-menu__mark", it.checked && "is-on") }, it.checked ? /* @__PURE__ */ React9.createElement(Icon, { name: /* @__PURE__ */ React9.createElement(IconCheck, null), size: 16, strokeWidth: 2.5 }) : null) : null
1842
1845
  ];
1843
1846
  const cls = cx("aura-menu__item", it.tone === "danger" && "aura-menu__item--danger");
1844
1847
  const reasonId = it.disabled && it.disabledReason ? itemId + "-r" + i : void 0;
@@ -4248,6 +4251,7 @@ window.Aura = (() => {
4248
4251
  label: props.label,
4249
4252
  hint: props.hint,
4250
4253
  error: props.error,
4254
+ invalid: props.invalid,
4251
4255
  required: props.required,
4252
4256
  optional: props.optional,
4253
4257
  disabled: props.disabled,
@@ -4292,8 +4296,18 @@ window.Aura = (() => {
4292
4296
  "aria-controls": open && live.length ? listId : void 0,
4293
4297
  "aria-autocomplete": "list",
4294
4298
  "aria-activedescendant": open && live[activeIdx] ? optId(activeIdx) : void 0,
4295
- "aria-invalid": props.error ? true : void 0,
4296
- "aria-describedby": [props.error ? id + "-error" : props.hint ? id + "-hint" : "", multi && picked.length ? summaryId : ""].filter(Boolean).join(" ") || void 0,
4299
+ "aria-invalid": props.error || props.invalid ? true : void 0,
4300
+ "aria-describedby": (
4301
+ /* each id once, in order: error or hint, the chip summary, then yours */
4302
+ Array.from(
4303
+ new Set(
4304
+ [
4305
+ props.error ? id + "-error" : props.hint ? id + "-hint" : "",
4306
+ multi && picked.length ? summaryId : ""
4307
+ ].concat(String(props["aria-describedby"] || "").split(/\s+/)).filter(Boolean)
4308
+ )
4309
+ ).join(" ") || void 0
4310
+ ),
4297
4311
  placeholder: multi && values.length ? void 0 : props.placeholder,
4298
4312
  disabled: props.disabled,
4299
4313
  readOnly: props.readOnly,
@@ -1631,7 +1631,7 @@ function useAutoTip() {
1631
1631
 
1632
1632
  // src/IconButton.tsx
1633
1633
  var IconButton = React8.forwardRef(function IconButton2(props, ref) {
1634
- const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant"]);
1634
+ const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant", "pressed"]);
1635
1635
  useAutoTip();
1636
1636
  const own = props.title !== void 0;
1637
1637
  return /* @__PURE__ */ React8.createElement(
@@ -1641,6 +1641,7 @@ var IconButton = React8.forwardRef(function IconButton2(props, ref) {
1641
1641
  ref,
1642
1642
  type: props.type || "button",
1643
1643
  "aria-label": props.label,
1644
+ "aria-pressed": props.pressed != null ? props.pressed : props["aria-pressed"],
1644
1645
  "data-aura-tip": own ? void 0 : props.label,
1645
1646
  className: cx(
1646
1647
  "aura-icon-btn",
@@ -1816,11 +1817,13 @@ var Menu = React9.forwardRef(function Menu2(props, ref) {
1816
1817
  if (it.separator) return /* @__PURE__ */ React9.createElement("div", { key: "s" + i, role: "separator", className: "aura-menu__sep" });
1817
1818
  const isRadio = it.type === "radio";
1818
1819
  const isCheck = !isRadio && it.checked !== void 0;
1819
- const lead = isRadio ? /* @__PURE__ */ React9.createElement("span", { className: cx("aura-menu__radio", it.checked && "is-on") }) : isCheck ? /* @__PURE__ */ React9.createElement("span", { className: cx("aura-menu__check", it.checked && "is-on") }, it.checked ? /* @__PURE__ */ React9.createElement(Icon, { name: /* @__PURE__ */ React9.createElement(IconCheck, null), size: 12, strokeWidth: 3 }) : null) : it.icon ? /* @__PURE__ */ React9.createElement(Icon, { name: it.icon }) : /* @__PURE__ */ React9.createElement("span", { className: "aura-menu__blank" });
1820
+ const checkAtEnd = isCheck && !!it.icon && it.checkPlacement !== "start";
1821
+ const lead = isRadio ? /* @__PURE__ */ React9.createElement("span", { className: cx("aura-menu__radio", it.checked && "is-on") }) : isCheck && !checkAtEnd ? /* @__PURE__ */ React9.createElement("span", { className: cx("aura-menu__check", it.checked && "is-on") }, it.checked ? /* @__PURE__ */ React9.createElement(Icon, { name: /* @__PURE__ */ React9.createElement(IconCheck, null), size: 12, strokeWidth: 3 }) : null) : it.icon ? /* @__PURE__ */ React9.createElement(Icon, { name: it.icon }) : /* @__PURE__ */ React9.createElement("span", { className: "aura-menu__blank" });
1820
1822
  const body = [
1821
1823
  /* @__PURE__ */ React9.createElement(React9.Fragment, { key: "l" }, lead),
1822
1824
  /* @__PURE__ */ React9.createElement("span", { key: "t", className: "aura-menu__label" }, it.label),
1823
- it.hint ? /* @__PURE__ */ React9.createElement("span", { key: "h", className: "aura-menu__hint" }, it.hint) : null
1825
+ it.hint ? /* @__PURE__ */ React9.createElement("span", { key: "h", className: "aura-menu__hint" }, it.hint) : null,
1826
+ checkAtEnd ? /* @__PURE__ */ React9.createElement("span", { key: "c", className: cx("aura-menu__mark", it.checked && "is-on") }, it.checked ? /* @__PURE__ */ React9.createElement(Icon, { name: /* @__PURE__ */ React9.createElement(IconCheck, null), size: 16, strokeWidth: 2.5 }) : null) : null
1824
1827
  ];
1825
1828
  const cls = cx("aura-menu__item", it.tone === "danger" && "aura-menu__item--danger");
1826
1829
  const reasonId = it.disabled && it.disabledReason ? itemId + "-r" + i : void 0;
@@ -4230,6 +4233,7 @@ var Combobox = React22.forwardRef(
4230
4233
  label: props.label,
4231
4234
  hint: props.hint,
4232
4235
  error: props.error,
4236
+ invalid: props.invalid,
4233
4237
  required: props.required,
4234
4238
  optional: props.optional,
4235
4239
  disabled: props.disabled,
@@ -4274,8 +4278,18 @@ var Combobox = React22.forwardRef(
4274
4278
  "aria-controls": open && live.length ? listId : void 0,
4275
4279
  "aria-autocomplete": "list",
4276
4280
  "aria-activedescendant": open && live[activeIdx] ? optId(activeIdx) : void 0,
4277
- "aria-invalid": props.error ? true : void 0,
4278
- "aria-describedby": [props.error ? id + "-error" : props.hint ? id + "-hint" : "", multi && picked.length ? summaryId : ""].filter(Boolean).join(" ") || void 0,
4281
+ "aria-invalid": props.error || props.invalid ? true : void 0,
4282
+ "aria-describedby": (
4283
+ /* each id once, in order: error or hint, the chip summary, then yours */
4284
+ Array.from(
4285
+ new Set(
4286
+ [
4287
+ props.error ? id + "-error" : props.hint ? id + "-hint" : "",
4288
+ multi && picked.length ? summaryId : ""
4289
+ ].concat(String(props["aria-describedby"] || "").split(/\s+/)).filter(Boolean)
4290
+ )
4291
+ ).join(" ") || void 0
4292
+ ),
4279
4293
  placeholder: multi && values.length ? void 0 : props.placeholder,
4280
4294
  disabled: props.disabled,
4281
4295
  readOnly: props.readOnly,
@@ -310,6 +310,7 @@ const Combobox = React.forwardRef(
310
310
  label: props.label,
311
311
  hint: props.hint,
312
312
  error: props.error,
313
+ invalid: props.invalid,
313
314
  required: props.required,
314
315
  optional: props.optional,
315
316
  disabled: props.disabled,
@@ -354,8 +355,18 @@ const Combobox = React.forwardRef(
354
355
  "aria-controls": open && live.length ? listId : void 0,
355
356
  "aria-autocomplete": "list",
356
357
  "aria-activedescendant": open && live[activeIdx] ? optId(activeIdx) : void 0,
357
- "aria-invalid": props.error ? true : void 0,
358
- "aria-describedby": [props.error ? id + "-error" : props.hint ? id + "-hint" : "", multi && picked.length ? summaryId : ""].filter(Boolean).join(" ") || void 0,
358
+ "aria-invalid": props.error || props.invalid ? true : void 0,
359
+ "aria-describedby": (
360
+ /* each id once, in order: error or hint, the chip summary, then yours */
361
+ Array.from(
362
+ new Set(
363
+ [
364
+ props.error ? id + "-error" : props.hint ? id + "-hint" : "",
365
+ multi && picked.length ? summaryId : ""
366
+ ].concat(String(props["aria-describedby"] || "").split(/\s+/)).filter(Boolean)
367
+ )
368
+ ).join(" ") || void 0
369
+ ),
359
370
  placeholder: multi && values.length ? void 0 : props.placeholder,
360
371
  disabled: props.disabled,
361
372
  readOnly: props.readOnly,
@@ -4,7 +4,7 @@ import { cx, omit } from "./internal.js";
4
4
  import { Icon } from "./Icon.js";
5
5
  import { useAutoTip } from "./autoTip.js";
6
6
  const IconButton = React.forwardRef(function IconButton2(props, ref) {
7
- const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant"]);
7
+ const rest = omit(props, ["icon", "label", "className", "size", "tone", "touchHeight", "variant", "pressed"]);
8
8
  useAutoTip();
9
9
  const own = props.title !== void 0;
10
10
  return /* @__PURE__ */ React.createElement(
@@ -14,6 +14,7 @@ const IconButton = React.forwardRef(function IconButton2(props, ref) {
14
14
  ref,
15
15
  type: props.type || "button",
16
16
  "aria-label": props.label,
17
+ "aria-pressed": props.pressed != null ? props.pressed : props["aria-pressed"],
17
18
  "data-aura-tip": own ? void 0 : props.label,
18
19
  className: cx(
19
20
  "aura-icon-btn",
package/dist/esm/Menu.js CHANGED
@@ -164,11 +164,13 @@ const Menu = React.forwardRef(function Menu2(props, ref) {
164
164
  if (it.separator) return /* @__PURE__ */ React.createElement("div", { key: "s" + i, role: "separator", className: "aura-menu__sep" });
165
165
  const isRadio = it.type === "radio";
166
166
  const isCheck = !isRadio && it.checked !== void 0;
167
- const lead = isRadio ? /* @__PURE__ */ React.createElement("span", { className: cx("aura-menu__radio", it.checked && "is-on") }) : isCheck ? /* @__PURE__ */ React.createElement("span", { className: cx("aura-menu__check", it.checked && "is-on") }, it.checked ? /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconCheck, null), size: 12, strokeWidth: 3 }) : null) : it.icon ? /* @__PURE__ */ React.createElement(Icon, { name: it.icon }) : /* @__PURE__ */ React.createElement("span", { className: "aura-menu__blank" });
167
+ const checkAtEnd = isCheck && !!it.icon && it.checkPlacement !== "start";
168
+ const lead = isRadio ? /* @__PURE__ */ React.createElement("span", { className: cx("aura-menu__radio", it.checked && "is-on") }) : isCheck && !checkAtEnd ? /* @__PURE__ */ React.createElement("span", { className: cx("aura-menu__check", it.checked && "is-on") }, it.checked ? /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconCheck, null), size: 12, strokeWidth: 3 }) : null) : it.icon ? /* @__PURE__ */ React.createElement(Icon, { name: it.icon }) : /* @__PURE__ */ React.createElement("span", { className: "aura-menu__blank" });
168
169
  const body = [
169
170
  /* @__PURE__ */ React.createElement(React.Fragment, { key: "l" }, lead),
170
171
  /* @__PURE__ */ React.createElement("span", { key: "t", className: "aura-menu__label" }, it.label),
171
- it.hint ? /* @__PURE__ */ React.createElement("span", { key: "h", className: "aura-menu__hint" }, it.hint) : null
172
+ it.hint ? /* @__PURE__ */ React.createElement("span", { key: "h", className: "aura-menu__hint" }, it.hint) : null,
173
+ checkAtEnd ? /* @__PURE__ */ React.createElement("span", { key: "c", className: cx("aura-menu__mark", it.checked && "is-on") }, it.checked ? /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconCheck, null), size: 16, strokeWidth: 2.5 }) : null) : null
172
174
  ];
173
175
  const cls = cx("aura-menu__item", it.tone === "danger" && "aura-menu__item--danger");
174
176
  const reasonId = it.disabled && it.disabledReason ? itemId + "-r" + i : void 0;
package/dist/index.d.cts CHANGED
@@ -384,12 +384,20 @@ export interface IconButtonProps extends React$1.ButtonHTMLAttributes<HTMLButton
384
384
  /** 44×44 instead of 32×32 below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24) —
385
385
  * a phone sheet's close button, a card's ⋯ trigger (5.15, Chamber-OS 100). */
386
386
  touchHeight?: boolean | undefined;
387
+ /** A toggle (5.65, Chamber-OS 180): sets `aria-pressed`, and a pressed button draws as on — the selected fill and the
388
+ * accent icon. Omit for an ordinary button. An `aria-pressed` you pass draws the same. */
389
+ pressed?: boolean | undefined;
387
390
  }
388
391
  export interface MenuItem {
389
392
  label?: string | undefined;
390
393
  icon?: IconInput | undefined;
391
- /** Present = a checkable item (menuitemcheckbox). */
394
+ /** Present = a checkable item (menuitemcheckbox). 5.66 (Chamber-OS 181): with an `icon` too, the icon stays at the
395
+ * start and the state is a check mark at the end (after `hint`); without one, a check box at the start. A radio
396
+ * item (`type: 'radio'`) still draws its circle in place of an icon. */
392
397
  checked?: boolean | undefined;
398
+ /** 5.66: where a checkable item with an `icon` shows its state — `end` (default: the icon stays, a check mark at the
399
+ * end) or `start` (the check box in place of the icon, as before 5.66). */
400
+ checkPlacement?: "start" | "end" | undefined;
393
401
  /** Dimmed and does nothing when chosen, but still reachable with the arrow keys and announced (5.10). */
394
402
  disabled?: boolean | undefined;
395
403
  /** Why it's disabled ("You can resend in 5 minutes"): shown in place of the hint and read with the item. (5.10) */
@@ -995,6 +1003,12 @@ export interface ComboboxMultipleProps extends Omit<ComboboxProps, "value" | "de
995
1003
  max?: number | undefined;
996
1004
  }
997
1005
  export interface ComboboxProps extends FieldProps {
1006
+ /** 5.66 (Chamber-OS 182): ids added to the input's own description (the hint or error, the chip summary) — a page's
1007
+ * `role="alert"` message beside the field (each id once). With `invalid` the field is marked wrong without
1008
+ * AURA's message line; `error` still wins. */
1009
+ "aria-describedby"?: string | undefined;
1010
+ /** 5.66 (Chamber-OS 182): the danger border and `aria-invalid="true"` without AURA's message line, as on TextField. */
1011
+ invalid?: boolean | undefined;
998
1012
  /** 5.38 (Chamber-OS 141): a 44px box, its buttons 44px wide — `true` below 640px or on a coarse pointer, as
999
1013
  * TextField's `touchHeight`; `'always'` at every width. Default: the density's input height. */
1000
1014
  touchHeight?: TouchHeight | undefined;
package/dist/index.d.ts CHANGED
@@ -384,12 +384,20 @@ export interface IconButtonProps extends React$1.ButtonHTMLAttributes<HTMLButton
384
384
  /** 44×44 instead of 32×32 below 640px (the viewport's) or wherever the primary pointer is coarse (a tablet, 5.24) —
385
385
  * a phone sheet's close button, a card's ⋯ trigger (5.15, Chamber-OS 100). */
386
386
  touchHeight?: boolean | undefined;
387
+ /** A toggle (5.65, Chamber-OS 180): sets `aria-pressed`, and a pressed button draws as on — the selected fill and the
388
+ * accent icon. Omit for an ordinary button. An `aria-pressed` you pass draws the same. */
389
+ pressed?: boolean | undefined;
387
390
  }
388
391
  export interface MenuItem {
389
392
  label?: string | undefined;
390
393
  icon?: IconInput | undefined;
391
- /** Present = a checkable item (menuitemcheckbox). */
394
+ /** Present = a checkable item (menuitemcheckbox). 5.66 (Chamber-OS 181): with an `icon` too, the icon stays at the
395
+ * start and the state is a check mark at the end (after `hint`); without one, a check box at the start. A radio
396
+ * item (`type: 'radio'`) still draws its circle in place of an icon. */
392
397
  checked?: boolean | undefined;
398
+ /** 5.66: where a checkable item with an `icon` shows its state — `end` (default: the icon stays, a check mark at the
399
+ * end) or `start` (the check box in place of the icon, as before 5.66). */
400
+ checkPlacement?: "start" | "end" | undefined;
393
401
  /** Dimmed and does nothing when chosen, but still reachable with the arrow keys and announced (5.10). */
394
402
  disabled?: boolean | undefined;
395
403
  /** Why it's disabled ("You can resend in 5 minutes"): shown in place of the hint and read with the item. (5.10) */
@@ -995,6 +1003,12 @@ export interface ComboboxMultipleProps extends Omit<ComboboxProps, "value" | "de
995
1003
  max?: number | undefined;
996
1004
  }
997
1005
  export interface ComboboxProps extends FieldProps {
1006
+ /** 5.66 (Chamber-OS 182): ids added to the input's own description (the hint or error, the chip summary) — a page's
1007
+ * `role="alert"` message beside the field (each id once). With `invalid` the field is marked wrong without
1008
+ * AURA's message line; `error` still wins. */
1009
+ "aria-describedby"?: string | undefined;
1010
+ /** 5.66 (Chamber-OS 182): the danger border and `aria-invalid="true"` without AURA's message line, as on TextField. */
1011
+ invalid?: boolean | undefined;
998
1012
  /** 5.38 (Chamber-OS 141): a 44px box, its buttons 44px wide — `true` below 640px or on a coarse pointer, as
999
1013
  * TextField's `touchHeight`; `'always'` at every width. Default: the density's input height. */
1000
1014
  touchHeight?: TouchHeight | undefined;
package/dist/styles.css CHANGED
@@ -317,6 +317,11 @@ button.aura-btn--creative[aria-disabled='true']:hover { box-shadow: var(--aura-s
317
317
  }
318
318
  .aura-menu__check.is-on { background: var(--aura-control-checked-bg); border-color: var(--aura-control-checked-bg); color: var(--aura-control-checked-fg); }
319
319
  .aura-menu__check.is-on .aura-icon { color: inherit; }
320
+ /* 5.66 (Chamber-OS 181): the trailing check mark of a checkable item that keeps its icon — the checked colour (text colour in forced colours), a fixed
321
+ * width so labels line up checked or not. */
322
+ .aura-menu__mark { flex: none; width: var(--aura-icon-sm); height: var(--aura-icon-sm); display: inline-flex; align-items: center; justify-content: center; }
323
+ .aura-menu__item .aura-menu__mark .aura-icon { color: var(--aura-control-checked-bg); }
324
+ .aura-menu__item--danger .aura-menu__mark .aura-icon { color: inherit; } /* a danger item's mark is its danger text */
320
325
  .aura-menu__item--danger, .aura-menu__item--danger .aura-icon { color: var(--aura-fg-danger); }
321
326
  .aura-menu__item--danger:hover, .aura-menu__item--danger:focus { background: var(--aura-alert-danger-bg); color: var(--aura-alert-danger-fg); }
322
327
  .aura-menu__item--danger:hover .aura-icon, .aura-menu__item--danger:focus .aura-icon { color: var(--aura-alert-danger-fg); }
@@ -358,6 +363,13 @@ a.aura-icon-btn { text-decoration: none; }
358
363
  .aura-icon-btn--outline { box-sizing: border-box; border: 1px solid var(--aura-button-secondary-border); } /* 5.44 (Chamber-OS 149): reads as a button beside outlined ones */
359
364
  .aura-icon-btn--danger:hover { background: var(--aura-alert-danger-bg); }
360
365
  .aura-icon-btn:disabled { opacity: var(--aura-disabled-opacity); pointer-events: none; }
366
+ /* 5.65 (Chamber-OS 180): a toggle (aria-pressed="true", or the pressed prop) looks on — the selected fill and the
367
+ * accent icon — and hover still shows on top of it (an accent hairline inside). Outline toggles take an accent border.
368
+ * The focus ring is unchanged. Not inside a field: PasswordField's reveal eye (aria-pressed) stays quiet (5.30 #14).
369
+ * One class stronger than the open-menu fill, so a pressed menu trigger stays on while its menu is open. */
370
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *) { background: var(--aura-bg-selected); color: var(--aura-fg-accent); }
371
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):hover { background: var(--aura-bg-selected); box-shadow: inset 0 0 0 1px var(--aura-fg-accent); }
372
+ .aura-icon-btn--outline[aria-pressed="true"]:not(.aura-input *) { border-color: var(--aura-fg-accent); }
361
373
  .aura-icon-btn:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
362
374
  /* 5.15 (Chamber-OS 100): touchHeight — visibly 44px on phones, for buttons and icon buttons a phone design wants full size.
363
375
  * 5.24 (Chamber-OS 123): also wherever the primary pointer is coarse — a tablet at 768–1366px is a finger, not a mouse.
@@ -2552,6 +2564,10 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
2552
2564
  .aura-switch-row.is-disabled .aura-choice__label { color: GrayText; }
2553
2565
  .aura-progress__track, .aura-upload__bar { border: 1px solid CanvasText; }
2554
2566
  .aura-progress :is(.aura-progress__bar, .aura-progress__swatch), .aura-upload__bar > span { background: Highlight; forced-color-adjust: none; } /* every tone (5.64) */
2567
+ .aura-menu__item .aura-menu__mark .aura-icon { color: inherit; } /* 5.66: the item's text colour */
2568
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *) { background: Highlight; color: HighlightText; forced-color-adjust: none; } /* 5.65 */
2569
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):hover { box-shadow: inset 0 0 0 1px HighlightText; }
2570
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):focus-visible { outline-color: CanvasText; }
2555
2571
  .aura-segmented__option.is-selected { outline: 2px solid Highlight; outline-offset: -2px; }
2556
2572
  .aura-tab { border-bottom-color: Canvas; }
2557
2573
  .aura-tab.is-active { border-bottom-color: Highlight; }
@@ -319,6 +319,11 @@ button.aura-btn--creative[aria-disabled='true']:hover { box-shadow: var(--aura-s
319
319
  }
320
320
  .aura-menu__check.is-on { background: var(--aura-control-checked-bg); border-color: var(--aura-control-checked-bg); color: var(--aura-control-checked-fg); }
321
321
  .aura-menu__check.is-on .aura-icon { color: inherit; }
322
+ /* 5.66 (Chamber-OS 181): the trailing check mark of a checkable item that keeps its icon — the checked colour (text colour in forced colours), a fixed
323
+ * width so labels line up checked or not. */
324
+ .aura-menu__mark { flex: none; width: var(--aura-icon-sm); height: var(--aura-icon-sm); display: inline-flex; align-items: center; justify-content: center; }
325
+ .aura-menu__item .aura-menu__mark .aura-icon { color: var(--aura-control-checked-bg); }
326
+ .aura-menu__item--danger .aura-menu__mark .aura-icon { color: inherit; } /* a danger item's mark is its danger text */
322
327
  .aura-menu__item--danger, .aura-menu__item--danger .aura-icon { color: var(--aura-fg-danger); }
323
328
  .aura-menu__item--danger:hover, .aura-menu__item--danger:focus { background: var(--aura-alert-danger-bg); color: var(--aura-alert-danger-fg); }
324
329
  .aura-menu__item--danger:hover .aura-icon, .aura-menu__item--danger:focus .aura-icon { color: var(--aura-alert-danger-fg); }
@@ -360,6 +365,13 @@ a.aura-icon-btn { text-decoration: none; }
360
365
  .aura-icon-btn--outline { box-sizing: border-box; border: 1px solid var(--aura-button-secondary-border); } /* 5.44 (Chamber-OS 149): reads as a button beside outlined ones */
361
366
  .aura-icon-btn--danger:hover { background: var(--aura-alert-danger-bg); }
362
367
  .aura-icon-btn:disabled { opacity: var(--aura-disabled-opacity); pointer-events: none; }
368
+ /* 5.65 (Chamber-OS 180): a toggle (aria-pressed="true", or the pressed prop) looks on — the selected fill and the
369
+ * accent icon — and hover still shows on top of it (an accent hairline inside). Outline toggles take an accent border.
370
+ * The focus ring is unchanged. Not inside a field: PasswordField's reveal eye (aria-pressed) stays quiet (5.30 #14).
371
+ * One class stronger than the open-menu fill, so a pressed menu trigger stays on while its menu is open. */
372
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *) { background: var(--aura-bg-selected); color: var(--aura-fg-accent); }
373
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):hover { background: var(--aura-bg-selected); box-shadow: inset 0 0 0 1px var(--aura-fg-accent); }
374
+ .aura-icon-btn--outline[aria-pressed="true"]:not(.aura-input *) { border-color: var(--aura-fg-accent); }
363
375
  .aura-icon-btn:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
364
376
  /* 5.15 (Chamber-OS 100): touchHeight — visibly 44px on phones, for buttons and icon buttons a phone design wants full size.
365
377
  * 5.24 (Chamber-OS 123): also wherever the primary pointer is coarse — a tablet at 768–1366px is a finger, not a mouse.
@@ -2554,6 +2566,10 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
2554
2566
  .aura-switch-row.is-disabled .aura-choice__label { color: GrayText; }
2555
2567
  .aura-progress__track, .aura-upload__bar { border: 1px solid CanvasText; }
2556
2568
  .aura-progress :is(.aura-progress__bar, .aura-progress__swatch), .aura-upload__bar > span { background: Highlight; forced-color-adjust: none; } /* every tone (5.64) */
2569
+ .aura-menu__item .aura-menu__mark .aura-icon { color: inherit; } /* 5.66: the item's text colour */
2570
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *) { background: Highlight; color: HighlightText; forced-color-adjust: none; } /* 5.65 */
2571
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):hover { box-shadow: inset 0 0 0 1px HighlightText; }
2572
+ .aura-icon-btn[aria-pressed="true"]:not(.aura-input *):focus-visible { outline-color: CanvasText; }
2557
2573
  .aura-segmented__option.is-selected { outline: 2px solid Highlight; outline-offset: -2px; }
2558
2574
  .aura-tab { border-bottom-color: Canvas; }
2559
2575
  .aura-tab.is-active { border-bottom-color: Highlight; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.64.0",
3
+ "version": "5.66.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",