@ramme-io/ui 4.1.0 → 4.1.1

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.
Files changed (33) hide show
  1. package/README.md +4 -3
  2. package/dist/component-registry.js +55 -52
  3. package/dist/components/ai/AIChatThread/AIChatThread.js +3 -3
  4. package/dist/components/ai/NewsSummaryCard/NewsSummaryCard.js +17 -17
  5. package/dist/components/ai/StockChart/StockChart.js +4 -4
  6. package/dist/components/auth/LoginPage.d.ts +22 -0
  7. package/dist/components/auth/LoginPage.js +50 -42
  8. package/dist/components/forms/ComboBox.js +2 -2
  9. package/dist/components/forms/DatePicker.js +37 -32
  10. package/dist/components/forms/FileUpload.js +39 -37
  11. package/dist/components/forms/Input.js +19 -18
  12. package/dist/components/forms/MultiSelect.js +9 -8
  13. package/dist/components/forms/Select.js +9 -8
  14. package/dist/components/forms/Textarea.d.ts +13 -11
  15. package/dist/components/forms/Textarea.js +36 -16
  16. package/dist/components/layout/Accordion.js +25 -32
  17. package/dist/components/layout/Card.js +38 -21
  18. package/dist/components/layout/DetailDrawer.js +36 -37
  19. package/dist/components/layout/SettingsContainer.js +23 -13
  20. package/dist/components/layout/Sheet.d.ts +58 -0
  21. package/dist/components/layout/Sheet.js +144 -0
  22. package/dist/components/navigation/MobileNav.d.ts +44 -1
  23. package/dist/components/navigation/MobileNav.js +96 -70
  24. package/dist/components/navigation/Tabs.js +19 -12
  25. package/dist/components/ui/icon-loader.d.ts +1 -1
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.js +218 -211
  28. package/dist/lib/hooks/useSheetGesture.d.ts +81 -0
  29. package/dist/lib/hooks/useSheetGesture.js +70 -0
  30. package/dist/setupTests.d.ts +1 -0
  31. package/dist/wizardManifest.js +130 -10
  32. package/package.json +9 -2
  33. package/src/wizardManifest.ts +130 -10
@@ -1,41 +1,41 @@
1
1
  import { jsxs as t, jsx as r } from "react/jsx-runtime";
2
- import { useState as x, useRef as A, useCallback as l } from "react";
2
+ import F, { useState as v, useRef as I, useCallback as i } from "react";
3
3
  import { Button as j } from "../ui/Button.js";
4
- import { Icon as i } from "../ui/Icon.js";
5
- import { cn as v } from "../../utils/cn.js";
6
- const S = ({
7
- onFileUpload: b,
8
- multiple: n = !1,
9
- acceptedFileTypes: o,
10
- label: c,
11
- className: N,
4
+ import { Icon as c } from "../ui/Icon.js";
5
+ import { cn as b } from "../../utils/cn.js";
6
+ const $ = ({
7
+ onFileUpload: N,
8
+ multiple: o = !1,
9
+ acceptedFileTypes: n,
10
+ label: s,
11
+ className: y,
12
12
  helperText: m
13
13
  }) => {
14
- const [y, s] = x(!1), [f, u] = x([]), p = A(null), d = l((e) => {
15
- e.preventDefault(), e.stopPropagation(), e.type === "dragenter" || e.type === "dragover" ? s(!0) : e.type === "dragleave" && s(!1);
14
+ const [D, d] = v(!1), [f, u] = v([]), p = I(null), l = i((e) => {
15
+ e.preventDefault(), e.stopPropagation(), e.type === "dragenter" || e.type === "dragover" ? d(!0) : e.type === "dragleave" && d(!1);
16
16
  }, []), g = (e) => {
17
- u((a) => n ? [...a, ...e] : [e[0]]), b(e);
18
- }, D = l((e) => {
19
- e.preventDefault(), e.stopPropagation(), s(!1), e.dataTransfer.files && e.dataTransfer.files.length > 0 && g(Array.from(e.dataTransfer.files));
20
- }, [n]), w = l((e) => {
17
+ u((a) => o ? [...a, ...e] : [e[0]]), N(e);
18
+ }, w = i((e) => {
19
+ e.preventDefault(), e.stopPropagation(), d(!1), e.dataTransfer.files && e.dataTransfer.files.length > 0 && g(Array.from(e.dataTransfer.files));
20
+ }, [o]), C = i((e) => {
21
21
  e.preventDefault(), e.target.files && e.target.files.length > 0 && g(Array.from(e.target.files));
22
- }, [n]), k = (e) => {
23
- u((a) => a.filter((h, C) => C !== e));
24
- };
25
- return /* @__PURE__ */ t("div", { className: v("w-full", N), children: [
26
- c && /* @__PURE__ */ r("label", { className: "block text-sm font-medium text-foreground mb-1.5", children: c }),
22
+ }, [o]), k = (e) => {
23
+ u((a) => a.filter((x, A) => A !== e));
24
+ }, h = F.useId();
25
+ return /* @__PURE__ */ t("div", { className: b("w-full", y), children: [
26
+ s && /* @__PURE__ */ r("label", { htmlFor: h, className: "block text-sm font-medium text-foreground mb-1.5", children: s }),
27
27
  /* @__PURE__ */ t(
28
28
  "div",
29
29
  {
30
- className: v(
30
+ className: b(
31
31
  "relative flex flex-col items-center justify-center p-6 border-2 border-dashed rounded-lg transition-colors duration-200 ease-in-out cursor-pointer",
32
- y ? "border-primary bg-primary/5" : "border-border bg-card hover:bg-muted/50",
32
+ D ? "border-primary bg-primary/5" : "border-border bg-card hover:bg-muted/50",
33
33
  "min-h-[150px]"
34
34
  ),
35
- onDragEnter: d,
36
- onDragLeave: d,
37
- onDragOver: d,
38
- onDrop: D,
35
+ onDragEnter: l,
36
+ onDragLeave: l,
37
+ onDragOver: l,
38
+ onDrop: w,
39
39
  onClick: () => {
40
40
  var e;
41
41
  return (e = p.current) == null ? void 0 : e.click();
@@ -45,28 +45,30 @@ const S = ({
45
45
  "input",
46
46
  {
47
47
  ref: p,
48
+ id: h,
48
49
  type: "file",
49
50
  className: "hidden",
50
- multiple: n,
51
- accept: o,
52
- onChange: w
51
+ "aria-label": s || "Choose files to upload",
52
+ multiple: o,
53
+ accept: n,
54
+ onChange: C
53
55
  }
54
56
  ),
55
- /* @__PURE__ */ r("div", { className: "bg-muted p-3 rounded-full mb-3", children: /* @__PURE__ */ r(i, { name: "upload-cloud", className: "h-6 w-6 text-muted-foreground" }) }),
57
+ /* @__PURE__ */ r("div", { className: "bg-muted p-3 rounded-full mb-3", children: /* @__PURE__ */ r(c, { name: "upload-cloud", className: "h-6 w-6 text-muted-foreground" }) }),
56
58
  /* @__PURE__ */ t("p", { className: "text-sm font-medium text-foreground text-center", children: [
57
59
  /* @__PURE__ */ r("span", { className: "text-primary font-semibold hover:underline", children: "Click to upload" }),
58
60
  " or drag and drop"
59
61
  ] }),
60
62
  /* @__PURE__ */ t("p", { className: "text-xs text-muted-foreground mt-1", children: [
61
- o ? o.replace(/,/g, ", ") : "Any file type",
62
- n ? "" : " (Single file)"
63
+ n ? n.replace(/,/g, ", ") : "Any file type",
64
+ o ? "" : " (Single file)"
63
65
  ] })
64
66
  ]
65
67
  }
66
68
  ),
67
69
  f.length > 0 && /* @__PURE__ */ r("div", { className: "mt-4 space-y-2", children: f.map((e, a) => /* @__PURE__ */ t("div", { className: "flex items-center justify-between p-2 rounded-md border border-border bg-card", children: [
68
70
  /* @__PURE__ */ t("div", { className: "flex items-center gap-3 overflow-hidden", children: [
69
- /* @__PURE__ */ r("div", { className: "bg-primary/10 p-2 rounded text-primary", children: /* @__PURE__ */ r(i, { name: "file", className: "h-4 w-4" }) }),
71
+ /* @__PURE__ */ r("div", { className: "bg-primary/10 p-2 rounded text-primary", children: /* @__PURE__ */ r(c, { name: "file", className: "h-4 w-4" }) }),
70
72
  /* @__PURE__ */ t("div", { className: "min-w-0", children: [
71
73
  /* @__PURE__ */ r("p", { className: "text-sm font-medium text-foreground truncate", children: e.name }),
72
74
  /* @__PURE__ */ t("p", { className: "text-xs text-muted-foreground", children: [
@@ -81,10 +83,10 @@ const S = ({
81
83
  variant: "ghost",
82
84
  size: "icon",
83
85
  className: "h-8 w-8 text-muted-foreground hover:text-destructive",
84
- onClick: (h) => {
85
- h.stopPropagation(), k(a);
86
+ onClick: (x) => {
87
+ x.stopPropagation(), k(a);
86
88
  },
87
- children: /* @__PURE__ */ r(i, { name: "x", className: "h-4 w-4" })
89
+ children: /* @__PURE__ */ r(c, { name: "x", className: "h-4 w-4" })
88
90
  }
89
91
  )
90
92
  ] }, `${e.name}-${a}`)) }),
@@ -92,5 +94,5 @@ const S = ({
92
94
  ] });
93
95
  };
94
96
  export {
95
- S as FileUpload
97
+ $ as FileUpload
96
98
  };
@@ -1,43 +1,44 @@
1
1
  import { jsxs as n, jsx as e } from "react/jsx-runtime";
2
- import b from "react";
3
- import { Icon as g } from "../ui/Icon.js";
2
+ import c from "react";
3
+ import { Icon as N } from "../ui/Icon.js";
4
4
  import { cn as o } from "../../utils/cn.js";
5
- const v = b.forwardRef(
5
+ const h = c.forwardRef(
6
6
  ({
7
7
  label: r,
8
8
  icon: t,
9
9
  helperText: i,
10
- error: a = !1,
10
+ error: d = !1,
11
11
  required: s = !1,
12
- showOptionalLabel: d = !1,
13
- className: m,
14
- containerClassName: c,
12
+ showOptionalLabel: m = !1,
13
+ className: f,
14
+ containerClassName: u,
15
15
  ...l
16
- }, f) => {
17
- const u = "flex h-10 w-full rounded-md border bg-background py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", p = a ? "border-destructive" : "border-input", x = t ? "pl-10 pr-3" : "px-3";
18
- return /* @__PURE__ */ n("div", { className: o("w-full", c), children: [
19
- r && /* @__PURE__ */ n("label", { htmlFor: l.id || l.name, className: "block text-sm font-medium text-foreground mb-1", children: [
16
+ }, p) => {
17
+ const b = c.useId(), a = l.id || l.name || b, x = "flex h-10 w-full rounded-md border bg-background py-2 ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", g = d ? "border-destructive" : "border-input", v = t ? "pl-10 pr-3" : "px-3";
18
+ return /* @__PURE__ */ n("div", { className: o("w-full", u), children: [
19
+ r && /* @__PURE__ */ n("label", { htmlFor: a, className: "block text-sm font-medium text-foreground mb-1", children: [
20
20
  r,
21
21
  s && /* @__PURE__ */ e("span", { className: "text-destructive ml-1", children: "*" }),
22
- !s && d && /* @__PURE__ */ e("span", { className: "text-xs text-muted-foreground ml-1", children: "(optional)" })
22
+ !s && m && /* @__PURE__ */ e("span", { className: "text-xs text-muted-foreground ml-1", children: "(optional)" })
23
23
  ] }),
24
24
  /* @__PURE__ */ n("div", { className: "relative w-full", children: [
25
- t && /* @__PURE__ */ e("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none", children: /* @__PURE__ */ e(g, { name: t, className: "text-muted-foreground", size: 16 }) }),
25
+ t && /* @__PURE__ */ e("div", { className: "absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none", children: /* @__PURE__ */ e(N, { name: t, className: "text-muted-foreground", size: 16 }) }),
26
26
  /* @__PURE__ */ e(
27
27
  "input",
28
28
  {
29
- ref: f,
30
- className: o(u, p, x, m),
29
+ ref: p,
30
+ id: a,
31
+ className: o(x, g, v, f),
31
32
  required: s,
32
33
  ...l
33
34
  }
34
35
  )
35
36
  ] }),
36
- i && /* @__PURE__ */ e("p", { className: o("mt-1.5 text-xs", a ? "text-destructive" : "text-muted-foreground"), children: i })
37
+ i && /* @__PURE__ */ e("p", { className: o("mt-1.5 text-xs", d ? "text-destructive" : "text-muted-foreground"), children: i })
37
38
  ] });
38
39
  }
39
40
  );
40
- v.displayName = "Input";
41
+ h.displayName = "Input";
41
42
  export {
42
- v as Input
43
+ h as Input
43
44
  };
@@ -7,24 +7,24 @@ const R = (a) => /* @__PURE__ */ e(d.DropdownIndicator, { ...a, children: /* @__
7
7
  options: a,
8
8
  value: u,
9
9
  onChange: m,
10
- label: t,
10
+ label: c,
11
11
  placeholder: s = "Select...",
12
12
  isClearable: b = !0,
13
13
  isDisabled: g = !1,
14
14
  isLoading: v = !1,
15
15
  isSearchable: x = !0,
16
16
  className: f,
17
- error: c,
18
- helperText: l
17
+ error: l,
18
+ helperText: n
19
19
  }) => {
20
- const n = S(), h = (r, o) => {
20
+ const t = S(), h = (r, o) => {
21
21
  const C = r ? Array.from(r) : null;
22
22
  m(C);
23
23
  }, y = {
24
24
  control: (r, o) => ({
25
25
  ...r,
26
26
  backgroundColor: "rgb(var(--app-card-bg-color))",
27
- borderColor: c ? "rgb(var(--app-danger-color))" : o.isFocused ? "rgb(var(--app-primary-color))" : "rgb(var(--app-border-color))",
27
+ borderColor: l ? "rgb(var(--app-danger-color))" : o.isFocused ? "rgb(var(--app-primary-color))" : "rgb(var(--app-border-color))",
28
28
  color: "rgb(var(--app-text-color))",
29
29
  borderRadius: "var(--app-border-radius-md)",
30
30
  boxShadow: o.isFocused ? "0 0 0 1px rgb(var(--app-primary-color))" : "none",
@@ -83,11 +83,12 @@ const R = (a) => /* @__PURE__ */ e(d.DropdownIndicator, { ...a, children: /* @__
83
83
  })
84
84
  };
85
85
  return /* @__PURE__ */ I("div", { className: p("w-full", f), children: [
86
- t && /* @__PURE__ */ e("label", { htmlFor: n, className: "block text-sm font-medium text-foreground mb-1.5", children: t }),
86
+ c && /* @__PURE__ */ e("label", { htmlFor: t, className: "block text-sm font-medium text-foreground mb-1.5", children: c }),
87
87
  /* @__PURE__ */ e(
88
88
  k,
89
89
  {
90
- instanceId: n,
90
+ instanceId: t,
91
+ inputId: t,
91
92
  styles: y,
92
93
  components: { DropdownIndicator: R, MultiValueRemove: w },
93
94
  options: a,
@@ -103,7 +104,7 @@ const R = (a) => /* @__PURE__ */ e(d.DropdownIndicator, { ...a, children: /* @__
103
104
  menuPosition: "fixed"
104
105
  }
105
106
  ),
106
- l && /* @__PURE__ */ e("p", { className: p("mt-1.5 text-xs", c ? "text-destructive" : "text-muted-foreground"), children: l })
107
+ n && /* @__PURE__ */ e("p", { className: p("mt-1.5 text-xs", l ? "text-destructive" : "text-muted-foreground"), children: n })
107
108
  ] });
108
109
  };
109
110
  export {
@@ -7,21 +7,21 @@ const S = (a) => /* @__PURE__ */ e(I.DropdownIndicator, { ...a, children: /* @__
7
7
  options: a,
8
8
  value: l,
9
9
  onChange: i,
10
- label: c,
10
+ label: p,
11
11
  placeholder: m = "Select...",
12
12
  isDisabled: s = !1,
13
13
  isLoading: u = !1,
14
14
  isClearable: b = !0,
15
15
  isSearchable: g = !0,
16
16
  className: v,
17
- error: p,
18
- helperText: t
17
+ error: t,
18
+ helperText: d
19
19
  }) => {
20
- const d = h(), x = {
20
+ const c = h(), x = {
21
21
  control: (r, o) => ({
22
22
  ...r,
23
23
  backgroundColor: "rgb(var(--app-card-bg-color))",
24
- borderColor: p ? "rgb(var(--app-danger-color))" : o.isFocused ? "rgb(var(--app-primary-color))" : "rgb(var(--app-border-color))",
24
+ borderColor: t ? "rgb(var(--app-danger-color))" : o.isFocused ? "rgb(var(--app-primary-color))" : "rgb(var(--app-border-color))",
25
25
  color: "rgb(var(--app-text-color))",
26
26
  borderRadius: "var(--app-border-radius-md)",
27
27
  boxShadow: o.isFocused ? "0 0 0 1px rgb(var(--app-primary-color))" : "none",
@@ -65,11 +65,12 @@ const S = (a) => /* @__PURE__ */ e(I.DropdownIndicator, { ...a, children: /* @__
65
65
  })
66
66
  };
67
67
  return /* @__PURE__ */ f("div", { className: n("w-full", v), children: [
68
- c && /* @__PURE__ */ e("label", { htmlFor: d, className: "block text-sm font-medium text-foreground mb-1.5", children: c }),
68
+ p && /* @__PURE__ */ e("label", { htmlFor: c, className: "block text-sm font-medium text-foreground mb-1.5", children: p }),
69
69
  /* @__PURE__ */ e(
70
70
  y,
71
71
  {
72
- instanceId: d,
72
+ instanceId: c,
73
+ inputId: c,
73
74
  styles: x,
74
75
  components: { DropdownIndicator: S },
75
76
  options: a,
@@ -84,7 +85,7 @@ const S = (a) => /* @__PURE__ */ e(I.DropdownIndicator, { ...a, children: /* @__
84
85
  menuPosition: "fixed"
85
86
  }
86
87
  ),
87
- t && /* @__PURE__ */ e("p", { className: n("mt-1.5 text-xs", p ? "text-destructive" : "text-muted-foreground"), children: t })
88
+ d && /* @__PURE__ */ e("p", { className: n("mt-1.5 text-xs", t ? "text-destructive" : "text-muted-foreground"), children: d })
88
89
  ] });
89
90
  };
90
91
  export {
@@ -1,22 +1,24 @@
1
1
  import React from 'react';
2
- interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
2
+ export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
3
3
  label?: string;
4
+ helperText?: string;
5
+ error?: boolean;
6
+ required?: boolean;
7
+ showOptionalLabel?: boolean;
4
8
  containerClassName?: string;
5
9
  }
6
10
  /**
7
11
  * @wizard
8
12
  * @name Textarea
9
- * @description A theme-aware textarea component for multi-line text input.
10
- * @tags form, input, ui
11
- * @props
12
- * - name: label
13
- * type: string
14
- * description: An optional label to display above the textarea.
15
- * - name: containerClassName
16
- * type: string
17
- * description: Optional additional CSS classes for the container div.
13
+ * @description A theme-aware multi-line text input with label, helper text, and validation state support. Strategic purpose: the multi-line sibling of Input, styled identically so the two are indistinguishable when stacked in one form. Forwards all standard HTML textarea attributes via spread.
14
+ * @tags form, input, ui, text, multiline
18
15
  * @category form
19
16
  * @id textarea
17
+ * @param {string} label - Optional label displayed above the textarea.
18
+ * @param {string} helperText - Supporting text rendered below the textarea. Appears in destructive color when error is true.
19
+ * @param {boolean} error - If true, applies destructive border styling to indicate a validation error. Defaults to false.
20
+ * @param {boolean} required - If true, appends a required (*) indicator next to the label. Defaults to false.
21
+ * @param {boolean} showOptionalLabel - If true, appends an (optional) label when the field is not required. Defaults to false.
22
+ * @param {string} containerClassName - Additional CSS classes applied to the outer container div.
20
23
  */
21
24
  export declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
22
- export {};
@@ -1,19 +1,39 @@
1
- import { jsxs as n, jsx as o } from "react/jsx-runtime";
2
- import d from "react";
3
- const m = d.forwardRef(
4
- ({ label: r, className: t, containerClassName: a, ...e }, s) => /* @__PURE__ */ n("div", { className: `w-full ${a || ""}`, children: [
5
- r && /* @__PURE__ */ o("label", { htmlFor: e.id || e.name, className: "block text-sm font-medium text-muted-foreground mb-1", children: r }),
6
- /* @__PURE__ */ o(
7
- "textarea",
8
- {
9
- ref: s,
10
- className: `w-full px-3 py-2 rounded-md bg-card border border-border transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-primary ${t || ""}`,
11
- ...e
12
- }
13
- )
14
- ] })
1
+ import { jsxs as n, jsx as e } from "react/jsx-runtime";
2
+ import i from "react";
3
+ import { cn as o } from "../../utils/cn.js";
4
+ const p = i.forwardRef(
5
+ ({
6
+ label: r,
7
+ helperText: a,
8
+ error: d = !1,
9
+ required: t = !1,
10
+ showOptionalLabel: c = !1,
11
+ className: m,
12
+ containerClassName: f,
13
+ ...s
14
+ }, u) => {
15
+ const x = "w-full rounded-md border bg-background px-3 py-2 ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", b = d ? "border-destructive" : "border-input", g = i.useId(), l = s.id || s.name || g;
16
+ return /* @__PURE__ */ n("div", { className: o("w-full", f), children: [
17
+ r && /* @__PURE__ */ n("label", { htmlFor: l, className: "block text-sm font-medium text-foreground mb-1", children: [
18
+ r,
19
+ t && /* @__PURE__ */ e("span", { className: "text-destructive ml-1", children: "*" }),
20
+ !t && c && /* @__PURE__ */ e("span", { className: "text-xs text-muted-foreground ml-1", children: "(optional)" })
21
+ ] }),
22
+ /* @__PURE__ */ e(
23
+ "textarea",
24
+ {
25
+ ref: u,
26
+ id: l,
27
+ className: o(x, b, m),
28
+ required: t,
29
+ ...s
30
+ }
31
+ ),
32
+ a && /* @__PURE__ */ e("p", { className: o("mt-1.5 text-xs", d ? "text-destructive" : "text-muted-foreground"), children: a })
33
+ ] });
34
+ }
15
35
  );
16
- m.displayName = "Textarea";
36
+ p.displayName = "Textarea";
17
37
  export {
18
- m as Textarea
38
+ p as Textarea
19
39
  };
@@ -1,52 +1,45 @@
1
- import { jsx as t, jsxs as m } from "react/jsx-runtime";
2
- import d, { useState as u, useCallback as f } from "react";
3
- const x = ({ id: e, header: r, children: i, isOpen: n, onToggle: a }) => {
4
- const [c, o] = u(n !== void 0 ? n : !1), s = n !== void 0, l = s ? n : c, h = f(() => {
5
- s && a ? a(e, !l) : o((g) => !g);
6
- }, [e, l, s, a]), p = `transform transition-transform duration-300 ${l ? "rotate-180" : "rotate-0"}`;
1
+ import { jsx as o, jsxs as m } from "react/jsx-runtime";
2
+ import c, { useState as f, useCallback as u } from "react";
3
+ const w = ({ id: e, header: n, children: l, isOpen: t, onToggle: s }) => {
4
+ const [d, r] = f(t !== void 0 ? t : !1), a = t !== void 0, i = a ? t : d, h = u(() => {
5
+ a && s ? s(e, !i) : r((g) => !g);
6
+ }, [e, i, a, s]), p = `transform transition-transform duration-300 ${i ? "rotate-180" : "rotate-0"}`;
7
7
  return /* @__PURE__ */ m("div", { className: "border border-border rounded-md overflow-hidden", children: [
8
- /* @__PURE__ */ m(
8
+ /* @__PURE__ */ o("h3", { className: "m-0", children: /* @__PURE__ */ m(
9
9
  "button",
10
10
  {
11
11
  id: `accordion-header-${e}`,
12
- "aria-expanded": l,
12
+ "aria-expanded": i,
13
13
  "aria-controls": `accordion-panel-${e}`,
14
14
  onClick: h,
15
- className: "flex items-center justify-between w-full p-4 text-foreground bg-background hover:bg-background/80 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2",
16
- role: "heading",
17
- "aria-level": 3,
15
+ className: "flex items-center justify-between w-full p-4 text-left text-foreground bg-background hover:bg-background/80 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2",
18
16
  children: [
19
- /* @__PURE__ */ t("span", { className: "text-xl font-semibold", children: r }),
20
- /* @__PURE__ */ t("svg", { className: `w-6 h-6 text-foreground ${p}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ t("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
17
+ /* @__PURE__ */ o("span", { className: "text-xl font-semibold", children: n }),
18
+ /* @__PURE__ */ o("svg", { className: `w-6 h-6 text-foreground shrink-0 ${p}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ o("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
21
19
  ]
22
20
  }
23
- ),
24
- /* @__PURE__ */ t(
21
+ ) }),
22
+ /* @__PURE__ */ o(
25
23
  "div",
26
24
  {
27
25
  id: `accordion-panel-${e}`,
28
26
  role: "region",
29
27
  "aria-labelledby": `accordion-header-${e}`,
30
- style: {
31
- maxHeight: l ? "1000px" : "0",
32
- // Arbitrary large height for transition
33
- overflow: "hidden",
34
- transition: "max-height 0.3s ease-in-out"
35
- },
36
- children: /* @__PURE__ */ t("div", { className: "p-4 bg-card", children: i })
28
+ className: `grid transition-[grid-template-rows] duration-300 ease-in-out ${i ? "grid-rows-[1fr]" : "grid-rows-[0fr]"}`,
29
+ children: /* @__PURE__ */ o("div", { className: "overflow-hidden min-h-0", children: /* @__PURE__ */ o("div", { className: "p-4 bg-card", children: l }) })
37
30
  }
38
31
  )
39
32
  ] });
40
- }, w = ({ children: e, singleOpen: r = !1, className: i }) => {
41
- const [n, a] = u(null), c = f((o, s) => {
42
- r && a(s ? o : null);
43
- }, [r]);
44
- return /* @__PURE__ */ t("div", { className: `space-y-4 ${i || ""}`, children: d.Children.map(e, (o) => d.isValidElement(o) ? d.cloneElement(o, {
45
- isOpen: r ? o.props.id === n : void 0,
46
- onToggle: r ? c : void 0
47
- }) : o) });
33
+ }, x = ({ children: e, singleOpen: n = !1, className: l }) => {
34
+ const [t, s] = f(null), d = u((r, a) => {
35
+ n && s(a ? r : null);
36
+ }, [n]);
37
+ return /* @__PURE__ */ o("div", { className: `space-y-4 ${l || ""}`, children: c.Children.map(e, (r) => c.isValidElement(r) ? c.cloneElement(r, {
38
+ isOpen: n ? r.props.id === t : void 0,
39
+ onToggle: n ? d : void 0
40
+ }) : r) });
48
41
  };
49
42
  export {
50
- w as Accordion,
51
- x as AccordionItem
43
+ x as Accordion,
44
+ w as AccordionItem
52
45
  };
@@ -1,59 +1,76 @@
1
- import { jsx as d } from "react/jsx-runtime";
1
+ import { jsx as r } from "react/jsx-runtime";
2
2
  import { forwardRef as t } from "react";
3
3
  import { cn as s } from "../../utils/cn.js";
4
4
  const l = t(
5
- ({ className: e, children: a, ...r }, o) => /* @__PURE__ */ d(
5
+ ({ className: e, children: a, ...d }, o) => /* @__PURE__ */ r(
6
6
  "div",
7
7
  {
8
8
  ref: o,
9
9
  className: s(
10
- "@container bg-card text-card-foreground rounded-lg border border-border shadow-sm",
10
+ "@container bg-card text-card-foreground",
11
+ /* A card in a narrow container is chrome restating chrome: its border
12
+ sits a few pixels inside the panel's own edge, and its radius and
13
+ shadow buy nothing at 390px while its inset costs real width. So
14
+ below a 28rem container the card keeps its surface and drops the
15
+ frame — the rule above it still groups, the box no longer taxes.
16
+
17
+ A CONTAINER query, not a breakpoint: this asks how much room the
18
+ card actually has, so the same card is framed in a wide dashboard
19
+ column and flush inside a sheet or a narrow sidebar on that very
20
+ same screen. A `sm:` breakpoint would get the narrow-panel-on-a-
21
+ big-monitor case exactly backwards.
22
+
23
+ 28rem, not 24rem: inside a sheet a 390px phone gives the card a
24
+ ~358px container, but a 430px phone gives ~398px — over 24rem, so
25
+ the frame would come back on the LARGER phone. 28rem clears every
26
+ handset while leaving real desktop columns framed. */
27
+ "border-y border-border @md:rounded-lg @md:border @md:shadow-sm",
11
28
  e
12
29
  ),
13
- ...r,
30
+ ...d,
14
31
  children: a
15
32
  }
16
33
  )
17
34
  );
18
35
  l.displayName = "Card";
19
36
  const i = t(
20
- ({ className: e, ...a }, r) => /* @__PURE__ */ d(
37
+ ({ className: e, ...a }, d) => /* @__PURE__ */ r(
21
38
  "div",
22
39
  {
23
- ref: r,
40
+ ref: d,
24
41
  className: s("flex flex-col space-y-fluid-xs p-fluid-lg", e),
25
42
  ...a
26
43
  }
27
44
  )
28
45
  );
29
46
  i.displayName = "CardHeader";
30
- const n = t(
31
- ({ className: e, ...a }, r) => /* @__PURE__ */ d(
47
+ const m = t(
48
+ ({ className: e, ...a }, d) => /* @__PURE__ */ r(
32
49
  "h3",
33
50
  {
34
- ref: r,
51
+ ref: d,
35
52
  className: s("text-fluid-lg font-semibold leading-none tracking-tight", e),
36
53
  ...a
37
54
  }
38
55
  )
39
56
  );
40
- n.displayName = "CardTitle";
41
- const m = t(
42
- ({ className: e, ...a }, r) => /* @__PURE__ */ d(
57
+ m.displayName = "CardTitle";
58
+ const n = t(
59
+ ({ className: e, ...a }, d) => /* @__PURE__ */ r(
43
60
  "p",
44
61
  {
45
- ref: r,
62
+ ref: d,
46
63
  className: s("text-fluid-sm text-muted-foreground", e),
47
64
  ...a
48
65
  }
49
66
  )
50
67
  );
51
- m.displayName = "CardDescription";
68
+ n.displayName = "CardDescription";
52
69
  const c = t(
53
- ({ className: e, ...a }, r) => /* @__PURE__ */ d(
70
+ ({ className: e, ...a }, d) => /* @__PURE__ */ r(
54
71
  "h2",
55
72
  {
56
- ref: r,
73
+ ref: d,
57
74
  className: s(
58
75
  "text-xs font-semibold uppercase tracking-widest text-muted-foreground flex items-center gap-1.5",
59
76
  e
@@ -64,14 +81,14 @@ const c = t(
64
81
  );
65
82
  c.displayName = "CardLabel";
66
83
  const p = t(
67
- ({ className: e, ...a }, r) => /* @__PURE__ */ d("div", { ref: r, className: s("p-fluid-lg pt-0", e), ...a })
84
+ ({ className: e, ...a }, d) => /* @__PURE__ */ r("div", { ref: d, className: s("p-fluid-lg pt-0", e), ...a })
68
85
  );
69
86
  p.displayName = "CardContent";
70
87
  const f = t(
71
- ({ className: e, ...a }, r) => /* @__PURE__ */ d(
88
+ ({ className: e, ...a }, d) => /* @__PURE__ */ r(
72
89
  "div",
73
90
  {
74
- ref: r,
91
+ ref: d,
75
92
  className: s("flex items-center p-fluid-lg pt-0", e),
76
93
  ...a
77
94
  }
@@ -81,9 +98,9 @@ f.displayName = "CardFooter";
81
98
  export {
82
99
  l as Card,
83
100
  p as CardContent,
84
- m as CardDescription,
101
+ n as CardDescription,
85
102
  f as CardFooter,
86
103
  i as CardHeader,
87
104
  c as CardLabel,
88
- n as CardTitle
105
+ m as CardTitle
89
106
  };