@jirawatpyk/aura-react 5.12.0 → 5.14.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/dist/index.d.cts CHANGED
@@ -89,6 +89,13 @@ export interface DataTableColumn<Row extends Record<string, any> = Record<string
89
89
  hideBelow?: number | "sm" | "md" | "lg" | "xl" | undefined;
90
90
  /** Row actions (a DropdownMenu or IconButton). In stacked cards it sits top-right instead of in the field list. Give it an empty label. */
91
91
  actions?: boolean | undefined;
92
+ /** Its place in a stacked card (5.13): `'hide'` leaves it out of the card (the grid keeps it), `'title'` / `'pill'`
93
+ * make it the card's title or the pill beside it (instead of the first column / first pill column), `'field'` a
94
+ * label/value field. Default: today's rule. */
95
+ card?: "hide" | "field" | "title" | "pill" | undefined;
96
+ /** The order of fields in a stacked card (5.13), lowest first; the grid's column order is unchanged. Fields
97
+ * without one sort by their column index (0-based). Screen readers and arrow keys follow the grid's order. */
98
+ cardOrder?: number | undefined;
92
99
  /** `end` right-aligns header and cells (amounts, counts) and uses tabular figures. Default `start`. */
93
100
  align?: "start" | "end" | undefined;
94
101
  }
@@ -178,6 +185,9 @@ export interface DataTableProps<Row extends Record<string, any> = Record<string,
178
185
  onRowActivate?: RowCallback<void, Row> | undefined;
179
186
  /** Fixed height in px: sticky header, and only the rows in view are rendered. */
180
187
  height?: number | undefined;
188
+ /** Stacked cards (`stackBelow`) without the row checkboxes and the select-all box (5.13). The grid keeps them and
189
+ * the selection is kept; Space doesn't change it while the cards show. */
190
+ hideSelectionInCards?: boolean | undefined;
181
191
  /** `'auto'` (5.11): rows grow to fit content that wraps (two badges, a long name); cells stay vertically centred and
182
192
  * rows keep at least the density's row height. Needs every row in the DOM, so it is ignored with `height`
183
193
  * (virtualized rows are one fixed height). Default: one fixed-height line per row, long text ends in an ellipsis. */
@@ -387,6 +397,7 @@ export interface FilterBarProps {
387
397
  onSearchChange?: ((value: string) => void) | undefined;
388
398
  /** ms to wait after the last keystroke. Default 300. */
389
399
  searchDelay?: number | undefined;
400
+ /** The search field's name. Default "Search". */
390
401
  searchLabel?: string | undefined;
391
402
  searchPlaceholder?: string | undefined;
392
403
  /** Filter controls beside the search: Select, SegmentedControl, a Popover of options… */
@@ -649,6 +660,9 @@ export interface TabsProps {
649
660
  variant?: "underline" | "segmented" | undefined;
650
661
  /** With `variant="segmented"`: stretch the track to the full width, tabs sharing it equally. (5.10) */
651
662
  fullWidth?: boolean | undefined;
663
+ /** Link tabs: what the current link is (5.14). `page` (default) for routes; `location` for links to sections of
664
+ * this page (`#contacts`). */
665
+ current?: "page" | "location" | undefined;
652
666
  }
653
667
  export interface NavItem {
654
668
  id: string;
@@ -985,6 +999,8 @@ export interface AppShellProps {
985
999
  /** A BottomNav for phones (4.19). Shown below its `hideFrom` breakpoint; the content keeps room for it, and a
986
1000
  * viewport ActionBar sits on top of it. With a `bottomNav` and no `nav`, there is no menu button. */
987
1001
  bottomNav?: React$1.ReactElement | undefined;
1002
+ /** `false` (5.14): `<main>` has no padding, for pages whose containers own the page padding and column. */
1003
+ contentPadding?: boolean | undefined;
988
1004
  className?: string | undefined;
989
1005
  }
990
1006
  export interface SeparatorProps {
@@ -996,7 +1012,7 @@ export interface SeparatorProps {
996
1012
  spacing?: 1 | 2 | 3 | 4 | 5 | 6 | 8 | undefined;
997
1013
  className?: string | undefined;
998
1014
  }
999
- export interface TableProps extends Omit<React$1.TableHTMLAttributes<HTMLTableElement>, "className"> {
1015
+ export interface TableProps extends Omit<React$1.TableHTMLAttributes<HTMLTableElement>, "className" | "align"> {
1000
1016
  /** The table's name (a `<caption>`). Give every table one; `captionHidden` keeps it for screen readers only. */
1001
1017
  caption?: React$1.ReactNode | undefined;
1002
1018
  captionHidden?: boolean | undefined;
@@ -1006,6 +1022,11 @@ export interface TableProps extends Omit<React$1.TableHTMLAttributes<HTMLTableEl
1006
1022
  * cell shows its column's header as a label: a `Td`'s `label`, else the text of the matching `Th` in `THead`.
1007
1023
  * Done in CSS (a container query), so the server's HTML is already right; table semantics are kept. */
1008
1024
  stackBelow?: "sm" | "md" | undefined;
1025
+ /** `middle` centres every body and footer cell on its row (5.13); default `top`, so wrapped text starts level. */
1026
+ align?: "top" | "middle" | undefined;
1027
+ /** `false` (5.13) drops the frame — border, radius, background — and the outer cells' side padding, so the table
1028
+ * lines up with the content around it, e.g. flush inside a Card under its heading. Default `true`. */
1029
+ bordered?: boolean | undefined;
1009
1030
  className?: string | undefined;
1010
1031
  children?: React$1.ReactNode | undefined;
1011
1032
  }
@@ -1026,6 +1047,10 @@ export interface TableCellProps extends Omit<React$1.TdHTMLAttributes<HTMLTableC
1026
1047
  scope?: "col" | "row" | "colgroup" | "rowgroup" | undefined;
1027
1048
  /** The label this cell shows when its table is stacked (`stackBelow`, 5.8). Default: the matching header's text. */
1028
1049
  label?: string | undefined;
1050
+ /** Its place in a stacked row (5.13), on a Td or a row header (`Th scope="row"`). `title` takes the first line,
1051
+ * without a label; `action` sits at the end of that line at its natural size; `field` (default) is a labelled field,
1052
+ * two to a line under them. */
1053
+ card?: "title" | "action" | "field" | undefined;
1029
1054
  className?: string | undefined;
1030
1055
  }
1031
1056
  export interface ActionBarProps {
@@ -1102,6 +1127,9 @@ export interface StatProps {
1102
1127
  /** Makes the whole card a link or a button (drill-down). */
1103
1128
  href?: string | undefined;
1104
1129
  onClick?: (() => void) | undefined;
1130
+ /** The label as a heading of this level (5.14), when the tile titles its section. Not with `onClick` (a heading
1131
+ * can't sit in a button); a link is fine. Default: a plain label. */
1132
+ headingLevel?: 2 | 3 | 4 | 5 | 6 | undefined;
1105
1133
  className?: string | undefined;
1106
1134
  }
1107
1135
  export interface TimePickerProps extends FieldProps {
@@ -1201,7 +1229,7 @@ export interface SkeletonProps {
1201
1229
  size?: number | undefined;
1202
1230
  className?: string | undefined;
1203
1231
  }
1204
- export interface EmptyStateProps {
1232
+ export interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
1205
1233
  title: React$1.ReactNode;
1206
1234
  description?: React$1.ReactNode | undefined;
1207
1235
  icon?: IconInput | undefined;
@@ -1209,7 +1237,12 @@ export interface EmptyStateProps {
1209
1237
  action?: React$1.ReactNode | undefined;
1210
1238
  size?: "sm" | "md" | undefined;
1211
1239
  bordered?: boolean | undefined;
1212
- headingLevel?: 2 | 3 | 4 | 5 | 6 | undefined;
1240
+ /** `danger` (5.13) for a failure — the data couldn't load: the danger tint, a danger-coloured icon, and a solid
1241
+ * danger frame with `bordered`. It stays quiet; pass `role="alert"` if it must interrupt. Default `neutral`. */
1242
+ tone?: "neutral" | "danger" | undefined;
1243
+ /** The title's heading level (default 3); `false` (5.14) makes it a paragraph, for a card or list whose outline
1244
+ * mustn't change. EmptyState has no live-region role unless you pass `role`. */
1245
+ headingLevel?: 2 | 3 | 4 | 5 | 6 | false | undefined;
1213
1246
  className?: string | undefined;
1214
1247
  }
1215
1248
  export interface PaginationProps {
package/dist/index.d.ts CHANGED
@@ -89,6 +89,13 @@ export interface DataTableColumn<Row extends Record<string, any> = Record<string
89
89
  hideBelow?: number | "sm" | "md" | "lg" | "xl" | undefined;
90
90
  /** Row actions (a DropdownMenu or IconButton). In stacked cards it sits top-right instead of in the field list. Give it an empty label. */
91
91
  actions?: boolean | undefined;
92
+ /** Its place in a stacked card (5.13): `'hide'` leaves it out of the card (the grid keeps it), `'title'` / `'pill'`
93
+ * make it the card's title or the pill beside it (instead of the first column / first pill column), `'field'` a
94
+ * label/value field. Default: today's rule. */
95
+ card?: "hide" | "field" | "title" | "pill" | undefined;
96
+ /** The order of fields in a stacked card (5.13), lowest first; the grid's column order is unchanged. Fields
97
+ * without one sort by their column index (0-based). Screen readers and arrow keys follow the grid's order. */
98
+ cardOrder?: number | undefined;
92
99
  /** `end` right-aligns header and cells (amounts, counts) and uses tabular figures. Default `start`. */
93
100
  align?: "start" | "end" | undefined;
94
101
  }
@@ -178,6 +185,9 @@ export interface DataTableProps<Row extends Record<string, any> = Record<string,
178
185
  onRowActivate?: RowCallback<void, Row> | undefined;
179
186
  /** Fixed height in px: sticky header, and only the rows in view are rendered. */
180
187
  height?: number | undefined;
188
+ /** Stacked cards (`stackBelow`) without the row checkboxes and the select-all box (5.13). The grid keeps them and
189
+ * the selection is kept; Space doesn't change it while the cards show. */
190
+ hideSelectionInCards?: boolean | undefined;
181
191
  /** `'auto'` (5.11): rows grow to fit content that wraps (two badges, a long name); cells stay vertically centred and
182
192
  * rows keep at least the density's row height. Needs every row in the DOM, so it is ignored with `height`
183
193
  * (virtualized rows are one fixed height). Default: one fixed-height line per row, long text ends in an ellipsis. */
@@ -387,6 +397,7 @@ export interface FilterBarProps {
387
397
  onSearchChange?: ((value: string) => void) | undefined;
388
398
  /** ms to wait after the last keystroke. Default 300. */
389
399
  searchDelay?: number | undefined;
400
+ /** The search field's name. Default "Search". */
390
401
  searchLabel?: string | undefined;
391
402
  searchPlaceholder?: string | undefined;
392
403
  /** Filter controls beside the search: Select, SegmentedControl, a Popover of options… */
@@ -649,6 +660,9 @@ export interface TabsProps {
649
660
  variant?: "underline" | "segmented" | undefined;
650
661
  /** With `variant="segmented"`: stretch the track to the full width, tabs sharing it equally. (5.10) */
651
662
  fullWidth?: boolean | undefined;
663
+ /** Link tabs: what the current link is (5.14). `page` (default) for routes; `location` for links to sections of
664
+ * this page (`#contacts`). */
665
+ current?: "page" | "location" | undefined;
652
666
  }
653
667
  export interface NavItem {
654
668
  id: string;
@@ -985,6 +999,8 @@ export interface AppShellProps {
985
999
  /** A BottomNav for phones (4.19). Shown below its `hideFrom` breakpoint; the content keeps room for it, and a
986
1000
  * viewport ActionBar sits on top of it. With a `bottomNav` and no `nav`, there is no menu button. */
987
1001
  bottomNav?: React$1.ReactElement | undefined;
1002
+ /** `false` (5.14): `<main>` has no padding, for pages whose containers own the page padding and column. */
1003
+ contentPadding?: boolean | undefined;
988
1004
  className?: string | undefined;
989
1005
  }
990
1006
  export interface SeparatorProps {
@@ -996,7 +1012,7 @@ export interface SeparatorProps {
996
1012
  spacing?: 1 | 2 | 3 | 4 | 5 | 6 | 8 | undefined;
997
1013
  className?: string | undefined;
998
1014
  }
999
- export interface TableProps extends Omit<React$1.TableHTMLAttributes<HTMLTableElement>, "className"> {
1015
+ export interface TableProps extends Omit<React$1.TableHTMLAttributes<HTMLTableElement>, "className" | "align"> {
1000
1016
  /** The table's name (a `<caption>`). Give every table one; `captionHidden` keeps it for screen readers only. */
1001
1017
  caption?: React$1.ReactNode | undefined;
1002
1018
  captionHidden?: boolean | undefined;
@@ -1006,6 +1022,11 @@ export interface TableProps extends Omit<React$1.TableHTMLAttributes<HTMLTableEl
1006
1022
  * cell shows its column's header as a label: a `Td`'s `label`, else the text of the matching `Th` in `THead`.
1007
1023
  * Done in CSS (a container query), so the server's HTML is already right; table semantics are kept. */
1008
1024
  stackBelow?: "sm" | "md" | undefined;
1025
+ /** `middle` centres every body and footer cell on its row (5.13); default `top`, so wrapped text starts level. */
1026
+ align?: "top" | "middle" | undefined;
1027
+ /** `false` (5.13) drops the frame — border, radius, background — and the outer cells' side padding, so the table
1028
+ * lines up with the content around it, e.g. flush inside a Card under its heading. Default `true`. */
1029
+ bordered?: boolean | undefined;
1009
1030
  className?: string | undefined;
1010
1031
  children?: React$1.ReactNode | undefined;
1011
1032
  }
@@ -1026,6 +1047,10 @@ export interface TableCellProps extends Omit<React$1.TdHTMLAttributes<HTMLTableC
1026
1047
  scope?: "col" | "row" | "colgroup" | "rowgroup" | undefined;
1027
1048
  /** The label this cell shows when its table is stacked (`stackBelow`, 5.8). Default: the matching header's text. */
1028
1049
  label?: string | undefined;
1050
+ /** Its place in a stacked row (5.13), on a Td or a row header (`Th scope="row"`). `title` takes the first line,
1051
+ * without a label; `action` sits at the end of that line at its natural size; `field` (default) is a labelled field,
1052
+ * two to a line under them. */
1053
+ card?: "title" | "action" | "field" | undefined;
1029
1054
  className?: string | undefined;
1030
1055
  }
1031
1056
  export interface ActionBarProps {
@@ -1102,6 +1127,9 @@ export interface StatProps {
1102
1127
  /** Makes the whole card a link or a button (drill-down). */
1103
1128
  href?: string | undefined;
1104
1129
  onClick?: (() => void) | undefined;
1130
+ /** The label as a heading of this level (5.14), when the tile titles its section. Not with `onClick` (a heading
1131
+ * can't sit in a button); a link is fine. Default: a plain label. */
1132
+ headingLevel?: 2 | 3 | 4 | 5 | 6 | undefined;
1105
1133
  className?: string | undefined;
1106
1134
  }
1107
1135
  export interface TimePickerProps extends FieldProps {
@@ -1201,7 +1229,7 @@ export interface SkeletonProps {
1201
1229
  size?: number | undefined;
1202
1230
  className?: string | undefined;
1203
1231
  }
1204
- export interface EmptyStateProps {
1232
+ export interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
1205
1233
  title: React$1.ReactNode;
1206
1234
  description?: React$1.ReactNode | undefined;
1207
1235
  icon?: IconInput | undefined;
@@ -1209,7 +1237,12 @@ export interface EmptyStateProps {
1209
1237
  action?: React$1.ReactNode | undefined;
1210
1238
  size?: "sm" | "md" | undefined;
1211
1239
  bordered?: boolean | undefined;
1212
- headingLevel?: 2 | 3 | 4 | 5 | 6 | undefined;
1240
+ /** `danger` (5.13) for a failure — the data couldn't load: the danger tint, a danger-coloured icon, and a solid
1241
+ * danger frame with `bordered`. It stays quiet; pass `role="alert"` if it must interrupt. Default `neutral`. */
1242
+ tone?: "neutral" | "danger" | undefined;
1243
+ /** The title's heading level (default 3); `false` (5.14) makes it a paragraph, for a card or list whose outline
1244
+ * mustn't change. EmptyState has no live-region role unless you pass `role`. */
1245
+ headingLevel?: 2 | 3 | 4 | 5 | 6 | false | undefined;
1213
1246
  className?: string | undefined;
1214
1247
  }
1215
1248
  export interface PaginationProps {
@@ -31,11 +31,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var server_exports = {};
32
32
  __export(server_exports, {
33
33
  Alert: () => ServerAlert,
34
+ Avatar: () => ServerAvatar,
34
35
  Badge: () => ServerBadge,
35
36
  Card: () => ServerCard,
36
37
  EmptyState: () => ServerEmptyState,
37
38
  Icon: () => Icon,
38
39
  STRINGS: () => STRINGS,
40
+ Stat: () => ServerStat,
39
41
  StatusPill: () => ServerStatusPill,
40
42
  brandScale: () => scale,
41
43
  breakpoints: () => breakpoints,
@@ -1015,6 +1017,7 @@ var Icon = React2.forwardRef(function Icon2(props, ref) {
1015
1017
  var iconNames = Object.keys(map);
1016
1018
 
1017
1019
  // src/icons.ts
1020
+ var IconMinus = /* @__PURE__ */ defineIcon("minus", [["path", { d: "M5 12h14" }]]);
1018
1021
  var IconCircleAlert = /* @__PURE__ */ defineIcon("circle-alert", [
1019
1022
  ["circle", { cx: "12", cy: "12", r: "10" }],
1020
1023
  ["line", { x1: "12", x2: "12", y1: "8", y2: "12" }],
@@ -1057,6 +1060,14 @@ var IconInbox = /* @__PURE__ */ defineIcon("inbox", [
1057
1060
  { d: "M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" }
1058
1061
  ]
1059
1062
  ]);
1063
+ var IconTrendingUp = /* @__PURE__ */ defineIcon("trending-up", [
1064
+ ["path", { d: "M16 7h6v6" }],
1065
+ ["path", { d: "m22 7-8.5 8.5-5-5L2 17" }]
1066
+ ]);
1067
+ var IconTrendingDown = /* @__PURE__ */ defineIcon("trending-down", [
1068
+ ["path", { d: "M16 17h6v-6" }],
1069
+ ["path", { d: "m22 17-8.5-8.5-5 5L2 7" }]
1070
+ ]);
1060
1071
 
1061
1072
  // src/display.tsx
1062
1073
  var h2 = React3.createElement;
@@ -1147,12 +1158,31 @@ function badgeElement(props, ref) {
1147
1158
  );
1148
1159
  }
1149
1160
  function emptyStateElement(props, ref) {
1150
- const HT = "h" + (props.headingLevel || 3);
1161
+ const HT = props.headingLevel === false ? "p" : "h" + (props.headingLevel || 3);
1162
+ const rest = omit(props, [
1163
+ "title",
1164
+ "description",
1165
+ "icon",
1166
+ "action",
1167
+ "size",
1168
+ "bordered",
1169
+ "headingLevel",
1170
+ "tone",
1171
+ "className",
1172
+ "children"
1173
+ ]);
1151
1174
  return /* @__PURE__ */ React3.createElement(
1152
1175
  "div",
1153
1176
  {
1177
+ ...rest,
1154
1178
  ref,
1155
- className: cx("aura-empty", props.size === "sm" && "is-sm", props.bordered && "is-bordered", props.className)
1179
+ className: cx(
1180
+ "aura-empty",
1181
+ props.size === "sm" && "is-sm",
1182
+ props.bordered && "is-bordered",
1183
+ props.tone === "danger" && "is-danger",
1184
+ props.className
1185
+ )
1156
1186
  },
1157
1187
  /* @__PURE__ */ React3.createElement("span", { className: "aura-empty__icon", "aria-hidden": true }, /* @__PURE__ */ React3.createElement(Icon, { name: props.icon || /* @__PURE__ */ React3.createElement(IconInbox, null), size: props.size === "sm" ? "md" : "lg" })),
1158
1188
  /* @__PURE__ */ React3.createElement(HT, { className: "aura-empty__title" }, props.title),
@@ -1160,6 +1190,66 @@ function emptyStateElement(props, ref) {
1160
1190
  props.action ? /* @__PURE__ */ React3.createElement("div", { className: "aura-empty__action" }, props.action) : null
1161
1191
  );
1162
1192
  }
1193
+ function statElement(props, ref, Link) {
1194
+ const ch = props.change;
1195
+ const dir = ch && (ch.direction || "flat");
1196
+ const tone2 = ch && (ch.tone || (dir === "up" ? "positive" : dir === "down" ? "negative" : "neutral"));
1197
+ const v = props.value;
1198
+ const numeric = typeof v === "number" || typeof v === "string" && /\d/.test(v) && /^[\s\d.,:+\-\u2212%()\u0E3F$\u20AC\u00A3\u00A5kKmMbB]+$/.test(v.replace(/\b[A-Z]{3}\b/g, ""));
1199
+ const Tag = props.href ? Link : props.onClick ? "button" : "div";
1200
+ const interactive = !!(props.href || props.onClick);
1201
+ if (props.headingLevel && Tag === "button")
1202
+ devWarnOnce(
1203
+ "stat-heading-button",
1204
+ "Stat `headingLevel` is ignored with `onClick`: a heading can\u2019t sit in a button. Use `href`, or put the heading outside."
1205
+ );
1206
+ const LabelTag = props.headingLevel && Tag !== "button" ? "h" + props.headingLevel : "span";
1207
+ const HeadTag = LabelTag === "span" ? "span" : "div";
1208
+ return /* @__PURE__ */ React3.createElement(
1209
+ Tag,
1210
+ {
1211
+ ref,
1212
+ className: cx("aura-stat", interactive && "is-interactive", props.loading && "is-loading", props.className),
1213
+ href: props.href,
1214
+ onClick: props.onClick,
1215
+ type: Tag === "button" ? "button" : void 0,
1216
+ "aria-busy": props.loading || void 0
1217
+ },
1218
+ /* @__PURE__ */ React3.createElement(HeadTag, { className: "aura-stat__head" }, /* @__PURE__ */ React3.createElement(LabelTag, { className: "aura-stat__label" }, props.label), props.icon ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__icon" }, /* @__PURE__ */ React3.createElement(Icon, { name: props.icon })) : null),
1219
+ props.loading ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__value" }, /* @__PURE__ */ React3.createElement("span", { className: "aura-skel aura-stat__skel" })) : /* @__PURE__ */ React3.createElement("span", { className: cx("aura-stat__value", numeric && "is-numeric") }, props.value, props.unit ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__unit" }, props.unit) : null),
1220
+ ch && !props.loading || props.caption ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__foot" }, ch && !props.loading ? /* @__PURE__ */ React3.createElement("span", { className: cx("aura-stat__change", "is-" + tone2) }, /* @__PURE__ */ React3.createElement(
1221
+ Icon,
1222
+ {
1223
+ name: dir === "up" ? /* @__PURE__ */ React3.createElement(IconTrendingUp, null) : dir === "down" ? /* @__PURE__ */ React3.createElement(IconTrendingDown, null) : /* @__PURE__ */ React3.createElement(IconMinus, null),
1224
+ size: 14
1225
+ }
1226
+ ), /* @__PURE__ */ React3.createElement("span", null, ch.value)) : null, ch && ch.label && !props.loading ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__caption" }, ch.label) : null, props.caption ? /* @__PURE__ */ React3.createElement("span", { className: "aura-stat__caption" }, props.caption) : null) : null
1227
+ );
1228
+ }
1229
+ var AVATAR_TONES = ["progress", "ready", "neutral", "warning"];
1230
+ function initials(name) {
1231
+ const parts = String(name || "?").trim().split(/\s+/);
1232
+ return ((parts[0] || "?")[0] + (parts.length > 1 ? parts[parts.length - 1][0] : parts[0][1] || "")).toUpperCase();
1233
+ }
1234
+ function avatarElement(props, ref, broken, onError) {
1235
+ const size = props.size || "md";
1236
+ let hash = 0;
1237
+ String(props.name || "").split("").forEach(function(ch) {
1238
+ hash = hash * 31 + ch.charCodeAt(0) >>> 0;
1239
+ });
1240
+ const tone2 = AVATAR_TONES[hash % AVATAR_TONES.length];
1241
+ return /* @__PURE__ */ React3.createElement(
1242
+ "span",
1243
+ {
1244
+ ref,
1245
+ className: cx("aura-avatar", "aura-avatar--" + size, "aura-avatar--" + tone2, props.className),
1246
+ role: "img",
1247
+ "aria-label": props.name + (props.status ? ", " + props.status : "")
1248
+ },
1249
+ props.src && broken !== props.src ? /* @__PURE__ */ React3.createElement("img", { key: props.src, src: props.src, alt: "", onError }) : /* @__PURE__ */ React3.createElement("span", { "aria-hidden": true }, initials(props.name)),
1250
+ props.status === "online" ? /* @__PURE__ */ React3.createElement("span", { className: "aura-avatar__status", "aria-hidden": true }) : null
1251
+ );
1252
+ }
1163
1253
  function buttonClass(opts = {}) {
1164
1254
  return cx(
1165
1255
  "aura-btn",
@@ -1185,3 +1275,9 @@ function ServerBadge(props) {
1185
1275
  function ServerEmptyState(props) {
1186
1276
  return emptyStateElement(props, void 0);
1187
1277
  }
1278
+ function ServerStat(props) {
1279
+ return statElement(omit(props, ["onClick"]), void 0, props.linkComponent || "a");
1280
+ }
1281
+ function ServerAvatar(props) {
1282
+ return avatarElement(props, void 0, null, void 0);
1283
+ }
@@ -81,6 +81,15 @@ export interface CardProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "ti
81
81
  /** id for the title element; the card is then labelled by it (aria-labelledby). */
82
82
  titleId?: string | undefined;
83
83
  }
84
+ export interface AvatarProps {
85
+ /** Accessible name; also gives the initials and a stable colour. */
86
+ name: string;
87
+ src?: string | undefined;
88
+ /** `sm` 24 · `md` 32 (default) · `lg` 40. */
89
+ size?: "sm" | "md" | "lg" | undefined;
90
+ status?: "online" | undefined;
91
+ className?: string | undefined;
92
+ }
84
93
  /** ISO date string, `YYYY-MM-DD` (Gregorian — the era is display only). */
85
94
  export type ISODate = string;
86
95
  export interface DateDisplayOptions {
@@ -89,6 +98,35 @@ export interface DateDisplayOptions {
89
98
  /** `buddhist` (พ.ศ.; default for th) or `gregory` (ค.ศ.; default for en and sv). */
90
99
  calendar?: "buddhist" | "gregory" | undefined;
91
100
  }
101
+ export interface StatChange {
102
+ /** Shown as written, e.g. "+12%" or "−3". */
103
+ value: React$1.ReactNode;
104
+ direction?: "up" | "down" | "flat" | undefined;
105
+ /** Default: up = positive, down = negative. Set it when a rise is bad (cancellations, wait time). */
106
+ tone?: "positive" | "negative" | "neutral" | undefined;
107
+ /** e.g. "vs last month". */
108
+ label?: React$1.ReactNode | undefined;
109
+ }
110
+ export interface StatProps {
111
+ /** Your router's link (e.g. `Link` from `next/link`) for this component; defaults to AuraProvider's `linkComponent`, then `<a>`. */
112
+ linkComponent?: React$1.ElementType | undefined;
113
+ label: React$1.ReactNode;
114
+ value?: React$1.ReactNode | undefined;
115
+ /** Small unit after the value ("งาน", "คน", "%"). */
116
+ unit?: React$1.ReactNode | undefined;
117
+ change?: StatChange | undefined;
118
+ caption?: React$1.ReactNode | undefined;
119
+ icon?: IconInput | undefined;
120
+ /** Skeleton in place of the value. */
121
+ loading?: boolean | undefined;
122
+ /** Makes the whole card a link or a button (drill-down). */
123
+ href?: string | undefined;
124
+ onClick?: (() => void) | undefined;
125
+ /** The label as a heading of this level (5.14), when the tile titles its section. Not with `onClick` (a heading
126
+ * can't sit in a button); a link is fine. Default: a plain label. */
127
+ headingLevel?: 2 | 3 | 4 | 5 | 6 | undefined;
128
+ className?: string | undefined;
129
+ }
92
130
  export type Tone = "neutral" | "accent" | "success" | "warning" | "danger";
93
131
  export interface BadgeProps extends React$1.HTMLAttributes<HTMLSpanElement> {
94
132
  tone?: Tone | undefined;
@@ -96,7 +134,7 @@ export interface BadgeProps extends React$1.HTMLAttributes<HTMLSpanElement> {
96
134
  variant?: "soft" | "solid" | "outline" | undefined;
97
135
  icon?: IconInput | undefined;
98
136
  }
99
- export interface EmptyStateProps {
137
+ export interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
100
138
  title: React$1.ReactNode;
101
139
  description?: React$1.ReactNode | undefined;
102
140
  icon?: IconInput | undefined;
@@ -104,7 +142,12 @@ export interface EmptyStateProps {
104
142
  action?: React$1.ReactNode | undefined;
105
143
  size?: "sm" | "md" | undefined;
106
144
  bordered?: boolean | undefined;
107
- headingLevel?: 2 | 3 | 4 | 5 | 6 | undefined;
145
+ /** `danger` (5.13) for a failure — the data couldn't load: the danger tint, a danger-coloured icon, and a solid
146
+ * danger frame with `bordered`. It stays quiet; pass `role="alert"` if it must interrupt. Default `neutral`. */
147
+ tone?: "neutral" | "danger" | undefined;
148
+ /** The title's heading level (default 3); `false` (5.14) makes it a paragraph, for a card or list whose outline
149
+ * mustn't change. EmptyState has no live-region role unless you pass `role`. */
150
+ headingLevel?: 2 | 3 | 4 | 5 | 6 | false | undefined;
108
151
  className?: string | undefined;
109
152
  }
110
153
  export interface ThemeOptions {
@@ -302,6 +345,11 @@ declare function ServerCard(props: CardProps): React$1.ReactElement;
302
345
  declare function ServerStatusPill(props: StatusPillProps): React$1.ReactElement;
303
346
  declare function ServerBadge(props: BadgeProps): React$1.ReactElement;
304
347
  declare function ServerEmptyState(props: EmptyStateProps): React$1.ReactElement;
348
+ /** Stat for Server Components (5.14): no `onClick` (a button needs the client); `href` renders `linkComponent`, else `<a>`. */
349
+ declare function ServerStat(props: Omit<StatProps, "onClick">): React$1.ReactElement;
350
+ /** Avatar for Server Components (5.14): initials and colour. Falling back to the initials when an image fails needs the
351
+ * client, so give a server avatar a `src` you know loads, or none. */
352
+ declare function ServerAvatar(props: AvatarProps): React$1.ReactElement;
305
353
  /** Makes icon names as strings work: `registerIcons(allIcons)` once at startup, with `allIcons` from
306
354
  * `@jirawatpyk/aura-react/icons`, or only the icons you use (`registerIcons([IconUsers, IconPlus])`). In 5.x every
307
355
  * name already works and this only says you are ready for 6.0 (it silences the notice); in 6.0 it is required. Call it in the module
@@ -312,9 +360,11 @@ export declare const Icon: React$1.ForwardRefExoticComponent<IconProps & React$1
312
360
 
313
361
  export {
314
362
  ServerAlert as Alert,
363
+ ServerAvatar as Avatar,
315
364
  ServerBadge as Badge,
316
365
  ServerCard as Card,
317
366
  ServerEmptyState as EmptyState,
367
+ ServerStat as Stat,
318
368
  ServerStatusPill as StatusPill,
319
369
  scale as brandScale,
320
370
  toneFor as statusTone,
@@ -81,6 +81,15 @@ export interface CardProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "ti
81
81
  /** id for the title element; the card is then labelled by it (aria-labelledby). */
82
82
  titleId?: string | undefined;
83
83
  }
84
+ export interface AvatarProps {
85
+ /** Accessible name; also gives the initials and a stable colour. */
86
+ name: string;
87
+ src?: string | undefined;
88
+ /** `sm` 24 · `md` 32 (default) · `lg` 40. */
89
+ size?: "sm" | "md" | "lg" | undefined;
90
+ status?: "online" | undefined;
91
+ className?: string | undefined;
92
+ }
84
93
  /** ISO date string, `YYYY-MM-DD` (Gregorian — the era is display only). */
85
94
  export type ISODate = string;
86
95
  export interface DateDisplayOptions {
@@ -89,6 +98,35 @@ export interface DateDisplayOptions {
89
98
  /** `buddhist` (พ.ศ.; default for th) or `gregory` (ค.ศ.; default for en and sv). */
90
99
  calendar?: "buddhist" | "gregory" | undefined;
91
100
  }
101
+ export interface StatChange {
102
+ /** Shown as written, e.g. "+12%" or "−3". */
103
+ value: React$1.ReactNode;
104
+ direction?: "up" | "down" | "flat" | undefined;
105
+ /** Default: up = positive, down = negative. Set it when a rise is bad (cancellations, wait time). */
106
+ tone?: "positive" | "negative" | "neutral" | undefined;
107
+ /** e.g. "vs last month". */
108
+ label?: React$1.ReactNode | undefined;
109
+ }
110
+ export interface StatProps {
111
+ /** Your router's link (e.g. `Link` from `next/link`) for this component; defaults to AuraProvider's `linkComponent`, then `<a>`. */
112
+ linkComponent?: React$1.ElementType | undefined;
113
+ label: React$1.ReactNode;
114
+ value?: React$1.ReactNode | undefined;
115
+ /** Small unit after the value ("งาน", "คน", "%"). */
116
+ unit?: React$1.ReactNode | undefined;
117
+ change?: StatChange | undefined;
118
+ caption?: React$1.ReactNode | undefined;
119
+ icon?: IconInput | undefined;
120
+ /** Skeleton in place of the value. */
121
+ loading?: boolean | undefined;
122
+ /** Makes the whole card a link or a button (drill-down). */
123
+ href?: string | undefined;
124
+ onClick?: (() => void) | undefined;
125
+ /** The label as a heading of this level (5.14), when the tile titles its section. Not with `onClick` (a heading
126
+ * can't sit in a button); a link is fine. Default: a plain label. */
127
+ headingLevel?: 2 | 3 | 4 | 5 | 6 | undefined;
128
+ className?: string | undefined;
129
+ }
92
130
  export type Tone = "neutral" | "accent" | "success" | "warning" | "danger";
93
131
  export interface BadgeProps extends React$1.HTMLAttributes<HTMLSpanElement> {
94
132
  tone?: Tone | undefined;
@@ -96,7 +134,7 @@ export interface BadgeProps extends React$1.HTMLAttributes<HTMLSpanElement> {
96
134
  variant?: "soft" | "solid" | "outline" | undefined;
97
135
  icon?: IconInput | undefined;
98
136
  }
99
- export interface EmptyStateProps {
137
+ export interface EmptyStateProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, "title" | "children"> {
100
138
  title: React$1.ReactNode;
101
139
  description?: React$1.ReactNode | undefined;
102
140
  icon?: IconInput | undefined;
@@ -104,7 +142,12 @@ export interface EmptyStateProps {
104
142
  action?: React$1.ReactNode | undefined;
105
143
  size?: "sm" | "md" | undefined;
106
144
  bordered?: boolean | undefined;
107
- headingLevel?: 2 | 3 | 4 | 5 | 6 | undefined;
145
+ /** `danger` (5.13) for a failure — the data couldn't load: the danger tint, a danger-coloured icon, and a solid
146
+ * danger frame with `bordered`. It stays quiet; pass `role="alert"` if it must interrupt. Default `neutral`. */
147
+ tone?: "neutral" | "danger" | undefined;
148
+ /** The title's heading level (default 3); `false` (5.14) makes it a paragraph, for a card or list whose outline
149
+ * mustn't change. EmptyState has no live-region role unless you pass `role`. */
150
+ headingLevel?: 2 | 3 | 4 | 5 | 6 | false | undefined;
108
151
  className?: string | undefined;
109
152
  }
110
153
  export interface ThemeOptions {
@@ -302,6 +345,11 @@ declare function ServerCard(props: CardProps): React$1.ReactElement;
302
345
  declare function ServerStatusPill(props: StatusPillProps): React$1.ReactElement;
303
346
  declare function ServerBadge(props: BadgeProps): React$1.ReactElement;
304
347
  declare function ServerEmptyState(props: EmptyStateProps): React$1.ReactElement;
348
+ /** Stat for Server Components (5.14): no `onClick` (a button needs the client); `href` renders `linkComponent`, else `<a>`. */
349
+ declare function ServerStat(props: Omit<StatProps, "onClick">): React$1.ReactElement;
350
+ /** Avatar for Server Components (5.14): initials and colour. Falling back to the initials when an image fails needs the
351
+ * client, so give a server avatar a `src` you know loads, or none. */
352
+ declare function ServerAvatar(props: AvatarProps): React$1.ReactElement;
305
353
  /** Makes icon names as strings work: `registerIcons(allIcons)` once at startup, with `allIcons` from
306
354
  * `@jirawatpyk/aura-react/icons`, or only the icons you use (`registerIcons([IconUsers, IconPlus])`). In 5.x every
307
355
  * name already works and this only says you are ready for 6.0 (it silences the notice); in 6.0 it is required. Call it in the module
@@ -312,9 +360,11 @@ export declare const Icon: React$1.ForwardRefExoticComponent<IconProps & React$1
312
360
 
313
361
  export {
314
362
  ServerAlert as Alert,
363
+ ServerAvatar as Avatar,
315
364
  ServerBadge as Badge,
316
365
  ServerCard as Card,
317
366
  ServerEmptyState as EmptyState,
367
+ ServerStat as Stat,
318
368
  ServerStatusPill as StatusPill,
319
369
  scale as brandScale,
320
370
  toneFor as statusTone,