@teton/smith-ui 0.2.180 → 0.2.181

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/card.d.ts CHANGED
@@ -23,6 +23,29 @@ export declare function Panel({ icon: Icon, title, theme, count, actions, bodyCl
23
23
  className?: string;
24
24
  children: ReactNode;
25
25
  }): import("react/jsx-runtime").JSX.Element;
26
+ declare const ALERT_TONES: {
27
+ red: {
28
+ accent: string;
29
+ chip: string;
30
+ };
31
+ amber: {
32
+ accent: string;
33
+ chip: string;
34
+ };
35
+ };
36
+ export type AlertTone = keyof typeof ALERT_TONES;
37
+ /**
38
+ * Attention banner for a problem the page wants to lead with: colored left
39
+ * accent, headline plus severity chip, one line of detail, optional action on
40
+ * the right. Callers render it conditionally — it has no "all clear" state.
41
+ */
42
+ export declare function AlertBanner({ tone, title, severity, action, children, }: {
43
+ tone?: AlertTone;
44
+ title: ReactNode;
45
+ severity?: string;
46
+ action?: ReactNode;
47
+ children: ReactNode;
48
+ }): import("react/jsx-runtime").JSX.Element;
26
49
  /**
27
50
  * Card with a colored, titled header bar — for grouped lists.
28
51
  * Right side shows a count pill (when `count` is set) and/or `actions`.
@@ -53,3 +76,4 @@ export declare function ViewAllFooter({ to, count, noun, }: {
53
76
  count: number;
54
77
  noun?: string;
55
78
  }): import("react/jsx-runtime").JSX.Element;
79
+ export {};
package/dist/detail.d.ts CHANGED
@@ -14,9 +14,11 @@ export interface TabItem {
14
14
  state?: unknown;
15
15
  }
16
16
  /** Underlined tab bar used across the device detail subpages. The active tab
17
- * renders as static text; the rest are router links. */
18
- export declare function TabNav({ items }: {
17
+ * renders as static text; the rest are router links. `actions` renders on the
18
+ * right of the bar, for controls that belong to the active tab's content. */
19
+ export declare function TabNav({ items, actions, }: {
19
20
  items: TabItem[];
21
+ actions?: ReactNode;
20
22
  }): import("react/jsx-runtime").JSX.Element;
21
23
  export interface SideNavItem {
22
24
  label: string;
@@ -0,0 +1,33 @@
1
+ import { ReactNode } from 'react';
2
+ import { ButtonSize, ButtonTone, ButtonVariant } from './button';
3
+ export interface DropdownItem {
4
+ label: ReactNode;
5
+ /** Secondary line under the label — good for the detail a tooltip carried. */
6
+ description?: ReactNode;
7
+ icon?: ReactNode;
8
+ /** Tints the icon with the tone the action would have as a standalone button. */
9
+ tone?: ButtonTone;
10
+ onClick?: () => void;
11
+ /** Leaves the menu open after selecting — for items that swap to an
12
+ * in-place confirmation (e.g. "Copied!") instead of navigating away. */
13
+ keepOpen?: boolean;
14
+ /** Renders the item as an external link instead of a button. */
15
+ href?: string;
16
+ target?: string;
17
+ disabled?: boolean;
18
+ }
19
+ /**
20
+ * A button that opens a menu of actions — for collapsing a row of related
21
+ * buttons into one control. Closes on outside click, Escape, or item select.
22
+ */
23
+ export declare function DropdownMenu({ label, items, icon, variant, tone, size, align, className, }: {
24
+ label: ReactNode;
25
+ items: DropdownItem[];
26
+ icon?: ReactNode;
27
+ variant?: ButtonVariant;
28
+ tone?: ButtonTone;
29
+ size?: ButtonSize;
30
+ /** Which edge of the trigger the menu is anchored to. */
31
+ align?: "left" | "right";
32
+ className?: string;
33
+ }): import("react/jsx-runtime").JSX.Element;
package/dist/index.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  export { BADGE_COLORS, Badge, type BadgeVariant, LabelChip } from './badge';
2
2
  export { Button, type ButtonSize, type ButtonTone, type ButtonVariant, } from './button';
3
- export { Card, ListRow, Panel, SectionCard, ViewAllFooter } from './card';
3
+ export { AlertBanner, type AlertTone, Card, ListRow, Panel, SectionCard, ViewAllFooter, } from './card';
4
4
  export { CountryFlag } from './country-flag';
5
5
  export { BackLink, InfoRow, SideNav, type SideNavItem, type TabItem, TabNav, } from './detail';
6
+ export { type DropdownItem, DropdownMenu } from './dropdown';
6
7
  export { PageContainer } from './page-container';
7
8
  export { SearchInput } from './search-input';
8
9
  export { StatCard } from './stat-card';
9
- export { StateTimeline, type TimelineLane, type TimelineSpan, type TimelineTone, } from './state-timeline';
10
+ export { StateTimeline, type TimelineLane, type TimelineSpan, type TimelineTone, UptimeBars, type UptimeBucket, } from './state-timeline';
10
11
  export { type IconComponent, SECTION_THEMES, type SectionTheme, type SectionThemeName, } from './theme';
11
12
  export { Toast, type ToastState } from './toast';
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { jsx as e, jsxs as l, Fragment as y } from "react/jsx-runtime";
2
- import { X as v, Loader2 as E, ArrowLeft as S, Search as L, Check as C } from "lucide-react";
3
- import { Link as h } from "react-router";
4
- import { useRef as j, useEffect as A } from "react";
5
- const R = {
1
+ import { jsx as e, jsxs as s, Fragment as v } from "react/jsx-runtime";
2
+ import { X as w, Loader2 as j, ArrowLeft as D, ChevronDown as O, Search as R, Check as B } from "lucide-react";
3
+ import { Link as f } from "react-router";
4
+ import { useState as M, useRef as _, useEffect as A } from "react";
5
+ const I = {
6
6
  gray: "bg-gray-100 text-gray-700",
7
7
  blue: "bg-blue-100 text-blue-700",
8
8
  green: "bg-green-100 text-green-700",
@@ -11,55 +11,55 @@ const R = {
11
11
  purple: "bg-purple-100 text-purple-700",
12
12
  orange: "bg-orange-100 text-orange-700"
13
13
  };
14
- function U({
15
- variant: t = "gray",
16
- pill: r = !1,
14
+ function J({
15
+ variant: r = "gray",
16
+ pill: t = !1,
17
17
  className: n = "",
18
- children: o
18
+ children: a
19
19
  }) {
20
20
  return /* @__PURE__ */ e(
21
21
  "span",
22
22
  {
23
- className: `px-1.5 py-0.5 text-xs font-medium ${r ? "rounded-full" : "rounded"} ${R[t]} ${n}`,
24
- children: o
23
+ className: `px-1.5 py-0.5 text-xs font-medium ${t ? "rounded-full" : "rounded"} ${I[r]} ${n}`,
24
+ children: a
25
25
  }
26
26
  );
27
27
  }
28
- function V({
29
- name: t,
30
- value: r,
28
+ function Q({
29
+ name: r,
30
+ value: t,
31
31
  onClick: n,
32
- onRemove: o,
33
- active: a = !1,
34
- title: g
32
+ onRemove: a,
33
+ active: o = !1,
34
+ title: m
35
35
  }) {
36
- const s = /* @__PURE__ */ l(y, { children: [
36
+ const l = /* @__PURE__ */ s(v, { children: [
37
37
  /* @__PURE__ */ e(
38
38
  "span",
39
39
  {
40
- className: `px-2 py-1 font-medium ${a ? "text-blue-700 bg-blue-100" : "text-gray-500 bg-gray-50"}`,
41
- children: t
40
+ className: `px-2 py-1 font-medium ${o ? "text-blue-700 bg-blue-100" : "text-gray-500 bg-gray-50"}`,
41
+ children: r
42
42
  }
43
43
  ),
44
- r !== void 0 && r !== "" && /* @__PURE__ */ e(
44
+ t !== void 0 && t !== "" && /* @__PURE__ */ e(
45
45
  "span",
46
46
  {
47
- className: `px-2 py-1 font-mono border-l ${a ? "text-blue-700 bg-blue-100 border-blue-200" : "text-gray-900 bg-white border-gray-200"}`,
48
- children: r
47
+ className: `px-2 py-1 font-mono border-l ${o ? "text-blue-700 bg-blue-100 border-blue-200" : "text-gray-900 bg-white border-gray-200"}`,
48
+ children: t
49
49
  }
50
50
  )
51
- ] }), i = `inline-flex items-center overflow-hidden rounded-md border text-xs ${a ? "border-blue-300" : "border-gray-200"}`;
52
- return o ? /* @__PURE__ */ l("span", { className: i, children: [
53
- s,
51
+ ] }), d = `inline-flex items-center overflow-hidden rounded-md border text-xs ${o ? "border-blue-300" : "border-gray-200"}`;
52
+ return a ? /* @__PURE__ */ s("span", { className: d, children: [
53
+ l,
54
54
  /* @__PURE__ */ e(
55
55
  "button",
56
56
  {
57
57
  type: "button",
58
- onClick: o,
59
- title: g,
60
- "aria-label": `Remove ${r !== void 0 ? `${t}=${r}` : t}`,
61
- className: `flex items-center px-1.5 py-1 border-l cursor-pointer transition-colors ${a ? "bg-blue-100 border-blue-200 text-blue-500 hover:bg-blue-200 hover:text-blue-700" : "border-gray-200 text-gray-400 hover:bg-gray-100 hover:text-gray-600"}`,
62
- children: /* @__PURE__ */ e(v, { className: "w-3 h-3" })
58
+ onClick: a,
59
+ title: m,
60
+ "aria-label": `Remove ${t !== void 0 ? `${r}=${t}` : r}`,
61
+ className: `flex items-center px-1.5 py-1 border-l cursor-pointer transition-colors ${o ? "bg-blue-100 border-blue-200 text-blue-500 hover:bg-blue-200 hover:text-blue-700" : "border-gray-200 text-gray-400 hover:bg-gray-100 hover:text-gray-600"}`,
62
+ children: /* @__PURE__ */ e(w, { className: "w-3 h-3" })
63
63
  }
64
64
  )
65
65
  ] }) : n ? /* @__PURE__ */ e(
@@ -67,13 +67,13 @@ function V({
67
67
  {
68
68
  type: "button",
69
69
  onClick: n,
70
- title: g,
71
- className: `${i} cursor-pointer transition-colors ${a ? "" : "hover:border-gray-300"}`,
72
- children: s
70
+ title: m,
71
+ className: `${d} cursor-pointer transition-colors ${o ? "" : "hover:border-gray-300"}`,
72
+ children: l
73
73
  }
74
- ) : /* @__PURE__ */ e("span", { className: i, children: s });
74
+ ) : /* @__PURE__ */ e("span", { className: d, children: l });
75
75
  }
76
- const _ = {
76
+ const K = {
77
77
  solid: {
78
78
  blue: "bg-blue-600 text-white hover:bg-blue-700",
79
79
  purple: "bg-purple-600 text-white hover:bg-purple-700",
@@ -98,129 +98,158 @@ const _ = {
98
98
  orange: "text-orange-600 hover:bg-orange-50",
99
99
  gray: "text-gray-600 hover:bg-gray-100"
100
100
  }
101
- }, B = {
101
+ }, P = {
102
102
  sm: "px-2.5 py-1.5 text-xs gap-1.5",
103
103
  md: "px-3 py-2 text-sm gap-2"
104
- }, M = {
104
+ }, U = {
105
105
  solid: "shadow-sm hover:shadow-md",
106
106
  soft: "shadow-sm hover:shadow",
107
107
  ghost: ""
108
108
  };
109
109
  function X({
110
- variant: t = "soft",
111
- tone: r = "blue",
110
+ variant: r = "soft",
111
+ tone: t = "blue",
112
112
  size: n = "md",
113
- icon: o,
114
- loading: a = !1,
115
- disabled: g = !1,
116
- type: s = "button",
117
- title: i,
118
- onClick: u,
119
- to: c,
120
- href: m,
121
- target: f,
122
- className: d = "",
123
- children: b
113
+ icon: a,
114
+ loading: o = !1,
115
+ disabled: m = !1,
116
+ type: l = "button",
117
+ title: d,
118
+ onClick: p,
119
+ to: g,
120
+ href: h,
121
+ target: i,
122
+ className: b = "",
123
+ children: c
124
124
  }) {
125
- const x = `inline-flex items-center justify-center font-medium rounded-lg transition-colors duration-100 cursor-pointer active:scale-[.98] ${B[n]} ${M[t]} ${_[t][r]} ${d}`, p = /* @__PURE__ */ l(y, { children: [
126
- a ? /* @__PURE__ */ e(E, { className: "w-4 h-4 animate-spin" }) : o,
127
- b
125
+ const u = `inline-flex items-center justify-center font-medium rounded-lg transition-colors duration-100 cursor-pointer active:scale-[.98] ${P[n]} ${U[r]} ${K[r][t]} ${b}`, x = /* @__PURE__ */ s(v, { children: [
126
+ o ? /* @__PURE__ */ e(j, { className: "w-4 h-4 animate-spin" }) : a,
127
+ c
128
128
  ] });
129
- return c ? /* @__PURE__ */ e(h, { to: c, className: x, title: i, children: p }) : m ? /* @__PURE__ */ e(
129
+ return g ? /* @__PURE__ */ e(f, { to: g, className: u, title: d, children: x }) : h ? /* @__PURE__ */ e(
130
130
  "a",
131
131
  {
132
- href: m,
133
- target: f,
134
- rel: f === "_blank" ? "noopener noreferrer" : void 0,
135
- className: x,
136
- title: i,
137
- children: p
132
+ href: h,
133
+ target: i,
134
+ rel: i === "_blank" ? "noopener noreferrer" : void 0,
135
+ className: u,
136
+ title: d,
137
+ children: x
138
138
  }
139
139
  ) : /* @__PURE__ */ e(
140
140
  "button",
141
141
  {
142
- type: s,
143
- onClick: u,
144
- disabled: g || a,
145
- title: i,
146
- className: `${x} disabled:opacity-50 disabled:cursor-not-allowed`,
147
- children: p
142
+ type: l,
143
+ onClick: p,
144
+ disabled: m || o,
145
+ title: d,
146
+ className: `${u} disabled:opacity-50 disabled:cursor-not-allowed`,
147
+ children: x
148
148
  }
149
149
  );
150
150
  }
151
151
  function $({
152
- className: t = "",
153
- children: r
152
+ className: r = "",
153
+ children: t
154
154
  }) {
155
155
  return /* @__PURE__ */ e(
156
156
  "div",
157
157
  {
158
- className: `bg-white rounded-xl border border-gray-200/80 shadow-sm ${t}`,
159
- children: r
158
+ className: `bg-white rounded-xl border border-gray-200/80 shadow-sm ${r}`,
159
+ children: t
160
160
  }
161
161
  );
162
162
  }
163
- function Y({
164
- icon: t,
165
- title: r,
163
+ function W({
164
+ icon: r,
165
+ title: t,
166
166
  theme: n,
167
- count: o,
168
- actions: a,
169
- bodyClassName: g = "p-5",
170
- className: s = "",
171
- children: i
167
+ count: a,
168
+ actions: o,
169
+ bodyClassName: m = "p-5",
170
+ className: l = "",
171
+ children: d
172
172
  }) {
173
- return /* @__PURE__ */ l($, { className: `overflow-hidden ${s}`, children: [
174
- /* @__PURE__ */ l(
173
+ return /* @__PURE__ */ s($, { className: `overflow-hidden ${l}`, children: [
174
+ /* @__PURE__ */ s(
175
175
  "div",
176
176
  {
177
177
  className: `px-4 py-3 flex items-center justify-between border-b border-black/5 ${n.header}`,
178
178
  children: [
179
- /* @__PURE__ */ l("h4", { className: "text-sm font-semibold flex items-center", children: [
180
- t && /* @__PURE__ */ e(t, { className: "w-4 h-4 mr-2" }),
181
- r
179
+ /* @__PURE__ */ s("h4", { className: "text-sm font-semibold flex items-center", children: [
180
+ r && /* @__PURE__ */ e(r, { className: "w-4 h-4 mr-2" }),
181
+ t
182
182
  ] }),
183
- (a || o !== void 0) && /* @__PURE__ */ l("div", { className: "flex items-center gap-2", children: [
184
- a,
185
- o !== void 0 && /* @__PURE__ */ e(
183
+ (o || a !== void 0) && /* @__PURE__ */ s("div", { className: "flex items-center gap-2", children: [
184
+ o,
185
+ a !== void 0 && /* @__PURE__ */ e(
186
186
  "span",
187
187
  {
188
188
  className: `text-xs font-semibold px-2 py-0.5 rounded-full ${n.badge}`,
189
- children: o
189
+ children: a
190
190
  }
191
191
  )
192
192
  ] })
193
193
  ]
194
194
  }
195
195
  ),
196
- /* @__PURE__ */ e("div", { className: g, children: i })
196
+ /* @__PURE__ */ e("div", { className: m, children: d })
197
197
  ] });
198
198
  }
199
- function z({
200
- icon: t,
201
- title: r,
199
+ const z = {
200
+ red: { accent: "border-l-red-500", chip: "bg-red-50 text-red-600" },
201
+ amber: { accent: "border-l-amber-500", chip: "bg-amber-50 text-amber-700" }
202
+ };
203
+ function ee({
204
+ tone: r = "red",
205
+ title: t,
206
+ severity: n,
207
+ action: a,
208
+ children: o
209
+ }) {
210
+ const { accent: m, chip: l } = z[r];
211
+ return /* @__PURE__ */ e($, { className: `border-l-4 ${m} px-5 py-4`, children: /* @__PURE__ */ s("div", { className: "flex items-start justify-between gap-4", children: [
212
+ /* @__PURE__ */ s("div", { className: "min-w-0 flex-1", children: [
213
+ /* @__PURE__ */ s("div", { className: "flex items-center gap-2.5 flex-wrap", children: [
214
+ /* @__PURE__ */ e("h4", { className: "text-base font-semibold text-gray-900", children: t }),
215
+ n && /* @__PURE__ */ e(
216
+ "span",
217
+ {
218
+ className: `text-[11px] font-bold uppercase tracking-wide px-1.5 py-0.5 rounded ${l}`,
219
+ children: n
220
+ }
221
+ )
222
+ ] }),
223
+ /* @__PURE__ */ e("div", { className: "mt-1 text-sm text-gray-600", children: o })
224
+ ] }),
225
+ a && /* @__PURE__ */ e("div", { className: "shrink-0 text-sm", children: a })
226
+ ] }) });
227
+ }
228
+ function re({
229
+ icon: r,
230
+ title: t,
202
231
  count: n,
203
- theme: o,
204
- actions: a,
205
- footer: g,
206
- children: s
232
+ theme: a,
233
+ actions: o,
234
+ footer: m,
235
+ children: l
207
236
  }) {
208
- return /* @__PURE__ */ l($, { className: "overflow-hidden flex flex-col", children: [
209
- /* @__PURE__ */ l(
237
+ return /* @__PURE__ */ s($, { className: "overflow-hidden flex flex-col", children: [
238
+ /* @__PURE__ */ s(
210
239
  "div",
211
240
  {
212
- className: `px-4 py-3 flex items-center justify-between border-b border-black/5 ${o.header}`,
241
+ className: `px-4 py-3 flex items-center justify-between border-b border-black/5 ${a.header}`,
213
242
  children: [
214
- /* @__PURE__ */ l("h4", { className: "text-sm font-semibold flex items-center", children: [
215
- t && /* @__PURE__ */ e(t, { className: "w-4 h-4 mr-2" }),
216
- r
243
+ /* @__PURE__ */ s("h4", { className: "text-sm font-semibold flex items-center", children: [
244
+ r && /* @__PURE__ */ e(r, { className: "w-4 h-4 mr-2" }),
245
+ t
217
246
  ] }),
218
- /* @__PURE__ */ l("div", { className: "flex items-center gap-2", children: [
219
- a,
247
+ /* @__PURE__ */ s("div", { className: "flex items-center gap-2", children: [
248
+ o,
220
249
  n !== void 0 && /* @__PURE__ */ e(
221
250
  "span",
222
251
  {
223
- className: `text-xs font-semibold px-2 py-0.5 rounded-full ${o.badge}`,
252
+ className: `text-xs font-semibold px-2 py-0.5 rounded-full ${a.badge}`,
224
253
  children: n
225
254
  }
226
255
  )
@@ -228,41 +257,41 @@ function z({
228
257
  ]
229
258
  }
230
259
  ),
231
- /* @__PURE__ */ e("div", { className: "divide-y divide-gray-100", children: s }),
232
- g
260
+ /* @__PURE__ */ e("div", { className: "divide-y divide-gray-100", children: l }),
261
+ m
233
262
  ] });
234
263
  }
235
- function G({
236
- to: t,
237
- onClick: r,
264
+ function te({
265
+ to: r,
266
+ onClick: t,
238
267
  hover: n = "hover:bg-gray-50",
239
- className: o = "",
240
- children: a
268
+ className: a = "",
269
+ children: o
241
270
  }) {
242
- const s = `flex items-center justify-between px-4 py-3 transition-colors ${n} ${!!(t || r) ? "cursor-pointer" : ""} ${o}`;
243
- return t ? /* @__PURE__ */ e(h, { to: t, className: s, children: a }) : r ? /* @__PURE__ */ e(
271
+ const l = `flex items-center justify-between px-4 py-3 transition-colors ${n} ${!!(r || t) ? "cursor-pointer" : ""} ${a}`;
272
+ return r ? /* @__PURE__ */ e(f, { to: r, className: l, children: o }) : t ? /* @__PURE__ */ e(
244
273
  "button",
245
274
  {
246
275
  type: "button",
247
- onClick: r,
248
- className: `w-full text-left ${s}`,
249
- children: a
276
+ onClick: t,
277
+ className: `w-full text-left ${l}`,
278
+ children: o
250
279
  }
251
- ) : /* @__PURE__ */ e("div", { className: s, children: a });
280
+ ) : /* @__PURE__ */ e("div", { className: l, children: o });
252
281
  }
253
- function H({
254
- to: t,
255
- count: r,
282
+ function ne({
283
+ to: r,
284
+ count: t,
256
285
  noun: n = "items"
257
286
  }) {
258
- return /* @__PURE__ */ l(
259
- h,
287
+ return /* @__PURE__ */ s(
288
+ f,
260
289
  {
261
- to: t,
290
+ to: r,
262
291
  className: "block px-4 py-2.5 text-sm font-medium text-blue-600 hover:text-blue-700 hover:bg-gray-50 transition-colors",
263
292
  children: [
264
293
  "View all ",
265
- r,
294
+ t,
266
295
  " ",
267
296
  n,
268
297
  " →"
@@ -270,16 +299,16 @@ function H({
270
299
  }
271
300
  );
272
301
  }
273
- const O = (t) => `https://flagicons.lipis.dev/flags/4x3/${t.toLowerCase()}.svg`;
274
- function Z({
275
- countryCode: t,
276
- country: r
302
+ const F = (r) => `https://flagicons.lipis.dev/flags/4x3/${r.toLowerCase()}.svg`;
303
+ function ae({
304
+ countryCode: r,
305
+ country: t
277
306
  }) {
278
- return t ? /* @__PURE__ */ e(
307
+ return r ? /* @__PURE__ */ e(
279
308
  "img",
280
309
  {
281
- src: O(t),
282
- alt: r || "Country flag",
310
+ src: F(r),
311
+ alt: t || "Country flag",
283
312
  className: "w-4 h-3 flex-shrink-0 rounded-sm ring-1 ring-black/5",
284
313
  onError: (n) => {
285
314
  n.target.style.display = "none";
@@ -287,107 +316,211 @@ function Z({
287
316
  }
288
317
  ) : null;
289
318
  }
290
- function q({
291
- to: t,
292
- onClick: r,
319
+ function oe({
320
+ to: r,
321
+ onClick: t,
293
322
  children: n
294
323
  }) {
295
- const o = "inline-flex items-center gap-2 text-sm font-medium text-gray-600 hover:text-gray-900 transition-colors cursor-pointer", a = /* @__PURE__ */ l(y, { children: [
296
- /* @__PURE__ */ e(S, { className: "w-4 h-4" }),
324
+ const a = "inline-flex items-center gap-2 text-sm font-medium text-gray-600 hover:text-gray-900 transition-colors cursor-pointer", o = /* @__PURE__ */ s(v, { children: [
325
+ /* @__PURE__ */ e(D, { className: "w-4 h-4" }),
297
326
  /* @__PURE__ */ e("span", { children: n })
298
327
  ] });
299
- return t ? /* @__PURE__ */ e(h, { to: t, className: o, children: a }) : /* @__PURE__ */ e("button", { type: "button", onClick: r, className: o, children: a });
328
+ return r ? /* @__PURE__ */ e(f, { to: r, className: a, children: o }) : /* @__PURE__ */ e("button", { type: "button", onClick: t, className: a, children: o });
300
329
  }
301
- function J({ items: t }) {
302
- return /* @__PURE__ */ e("div", { className: "border-b border-gray-200", children: /* @__PURE__ */ e("nav", { className: "-mb-px flex space-x-8", children: t.map((r) => {
303
- const n = r.active ? "py-2 px-1 border-b-2 border-blue-500 text-blue-600 font-medium text-sm" : "py-2 px-1 border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 font-medium text-sm transition-colors cursor-pointer";
304
- return r.to && !r.active ? /* @__PURE__ */ e(
305
- h,
306
- {
307
- to: r.to,
308
- state: r.state,
309
- className: n,
310
- children: r.label
311
- },
312
- r.label
313
- ) : /* @__PURE__ */ e("span", { className: n, children: r.label }, r.label);
314
- }) }) });
330
+ function se({
331
+ items: r,
332
+ actions: t
333
+ }) {
334
+ return /* @__PURE__ */ s("div", { className: "border-b border-gray-200 flex items-end justify-between gap-4", children: [
335
+ /* @__PURE__ */ e("nav", { className: "-mb-px flex space-x-8", children: r.map((n) => {
336
+ const a = n.active ? "py-2 px-1 border-b-2 border-blue-500 text-blue-600 font-medium text-sm" : "py-2 px-1 border-b-2 border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300 font-medium text-sm transition-colors cursor-pointer";
337
+ return n.to && !n.active ? /* @__PURE__ */ e(
338
+ f,
339
+ {
340
+ to: n.to,
341
+ state: n.state,
342
+ className: a,
343
+ children: n.label
344
+ },
345
+ n.label
346
+ ) : /* @__PURE__ */ e("span", { className: a, children: n.label }, n.label);
347
+ }) }),
348
+ t && /* @__PURE__ */ e("div", { className: "flex items-center gap-2 pb-1.5", children: t })
349
+ ] });
315
350
  }
316
- function Q({ items: t }) {
317
- return /* @__PURE__ */ e("nav", { className: "space-y-1", children: t.map((r) => {
318
- const n = r.icon, o = `group/side relative flex items-center gap-3 h-10 rounded-md px-3 text-sm transition-all duration-200 cursor-pointer ${r.active ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-600 hover:bg-gray-100 hover:text-gray-900"}`, a = /* @__PURE__ */ l(y, { children: [
351
+ function le({ items: r }) {
352
+ return /* @__PURE__ */ e("nav", { className: "space-y-1", children: r.map((t) => {
353
+ const n = t.icon, a = `group/side relative flex items-center gap-3 h-10 rounded-md px-3 text-sm transition-all duration-200 cursor-pointer ${t.active ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-600 hover:bg-gray-100 hover:text-gray-900"}`, o = /* @__PURE__ */ s(v, { children: [
319
354
  /* @__PURE__ */ e(
320
355
  "span",
321
356
  {
322
- className: `absolute left-0 top-1.5 bottom-1.5 w-[3px] rounded-r-full bg-blue-600 transition-all duration-300 ease-out ${r.active ? "opacity-100 scale-y-100" : "opacity-0 scale-y-0"}`
357
+ className: `absolute left-0 top-1.5 bottom-1.5 w-[3px] rounded-r-full bg-blue-600 transition-all duration-300 ease-out ${t.active ? "opacity-100 scale-y-100" : "opacity-0 scale-y-0"}`
323
358
  }
324
359
  ),
325
360
  n && /* @__PURE__ */ e(n, { className: "w-[18px] h-[18px] shrink-0 transition-transform duration-200 group-hover/side:scale-110" }),
326
- /* @__PURE__ */ e("span", { className: "truncate", children: r.label })
361
+ /* @__PURE__ */ e("span", { className: "truncate", children: t.label })
327
362
  ] });
328
- return r.active ? /* @__PURE__ */ e("span", { className: o, "aria-current": "page", children: a }, r.to) : /* @__PURE__ */ e(h, { to: r.to, className: o, children: a }, r.to);
363
+ return t.active ? /* @__PURE__ */ e("span", { className: a, "aria-current": "page", children: o }, t.to) : /* @__PURE__ */ e(f, { to: t.to, className: a, children: o }, t.to);
329
364
  }) });
330
365
  }
331
- function W({
332
- label: t,
333
- icon: r,
366
+ function ie({
367
+ label: r,
368
+ icon: t,
334
369
  iconClassName: n = "text-gray-400",
335
- children: o
370
+ children: a
336
371
  }) {
337
- return /* @__PURE__ */ l("div", { className: "flex items-center justify-between gap-4", children: [
338
- /* @__PURE__ */ l("span", { className: "text-gray-700 flex items-center flex-shrink-0", children: [
339
- r && /* @__PURE__ */ e(r, { className: `w-4 h-4 mr-2 ${n}` }),
340
- t
372
+ return /* @__PURE__ */ s("div", { className: "flex items-center justify-between gap-4", children: [
373
+ /* @__PURE__ */ s("span", { className: "text-gray-700 flex items-center flex-shrink-0", children: [
374
+ t && /* @__PURE__ */ e(t, { className: `w-4 h-4 mr-2 ${n}` }),
375
+ r
341
376
  ] }),
342
- /* @__PURE__ */ e("span", { className: "text-sm text-gray-900 text-right min-w-0", children: o })
377
+ /* @__PURE__ */ e("span", { className: "text-sm text-gray-900 text-right min-w-0", children: a })
343
378
  ] });
344
379
  }
345
- function ee({
346
- className: t = "space-y-6",
347
- children: r
380
+ const V = {
381
+ blue: "text-blue-600",
382
+ purple: "text-purple-600",
383
+ red: "text-red-600",
384
+ green: "text-green-600",
385
+ orange: "text-orange-600",
386
+ gray: "text-gray-500"
387
+ }, L = "w-full flex items-start gap-3 px-3 py-2 text-left transition-colors hover:bg-gray-50 cursor-pointer";
388
+ function de({
389
+ label: r,
390
+ items: t,
391
+ icon: n,
392
+ variant: a = "soft",
393
+ tone: o = "gray",
394
+ size: m = "md",
395
+ align: l = "right",
396
+ className: d = ""
397
+ }) {
398
+ const [p, g] = M(!1), h = _(null);
399
+ return A(() => {
400
+ if (!p) return;
401
+ const i = (c) => {
402
+ var u;
403
+ (u = h.current) != null && u.contains(c.target) || g(!1);
404
+ }, b = (c) => {
405
+ c.key === "Escape" && g(!1);
406
+ };
407
+ return document.addEventListener("mousedown", i), document.addEventListener("keydown", b), () => {
408
+ document.removeEventListener("mousedown", i), document.removeEventListener("keydown", b);
409
+ };
410
+ }, [p]), /* @__PURE__ */ s("div", { className: `relative ${d}`, ref: h, children: [
411
+ /* @__PURE__ */ s(
412
+ X,
413
+ {
414
+ variant: a,
415
+ tone: o,
416
+ size: m,
417
+ icon: n,
418
+ onClick: () => g((i) => !i),
419
+ children: [
420
+ r,
421
+ /* @__PURE__ */ e(
422
+ O,
423
+ {
424
+ className: `w-4 h-4 transition-transform duration-200 ${p ? "rotate-180" : ""}`
425
+ }
426
+ )
427
+ ]
428
+ }
429
+ ),
430
+ p && /* @__PURE__ */ e(
431
+ "div",
432
+ {
433
+ className: `absolute ${l === "right" ? "right-0" : "left-0"} mt-2 w-64 py-1 bg-white rounded-lg shadow-lg border border-gray-200 z-50 animate-dropdown-in`,
434
+ children: t.map((i, b) => {
435
+ const c = V[i.tone ?? "gray"], u = /* @__PURE__ */ s(v, { children: [
436
+ i.icon && /* @__PURE__ */ e(
437
+ "span",
438
+ {
439
+ className: `flex items-center gap-1 mt-0.5 flex-shrink-0 ${c}`,
440
+ children: i.icon
441
+ }
442
+ ),
443
+ /* @__PURE__ */ s("span", { className: "min-w-0", children: [
444
+ /* @__PURE__ */ e("span", { className: "block text-sm font-medium text-gray-900", children: i.label }),
445
+ i.description && /* @__PURE__ */ e("span", { className: "block text-xs text-gray-500 mt-0.5 break-all", children: i.description })
446
+ ] })
447
+ ] });
448
+ return i.href ? /* @__PURE__ */ e(
449
+ "a",
450
+ {
451
+ href: i.href,
452
+ target: i.target,
453
+ rel: i.target === "_blank" ? "noopener noreferrer" : void 0,
454
+ className: L,
455
+ onClick: () => g(!1),
456
+ children: u
457
+ },
458
+ b
459
+ ) : /* @__PURE__ */ e(
460
+ "button",
461
+ {
462
+ type: "button",
463
+ disabled: i.disabled,
464
+ onClick: () => {
465
+ var x;
466
+ i.keepOpen || g(!1), (x = i.onClick) == null || x.call(i);
467
+ },
468
+ className: `${L} disabled:opacity-50 disabled:cursor-not-allowed`,
469
+ children: u
470
+ },
471
+ b
472
+ );
473
+ })
474
+ }
475
+ )
476
+ ] });
477
+ }
478
+ function ce({
479
+ className: r = "space-y-6",
480
+ children: t
348
481
  }) {
349
482
  return /* @__PURE__ */ e(
350
483
  "div",
351
484
  {
352
- className: `flex-1 overflow-y-auto px-4 sm:px-6 lg:px-8 py-6 ${t}`,
353
- children: r
485
+ className: `flex-1 overflow-y-auto px-4 sm:px-6 lg:px-8 py-6 ${r}`,
486
+ children: t
354
487
  }
355
488
  );
356
489
  }
357
- function re({
358
- value: t,
359
- onChange: r,
490
+ function ge({
491
+ value: r,
492
+ onChange: t,
360
493
  placeholder: n = "Search...",
361
- className: o = "w-full",
362
- slashToFocus: a = !1
494
+ className: a = "w-full",
495
+ slashToFocus: o = !1
363
496
  }) {
364
- const g = j(null);
497
+ const m = _(null);
365
498
  return A(() => {
366
- if (!a) return;
367
- function s(i) {
368
- var c;
369
- if (i.key !== "/" || i.ctrlKey || i.metaKey || i.altKey) return;
370
- const u = i.target;
371
- u.tagName === "INPUT" || u.tagName === "TEXTAREA" || u.tagName === "SELECT" || u.isContentEditable || (i.preventDefault(), (c = g.current) == null || c.focus());
499
+ if (!o) return;
500
+ function l(d) {
501
+ var g;
502
+ if (d.key !== "/" || d.ctrlKey || d.metaKey || d.altKey) return;
503
+ const p = d.target;
504
+ p.tagName === "INPUT" || p.tagName === "TEXTAREA" || p.tagName === "SELECT" || p.isContentEditable || (d.preventDefault(), (g = m.current) == null || g.focus());
372
505
  }
373
- return document.addEventListener("keydown", s), () => document.removeEventListener("keydown", s);
374
- }, [a]), /* @__PURE__ */ l("div", { className: `relative ${o}`, children: [
375
- /* @__PURE__ */ e(L, { className: "absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-4 h-4 pointer-events-none" }),
506
+ return document.addEventListener("keydown", l), () => document.removeEventListener("keydown", l);
507
+ }, [o]), /* @__PURE__ */ s("div", { className: `relative ${a}`, children: [
508
+ /* @__PURE__ */ e(R, { className: "absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 w-4 h-4 pointer-events-none" }),
376
509
  /* @__PURE__ */ e(
377
510
  "input",
378
511
  {
379
- ref: g,
512
+ ref: m,
380
513
  type: "text",
381
- value: t,
382
- onChange: (s) => r(s.target.value),
514
+ value: r,
515
+ onChange: (l) => t(l.target.value),
383
516
  placeholder: n,
384
517
  className: "w-full pl-10 pr-10 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm text-gray-900 placeholder-gray-400"
385
518
  }
386
519
  ),
387
- a && !t && /* @__PURE__ */ e("kbd", { className: "absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 text-xs border border-gray-300 rounded px-1 py-0.5 font-mono leading-none pointer-events-none", children: "/" })
520
+ o && !r && /* @__PURE__ */ e("kbd", { className: "absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 text-xs border border-gray-300 rounded px-1 py-0.5 font-mono leading-none pointer-events-none", children: "/" })
388
521
  ] });
389
522
  }
390
- const D = {
523
+ const H = {
391
524
  neutral: { badge: "bg-gray-100", icon: "text-gray-400" },
392
525
  green: { badge: "bg-green-100", icon: "text-green-600" },
393
526
  blue: { badge: "bg-blue-100", icon: "text-blue-600" },
@@ -395,102 +528,163 @@ const D = {
395
528
  red: { badge: "bg-red-100", icon: "text-red-600" },
396
529
  purple: { badge: "bg-purple-100", icon: "text-purple-600" }
397
530
  };
398
- function te({
399
- icon: t,
400
- label: r,
531
+ function be({
532
+ icon: r,
533
+ label: t,
401
534
  value: n,
402
- tone: o = "neutral"
535
+ tone: a = "neutral"
403
536
  }) {
404
- const a = D[o];
405
- return /* @__PURE__ */ l("div", { className: "flex items-center gap-4", children: [
537
+ const o = H[a];
538
+ return /* @__PURE__ */ s("div", { className: "flex items-center gap-4", children: [
406
539
  /* @__PURE__ */ e(
407
540
  "div",
408
541
  {
409
- className: `flex h-12 w-12 items-center justify-center rounded-xl ${a.badge}`,
410
- children: /* @__PURE__ */ e(t, { className: `w-6 h-6 ${a.icon}` })
542
+ className: `flex h-12 w-12 items-center justify-center rounded-xl ${o.badge}`,
543
+ children: /* @__PURE__ */ e(r, { className: `w-6 h-6 ${o.icon}` })
411
544
  }
412
545
  ),
413
- /* @__PURE__ */ l("div", { children: [
414
- /* @__PURE__ */ e("p", { className: "text-sm font-medium text-gray-500", children: r }),
546
+ /* @__PURE__ */ s("div", { children: [
547
+ /* @__PURE__ */ e("p", { className: "text-sm font-medium text-gray-500", children: t }),
415
548
  /* @__PURE__ */ e("p", { className: "text-3xl font-bold text-gray-900 tabular-nums", children: n })
416
549
  ] })
417
550
  ] });
418
551
  }
419
- const N = {
552
+ const S = {
420
553
  ok: "bg-green-500",
421
554
  down: "bg-red-500",
422
555
  unknown: "bg-gray-300"
423
- }, w = (t) => `${(t * 100).toFixed(4)}%`;
424
- function ne({
425
- from: t,
426
- to: r,
556
+ }, C = (r) => `${(r * 100).toFixed(4)}%`;
557
+ function ue({
558
+ from: r,
559
+ to: t,
560
+ spans: n,
561
+ buckets: a = 48,
562
+ height: o = "1.75rem",
563
+ renderTooltip: m
564
+ }) {
565
+ const [l, d] = M(null), p = r.getTime(), g = t.getTime() - p;
566
+ if (!(g > 0)) return null;
567
+ const h = g / a, i = Array.from({ length: a }, (c, u) => {
568
+ const x = p + u * h, N = x + h;
569
+ let y = 0;
570
+ for (const T of n) {
571
+ const k = Math.max(T.start.getTime(), x), E = Math.min(T.end.getTime(), N);
572
+ E > k && (y += E - k);
573
+ }
574
+ return {
575
+ start: new Date(x),
576
+ end: new Date(N),
577
+ downMs: y,
578
+ ratio: 1 - y / h
579
+ };
580
+ });
581
+ return /* @__PURE__ */ s("div", { className: "relative", children: [
582
+ l !== null && m && /* @__PURE__ */ e(
583
+ "div",
584
+ {
585
+ className: "pointer-events-none absolute bottom-full z-10 mb-2 whitespace-nowrap rounded-md bg-gray-900 px-2 py-1.5 text-[11px] leading-tight text-white shadow-lg",
586
+ style: ((c) => {
587
+ const u = (c + 0.5) / a;
588
+ return u < 0.15 ? { left: 0 } : u > 0.85 ? { right: 0 } : { left: `${u * 100}%`, transform: "translateX(-50%)" };
589
+ })(l),
590
+ children: m(i[l])
591
+ }
592
+ ),
593
+ /* @__PURE__ */ e(
594
+ "div",
595
+ {
596
+ className: "flex items-stretch gap-[2px]",
597
+ style: { height: o },
598
+ onMouseLeave: () => d(null),
599
+ children: i.map((c, u) => /* @__PURE__ */ e(
600
+ "div",
601
+ {
602
+ onMouseEnter: () => d(u),
603
+ className: `relative min-w-[2px] flex-1 cursor-pointer overflow-hidden rounded-[2px] bg-emerald-500 transition-opacity ${l === u ? "opacity-60" : ""}`,
604
+ children: c.downMs > 0 && /* @__PURE__ */ e(
605
+ "div",
606
+ {
607
+ className: "absolute inset-x-0 bottom-0 bg-red-500",
608
+ style: { height: `max(3px, ${(1 - c.ratio) * 100}%)` }
609
+ }
610
+ )
611
+ },
612
+ c.start.getTime()
613
+ ))
614
+ }
615
+ )
616
+ ] });
617
+ }
618
+ function me({
619
+ from: r,
620
+ to: t,
427
621
  lanes: n,
428
- baseline: o = "ok",
429
- ticks: a = 5,
430
- formatTick: g = (c) => c.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }),
431
- labelWidth: s = "8rem",
432
- rowHeight: i = "1.25rem",
433
- emptyLabel: u = "No data"
622
+ baseline: a = "ok",
623
+ ticks: o = 5,
624
+ formatTick: m = (g) => g.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }),
625
+ labelWidth: l = "8rem",
626
+ rowHeight: d = "1.25rem",
627
+ emptyLabel: p = "No data"
434
628
  }) {
435
- const c = t.getTime(), m = r.getTime() - c;
436
- if (!(m > 0) || n.length === 0)
437
- return /* @__PURE__ */ e("div", { className: "py-8 text-center text-sm text-gray-500", children: u });
438
- const f = Array.from(
439
- { length: Math.max(2, a) },
440
- (d, b) => new Date(c + m * b / (Math.max(2, a) - 1))
629
+ const g = r.getTime(), h = t.getTime() - g;
630
+ if (!(h > 0) || n.length === 0)
631
+ return /* @__PURE__ */ e("div", { className: "py-8 text-center text-sm text-gray-500", children: p });
632
+ const i = Array.from(
633
+ { length: Math.max(2, o) },
634
+ (b, c) => new Date(g + h * c / (Math.max(2, o) - 1))
441
635
  );
442
- return /* @__PURE__ */ l("div", { className: "space-y-1.5", children: [
443
- n.map((d) => /* @__PURE__ */ l("div", { className: "flex items-center gap-3", children: [
636
+ return /* @__PURE__ */ s("div", { className: "space-y-1.5", children: [
637
+ n.map((b) => /* @__PURE__ */ s("div", { className: "flex items-center gap-3", children: [
444
638
  /* @__PURE__ */ e(
445
639
  "div",
446
640
  {
447
641
  className: "shrink-0 truncate font-mono text-xs text-gray-600",
448
- style: { width: s },
449
- title: d.name,
450
- children: d.label ?? d.name
642
+ style: { width: l },
643
+ title: b.name,
644
+ children: b.label ?? b.name
451
645
  }
452
646
  ),
453
647
  /* @__PURE__ */ e(
454
648
  "div",
455
649
  {
456
- className: `relative flex-1 overflow-hidden rounded-sm ${N[o]}`,
457
- style: { height: i },
458
- children: d.spans.map((b) => {
459
- const x = Math.max(b.start.getTime(), c), p = Math.min(b.end.getTime(), c + m);
460
- if (p <= x) return null;
461
- const T = (x - c) / m, k = (p - x) / m;
650
+ className: `relative flex-1 overflow-hidden rounded-sm ${S[a]}`,
651
+ style: { height: d },
652
+ children: b.spans.map((c) => {
653
+ const u = Math.max(c.start.getTime(), g), x = Math.min(c.end.getTime(), g + h);
654
+ if (x <= u) return null;
655
+ const N = (u - g) / h, y = (x - u) / h;
462
656
  return /* @__PURE__ */ e(
463
657
  "div",
464
658
  {
465
- className: `absolute inset-y-0 ${N[b.tone]}`,
659
+ className: `absolute inset-y-0 ${S[c.tone]}`,
466
660
  style: {
467
- left: w(T),
468
- width: `max(2px, ${w(k)})`
661
+ left: C(N),
662
+ width: `max(2px, ${C(y)})`
469
663
  },
470
- title: b.label
664
+ title: c.label
471
665
  },
472
- `${b.start.getTime()}-${b.end.getTime()}`
666
+ `${c.start.getTime()}-${c.end.getTime()}`
473
667
  );
474
668
  })
475
669
  }
476
670
  ),
477
- d.trailing !== void 0 && /* @__PURE__ */ e("div", { className: "w-16 shrink-0 text-right font-mono text-xs tabular-nums text-gray-600", children: d.trailing })
478
- ] }, d.name)),
671
+ b.trailing !== void 0 && /* @__PURE__ */ e("div", { className: "w-16 shrink-0 text-right font-mono text-xs tabular-nums text-gray-600", children: b.trailing })
672
+ ] }, b.name)),
479
673
  /* @__PURE__ */ e(
480
674
  "div",
481
675
  {
482
676
  className: "flex justify-between pt-1 text-[11px] tabular-nums text-gray-400",
483
677
  style: {
484
- marginLeft: s,
678
+ marginLeft: l,
485
679
  paddingLeft: "0.75rem",
486
- marginRight: n.some((d) => d.trailing !== void 0) ? "4rem" : void 0
680
+ marginRight: n.some((b) => b.trailing !== void 0) ? "4rem" : void 0
487
681
  },
488
- children: f.map((d) => /* @__PURE__ */ e("span", { children: g(d) }, d.getTime()))
682
+ children: i.map((b) => /* @__PURE__ */ e("span", { children: m(b) }, b.getTime()))
489
683
  }
490
684
  )
491
685
  ] });
492
686
  }
493
- const ae = {
687
+ const pe = {
494
688
  blue: {
495
689
  header: "bg-blue-50 text-blue-800",
496
690
  hover: "hover:bg-blue-50",
@@ -532,24 +726,24 @@ const ae = {
532
726
  badge: "bg-gray-200 text-gray-700"
533
727
  }
534
728
  };
535
- function oe({
536
- toast: t,
537
- onClose: r
729
+ function he({
730
+ toast: r,
731
+ onClose: t
538
732
  }) {
539
- return t ? /* @__PURE__ */ e(
733
+ return r ? /* @__PURE__ */ e(
540
734
  "div",
541
735
  {
542
- className: `fixed top-4 right-4 z-50 p-4 rounded-lg shadow-lg border transition-all duration-300 ease-in-out ${t.type === "success" ? "bg-green-50 text-green-800 border-green-200" : "bg-red-50 text-red-800 border-red-200"}`,
543
- children: /* @__PURE__ */ l("div", { className: "flex items-center space-x-2", children: [
544
- t.type === "success" ? /* @__PURE__ */ e(C, { className: "w-5 h-5 text-green-600" }) : /* @__PURE__ */ e(v, { className: "w-5 h-5 text-red-600" }),
545
- /* @__PURE__ */ e("span", { className: "text-sm font-medium", children: t.message }),
736
+ className: `fixed top-4 right-4 z-50 p-4 rounded-lg shadow-lg border transition-all duration-300 ease-in-out ${r.type === "success" ? "bg-green-50 text-green-800 border-green-200" : "bg-red-50 text-red-800 border-red-200"}`,
737
+ children: /* @__PURE__ */ s("div", { className: "flex items-center space-x-2", children: [
738
+ r.type === "success" ? /* @__PURE__ */ e(B, { className: "w-5 h-5 text-green-600" }) : /* @__PURE__ */ e(w, { className: "w-5 h-5 text-red-600" }),
739
+ /* @__PURE__ */ e("span", { className: "text-sm font-medium", children: r.message }),
546
740
  /* @__PURE__ */ e(
547
741
  "button",
548
742
  {
549
743
  type: "button",
550
- onClick: r,
744
+ onClick: t,
551
745
  className: "ml-2 text-gray-400 hover:text-gray-600 cursor-pointer",
552
- children: /* @__PURE__ */ e(v, { className: "w-4 h-4" })
746
+ children: /* @__PURE__ */ e(w, { className: "w-4 h-4" })
553
747
  }
554
748
  )
555
749
  ] })
@@ -557,24 +751,27 @@ function oe({
557
751
  ) : null;
558
752
  }
559
753
  export {
560
- R as BADGE_COLORS,
561
- q as BackLink,
562
- U as Badge,
754
+ ee as AlertBanner,
755
+ I as BADGE_COLORS,
756
+ oe as BackLink,
757
+ J as Badge,
563
758
  X as Button,
564
759
  $ as Card,
565
- Z as CountryFlag,
566
- W as InfoRow,
567
- V as LabelChip,
568
- G as ListRow,
569
- ee as PageContainer,
570
- Y as Panel,
571
- ae as SECTION_THEMES,
572
- re as SearchInput,
573
- z as SectionCard,
574
- Q as SideNav,
575
- te as StatCard,
576
- ne as StateTimeline,
577
- J as TabNav,
578
- oe as Toast,
579
- H as ViewAllFooter
760
+ ae as CountryFlag,
761
+ de as DropdownMenu,
762
+ ie as InfoRow,
763
+ Q as LabelChip,
764
+ te as ListRow,
765
+ ce as PageContainer,
766
+ W as Panel,
767
+ pe as SECTION_THEMES,
768
+ ge as SearchInput,
769
+ re as SectionCard,
770
+ le as SideNav,
771
+ be as StatCard,
772
+ me as StateTimeline,
773
+ se as TabNav,
774
+ he as Toast,
775
+ ue as UptimeBars,
776
+ ne as ViewAllFooter
580
777
  };
@@ -18,6 +18,33 @@ export interface TimelineLane {
18
18
  trailing?: ReactNode;
19
19
  }
20
20
  export type TimelineTone = "ok" | "down" | "unknown";
21
+ export interface UptimeBucket {
22
+ start: Date;
23
+ end: Date;
24
+ /** Downtime inside this bucket, in ms. */
25
+ downMs: number;
26
+ /** Fraction of the bucket spent up, 0..1. */
27
+ ratio: number;
28
+ }
29
+ /**
30
+ * Status-page style availability bars: the window is split into equal buckets,
31
+ * each drawn green with a red portion sized to the downtime inside it.
32
+ *
33
+ * The proportion is the point — colouring a whole bucket red for a 30-second
34
+ * blip makes a flapping device look permanently offline. A red sliver reads as
35
+ * "briefly down", a full red bar as "down the whole time", with no intermediate
36
+ * colour whose meaning has to be guessed.
37
+ */
38
+ export declare function UptimeBars({ from, to, spans, buckets, height, renderTooltip, }: {
39
+ from: Date;
40
+ to: Date;
41
+ /** Down intervals in absolute time; clipped to the window. */
42
+ spans: TimelineSpan[];
43
+ buckets?: number;
44
+ height?: string;
45
+ /** Hover card contents for a bucket. No tooltip is shown when omitted. */
46
+ renderTooltip?: (bucket: UptimeBucket) => ReactNode;
47
+ }): import("react/jsx-runtime").JSX.Element | null;
21
48
  /**
22
49
  * Horizontal state timeline: one lane per series, spans drawn as coloured bands
23
50
  * against a baseline.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teton/smith-ui",
3
- "version": "0.2.180",
3
+ "version": "0.2.181",
4
4
  "description": "Smith dashboard design-system primitives (React + Tailwind CSS v4).",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {