@jirawatpyk/aura-react 5.33.0 → 5.34.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.
@@ -112,6 +112,8 @@ export interface DateDisplayOptions {
112
112
  export type DataAttributes = {
113
113
  [key: `data-${string}`]: string | number | boolean | undefined;
114
114
  };
115
+ export type Breakpoint = "base" | "sm" | "md" | "lg" | "xl";
116
+ export type Responsive<T> = T | Partial<Record<Breakpoint, T>>;
115
117
  export interface StatChange {
116
118
  /** Shown as written, e.g. "+12%" or "−3". */
117
119
  value: React$1.ReactNode;
@@ -199,6 +201,70 @@ export interface Theme {
199
201
  /** CSS overriding the tokens. No selector: the whole page. A selector (".tenant-acme") scopes it. Load after aura.css. */
200
202
  css(selector?: string): string;
201
203
  }
204
+ /** A monitored thing's state on a StatusTile. */
205
+ export type StatusTileStatus = "down" | "problem" | "maintenance" | "ok";
206
+ /** A colour for a tile's value or a marker: `danger`, `warning`, `accent` (violet), `neutral` (grey) or `default`
207
+ * (the text colour). */
208
+ export type TileTone = "danger" | "warning" | "accent" | "neutral" | "default";
209
+ /** A small icon at the end of a StatusTile's second line ("SSL expires soon", "Muted"). */
210
+ export interface StatusTileMarker {
211
+ icon: IconInput;
212
+ /** What it means. Read with the tile's name and shown as a tip on hover (a mouse only: on a phone, say it on the
213
+ * detail page too). */
214
+ label: string;
215
+ /** Default `neutral`. */
216
+ tone?: TileTone | undefined;
217
+ }
218
+ export interface StatusTileProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "style" | "lang" | "dir">, React$1.AriaAttributes, DataAttributes {
219
+ /** down (red), problem (amber), maintenance (violet) or ok (grey). Each has its own icon too, so colour is never the
220
+ * only sign. */
221
+ status: StatusTileStatus;
222
+ /** The name. Wraps to two lines at most, then ends with "…"; a cut name shows in full in a tip on hover. */
223
+ title: React$1.ReactNode;
224
+ /** Top right, tabular figures: "12m", "99.98%", "240 ms". */
225
+ value?: React$1.ReactNode | undefined;
226
+ /** The value's colour. Default: the status's (down → danger, problem → warning, maintenance → accent, ok → default). */
227
+ valueTone?: TileTone | undefined;
228
+ /** A short second line: "since 09:41", "3 of 4 checks". */
229
+ meta?: React$1.ReactNode | undefined;
230
+ /** Small icons at the end of the second line, each with a label. */
231
+ markers?: ReadonlyArray<StatusTileMarker> | undefined;
232
+ /** Makes the whole tile a link. Its name is everything the tile says, in reading order. */
233
+ href?: string | undefined;
234
+ /** Your router's link (e.g. `next/link`); defaults to AuraProvider's `linkComponent`, then `<a>`. */
235
+ linkComponent?: React$1.ElementType | undefined;
236
+ /** The status word read out after the title. Default: the locale's (Down, Problem, Maintenance, OK). */
237
+ statusLabel?: string | undefined;
238
+ className?: string | undefined;
239
+ }
240
+ export interface TileGridProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "style" | "lang" | "dir">, React$1.AriaAttributes, DataAttributes {
241
+ /** Equal columns, responsive like Grid. Default `{ base: 2, md: 3 }` (two on phones, three from 768px). */
242
+ columns?: Responsive<number> | undefined;
243
+ /** Each child (and each child of a Fragment) becomes one list item; the grid is a `ul` with an 8px gap. */
244
+ children?: React$1.ReactNode;
245
+ className?: string | undefined;
246
+ }
247
+ export interface SparklineProps extends Pick<React$1.SVGAttributes<SVGSVGElement>, "id" | "style">, DataAttributes {
248
+ /** The values, oldest first. `null` (or a value that isn't a finite number) is no point: the line breaks there. */
249
+ data: ReadonlyArray<number | null | undefined>;
250
+ /** Which points failed, by the same index as `data`. Shown only when `failures` isn't `none`. */
251
+ failed?: ReadonlyArray<boolean | null | undefined> | undefined;
252
+ /** How failed points show: `none` (default), `band` (a red band behind the point) or `ticks` (a red tick at the
253
+ * foot). */
254
+ failures?: "none" | "band" | "ticks" | undefined;
255
+ /** The line's colour. Default `neutral`. */
256
+ tone?: "neutral" | "accent" | "danger" | "warning" | "positive" | undefined;
257
+ /** `sm` 80×24 (default), `md` 120×32. */
258
+ size?: "sm" | "md" | undefined;
259
+ /** The scale's ends; default the data's own lowest and highest. Give tiles the same ones to compare them. Values
260
+ * beyond them are drawn at the edge. */
261
+ min?: number | undefined;
262
+ max?: number | undefined;
263
+ /** What the line says, for screen readers ("Response time, last 24 h: 180–420 ms, 2 failures"). Without it the
264
+ * sparkline is decoration and hidden from them. */
265
+ label?: string | undefined;
266
+ className?: string | undefined;
267
+ }
202
268
  /** Options for formatDate: locale/calendar plus a preset or any Intl.DateTimeFormat options. */
203
269
  export type FormatDateOptions = DateDisplayOptions & {
204
270
  format?: "short" | "long" | "numeric" | Intl.DateTimeFormatOptions | undefined;
@@ -309,6 +375,11 @@ export interface AuraStrings {
309
375
  breadcrumbMore: string;
310
376
  /** A Stepper step with `status: 'error'` (5.18). */
311
377
  stepError: string;
378
+ /** StatusTile's status words (5.34). */
379
+ statusDown: string;
380
+ statusProblem: string;
381
+ statusMaintenance: string;
382
+ statusOk: string;
312
383
  }
313
384
  /** Built-in strings by locale. th and sv also ship as packs (`@jirawatpyk/aura-react/locales/th`, `/sv`, 5.9); in 6.0
314
385
  * only en stays built in and a Thai or Swedish app passes its pack to AuraProvider `strings`. */
@@ -430,6 +501,9 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
430
501
  style?: React$1.CSSProperties | undefined;
431
502
  }
432
503
  export declare const PageHeader: React$1.ForwardRefExoticComponent<PageHeaderProps & React$1.RefAttributes<HTMLDivElement>>;
504
+ declare function ServerStatusTile(props: StatusTileProps): React$1.ReactElement;
505
+ export declare const TileGrid: React$1.ForwardRefExoticComponent<TileGridProps & React$1.RefAttributes<HTMLUListElement>>;
506
+ export declare const Sparkline: React$1.ForwardRefExoticComponent<SparklineProps & React$1.RefAttributes<SVGSVGElement>>;
433
507
 
434
508
  export {
435
509
  ServerAlert as Alert,
@@ -439,6 +513,7 @@ export {
439
513
  ServerEmptyState as EmptyState,
440
514
  ServerStat as Stat,
441
515
  ServerStatusPill as StatusPill,
516
+ ServerStatusTile as StatusTile,
442
517
  scale as brandScale,
443
518
  toneFor as statusTone,
444
519
  };
@@ -112,6 +112,8 @@ export interface DateDisplayOptions {
112
112
  export type DataAttributes = {
113
113
  [key: `data-${string}`]: string | number | boolean | undefined;
114
114
  };
115
+ export type Breakpoint = "base" | "sm" | "md" | "lg" | "xl";
116
+ export type Responsive<T> = T | Partial<Record<Breakpoint, T>>;
115
117
  export interface StatChange {
116
118
  /** Shown as written, e.g. "+12%" or "−3". */
117
119
  value: React$1.ReactNode;
@@ -199,6 +201,70 @@ export interface Theme {
199
201
  /** CSS overriding the tokens. No selector: the whole page. A selector (".tenant-acme") scopes it. Load after aura.css. */
200
202
  css(selector?: string): string;
201
203
  }
204
+ /** A monitored thing's state on a StatusTile. */
205
+ export type StatusTileStatus = "down" | "problem" | "maintenance" | "ok";
206
+ /** A colour for a tile's value or a marker: `danger`, `warning`, `accent` (violet), `neutral` (grey) or `default`
207
+ * (the text colour). */
208
+ export type TileTone = "danger" | "warning" | "accent" | "neutral" | "default";
209
+ /** A small icon at the end of a StatusTile's second line ("SSL expires soon", "Muted"). */
210
+ export interface StatusTileMarker {
211
+ icon: IconInput;
212
+ /** What it means. Read with the tile's name and shown as a tip on hover (a mouse only: on a phone, say it on the
213
+ * detail page too). */
214
+ label: string;
215
+ /** Default `neutral`. */
216
+ tone?: TileTone | undefined;
217
+ }
218
+ export interface StatusTileProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "style" | "lang" | "dir">, React$1.AriaAttributes, DataAttributes {
219
+ /** down (red), problem (amber), maintenance (violet) or ok (grey). Each has its own icon too, so colour is never the
220
+ * only sign. */
221
+ status: StatusTileStatus;
222
+ /** The name. Wraps to two lines at most, then ends with "…"; a cut name shows in full in a tip on hover. */
223
+ title: React$1.ReactNode;
224
+ /** Top right, tabular figures: "12m", "99.98%", "240 ms". */
225
+ value?: React$1.ReactNode | undefined;
226
+ /** The value's colour. Default: the status's (down → danger, problem → warning, maintenance → accent, ok → default). */
227
+ valueTone?: TileTone | undefined;
228
+ /** A short second line: "since 09:41", "3 of 4 checks". */
229
+ meta?: React$1.ReactNode | undefined;
230
+ /** Small icons at the end of the second line, each with a label. */
231
+ markers?: ReadonlyArray<StatusTileMarker> | undefined;
232
+ /** Makes the whole tile a link. Its name is everything the tile says, in reading order. */
233
+ href?: string | undefined;
234
+ /** Your router's link (e.g. `next/link`); defaults to AuraProvider's `linkComponent`, then `<a>`. */
235
+ linkComponent?: React$1.ElementType | undefined;
236
+ /** The status word read out after the title. Default: the locale's (Down, Problem, Maintenance, OK). */
237
+ statusLabel?: string | undefined;
238
+ className?: string | undefined;
239
+ }
240
+ export interface TileGridProps extends Pick<React$1.HTMLAttributes<HTMLElement>, "id" | "style" | "lang" | "dir">, React$1.AriaAttributes, DataAttributes {
241
+ /** Equal columns, responsive like Grid. Default `{ base: 2, md: 3 }` (two on phones, three from 768px). */
242
+ columns?: Responsive<number> | undefined;
243
+ /** Each child (and each child of a Fragment) becomes one list item; the grid is a `ul` with an 8px gap. */
244
+ children?: React$1.ReactNode;
245
+ className?: string | undefined;
246
+ }
247
+ export interface SparklineProps extends Pick<React$1.SVGAttributes<SVGSVGElement>, "id" | "style">, DataAttributes {
248
+ /** The values, oldest first. `null` (or a value that isn't a finite number) is no point: the line breaks there. */
249
+ data: ReadonlyArray<number | null | undefined>;
250
+ /** Which points failed, by the same index as `data`. Shown only when `failures` isn't `none`. */
251
+ failed?: ReadonlyArray<boolean | null | undefined> | undefined;
252
+ /** How failed points show: `none` (default), `band` (a red band behind the point) or `ticks` (a red tick at the
253
+ * foot). */
254
+ failures?: "none" | "band" | "ticks" | undefined;
255
+ /** The line's colour. Default `neutral`. */
256
+ tone?: "neutral" | "accent" | "danger" | "warning" | "positive" | undefined;
257
+ /** `sm` 80×24 (default), `md` 120×32. */
258
+ size?: "sm" | "md" | undefined;
259
+ /** The scale's ends; default the data's own lowest and highest. Give tiles the same ones to compare them. Values
260
+ * beyond them are drawn at the edge. */
261
+ min?: number | undefined;
262
+ max?: number | undefined;
263
+ /** What the line says, for screen readers ("Response time, last 24 h: 180–420 ms, 2 failures"). Without it the
264
+ * sparkline is decoration and hidden from them. */
265
+ label?: string | undefined;
266
+ className?: string | undefined;
267
+ }
202
268
  /** Options for formatDate: locale/calendar plus a preset or any Intl.DateTimeFormat options. */
203
269
  export type FormatDateOptions = DateDisplayOptions & {
204
270
  format?: "short" | "long" | "numeric" | Intl.DateTimeFormatOptions | undefined;
@@ -309,6 +375,11 @@ export interface AuraStrings {
309
375
  breadcrumbMore: string;
310
376
  /** A Stepper step with `status: 'error'` (5.18). */
311
377
  stepError: string;
378
+ /** StatusTile's status words (5.34). */
379
+ statusDown: string;
380
+ statusProblem: string;
381
+ statusMaintenance: string;
382
+ statusOk: string;
312
383
  }
313
384
  /** Built-in strings by locale. th and sv also ship as packs (`@jirawatpyk/aura-react/locales/th`, `/sv`, 5.9); in 6.0
314
385
  * only en stays built in and a Thai or Swedish app passes its pack to AuraProvider `strings`. */
@@ -430,6 +501,9 @@ export interface PageHeaderProps extends Pick<React$1.HTMLAttributes<HTMLElement
430
501
  style?: React$1.CSSProperties | undefined;
431
502
  }
432
503
  export declare const PageHeader: React$1.ForwardRefExoticComponent<PageHeaderProps & React$1.RefAttributes<HTMLDivElement>>;
504
+ declare function ServerStatusTile(props: StatusTileProps): React$1.ReactElement;
505
+ export declare const TileGrid: React$1.ForwardRefExoticComponent<TileGridProps & React$1.RefAttributes<HTMLUListElement>>;
506
+ export declare const Sparkline: React$1.ForwardRefExoticComponent<SparklineProps & React$1.RefAttributes<SVGSVGElement>>;
433
507
 
434
508
  export {
435
509
  ServerAlert as Alert,
@@ -439,6 +513,7 @@ export {
439
513
  ServerEmptyState as EmptyState,
440
514
  ServerStat as Stat,
441
515
  ServerStatusPill as StatusPill,
516
+ ServerStatusTile as StatusTile,
442
517
  scale as brandScale,
443
518
  toneFor as statusTone,
444
519
  };
@@ -268,11 +268,15 @@ var th = {
268
268
  pageN: function(p) {
269
269
  return "\u0E2B\u0E19\u0E49\u0E32 " + p;
270
270
  },
271
- progressReserved: function(v, r, max) {
272
- return "\u0E43\u0E0A\u0E49\u0E41\u0E25\u0E49\u0E27 " + n(v) + " \u0E08\u0E32\u0E01 " + n(max) + " \u0E08\u0E2D\u0E07\u0E44\u0E27\u0E49 " + n(r);
271
+ progressReserved: function(v, r2, max) {
272
+ return "\u0E43\u0E0A\u0E49\u0E41\u0E25\u0E49\u0E27 " + n(v) + " \u0E08\u0E32\u0E01 " + n(max) + " \u0E08\u0E2D\u0E07\u0E44\u0E27\u0E49 " + n(r2);
273
273
  },
274
274
  breadcrumbMore: "\u0E41\u0E2A\u0E14\u0E07\u0E40\u0E2A\u0E49\u0E19\u0E17\u0E32\u0E07\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14",
275
275
  stepError: "\u0E21\u0E35\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14",
276
+ statusDown: "\u0E25\u0E48\u0E21",
277
+ statusProblem: "\u0E21\u0E35\u0E1B\u0E31\u0E0D\u0E2B\u0E32",
278
+ statusMaintenance: "\u0E1B\u0E34\u0E14\u0E1B\u0E23\u0E31\u0E1A\u0E1B\u0E23\u0E38\u0E07",
279
+ statusOk: "\u0E1B\u0E01\u0E15\u0E34",
276
280
  accepts: function(list, max) {
277
281
  return [list, max && "\u0E44\u0E21\u0E48\u0E40\u0E01\u0E34\u0E19 " + max + " \u0E15\u0E48\u0E2D\u0E44\u0E1F\u0E25\u0E4C"].filter(Boolean).join(" \xB7 ");
278
282
  }
@@ -399,11 +403,15 @@ var sv = {
399
403
  pageN: function(p) {
400
404
  return "Sida " + p;
401
405
  },
402
- progressReserved: function(v, r, max) {
403
- return nsv(v) + " av " + nsv(max) + " anv\xE4nda, " + nsv(r) + " reserverade";
406
+ progressReserved: function(v, r2, max) {
407
+ return nsv(v) + " av " + nsv(max) + " anv\xE4nda, " + nsv(r2) + " reserverade";
404
408
  },
405
409
  breadcrumbMore: "Visa hela s\xF6kv\xE4gen",
406
410
  stepError: "har fel",
411
+ statusDown: "Nere",
412
+ statusProblem: "Problem",
413
+ statusMaintenance: "Underh\xE5ll",
414
+ statusOk: "OK",
407
415
  accepts: function(list, max) {
408
416
  return [list, max && "h\xF6gst " + max + " per fil"].filter(Boolean).join(", ");
409
417
  }
@@ -531,11 +539,15 @@ var STRINGS = {
531
539
  pageN: function(p) {
532
540
  return "Page " + p;
533
541
  },
534
- progressReserved: function(v, r, max) {
535
- return n2(v) + " of " + n2(max) + " used, " + n2(r) + " reserved";
542
+ progressReserved: function(v, r2, max) {
543
+ return n2(v) + " of " + n2(max) + " used, " + n2(r2) + " reserved";
536
544
  },
537
545
  breadcrumbMore: "Show the full path",
538
546
  stepError: "has errors",
547
+ statusDown: "Down",
548
+ statusProblem: "Problem",
549
+ statusMaintenance: "Maintenance",
550
+ statusOk: "OK",
539
551
  accepts: function(list, max) {
540
552
  return [list, max && "up to " + max + " each"].filter(Boolean).join(", ");
541
553
  }
@@ -546,14 +558,14 @@ var STRINGS = {
546
558
 
547
559
  // src/theme.ts
548
560
  function hexToRgb(hex) {
549
- let h5 = String(hex).trim().replace("#", "");
550
- if (h5.length === 3)
551
- h5 = h5.split("").map(function(c) {
561
+ let h6 = String(hex).trim().replace("#", "");
562
+ if (h6.length === 3)
563
+ h6 = h6.split("").map(function(c) {
552
564
  return c + c;
553
565
  }).join("");
554
- if (!/^[0-9a-f]{6}$/i.test(h5)) throw new Error('createTheme: "' + hex + '" is not a #rgb or #rrggbb colour');
566
+ if (!/^[0-9a-f]{6}$/i.test(h6)) throw new Error('createTheme: "' + hex + '" is not a #rgb or #rrggbb colour');
555
567
  return [0, 2, 4].map(function(i) {
556
- return parseInt(h5.slice(i, i + 2), 16) / 255;
568
+ return parseInt(h6.slice(i, i + 2), 16) / 255;
557
569
  });
558
570
  }
559
571
  function rgbToHex(rgb) {
@@ -569,10 +581,10 @@ function delin(c) {
569
581
  return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
570
582
  }
571
583
  function rgbToOklch(rgb) {
572
- const r = lin(rgb[0]), g = lin(rgb[1]), b = lin(rgb[2]);
573
- const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
574
- const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
575
- const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
584
+ const r2 = lin(rgb[0]), g = lin(rgb[1]), b = lin(rgb[2]);
585
+ const l = Math.cbrt(0.4122214708 * r2 + 0.5363325363 * g + 0.0514459929 * b);
586
+ const m = Math.cbrt(0.2119034982 * r2 + 0.6806995451 * g + 0.1073969566 * b);
587
+ const s = Math.cbrt(0.0883024619 * r2 + 0.2817188376 * g + 0.6299787005 * b);
576
588
  const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
577
589
  const A = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
578
590
  const B = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
@@ -732,13 +744,13 @@ function createTheme(opts) {
732
744
  D["card-shadow-creative"] = "8px 8px 0px " + shadowDark;
733
745
  const checks = [];
734
746
  function check(theme, fg, bg, target, fgHex, bgHex) {
735
- const r = contrast(fgHex, bgHex);
747
+ const r2 = contrast(fgHex, bgHex);
736
748
  checks.push({
737
749
  theme,
738
750
  pair: fg + " on " + bg,
739
- ratio: Math.round(r * 100) / 100,
751
+ ratio: Math.round(r2 * 100) / 100,
740
752
  target,
741
- pass: r >= target - 5e-3
753
+ pass: r2 >= target - 5e-3
742
754
  });
743
755
  }
744
756
  [
@@ -858,6 +870,18 @@ function colorSchemeScript(options) {
858
870
 
859
871
  // src/breakpoints.ts
860
872
  var breakpoints = { sm: 640, md: 768, lg: 1024, xl: 1280 };
873
+ var ORDER = ["base", "sm", "md", "lg", "xl"];
874
+ function respVars(prefix, value, map2) {
875
+ const style = {};
876
+ if (value == null) return style;
877
+ if (typeof value !== "object") value = { base: value };
878
+ let byBp = value, cur;
879
+ ORDER.forEach(function(k) {
880
+ if (byBp[k] !== void 0) cur = map2 ? map2(byBp[k]) : byBp[k];
881
+ if (cur !== void 0) style["--" + prefix + "-" + k] = cur;
882
+ });
883
+ return style;
884
+ }
861
885
 
862
886
  // src/display.tsx
863
887
  import * as React3 from "react";
@@ -921,9 +945,9 @@ function iconSvg(shapes, props, ref) {
921
945
  ...a11y
922
946
  },
923
947
  shapes.map(function(s, i) {
924
- const attrs = { key: i };
925
- for (const k in s[1]) attrs[k === "stroke-width" ? "strokeWidth" : k] = s[1][k];
926
- return h(s[0], attrs);
948
+ const attrs2 = { key: i };
949
+ for (const k in s[1]) attrs2[k === "stroke-width" ? "strokeWidth" : k] = s[1][k];
950
+ return h(s[0], attrs2);
927
951
  })
928
952
  );
929
953
  }
@@ -1055,6 +1079,14 @@ var IconTrendingDown = /* @__PURE__ */ defineIcon("trending-down", [
1055
1079
  ["path", { d: "M16 17h6v-6" }],
1056
1080
  ["path", { d: "m22 17-8.5-8.5-5 5L2 7" }]
1057
1081
  ]);
1082
+ var IconWrench = /* @__PURE__ */ defineIcon("wrench", [
1083
+ [
1084
+ "path",
1085
+ {
1086
+ d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z"
1087
+ }
1088
+ ]
1089
+ ]);
1058
1090
 
1059
1091
  // src/display.tsx
1060
1092
  var h2 = React3.createElement;
@@ -1295,14 +1327,14 @@ function ServerAvatar(props) {
1295
1327
  import * as React4 from "react";
1296
1328
  var h3 = React4.createElement;
1297
1329
  var Container = React4.forwardRef(function Container2(props, ref) {
1298
- const attrs = {};
1330
+ const attrs2 = {};
1299
1331
  Object.keys(props).forEach(function(k) {
1300
1332
  if (k === "id" || k === "lang" || k === "dir" || /^(aria|data)-/.test(k))
1301
- attrs[k] = props[k];
1333
+ attrs2[k] = props[k];
1302
1334
  });
1303
1335
  return h3(
1304
1336
  props.as || "div",
1305
- Object.assign(attrs, {
1337
+ Object.assign(attrs2, {
1306
1338
  ref,
1307
1339
  className: cx(
1308
1340
  "aura-container",
@@ -1320,15 +1352,15 @@ var Container = React4.forwardRef(function Container2(props, ref) {
1320
1352
  import * as React5 from "react";
1321
1353
  var h4 = React5.createElement;
1322
1354
  var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1323
- const attrs = {};
1355
+ const attrs2 = {};
1324
1356
  Object.keys(props).forEach(function(k) {
1325
1357
  if (k === "id" || k === "lang" || k === "dir" || k === "role" || /^(aria|data)-/.test(k))
1326
- attrs[k] = props[k];
1358
+ attrs2[k] = props[k];
1327
1359
  });
1328
1360
  const level = props.headingLevel || 1;
1329
1361
  return h4(
1330
1362
  "div",
1331
- Object.assign(attrs, { ref, className: cx("aura-page-header", props.className), style: props.style }),
1363
+ Object.assign(attrs2, { ref, className: cx("aura-page-header", props.className), style: props.style }),
1332
1364
  h4(
1333
1365
  "div",
1334
1366
  { className: "aura-page-header__text" },
@@ -1340,6 +1372,207 @@ var PageHeader = React5.forwardRef(function PageHeader2(props, ref) {
1340
1372
  props.actions != null && props.actions !== false ? h4("div", { className: "aura-page-header__actions" }, props.actions) : null
1341
1373
  );
1342
1374
  });
1375
+
1376
+ // src/tiles.tsx
1377
+ import * as React6 from "react";
1378
+ var h5 = React6.createElement;
1379
+ var STATUS_ICON = {
1380
+ down: IconCircleAlert,
1381
+ problem: IconTriangleAlert,
1382
+ maintenance: IconWrench,
1383
+ ok: IconCircleCheck
1384
+ };
1385
+ var STATUS_TONE = {
1386
+ down: "danger",
1387
+ problem: "warning",
1388
+ maintenance: "accent",
1389
+ ok: "default"
1390
+ };
1391
+ var STATUS_WORD = {
1392
+ down: "statusDown",
1393
+ problem: "statusProblem",
1394
+ maintenance: "statusMaintenance",
1395
+ ok: "statusOk"
1396
+ };
1397
+ function statusWord(status, t) {
1398
+ return String(t[STATUS_WORD[status]] || STATUS_WORD[status]);
1399
+ }
1400
+ function attrs(props) {
1401
+ const out = {};
1402
+ Object.keys(props).forEach(function(k) {
1403
+ if (k === "id" || k === "style" || k === "lang" || k === "dir" || /^(aria|data)-/.test(k))
1404
+ out[k] = props[k];
1405
+ });
1406
+ return out;
1407
+ }
1408
+ var comma = h5("span", { className: "aura-status-tile__sep" }, ",");
1409
+ function statusTileElement(props, ref, Link, t, titleRef) {
1410
+ const status = STATUS_ICON[props.status] ? props.status : "ok";
1411
+ const valueTone = props.valueTone || STATUS_TONE[status];
1412
+ const word = props.statusLabel || statusWord(status, t);
1413
+ const markers = (props.markers || []).filter(Boolean);
1414
+ const has = function(v) {
1415
+ return v != null && v !== false && v !== "";
1416
+ };
1417
+ const hasValue = has(props.value), hasMeta = has(props.meta);
1418
+ const Tag = props.href ? Link : "div";
1419
+ return h5(
1420
+ Tag,
1421
+ Object.assign(attrs(props), {
1422
+ ref,
1423
+ href: props.href,
1424
+ className: cx("aura-status-tile", "aura-status-tile--" + status, props.href && "is-interactive", props.className)
1425
+ }),
1426
+ h5(
1427
+ "span",
1428
+ { className: "aura-status-tile__head" },
1429
+ h5(Icon, { name: h5(STATUS_ICON[status]), size: 16, className: "aura-status-tile__icon" }),
1430
+ h5("span", { className: "aura-status-tile__title", ref: titleRef }, props.title, comma),
1431
+ h5("span", { className: "aura-sr-only" }, word + (hasValue || hasMeta || markers.length ? "," : "")),
1432
+ hasValue ? h5(
1433
+ "span",
1434
+ { className: cx("aura-status-tile__value", "is-" + valueTone) },
1435
+ props.value,
1436
+ hasMeta || markers.length ? comma : null
1437
+ ) : null
1438
+ ),
1439
+ hasMeta || markers.length ? h5(
1440
+ "span",
1441
+ { className: "aura-status-tile__foot" },
1442
+ hasMeta ? h5("span", { className: "aura-status-tile__meta" }, props.meta, markers.length ? comma : null) : null,
1443
+ markers.length ? h5(
1444
+ "span",
1445
+ { className: "aura-status-tile__markers" },
1446
+ markers.map(function(m, i) {
1447
+ return h5(
1448
+ "span",
1449
+ {
1450
+ key: i,
1451
+ className: cx("aura-status-tile__marker", "is-" + (m.tone || "neutral")),
1452
+ "data-aura-tip": m.label
1453
+ },
1454
+ h5(Icon, { name: m.icon, size: 14 }),
1455
+ h5("span", { className: "aura-sr-only" }, m.label + (i < markers.length - 1 ? "," : ""))
1456
+ );
1457
+ })
1458
+ ) : null
1459
+ ) : null
1460
+ );
1461
+ }
1462
+ function ServerStatusTile(props) {
1463
+ return statusTileElement(props, void 0, props.linkComponent || "a", STRINGS.en);
1464
+ }
1465
+ var TileGrid = React6.forwardRef(function TileGrid2(props, ref) {
1466
+ const style = Object.assign(
1467
+ {},
1468
+ respVars("aura-grid-cols", props.columns == null ? { base: 2, md: 3 } : props.columns),
1469
+ props.style
1470
+ );
1471
+ return h5(
1472
+ "ul",
1473
+ Object.assign(attrs(props), {
1474
+ ref,
1475
+ role: "list",
1476
+ className: cx("aura-grid-layout", "aura-tile-grid", props.className),
1477
+ style
1478
+ }),
1479
+ /* toArray drops null and booleans and keys each element; a Fragment's children are items too. */
1480
+ flat(props.children).map(function(c, i) {
1481
+ return h5("li", { key: React6.isValidElement(c) && c.key != null ? c.key : i }, c);
1482
+ })
1483
+ );
1484
+ });
1485
+ function flat(children) {
1486
+ const out = [];
1487
+ React6.Children.toArray(children).forEach(function(c) {
1488
+ if (React6.isValidElement(c) && c.type === React6.Fragment)
1489
+ flat(c.props.children).forEach(function(x) {
1490
+ out.push(React6.isValidElement(x) ? React6.cloneElement(x, { key: String(c.key) + "/" + String(x.key) }) : x);
1491
+ });
1492
+ else if (c !== "") out.push(c);
1493
+ });
1494
+ return out;
1495
+ }
1496
+ var SIZES2 = { sm: [80, 24], md: [120, 32] };
1497
+ var PAD = 2;
1498
+ function r(n3) {
1499
+ return Math.round(n3 * 100) / 100;
1500
+ }
1501
+ function num(v) {
1502
+ return typeof v === "number" && isFinite(v) ? v : null;
1503
+ }
1504
+ var Sparkline = React6.forwardRef(function Sparkline2(props, ref) {
1505
+ const wh = SIZES2[props.size || "sm"] || SIZES2.sm;
1506
+ const W = wh[0], H = wh[1];
1507
+ const data = (props.data || []).map(num);
1508
+ const n3 = data.length;
1509
+ const vals = data.filter(function(v) {
1510
+ return v != null;
1511
+ });
1512
+ let lo = num(props.min), hi = num(props.max);
1513
+ if (lo == null) lo = vals.length ? Math.min.apply(null, vals) : 0;
1514
+ if (hi == null) hi = vals.length ? Math.max.apply(null, vals) : 0;
1515
+ if (lo > hi) {
1516
+ const s = lo;
1517
+ lo = hi;
1518
+ hi = s;
1519
+ }
1520
+ const step = n3 > 1 ? (W - 2 * PAD) / (n3 - 1) : 0;
1521
+ const x = function(i) {
1522
+ return n3 > 1 ? PAD + i * step : W / 2;
1523
+ };
1524
+ const y = function(v) {
1525
+ if (hi === lo) return H / 2;
1526
+ const k = Math.max(0, Math.min(1, (v - lo) / (hi - lo)));
1527
+ return H - PAD - k * (H - 2 * PAD);
1528
+ };
1529
+ let d = "";
1530
+ const dots = [];
1531
+ data.forEach(function(v, i) {
1532
+ if (v == null) return;
1533
+ const prev = i > 0 && data[i - 1] != null, next = i < n3 - 1 && data[i + 1] != null;
1534
+ if (!prev && !next) dots.push(h5("circle", { key: "d" + i, cx: r(x(i)), cy: r(y(v)), r: 1.5 }));
1535
+ else d += (prev ? "L" : "M") + r(x(i)) + " " + r(y(v));
1536
+ });
1537
+ const mode = props.failures || "none";
1538
+ const fails = [];
1539
+ if (mode !== "none" && props.failed)
1540
+ data.forEach(function(_v, i) {
1541
+ if (!props.failed[i]) return;
1542
+ if (mode === "band") {
1543
+ const w = Math.max(2, step || W), left = Math.max(0, x(i) - w / 2), right = Math.min(W, x(i) + w / 2);
1544
+ fails.push(h5("rect", { key: "f" + i, x: r(left), y: 0, width: r(right - left), height: H }));
1545
+ } else
1546
+ fails.push(
1547
+ h5("rect", {
1548
+ key: "f" + i,
1549
+ x: r(Math.max(0, Math.min(W - 1.5, x(i) - 0.75))),
1550
+ y: H - 6,
1551
+ width: 1.5,
1552
+ height: 6
1553
+ })
1554
+ );
1555
+ });
1556
+ const named = !!props.label;
1557
+ return h5(
1558
+ "svg",
1559
+ Object.assign(attrs(props), {
1560
+ ref,
1561
+ className: cx("aura-sparkline", "is-" + (props.tone || "neutral"), props.className),
1562
+ width: W,
1563
+ height: H,
1564
+ viewBox: "0 0 " + W + " " + H,
1565
+ role: named ? "img" : void 0,
1566
+ "aria-label": named ? props.label : void 0,
1567
+ "aria-hidden": named ? void 0 : true,
1568
+ focusable: "false"
1569
+ }),
1570
+ fails.length && mode === "band" ? h5("g", { className: "aura-sparkline__band" }, fails) : null,
1571
+ d ? h5("path", { className: "aura-sparkline__line", d }) : null,
1572
+ dots.length ? h5("g", { className: "aura-sparkline__dots" }, dots) : null,
1573
+ fails.length && mode === "ticks" ? h5("g", { className: "aura-sparkline__ticks" }, fails) : null
1574
+ );
1575
+ });
1343
1576
  export {
1344
1577
  ServerAlert as Alert,
1345
1578
  ServerAvatar as Avatar,
@@ -1350,8 +1583,11 @@ export {
1350
1583
  Icon,
1351
1584
  PageHeader,
1352
1585
  STRINGS,
1586
+ Sparkline,
1353
1587
  ServerStat as Stat,
1354
1588
  ServerStatusPill as StatusPill,
1589
+ ServerStatusTile as StatusTile,
1590
+ TileGrid,
1355
1591
  scale as brandScale,
1356
1592
  breakpoints,
1357
1593
  buttonClass,