@jirawatpyk/aura-react 5.66.0 → 5.68.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.
@@ -0,0 +1,80 @@
1
+ 'use client';
2
+ import * as React from "react";
3
+ import { Checkbox } from "./Checkbox.js";
4
+ import { describedBy, fieldNote } from "./Field.js";
5
+ import { cx, touchClass, uid, useMaybeControlled } from "./internal.js";
6
+ import { useStrings } from "./locale.js";
7
+ const CheckboxGroup = React.forwardRef(
8
+ function CheckboxGroup2(props, ref) {
9
+ const t = useStrings();
10
+ const auto = uid(), id = props.id || auto;
11
+ const st = useMaybeControlled(props.value, props.defaultValue || [], props.onChange);
12
+ const picked = st[0] || [];
13
+ const opts = (props.options || []).map(function(o) {
14
+ return typeof o === "object" ? o : { value: o, label: o };
15
+ });
16
+ const name = props.name || id;
17
+ const setRef = React.useCallback(
18
+ function(el) {
19
+ if (el)
20
+ el.focus = function(o) {
21
+ const b = el.querySelector('input[type="checkbox"]:checked:not(:disabled)') || el.querySelector('input[type="checkbox"]:not(:disabled)');
22
+ if (b) b.focus(o);
23
+ };
24
+ if (typeof ref === "function") ref(el);
25
+ else if (ref) ref.current = el;
26
+ },
27
+ [ref]
28
+ );
29
+ return /* @__PURE__ */ React.createElement(
30
+ "fieldset",
31
+ {
32
+ ref: setRef,
33
+ className: cx(
34
+ "aura-field aura-radio-group aura-checkbox-group",
35
+ props.error && "is-invalid",
36
+ props.disabled && "is-disabled",
37
+ touchClass(props.touchHeight),
38
+ props.className
39
+ ),
40
+ "aria-describedby": describedBy(id, props),
41
+ disabled: props.disabled
42
+ },
43
+ props.label ? /* @__PURE__ */ React.createElement("legend", { className: "aura-field__label" }, props.label, props.required ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", { className: "aura-field__req", "aria-hidden": true }, " *"), /* @__PURE__ */ React.createElement("span", { className: "aura-sr-only" }, " (" + t.required + ")")) : null) : null,
44
+ /* @__PURE__ */ React.createElement("div", { className: cx("aura-radio-group__list", props.orientation === "horizontal" && "is-horizontal") }, opts.map(function(v) {
45
+ return /* @__PURE__ */ React.createElement(
46
+ Checkbox,
47
+ {
48
+ key: v.value,
49
+ name,
50
+ value: v.value,
51
+ checked: picked.indexOf(v.value) >= 0,
52
+ disabled: props.disabled || v.disabled,
53
+ description: v.description,
54
+ touchHeight: props.touchHeight,
55
+ "aria-invalid": props.error ? true : void 0,
56
+ "aria-describedby": props.error ? id + "-error" : void 0,
57
+ onChange: function(on) {
58
+ const known = opts.map(function(o) {
59
+ return o.value;
60
+ });
61
+ const next = known.filter(function(val) {
62
+ return val === v.value ? on : picked.indexOf(val) >= 0;
63
+ }).concat(
64
+ picked.filter(function(val) {
65
+ return known.indexOf(val) < 0;
66
+ })
67
+ );
68
+ st[1](next);
69
+ }
70
+ },
71
+ v.label
72
+ );
73
+ })),
74
+ fieldNote(id, props.error, props.hint, props.errorLive)
75
+ );
76
+ }
77
+ );
78
+ export {
79
+ CheckboxGroup
80
+ };
package/dist/esm/Field.js CHANGED
@@ -27,12 +27,19 @@ const Field = React.forwardRef(function Field2(props, ref) {
27
27
  ) : null,
28
28
  hasAddon(props.labelAddon) ? /* @__PURE__ */ React.createElement("div", { className: "aura-field__addon", id: props.id + "-addon" }, props.labelAddon) : null,
29
29
  props.children,
30
- 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
30
+ fieldNote(props.id, props.error, props.hint, props.errorLive)
31
31
  );
32
32
  });
33
33
  function describedBy(id, p) {
34
34
  return p.error ? id + "-error" : p.hint ? id + "-hint" : void 0;
35
35
  }
36
+ function fieldNote(id, error, hint, live) {
37
+ const err = error ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconCircleAlert, null), size: 14 }), error) : null;
38
+ const hintLine = hint ? /* @__PURE__ */ React.createElement("p", { className: "aura-field__hint", id: id + "-hint" }, hint) : null;
39
+ if (!live)
40
+ return err ? /* @__PURE__ */ React.createElement("p", { className: "aura-field__error", id: id + "-error" }, err) : hintLine;
41
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, err ? null : hintLine, /* @__PURE__ */ React.createElement("p", { className: "aura-field__error", id: id == null ? void 0 : id + "-error", "aria-live": "polite" }, err));
42
+ }
36
43
  function hasAddon(n) {
37
44
  return n != null && typeof n !== "boolean" && n !== "";
38
45
  }
@@ -68,6 +75,7 @@ export {
68
75
  FIELD_KEYS,
69
76
  Field,
70
77
  describedBy,
78
+ fieldNote,
71
79
  hasAddon,
72
80
  joinDescribedBy
73
81
  };
@@ -1,9 +1,7 @@
1
1
  'use client';
2
2
  import * as React from "react";
3
- import { describedBy } from "./Field.js";
4
- import { Icon } from "./Icon.js";
3
+ import { describedBy, fieldNote } from "./Field.js";
5
4
  import { cx, touchClass, uid, useMaybeControlled } from "./internal.js";
6
- import { IconCircleAlert } from "./icons.js";
7
5
  const RadioGroup = React.forwardRef(function RadioGroup2(props, ref) {
8
6
  const auto = uid(), id = props.id || auto;
9
7
  const st = useMaybeControlled(
@@ -31,6 +29,7 @@ const RadioGroup = React.forwardRef(function RadioGroup2(props, ref) {
31
29
  className: cx(
32
30
  "aura-field aura-radio-group",
33
31
  props.error && "is-invalid",
32
+ props.disabled && "is-disabled",
34
33
  touchClass(props.touchHeight),
35
34
  props.className
36
35
  ),
@@ -60,7 +59,7 @@ const RadioGroup = React.forwardRef(function RadioGroup2(props, ref) {
60
59
  }
61
60
  ), /* @__PURE__ */ React.createElement("span", { className: "aura-choice__text" }, /* @__PURE__ */ React.createElement("span", { className: "aura-choice__label", id: oid ? oid + "-label" : void 0 }, v.label), v.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-choice__desc", id: oid + "-desc" }, v.description) : null));
62
61
  })),
63
- props.error ? /* @__PURE__ */ React.createElement("p", { className: "aura-field__error", id: 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: id + "-hint" }, props.hint) : null
62
+ fieldNote(id, props.error, props.hint, props.errorLive)
64
63
  );
65
64
  });
66
65
  export {
package/dist/esm/index.js CHANGED
@@ -13,6 +13,7 @@ import { Select } from "./Select.js";
13
13
  import { FilterSelect } from "./FilterSelect.js";
14
14
  import { FilterDateRange } from "./FilterDateRange.js";
15
15
  import { RadioGroup } from "./RadioGroup.js";
16
+ import { CheckboxGroup } from "./CheckboxGroup.js";
16
17
  import { Switch } from "./Switch.js";
17
18
  import { Combobox, defaultFilter } from "./Combobox.js";
18
19
  import { DatePicker, DateRangePicker, Calendar, formatDate, parseDate, useFormatDate } from "./DatePicker.js";
@@ -78,6 +79,7 @@ export {
78
79
  Calendar,
79
80
  Card,
80
81
  Checkbox,
82
+ CheckboxGroup,
81
83
  ColorSchemeScript,
82
84
  ColorSchemeToggle,
83
85
  Combobox,
@@ -133,6 +133,7 @@ const STRINGS = {
133
133
  statusOk: "OK",
134
134
  statusUnknown: "No data",
135
135
  opensInNewTab: "opens in a new tab",
136
+ required: "required",
136
137
  filtersApplied: function(n2) {
137
138
  return "Filters, " + n2.toLocaleString("en") + " applied";
138
139
  },
@@ -129,6 +129,7 @@ const sv = {
129
129
  statusOk: "OK",
130
130
  statusUnknown: "Ingen data",
131
131
  opensInNewTab: "\xF6ppnas i en ny flik",
132
+ required: "obligatoriskt",
132
133
  filtersApplied: function(n) {
133
134
  return "Filter, " + n.toLocaleString("sv-SE") + " aktiva";
134
135
  },
@@ -129,6 +129,7 @@ const th = {
129
129
  statusOk: "\u0E1B\u0E01\u0E15\u0E34",
130
130
  statusUnknown: "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
131
131
  opensInNewTab: "\u0E40\u0E1B\u0E34\u0E14\u0E43\u0E19\u0E41\u0E17\u0E47\u0E1A\u0E43\u0E2B\u0E21\u0E48",
132
+ required: "\u0E08\u0E33\u0E40\u0E1B\u0E47\u0E19",
132
133
  filtersApplied: function(n2) {
133
134
  return "\u0E15\u0E31\u0E27\u0E01\u0E23\u0E2D\u0E07, \u0E43\u0E0A\u0E49\u0E2D\u0E22\u0E39\u0E48 " + n2.toLocaleString("en") + " \u0E23\u0E32\u0E22\u0E01\u0E32\u0E23";
134
135
  },
package/dist/index.d.cts CHANGED
@@ -680,13 +680,42 @@ export interface RadioGroupProps extends FieldProps {
680
680
  name?: string | undefined;
681
681
  /** Default `vertical`. */
682
682
  orientation?: "vertical" | "horizontal" | undefined;
683
+ /** Disables every option and (5.68) dims the legend, as Field does its label. */
683
684
  disabled?: boolean | undefined;
685
+ /** 5.68 (Chamber-OS 184): announce the error line when it appears (`aria-live="polite"`) — for an error shown as
686
+ * the user changes the group ("Choose at least one…" when the last box is unticked), not on submit. The error line
687
+ * stays in the page, empty, while there is none, so the first message is read too. Off by default. */
688
+ errorLive?: boolean | undefined;
684
689
  id?: string | undefined;
685
690
  className?: string | undefined;
686
691
  /** 44px rows (5.30, Chamber-OS 135), the one-line label centred: `true` below 640px or on a coarse pointer (touch
687
692
  * screens already get it), `'always'` at every width, also with a mouse. Default: as tall as the control and label. */
688
693
  touchHeight?: TouchHeight | undefined;
689
694
  }
695
+ /** 5.67 (Chamber-OS 183): RadioGroup's many-choice twin — one legend, one hint, one error over a set of checkboxes. */
696
+ export interface CheckboxGroupProps extends FieldProps {
697
+ options: ChoiceOption[];
698
+ /** The ticked options' values, in option order (not the order they were ticked); values not among the options are
699
+ * kept, after them. `required` shows the `*` and adds "(required)" to the group's name; "at least one" is yours to
700
+ * check — pass `error`. */
701
+ value?: string[] | undefined;
702
+ defaultValue?: string[] | undefined;
703
+ onChange?: ((values: string[]) => void) | undefined;
704
+ /** Each box's `name` for a native form (one entry per ticked value). Default: the group's id. */
705
+ name?: string | undefined;
706
+ /** Default `vertical`. */
707
+ orientation?: "vertical" | "horizontal" | undefined;
708
+ /** Disables every option and (5.68) dims the legend, as Field does its label. */
709
+ disabled?: boolean | undefined;
710
+ /** 5.68 (Chamber-OS 184): announce the error line when it appears (`aria-live="polite"`) — for an error shown as
711
+ * the user changes the group ("Choose at least one…" when the last box is unticked), not on submit. The error line
712
+ * stays in the page, empty, while there is none, so the first message is read too. Off by default. */
713
+ errorLive?: boolean | undefined;
714
+ id?: string | undefined;
715
+ className?: string | undefined;
716
+ /** 44px rows, as RadioGroup: `true` below 640px or on a coarse pointer, `'always'` at every width. */
717
+ touchHeight?: TouchHeight | undefined;
718
+ }
690
719
  export interface SwitchProps {
691
720
  label?: string | undefined;
692
721
  description?: string | undefined;
@@ -1908,6 +1937,12 @@ export interface FieldComponentProps extends Omit<FieldPropsPublic, "label"> {
1908
1937
  /** The control's id: the label points at it, and the hint/error ids derive from it. */
1909
1938
  id?: string | undefined;
1910
1939
  children?: React$1.ReactNode | undefined;
1940
+ /** 5.68 (Chamber-OS 184): announce the error line when it appears — for an error shown as the user types or ticks,
1941
+ * not on submit. The error `<p>` gets `aria-live="polite"` and stays in the page, empty, while there is no error, so
1942
+ * the first message is read too. Off by default: an error shown on submit, with focus moved to the field, is read
1943
+ * already, and a live line would read it twice. Your control should still point at `{id}-error` in its
1944
+ * `aria-describedby` while there is an error (TextField and the others do), so the message stays its description. */
1945
+ errorLive?: boolean | undefined;
1911
1946
  /** 5.31 (Chamber-OS addendum 41): a node between the label and the control, in a `.aura-field__addon` box with the
1912
1947
  * id `{id}-addon`. TextField and Textarea add that id to the input's `aria-describedby`; a custom control should too. */
1913
1948
  labelAddon?: React$1.ReactNode | undefined;
@@ -1933,6 +1968,7 @@ export declare const FilterSelect: React$1.ForwardRefExoticComponent<FilterSelec
1933
1968
  * complete, a preset is picked or the range is cleared; never on a lone start day. */
1934
1969
  export declare const FilterDateRange: React$1.ForwardRefExoticComponent<FilterDateRangeProps & React$1.RefAttributes<HTMLButtonElement>>;
1935
1970
  export declare const RadioGroup: React$1.ForwardRefExoticComponent<RadioGroupProps & React$1.RefAttributes<HTMLFieldSetElement>>;
1971
+ export declare const CheckboxGroup: React$1.ForwardRefExoticComponent<CheckboxGroupProps & React$1.RefAttributes<HTMLFieldSetElement>>;
1936
1972
  export declare const Switch: React$1.ForwardRefExoticComponent<SwitchProps & React$1.RefAttributes<HTMLButtonElement>>;
1937
1973
  /** One value, or with `multiple` any number (chips). Two call signatures so value/onChange are typed for each. */
1938
1974
  export interface ComboboxComponent {
@@ -2239,6 +2275,8 @@ export interface AuraStrings {
2239
2275
  statusUnknown: string;
2240
2276
  /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
2241
2277
  opensInNewTab: string;
2278
+ /** 5.67: read after a CheckboxGroup's legend when `required` (its `*` is hidden from screen readers). */
2279
+ required: string;
2242
2280
  /** 5.42: FilterBar's collapsed-filters button, read with its count ("Filters, 2 applied"). */
2243
2281
  filtersApplied: (n: number) => string;
2244
2282
  /** 5.42: closes FilterBar's "Filters" sheet. */
package/dist/index.d.ts CHANGED
@@ -680,13 +680,42 @@ export interface RadioGroupProps extends FieldProps {
680
680
  name?: string | undefined;
681
681
  /** Default `vertical`. */
682
682
  orientation?: "vertical" | "horizontal" | undefined;
683
+ /** Disables every option and (5.68) dims the legend, as Field does its label. */
683
684
  disabled?: boolean | undefined;
685
+ /** 5.68 (Chamber-OS 184): announce the error line when it appears (`aria-live="polite"`) — for an error shown as
686
+ * the user changes the group ("Choose at least one…" when the last box is unticked), not on submit. The error line
687
+ * stays in the page, empty, while there is none, so the first message is read too. Off by default. */
688
+ errorLive?: boolean | undefined;
684
689
  id?: string | undefined;
685
690
  className?: string | undefined;
686
691
  /** 44px rows (5.30, Chamber-OS 135), the one-line label centred: `true` below 640px or on a coarse pointer (touch
687
692
  * screens already get it), `'always'` at every width, also with a mouse. Default: as tall as the control and label. */
688
693
  touchHeight?: TouchHeight | undefined;
689
694
  }
695
+ /** 5.67 (Chamber-OS 183): RadioGroup's many-choice twin — one legend, one hint, one error over a set of checkboxes. */
696
+ export interface CheckboxGroupProps extends FieldProps {
697
+ options: ChoiceOption[];
698
+ /** The ticked options' values, in option order (not the order they were ticked); values not among the options are
699
+ * kept, after them. `required` shows the `*` and adds "(required)" to the group's name; "at least one" is yours to
700
+ * check — pass `error`. */
701
+ value?: string[] | undefined;
702
+ defaultValue?: string[] | undefined;
703
+ onChange?: ((values: string[]) => void) | undefined;
704
+ /** Each box's `name` for a native form (one entry per ticked value). Default: the group's id. */
705
+ name?: string | undefined;
706
+ /** Default `vertical`. */
707
+ orientation?: "vertical" | "horizontal" | undefined;
708
+ /** Disables every option and (5.68) dims the legend, as Field does its label. */
709
+ disabled?: boolean | undefined;
710
+ /** 5.68 (Chamber-OS 184): announce the error line when it appears (`aria-live="polite"`) — for an error shown as
711
+ * the user changes the group ("Choose at least one…" when the last box is unticked), not on submit. The error line
712
+ * stays in the page, empty, while there is none, so the first message is read too. Off by default. */
713
+ errorLive?: boolean | undefined;
714
+ id?: string | undefined;
715
+ className?: string | undefined;
716
+ /** 44px rows, as RadioGroup: `true` below 640px or on a coarse pointer, `'always'` at every width. */
717
+ touchHeight?: TouchHeight | undefined;
718
+ }
690
719
  export interface SwitchProps {
691
720
  label?: string | undefined;
692
721
  description?: string | undefined;
@@ -1908,6 +1937,12 @@ export interface FieldComponentProps extends Omit<FieldPropsPublic, "label"> {
1908
1937
  /** The control's id: the label points at it, and the hint/error ids derive from it. */
1909
1938
  id?: string | undefined;
1910
1939
  children?: React$1.ReactNode | undefined;
1940
+ /** 5.68 (Chamber-OS 184): announce the error line when it appears — for an error shown as the user types or ticks,
1941
+ * not on submit. The error `<p>` gets `aria-live="polite"` and stays in the page, empty, while there is no error, so
1942
+ * the first message is read too. Off by default: an error shown on submit, with focus moved to the field, is read
1943
+ * already, and a live line would read it twice. Your control should still point at `{id}-error` in its
1944
+ * `aria-describedby` while there is an error (TextField and the others do), so the message stays its description. */
1945
+ errorLive?: boolean | undefined;
1911
1946
  /** 5.31 (Chamber-OS addendum 41): a node between the label and the control, in a `.aura-field__addon` box with the
1912
1947
  * id `{id}-addon`. TextField and Textarea add that id to the input's `aria-describedby`; a custom control should too. */
1913
1948
  labelAddon?: React$1.ReactNode | undefined;
@@ -1933,6 +1968,7 @@ export declare const FilterSelect: React$1.ForwardRefExoticComponent<FilterSelec
1933
1968
  * complete, a preset is picked or the range is cleared; never on a lone start day. */
1934
1969
  export declare const FilterDateRange: React$1.ForwardRefExoticComponent<FilterDateRangeProps & React$1.RefAttributes<HTMLButtonElement>>;
1935
1970
  export declare const RadioGroup: React$1.ForwardRefExoticComponent<RadioGroupProps & React$1.RefAttributes<HTMLFieldSetElement>>;
1971
+ export declare const CheckboxGroup: React$1.ForwardRefExoticComponent<CheckboxGroupProps & React$1.RefAttributes<HTMLFieldSetElement>>;
1936
1972
  export declare const Switch: React$1.ForwardRefExoticComponent<SwitchProps & React$1.RefAttributes<HTMLButtonElement>>;
1937
1973
  /** One value, or with `multiple` any number (chips). Two call signatures so value/onChange are typed for each. */
1938
1974
  export interface ComboboxComponent {
@@ -2239,6 +2275,8 @@ export interface AuraStrings {
2239
2275
  statusUnknown: string;
2240
2276
  /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
2241
2277
  opensInNewTab: string;
2278
+ /** 5.67: read after a CheckboxGroup's legend when `required` (its `*` is hidden from screen readers). */
2279
+ required: string;
2242
2280
  /** 5.42: FilterBar's collapsed-filters button, read with its count ("Filters, 2 applied"). */
2243
2281
  filtersApplied: (n: number) => string;
2244
2282
  /** 5.42: closes FilterBar's "Filters" sheet. */
@@ -154,6 +154,7 @@ var sv = {
154
154
  statusOk: "OK",
155
155
  statusUnknown: "Ingen data",
156
156
  opensInNewTab: "\xF6ppnas i en ny flik",
157
+ required: "obligatoriskt",
157
158
  filtersApplied: function(n) {
158
159
  return "Filter, " + n.toLocaleString("sv-SE") + " aktiva";
159
160
  },
@@ -98,6 +98,8 @@ export interface AuraStrings {
98
98
  statusUnknown: string;
99
99
  /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
100
100
  opensInNewTab: string;
101
+ /** 5.67: read after a CheckboxGroup's legend when `required` (its `*` is hidden from screen readers). */
102
+ required: string;
101
103
  /** 5.42: FilterBar's collapsed-filters button, read with its count ("Filters, 2 applied"). */
102
104
  filtersApplied: (n: number) => string;
103
105
  /** 5.42: closes FilterBar's "Filters" sheet. */
@@ -98,6 +98,8 @@ export interface AuraStrings {
98
98
  statusUnknown: string;
99
99
  /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
100
100
  opensInNewTab: string;
101
+ /** 5.67: read after a CheckboxGroup's legend when `required` (its `*` is hidden from screen readers). */
102
+ required: string;
101
103
  /** 5.42: FilterBar's collapsed-filters button, read with its count ("Filters, 2 applied"). */
102
104
  filtersApplied: (n: number) => string;
103
105
  /** 5.42: closes FilterBar's "Filters" sheet. */
@@ -154,6 +154,7 @@ var th = {
154
154
  statusOk: "\u0E1B\u0E01\u0E15\u0E34",
155
155
  statusUnknown: "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
156
156
  opensInNewTab: "\u0E40\u0E1B\u0E34\u0E14\u0E43\u0E19\u0E41\u0E17\u0E47\u0E1A\u0E43\u0E2B\u0E21\u0E48",
157
+ required: "\u0E08\u0E33\u0E40\u0E1B\u0E47\u0E19",
157
158
  filtersApplied: function(n2) {
158
159
  return "\u0E15\u0E31\u0E27\u0E01\u0E23\u0E2D\u0E07, \u0E43\u0E0A\u0E49\u0E2D\u0E22\u0E39\u0E48 " + n2.toLocaleString("en") + " \u0E23\u0E32\u0E22\u0E01\u0E32\u0E23";
159
160
  },
@@ -98,6 +98,8 @@ export interface AuraStrings {
98
98
  statusUnknown: string;
99
99
  /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
100
100
  opensInNewTab: string;
101
+ /** 5.67: read after a CheckboxGroup's legend when `required` (its `*` is hidden from screen readers). */
102
+ required: string;
101
103
  /** 5.42: FilterBar's collapsed-filters button, read with its count ("Filters, 2 applied"). */
102
104
  filtersApplied: (n: number) => string;
103
105
  /** 5.42: closes FilterBar's "Filters" sheet. */
@@ -98,6 +98,8 @@ export interface AuraStrings {
98
98
  statusUnknown: string;
99
99
  /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
100
100
  opensInNewTab: string;
101
+ /** 5.67: read after a CheckboxGroup's legend when `required` (its `*` is hidden from screen readers). */
102
+ required: string;
101
103
  /** 5.42: FilterBar's collapsed-filters button, read with its count ("Filters, 2 applied"). */
102
104
  filtersApplied: (n: number) => string;
103
105
  /** 5.42: closes FilterBar's "Filters" sheet. */
@@ -345,6 +345,7 @@ var th = {
345
345
  statusOk: "\u0E1B\u0E01\u0E15\u0E34",
346
346
  statusUnknown: "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
347
347
  opensInNewTab: "\u0E40\u0E1B\u0E34\u0E14\u0E43\u0E19\u0E41\u0E17\u0E47\u0E1A\u0E43\u0E2B\u0E21\u0E48",
348
+ required: "\u0E08\u0E33\u0E40\u0E1B\u0E47\u0E19",
348
349
  filtersApplied: function(n3) {
349
350
  return "\u0E15\u0E31\u0E27\u0E01\u0E23\u0E2D\u0E07, \u0E43\u0E0A\u0E49\u0E2D\u0E22\u0E39\u0E48 " + n3.toLocaleString("en") + " \u0E23\u0E32\u0E22\u0E01\u0E32\u0E23";
350
351
  },
@@ -486,6 +487,7 @@ var sv = {
486
487
  statusOk: "OK",
487
488
  statusUnknown: "Ingen data",
488
489
  opensInNewTab: "\xF6ppnas i en ny flik",
490
+ required: "obligatoriskt",
489
491
  filtersApplied: function(n3) {
490
492
  return "Filter, " + n3.toLocaleString("sv-SE") + " aktiva";
491
493
  },
@@ -628,6 +630,7 @@ var STRINGS = {
628
630
  statusOk: "OK",
629
631
  statusUnknown: "No data",
630
632
  opensInNewTab: "opens in a new tab",
633
+ required: "required",
631
634
  filtersApplied: function(n3) {
632
635
  return "Filters, " + n3.toLocaleString("en") + " applied";
633
636
  },
@@ -432,6 +432,8 @@ export interface AuraStrings {
432
432
  statusUnknown: string;
433
433
  /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
434
434
  opensInNewTab: string;
435
+ /** 5.67: read after a CheckboxGroup's legend when `required` (its `*` is hidden from screen readers). */
436
+ required: string;
435
437
  /** 5.42: FilterBar's collapsed-filters button, read with its count ("Filters, 2 applied"). */
436
438
  filtersApplied: (n: number) => string;
437
439
  /** 5.42: closes FilterBar's "Filters" sheet. */
@@ -432,6 +432,8 @@ export interface AuraStrings {
432
432
  statusUnknown: string;
433
433
  /** Read after a Menu link item with `target="_blank"` (5.41): "Visit site (opens in a new tab)". */
434
434
  opensInNewTab: string;
435
+ /** 5.67: read after a CheckboxGroup's legend when `required` (its `*` is hidden from screen readers). */
436
+ required: string;
435
437
  /** 5.42: FilterBar's collapsed-filters button, read with its count ("Filters, 2 applied"). */
436
438
  filtersApplied: (n: number) => string;
437
439
  /** 5.42: closes FilterBar's "Filters" sheet. */
@@ -279,6 +279,7 @@ var th = {
279
279
  statusOk: "\u0E1B\u0E01\u0E15\u0E34",
280
280
  statusUnknown: "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
281
281
  opensInNewTab: "\u0E40\u0E1B\u0E34\u0E14\u0E43\u0E19\u0E41\u0E17\u0E47\u0E1A\u0E43\u0E2B\u0E21\u0E48",
282
+ required: "\u0E08\u0E33\u0E40\u0E1B\u0E47\u0E19",
282
283
  filtersApplied: function(n3) {
283
284
  return "\u0E15\u0E31\u0E27\u0E01\u0E23\u0E2D\u0E07, \u0E43\u0E0A\u0E49\u0E2D\u0E22\u0E39\u0E48 " + n3.toLocaleString("en") + " \u0E23\u0E32\u0E22\u0E01\u0E32\u0E23";
284
285
  },
@@ -420,6 +421,7 @@ var sv = {
420
421
  statusOk: "OK",
421
422
  statusUnknown: "Ingen data",
422
423
  opensInNewTab: "\xF6ppnas i en ny flik",
424
+ required: "obligatoriskt",
423
425
  filtersApplied: function(n3) {
424
426
  return "Filter, " + n3.toLocaleString("sv-SE") + " aktiva";
425
427
  },
@@ -562,6 +564,7 @@ var STRINGS = {
562
564
  statusOk: "OK",
563
565
  statusUnknown: "No data",
564
566
  opensInNewTab: "opens in a new tab",
567
+ required: "required",
565
568
  filtersApplied: function(n3) {
566
569
  return "Filters, " + n3.toLocaleString("en") + " applied";
567
570
  },
package/dist/styles.css CHANGED
@@ -525,6 +525,9 @@ a.aura-icon-btn { text-decoration: none; }
525
525
  .aura-field__hint, .aura-field__error { display: flex; align-items: flex-start; gap: var(--aura-space-1); margin: 0; font-size: max(12px, .75rem); line-height: 1.5; color: var(--aura-fg-secondary); }
526
526
  .aura-field__error { color: var(--aura-fg-danger); }
527
527
  .aura-field__error .aura-icon { margin-top: 2px; }
528
+ /* 5.68 (Chamber-OS 184): an `errorLive` error line waits in the page, empty, until there is an error. Out of the
529
+ * flow (an absolute child takes no gap) and clipped; the screen reader still has the live region. */
530
+ .aura-field__error:empty { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
528
531
  /* 5.31 (Chamber-OS addendum 41): TextField/Textarea `labelAddon`, between the label and the box, in the field's gap. */
529
532
  .aura-field__addon { min-width: 0; font-size: max(13px, .8125rem); line-height: 1.5; color: var(--aura-fg-primary); }
530
533
  .aura-field.is-disabled .aura-field__label { color: var(--aura-fg-secondary); }
@@ -608,6 +611,8 @@ a.aura-icon-btn { text-decoration: none; }
608
611
  .aura-radio:checked { border: 5px solid var(--aura-control-checked-bg); background: var(--aura-control-checked-fg); }
609
612
  .aura-radio:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
610
613
  .aura-radio-group.is-invalid .aura-radio:not(:checked) { border-color: var(--aura-border-danger); }
614
+ /* 5.67 (Chamber-OS 183): CheckboxGroup shares RadioGroup's legend, list and touch rows; an error edges the empty boxes. */
615
+ .aura-checkbox-group.is-invalid .aura-check__input:not(:checked) + .aura-check__box { border-color: var(--aura-border-danger); }
611
616
 
612
617
  .aura-switch-row { display: flex; align-items: flex-start; gap: var(--aura-space-3); font-family: var(--font-sans); }
613
618
  /* 5.10.1: disabled rows, on or off, are treated alike and stay readable — the label turns secondary, the description
@@ -527,6 +527,9 @@ a.aura-icon-btn { text-decoration: none; }
527
527
  .aura-field__hint, .aura-field__error { display: flex; align-items: flex-start; gap: var(--aura-space-1); margin: 0; font-size: max(12px, .75rem); line-height: 1.5; color: var(--aura-fg-secondary); }
528
528
  .aura-field__error { color: var(--aura-fg-danger); }
529
529
  .aura-field__error .aura-icon { margin-top: 2px; }
530
+ /* 5.68 (Chamber-OS 184): an `errorLive` error line waits in the page, empty, until there is an error. Out of the
531
+ * flow (an absolute child takes no gap) and clipped; the screen reader still has the live region. */
532
+ .aura-field__error:empty { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
530
533
  /* 5.31 (Chamber-OS addendum 41): TextField/Textarea `labelAddon`, between the label and the box, in the field's gap. */
531
534
  .aura-field__addon { min-width: 0; font-size: max(13px, .8125rem); line-height: 1.5; color: var(--aura-fg-primary); }
532
535
  .aura-field.is-disabled .aura-field__label { color: var(--aura-fg-secondary); }
@@ -610,6 +613,8 @@ a.aura-icon-btn { text-decoration: none; }
610
613
  .aura-radio:checked { border: 5px solid var(--aura-control-checked-bg); background: var(--aura-control-checked-fg); }
611
614
  .aura-radio:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
612
615
  .aura-radio-group.is-invalid .aura-radio:not(:checked) { border-color: var(--aura-border-danger); }
616
+ /* 5.67 (Chamber-OS 183): CheckboxGroup shares RadioGroup's legend, list and touch rows; an error edges the empty boxes. */
617
+ .aura-checkbox-group.is-invalid .aura-check__input:not(:checked) + .aura-check__box { border-color: var(--aura-border-danger); }
613
618
 
614
619
  .aura-switch-row { display: flex; align-items: flex-start; gap: var(--aura-space-3); font-family: var(--font-sans); }
615
620
  /* 5.10.1: disabled rows, on or off, are treated alike and stay readable — the label turns secondary, the description
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.66.0",
3
+ "version": "5.68.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",