@schandlergarcia/sf-web-components 1.7.0 → 1.9.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 (188) hide show
  1. package/dist/components/library/cards/ActionList.d.ts +10 -10
  2. package/dist/components/library/cards/ActionList.js +2 -3
  3. package/dist/components/library/cards/ActionList.js.map +1 -1
  4. package/dist/components/library/cards/ActivityCard.d.ts +18 -5
  5. package/dist/components/library/cards/ActivityCard.js +3 -4
  6. package/dist/components/library/cards/ActivityCard.js.map +1 -1
  7. package/dist/components/library/cards/BaseCard.d.ts +30 -24
  8. package/dist/components/library/cards/BaseCard.js +2 -3
  9. package/dist/components/library/cards/BaseCard.js.map +1 -1
  10. package/dist/components/library/cards/CalloutCard.d.ts +11 -9
  11. package/dist/components/library/cards/CalloutCard.js +2 -3
  12. package/dist/components/library/cards/CalloutCard.js.map +1 -1
  13. package/dist/components/library/cards/ChartCard.d.ts +29 -17
  14. package/dist/components/library/cards/ChartCard.js +13 -14
  15. package/dist/components/library/cards/ChartCard.js.map +1 -1
  16. package/dist/components/library/cards/FeedPanel.d.ts +12 -11
  17. package/dist/components/library/cards/FeedPanel.js +3 -4
  18. package/dist/components/library/cards/FeedPanel.js.map +1 -1
  19. package/dist/components/library/cards/ListCard.d.ts +33 -20
  20. package/dist/components/library/cards/ListCard.js +35 -35
  21. package/dist/components/library/cards/ListCard.js.map +1 -1
  22. package/dist/components/library/cards/MetricCard.d.ts +23 -17
  23. package/dist/components/library/cards/MetricCard.js +10 -11
  24. package/dist/components/library/cards/MetricCard.js.map +1 -1
  25. package/dist/components/library/cards/MetricsStrip.d.ts +11 -11
  26. package/dist/components/library/cards/MetricsStrip.js +1 -1
  27. package/dist/components/library/cards/MetricsStrip.js.map +1 -1
  28. package/dist/components/library/cards/SectionCard.d.ts +17 -12
  29. package/dist/components/library/cards/SectionCard.js +18 -19
  30. package/dist/components/library/cards/SectionCard.js.map +1 -1
  31. package/dist/components/library/cards/SemanticMetricCard.d.ts +15 -20
  32. package/dist/components/library/cards/SemanticMetricCardWithLoading.d.ts +8 -7
  33. package/dist/components/library/cards/SemanticTableCard.d.ts +13 -18
  34. package/dist/components/library/cards/SemanticTableCardWithLoading.d.ts +8 -7
  35. package/dist/components/library/cards/StatusCard.d.ts +29 -15
  36. package/dist/components/library/cards/StatusCard.js +16 -17
  37. package/dist/components/library/cards/StatusCard.js.map +1 -1
  38. package/dist/components/library/cards/TableCard.d.ts +40 -23
  39. package/dist/components/library/cards/TableCard.js +59 -59
  40. package/dist/components/library/cards/TableCard.js.map +1 -1
  41. package/dist/components/library/cards/WidgetCard.d.ts +19 -11
  42. package/dist/components/library/cards/WidgetCard.js.map +1 -1
  43. package/dist/components/library/charts/D3Chart.d.ts +23 -16
  44. package/dist/components/library/charts/D3Chart.js.map +1 -1
  45. package/dist/components/library/charts/D3ChartTemplates.d.ts +33 -3
  46. package/dist/components/library/charts/D3ChartTemplates.js +7 -7
  47. package/dist/components/library/charts/D3ChartTemplates.js.map +1 -1
  48. package/dist/components/library/charts/GeoMap.d.ts +81 -18
  49. package/dist/components/library/charts/GeoMap.js +28 -26
  50. package/dist/components/library/charts/GeoMap.js.map +1 -1
  51. package/dist/components/library/chat/ChatBar.d.ts +14 -11
  52. package/dist/components/library/chat/ChatBar.js +2 -3
  53. package/dist/components/library/chat/ChatBar.js.map +1 -1
  54. package/dist/components/library/chat/ChatInput.d.ts +9 -8
  55. package/dist/components/library/chat/ChatInput.js.map +1 -1
  56. package/dist/components/library/chat/ChatMessage.d.ts +17 -4
  57. package/dist/components/library/chat/ChatMessage.js.map +1 -1
  58. package/dist/components/library/chat/ChatMessageList.d.ts +11 -8
  59. package/dist/components/library/chat/ChatMessageList.js.map +1 -1
  60. package/dist/components/library/chat/ChatPanel.d.ts +16 -12
  61. package/dist/components/library/chat/ChatPanel.js +8 -9
  62. package/dist/components/library/chat/ChatPanel.js.map +1 -1
  63. package/dist/components/library/chat/ChatSuggestions.d.ts +5 -4
  64. package/dist/components/library/chat/ChatSuggestions.js +2 -3
  65. package/dist/components/library/chat/ChatSuggestions.js.map +1 -1
  66. package/dist/components/library/chat/ChatToolCall.d.ts +11 -3
  67. package/dist/components/library/chat/ChatToolCall.js.map +1 -1
  68. package/dist/components/library/chat/ChatTypingIndicator.d.ts +4 -3
  69. package/dist/components/library/chat/ChatTypingIndicator.js +2 -3
  70. package/dist/components/library/chat/ChatTypingIndicator.js.map +1 -1
  71. package/dist/components/library/chat/ChatWelcome.d.ts +9 -7
  72. package/dist/components/library/chat/ChatWelcome.js +6 -7
  73. package/dist/components/library/chat/ChatWelcome.js.map +1 -1
  74. package/dist/components/library/chat/index.d.ts +10 -0
  75. package/dist/components/library/chat/useChatState.d.ts +36 -11
  76. package/dist/components/library/chat/useChatState.js +63 -46
  77. package/dist/components/library/chat/useChatState.js.map +1 -1
  78. package/dist/components/library/data/DataModeProvider.d.ts +15 -11
  79. package/dist/components/library/data/DataModeProvider.js +1 -1
  80. package/dist/components/library/data/DataModeProvider.js.map +1 -1
  81. package/dist/components/library/data/DataModeToggle.d.ts +4 -3
  82. package/dist/components/library/data/DataModeToggle.js +4 -5
  83. package/dist/components/library/data/DataModeToggle.js.map +1 -1
  84. package/dist/components/library/data/chartDataProvider.d.ts +41 -3
  85. package/dist/components/library/data/filterUtils.d.ts +38 -9
  86. package/dist/components/library/data/filterUtils.js.map +1 -1
  87. package/dist/components/library/data/useDataSource.d.ts +6 -4
  88. package/dist/components/library/data/useDataSource.js.map +1 -1
  89. package/dist/components/library/data/usePageFilters.d.ts +31 -5
  90. package/dist/components/library/data/usePageFilters.js +6 -2
  91. package/dist/components/library/data/usePageFilters.js.map +1 -1
  92. package/dist/components/library/filters/FilterBar.d.ts +18 -8
  93. package/dist/components/library/filters/FilterBar.js +2 -3
  94. package/dist/components/library/filters/FilterBar.js.map +1 -1
  95. package/dist/components/library/filters/SearchFilter.d.ts +7 -6
  96. package/dist/components/library/filters/SearchFilter.js +2 -3
  97. package/dist/components/library/filters/SearchFilter.js.map +1 -1
  98. package/dist/components/library/filters/SelectFilter.d.ts +13 -7
  99. package/dist/components/library/filters/SelectFilter.js +2 -3
  100. package/dist/components/library/filters/SelectFilter.js.map +1 -1
  101. package/dist/components/library/filters/ToggleFilter.d.ts +7 -5
  102. package/dist/components/library/filters/ToggleFilter.js +2 -3
  103. package/dist/components/library/filters/ToggleFilter.js.map +1 -1
  104. package/dist/components/library/forms/FormField.d.ts +10 -8
  105. package/dist/components/library/forms/FormField.js +3 -4
  106. package/dist/components/library/forms/FormField.js.map +1 -1
  107. package/dist/components/library/forms/FormModal.d.ts +23 -14
  108. package/dist/components/library/forms/FormModal.js.map +1 -1
  109. package/dist/components/library/forms/FormRenderer.d.ts +29 -9
  110. package/dist/components/library/forms/FormRenderer.js +6 -7
  111. package/dist/components/library/forms/FormRenderer.js.map +1 -1
  112. package/dist/components/library/forms/FormSection.d.ts +10 -8
  113. package/dist/components/library/forms/FormSection.js +2 -3
  114. package/dist/components/library/forms/FormSection.js.map +1 -1
  115. package/dist/components/library/forms/index.d.ts +5 -0
  116. package/dist/components/library/forms/useFormState.d.ts +23 -15
  117. package/dist/components/library/forms/useFormState.js +53 -47
  118. package/dist/components/library/forms/useFormState.js.map +1 -1
  119. package/dist/components/library/index.d.ts +92 -73
  120. package/dist/components/library/index.js +25 -25
  121. package/dist/components/library/index.js.map +1 -1
  122. package/dist/components/library/layout/PageContainer.d.ts +6 -4
  123. package/dist/components/library/layout/PageContainer.js +4 -5
  124. package/dist/components/library/layout/PageContainer.js.map +1 -1
  125. package/dist/components/library/skeletons/CardSkeleton.d.ts +5 -4
  126. package/dist/components/library/skeletons/CardSkeleton.js +2 -3
  127. package/dist/components/library/skeletons/CardSkeleton.js.map +1 -1
  128. package/dist/components/library/theme/AppThemeProvider.d.ts +13 -50
  129. package/dist/components/library/theme/AppThemeProvider.js.map +1 -1
  130. package/dist/components/library/theme/tokens.d.ts +45 -44
  131. package/dist/components/library/theme/tokens.js.map +1 -1
  132. package/package.json +4 -1
  133. package/src/components/library/cards/{ActionList.jsx → ActionList.tsx} +13 -9
  134. package/src/components/library/cards/{ActivityCard.jsx → ActivityCard.tsx} +33 -4
  135. package/src/components/library/cards/{BaseCard.jsx → BaseCard.tsx} +33 -6
  136. package/src/components/library/cards/{CalloutCard.jsx → CalloutCard.tsx} +12 -10
  137. package/src/components/library/cards/{ChartCard.jsx → ChartCard.tsx} +32 -6
  138. package/src/components/library/cards/{FeedPanel.jsx → FeedPanel.tsx} +13 -2
  139. package/src/components/library/cards/{ListCard.jsx → ListCard.tsx} +43 -7
  140. package/src/components/library/cards/{MetricCard.jsx → MetricCard.tsx} +25 -6
  141. package/src/components/library/cards/{MetricsStrip.jsx → MetricsStrip.tsx} +22 -12
  142. package/src/components/library/cards/{SectionCard.jsx → SectionCard.tsx} +27 -8
  143. package/src/components/library/cards/{SemanticMetricCard.jsx → SemanticMetricCard.tsx} +18 -6
  144. package/src/components/library/cards/{SemanticMetricCardWithLoading.jsx → SemanticMetricCardWithLoading.tsx} +9 -3
  145. package/src/components/library/cards/{SemanticTableCard.jsx → SemanticTableCard.tsx} +16 -5
  146. package/src/components/library/cards/{SemanticTableCardWithLoading.jsx → SemanticTableCardWithLoading.tsx} +9 -5
  147. package/src/components/library/cards/{StatusCard.jsx → StatusCard.tsx} +61 -12
  148. package/src/components/library/cards/{TableCard.jsx → TableCard.tsx} +51 -12
  149. package/src/components/library/cards/{WidgetCard.jsx → WidgetCard.tsx} +28 -5
  150. package/src/components/library/charts/{D3Chart.jsx → D3Chart.tsx} +27 -7
  151. package/src/components/library/charts/{D3ChartTemplates.jsx → D3ChartTemplates.tsx} +60 -28
  152. package/src/components/library/charts/{GeoMap.jsx → GeoMap.tsx} +106 -17
  153. package/src/components/library/chat/{ChatBar.jsx → ChatBar.tsx} +19 -8
  154. package/src/components/library/chat/{ChatInput.jsx → ChatInput.tsx} +13 -11
  155. package/src/components/library/chat/{ChatMessage.jsx → ChatMessage.tsx} +22 -9
  156. package/src/components/library/chat/{ChatMessageList.jsx → ChatMessageList.tsx} +13 -11
  157. package/src/components/library/chat/{ChatPanel.jsx → ChatPanel.tsx} +16 -13
  158. package/src/components/library/chat/{ChatSuggestions.jsx → ChatSuggestions.tsx} +6 -5
  159. package/src/components/library/chat/{ChatToolCall.jsx → ChatToolCall.tsx} +14 -4
  160. package/src/components/library/chat/{ChatTypingIndicator.jsx → ChatTypingIndicator.tsx} +5 -2
  161. package/src/components/library/chat/{ChatWelcome.jsx → ChatWelcome.tsx} +9 -7
  162. package/src/components/library/chat/index.tsx +26 -0
  163. package/src/components/library/chat/useChatState.tsx +181 -0
  164. package/src/components/library/data/{DataModeProvider.jsx → DataModeProvider.tsx} +25 -8
  165. package/src/components/library/data/{DataModeToggle.jsx → DataModeToggle.tsx} +5 -2
  166. package/src/components/library/data/{chartDataProvider.jsx → chartDataProvider.tsx} +49 -5
  167. package/src/components/library/data/{filterUtils.jsx → filterUtils.tsx} +58 -12
  168. package/src/components/library/data/{useDataSource.jsx → useDataSource.tsx} +9 -2
  169. package/src/components/library/data/{usePageFilters.jsx → usePageFilters.tsx} +49 -9
  170. package/src/components/library/filters/{FilterBar.jsx → FilterBar.tsx} +21 -11
  171. package/src/components/library/filters/{SearchFilter.jsx → SearchFilter.tsx} +8 -2
  172. package/src/components/library/filters/{SelectFilter.jsx → SelectFilter.tsx} +15 -8
  173. package/src/components/library/filters/{ToggleFilter.jsx → ToggleFilter.tsx} +7 -6
  174. package/src/components/library/forms/{FormField.jsx → FormField.tsx} +91 -45
  175. package/src/components/library/forms/{FormModal.jsx → FormModal.tsx} +21 -20
  176. package/src/components/library/forms/{FormRenderer.jsx → FormRenderer.tsx} +32 -10
  177. package/src/components/library/forms/{FormSection.jsx → FormSection.tsx} +13 -7
  178. package/src/components/library/forms/index.tsx +11 -0
  179. package/src/components/library/forms/{useFormState.jsx → useFormState.tsx} +43 -23
  180. package/src/components/library/{index.jsx → index.ts} +14 -14
  181. package/src/components/library/layout/{PageContainer.jsx → PageContainer.tsx} +6 -3
  182. package/src/components/library/skeletons/{CardSkeleton.jsx → CardSkeleton.tsx} +5 -4
  183. package/src/components/library/theme/{AppThemeProvider.jsx → AppThemeProvider.tsx} +20 -7
  184. package/src/components/library/theme/{tokens.jsx → tokens.tsx} +37 -3
  185. package/src/components/library/chat/index.jsx +0 -10
  186. package/src/components/library/chat/useChatState.jsx +0 -130
  187. package/src/components/library/forms/index.jsx +0 -5
  188. /package/src/components/library/filters/{index.jsx → index.ts} +0 -0
@@ -1,13 +1,17 @@
1
1
  import React from "react";
2
- import BaseCard from "./BaseCard";
2
+ import BaseCard, { BaseCardProps } from "./BaseCard";
3
3
 
4
- const CHANGE_STYLES = {
4
+ type ChangeType = "positive" | "negative" | "neutral";
5
+ type Color = "default" | "primary" | "success" | "warning" | "danger";
6
+ type Layout = "default" | "compact";
7
+
8
+ const CHANGE_STYLES: Record<ChangeType, string> = {
5
9
  positive: "text-emerald-700 dark:text-emerald-400",
6
10
  negative: "text-rose-700 dark:text-rose-400",
7
11
  neutral: "text-slate-600 dark:text-slate-300"
8
12
  };
9
13
 
10
- const COLOR_STYLES = {
14
+ const COLOR_STYLES: Record<Color, string> = {
11
15
  default: "bg-slate-100 text-slate-800 dark:bg-slate-800 dark:text-slate-100",
12
16
  primary: "bg-brand-100 text-brand-800 dark:bg-brand-950/40 dark:text-brand-200",
13
17
  success: "bg-emerald-100 text-emerald-800 dark:bg-emerald-950/40 dark:text-emerald-200",
@@ -15,6 +19,23 @@ const COLOR_STYLES = {
15
19
  danger: "bg-rose-100 text-rose-800 dark:bg-rose-950/40 dark:text-rose-200"
16
20
  };
17
21
 
22
+ export interface MetricCardProps extends Omit<BaseCardProps, "variant" | "padding" | "size" | "header" | "body" | "footer"> {
23
+ title: string;
24
+ value: string | number;
25
+ subtitle?: string;
26
+ change?: string | number;
27
+ changeType?: ChangeType;
28
+ icon?: React.ReactNode;
29
+ color?: Color;
30
+ trend?: string;
31
+ trendIcon?: React.ReactNode;
32
+ layout?: Layout;
33
+ footer?: React.ReactNode;
34
+ actions?: React.ReactNode;
35
+ loading?: boolean;
36
+ error?: string | Error;
37
+ }
38
+
18
39
  export default function MetricCard({
19
40
  title,
20
41
  value,
@@ -31,7 +52,7 @@ export default function MetricCard({
31
52
  loading = false,
32
53
  error,
33
54
  ...cardProps
34
- }) {
55
+ }: MetricCardProps) {
35
56
  const changeClass = CHANGE_STYLES[changeType] ?? CHANGE_STYLES.neutral;
36
57
  const pillClass = COLOR_STYLES[color] ?? COLOR_STYLES.default;
37
58
 
@@ -105,5 +126,3 @@ export default function MetricCard({
105
126
  />
106
127
  );
107
128
  }
108
-
109
-
@@ -1,4 +1,4 @@
1
- import React, { useState } from "react";
1
+ import { useState } from "react";
2
2
 
3
3
  const PLACEHOLDER_METRICS = [
4
4
  { label: "Metric A", value: "—", trend: null },
@@ -6,21 +6,27 @@ const PLACEHOLDER_METRICS = [
6
6
  { label: "Metric C", value: "—", trend: null },
7
7
  ];
8
8
 
9
- /**
10
- * Horizontal strip of KPI metrics — compact alternative to a row of MetricCards.
11
- *
12
- * @param {{ label: string, value: string|number, trend?: string|number }[]} metrics
13
- * @param {string} title
14
- * @param {boolean} collapsible Allow collapsing into a single-line summary
15
- * @param {boolean} collapsed Initial collapsed state
16
- */
9
+ export interface Metric {
10
+ label: string;
11
+ value: string | number;
12
+ trend?: string | number | null;
13
+ }
14
+
15
+ export interface MetricsStripProps {
16
+ metrics?: Metric[];
17
+ title?: string;
18
+ collapsible?: boolean;
19
+ collapsed?: boolean;
20
+ className?: string;
21
+ }
22
+
17
23
  export default function MetricsStrip({
18
24
  metrics = [],
19
25
  title,
20
26
  collapsible = false,
21
27
  collapsed: initialCollapsed = false,
22
28
  className = "",
23
- }) {
29
+ }: MetricsStripProps) {
24
30
  const [collapsed, setCollapsed] = useState(initialCollapsed);
25
31
  const items = metrics.length ? metrics : PLACEHOLDER_METRICS;
26
32
 
@@ -70,8 +76,12 @@ export default function MetricsStrip({
70
76
  );
71
77
  }
72
78
 
73
- function TrendBadge({ trend }) {
74
- const isPositive = String(trend).startsWith?.("+") || trend > 0;
79
+ interface TrendBadgeProps {
80
+ trend: string | number;
81
+ }
82
+
83
+ function TrendBadge({ trend }: TrendBadgeProps) {
84
+ const isPositive = String(trend).startsWith?.("+") || (typeof trend === "number" && trend > 0);
75
85
  const color = isPositive ? "text-red-500" : "text-emerald-500";
76
86
  const label = typeof trend === "number" ? (trend > 0 ? `+${trend}` : trend) : trend;
77
87
  return <span className={`text-xs ${color}`}>{label}</span>;
@@ -1,27 +1,48 @@
1
- import React from "react";
2
- import BaseCard from "./BaseCard";
1
+ import BaseCard, { BaseCardProps } from "./BaseCard";
3
2
  import UIText from "../ui/Text";
4
3
 
5
- const VARIANT_STYLES = {
4
+ type Variant = "default" | "primary" | "secondary" | "accent";
5
+ type Size = "sm" | "md" | "lg" | "xl";
6
+ type Alignment = "left" | "center" | "right";
7
+
8
+ const VARIANT_STYLES: Record<Variant, string> = {
6
9
  default: "bg-white dark:bg-slate-900",
7
10
  primary: "bg-brand-50 dark:bg-brand-950/30",
8
11
  secondary: "bg-slate-50 dark:bg-slate-950/30",
9
12
  accent: "bg-emerald-50 dark:bg-emerald-950/25"
10
13
  };
11
14
 
12
- const SIZE_STYLES = {
15
+ interface SizeConfig {
16
+ title: string;
17
+ desc: string;
18
+ pad: string;
19
+ }
20
+
21
+ const SIZE_STYLES: Record<Size, SizeConfig> = {
13
22
  sm: { title: "text-lg", desc: "text-sm", pad: "p-4" },
14
23
  md: { title: "text-xl", desc: "text-sm", pad: "p-5" },
15
24
  lg: { title: "text-2xl", desc: "text-base", pad: "p-6" },
16
25
  xl: { title: "text-3xl", desc: "text-base", pad: "p-7" }
17
26
  };
18
27
 
19
- const ALIGN_STYLES = {
28
+ const ALIGN_STYLES: Record<Alignment, string> = {
20
29
  left: "text-left items-start",
21
30
  center: "text-center items-center",
22
31
  right: "text-right items-end"
23
32
  };
24
33
 
34
+ export interface SectionCardProps extends Omit<BaseCardProps, "variant" | "padding" | "body"> {
35
+ title?: string;
36
+ description?: string;
37
+ label?: string;
38
+ variant?: Variant;
39
+ showDivider?: boolean;
40
+ alignment?: Alignment;
41
+ size?: Size;
42
+ isDark?: boolean;
43
+ className?: string;
44
+ }
45
+
25
46
  export default function SectionCard({
26
47
  title,
27
48
  description,
@@ -33,7 +54,7 @@ export default function SectionCard({
33
54
  isDark = false,
34
55
  className = "",
35
56
  ...cardProps
36
- }) {
57
+ }: SectionCardProps) {
37
58
  const s = SIZE_STYLES[size] ?? SIZE_STYLES.md;
38
59
  const align = ALIGN_STYLES[alignment] ?? ALIGN_STYLES.left;
39
60
  const variantClass = VARIANT_STYLES[variant] ?? VARIANT_STYLES.default;
@@ -79,5 +100,3 @@ export default function SectionCard({
79
100
  />
80
101
  );
81
102
  }
82
-
83
-
@@ -1,7 +1,21 @@
1
1
  import React from "react";
2
- import MetricCard from "./MetricCard";
2
+ import MetricCard, { MetricCardProps } from "./MetricCard";
3
3
  import { getSemanticMetric } from "../data/chartDataProvider";
4
4
 
5
+ export interface SemanticMetricCardProps extends Omit<MetricCardProps, "value"> {
6
+ semanticId: string;
7
+ metricId?: string;
8
+ value?: string | number;
9
+ unit?: string;
10
+ format?: string;
11
+ changeLabel?: string;
12
+ description?: string;
13
+ seriesName?: string;
14
+ availableFilters?: string[];
15
+ showFilters?: boolean;
16
+ compact?: boolean;
17
+ }
18
+
5
19
  export default function SemanticMetricCard({
6
20
  semanticId,
7
21
  metricId,
@@ -21,8 +35,8 @@ export default function SemanticMetricCard({
21
35
  className,
22
36
  loading = false,
23
37
  ...rest
24
- }) {
25
- const metric = React.useMemo(() => getSemanticMetric(semanticId, metricId), [semanticId, metricId]);
38
+ }: SemanticMetricCardProps) {
39
+ const metric = React.useMemo(() => getSemanticMetric(semanticId, metricId ?? ""), [semanticId, metricId]);
26
40
 
27
41
  const resolvedTitle = title ?? metric?.title ?? metricId ?? "Metric";
28
42
  const resolvedSubtitle = subtitle ?? metric?.subtitle;
@@ -32,13 +46,12 @@ export default function SemanticMetricCard({
32
46
  const resolvedChangeType = metric?.changeType ?? "neutral";
33
47
  const resolvedColor = metric?.color ?? "default";
34
48
 
35
- // Note: unit/format/etc. are accepted for forward compatibility; basic rendering is handled by MetricCard for now.
36
49
  return (
37
50
  <MetricCard
38
51
  title={resolvedTitle}
39
52
  subtitle={resolvedSubtitle}
40
53
  value={resolvedValue}
41
- change={resolvedChangeLabel ? `${resolvedChangeLabel} ${resolvedChange ?? ""}`.trim() : resolvedChange}
54
+ change={changeLabel ? `${changeLabel} ${resolvedChange ?? ""}`.trim() : resolvedChange}
42
55
  changeType={resolvedChangeType}
43
56
  color={resolvedColor}
44
57
  trend={resolvedTrend}
@@ -49,4 +62,3 @@ export default function SemanticMetricCard({
49
62
  />
50
63
  );
51
64
  }
52
-
@@ -1,5 +1,12 @@
1
1
  import React from "react";
2
- import SemanticMetricCard from "./SemanticMetricCard";
2
+ import SemanticMetricCard, { SemanticMetricCardProps } from "./SemanticMetricCard";
3
+
4
+ export interface SemanticMetricCardWithLoadingProps extends SemanticMetricCardProps {
5
+ simulateInitialLoad?: boolean;
6
+ minInitialDelayMs?: number;
7
+ maxInitialDelayMs?: number;
8
+ loading?: boolean;
9
+ }
3
10
 
4
11
  export default function SemanticMetricCardWithLoading({
5
12
  simulateInitialLoad = true,
@@ -7,7 +14,7 @@ export default function SemanticMetricCardWithLoading({
7
14
  maxInitialDelayMs = 900,
8
15
  loading: loadingProp,
9
16
  ...props
10
- }) {
17
+ }: SemanticMetricCardWithLoadingProps) {
11
18
  const [loading, setLoading] = React.useState(Boolean(simulateInitialLoad));
12
19
 
13
20
  React.useEffect(() => {
@@ -20,4 +27,3 @@ export default function SemanticMetricCardWithLoading({
20
27
 
21
28
  return <SemanticMetricCard loading={loadingProp ?? loading} {...props} />;
22
29
  }
23
-
@@ -1,7 +1,19 @@
1
1
  import React from "react";
2
- import TableCard from "./TableCard";
2
+ import TableCard, { TableCardProps, TableColumn } from "./TableCard";
3
3
  import { getSemanticDataset } from "../data/chartDataProvider";
4
4
 
5
+ export interface SemanticTableCardProps extends Omit<TableCardProps, "data" | "columns"> {
6
+ semanticId: string;
7
+ dataOverride?: Record<string, unknown>[];
8
+ columnsOverride?: TableColumn[];
9
+ compact?: boolean;
10
+ striped?: boolean;
11
+ isDark?: boolean;
12
+ simulateInitialLoad?: boolean;
13
+ minInitialDelayMs?: number;
14
+ maxInitialDelayMs?: number;
15
+ }
16
+
5
17
  export default function SemanticTableCard({
6
18
  semanticId,
7
19
  dataOverride,
@@ -19,12 +31,12 @@ export default function SemanticTableCard({
19
31
  minInitialDelayMs,
20
32
  maxInitialDelayMs,
21
33
  ...rest
22
- }) {
34
+ }: SemanticTableCardProps) {
23
35
  const ds = React.useMemo(() => getSemanticDataset(semanticId), [semanticId]);
24
36
  const table = ds?.table;
25
37
 
26
- const resolvedColumns = columnsOverride ?? table?.columns ?? [];
27
- const resolvedData = dataOverride ?? table?.rows ?? [];
38
+ const resolvedColumns = (columnsOverride ?? table?.columns ?? []) as TableColumn[];
39
+ const resolvedData = (dataOverride ?? table?.rows ?? []) as Record<string, unknown>[];
28
40
  const resolvedTitle = title ?? table?.title ?? ds?.title ?? "Table";
29
41
  const resolvedSubtitle = subtitle ?? table?.subtitle;
30
42
 
@@ -45,4 +57,3 @@ export default function SemanticTableCard({
45
57
  />
46
58
  );
47
59
  }
48
-
@@ -1,5 +1,11 @@
1
- import React from "react";
2
- import SemanticTableCard from "./SemanticTableCard";
1
+ import SemanticTableCard, { SemanticTableCardProps } from "./SemanticTableCard";
2
+
3
+ export interface SemanticTableCardWithLoadingProps extends SemanticTableCardProps {
4
+ simulateInitialLoad?: boolean;
5
+ minInitialDelayMs?: number;
6
+ maxInitialDelayMs?: number;
7
+ loading?: boolean;
8
+ }
3
9
 
4
10
  export default function SemanticTableCardWithLoading({
5
11
  simulateInitialLoad = true,
@@ -7,8 +13,7 @@ export default function SemanticTableCardWithLoading({
7
13
  maxInitialDelayMs = 900,
8
14
  loading: loadingProp,
9
15
  ...props
10
- }) {
11
- // Leverage TableCard's simulateInitialLoad by default; also allow explicit loading override.
16
+ }: SemanticTableCardWithLoadingProps) {
12
17
  return (
13
18
  <SemanticTableCard
14
19
  {...props}
@@ -19,4 +24,3 @@ export default function SemanticTableCardWithLoading({
19
24
  />
20
25
  );
21
26
  }
22
-
@@ -1,8 +1,17 @@
1
1
  import React from "react";
2
- import BaseCard from "./BaseCard";
2
+ import BaseCard, { BaseCardProps } from "./BaseCard";
3
3
  import UIText from "../ui/Text";
4
4
 
5
- const STATUS_META = {
5
+ type Status = "operational" | "degraded" | "outage" | "maintenance";
6
+ type Layout = "list" | "grid" | "timeline";
7
+
8
+ interface StatusMeta {
9
+ label: string;
10
+ dot: string;
11
+ chip: string;
12
+ }
13
+
14
+ const STATUS_META: Record<Status, StatusMeta> = {
6
15
  operational: {
7
16
  label: "Operational",
8
17
  dot: "bg-emerald-500",
@@ -25,15 +34,15 @@ const STATUS_META = {
25
34
  }
26
35
  };
27
36
 
28
- function normalizeStatus(status) {
37
+ function normalizeStatus(status: string | undefined): Status {
29
38
  const s = String(status ?? "operational").toLowerCase();
30
39
  if (s === "ok" || s === "healthy" || s === "up") return "operational";
31
40
  if (s === "warn" || s === "warning" || s === "partial") return "degraded";
32
41
  if (s === "down" || s === "critical") return "outage";
33
- return STATUS_META[s] ? s : "operational";
42
+ return STATUS_META[s as Status] ? (s as Status) : "operational";
34
43
  }
35
44
 
36
- function formatTimestamp(ts) {
45
+ function formatTimestamp(ts: string | Date | undefined): string {
37
46
  if (!ts) return "";
38
47
  try {
39
48
  const d = ts instanceof Date ? ts : new Date(ts);
@@ -44,7 +53,11 @@ function formatTimestamp(ts) {
44
53
  }
45
54
  }
46
55
 
47
- function StatusChip({ status }) {
56
+ interface StatusChipProps {
57
+ status: string | undefined;
58
+ }
59
+
60
+ function StatusChip({ status }: StatusChipProps) {
48
61
  const key = normalizeStatus(status);
49
62
  const meta = STATUS_META[key];
50
63
  return (
@@ -55,7 +68,23 @@ function StatusChip({ status }) {
55
68
  );
56
69
  }
57
70
 
58
- function ItemRow({ item, showTimestamp }) {
71
+ export interface StatusItem {
72
+ id?: string | number;
73
+ title?: string;
74
+ name?: string;
75
+ description?: string;
76
+ status?: string;
77
+ timestamp?: string | Date;
78
+ value?: string | number;
79
+ unit?: string;
80
+ }
81
+
82
+ interface ItemRowProps {
83
+ item: StatusItem;
84
+ showTimestamp: boolean;
85
+ }
86
+
87
+ function ItemRow({ item, showTimestamp }: ItemRowProps) {
59
88
  const name = item?.title ?? item?.name ?? "Item";
60
89
  const desc = item?.description;
61
90
  const value = item?.value;
@@ -89,7 +118,12 @@ function ItemRow({ item, showTimestamp }) {
89
118
  );
90
119
  }
91
120
 
92
- function Timeline({ items, showTimestamp }) {
121
+ interface TimelineProps {
122
+ items: StatusItem[];
123
+ showTimestamp: boolean;
124
+ }
125
+
126
+ function Timeline({ items, showTimestamp }: TimelineProps) {
93
127
  return (
94
128
  <div className="relative mt-4">
95
129
  <div className="absolute left-3 top-0 h-full w-px bg-slate-200 dark:bg-slate-800" aria-hidden="true" />
@@ -110,6 +144,21 @@ function Timeline({ items, showTimestamp }) {
110
144
  );
111
145
  }
112
146
 
147
+ export interface StatusCardProps extends Omit<BaseCardProps, "variant" | "header" | "body"> {
148
+ title?: string;
149
+ subtitle?: string;
150
+ status?: string;
151
+ items?: StatusItem[];
152
+ layout?: Layout;
153
+ showProgress?: boolean;
154
+ showTimestamp?: boolean;
155
+ actions?: React.ReactNode;
156
+ loading?: boolean;
157
+ error?: string | Error;
158
+ emptyMessage?: string;
159
+ maxBodyHeight?: string | number;
160
+ }
161
+
113
162
  export default function StatusCard({
114
163
  title,
115
164
  subtitle,
@@ -124,7 +173,7 @@ export default function StatusCard({
124
173
  emptyMessage = "No status items.",
125
174
  maxBodyHeight,
126
175
  ...cardProps
127
- }) {
176
+ }: StatusCardProps) {
128
177
  const overall = normalizeStatus(status);
129
178
  const header = (
130
179
  <div className="flex items-start justify-between gap-3">
@@ -166,7 +215,9 @@ export default function StatusCard({
166
215
  const okCount = items.filter((it) => normalizeStatus(it?.status) === "operational").length;
167
216
  const percentOk = total > 0 ? Math.round((okCount / total) * 100) : 100;
168
217
 
169
- const scrollStyle = maxBodyHeight ? { maxHeight: maxBodyHeight, overflowY: "auto" } : {};
218
+ const scrollStyle: React.CSSProperties = maxBodyHeight
219
+ ? { maxHeight: typeof maxBodyHeight === "number" ? `${maxBodyHeight}px` : maxBodyHeight, overflowY: "auto" }
220
+ : {};
170
221
 
171
222
  const itemsContent = loading ? (
172
223
  <div className="space-y-3">
@@ -216,5 +267,3 @@ export default function StatusCard({
216
267
 
217
268
  return <BaseCard variant="status" header={header} body={body} {...cardProps} />;
218
269
  }
219
-
220
-
@@ -1,10 +1,12 @@
1
1
  import React from "react";
2
- import BaseCard from "./BaseCard";
2
+ import BaseCard, { BaseCardProps } from "./BaseCard";
3
3
  import UIInput from "../ui/UIInput";
4
4
  import UIButton from "../ui/UIButton";
5
5
  import UIText from "../ui/Text";
6
6
 
7
- function defaultTypeFormat(type, value) {
7
+ type ColumnType = "currency" | "percentage" | "number" | "text";
8
+
9
+ function defaultTypeFormat(type: ColumnType | undefined, value: unknown): string {
8
10
  if (value == null) return "";
9
11
  if (!type) return String(value);
10
12
 
@@ -23,7 +25,7 @@ function defaultTypeFormat(type, value) {
23
25
  return String(value);
24
26
  }
25
27
 
26
- function stableSort(data, compare) {
28
+ function stableSort<T>(data: T[], compare: (a: T, b: T) => number): T[] {
27
29
  return data
28
30
  .map((item, idx) => ({ item, idx }))
29
31
  .sort((a, b) => {
@@ -33,6 +35,44 @@ function stableSort(data, compare) {
33
35
  .map((x) => x.item);
34
36
  }
35
37
 
38
+ export interface TableColumn {
39
+ key: string;
40
+ label: string;
41
+ type?: ColumnType;
42
+ sortable?: boolean;
43
+ mono?: boolean;
44
+ className?: string;
45
+ render?: (value: unknown, row: Record<string, unknown>) => React.ReactNode;
46
+ }
47
+
48
+ export interface SortState {
49
+ key: string;
50
+ direction: "asc" | "desc";
51
+ }
52
+
53
+ export interface TableCardProps extends Omit<BaseCardProps, "variant" | "header" | "body"> {
54
+ data?: Record<string, unknown>[];
55
+ columns?: TableColumn[];
56
+ title?: string;
57
+ subtitle?: string;
58
+ searchable?: boolean;
59
+ sortable?: boolean;
60
+ paginated?: boolean;
61
+ selectable?: boolean;
62
+ pageSize?: number;
63
+ actions?: React.ReactNode;
64
+ rowActions?: (row: Record<string, unknown>) => React.ReactNode;
65
+ onRowSelect?: (row: Record<string, unknown>) => void;
66
+ onSort?: (sort: SortState) => void;
67
+ onSearch?: (query: string) => void;
68
+ loading?: boolean;
69
+ error?: string | Error;
70
+ emptyMessage?: string;
71
+ simulateInitialLoad?: boolean;
72
+ minInitialDelayMs?: number;
73
+ maxInitialDelayMs?: number;
74
+ }
75
+
36
76
  export default function TableCard({
37
77
  data = [],
38
78
  columns = [],
@@ -55,12 +95,12 @@ export default function TableCard({
55
95
  minInitialDelayMs = 350,
56
96
  maxInitialDelayMs = 900,
57
97
  ...cardProps
58
- }) {
98
+ }: TableCardProps) {
59
99
  const [query, setQuery] = React.useState("");
60
- const [sortKey, setSortKey] = React.useState(null);
61
- const [sortDir, setSortDir] = React.useState("asc");
100
+ const [sortKey, setSortKey] = React.useState<string | null>(null);
101
+ const [sortDir, setSortDir] = React.useState<"asc" | "desc">("asc");
62
102
  const [page, setPage] = React.useState(1);
63
- const [selectedId, setSelectedId] = React.useState(null);
103
+ const [selectedId, setSelectedId] = React.useState<string | number | undefined>(undefined);
64
104
  const [simLoading, setSimLoading] = React.useState(simulateInitialLoad);
65
105
 
66
106
  React.useEffect(() => {
@@ -163,7 +203,7 @@ export default function TableCard({
163
203
  );
164
204
  }
165
205
 
166
- const canSort = (col) => sortable && (col.sortable ?? true);
206
+ const canSort = (col: TableColumn) => sortable && (col.sortable ?? true);
167
207
 
168
208
  return (
169
209
  <BaseCard
@@ -248,11 +288,12 @@ export default function TableCard({
248
288
  </tr>
249
289
  ) : (
250
290
  pageData.map((row, idx) => {
251
- const rowId = row?.id ?? idx;
291
+ const rawId = row?.id;
292
+ const rowId: string | number = typeof rawId === "string" || typeof rawId === "number" ? rawId : idx;
252
293
  const selected = selectable && selectedId === rowId;
253
294
  return (
254
295
  <tr
255
- key={rowId}
296
+ key={String(rowId)}
256
297
  className={[
257
298
  "group",
258
299
  selectable ? "cursor-pointer" : "",
@@ -333,5 +374,3 @@ export default function TableCard({
333
374
  />
334
375
  );
335
376
  }
336
-
337
-
@@ -1,8 +1,22 @@
1
1
  import React from "react";
2
- import BaseCard from "./BaseCard";
2
+ import BaseCard, { BaseCardProps } from "./BaseCard";
3
3
  import UIText from "../ui/Text";
4
4
 
5
- function Section({ title, actions, content, divided }) {
5
+ export interface WidgetSection {
6
+ id?: string | number;
7
+ title?: string;
8
+ actions?: React.ReactNode;
9
+ content: React.ReactNode;
10
+ }
11
+
12
+ interface SectionProps {
13
+ title?: string;
14
+ actions?: React.ReactNode;
15
+ content: React.ReactNode;
16
+ divided: boolean;
17
+ }
18
+
19
+ function Section({ title, actions, content, divided }: SectionProps) {
6
20
  return (
7
21
  <div className={divided ? "border-t border-slate-200 pt-4 dark:border-slate-800" : ""}>
8
22
  {(title || actions) ? (
@@ -22,6 +36,17 @@ function Section({ title, actions, content, divided }) {
22
36
  );
23
37
  }
24
38
 
39
+ export interface WidgetCardProps extends Omit<BaseCardProps, "variant" | "header" | "body"> {
40
+ header: React.ReactNode;
41
+ sections?: WidgetSection[];
42
+ footer?: React.ReactNode;
43
+ divided?: boolean;
44
+ collapsible?: boolean;
45
+ defaultExpanded?: boolean;
46
+ loading?: boolean;
47
+ emptyMessage?: string;
48
+ }
49
+
25
50
  export default function WidgetCard({
26
51
  header,
27
52
  sections = [],
@@ -32,7 +57,7 @@ export default function WidgetCard({
32
57
  loading = false,
33
58
  emptyMessage = "No sections.",
34
59
  ...cardProps
35
- }) {
60
+ }: WidgetCardProps) {
36
61
  const [expanded, setExpanded] = React.useState(defaultExpanded);
37
62
 
38
63
  const hdr = (
@@ -86,5 +111,3 @@ export default function WidgetCard({
86
111
 
87
112
  return <BaseCard variant="widget" header={hdr} body={body} {...cardProps} />;
88
113
  }
89
-
90
-