@ramme-io/ui 4.1.1 → 4.2.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.
@@ -1,9 +1,9 @@
1
- import { jsxs as a, jsx as e } from "react/jsx-runtime";
1
+ import { jsxs as s, jsx as e } from "react/jsx-runtime";
2
2
  import _ from "react";
3
3
  import { ResponsiveContainer as F, ComposedChart as W, CartesianGrid as K, XAxis as U, YAxis as A, Tooltip as $, Legend as j, Line as S, Bar as z } from "recharts";
4
4
  import { Card as E, CardHeader as H, CardTitle as L, CardContent as V } from "../../layout/Card.js";
5
5
  import { useChartTheme as Y } from "../../../lib/hooks/useChartTheme.js";
6
- function G(s, p, C) {
6
+ function G(a, p, C) {
7
7
  const N = Date.now(), M = p && Array.isArray(p) && p.length > 0 ? p : ["price", "volume"], c = {
8
8
  "1D": { duration: 6.5 * 60 * 60 * 1e3, points: 78, basePrice: 150 },
9
9
  // 5-minute intervals (market hours)
@@ -13,30 +13,30 @@ function G(s, p, C) {
13
13
  // Daily close
14
14
  "1Y": { duration: 365 * 24 * 60 * 60 * 1e3, points: 52, basePrice: 100 }
15
15
  // Weekly close
16
- }, g = c[s] || c["1M"], { duration: l, points: h, basePrice: r } = g, o = l / h, x = [];
16
+ }, g = c[a] || c["1M"], { duration: l, points: u, basePrice: r } = g, o = l / u, x = [];
17
17
  let n = r;
18
- const u = [];
19
- for (let d = 0; d < h; d++) {
18
+ const h = [];
19
+ for (let d = 0; d < u; d++) {
20
20
  const v = N - l + d * o, m = {
21
21
  timestamp: new Date(v).toLocaleString("en-US", {
22
- ...s === "1D" && { hour: "2-digit", minute: "2-digit" },
23
- ...s === "1W" && { weekday: "short", hour: "2-digit" },
24
- ...s === "1M" && { month: "short", day: "numeric" },
25
- ...s === "1Y" && { month: "short", year: "2-digit" }
22
+ ...a === "1D" && { hour: "2-digit", minute: "2-digit" },
23
+ ...a === "1W" && { weekday: "short", hour: "2-digit" },
24
+ ...a === "1M" && { month: "short", day: "numeric" },
25
+ ...a === "1Y" && { month: "short", year: "2-digit" }
26
26
  })
27
27
  };
28
28
  M.forEach((i) => {
29
29
  switch (i) {
30
30
  case "price":
31
- const P = r * 0.02, y = 1e-4 * r, k = (Math.random() - 0.48) * P + y;
32
- n = Math.max(n + k, r * 0.7), u.push(n), m[i] = Number(n.toFixed(2));
31
+ const P = r * 0.02, y = 1e-4 * r, b = (Math.random() - 0.48) * P + y;
32
+ n = Math.max(n + b, r * 0.7), h.push(n), m[i] = Number(n.toFixed(2));
33
33
  break;
34
34
  case "volume":
35
35
  const t = 1e6, f = Math.random() > 0.7 ? Math.random() * 2 : 1;
36
36
  m[i] = Math.round((t + Math.random() * t * 2) * f);
37
37
  break;
38
38
  case "moving_average":
39
- const w = Math.min(20, d + 1), D = u.slice(-w).reduce((I, T) => I + T, 0) / w;
39
+ const w = Math.min(20, d + 1), D = h.slice(-w).reduce((I, T) => I + T, 0) / w;
40
40
  m[i] = Number(D.toFixed(2));
41
41
  break;
42
42
  default:
@@ -46,7 +46,7 @@ function G(s, p, C) {
46
46
  }
47
47
  return x;
48
48
  }
49
- const b = {
49
+ const k = {
50
50
  price: { label: "Price", unit: "USD", color: "#10b981" },
51
51
  // Emerald/green
52
52
  volume: { label: "Volume", unit: "shares", color: "#f59e0b" },
@@ -54,16 +54,16 @@ const b = {
54
54
  moving_average: { label: "MA(20)", unit: "", color: "#ef4444" }
55
55
  // Red
56
56
  }, Q = ({
57
- params: s,
57
+ params: a,
58
58
  title: p,
59
59
  data: C
60
60
  }) => {
61
- var y, k;
62
- const { ticker: N, timeRange: M, metrics: c } = s, { textColor: g, gridColor: l } = Y(), h = N || s.symbol || "UNKNOWN", r = M || "1M", o = c && Array.isArray(c) && c.length > 0 ? c : ["price", "volume"], x = _.useMemo(
61
+ var y, b;
62
+ const { ticker: N, timeRange: M, metrics: c } = a, { textColor: g, gridColor: l } = Y(), u = N || a.symbol || "UNKNOWN", r = M || "1M", o = c && Array.isArray(c) && c.length > 0 ? c : ["price", "volume"], x = _.useMemo(
63
63
  () => {
64
64
  const t = C || G(r, o);
65
65
  return console.log("[StockChart] Data generated:", {
66
- ticker: h,
66
+ ticker: u,
67
67
  timeRange: r,
68
68
  metrics: o,
69
69
  dataPoints: t.length,
@@ -71,20 +71,20 @@ const b = {
71
71
  lastPoint: t[t.length - 1]
72
72
  }), t;
73
73
  },
74
- [C, r, o, h]
75
- ), n = x.filter((t) => t.price !== void 0), u = ((y = n[0]) == null ? void 0 : y.price) || 0, d = ((k = n[n.length - 1]) == null ? void 0 : k.price) || 0, v = d - u, m = u > 0 ? (v / u * 100).toFixed(2) : "0.00", i = v >= 0, P = p || `${h.toUpperCase()} - ${r}`;
76
- return /* @__PURE__ */ a(E, { className: "w-full max-w-2xl shadow-lg border-primary/20", children: [
77
- /* @__PURE__ */ e(H, { className: "pb-2", children: /* @__PURE__ */ a("div", { className: "flex items-center justify-between", children: [
74
+ [C, r, o, u]
75
+ ), n = x.filter((t) => t.price !== void 0), h = ((y = n[0]) == null ? void 0 : y.price) || 0, d = ((b = n[n.length - 1]) == null ? void 0 : b.price) || 0, v = d - h, m = h > 0 ? (v / h * 100).toFixed(2) : "0.00", i = v >= 0, P = p || `${u.toUpperCase()} - ${r}`;
76
+ return /* @__PURE__ */ s(E, { className: "w-full max-w-2xl shadow-lg border-primary/20", children: [
77
+ /* @__PURE__ */ e(H, { className: "pb-2", children: /* @__PURE__ */ s("div", { className: "flex items-center justify-between", children: [
78
78
  /* @__PURE__ */ e(L, { className: "text-sm font-medium text-foreground/80", children: P }),
79
- o.includes("price") && /* @__PURE__ */ a("div", { className: "flex items-center gap-2", children: [
80
- /* @__PURE__ */ a("span", { className: "text-base font-semibold", children: [
79
+ o.includes("price") && /* @__PURE__ */ s("div", { className: "flex items-center gap-2", children: [
80
+ /* @__PURE__ */ s("span", { className: "text-base font-semibold", children: [
81
81
  "$",
82
82
  d.toFixed(2)
83
83
  ] }),
84
- /* @__PURE__ */ a(
84
+ /* @__PURE__ */ s(
85
85
  "span",
86
86
  {
87
- className: `text-xs font-medium ${i ? "text-green-600 dark:text-green-400" : "text-red-600 dark:text-red-400"}`,
87
+ className: `text-xs font-medium ${i ? "text-success-strong" : "text-destructive-strong"}`,
88
88
  children: [
89
89
  i ? "+" : "",
90
90
  v.toFixed(2),
@@ -97,8 +97,8 @@ const b = {
97
97
  )
98
98
  ] })
99
99
  ] }) }),
100
- /* @__PURE__ */ a(V, { className: "pt-0", children: [
101
- /* @__PURE__ */ e("div", { className: "h-64 w-full bg-background", style: { minHeight: "256px", minWidth: "350px" }, children: /* @__PURE__ */ e(F, { width: "100%", height: 256, children: /* @__PURE__ */ a(W, { data: x, margin: { top: 5, right: 20, bottom: 5, left: 0 }, children: [
100
+ /* @__PURE__ */ s(V, { className: "pt-0", children: [
101
+ /* @__PURE__ */ e("div", { className: "h-64 w-full bg-background", style: { minHeight: "256px", minWidth: "350px" }, children: /* @__PURE__ */ e(F, { width: "100%", height: 256, children: /* @__PURE__ */ s(W, { data: x, margin: { top: 5, right: 20, bottom: 5, left: 0 }, children: [
102
102
  /* @__PURE__ */ e(K, { strokeDasharray: "3 3", stroke: l, opacity: 0.3 }),
103
103
  /* @__PURE__ */ e(
104
104
  U,
@@ -136,7 +136,7 @@ const b = {
136
136
  yAxisId: "price",
137
137
  type: "monotone",
138
138
  dataKey: "price",
139
- stroke: b.price.color,
139
+ stroke: k.price.color,
140
140
  strokeWidth: 2,
141
141
  dot: !1,
142
142
  name: "Price (USD)"
@@ -148,7 +148,7 @@ const b = {
148
148
  yAxisId: "price",
149
149
  type: "monotone",
150
150
  dataKey: "moving_average",
151
- stroke: b.moving_average.color,
151
+ stroke: k.moving_average.color,
152
152
  strokeWidth: 2,
153
153
  dot: !1,
154
154
  name: "MA(20)",
@@ -160,15 +160,15 @@ const b = {
160
160
  {
161
161
  yAxisId: "volume",
162
162
  dataKey: "volume",
163
- fill: b.volume.color,
163
+ fill: k.volume.color,
164
164
  opacity: 0.6,
165
165
  name: "Volume"
166
166
  }
167
167
  )
168
168
  ] }) }) }),
169
169
  /* @__PURE__ */ e("div", { className: "mt-3 flex flex-wrap gap-2", children: o.map((t) => {
170
- const f = b[t];
171
- return /* @__PURE__ */ a(
170
+ const f = k[t];
171
+ return /* @__PURE__ */ s(
172
172
  "div",
173
173
  {
174
174
  className: "inline-flex items-center gap-1.5 rounded-full bg-muted/50 px-2.5 py-1 text-xs",
@@ -181,7 +181,7 @@ const b = {
181
181
  }
182
182
  ),
183
183
  /* @__PURE__ */ e("span", { className: "font-medium", children: f.label }),
184
- f.unit && /* @__PURE__ */ a("span", { className: "text-muted-foreground", children: [
184
+ f.unit && /* @__PURE__ */ s("span", { className: "text-muted-foreground", children: [
185
185
  "(",
186
186
  f.unit,
187
187
  ")"
@@ -4,8 +4,9 @@ export interface StatusBadgeProps {
4
4
  /** One of the 5 built-in presets. Omit and use `color` + `label` for a
5
5
  * status this preset set doesn't cover (e.g. a domain-specific state). */
6
6
  status?: StatusType;
7
- /** Tailwind background class for the dot, e.g. 'bg-emerald-500'. Overrides
8
- * the `status` preset's color when both are given. */
7
+ /** Background class for the dot, e.g. 'bg-success' or 'bg-chart-2'. Overrides
8
+ * the `status` preset's colour when both are given. Use a semantic token: a
9
+ * numeric shade is fixed across all five themes. */
9
10
  color?: string;
10
11
  /**
11
12
  * Optional custom label. If not provided, uses the default status name.
@@ -27,7 +28,7 @@ export interface StatusBadgeProps {
27
28
  * description: One of the 5 built-in presets. Determines the color of the dot. Omit and use `color`+`label` for a status outside this set.
28
29
  * - name: color
29
30
  * type: string
30
- * description: Tailwind background class for the dot (e.g. 'bg-emerald-500'). Overrides the `status` preset's color when both are given.
31
+ * description: Background class for the dot (e.g. 'bg-success'). Use a semantic token — a numeric shade does not adapt to the active theme. Overrides the `status` preset's colour when both are given.
31
32
  * - name: label
32
33
  * type: string
33
34
  * description: Custom text to display next to the dot. If omitted, displays the status name (e.g., "Online").
@@ -1,28 +1,28 @@
1
- import { jsxs as g, jsx as r } from "react/jsx-runtime";
2
- import { cn as t } from "../../utils/cn.js";
3
- const d = {
4
- online: { color: "bg-green-500", label: "Online" },
5
- offline: { color: "bg-gray-400", label: "Offline" },
6
- error: { color: "bg-red-500", label: "Error" },
7
- warning: { color: "bg-yellow-500", label: "Warning" },
8
- active: { color: "bg-blue-500", label: "Active" }
1
+ import { jsxs as d, jsx as e } from "react/jsx-runtime";
2
+ import { cn as i } from "../../utils/cn.js";
3
+ const g = {
4
+ online: { color: "bg-success", label: "Online" },
5
+ offline: { color: "bg-muted-foreground", label: "Offline" },
6
+ error: { color: "bg-destructive", label: "Error" },
7
+ warning: { color: "bg-warning", label: "Warning" },
8
+ active: { color: "bg-info", label: "Active" }
9
9
  }, m = ({
10
- status: e,
11
- color: a,
12
- label: n,
13
- className: i,
14
- showDot: c = !0
10
+ status: n,
11
+ color: t,
12
+ label: r,
13
+ className: c,
14
+ showDot: a = !0
15
15
  }) => {
16
- const l = e ? d[e] : void 0, s = a ?? (l == null ? void 0 : l.color) ?? "bg-muted-foreground", o = n === null ? null : n ?? (l == null ? void 0 : l.label) ?? null;
17
- return /* @__PURE__ */ g("div", { className: t("inline-flex items-center gap-2", i), children: [
18
- c && /* @__PURE__ */ r(
16
+ const o = n ? g[n] : void 0, s = t ?? (o == null ? void 0 : o.color) ?? "bg-muted-foreground", l = r === null ? null : r ?? (o == null ? void 0 : o.label) ?? null;
17
+ return /* @__PURE__ */ d("div", { className: i("inline-flex items-center gap-2", c), children: [
18
+ a && /* @__PURE__ */ e(
19
19
  "span",
20
20
  {
21
- className: t("h-2.5 w-2.5 rounded-full ring-2 ring-white dark:ring-slate-900", s),
21
+ className: i("h-2.5 w-2.5 rounded-full ring-2 ring-card", s),
22
22
  "aria-hidden": "true"
23
23
  }
24
24
  ),
25
- o && /* @__PURE__ */ r("span", { className: "text-sm font-medium text-slate-700 dark:text-slate-300", children: o })
25
+ l && /* @__PURE__ */ e("span", { className: "text-sm font-medium text-foreground", children: l })
26
26
  ] });
27
27
  };
28
28
  export {
@@ -1,37 +1,37 @@
1
- import { jsxs as l, jsx as e } from "react/jsx-runtime";
2
- import { Icon as c } from "../ui/Icon.js";
3
- const i = {
1
+ import { jsxs as c, jsx as s } from "react/jsx-runtime";
2
+ import { Icon as o } from "../ui/Icon.js";
3
+ const a = {
4
4
  info: {
5
5
  icon: "info",
6
- classes: "bg-primary/10 border-primary/50 text-primary"
6
+ classes: "bg-info/10 border-info/50 text-info-strong"
7
7
  },
8
8
  success: {
9
9
  icon: "check-circle",
10
- classes: "bg-green-500/10 border-green-500/50 text-green-700 dark:text-green-400"
10
+ classes: "bg-success/10 border-success/50 text-success-strong"
11
11
  },
12
12
  warning: {
13
13
  icon: "alert-triangle",
14
- classes: "bg-yellow-500/10 border-yellow-500/50 text-yellow-700 dark:text-yellow-400"
14
+ classes: "bg-warning/10 border-warning/50 text-warning-strong"
15
15
  },
16
16
  danger: {
17
17
  icon: "x-circle",
18
- classes: "bg-red-500/10 border-red-500/50 text-red-700 dark:text-red-500"
18
+ classes: "bg-destructive/10 border-destructive/50 text-destructive-strong"
19
19
  }
20
- }, m = ({
21
- title: o,
22
- children: r,
23
- variant: t = "info",
24
- className: a
20
+ }, g = ({
21
+ title: n,
22
+ children: e,
23
+ variant: i = "info",
24
+ className: t
25
25
  }) => {
26
- const s = i[t];
27
- return /* @__PURE__ */ l("div", { className: `flex items-start gap-4 p-4 border-l-4 rounded-r-lg ${s.classes} ${a || ""}`, role: "alert", children: [
28
- /* @__PURE__ */ e("div", { className: "flex-shrink-0", children: /* @__PURE__ */ e(c, { name: s.icon, size: 20 }) }),
29
- /* @__PURE__ */ l("div", { className: "flex-grow", children: [
30
- /* @__PURE__ */ e("h4", { className: "font-semibold", children: o }),
31
- r && /* @__PURE__ */ e("div", { className: "text-sm mt-1", children: r })
26
+ const r = a[i];
27
+ return /* @__PURE__ */ c("div", { className: `flex items-start gap-4 p-4 border-l-4 rounded-r-lg ${r.classes} ${t || ""}`, role: "alert", children: [
28
+ /* @__PURE__ */ s("div", { className: "flex-shrink-0", children: /* @__PURE__ */ s(o, { name: r.icon, size: 20 }) }),
29
+ /* @__PURE__ */ c("div", { className: "flex-grow", children: [
30
+ /* @__PURE__ */ s("h4", { className: "font-semibold", children: n }),
31
+ e && /* @__PURE__ */ s("div", { className: "text-sm mt-1", children: e })
32
32
  ] })
33
33
  ] });
34
34
  };
35
35
  export {
36
- m as Alert
36
+ g as Alert
37
37
  };
@@ -1,24 +1,24 @@
1
- import { jsx as t } from "react/jsx-runtime";
2
- import { cn as d } from "../../utils/cn.js";
1
+ import { jsx as d } from "react/jsx-runtime";
2
+ import { cn as t } from "../../utils/cn.js";
3
3
  const m = ({
4
4
  options: n,
5
- value: i,
5
+ value: o,
6
6
  onChange: l,
7
7
  size: r = "md",
8
- className: o
9
- }) => /* @__PURE__ */ t("div", { className: d(
8
+ className: i
9
+ }) => /* @__PURE__ */ d("div", { className: t(
10
10
  // Container: Use 'muted' background for the track (works in all themes)
11
11
  "inline-flex bg-muted border border-border",
12
12
  r === "xs" ? "rounded-md p-0.5" : "rounded-lg p-1",
13
- o
13
+ i
14
14
  ), children: n.map((e) => {
15
- const s = e.value === i;
16
- return /* @__PURE__ */ t(
15
+ const s = e.value === o;
16
+ return /* @__PURE__ */ d(
17
17
  "button",
18
18
  {
19
19
  onClick: () => !e.disabled && l(e.value),
20
20
  disabled: e.disabled,
21
- className: d(
21
+ className: t(
22
22
  "relative rounded-md font-medium transition-all duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-primary",
23
23
  // Size Variants
24
24
  //
@@ -40,7 +40,7 @@ const m = ({
40
40
  // those two already clear AA and must not move.
41
41
  r === "xs" ? "inline-flex items-center justify-center min-h-6 text-2xs px-2 py-0.5" : r === "sm" ? "text-xs px-3 py-1" : "text-sm px-4 py-1.5",
42
42
  // State Styles (Theme Aware)
43
- s ? "bg-card text-foreground shadow-sm ring-1 ring-black/5 dark:ring-white/10" : "text-muted-foreground hover:text-foreground hover:bg-background/50",
43
+ s ? "bg-card text-foreground shadow-sm ring-1 ring-border" : "text-muted-foreground hover:text-foreground hover:bg-background/50",
44
44
  e.disabled && "opacity-50 cursor-not-allowed"
45
45
  ),
46
46
  type: "button",
@@ -8,13 +8,14 @@ import React from 'react';
8
8
  * @id detail-drawer
9
9
  * @param {boolean} isOpen - Whether the drawer is showing.
10
10
  * @param {function} onClose - Called when the drawer requests dismissal.
11
- * @param {string} variant - 'push' compresses sibling flex content so the list stays visible; 'overlay' floats fixed above the page. Defaults to push.
11
+ * @param {string} variant - 'push' compresses sibling flex content so the list stays visible; 'overlay' floats fixed above the page. Defaults to overlay.
12
12
  * @param {string} side - Which edge it docks to: 'left' or 'right'. Defaults to right.
13
13
  * @param {boolean} resizable - Enables the draggable handle on the inner border.
14
14
  * @param {number} width - Current width in px. Controlled — pair with onWidthChange.
15
15
  * @param {function} onWidthChange - Called with the new width while dragging.
16
16
  * @param {number} minWidth - Lower bound for resizing. Defaults to 320.
17
17
  * @param {number} maxWidth - Upper bound for resizing. Defaults to 60% of the window width.
18
+ * @param {string} title - Names the panel for assistive technology. Not rendered: there is no header row to put it in, and adding one is a design decision. Without it an overlay announces only as "dialog".
18
19
  * @param {ReactNode} children - The detail content.
19
20
  */
20
21
  export interface DetailDrawerProps {
@@ -28,5 +29,12 @@ export interface DetailDrawerProps {
28
29
  minWidth?: number;
29
30
  maxWidth?: number;
30
31
  side?: 'left' | 'right';
32
+ /**
33
+ * Names the panel for assistive technology. Not rendered — this component
34
+ * has no header row to put it in, and adding one is a visual change that is
35
+ * a designer's call, not this fix's. Without it an overlay announces only as
36
+ * "dialog" and a push panel as nothing at all.
37
+ */
38
+ title?: string;
31
39
  }
32
40
  export declare const DetailDrawer: React.FC<DetailDrawerProps>;
@@ -1,88 +1,98 @@
1
- import { jsxs as b, jsx as r, Fragment as k } from "react/jsx-runtime";
2
- import { useRef as E, useEffect as y } from "react";
3
- import { createPortal as L } from "react-dom";
4
- import { Icon as D } from "../ui/Icon.js";
5
- import { cn as h } from "../../utils/cn.js";
6
- import { useBodyScrollLock as M } from "../../lib/hooks/useBodyScrollLock.js";
7
- const B = ({
1
+ import { jsxs as p, jsx as o, Fragment as M } from "react/jsx-runtime";
2
+ import { useRef as g, useId as z, useEffect as x } from "react";
3
+ import { useDialogFocus as I } from "../../lib/hooks/useDialogFocus.js";
4
+ import { createPortal as $ } from "react-dom";
5
+ import { Icon as j } from "../ui/Icon.js";
6
+ import { cn as k } from "../../utils/cn.js";
7
+ import { useBodyScrollLock as S } from "../../lib/hooks/useBodyScrollLock.js";
8
+ const q = ({
8
9
  isOpen: t,
9
- onClose: n,
10
- children: p,
11
- variant: u = "overlay",
12
- resizable: d = !1,
13
- width: g = 420,
14
- onWidthChange: a,
15
- minWidth: c = 320,
16
- maxWidth: m = typeof window < "u" ? window.innerWidth * 0.6 : 800,
17
- side: o = "right"
10
+ onClose: i,
11
+ children: D,
12
+ variant: a = "overlay",
13
+ resizable: u = !1,
14
+ width: E = 420,
15
+ onWidthChange: c,
16
+ minWidth: m = 320,
17
+ maxWidth: f = typeof window < "u" ? window.innerWidth * 0.6 : 800,
18
+ side: n = "right",
19
+ title: l
18
20
  }) => {
19
- const i = E(!1);
20
- if (y(() => {
21
- if (!d || !a) return;
22
- const e = (v) => {
23
- if (!i.current) return;
24
- const x = o === "right" ? window.innerWidth - v.clientX : v.clientX;
25
- a(Math.max(c, Math.min(m, x)));
21
+ const d = g(!1), v = g(null), L = z();
22
+ if (I(t && a === "overlay", v), x(() => {
23
+ if (!u || !c) return;
24
+ const r = (h) => {
25
+ if (!d.current) return;
26
+ const N = n === "right" ? window.innerWidth - h.clientX : h.clientX;
27
+ c(Math.max(m, Math.min(f, N)));
26
28
  }, s = () => {
27
- i.current && (i.current = !1, document.body.style.userSelect = "", document.body.style.cursor = "");
29
+ d.current && (d.current = !1, document.body.style.userSelect = "", document.body.style.cursor = "");
28
30
  };
29
- return window.addEventListener("mousemove", e), window.addEventListener("mouseup", s), () => {
30
- window.removeEventListener("mousemove", e), window.removeEventListener("mouseup", s);
31
+ return window.addEventListener("mousemove", r), window.addEventListener("mouseup", s), () => {
32
+ window.removeEventListener("mousemove", r), window.removeEventListener("mouseup", s);
31
33
  };
32
- }, [d, a, c, m, o]), y(() => {
33
- const e = (s) => {
34
- s.key === "Escape" && t && n();
34
+ }, [u, c, m, f, n]), x(() => {
35
+ const r = (s) => {
36
+ s.key === "Escape" && t && i();
35
37
  };
36
- return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
37
- }, [t, n]), M(t && u === "overlay"), !t) return null;
38
- const l = u === "overlay", f = o === "right" ? "right-0 border-l" : "left-0 border-r", w = /* @__PURE__ */ b(
38
+ return window.addEventListener("keydown", r), () => window.removeEventListener("keydown", r);
39
+ }, [t, i]), S(t && a === "overlay"), !t) return null;
40
+ const e = a === "overlay", w = L, b = n === "right" ? "right-0 border-l" : "left-0 border-r", y = /* @__PURE__ */ p(
39
41
  "div",
40
42
  {
41
- className: h(
43
+ ref: v,
44
+ role: e ? "dialog" : "region",
45
+ "aria-modal": e ? !0 : void 0,
46
+ tabIndex: e ? -1 : void 0,
47
+ "aria-labelledby": l ? w : void 0,
48
+ "aria-label": l ? void 0 : e ? "Detail panel" : "Detail",
49
+ className: k(
42
50
  "flex flex-col border-border bg-card shadow-2xl transition-transform duration-300",
43
- l ? `fixed inset-y-0 ${f} z-drawer w-full sm:w-[420px] animate-in ${o === "right" ? "slide-in-from-right" : "slide-in-from-left"}` : `relative h-full flex-shrink-0 ${f}`
51
+ e ? `fixed inset-y-0 ${b} z-drawer w-full sm:w-[420px] animate-in ${n === "right" ? "slide-in-from-right" : "slide-in-from-left"}` : `relative h-full flex-shrink-0 ${b}`
44
52
  ),
45
- style: l ? void 0 : { width: `min(100vw, ${g}px)` },
53
+ style: e ? void 0 : { width: `min(100vw, ${E}px)` },
46
54
  children: [
47
- d && !l && /* @__PURE__ */ r(
55
+ u && !e && /* @__PURE__ */ o(
48
56
  "div",
49
57
  {
50
- className: h(
58
+ className: k(
51
59
  "absolute top-0 bottom-0 w-1.5 cursor-col-resize hover:bg-primary/50 active:bg-primary z-10",
52
- o === "right" ? "left-0 -ml-0.5" : "right-0 -mr-0.5"
60
+ n === "right" ? "left-0 -ml-0.5" : "right-0 -mr-0.5"
53
61
  ),
54
- onMouseDown: (e) => {
55
- e.preventDefault(), i.current = !0, document.body.style.userSelect = "none", document.body.style.cursor = "col-resize";
62
+ onMouseDown: (r) => {
63
+ r.preventDefault(), d.current = !0, document.body.style.userSelect = "none", document.body.style.cursor = "col-resize";
56
64
  }
57
65
  }
58
66
  ),
59
- /* @__PURE__ */ r("div", { className: "flex justify-end p-2 absolute top-0 right-0 z-20", children: /* @__PURE__ */ r(
67
+ /* @__PURE__ */ o("div", { className: "flex justify-end p-2 absolute top-0 right-0 z-20", children: /* @__PURE__ */ o(
60
68
  "button",
61
69
  {
62
- onClick: n,
70
+ onClick: i,
63
71
  className: "rounded-full p-1.5 bg-background/50 backdrop-blur hover:bg-muted text-muted-foreground hover:text-foreground transition-all shadow-sm border border-border",
64
72
  "aria-label": "Close",
65
- children: /* @__PURE__ */ r(D, { name: "x", size: 16 })
73
+ children: /* @__PURE__ */ o(j, { name: "x", size: 16 })
66
74
  }
67
75
  ) }),
68
- /* @__PURE__ */ r("div", { className: "flex-1 overflow-y-auto custom-scrollbar relative h-full", children: p })
76
+ l && // sr-only, not a visible heading: see the `title` prop's note above.
77
+ /* @__PURE__ */ o("h2", { id: w, className: "sr-only", children: l }),
78
+ /* @__PURE__ */ o("div", { className: "flex-1 overflow-y-auto custom-scrollbar relative h-full", children: D })
69
79
  ]
70
80
  }
71
81
  );
72
- return l ? typeof document > "u" ? null : L(
73
- /* @__PURE__ */ b(k, { children: [
74
- /* @__PURE__ */ r(
82
+ return e ? typeof document > "u" ? null : $(
83
+ /* @__PURE__ */ p(M, { children: [
84
+ /* @__PURE__ */ o(
75
85
  "div",
76
86
  {
77
87
  className: "fixed inset-0 z-scrim bg-background/80 backdrop-blur-sm transition-opacity",
78
- onClick: n
88
+ onClick: i
79
89
  }
80
90
  ),
81
- w
91
+ y
82
92
  ] }),
83
93
  document.body
84
- ) : w;
94
+ ) : y;
85
95
  };
86
96
  export {
87
- B as DetailDrawer
97
+ q as DetailDrawer
88
98
  };