@jirawatpyk/aura-react 5.25.0 → 5.26.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.
@@ -49,6 +49,8 @@ const Accordion = React.forwardRef(function Accordion2(props, ref) {
49
49
  {
50
50
  type: "button",
51
51
  id: bid,
52
+ "aria-labelledby": it.description ? bid + "-title" : void 0,
53
+ "aria-describedby": it.description ? bid + "-desc" : void 0,
52
54
  "aria-expanded": on,
53
55
  "aria-controls": pid,
54
56
  disabled: it.disabled,
@@ -57,9 +59,19 @@ const Accordion = React.forwardRef(function Accordion2(props, ref) {
57
59
  }
58
60
  },
59
61
  it.icon ? /* @__PURE__ */ React.createElement(Icon, { name: it.icon, className: "aura-accordion__lead" }) : null,
60
- /* @__PURE__ */ React.createElement("span", { className: "aura-accordion__title" }, it.title, it.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-accordion__desc" }, it.description) : null),
62
+ /* @__PURE__ */ React.createElement("span", { className: "aura-accordion__title" }, /* @__PURE__ */ React.createElement("span", { id: it.description ? bid + "-title" : void 0 }, it.title), it.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-accordion__desc", id: bid + "-desc" }, it.description) : null),
61
63
  /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconChevronDown, null), className: "aura-accordion__chevron" })
62
- )), /* @__PURE__ */ React.createElement("div", { id: pid, role: "region", "aria-labelledby": bid, className: "aura-accordion__panel", hidden: !on }, it.content));
64
+ )), /* @__PURE__ */ React.createElement(
65
+ "div",
66
+ {
67
+ id: pid,
68
+ role: "region",
69
+ "aria-labelledby": it.description ? bid + "-title" : bid,
70
+ className: "aura-accordion__panel",
71
+ hidden: !on
72
+ },
73
+ it.content
74
+ ));
63
75
  }));
64
76
  });
65
77
  export {
@@ -33,6 +33,7 @@ const Checkbox = React.forwardRef(function Checkbox2(props, ref) {
33
33
  "Checkbox `label` is only the accessible name: it is not shown. In 6.0 it will be shown beside the box, like Switch and TextField. For visible text now pass it as children; for a bare box (a table row) add `hideLabel`."
34
34
  );
35
35
  const descId = props.description ? (props.id || auto) + "-desc" : void 0;
36
+ const labelId = labelled && descId && !props["aria-label"] && !props["aria-labelledby"] ? (props.id || auto) + "-label" : void 0;
36
37
  const ha = props.hitArea;
37
38
  const hit = !labelled && ha && ha !== "box" ? ha === "target" ? { x: 4, y: 4 } : ha : null;
38
39
  return /* @__PURE__ */ React.createElement(
@@ -61,7 +62,8 @@ const Checkbox = React.forwardRef(function Checkbox2(props, ref) {
61
62
  tabIndex: props.tabIndex,
62
63
  disabled: props.disabled,
63
64
  "aria-describedby": cx(props["aria-describedby"], descId) || void 0,
64
- "aria-label": labelled ? void 0 : props.label,
65
+ "aria-label": (labelled ? void 0 : props.label) || props["aria-label"] || void 0,
66
+ "aria-labelledby": labelId || props["aria-labelledby"],
65
67
  onChange: function(e) {
66
68
  st[1](e.target.checked);
67
69
  }
@@ -69,7 +71,7 @@ const Checkbox = React.forwardRef(function Checkbox2(props, ref) {
69
71
  ),
70
72
  /* @__PURE__ */ React.createElement("span", { className: "aura-check__box", "aria-hidden": true }, props.indeterminate ? /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconMinus, null), size: 12, strokeWidth: 3 }) : on ? /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconCheck, null), size: 12, strokeWidth: 3 }) : null),
71
73
  !labelled && props.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-sr-only", id: descId }, props.description) : null,
72
- labelled ? /* @__PURE__ */ React.createElement("span", { className: "aura-check__text" }, /* @__PURE__ */ React.createElement("span", { className: "aura-check__label" }, text), props.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-check__desc", id: descId }, props.description) : null) : null
74
+ labelled ? /* @__PURE__ */ React.createElement("span", { className: "aura-check__text" }, /* @__PURE__ */ React.createElement("span", { className: "aura-check__label", id: labelId }, text), props.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-check__desc", id: descId }, props.description) : null) : null
73
75
  );
74
76
  });
75
77
  export {
@@ -234,6 +234,8 @@ const Combobox = React.forwardRef(
234
234
  id: optId(i),
235
235
  role: "option",
236
236
  "data-idx": i,
237
+ "aria-labelledby": o.description ? optId(i) + "-label" : void 0,
238
+ "aria-describedby": o.description ? optId(i) + "-desc" : void 0,
237
239
  "aria-selected": isSel,
238
240
  "aria-disabled": blocked || void 0,
239
241
  className: cx(
@@ -253,7 +255,7 @@ const Combobox = React.forwardRef(
253
255
  }
254
256
  },
255
257
  o.icon ? /* @__PURE__ */ React.createElement(Icon, { name: o.icon }) : null,
256
- /* @__PURE__ */ React.createElement("span", { className: "aura-combo__text" }, /* @__PURE__ */ React.createElement("span", { className: "aura-combo__label" }, o.label), o.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-combo__desc" }, o.description) : null),
258
+ /* @__PURE__ */ React.createElement("span", { className: "aura-combo__text" }, /* @__PURE__ */ React.createElement("span", { className: "aura-combo__label", id: o.description ? optId(i) + "-label" : void 0 }, o.label), o.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-combo__desc", id: optId(i) + "-desc" }, o.description) : null),
257
259
  isSel ? /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconCheck, null), className: "aura-combo__check" }) : null
258
260
  );
259
261
  }
@@ -202,6 +202,8 @@ function Command(props) {
202
202
  key: it.id,
203
203
  id: optId(n),
204
204
  role: "option",
205
+ "aria-labelledby": it.description ? optId(n) + "-label" + (it.shortcut ? " " + optId(n) + "-kbd" : "") : void 0,
206
+ "aria-describedby": it.description ? optId(n) + "-desc" : void 0,
205
207
  "aria-selected": n === active,
206
208
  "aria-disabled": it.disabled || void 0,
207
209
  className: cx(
@@ -220,8 +222,8 @@ function Command(props) {
220
222
  }
221
223
  },
222
224
  it.icon ? /* @__PURE__ */ React.createElement(Icon, { name: it.icon }) : null,
223
- /* @__PURE__ */ React.createElement("span", { className: "aura-command__text" }, /* @__PURE__ */ React.createElement("span", { className: "aura-command__label" }, it.label), it.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-command__desc" }, it.description) : null),
224
- it.shortcut ? /* @__PURE__ */ React.createElement("kbd", { className: "aura-command__kbd" }, it.shortcut) : null
225
+ /* @__PURE__ */ React.createElement("span", { className: "aura-command__text" }, /* @__PURE__ */ React.createElement("span", { className: "aura-command__label", id: it.description ? optId(n) + "-label" : void 0 }, it.label), it.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-command__desc", id: optId(n) + "-desc" }, it.description) : null),
226
+ it.shortcut ? /* @__PURE__ */ React.createElement("kbd", { className: "aura-command__kbd", id: it.description ? optId(n) + "-kbd" : void 0 }, it.shortcut) : null
225
227
  );
226
228
  })
227
229
  );
@@ -3,13 +3,23 @@ import * as React from "react";
3
3
  import { cx } from "./internal.js";
4
4
  const h = React.createElement;
5
5
  const Container = React.forwardRef(function Container2(props, ref) {
6
+ const attrs = {};
7
+ Object.keys(props).forEach(function(k) {
8
+ if (k === "id" || k === "lang" || k === "dir" || /^(aria|data)-/.test(k))
9
+ attrs[k] = props[k];
10
+ });
6
11
  return h(
7
12
  props.as || "div",
8
- {
13
+ Object.assign(attrs, {
9
14
  ref,
10
- className: cx("aura-container", props.size === "narrow" && "is-narrow", props.className),
15
+ className: cx(
16
+ "aura-container",
17
+ props.size === "narrow" && "is-narrow",
18
+ props.align === "start" && "is-start",
19
+ props.className
20
+ ),
11
21
  style: props.style
12
- },
22
+ }),
13
23
  props.children
14
24
  );
15
25
  });
@@ -1318,6 +1318,10 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
1318
1318
  "data-density": props.density,
1319
1319
  className: cx(
1320
1320
  "aura-table",
1321
+ /* 5.26 (Chamber-OS 127): bleed and bordered={false}; the outermost element carries aura-bleed. */
1322
+ props.bleed && "aura-bleed-frame",
1323
+ props.bleed && !levels.length && "aura-bleed",
1324
+ props.bordered === false && "aura-table--borderless",
1321
1325
  stacked && "aura-table--stacked",
1322
1326
  noCardSel && "aura-table--cards-nosel",
1323
1327
  scrolledX[0] && "is-scrolled-x",
@@ -1415,7 +1419,7 @@ const DataTableImpl = React.forwardRef(function DataTable(props, ref) {
1415
1419
  out
1416
1420
  );
1417
1421
  }
1418
- return /* @__PURE__ */ React.createElement("div", { ref, className: cx("aura-table-box", props.className) }, out);
1422
+ return /* @__PURE__ */ React.createElement("div", { ref, className: cx("aura-table-box", props.bleed && "aura-bleed", props.className) }, out);
1419
1423
  });
1420
1424
  const DataTable2 = DataTableImpl;
1421
1425
  export {
@@ -663,7 +663,9 @@ export {
663
663
  Calendar,
664
664
  DatePicker,
665
665
  DateRangePicker,
666
+ allowedDate,
666
667
  formatDate,
667
668
  parseDate2 as parseDate,
669
+ useCalendarPopover,
668
670
  useFormatDate
669
671
  };
@@ -0,0 +1,157 @@
1
+ 'use client';
2
+ import * as React from "react";
3
+ import { createPortal } from "react-dom";
4
+ import { Calendar, allowedDate, useCalendarPopover } from "./DatePicker.js";
5
+ import { Button } from "./Button.js";
6
+ import { Icon } from "./Icon.js";
7
+ import { IconChevronDown } from "./icons.js";
8
+ import { cx, trapTab, uid, useMaybeControlled, useMergedRef } from "./internal.js";
9
+ import { useAuraLocale } from "./locale.js";
10
+ import { dateText, defaultCalendar, formatDateRange } from "./dates.js";
11
+ const NONE = { start: null, end: null };
12
+ const FilterDateRange = React.forwardRef(
13
+ function FilterDateRange2(props, ref) {
14
+ const auto = uid(), id = props.id || auto, dialogId = id + "-cal";
15
+ const ctx = useAuraLocale(), locale = props.locale || ctx.locale || "en", calendar = props.calendar || ctx.calendar || defaultCalendar(locale), dt = dateText(locale);
16
+ const st = useMaybeControlled(props.value, props.defaultValue || NONE, props.onChange);
17
+ const raw = st[0] || NONE;
18
+ const v = raw.start && raw.end ? raw.start <= raw.end ? raw : { start: raw.end, end: raw.start } : NONE;
19
+ const draft = React.useState(null);
20
+ const boxRef = React.useRef(null), faceRef = React.useRef(null);
21
+ const pop = useCalendarPopover(boxRef);
22
+ const anyLabel = props.anyLabel || dt.anyTime;
23
+ const value = v.start && v.end ? formatDateRange(v.start, v.end, { locale, calendar }) : anyLabel;
24
+ const setFace = useMergedRef(ref, faceRef);
25
+ const limits = {
26
+ min: props.min,
27
+ max: props.max,
28
+ today: props.today,
29
+ timeZone: props.timeZone || ctx.timeZone,
30
+ isDateDisabled: props.isDateDisabled
31
+ };
32
+ function close() {
33
+ pop.setOpen(false);
34
+ draft[1](null);
35
+ if (faceRef.current) faceRef.current.focus();
36
+ }
37
+ function choose(r) {
38
+ if (r.start !== raw.start || r.end !== raw.end) st[1](r);
39
+ close();
40
+ }
41
+ function pick(iso) {
42
+ if (!iso) return;
43
+ if (!draft[0]) {
44
+ draft[1](iso);
45
+ return;
46
+ }
47
+ const a = draft[0];
48
+ choose(a <= iso ? { start: a, end: iso } : { start: iso, end: a });
49
+ }
50
+ const isAny = !v.start || !v.end;
51
+ const attrs = {};
52
+ Object.keys(props).forEach(function(k) {
53
+ if (k === "style" || /^(aria|data)-/.test(k) && k !== "aria-label")
54
+ attrs[k] = props[k];
55
+ });
56
+ const presetBtn = function(label, r, on, key) {
57
+ return /* @__PURE__ */ React.createElement(
58
+ Button,
59
+ {
60
+ key,
61
+ size: "sm",
62
+ variant: "ghost",
63
+ touchHeight: true,
64
+ disabled: !!r.start && !!r.end && !(allowedDate(r.start, limits) && allowedDate(r.end, limits)),
65
+ className: cx("aura-filterdate__preset", on && "is-selected"),
66
+ "aria-pressed": on,
67
+ onClick: function() {
68
+ choose(r);
69
+ }
70
+ },
71
+ label
72
+ );
73
+ };
74
+ const cal = pop.open && pop.mounted && pop.pos ? createPortal(
75
+ /* @__PURE__ */ React.createElement(
76
+ "div",
77
+ {
78
+ ref: pop.popRef,
79
+ id: dialogId,
80
+ role: "dialog",
81
+ "aria-modal": false,
82
+ "aria-label": props.label,
83
+ className: "aura-cal__popover aura-filterdate__pop",
84
+ style: Object.assign({}, pop.pos, {
85
+ maxHeight: window.innerHeight - (pop.pos.top != null ? pop.pos.top : pop.pos.bottom) - 8
86
+ }),
87
+ onKeyDown: function(e) {
88
+ if (e.key === "Escape") {
89
+ e.stopPropagation();
90
+ close();
91
+ } else trapTab(e, pop.popRef.current);
92
+ }
93
+ },
94
+ /* @__PURE__ */ React.createElement("div", { className: "aura-filterdate__presets" }, presetBtn(anyLabel, NONE, isAny, "__any"), (props.presets || []).map(function(p, i) {
95
+ return presetBtn(
96
+ p.label,
97
+ p.range,
98
+ !isAny && p.range.start === v.start && p.range.end === v.end,
99
+ "p" + i
100
+ );
101
+ })),
102
+ /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("p", { className: "aura-cal__hint", "aria-live": "polite" }, draft[0] ? dt.chooseEnd : dt.chooseStart), /* @__PURE__ */ React.createElement(
103
+ Calendar,
104
+ {
105
+ range: true,
106
+ locale,
107
+ calendar,
108
+ weekStartsOn: props.weekStartsOn,
109
+ min: props.min,
110
+ max: props.max,
111
+ timeZone: props.timeZone,
112
+ today: props.today,
113
+ isDateDisabled: props.isDateDisabled,
114
+ start: draft[0] || v.start,
115
+ end: draft[0] ? null : v.end,
116
+ focus: draft[0] || v.start,
117
+ footer: false,
118
+ onSelect: pick
119
+ }
120
+ ))
121
+ ),
122
+ document.body
123
+ ) : null;
124
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
125
+ "div",
126
+ {
127
+ ref: boxRef,
128
+ className: cx("aura-filterselect", pop.open && "is-open", props.disabled && "is-disabled", props.className)
129
+ },
130
+ /* @__PURE__ */ React.createElement(
131
+ "button",
132
+ {
133
+ ...attrs,
134
+ ref: setFace,
135
+ id,
136
+ type: "button",
137
+ className: "aura-filterselect__face",
138
+ disabled: props.disabled,
139
+ "aria-label": props["aria-label"] || props.label + ": " + value,
140
+ "aria-haspopup": "dialog",
141
+ "aria-expanded": pop.open,
142
+ "aria-controls": pop.open ? dialogId : void 0,
143
+ onClick: function() {
144
+ pop.setOpen(!pop.open);
145
+ draft[1](null);
146
+ }
147
+ },
148
+ /* @__PURE__ */ React.createElement("span", { className: "aura-filterselect__name" }, props.label),
149
+ /* @__PURE__ */ React.createElement("span", { className: "aura-filterselect__value" }, value),
150
+ /* @__PURE__ */ React.createElement(Icon, { name: /* @__PURE__ */ React.createElement(IconChevronDown, null), className: "aura-filterselect__chevron" })
151
+ )
152
+ ), cal);
153
+ }
154
+ );
155
+ export {
156
+ FilterDateRange
157
+ };
@@ -34,8 +34,9 @@ const RadioGroup = React.forwardRef(function RadioGroup2(props, ref) {
34
34
  disabled: props.disabled
35
35
  },
36
36
  props.label ? /* @__PURE__ */ React.createElement("legend", { className: "aura-field__label" }, props.label, props.required ? /* @__PURE__ */ React.createElement("span", { className: "aura-field__req", "aria-hidden": true }, " *") : null) : null,
37
- /* @__PURE__ */ React.createElement("div", { className: cx("aura-radio-group__list", props.orientation === "horizontal" && "is-horizontal") }, (props.options || []).map(function(o) {
37
+ /* @__PURE__ */ React.createElement("div", { className: cx("aura-radio-group__list", props.orientation === "horizontal" && "is-horizontal") }, (props.options || []).map(function(o, i) {
38
38
  const v = typeof o === "object" ? o : { value: o, label: o };
39
+ const oid = v.description ? id + "-opt-" + i : "";
39
40
  return /* @__PURE__ */ React.createElement("label", { key: v.value, className: cx("aura-choice", v.disabled && "is-disabled") }, /* @__PURE__ */ React.createElement(
40
41
  "input",
41
42
  {
@@ -45,12 +46,14 @@ const RadioGroup = React.forwardRef(function RadioGroup2(props, ref) {
45
46
  value: v.value,
46
47
  disabled: v.disabled,
47
48
  required: props.required || void 0,
49
+ "aria-labelledby": oid ? oid + "-label" : void 0,
50
+ "aria-describedby": oid ? oid + "-desc" : void 0,
48
51
  checked: st[0] === v.value,
49
52
  onChange: function() {
50
53
  st[1](v.value);
51
54
  }
52
55
  }
53
- ), /* @__PURE__ */ React.createElement("span", { className: "aura-choice__text" }, /* @__PURE__ */ React.createElement("span", { className: "aura-choice__label" }, v.label), v.description ? /* @__PURE__ */ React.createElement("span", { className: "aura-choice__desc" }, v.description) : null));
56
+ ), /* @__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));
54
57
  })),
55
58
  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
56
59
  );
package/dist/esm/Table.js CHANGED
@@ -55,6 +55,9 @@ const Table = React.forwardRef(function Table2(props, ref) {
55
55
  stackBelow,
56
56
  align,
57
57
  bordered,
58
+ bleed,
59
+ stickyHeader,
60
+ maxHeight,
58
61
  stackStyle,
59
62
  rowHeight,
60
63
  className,
@@ -62,6 +65,11 @@ const Table = React.forwardRef(function Table2(props, ref) {
62
65
  ...rest
63
66
  } = props;
64
67
  const cards = !!stackBelow && stackStyle === "cards";
68
+ if (maxHeight != null && caption == null && !rest["aria-label"] && !rest["aria-labelledby"])
69
+ devWarnOnce(
70
+ "tbl-max-name",
71
+ "Table maxHeight: the box scrolls, so keyboard users get it as a focusable region \u2014 give the table a `caption` (captionHidden keeps it for screen readers) or an `aria-label` to name it."
72
+ );
65
73
  const labels = stackBelow ? headerLabels(children) : null;
66
74
  if (labels && !labels.length)
67
75
  devWarnOnce(
@@ -73,15 +81,19 @@ const Table = React.forwardRef(function Table2(props, ref) {
73
81
  const capId = uid();
74
82
  const wrap = React.useRef(null);
75
83
  const sc = React.useState(false), scrolls = sc[0];
84
+ const wide = React.useState(false);
76
85
  useIsoLayoutEffect(function() {
77
86
  const el = wrap.current;
78
87
  if (!el || typeof ResizeObserver === "undefined") return;
79
88
  function check() {
80
- sc[1](el.scrollWidth > el.clientWidth + 1);
89
+ const sideways = el.scrollWidth > el.clientWidth + 1;
90
+ wide[1](sideways);
91
+ sc[1](sideways || el.scrollHeight > el.clientHeight + 1);
81
92
  }
82
93
  check();
83
94
  const ro = new ResizeObserver(check);
84
95
  ro.observe(el);
96
+ if (el.firstElementChild) ro.observe(el.firstElementChild);
85
97
  return function() {
86
98
  ro.disconnect();
87
99
  };
@@ -90,11 +102,23 @@ const Table = React.forwardRef(function Table2(props, ref) {
90
102
  "div",
91
103
  {
92
104
  ref: wrap,
93
- className: cx("aura-tbl-wrap", stackBelow && "is-stackable", bordered === false && "is-flush"),
105
+ className: cx(
106
+ "aura-tbl-wrap",
107
+ stackBelow && "is-stackable",
108
+ bordered === false && "is-flush",
109
+ /* 5.26 (Chamber-OS 127): the frame that bleeds; the outermost element carries aura-bleed. */
110
+ bleed && "aura-bleed-frame",
111
+ bleed && !cards && "aura-bleed",
112
+ /* 5.26 (Chamber-OS 129): stickyHeader pins to the page, or inside the box when it has a maxHeight. */
113
+ stickyHeader && (maxHeight != null ? "is-sticky-box" : "is-sticky-page"),
114
+ maxHeight != null && "has-max",
115
+ wide[0] && "is-wide"
116
+ ),
117
+ style: maxHeight != null ? { maxHeight: typeof maxHeight === "number" ? maxHeight + "px" : maxHeight } : void 0,
94
118
  "data-density": density || pageDensity,
95
119
  tabIndex: scrolls ? 0 : void 0,
96
- role: scrolls && (caption != null || rest["aria-label"]) ? "region" : void 0,
97
- "aria-labelledby": scrolls && caption != null ? capId : void 0,
120
+ role: scrolls && (caption != null || rest["aria-label"] || rest["aria-labelledby"]) ? "region" : void 0,
121
+ "aria-labelledby": scrolls ? caption != null ? capId : rest["aria-labelledby"] : void 0,
98
122
  "aria-label": scrolls && caption == null ? rest["aria-label"] : void 0
99
123
  },
100
124
  /* @__PURE__ */ React.createElement(
@@ -117,7 +141,7 @@ const Table = React.forwardRef(function Table2(props, ref) {
117
141
  labels ? /* @__PURE__ */ React.createElement(StackLabels.Provider, { value: labels }, children) : outer ? /* @__PURE__ */ React.createElement(StackLabels.Provider, { value: null }, children) : children
118
142
  )
119
143
  );
120
- return cards ? /* @__PURE__ */ React.createElement("div", { className: "aura-tbl-cards aura-tbl-cards--" + stackBelow }, table) : table;
144
+ return cards ? /* @__PURE__ */ React.createElement("div", { className: cx("aura-tbl-cards aura-tbl-cards--" + stackBelow, bleed && "aura-bleed") }, table) : table;
121
145
  });
122
146
  function section(tag, cls) {
123
147
  const C = React.forwardRef(function TableSection(props, ref) {
package/dist/esm/dates.js CHANGED
@@ -56,6 +56,7 @@ const DATE_TEXT = {
56
56
  clearDates: "\u0E25\u0E49\u0E32\u0E07\u0E0A\u0E48\u0E27\u0E07\u0E27\u0E31\u0E19\u0E17\u0E35\u0E48",
57
57
  chooseStart: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E27\u0E31\u0E19\u0E40\u0E23\u0E34\u0E48\u0E21\u0E15\u0E49\u0E19",
58
58
  chooseEnd: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E27\u0E31\u0E19\u0E2A\u0E34\u0E49\u0E19\u0E2A\u0E38\u0E14",
59
+ anyTime: "\u0E17\u0E38\u0E01\u0E0A\u0E48\u0E27\u0E07\u0E40\u0E27\u0E25\u0E32",
59
60
  dateUnavailable: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E27\u0E31\u0E19\u0E17\u0E35\u0E48\u0E19\u0E35\u0E49\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49 \u0E25\u0E2D\u0E07\u0E40\u0E1B\u0E34\u0E14\u0E1B\u0E0F\u0E34\u0E17\u0E34\u0E19\u0E14\u0E39\u0E27\u0E31\u0E19\u0E17\u0E35\u0E48\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E44\u0E14\u0E49"
60
61
  },
61
62
  en: {
@@ -74,6 +75,7 @@ const DATE_TEXT = {
74
75
  clearDates: "Clear dates",
75
76
  chooseStart: "Choose the start date",
76
77
  chooseEnd: "Choose the end date",
78
+ anyTime: "Any time",
77
79
  dateUnavailable: "That date can't be chosen. Open the calendar to see the dates you can pick."
78
80
  },
79
81
  sv: {
@@ -92,6 +94,7 @@ const DATE_TEXT = {
92
94
  clearDates: "Rensa datumen",
93
95
  chooseStart: "V\xE4lj startdatum",
94
96
  chooseEnd: "V\xE4lj slutdatum",
97
+ anyTime: "N\xE4r som helst",
95
98
  dateUnavailable: "Det datumet g\xE5r inte att v\xE4lja. \xD6ppna kalendern f\xF6r att se vilka datum som g\xE5r."
96
99
  }
97
100
  };
@@ -116,6 +119,16 @@ function formatDate(iso, opts) {
116
119
  const loc = o.locale || "en";
117
120
  return fmt(localeTag(loc, o.calendar || defaultCalendar(loc)), f, d).replace(ERA, "");
118
121
  }
122
+ function formatDateRange(start, end, opts) {
123
+ const o = opts || {}, a = fromISO(start), b = fromISO(end);
124
+ if (!a || !b) return "";
125
+ if (start > end) return formatDateRange(end, start, opts);
126
+ const loc = o.locale || "en", tag = localeTag(loc, o.calendar || defaultCalendar(loc)), f = PRESETS.short;
127
+ const k = tag + JSON.stringify(f);
128
+ if (!fmtCache[k]) fmtCache[k] = new Intl.DateTimeFormat(tag, f);
129
+ const F = fmtCache[k];
130
+ return F.formatRange ? F.formatRange(a, b).replace(/\s?(พ\.ศ\.|\bBE\b)\s?/g, " ").replace(/[\s\u2009\u202f]*[–-][\s\u2009\u202f]*/g, " \u2013 ").trim() : start === end ? formatDate(start, o) : formatDate(start, o) + " \u2013 " + formatDate(end, o);
131
+ }
119
132
  let MONTHS = null;
120
133
  function monthIndex(word) {
121
134
  if (!MONTHS) {
@@ -188,6 +201,7 @@ export {
188
201
  fmt,
189
202
  fmtCache,
190
203
  formatDate,
204
+ formatDateRange,
191
205
  fromISO,
192
206
  localeTag,
193
207
  makeDate,
package/dist/esm/index.js CHANGED
@@ -11,6 +11,7 @@ import { TextField } from "./TextField.js";
11
11
  import { Textarea } from "./Textarea.js";
12
12
  import { Select } from "./Select.js";
13
13
  import { FilterSelect } from "./FilterSelect.js";
14
+ import { FilterDateRange } from "./FilterDateRange.js";
14
15
  import { RadioGroup } from "./RadioGroup.js";
15
16
  import { Switch } from "./Switch.js";
16
17
  import { Combobox, defaultFilter } from "./Combobox.js";
@@ -88,6 +89,7 @@ export {
88
89
  Field,
89
90
  FileUpload,
90
91
  FilterBar,
92
+ FilterDateRange,
91
93
  FilterSelect,
92
94
  FormErrorSummary,
93
95
  Grid,
package/dist/index.d.cts CHANGED
@@ -236,6 +236,14 @@ export interface DataTableProps<Row extends Record<string, any> = Record<string,
236
236
  density?: "comfortable" | "compact" | undefined;
237
237
  /** Table width in px below which rows render as stacked cards (phones). Try 640. It follows the table's own width, not the window. Since 4.20 the cards are the same markup as the grid, laid out by a container query, so any width is right before hydration and each row is in the HTML once. With `height` (virtual rows) the server can only send the first screenful; the rest of the cards arrive on hydration. */
238
238
  stackBelow?: number | undefined;
239
+ /** Edge to edge inside a Card (5.26, Chamber-OS 127): as a direct child of a Card's content, the table spans the
240
+ * card's full inner width — no side borders, no radius — keeping its header band and top rule; as the card's last
241
+ * content (no footer, nothing after it) it drops its bottom rule and the card's radius closes it. Below the Card's
242
+ * `flushBelow` width, and outside a Card, it does nothing. */
243
+ bleed?: boolean | undefined;
244
+ /** `false` drops the frame — border and radius — keeping the header band and the 24px gutter, for a table that sits
245
+ * in a section without bleeding (5.26). Default `true`. */
246
+ bordered?: boolean | undefined;
239
247
  className?: string | undefined;
240
248
  }
241
249
  /** An AURA icon name, or any icon element (e.g. `<Building />` from lucide-react). AURA sizes it and hides it from screen readers. */
@@ -300,7 +308,9 @@ export interface CheckboxProps extends Omit<React$1.InputHTMLAttributes<HTMLInpu
300
308
  hideLabel?: boolean | undefined;
301
309
  /** The visible label beside the box. */
302
310
  children?: React$1.ReactNode | undefined;
303
- /** Second line under the visible label, linked by `aria-describedby` after any id you pass there (5.11). */
311
+ /** Second line under the visible label, linked by `aria-describedby` after any id you pass there (5.11). Since 5.26
312
+ * it is not part of the name: the box is named by the visible label alone, or by your `aria-label` /
313
+ * `aria-labelledby` (Chamber-OS 125). */
304
314
  description?: React$1.ReactNode | undefined;
305
315
  onChange?: ((checked: boolean) => void) | undefined;
306
316
  disabled?: boolean | undefined;
@@ -468,6 +478,7 @@ export interface CommandItem {
468
478
  /** Items with the same group are listed together under its heading, in first-seen order. */
469
479
  group?: string | undefined;
470
480
  icon?: IconInput | undefined;
481
+ /** A second line; read after the item's name (label and shortcut), not as part of it (5.26). */
471
482
  description?: string | undefined;
472
483
  /** Extra words that find it ("invoice" → Billing). */
473
484
  keywords?: string[] | undefined;
@@ -542,6 +553,8 @@ export interface FilterSelectProps extends Omit<React$1.SelectHTMLAttributes<HTM
542
553
  * readers keep the option's own text. */
543
554
  allLabel?: string | undefined;
544
555
  }
556
+ /** A RadioGroup option. `description` is a second line under the label; since 5.26 the radio is named by `label`
557
+ * alone and the description is read after it (`aria-describedby`), also when the option is disabled (Chamber-OS 125). */
545
558
  export type ChoiceOption = string | {
546
559
  value: string;
547
560
  label: string;
@@ -841,7 +854,7 @@ export interface DropdownMenuProps {
841
854
  export interface ComboboxOption {
842
855
  value: string;
843
856
  label: string;
844
- /** Second line in the list; also searched. */
857
+ /** Second line in the list; also searched. Read after the option's name, not as part of it (5.26). */
845
858
  description?: string | undefined;
846
859
  /** Extra search terms (English name, phone, code…). */
847
860
  keywords?: string[] | undefined;
@@ -1035,6 +1048,39 @@ export interface DateRange {
1035
1048
  start: ISODate | null;
1036
1049
  end: ISODate | null;
1037
1050
  }
1051
+ /** A FilterDateRange preset: a name and the range it sets (5.26). */
1052
+ export interface DateRangePreset {
1053
+ label: string;
1054
+ range: DateRange;
1055
+ }
1056
+ /** A compact date-range filter for FilterBar (5.26, Chamber-OS 128): "Submitted Any time ▾", one click to the range
1057
+ * calendar. Dates as DateRangePicker: `locale` / `calendar` from the provider (Thai shows Buddhist-era years), `min`,
1058
+ * `max`, `timeZone`, `weekStartsOn`. */
1059
+ export interface FilterDateRangeProps extends DateDisplayOptions, Pick<React$1.HTMLAttributes<HTMLButtonElement>, "style">, React$1.AriaAttributes, DataAttributes {
1060
+ /** The filter's name: first on the face ("Submitted"), the popover's name, and the start of the face's accessible
1061
+ * name ("Submitted: Any time"). */
1062
+ label: string;
1063
+ value?: DateRange | undefined;
1064
+ defaultValue?: DateRange | undefined;
1065
+ /** Runs once a range is complete, a preset is picked, or "Any time" clears it — never on a lone start day, and
1066
+ * not when the same range is picked again. There is no form field: write the range to the URL or state here. */
1067
+ onChange?: ((value: DateRange) => void) | undefined;
1068
+ /** Choices beside the calendar (Last 7 days, This month…), each setting a whole range; one that reaches past
1069
+ * `min` / `max` or onto an `isDateDisabled` day is shown disabled. */
1070
+ presets?: DateRangePreset[] | undefined;
1071
+ /** The empty value and the choice that clears it. Default "Any time" in the date locale. */
1072
+ anyLabel?: string | undefined;
1073
+ min?: ISODate | "today" | undefined;
1074
+ max?: ISODate | "today" | undefined;
1075
+ isDateDisabled?: ((iso: ISODate) => boolean) | undefined;
1076
+ weekStartsOn?: 0 | 1 | undefined;
1077
+ timeZone?: string | undefined;
1078
+ /** Today, given outright (ISO); wins over `timeZone`. */
1079
+ today?: ISODate | undefined;
1080
+ disabled?: boolean | undefined;
1081
+ id?: string | undefined;
1082
+ className?: string | undefined;
1083
+ }
1038
1084
  export interface DateRangePickerProps extends DateFieldProps {
1039
1085
  value?: DateRange | undefined;
1040
1086
  defaultValue?: DateRange | undefined;
@@ -1149,6 +1195,22 @@ export interface TableProps extends Omit<React$1.TableHTMLAttributes<HTMLTableEl
1149
1195
  /** `false` (5.13) drops the frame — border, radius, background — and the outer cells' side padding, so the table
1150
1196
  * lines up with the content around it, e.g. flush inside a Card under its heading. Default `true`. */
1151
1197
  bordered?: boolean | undefined;
1198
+ /** Edge to edge inside a Card (5.26, Chamber-OS 127): as a direct child of a Card's content, the table spans the
1199
+ * card's full inner width — no side borders, no radius — keeping its header band and top rule, and its outer
1200
+ * cells' 24px padding keeps the text level with the card's content. As the card's last content it drops its
1201
+ * bottom rule and the card's radius closes it. Below the Card's `flushBelow` width, and outside a Card, it does
1202
+ * nothing. With `bordered={false}` too, the outer cells take the card's padding while it bleeds. */
1203
+ bleed?: boolean | undefined;
1204
+ /** Keep the header row in view while the rows scroll (5.26, Chamber-OS 129), with its band, its bottom rule and
1205
+ * above the body. Without `maxHeight` it pins to the page's scroll, under an AppShell's top bar
1206
+ * (`--aura-shell-bar-height`; set `--aura-table-sticky-top` for another offset). A table wider than its box
1207
+ * scrolls sideways instead and its header can't pin to the page then: give it `maxHeight`. Inside your own scroll
1208
+ * container within an AppShell set `--aura-table-sticky-top: 0px` or use `maxHeight`. With `maxHeight` the box
1209
+ * scrolls both ways and the header pins to its top. One header row. Stacked rows (`stackBelow`) have no visible header, so it
1210
+ * does nothing there. Default off. */
1211
+ stickyHeader?: boolean | undefined;
1212
+ /** Caps the table's box (px, or any CSS length such as `60vh`); the rows scroll inside it. (5.26) */
1213
+ maxHeight?: number | string | undefined;
1152
1214
  /** How stacked rows look (5.15, Chamber-OS 85): `list` (default) — one frame, rows divided by rules; `cards` —
1153
1215
  * each row its own framed card, spaced like DataTable's cards, with no frame around them. From the `stackBelow`
1154
1216
  * width up the table is unchanged. The table then sits in one more `div` (`.aura-tbl-cards`). */
@@ -1421,6 +1483,7 @@ export interface PaginationProps {
1421
1483
  export interface AccordionItem {
1422
1484
  id: string;
1423
1485
  title: React$1.ReactNode;
1486
+ /** A second line under the title; read as the header button's description, not its name (5.26). */
1424
1487
  description?: React$1.ReactNode | undefined;
1425
1488
  content: React$1.ReactNode;
1426
1489
  icon?: IconInput | undefined;
@@ -1548,6 +1611,10 @@ export declare const Select: React$1.ForwardRefExoticComponent<SelectProps & Rea
1548
1611
  /** A compact filter for FilterBar (5.12): a small button reading "Status All ▾" that opens Select's list. The name
1549
1612
  * is the accessible name, the chosen option its value; forms, refs and the keyboard work as in Select. */
1550
1613
  export declare const FilterSelect: React$1.ForwardRefExoticComponent<FilterSelectProps & React$1.RefAttributes<HTMLSelectElement>>;
1614
+ /** A compact date-range filter for FilterBar (5.26, Chamber-OS 128): a face like FilterSelect's — "Submitted Any
1615
+ * time ▾" — that opens the range calendar, with optional presets, in one click. `onChange` runs once a range is
1616
+ * complete, a preset is picked or the range is cleared; never on a lone start day. */
1617
+ export declare const FilterDateRange: React$1.ForwardRefExoticComponent<FilterDateRangeProps & React$1.RefAttributes<HTMLButtonElement>>;
1551
1618
  export declare const RadioGroup: React$1.ForwardRefExoticComponent<RadioGroupProps & React$1.RefAttributes<HTMLFieldSetElement>>;
1552
1619
  export declare const Switch: React$1.ForwardRefExoticComponent<SwitchProps & React$1.RefAttributes<HTMLButtonElement>>;
1553
1620
  /** One value, or with `multiple` any number (chips). Two call signatures so value/onChange are typed for each. */
@@ -1644,11 +1711,17 @@ export declare const Avatar: React$1.ForwardRefExoticComponent<AvatarProps & Rea
1644
1711
  export declare const Stack: React$1.ForwardRefExoticComponent<StackProps & React$1.RefAttributes<HTMLElement>>;
1645
1712
  /** Grid — equal columns. columns may be responsive ({ base: 1, md: 2, lg: 3 }), or use minItemWidth to fit as many as fit. */
1646
1713
  export declare const Grid: React$1.ForwardRefExoticComponent<GridProps & React$1.RefAttributes<HTMLElement>>;
1647
- /** Centred page column. */
1648
- export interface ContainerProps {
1714
+ /** Centred page column. To name it (`aria-label`), render a landmark with `as="section"` (or `main`, `nav`): a
1715
+ * plain `div` may not carry a name. */
1716
+ export interface ContainerProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "lang" | "dir">, React$1.AriaAttributes, DataAttributes {
1649
1717
  /** `narrow` caps it at aura-container-narrow (720px). Default `default` (1280px). */
1650
1718
  size?: "default" | "narrow" | undefined;
1719
+ /** `start` puts the column at the start edge (left; right in RTL) instead of centring it — a form board beside
1720
+ * the page's start (5.26, Chamber-OS 126). Default `center`. */
1721
+ align?: "center" | "start" | undefined;
1651
1722
  as?: keyof React$1.JSX.IntrinsicElements | undefined;
1723
+ /** Utilities that set `max-width` or `margin` (e.g. `max-w-[672px] mx-0`) are supported with `styles.layer.css`,
1724
+ * where a utility beats `.aura-container` (5.26). */
1652
1725
  className?: string | undefined;
1653
1726
  style?: React$1.CSSProperties | undefined;
1654
1727
  children?: React$1.ReactNode | undefined;