@schandlergarcia/sf-web-components 1.0.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.
Files changed (195) hide show
  1. package/.a4drules/skills/building-data-visualization/SKILL.md +72 -0
  2. package/.a4drules/skills/building-data-visualization/implementation/bar-line-chart.md +316 -0
  3. package/.a4drules/skills/building-data-visualization/implementation/dashboard-layout.md +189 -0
  4. package/.a4drules/skills/building-data-visualization/implementation/donut-chart.md +181 -0
  5. package/.a4drules/skills/building-data-visualization/implementation/stat-card.md +150 -0
  6. package/.a4drules/skills/building-react-components/SKILL.md +96 -0
  7. package/.a4drules/skills/building-react-components/implementation/component.md +78 -0
  8. package/.a4drules/skills/building-react-components/implementation/header-footer.md +132 -0
  9. package/.a4drules/skills/building-react-components/implementation/page.md +93 -0
  10. package/.a4drules/skills/configuring-csp-trusted-sites/SKILL.md +90 -0
  11. package/.a4drules/skills/configuring-csp-trusted-sites/implementation/metadata-format.md +281 -0
  12. package/.a4drules/skills/configuring-webapp-metadata/SKILL.md +158 -0
  13. package/.a4drules/skills/creating-webapp/SKILL.md +140 -0
  14. package/.a4drules/skills/deploying-to-salesforce/SKILL.md +226 -0
  15. package/.a4drules/skills/implementing-file-upload/SKILL.md +396 -0
  16. package/.a4drules/skills/installing-webapp-features/SKILL.md +210 -0
  17. package/.a4drules/skills/managing-agentforce-conversation-client/SKILL.md +186 -0
  18. package/.a4drules/skills/managing-agentforce-conversation-client/references/constraints.md +134 -0
  19. package/.a4drules/skills/managing-agentforce-conversation-client/references/examples.md +132 -0
  20. package/.a4drules/skills/managing-agentforce-conversation-client/references/style-tokens.md +101 -0
  21. package/.a4drules/skills/managing-agentforce-conversation-client/references/troubleshooting.md +57 -0
  22. package/.a4drules/skills/using-salesforce-data/SKILL.md +363 -0
  23. package/.a4drules/skills/using-salesforce-data/graphql-search.sh +139 -0
  24. package/.a4drules/webapp-data.md +353 -0
  25. package/.a4drules/webapp-ui.md +16 -0
  26. package/README.md +124 -0
  27. package/dist/components/library/cards/ActionList.js +27 -0
  28. package/dist/components/library/cards/ActionList.js.map +1 -0
  29. package/dist/components/library/cards/ActivityCard.js +40 -0
  30. package/dist/components/library/cards/ActivityCard.js.map +1 -0
  31. package/dist/components/library/cards/BaseCard.js +89 -0
  32. package/dist/components/library/cards/BaseCard.js.map +1 -0
  33. package/dist/components/library/cards/CalloutCard.js +28 -0
  34. package/dist/components/library/cards/CalloutCard.js.map +1 -0
  35. package/dist/components/library/cards/ChartCard.js +79 -0
  36. package/dist/components/library/cards/ChartCard.js.map +1 -0
  37. package/dist/components/library/cards/FeedPanel.js +38 -0
  38. package/dist/components/library/cards/FeedPanel.js.map +1 -0
  39. package/dist/components/library/cards/ListCard.js +112 -0
  40. package/dist/components/library/cards/ListCard.js.map +1 -0
  41. package/dist/components/library/cards/MetricCard.js +86 -0
  42. package/dist/components/library/cards/MetricCard.js.map +1 -0
  43. package/dist/components/library/cards/MetricsStrip.js +60 -0
  44. package/dist/components/library/cards/MetricsStrip.js.map +1 -0
  45. package/dist/components/library/cards/SectionCard.js +59 -0
  46. package/dist/components/library/cards/SectionCard.js.map +1 -0
  47. package/dist/components/library/cards/StatusCard.js +137 -0
  48. package/dist/components/library/cards/StatusCard.js.map +1 -0
  49. package/dist/components/library/cards/TableCard.js +244 -0
  50. package/dist/components/library/cards/TableCard.js.map +1 -0
  51. package/dist/components/library/cards/WidgetCard.js +60 -0
  52. package/dist/components/library/cards/WidgetCard.js.map +1 -0
  53. package/dist/components/library/charts/D3Chart.js +74 -0
  54. package/dist/components/library/charts/D3Chart.js.map +1 -0
  55. package/dist/components/library/charts/D3ChartTemplates.js +44 -0
  56. package/dist/components/library/charts/D3ChartTemplates.js.map +1 -0
  57. package/dist/components/library/charts/GeoMap.js +229 -0
  58. package/dist/components/library/charts/GeoMap.js.map +1 -0
  59. package/dist/components/library/chat/ChatBar.js +194 -0
  60. package/dist/components/library/chat/ChatBar.js.map +1 -0
  61. package/dist/components/library/chat/ChatInput.js +67 -0
  62. package/dist/components/library/chat/ChatInput.js.map +1 -0
  63. package/dist/components/library/chat/ChatMessage.js +112 -0
  64. package/dist/components/library/chat/ChatMessage.js.map +1 -0
  65. package/dist/components/library/chat/ChatMessageList.js +50 -0
  66. package/dist/components/library/chat/ChatMessageList.js.map +1 -0
  67. package/dist/components/library/chat/ChatPanel.js +77 -0
  68. package/dist/components/library/chat/ChatPanel.js.map +1 -0
  69. package/dist/components/library/chat/ChatSuggestions.js +22 -0
  70. package/dist/components/library/chat/ChatSuggestions.js.map +1 -0
  71. package/dist/components/library/chat/ChatToolCall.js +87 -0
  72. package/dist/components/library/chat/ChatToolCall.js.map +1 -0
  73. package/dist/components/library/chat/ChatTypingIndicator.js +20 -0
  74. package/dist/components/library/chat/ChatTypingIndicator.js.map +1 -0
  75. package/dist/components/library/chat/ChatWelcome.js +24 -0
  76. package/dist/components/library/chat/ChatWelcome.js.map +1 -0
  77. package/dist/components/library/chat/useChatState.js +77 -0
  78. package/dist/components/library/chat/useChatState.js.map +1 -0
  79. package/dist/components/library/data/DataModeProvider.js +47 -0
  80. package/dist/components/library/data/DataModeProvider.js.map +1 -0
  81. package/dist/components/library/data/DataModeToggle.js +28 -0
  82. package/dist/components/library/data/DataModeToggle.js.map +1 -0
  83. package/dist/components/library/data/filterUtils.js +71 -0
  84. package/dist/components/library/data/filterUtils.js.map +1 -0
  85. package/dist/components/library/data/useDataSource.js +13 -0
  86. package/dist/components/library/data/useDataSource.js.map +1 -0
  87. package/dist/components/library/data/usePageFilters.js +46 -0
  88. package/dist/components/library/data/usePageFilters.js.map +1 -0
  89. package/dist/components/library/filters/FilterBar.js +89 -0
  90. package/dist/components/library/filters/FilterBar.js.map +1 -0
  91. package/dist/components/library/filters/SearchFilter.js +44 -0
  92. package/dist/components/library/filters/SearchFilter.js.map +1 -0
  93. package/dist/components/library/filters/SelectFilter.js +44 -0
  94. package/dist/components/library/filters/SelectFilter.js.map +1 -0
  95. package/dist/components/library/filters/ToggleFilter.js +48 -0
  96. package/dist/components/library/filters/ToggleFilter.js.map +1 -0
  97. package/dist/components/library/forms/FormField.js +256 -0
  98. package/dist/components/library/forms/FormField.js.map +1 -0
  99. package/dist/components/library/forms/FormModal.js +161 -0
  100. package/dist/components/library/forms/FormModal.js.map +1 -0
  101. package/dist/components/library/forms/FormRenderer.js +32 -0
  102. package/dist/components/library/forms/FormRenderer.js.map +1 -0
  103. package/dist/components/library/forms/FormSection.js +49 -0
  104. package/dist/components/library/forms/FormSection.js.map +1 -0
  105. package/dist/components/library/forms/useFormState.js +85 -0
  106. package/dist/components/library/forms/useFormState.js.map +1 -0
  107. package/dist/components/library/heroui/Accordion.js +12 -0
  108. package/dist/components/library/heroui/Accordion.js.map +1 -0
  109. package/dist/components/library/heroui/Alert.js +12 -0
  110. package/dist/components/library/heroui/Alert.js.map +1 -0
  111. package/dist/components/library/heroui/Badge.js +12 -0
  112. package/dist/components/library/heroui/Badge.js.map +1 -0
  113. package/dist/components/library/heroui/Breadcrumbs.js +12 -0
  114. package/dist/components/library/heroui/Breadcrumbs.js.map +1 -0
  115. package/dist/components/library/heroui/Button.js +18 -0
  116. package/dist/components/library/heroui/Button.js.map +1 -0
  117. package/dist/components/library/heroui/Card.js +12 -0
  118. package/dist/components/library/heroui/Card.js.map +1 -0
  119. package/dist/components/library/heroui/Drawer.js +12 -0
  120. package/dist/components/library/heroui/Drawer.js.map +1 -0
  121. package/dist/components/library/heroui/Dropdown.js +12 -0
  122. package/dist/components/library/heroui/Dropdown.js.map +1 -0
  123. package/dist/components/library/heroui/Input.js +10 -0
  124. package/dist/components/library/heroui/Input.js.map +1 -0
  125. package/dist/components/library/heroui/Kbd.js +12 -0
  126. package/dist/components/library/heroui/Kbd.js.map +1 -0
  127. package/dist/components/library/heroui/Meter.js +12 -0
  128. package/dist/components/library/heroui/Meter.js.map +1 -0
  129. package/dist/components/library/heroui/Modal.js +12 -0
  130. package/dist/components/library/heroui/Modal.js.map +1 -0
  131. package/dist/components/library/heroui/Pagination.js +12 -0
  132. package/dist/components/library/heroui/Pagination.js.map +1 -0
  133. package/dist/components/library/heroui/ProgressBar.js +12 -0
  134. package/dist/components/library/heroui/ProgressBar.js.map +1 -0
  135. package/dist/components/library/heroui/ProgressCircle.js +12 -0
  136. package/dist/components/library/heroui/ProgressCircle.js.map +1 -0
  137. package/dist/components/library/heroui/ScrollShadow.js +12 -0
  138. package/dist/components/library/heroui/ScrollShadow.js.map +1 -0
  139. package/dist/components/library/heroui/Select.js +12 -0
  140. package/dist/components/library/heroui/Select.js.map +1 -0
  141. package/dist/components/library/heroui/Separator.js +12 -0
  142. package/dist/components/library/heroui/Separator.js.map +1 -0
  143. package/dist/components/library/heroui/Skeleton.js +12 -0
  144. package/dist/components/library/heroui/Skeleton.js.map +1 -0
  145. package/dist/components/library/heroui/Tabs.js +12 -0
  146. package/dist/components/library/heroui/Tabs.js.map +1 -0
  147. package/dist/components/library/heroui/Toast.js +13 -0
  148. package/dist/components/library/heroui/Toast.js.map +1 -0
  149. package/dist/components/library/heroui/Toggle.js +12 -0
  150. package/dist/components/library/heroui/Toggle.js.map +1 -0
  151. package/dist/components/library/heroui/Tooltip.js +12 -0
  152. package/dist/components/library/heroui/Tooltip.js.map +1 -0
  153. package/dist/components/library/layout/PageContainer.js +9 -0
  154. package/dist/components/library/layout/PageContainer.js.map +1 -0
  155. package/dist/components/library/skeletons/CardSkeleton.js +29 -0
  156. package/dist/components/library/skeletons/CardSkeleton.js.map +1 -0
  157. package/dist/components/library/theme/AppThemeProvider.js +55 -0
  158. package/dist/components/library/theme/AppThemeProvider.js.map +1 -0
  159. package/dist/components/library/theme/tokens.js +55 -0
  160. package/dist/components/library/theme/tokens.js.map +1 -0
  161. package/dist/components/library/ui/Avatar.js +33 -0
  162. package/dist/components/library/ui/Avatar.js.map +1 -0
  163. package/dist/components/library/ui/Button.js +50 -0
  164. package/dist/components/library/ui/Button.js.map +1 -0
  165. package/dist/components/library/ui/Card.js +21 -0
  166. package/dist/components/library/ui/Card.js.map +1 -0
  167. package/dist/components/library/ui/Chip.js +31 -0
  168. package/dist/components/library/ui/Chip.js.map +1 -0
  169. package/dist/components/library/ui/Container.js +42 -0
  170. package/dist/components/library/ui/Container.js.map +1 -0
  171. package/dist/components/library/ui/EmptyState.js +27 -0
  172. package/dist/components/library/ui/EmptyState.js.map +1 -0
  173. package/dist/components/library/ui/Input.js +22 -0
  174. package/dist/components/library/ui/Input.js.map +1 -0
  175. package/dist/components/library/ui/Spinner.js +64 -0
  176. package/dist/components/library/ui/Spinner.js.map +1 -0
  177. package/dist/components/library/ui/Text.js +43 -0
  178. package/dist/components/library/ui/Text.js.map +1 -0
  179. package/dist/components/library/ui/Toggle.js +47 -0
  180. package/dist/components/library/ui/Toggle.js.map +1 -0
  181. package/dist/components/workspace/ComponentRegistry.js +231 -0
  182. package/dist/components/workspace/ComponentRegistry.js.map +1 -0
  183. package/dist/index.js +185 -0
  184. package/dist/index.js.map +1 -0
  185. package/dist/lib/utils.js +9 -0
  186. package/dist/lib/utils.js.map +1 -0
  187. package/dist/node_modules/clsx/dist/clsx.js +17 -0
  188. package/dist/node_modules/clsx/dist/clsx.js.map +1 -0
  189. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js +2925 -0
  190. package/dist/node_modules/tailwind-merge/dist/bundle-mjs.js.map +1 -0
  191. package/package.json +81 -0
  192. package/scripts/get-graphql-schema.mjs +68 -0
  193. package/scripts/reset-command-center.sh +358 -0
  194. package/scripts/rewrite-e2e-assets.mjs +23 -0
  195. package/scripts/validate-dashboard.sh +290 -0
@@ -0,0 +1,28 @@
1
+ import { jsx as e, jsxs as d } from "react/jsx-runtime";
2
+ import "react";
3
+ const t = {
4
+ neutral: "border-slate-200 bg-slate-50 text-slate-700 dark:border-slate-800 dark:bg-slate-950/30 dark:text-slate-200",
5
+ success: "border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900/40 dark:bg-emerald-950/20 dark:text-emerald-200",
6
+ warning: "border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900/40 dark:bg-amber-950/20 dark:text-amber-200",
7
+ danger: "border-rose-200 bg-rose-50 text-rose-800 dark:border-rose-900/40 dark:bg-rose-950/20 dark:text-rose-200",
8
+ info: "border-blue-200 bg-blue-50 text-blue-800 dark:border-blue-900/40 dark:bg-blue-950/20 dark:text-blue-200"
9
+ };
10
+ function n({
11
+ title: r,
12
+ message: l,
13
+ tone: b = "neutral",
14
+ icon: a,
15
+ className: s = ""
16
+ }) {
17
+ return /* @__PURE__ */ e("div", { className: `rounded-xl border p-4 ${t[b] ?? t.neutral} ${s}`, children: /* @__PURE__ */ d("div", { className: "flex gap-3", children: [
18
+ a && /* @__PURE__ */ e("div", { className: "mt-0.5 shrink-0", children: a }),
19
+ /* @__PURE__ */ d("div", { children: [
20
+ r && /* @__PURE__ */ e("div", { className: "mb-1 text-sm font-semibold", children: r }),
21
+ /* @__PURE__ */ e("div", { className: "text-sm", children: l })
22
+ ] })
23
+ ] }) });
24
+ }
25
+ export {
26
+ n as default
27
+ };
28
+ //# sourceMappingURL=CalloutCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CalloutCard.js","sources":["../../../../src/components/library/cards/CalloutCard.jsx"],"sourcesContent":["import React from \"react\";\n\nconst TONE_CLASSES = {\n neutral: \"border-slate-200 bg-slate-50 text-slate-700 dark:border-slate-800 dark:bg-slate-950/30 dark:text-slate-200\",\n success: \"border-emerald-200 bg-emerald-50 text-emerald-800 dark:border-emerald-900/40 dark:bg-emerald-950/20 dark:text-emerald-200\",\n warning: \"border-amber-200 bg-amber-50 text-amber-800 dark:border-amber-900/40 dark:bg-amber-950/20 dark:text-amber-200\",\n danger: \"border-rose-200 bg-rose-50 text-rose-800 dark:border-rose-900/40 dark:bg-rose-950/20 dark:text-rose-200\",\n info: \"border-blue-200 bg-blue-50 text-blue-800 dark:border-blue-900/40 dark:bg-blue-950/20 dark:text-blue-200\",\n};\n\n/**\n * Highlighted callout box for important inline messages.\n *\n * @param {string} title\n * @param {string|ReactNode} message\n * @param {\"neutral\"|\"success\"|\"warning\"|\"danger\"|\"info\"} tone\n * @param {ReactNode} icon Optional leading icon\n */\nexport default function CalloutCard({\n title,\n message,\n tone = \"neutral\",\n icon,\n className = \"\",\n}) {\n return (\n <div className={`rounded-xl border p-4 ${TONE_CLASSES[tone] ?? TONE_CLASSES.neutral} ${className}`}>\n <div className=\"flex gap-3\">\n {icon && <div className=\"mt-0.5 shrink-0\">{icon}</div>}\n <div>\n {title && <div className=\"mb-1 text-sm font-semibold\">{title}</div>}\n <div className=\"text-sm\">{message}</div>\n </div>\n </div>\n </div>\n );\n}\n"],"names":["TONE_CLASSES","CalloutCard","title","message","tone","icon","className","jsx","jsxs"],"mappings":";;AAEA,MAAMA,IAAe;AAAA,EACnB,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,MAAM;AACR;AAUA,SAAwBC,EAAY;AAAA,EAClC,OAAAC;AAAA,EACA,SAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,MAAAC;AAAA,EACA,WAAAC,IAAY;AACd,GAAG;AACD,SACE,gBAAAC,EAAC,OAAA,EAAI,WAAW,yBAAyBP,EAAaI,CAAI,KAAKJ,EAAa,OAAO,IAAIM,CAAS,IAC9F,UAAA,gBAAAE,EAAC,OAAA,EAAI,WAAU,cACZ,UAAA;AAAA,IAAAH,KAAQ,gBAAAE,EAAC,OAAA,EAAI,WAAU,mBAAmB,UAAAF,GAAK;AAAA,sBAC/C,OAAA,EACE,UAAA;AAAA,MAAAH,KAAS,gBAAAK,EAAC,OAAA,EAAI,WAAU,8BAA8B,UAAAL,GAAM;AAAA,MAC7D,gBAAAK,EAAC,OAAA,EAAI,WAAU,WAAW,UAAAJ,EAAA,CAAQ;AAAA,IAAA,EAAA,CACpC;AAAA,EAAA,EAAA,CACF,EAAA,CACF;AAEJ;"}
@@ -0,0 +1,79 @@
1
+ import { jsxs as a, jsx as e } from "react/jsx-runtime";
2
+ import "react";
3
+ import f from "./BaseCard.js";
4
+ import g from "../ui/Text.js";
5
+ import k from "../ui/Chip.js";
6
+ function I({
7
+ chart: b,
8
+ chartType: s,
9
+ title: t,
10
+ subtitle: i,
11
+ filters: d,
12
+ timeRange: r,
13
+ actions: n,
14
+ legend: m,
15
+ height: N = 280,
16
+ showGrid: c,
17
+ showAxes: h,
18
+ data: o,
19
+ loading: p = !1,
20
+ error: u,
21
+ ...x
22
+ }) {
23
+ const v = /* @__PURE__ */ a("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between", children: [
24
+ /* @__PURE__ */ a("div", { className: "min-w-0", children: [
25
+ t ? /* @__PURE__ */ e(g, { as: "div", size: "sm", weight: "medium", children: t }) : null,
26
+ i ? /* @__PURE__ */ e(g, { as: "div", size: "xs", muted: !0, className: "mt-1", children: i }) : null
27
+ ] }),
28
+ /* @__PURE__ */ a("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [
29
+ d ? /* @__PURE__ */ e("div", { className: "flex items-center gap-2", children: d }) : null,
30
+ r ? /* @__PURE__ */ e(
31
+ "select",
32
+ {
33
+ className: "h-9 rounded-lg border border-slate-200 bg-white px-3 text-sm text-slate-900 shadow-sm dark:border-slate-800 dark:bg-slate-900 dark:text-slate-50",
34
+ value: r.current,
35
+ onChange: (l) => r.onChange?.(l.target.value),
36
+ "aria-label": "Time range",
37
+ children: r.options?.map((l) => /* @__PURE__ */ e("option", { value: l.value ?? l, children: l.label ?? l }, l.value ?? l))
38
+ }
39
+ ) : null,
40
+ n ? /* @__PURE__ */ e("div", { className: "flex items-center gap-2", children: n }) : null
41
+ ] })
42
+ ] });
43
+ return u ? /* @__PURE__ */ e(
44
+ f,
45
+ {
46
+ variant: "chart",
47
+ header: v,
48
+ body: /* @__PURE__ */ e("div", { className: "mt-4 rounded-xl border border-rose-200 bg-rose-50 p-4 text-sm text-rose-900 dark:border-rose-900/40 dark:bg-rose-950/30 dark:text-rose-100", children: String(u) }),
49
+ ...x
50
+ }
51
+ ) : /* @__PURE__ */ e(
52
+ f,
53
+ {
54
+ variant: "chart",
55
+ header: /* @__PURE__ */ a("div", { className: "flex items-center justify-between gap-3", children: [
56
+ /* @__PURE__ */ e("div", { className: "min-w-0", children: v }),
57
+ s ? /* @__PURE__ */ e(k, { children: s }) : null
58
+ ] }),
59
+ body: /* @__PURE__ */ a("div", { className: "mt-4", children: [
60
+ /* @__PURE__ */ e("div", { className: "w-full", style: { height: N }, children: b }),
61
+ m ? /* @__PURE__ */ e("div", { className: "mt-3", children: m }) : null,
62
+ (c != null || h != null) && o ? /* @__PURE__ */ a("div", { className: "mt-2 text-xs text-slate-500 dark:text-slate-400", children: [
63
+ "grid: ",
64
+ String(!!c),
65
+ " · axes: ",
66
+ String(!!h),
67
+ " · points: ",
68
+ o.length
69
+ ] }) : null,
70
+ p ? /* @__PURE__ */ e("div", { className: "mt-3 text-xs text-slate-500 dark:text-slate-400", children: "Loading…" }) : null
71
+ ] }),
72
+ ...x
73
+ }
74
+ );
75
+ }
76
+ export {
77
+ I as default
78
+ };
79
+ //# sourceMappingURL=ChartCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChartCard.js","sources":["../../../../src/components/library/cards/ChartCard.jsx"],"sourcesContent":["import React from \"react\";\nimport BaseCard from \"./BaseCard\";\nimport UIText from \"../ui/Text\";\nimport UIChip from \"../ui/Chip\";\n\nexport default function ChartCard({\n chart,\n chartType,\n title,\n subtitle,\n filters,\n timeRange,\n actions,\n legend,\n height = 280,\n showGrid,\n showAxes,\n data,\n loading = false,\n error,\n ...cardProps\n}) {\n const header = (\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"min-w-0\">\n {title ? (\n <UIText as=\"div\" size=\"sm\" weight=\"medium\">\n {title}\n </UIText>\n ) : null}\n {subtitle ? (\n <UIText as=\"div\" size=\"xs\" muted className=\"mt-1\">\n {subtitle}\n </UIText>\n ) : null}\n </div>\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {filters ? <div className=\"flex items-center gap-2\">{filters}</div> : null}\n {timeRange ? (\n <select\n className=\"h-9 rounded-lg border border-slate-200 bg-white px-3 text-sm text-slate-900 shadow-sm dark:border-slate-800 dark:bg-slate-900 dark:text-slate-50\"\n value={timeRange.current}\n onChange={(e) => timeRange.onChange?.(e.target.value)}\n aria-label=\"Time range\"\n >\n {timeRange.options?.map((opt) => (\n <option key={opt.value ?? opt} value={opt.value ?? opt}>\n {opt.label ?? opt}\n </option>\n ))}\n </select>\n ) : null}\n {actions ? <div className=\"flex items-center gap-2\">{actions}</div> : null}\n </div>\n </div>\n );\n\n if (error) {\n return (\n <BaseCard\n variant=\"chart\"\n header={header}\n body={\n <div className=\"mt-4 rounded-xl border border-rose-200 bg-rose-50 p-4 text-sm text-rose-900 dark:border-rose-900/40 dark:bg-rose-950/30 dark:text-rose-100\">\n {String(error)}\n </div>\n }\n {...cardProps}\n />\n );\n }\n\n const hint = chartType ? <UIChip>{chartType}</UIChip> : null;\n\n return (\n <BaseCard\n variant=\"chart\"\n header={\n <div className=\"flex items-center justify-between gap-3\">\n <div className=\"min-w-0\">{header}</div>\n {hint}\n </div>\n }\n body={\n <div className=\"mt-4\">\n <div className=\"w-full\" style={{ height }}>\n {chart}\n </div>\n {legend ? <div className=\"mt-3\">{legend}</div> : null}\n {(showGrid != null || showAxes != null) && data ? (\n <div className=\"mt-2 text-xs text-slate-500 dark:text-slate-400\">\n grid: {String(!!showGrid)} · axes: {String(!!showAxes)} · points: {data.length}\n </div>\n ) : null}\n {loading ? (\n <div className=\"mt-3 text-xs text-slate-500 dark:text-slate-400\">Loading…</div>\n ) : null}\n </div>\n }\n {...cardProps}\n />\n );\n}\n\n\n"],"names":["ChartCard","chart","chartType","title","subtitle","filters","timeRange","actions","legend","height","showGrid","showAxes","data","loading","error","cardProps","header","jsxs","jsx","UIText","e","opt","BaseCard","UIChip"],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { jsxs as l, jsx as e } from "react/jsx-runtime";
2
+ import "react";
3
+ import i from "../ui/Text.js";
4
+ function b({
5
+ title: s,
6
+ subtitle: d,
7
+ actions: a,
8
+ children: o,
9
+ width: r,
10
+ className: m = "",
11
+ headerClassName: n = "",
12
+ bodyClassName: t = "",
13
+ ...c
14
+ }) {
15
+ const h = r ? typeof r == "number" ? { width: `${r}px` } : { width: r } : void 0;
16
+ return /* @__PURE__ */ l(
17
+ "div",
18
+ {
19
+ className: `flex shrink-0 flex-col overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm dark:border-slate-800 dark:bg-slate-900 ${m}`,
20
+ style: h,
21
+ ...c,
22
+ children: [
23
+ (s || d || a) && /* @__PURE__ */ e("div", { className: `shrink-0 border-b border-slate-100 px-4 py-3 dark:border-slate-800 ${n}`, children: /* @__PURE__ */ l("div", { className: "flex items-start justify-between gap-3", children: [
24
+ /* @__PURE__ */ l("div", { className: "min-w-0", children: [
25
+ s && /* @__PURE__ */ e(i, { as: "div", size: "sm", weight: "semibold", children: s }),
26
+ d && /* @__PURE__ */ e(i, { as: "div", size: "xs", muted: !0, className: "mt-0.5", children: d })
27
+ ] }),
28
+ a && /* @__PURE__ */ e("div", { className: "shrink-0", children: a })
29
+ ] }) }),
30
+ /* @__PURE__ */ e("div", { className: `flex-1 overflow-y-auto ${t}`, children: o })
31
+ ]
32
+ }
33
+ );
34
+ }
35
+ export {
36
+ b as default
37
+ };
38
+ //# sourceMappingURL=FeedPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeedPanel.js","sources":["../../../../src/components/library/cards/FeedPanel.jsx"],"sourcesContent":["import React from \"react\";\nimport UIText from \"../ui/Text\";\n\nexport default function FeedPanel({\n title,\n subtitle,\n actions,\n children,\n width,\n className = \"\",\n headerClassName = \"\",\n bodyClassName = \"\",\n ...rest\n}) {\n const widthStyle = width ? (typeof width === \"number\" ? { width: `${width}px` } : { width }) : undefined;\n\n return (\n <div\n className={`flex shrink-0 flex-col overflow-hidden rounded-xl border border-slate-200 bg-white shadow-sm dark:border-slate-800 dark:bg-slate-900 ${className}`}\n style={widthStyle}\n {...rest}\n >\n {(title || subtitle || actions) && (\n <div className={`shrink-0 border-b border-slate-100 px-4 py-3 dark:border-slate-800 ${headerClassName}`}>\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n {title && <UIText as=\"div\" size=\"sm\" weight=\"semibold\">{title}</UIText>}\n {subtitle && <UIText as=\"div\" size=\"xs\" muted className=\"mt-0.5\">{subtitle}</UIText>}\n </div>\n {actions && <div className=\"shrink-0\">{actions}</div>}\n </div>\n </div>\n )}\n <div className={`flex-1 overflow-y-auto ${bodyClassName}`}>\n {children}\n </div>\n </div>\n );\n}\n"],"names":["FeedPanel","title","subtitle","actions","children","width","className","headerClassName","bodyClassName","rest","widthStyle","jsxs","jsx","UIText"],"mappings":";;;AAGA,SAAwBA,EAAU;AAAA,EAChC,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,OAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,iBAAAC,IAAkB;AAAA,EAClB,eAAAC,IAAgB;AAAA,EAChB,GAAGC;AACL,GAAG;AACD,QAAMC,IAAaL,IAAS,OAAOA,KAAU,WAAW,EAAE,OAAO,GAAGA,CAAK,KAAA,IAAS,EAAE,OAAAA,MAAW;AAE/F,SACE,gBAAAM;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAW,wIAAwIL,CAAS;AAAA,MAC5J,OAAOI;AAAA,MACN,GAAGD;AAAA,MAEF,UAAA;AAAA,SAAAR,KAASC,KAAYC,MACrB,gBAAAS,EAAC,OAAA,EAAI,WAAW,sEAAsEL,CAAe,IACnG,UAAA,gBAAAI,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,UAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,WACZ,UAAA;AAAA,YAAAV,KAAS,gBAAAW,EAACC,KAAO,IAAG,OAAM,MAAK,MAAK,QAAO,YAAY,UAAAZ,EAAA,CAAM;AAAA,YAC7DC,KAAY,gBAAAU,EAACC,GAAA,EAAO,IAAG,OAAM,MAAK,MAAK,OAAK,IAAC,WAAU,UAAU,UAAAX,EAAA,CAAS;AAAA,UAAA,GAC7E;AAAA,UACCC,KAAW,gBAAAS,EAAC,OAAA,EAAI,WAAU,YAAY,UAAAT,EAAA,CAAQ;AAAA,QAAA,EAAA,CACjD,EAAA,CACF;AAAA,0BAED,OAAA,EAAI,WAAW,0BAA0BK,CAAa,IACpD,UAAAJ,EAAA,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;"}
@@ -0,0 +1,112 @@
1
+ import { jsx as e, jsxs as s } from "react/jsx-runtime";
2
+ import B from "react";
3
+ import w from "./BaseCard.js";
4
+ import i from "../ui/Text.js";
5
+ import E from "../ui/Chip.js";
6
+ function R(t) {
7
+ if (!t) return "";
8
+ try {
9
+ const a = t instanceof Date ? t : new Date(t);
10
+ return Number.isNaN(a.getTime()) ? String(t) : a.toLocaleString(void 0, { dateStyle: "medium", timeStyle: "short" });
11
+ } catch {
12
+ return String(t);
13
+ }
14
+ }
15
+ function _({ item: t }) {
16
+ const a = t?.avatar, d = t?.title ?? t?.name ?? "Item";
17
+ return a ? typeof a == "string" ? /* @__PURE__ */ e(
18
+ "img",
19
+ {
20
+ src: a,
21
+ alt: "",
22
+ className: "h-9 w-9 rounded-full border border-slate-200 object-cover dark:border-slate-800"
23
+ }
24
+ ) : B.isValidElement(a) ? /* @__PURE__ */ e("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full border border-slate-200 bg-slate-50 dark:border-slate-800 dark:bg-slate-800", children: a }) : /* @__PURE__ */ e("div", { className: "h-9 w-9 rounded-full border border-slate-200 bg-slate-100 text-xs font-semibold text-slate-700 dark:border-slate-800 dark:bg-slate-800 dark:text-slate-200 grid place-items-center", children: String(d).slice(0, 2).toUpperCase() }) : null;
25
+ }
26
+ function K({
27
+ items: t = [],
28
+ title: a,
29
+ subtitle: d,
30
+ showAvatars: n = !0,
31
+ showStatus: y = !0,
32
+ showActions: S = !0,
33
+ showTimestamp: j = !0,
34
+ dense: C = !1,
35
+ divided: U = !0,
36
+ actions: o,
37
+ itemActions: z,
38
+ onItemClick: c,
39
+ loading: L = !1,
40
+ error: m,
41
+ emptyMessage: T = "No items.",
42
+ emptyIcon: u,
43
+ maxBodyHeight: h,
44
+ ...b
45
+ }) {
46
+ const g = /* @__PURE__ */ s("div", { className: "flex items-start justify-between gap-3", children: [
47
+ /* @__PURE__ */ s("div", { className: "min-w-0", children: [
48
+ a ? /* @__PURE__ */ e(i, { as: "div", size: "sm", weight: "medium", children: a }) : null,
49
+ d ? /* @__PURE__ */ e(i, { as: "div", size: "xs", muted: !0, className: "mt-1", children: d }) : null
50
+ ] }),
51
+ o ? /* @__PURE__ */ e("div", { className: "shrink-0", children: o }) : null
52
+ ] });
53
+ if (m)
54
+ return /* @__PURE__ */ e(
55
+ w,
56
+ {
57
+ variant: "widget",
58
+ header: g,
59
+ body: /* @__PURE__ */ e("div", { className: "mt-4 rounded-xl border border-rose-200 bg-rose-50 p-4 text-sm text-rose-900 dark:border-rose-900/40 dark:bg-rose-950/30 dark:text-rose-100", children: String(m) }),
60
+ ...b
61
+ }
62
+ );
63
+ const D = C ? "py-2" : "py-3", I = h ? { maxHeight: h, overflowY: "auto" } : {}, V = L ? /* @__PURE__ */ e("div", { className: "mt-4 space-y-3", children: Array.from({ length: 4 }).map((r, l) => /* @__PURE__ */ s("div", { className: "flex items-center gap-3 rounded-xl border border-slate-200 bg-white p-3 dark:border-slate-800 dark:bg-slate-900", children: [
64
+ n ? /* @__PURE__ */ e("div", { className: "h-9 w-9 animate-pulse rounded-full bg-slate-200 dark:bg-slate-800" }) : null,
65
+ /* @__PURE__ */ s("div", { className: "flex-1 space-y-2", children: [
66
+ /* @__PURE__ */ e("div", { className: "h-4 w-1/3 animate-pulse rounded bg-slate-200 dark:bg-slate-800" }),
67
+ /* @__PURE__ */ e("div", { className: "h-3 w-2/3 animate-pulse rounded bg-slate-200 dark:bg-slate-800" })
68
+ ] })
69
+ ] }, l)) }) : t.length === 0 ? /* @__PURE__ */ s("div", { className: "mt-4 rounded-xl border border-dashed border-slate-300 bg-slate-50 p-6 text-center dark:border-slate-700 dark:bg-slate-950/30", children: [
70
+ u ? /* @__PURE__ */ e("div", { className: "mb-2", children: u }) : null,
71
+ /* @__PURE__ */ e(i, { size: "sm", muted: !0, children: T })
72
+ ] }) : /* @__PURE__ */ e("div", { className: "mt-4 overflow-hidden rounded-xl border border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900", children: /* @__PURE__ */ e("ul", { className: U ? "divide-y divide-slate-200 dark:divide-slate-800" : "", style: I, children: t.map((r, l) => {
73
+ const Y = r?.id ?? l, A = r?.title ?? r?.name ?? "Item", f = r?.description, x = r?.status, v = r?.timestamp, p = r?.value, N = r?.unit, k = S ? z?.(r, l) : null;
74
+ return /* @__PURE__ */ s(
75
+ "li",
76
+ {
77
+ className: [
78
+ "group flex items-start justify-between gap-3 px-4",
79
+ D,
80
+ c ? "cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-950/30" : ""
81
+ ].filter(Boolean).join(" "),
82
+ onClick: () => c?.(r, l),
83
+ children: [
84
+ /* @__PURE__ */ s("div", { className: "flex min-w-0 items-start gap-3", children: [
85
+ n ? /* @__PURE__ */ e(_, { item: r }) : null,
86
+ /* @__PURE__ */ s("div", { className: "min-w-0", children: [
87
+ /* @__PURE__ */ s("div", { className: "flex flex-wrap items-center gap-2", children: [
88
+ /* @__PURE__ */ e("div", { className: "text-sm font-semibold text-slate-900 dark:text-slate-50", children: A }),
89
+ y && x ? /* @__PURE__ */ e(E, { children: String(x) }) : null
90
+ ] }),
91
+ f ? /* @__PURE__ */ e("div", { className: "mt-1 text-sm text-slate-600 dark:text-slate-300", children: f }) : null,
92
+ j && v ? /* @__PURE__ */ e("div", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: R(v) }) : null
93
+ ] })
94
+ ] }),
95
+ /* @__PURE__ */ s("div", { className: "flex shrink-0 items-center gap-2", children: [
96
+ p != null ? /* @__PURE__ */ e("div", { className: "text-right", children: /* @__PURE__ */ s("div", { className: "text-sm font-semibold text-slate-900 dark:text-slate-50", children: [
97
+ String(p),
98
+ N ? /* @__PURE__ */ e("span", { className: "ml-1 text-xs font-medium text-slate-500 dark:text-slate-400", children: N }) : null
99
+ ] }) }) : null,
100
+ k ? /* @__PURE__ */ e("div", { className: "opacity-100 sm:opacity-0 sm:group-hover:opacity-100", children: k }) : null
101
+ ] })
102
+ ]
103
+ },
104
+ Y
105
+ );
106
+ }) }) });
107
+ return /* @__PURE__ */ e(w, { variant: "widget", header: g, body: V, isLoading: !1, ...b });
108
+ }
109
+ export {
110
+ K as default
111
+ };
112
+ //# sourceMappingURL=ListCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ListCard.js","sources":["../../../../src/components/library/cards/ListCard.jsx"],"sourcesContent":["import React from \"react\";\nimport BaseCard from \"./BaseCard\";\nimport UIText from \"../ui/Text\";\nimport UIChip from \"../ui/Chip\";\n\nfunction formatTimestamp(ts) {\n if (!ts) return \"\";\n try {\n const d = ts instanceof Date ? ts : new Date(ts);\n if (Number.isNaN(d.getTime())) return String(ts);\n return d.toLocaleString(undefined, { dateStyle: \"medium\", timeStyle: \"short\" });\n } catch {\n return String(ts);\n }\n}\n\nfunction Avatar({ item }) {\n const avatar = item?.avatar;\n const name = item?.title ?? item?.name ?? \"Item\";\n if (!avatar) return null;\n if (typeof avatar === \"string\") {\n return (\n <img\n src={avatar}\n alt=\"\"\n className=\"h-9 w-9 rounded-full border border-slate-200 object-cover dark:border-slate-800\"\n />\n );\n }\n if (React.isValidElement(avatar)) {\n return (\n <div className=\"flex h-9 w-9 shrink-0 items-center justify-center rounded-full border border-slate-200 bg-slate-50 dark:border-slate-800 dark:bg-slate-800\">\n {avatar}\n </div>\n );\n }\n return (\n <div className=\"h-9 w-9 rounded-full border border-slate-200 bg-slate-100 text-xs font-semibold text-slate-700 dark:border-slate-800 dark:bg-slate-800 dark:text-slate-200 grid place-items-center\">\n {String(name).slice(0, 2).toUpperCase()}\n </div>\n );\n}\n\nexport default function ListCard({\n items = [],\n title,\n subtitle,\n showAvatars = true,\n showStatus = true,\n showActions = true,\n showTimestamp = true,\n dense = false,\n divided = true,\n actions,\n itemActions,\n onItemClick,\n loading = false,\n error,\n emptyMessage = \"No items.\",\n emptyIcon,\n maxBodyHeight,\n ...cardProps\n}) {\n const header = (\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n {title ? (\n <UIText as=\"div\" size=\"sm\" weight=\"medium\">\n {title}\n </UIText>\n ) : null}\n {subtitle ? (\n <UIText as=\"div\" size=\"xs\" muted className=\"mt-1\">\n {subtitle}\n </UIText>\n ) : null}\n </div>\n {actions ? <div className=\"shrink-0\">{actions}</div> : null}\n </div>\n );\n\n if (error) {\n return (\n <BaseCard\n variant=\"widget\"\n header={header}\n body={\n <div className=\"mt-4 rounded-xl border border-rose-200 bg-rose-50 p-4 text-sm text-rose-900 dark:border-rose-900/40 dark:bg-rose-950/30 dark:text-rose-100\">\n {String(error)}\n </div>\n }\n {...cardProps}\n />\n );\n }\n\n const padY = dense ? \"py-2\" : \"py-3\";\n\n const scrollStyle = maxBodyHeight ? { maxHeight: maxBodyHeight, overflowY: \"auto\" } : {};\n\n const body =\n loading ? (\n <div className=\"mt-4 space-y-3\">\n {Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"flex items-center gap-3 rounded-xl border border-slate-200 bg-white p-3 dark:border-slate-800 dark:bg-slate-900\">\n {showAvatars ? <div className=\"h-9 w-9 animate-pulse rounded-full bg-slate-200 dark:bg-slate-800\" /> : null}\n <div className=\"flex-1 space-y-2\">\n <div className=\"h-4 w-1/3 animate-pulse rounded bg-slate-200 dark:bg-slate-800\" />\n <div className=\"h-3 w-2/3 animate-pulse rounded bg-slate-200 dark:bg-slate-800\" />\n </div>\n </div>\n ))}\n </div>\n ) : items.length === 0 ? (\n <div className=\"mt-4 rounded-xl border border-dashed border-slate-300 bg-slate-50 p-6 text-center dark:border-slate-700 dark:bg-slate-950/30\">\n {emptyIcon ? <div className=\"mb-2\">{emptyIcon}</div> : null}\n <UIText size=\"sm\" muted>\n {emptyMessage}\n </UIText>\n </div>\n ) : (\n <div className=\"mt-4 overflow-hidden rounded-xl border border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-900\">\n <ul className={divided ? \"divide-y divide-slate-200 dark:divide-slate-800\" : \"\"} style={scrollStyle}>\n {items.map((item, idx) => {\n const key = item?.id ?? idx;\n const name = item?.title ?? item?.name ?? \"Item\";\n const desc = item?.description;\n const status = item?.status;\n const ts = item?.timestamp;\n const itemValue = item?.value;\n const itemUnit = item?.unit;\n const right = showActions ? itemActions?.(item, idx) : null;\n\n return (\n <li\n key={key}\n className={[\n \"group flex items-start justify-between gap-3 px-4\",\n padY,\n onItemClick ? \"cursor-pointer hover:bg-slate-50 dark:hover:bg-slate-950/30\" : \"\"\n ]\n .filter(Boolean)\n .join(\" \")}\n onClick={() => onItemClick?.(item, idx)}\n >\n <div className=\"flex min-w-0 items-start gap-3\">\n {showAvatars ? <Avatar item={item} /> : null}\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <div className=\"text-sm font-semibold text-slate-900 dark:text-slate-50\">\n {name}\n </div>\n {showStatus && status ? (\n <UIChip>{String(status)}</UIChip>\n ) : null}\n </div>\n {desc ? (\n <div className=\"mt-1 text-sm text-slate-600 dark:text-slate-300\">{desc}</div>\n ) : null}\n {showTimestamp && ts ? (\n <div className=\"mt-1 text-xs text-slate-500 dark:text-slate-400\">\n {formatTimestamp(ts)}\n </div>\n ) : null}\n </div>\n </div>\n\n <div className=\"flex shrink-0 items-center gap-2\">\n {itemValue != null ? (\n <div className=\"text-right\">\n <div className=\"text-sm font-semibold text-slate-900 dark:text-slate-50\">\n {String(itemValue)}\n {itemUnit ? <span className=\"ml-1 text-xs font-medium text-slate-500 dark:text-slate-400\">{itemUnit}</span> : null}\n </div>\n </div>\n ) : null}\n {right ? (\n <div className=\"opacity-100 sm:opacity-0 sm:group-hover:opacity-100\">\n {right}\n </div>\n ) : null}\n </div>\n </li>\n );\n })}\n </ul>\n </div>\n );\n\n return <BaseCard variant=\"widget\" header={header} body={body} isLoading={false} {...cardProps} />;\n}\n\n\n"],"names":["formatTimestamp","ts","d","Avatar","item","avatar","name","jsx","React","ListCard","items","title","subtitle","showAvatars","showStatus","showActions","showTimestamp","dense","divided","actions","itemActions","onItemClick","loading","error","emptyMessage","emptyIcon","maxBodyHeight","cardProps","header","jsxs","UIText","BaseCard","padY","scrollStyle","body","_","i","idx","key","desc","status","itemValue","itemUnit","right","UIChip"],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ import { jsx as e, jsxs as t } from "react/jsx-runtime";
2
+ import "react";
3
+ import x from "./BaseCard.js";
4
+ const o = {
5
+ positive: "text-emerald-700 dark:text-emerald-400",
6
+ negative: "text-rose-700 dark:text-rose-400",
7
+ neutral: "text-slate-600 dark:text-slate-300"
8
+ }, b = {
9
+ default: "bg-slate-100 text-slate-800 dark:bg-slate-800 dark:text-slate-100",
10
+ primary: "bg-brand-100 text-brand-800 dark:bg-brand-950/40 dark:text-brand-200",
11
+ success: "bg-emerald-100 text-emerald-800 dark:bg-emerald-950/40 dark:text-emerald-200",
12
+ warning: "bg-amber-100 text-amber-900 dark:bg-amber-950/40 dark:text-amber-200",
13
+ danger: "bg-rose-100 text-rose-800 dark:bg-rose-950/40 dark:text-rose-200"
14
+ };
15
+ function L({
16
+ title: u,
17
+ value: g,
18
+ subtitle: s,
19
+ change: a,
20
+ changeType: f = "neutral",
21
+ icon: l,
22
+ color: k = "default",
23
+ trend: r,
24
+ trendIcon: d,
25
+ layout: p = "default",
26
+ footer: i,
27
+ actions: n,
28
+ loading: h = !1,
29
+ error: m,
30
+ ...c
31
+ }) {
32
+ const v = o[f] ?? o.neutral, N = b[k] ?? b.default;
33
+ if (m)
34
+ return /* @__PURE__ */ e(
35
+ x,
36
+ {
37
+ variant: "metric",
38
+ body: /* @__PURE__ */ e("div", { className: "rounded-xl border border-rose-200 bg-rose-50 p-4 text-sm text-rose-900 dark:border-rose-900/40 dark:bg-rose-950/30 dark:text-rose-100", children: String(m) }),
39
+ ...c
40
+ }
41
+ );
42
+ const y = /* @__PURE__ */ t("div", { className: "flex items-start justify-between gap-3", children: [
43
+ /* @__PURE__ */ t("div", { className: "min-w-0", children: [
44
+ /* @__PURE__ */ e("div", { className: "text-sm font-medium text-slate-600 dark:text-slate-300", children: u }),
45
+ s ? /* @__PURE__ */ e("div", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: s }) : null
46
+ ] }),
47
+ n ? /* @__PURE__ */ e("div", { className: "shrink-0", children: n }) : null
48
+ ] }), j = /* @__PURE__ */ e("div", { className: ["mt-2", p === "compact" ? "space-y-1" : "space-y-2"].join(" "), children: /* @__PURE__ */ t("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1", children: [
49
+ /* @__PURE__ */ t("div", { className: "flex items-center gap-2", children: [
50
+ l ? /* @__PURE__ */ e(
51
+ "span",
52
+ {
53
+ className: [
54
+ "inline-flex h-8 w-8 items-center justify-center rounded-lg",
55
+ N
56
+ ].join(" "),
57
+ "aria-hidden": "true",
58
+ children: l
59
+ }
60
+ ) : null,
61
+ /* @__PURE__ */ e("div", { className: "text-2xl font-semibold tracking-tight text-slate-900 dark:text-slate-50", children: g })
62
+ ] }),
63
+ (a || r) && /* @__PURE__ */ t("div", { className: ["flex items-center gap-1.5 text-xs font-medium", v].join(" "), children: [
64
+ d ? /* @__PURE__ */ e("span", { "aria-hidden": "true", children: d }) : null,
65
+ a ? /* @__PURE__ */ e("span", { children: a }) : null,
66
+ r ? /* @__PURE__ */ e("span", { className: "text-[11px] font-normal text-slate-500 dark:text-slate-400", children: r }) : null
67
+ ] })
68
+ ] }) });
69
+ return /* @__PURE__ */ e(
70
+ x,
71
+ {
72
+ variant: "metric",
73
+ padding: "sm",
74
+ size: "sm",
75
+ header: y,
76
+ body: j,
77
+ footer: i ? /* @__PURE__ */ e("div", { className: "mt-3", children: i }) : null,
78
+ isLoading: h,
79
+ ...c
80
+ }
81
+ );
82
+ }
83
+ export {
84
+ L as default
85
+ };
86
+ //# sourceMappingURL=MetricCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetricCard.js","sources":["../../../../src/components/library/cards/MetricCard.jsx"],"sourcesContent":["import React from \"react\";\nimport BaseCard from \"./BaseCard\";\n\nconst CHANGE_STYLES = {\n positive: \"text-emerald-700 dark:text-emerald-400\",\n negative: \"text-rose-700 dark:text-rose-400\",\n neutral: \"text-slate-600 dark:text-slate-300\"\n};\n\nconst COLOR_STYLES = {\n default: \"bg-slate-100 text-slate-800 dark:bg-slate-800 dark:text-slate-100\",\n primary: \"bg-brand-100 text-brand-800 dark:bg-brand-950/40 dark:text-brand-200\",\n success: \"bg-emerald-100 text-emerald-800 dark:bg-emerald-950/40 dark:text-emerald-200\",\n warning: \"bg-amber-100 text-amber-900 dark:bg-amber-950/40 dark:text-amber-200\",\n danger: \"bg-rose-100 text-rose-800 dark:bg-rose-950/40 dark:text-rose-200\"\n};\n\nexport default function MetricCard({\n title,\n value,\n subtitle,\n change,\n changeType = \"neutral\",\n icon,\n color = \"default\",\n trend,\n trendIcon,\n layout = \"default\",\n footer,\n actions,\n loading = false,\n error,\n ...cardProps\n}) {\n const changeClass = CHANGE_STYLES[changeType] ?? CHANGE_STYLES.neutral;\n const pillClass = COLOR_STYLES[color] ?? COLOR_STYLES.default;\n\n if (error) {\n return (\n <BaseCard\n variant=\"metric\"\n body={\n <div className=\"rounded-xl border border-rose-200 bg-rose-50 p-4 text-sm text-rose-900 dark:border-rose-900/40 dark:bg-rose-950/30 dark:text-rose-100\">\n {String(error)}\n </div>\n }\n {...cardProps}\n />\n );\n }\n\n const header = (\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"text-sm font-medium text-slate-600 dark:text-slate-300\">{title}</div>\n {subtitle ? (\n <div className=\"mt-1 text-xs text-slate-500 dark:text-slate-400\">{subtitle}</div>\n ) : null}\n </div>\n {actions ? <div className=\"shrink-0\">{actions}</div> : null}\n </div>\n );\n\n const body = (\n <div className={[\"mt-2\", layout === \"compact\" ? \"space-y-1\" : \"space-y-2\"].join(\" \")}>\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1\">\n <div className=\"flex items-center gap-2\">\n {icon ? (\n <span\n className={[\n \"inline-flex h-8 w-8 items-center justify-center rounded-lg\",\n pillClass\n ].join(\" \")}\n aria-hidden=\"true\"\n >\n {icon}\n </span>\n ) : null}\n <div className=\"text-2xl font-semibold tracking-tight text-slate-900 dark:text-slate-50\">\n {value}\n </div>\n </div>\n\n {(change || trend) && (\n <div className={[\"flex items-center gap-1.5 text-xs font-medium\", changeClass].join(\" \")}>\n {trendIcon ? <span aria-hidden=\"true\">{trendIcon}</span> : null}\n {change ? <span>{change}</span> : null}\n {trend ? <span className=\"text-[11px] font-normal text-slate-500 dark:text-slate-400\">{trend}</span> : null}\n </div>\n )}\n </div>\n </div>\n );\n\n return (\n <BaseCard\n variant=\"metric\"\n padding=\"sm\"\n size=\"sm\"\n header={header}\n body={body}\n footer={footer ? <div className=\"mt-3\">{footer}</div> : null}\n isLoading={loading}\n {...cardProps}\n />\n );\n}\n\n\n"],"names":["CHANGE_STYLES","COLOR_STYLES","MetricCard","title","value","subtitle","change","changeType","icon","color","trend","trendIcon","layout","footer","actions","loading","error","cardProps","changeClass","pillClass","jsx","BaseCard","header","jsxs","body"],"mappings":";;;AAGA,MAAMA,IAAgB;AAAA,EACpB,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AACX,GAEMC,IAAe;AAAA,EACnB,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AAAA,EACT,QAAQ;AACV;AAEA,SAAwBC,EAAW;AAAA,EACjC,OAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,QAAAC;AAAA,EACA,YAAAC,IAAa;AAAA,EACb,MAAAC;AAAA,EACA,OAAAC,IAAQ;AAAA,EACR,OAAAC;AAAA,EACA,WAAAC;AAAA,EACA,QAAAC,IAAS;AAAA,EACT,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,OAAAC;AAAA,EACA,GAAGC;AACL,GAAG;AACD,QAAMC,IAAclB,EAAcO,CAAU,KAAKP,EAAc,SACzDmB,IAAYlB,EAAaQ,CAAK,KAAKR,EAAa;AAEtD,MAAIe;AACF,WACE,gBAAAI;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,SAAQ;AAAA,QACR,MACE,gBAAAD,EAAC,OAAA,EAAI,WAAU,yIACZ,UAAA,OAAOJ,CAAK,GACf;AAAA,QAED,GAAGC;AAAA,MAAA;AAAA,IAAA;AAKV,QAAMK,IACJ,gBAAAC,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,WACb,UAAA;AAAA,MAAA,gBAAAH,EAAC,OAAA,EAAI,WAAU,0DAA0D,UAAAjB,GAAM;AAAA,MAC9EE,IACC,gBAAAe,EAAC,OAAA,EAAI,WAAU,mDAAmD,aAAS,IACzE;AAAA,IAAA,GACN;AAAA,IACCN,IAAU,gBAAAM,EAAC,OAAA,EAAI,WAAU,YAAY,aAAQ,IAAS;AAAA,EAAA,GACzD,GAGII,IACJ,gBAAAJ,EAAC,OAAA,EAAI,WAAW,CAAC,QAAQR,MAAW,YAAY,cAAc,WAAW,EAAE,KAAK,GAAG,GACjF,UAAA,gBAAAW,EAAC,OAAA,EAAI,WAAU,+CACb,UAAA;AAAA,IAAA,gBAAAA,EAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,MAAAf,IACC,gBAAAY;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACAD;AAAA,UAAA,EACA,KAAK,GAAG;AAAA,UACV,eAAY;AAAA,UAEX,UAAAX;AAAA,QAAA;AAAA,MAAA,IAED;AAAA,MACJ,gBAAAY,EAAC,OAAA,EAAI,WAAU,2EACZ,UAAAhB,EAAA,CACH;AAAA,IAAA,GACF;AAAA,KAEEE,KAAUI,MACV,gBAAAa,EAAC,OAAA,EAAI,WAAW,CAAC,iDAAiDL,CAAW,EAAE,KAAK,GAAG,GACpF,UAAA;AAAA,MAAAP,IAAY,gBAAAS,EAAC,QAAA,EAAK,eAAY,QAAQ,aAAU,IAAU;AAAA,MAC1Dd,IAAS,gBAAAc,EAAC,QAAA,EAAM,UAAAd,EAAA,CAAO,IAAU;AAAA,MACjCI,IAAQ,gBAAAU,EAAC,QAAA,EAAK,WAAU,8DAA8D,aAAM,IAAU;AAAA,IAAA,EAAA,CACzG;AAAA,EAAA,EAAA,CAEJ,EAAA,CACF;AAGF,SACE,gBAAAA;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAAC;AAAA,MACA,MAAAE;AAAA,MACA,QAAQX,IAAS,gBAAAO,EAAC,SAAI,WAAU,QAAQ,aAAO,IAAS;AAAA,MACxD,WAAWL;AAAA,MACV,GAAGE;AAAA,IAAA;AAAA,EAAA;AAGV;"}
@@ -0,0 +1,60 @@
1
+ import { jsxs as a, jsx as l } from "react/jsx-runtime";
2
+ import { useState as x } from "react";
3
+ const u = [
4
+ { label: "Metric A", value: "—", trend: null },
5
+ { label: "Metric B", value: "—", trend: null },
6
+ { label: "Metric C", value: "—", trend: null }
7
+ ];
8
+ function f({
9
+ metrics: e = [],
10
+ title: r,
11
+ collapsible: s = !1,
12
+ collapsed: n = !1,
13
+ className: d = ""
14
+ }) {
15
+ const [c, i] = x(n), o = e.length ? e : u;
16
+ return s && c ? /* @__PURE__ */ a(
17
+ "button",
18
+ {
19
+ type: "button",
20
+ onClick: () => i(!1),
21
+ className: `flex w-full items-center justify-between rounded-lg border border-slate-200 bg-white px-3 py-2 text-left text-xs text-slate-500 hover:bg-slate-50 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-400 dark:hover:bg-slate-800 ${d}`,
22
+ children: [
23
+ /* @__PURE__ */ a("span", { children: [
24
+ r ?? "Metrics",
25
+ ": ",
26
+ o.map((t) => `${t.label} ${t.value}`).join(" · ")
27
+ ] }),
28
+ /* @__PURE__ */ l("span", { children: "▸" })
29
+ ]
30
+ }
31
+ ) : /* @__PURE__ */ a("div", { className: `rounded-xl border border-slate-200 bg-white p-3 dark:border-slate-800 dark:bg-slate-900 ${d}`, children: [
32
+ (r || s) && /* @__PURE__ */ a("div", { className: "mb-2 flex items-center justify-between", children: [
33
+ /* @__PURE__ */ l("span", { className: "text-xs font-medium text-slate-500 dark:text-slate-400", children: r ?? "Metrics" }),
34
+ s && /* @__PURE__ */ l(
35
+ "button",
36
+ {
37
+ type: "button",
38
+ onClick: () => i(!0),
39
+ className: "text-xs text-slate-400 hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-300",
40
+ children: "Collapse"
41
+ }
42
+ )
43
+ ] }),
44
+ /* @__PURE__ */ l("div", { className: "flex flex-wrap gap-4", children: o.map((t) => /* @__PURE__ */ a("div", { className: "min-w-[80px]", children: [
45
+ /* @__PURE__ */ l("div", { className: "text-xs text-slate-400 dark:text-slate-500", children: t.label }),
46
+ /* @__PURE__ */ a("div", { className: "flex items-baseline gap-1.5", children: [
47
+ /* @__PURE__ */ l("span", { className: "text-sm font-semibold text-slate-700 dark:text-slate-200", children: t.value }),
48
+ t.trend != null && /* @__PURE__ */ l(b, { trend: t.trend })
49
+ ] })
50
+ ] }, t.label)) })
51
+ ] });
52
+ }
53
+ function b({ trend: e }) {
54
+ const s = String(e).startsWith?.("+") || e > 0 ? "text-red-500" : "text-emerald-500", n = typeof e == "number" && e > 0 ? `+${e}` : e;
55
+ return /* @__PURE__ */ l("span", { className: `text-xs ${s}`, children: n });
56
+ }
57
+ export {
58
+ f as default
59
+ };
60
+ //# sourceMappingURL=MetricsStrip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MetricsStrip.js","sources":["../../../../src/components/library/cards/MetricsStrip.jsx"],"sourcesContent":["import React, { useState } from \"react\";\n\nconst PLACEHOLDER_METRICS = [\n { label: \"Metric A\", value: \"—\", trend: null },\n { label: \"Metric B\", value: \"—\", trend: null },\n { label: \"Metric C\", value: \"—\", trend: null },\n];\n\n/**\n * Horizontal strip of KPI metrics — compact alternative to a row of MetricCards.\n *\n * @param {{ label: string, value: string|number, trend?: string|number }[]} metrics\n * @param {string} title\n * @param {boolean} collapsible Allow collapsing into a single-line summary\n * @param {boolean} collapsed Initial collapsed state\n */\nexport default function MetricsStrip({\n metrics = [],\n title,\n collapsible = false,\n collapsed: initialCollapsed = false,\n className = \"\",\n}) {\n const [collapsed, setCollapsed] = useState(initialCollapsed);\n const items = metrics.length ? metrics : PLACEHOLDER_METRICS;\n\n if (collapsible && collapsed) {\n return (\n <button\n type=\"button\"\n onClick={() => setCollapsed(false)}\n className={`flex w-full items-center justify-between rounded-lg border border-slate-200 bg-white px-3 py-2 text-left text-xs text-slate-500 hover:bg-slate-50 dark:border-slate-800 dark:bg-slate-900 dark:text-slate-400 dark:hover:bg-slate-800 ${className}`}\n >\n <span>{title ?? \"Metrics\"}: {items.map((m) => `${m.label} ${m.value}`).join(\" · \")}</span>\n <span>▸</span>\n </button>\n );\n }\n\n return (\n <div className={`rounded-xl border border-slate-200 bg-white p-3 dark:border-slate-800 dark:bg-slate-900 ${className}`}>\n {(title || collapsible) && (\n <div className=\"mb-2 flex items-center justify-between\">\n <span className=\"text-xs font-medium text-slate-500 dark:text-slate-400\">{title ?? \"Metrics\"}</span>\n {collapsible && (\n <button\n type=\"button\"\n onClick={() => setCollapsed(true)}\n className=\"text-xs text-slate-400 hover:text-slate-600 dark:text-slate-500 dark:hover:text-slate-300\"\n >\n Collapse\n </button>\n )}\n </div>\n )}\n <div className=\"flex flex-wrap gap-4\">\n {items.map((m) => (\n <div key={m.label} className=\"min-w-[80px]\">\n <div className=\"text-xs text-slate-400 dark:text-slate-500\">{m.label}</div>\n <div className=\"flex items-baseline gap-1.5\">\n <span className=\"text-sm font-semibold text-slate-700 dark:text-slate-200\">{m.value}</span>\n {m.trend != null && (\n <TrendBadge trend={m.trend} />\n )}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nfunction TrendBadge({ trend }) {\n const isPositive = String(trend).startsWith?.(\"+\") || trend > 0;\n const color = isPositive ? \"text-red-500\" : \"text-emerald-500\";\n const label = typeof trend === \"number\" ? (trend > 0 ? `+${trend}` : trend) : trend;\n return <span className={`text-xs ${color}`}>{label}</span>;\n}\n"],"names":["PLACEHOLDER_METRICS","MetricsStrip","metrics","title","collapsible","initialCollapsed","className","collapsed","setCollapsed","useState","items","jsxs","m","jsx","TrendBadge","trend","color","label"],"mappings":";;AAEA,MAAMA,IAAsB;AAAA,EAC1B,EAAE,OAAO,YAAY,OAAO,KAAK,OAAO,KAAA;AAAA,EACxC,EAAE,OAAO,YAAY,OAAO,KAAK,OAAO,KAAA;AAAA,EACxC,EAAE,OAAO,YAAY,OAAO,KAAK,OAAO,KAAA;AAC1C;AAUA,SAAwBC,EAAa;AAAA,EACnC,SAAAC,IAAU,CAAA;AAAA,EACV,OAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,WAAWC,IAAmB;AAAA,EAC9B,WAAAC,IAAY;AACd,GAAG;AACD,QAAM,CAACC,GAAWC,CAAY,IAAIC,EAASJ,CAAgB,GACrDK,IAAQR,EAAQ,SAASA,IAAUF;AAEzC,SAAII,KAAeG,IAEf,gBAAAI;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS,MAAMH,EAAa,EAAK;AAAA,MACjC,WAAW,yOAAyOF,CAAS;AAAA,MAE7P,UAAA;AAAA,QAAA,gBAAAK,EAAC,QAAA,EAAM,UAAA;AAAA,UAAAR,KAAS;AAAA,UAAU;AAAA,UAAGO,EAAM,IAAI,CAACE,MAAM,GAAGA,EAAE,KAAK,IAAIA,EAAE,KAAK,EAAE,EAAE,KAAK,KAAK;AAAA,QAAA,GAAE;AAAA,QACnF,gBAAAC,EAAC,UAAK,UAAA,IAAA,CAAC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,IAMX,gBAAAF,EAAC,OAAA,EAAI,WAAW,2FAA2FL,CAAS,IAChH,UAAA;AAAA,KAAAH,KAASC,MACT,gBAAAO,EAAC,OAAA,EAAI,WAAU,0CACb,UAAA;AAAA,MAAA,gBAAAE,EAAC,QAAA,EAAK,WAAU,0DAA0D,UAAAV,KAAS,WAAU;AAAA,MAC5FC,KACC,gBAAAS;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,MAAML,EAAa,EAAI;AAAA,UAChC,WAAU;AAAA,UACX,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,GAEJ;AAAA,IAEF,gBAAAK,EAAC,OAAA,EAAI,WAAU,wBACZ,UAAAH,EAAM,IAAI,CAACE,MACV,gBAAAD,EAAC,OAAA,EAAkB,WAAU,gBAC3B,UAAA;AAAA,MAAA,gBAAAE,EAAC,OAAA,EAAI,WAAU,8CAA8C,UAAAD,EAAE,OAAM;AAAA,MACrE,gBAAAD,EAAC,OAAA,EAAI,WAAU,+BACb,UAAA;AAAA,QAAA,gBAAAE,EAAC,QAAA,EAAK,WAAU,4DAA4D,UAAAD,EAAE,OAAM;AAAA,QACnFA,EAAE,SAAS,0BACTE,GAAA,EAAW,OAAOF,EAAE,MAAA,CAAO;AAAA,MAAA,EAAA,CAEhC;AAAA,IAAA,KAPQA,EAAE,KAQZ,CACD,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAEA,SAASE,EAAW,EAAE,OAAAC,KAAS;AAE7B,QAAMC,IADa,OAAOD,CAAK,EAAE,aAAa,GAAG,KAAKA,IAAQ,IACnC,iBAAiB,oBACtCE,IAAQ,OAAOF,KAAU,YAAYA,IAAQ,IAAI,IAAIA,CAAK,KAAcA;AAC9E,2BAAQ,QAAA,EAAK,WAAW,WAAWC,CAAK,IAAK,UAAAC,GAAM;AACrD;"}
@@ -0,0 +1,59 @@
1
+ import { jsx as t, jsxs as d } from "react/jsx-runtime";
2
+ import "react";
3
+ import k from "./BaseCard.js";
4
+ import r from "../ui/Text.js";
5
+ const n = {
6
+ default: "bg-white dark:bg-slate-900",
7
+ primary: "bg-brand-50 dark:bg-brand-950/30",
8
+ secondary: "bg-slate-50 dark:bg-slate-950/30",
9
+ accent: "bg-emerald-50 dark:bg-emerald-950/25"
10
+ }, i = {
11
+ sm: { title: "text-lg", desc: "text-sm", pad: "p-4" },
12
+ md: { title: "text-xl", desc: "text-sm", pad: "p-5" },
13
+ lg: { title: "text-2xl", desc: "text-base", pad: "p-6" },
14
+ xl: { title: "text-3xl", desc: "text-base", pad: "p-7" }
15
+ }, c = {
16
+ left: "text-left items-start",
17
+ center: "text-center items-center",
18
+ right: "text-right items-end"
19
+ };
20
+ function v({
21
+ title: a,
22
+ description: l,
23
+ label: s,
24
+ variant: o = "default",
25
+ showDivider: m = !0,
26
+ alignment: x = "left",
27
+ size: g = "md",
28
+ isDark: p = !1,
29
+ className: f = "",
30
+ ...b
31
+ }) {
32
+ const e = i[g] ?? i.md, u = c[x] ?? c.left, h = n[o] ?? n.default;
33
+ return /* @__PURE__ */ t(
34
+ k,
35
+ {
36
+ variant: "widget",
37
+ padding: "none",
38
+ className: [
39
+ h,
40
+ p ? "dark" : "",
41
+ "overflow-hidden",
42
+ f
43
+ ].filter(Boolean).join(" "),
44
+ ...b,
45
+ body: /* @__PURE__ */ d("div", { className: e.pad, children: [
46
+ /* @__PURE__ */ d("div", { className: ["flex flex-col gap-2", u].join(" "), children: [
47
+ s ? /* @__PURE__ */ t("span", { className: "inline-flex rounded-full bg-slate-900 px-2 py-1 text-[11px] font-semibold text-white dark:bg-slate-100 dark:text-slate-900", children: s }) : null,
48
+ a ? /* @__PURE__ */ t(r, { as: "h2", weight: "bold", className: ["tracking-tight", e.title].join(" "), children: a }) : null,
49
+ l ? /* @__PURE__ */ t(r, { as: "p", muted: !0, className: [e.desc, "max-w-3xl"].join(" "), children: l }) : null
50
+ ] }),
51
+ m ? /* @__PURE__ */ t("div", { className: "mt-4 h-px w-full bg-slate-200 dark:bg-slate-800" }) : null
52
+ ] })
53
+ }
54
+ );
55
+ }
56
+ export {
57
+ v as default
58
+ };
59
+ //# sourceMappingURL=SectionCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SectionCard.js","sources":["../../../../src/components/library/cards/SectionCard.jsx"],"sourcesContent":["import React from \"react\";\nimport BaseCard from \"./BaseCard\";\nimport UIText from \"../ui/Text\";\n\nconst VARIANT_STYLES = {\n default: \"bg-white dark:bg-slate-900\",\n primary: \"bg-brand-50 dark:bg-brand-950/30\",\n secondary: \"bg-slate-50 dark:bg-slate-950/30\",\n accent: \"bg-emerald-50 dark:bg-emerald-950/25\"\n};\n\nconst SIZE_STYLES = {\n sm: { title: \"text-lg\", desc: \"text-sm\", pad: \"p-4\" },\n md: { title: \"text-xl\", desc: \"text-sm\", pad: \"p-5\" },\n lg: { title: \"text-2xl\", desc: \"text-base\", pad: \"p-6\" },\n xl: { title: \"text-3xl\", desc: \"text-base\", pad: \"p-7\" }\n};\n\nconst ALIGN_STYLES = {\n left: \"text-left items-start\",\n center: \"text-center items-center\",\n right: \"text-right items-end\"\n};\n\nexport default function SectionCard({\n title,\n description,\n label,\n variant = \"default\",\n showDivider = true,\n alignment = \"left\",\n size = \"md\",\n isDark = false,\n className = \"\",\n ...cardProps\n}) {\n const s = SIZE_STYLES[size] ?? SIZE_STYLES.md;\n const align = ALIGN_STYLES[alignment] ?? ALIGN_STYLES.left;\n const variantClass = VARIANT_STYLES[variant] ?? VARIANT_STYLES.default;\n\n return (\n <BaseCard\n variant=\"widget\"\n padding=\"none\"\n className={[\n variantClass,\n isDark ? \"dark\" : \"\",\n \"overflow-hidden\",\n className\n ]\n .filter(Boolean)\n .join(\" \")}\n {...cardProps}\n body={\n <div className={s.pad}>\n <div className={[\"flex flex-col gap-2\", align].join(\" \")}>\n {label ? (\n <span className=\"inline-flex rounded-full bg-slate-900 px-2 py-1 text-[11px] font-semibold text-white dark:bg-slate-100 dark:text-slate-900\">\n {label}\n </span>\n ) : null}\n {title ? (\n <UIText as=\"h2\" weight=\"bold\" className={[\"tracking-tight\", s.title].join(\" \")}>\n {title}\n </UIText>\n ) : null}\n {description ? (\n <UIText as=\"p\" muted className={[s.desc, \"max-w-3xl\"].join(\" \")}>\n {description}\n </UIText>\n ) : null}\n </div>\n\n {showDivider ? (\n <div className=\"mt-4 h-px w-full bg-slate-200 dark:bg-slate-800\" />\n ) : null}\n </div>\n }\n />\n );\n}\n\n\n"],"names":["VARIANT_STYLES","SIZE_STYLES","ALIGN_STYLES","SectionCard","title","description","label","variant","showDivider","alignment","size","isDark","className","cardProps","s","align","variantClass","jsx","BaseCard","jsxs","UIText"],"mappings":";;;;AAIA,MAAMA,IAAiB;AAAA,EACrB,SAAS;AAAA,EACT,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AACV,GAEMC,IAAc;AAAA,EAClB,IAAI,EAAE,OAAO,WAAW,MAAM,WAAW,KAAK,MAAA;AAAA,EAC9C,IAAI,EAAE,OAAO,WAAW,MAAM,WAAW,KAAK,MAAA;AAAA,EAC9C,IAAI,EAAE,OAAO,YAAY,MAAM,aAAa,KAAK,MAAA;AAAA,EACjD,IAAI,EAAE,OAAO,YAAY,MAAM,aAAa,KAAK,MAAA;AACnD,GAEMC,IAAe;AAAA,EACnB,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AACT;AAEA,SAAwBC,EAAY;AAAA,EAClC,OAAAC;AAAA,EACA,aAAAC;AAAA,EACA,OAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,aAAAC,IAAc;AAAA,EACd,WAAAC,IAAY;AAAA,EACZ,MAAAC,IAAO;AAAA,EACP,QAAAC,IAAS;AAAA,EACT,WAAAC,IAAY;AAAA,EACZ,GAAGC;AACL,GAAG;AACD,QAAMC,IAAIb,EAAYS,CAAI,KAAKT,EAAY,IACrCc,IAAQb,EAAaO,CAAS,KAAKP,EAAa,MAChDc,IAAehB,EAAeO,CAAO,KAAKP,EAAe;AAE/D,SACE,gBAAAiB;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAAQ;AAAA,MACR,SAAQ;AAAA,MACR,WAAW;AAAA,QACTF;AAAA,QACAL,IAAS,SAAS;AAAA,QAClB;AAAA,QACAC;AAAA,MAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,MACV,GAAGC;AAAA,MACJ,MACE,gBAAAM,EAAC,OAAA,EAAI,WAAWL,EAAE,KAChB,UAAA;AAAA,QAAA,gBAAAK,EAAC,OAAA,EAAI,WAAW,CAAC,uBAAuBJ,CAAK,EAAE,KAAK,GAAG,GACpD,UAAA;AAAA,UAAAT,IACC,gBAAAW,EAAC,QAAA,EAAK,WAAU,8HACb,aACH,IACE;AAAA,UACHb,IACC,gBAAAa,EAACG,GAAA,EAAO,IAAG,MAAK,QAAO,QAAO,WAAW,CAAC,kBAAkBN,EAAE,KAAK,EAAE,KAAK,GAAG,GAC1E,aACH,IACE;AAAA,UACHT,IACC,gBAAAY,EAACG,GAAA,EAAO,IAAG,KAAI,OAAK,IAAC,WAAW,CAACN,EAAE,MAAM,WAAW,EAAE,KAAK,GAAG,GAC3D,aACH,IACE;AAAA,QAAA,GACN;AAAA,QAECN,IACC,gBAAAS,EAAC,OAAA,EAAI,WAAU,mDAAkD,IAC/D;AAAA,MAAA,EAAA,CACN;AAAA,IAAA;AAAA,EAAA;AAIR;"}