streamlit-react-components 1.0.0__py3-none-any.whl

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.
@@ -0,0 +1,23 @@
1
+ """Common display components."""
2
+
3
+ from .panel import panel
4
+ from .section_header import section_header
5
+ from .stat_card import stat_card
6
+ from .metric_row import metric_row
7
+ from .data_table import data_table
8
+ from .step_indicator import step_indicator
9
+ from .button_group import button_group
10
+ from .chart_legend import chart_legend
11
+ from .plotly_chart import plotly_chart
12
+
13
+ __all__ = [
14
+ "panel",
15
+ "section_header",
16
+ "stat_card",
17
+ "metric_row",
18
+ "data_table",
19
+ "step_indicator",
20
+ "button_group",
21
+ "chart_legend",
22
+ "plotly_chart",
23
+ ]
@@ -0,0 +1,69 @@
1
+ """ButtonGroup component - A group of action buttons."""
2
+
3
+ import streamlit.components.v1 as components
4
+ from pathlib import Path
5
+ from typing import Dict, Any, List, Optional
6
+
7
+ _FRONTEND_DIR = Path(__file__).parent.parent / "_frontend"
8
+
9
+ _component = components.declare_component(
10
+ "streamlit_react_components",
11
+ path=str(_FRONTEND_DIR),
12
+ )
13
+
14
+
15
+ def button_group(
16
+ buttons: List[Dict[str, Any]],
17
+ style: Optional[Dict[str, Any]] = None,
18
+ class_name: str = "",
19
+ key: Optional[str] = None,
20
+ ) -> Optional[str]:
21
+ """
22
+ Display a group of action buttons.
23
+
24
+ Args:
25
+ buttons: List of button configs, each with:
26
+ - id: Unique identifier
27
+ - label: Button text (optional)
28
+ - icon: Button icon/emoji (optional)
29
+ - color: Preset name ("blue", "green", "red", "yellow", "purple",
30
+ "slate") or hex value like "#94a3b8" (optional)
31
+ - disabled: Whether button is disabled (optional)
32
+ - style: Inline CSS styles dict for this button (optional)
33
+ - className: Tailwind CSS classes for this button (optional)
34
+ style: Inline CSS styles as a dictionary
35
+ class_name: Tailwind CSS classes
36
+ key: Unique key for the component
37
+
38
+ Returns:
39
+ The ID of the clicked button, or None if no click
40
+
41
+ Example:
42
+ # Using preset colors
43
+ clicked = button_group(
44
+ buttons=[
45
+ {"id": "view", "icon": "👁️"},
46
+ {"id": "edit", "icon": "✏️"},
47
+ {"id": "approve", "icon": "✓", "color": "green"},
48
+ {"id": "reject", "icon": "✕", "color": "red"}
49
+ ]
50
+ )
51
+
52
+ # Using hex colors and custom styling
53
+ clicked = button_group(
54
+ buttons=[
55
+ {"id": "custom", "icon": "🎨", "color": "#ff5733"},
56
+ {"id": "styled", "label": "Styled", "style": {"padding": "12px"}}
57
+ ]
58
+ )
59
+ if clicked == "approve":
60
+ approve_item()
61
+ """
62
+ return _component(
63
+ component="button_group",
64
+ buttons=buttons,
65
+ style=style,
66
+ className=class_name,
67
+ key=key,
68
+ default=None,
69
+ )
@@ -0,0 +1,49 @@
1
+ """ChartLegend component - A chart legend with colored indicators."""
2
+
3
+ import streamlit.components.v1 as components
4
+ from pathlib import Path
5
+ from typing import Dict, Any, List, Optional
6
+
7
+ _FRONTEND_DIR = Path(__file__).parent.parent / "_frontend"
8
+
9
+ _component = components.declare_component(
10
+ "streamlit_react_components",
11
+ path=str(_FRONTEND_DIR),
12
+ )
13
+
14
+
15
+ def chart_legend(
16
+ items: List[Dict[str, str]],
17
+ style: Optional[Dict[str, Any]] = None,
18
+ class_name: str = "",
19
+ key: Optional[str] = None,
20
+ ) -> None:
21
+ """
22
+ Display a chart legend with colored indicators.
23
+
24
+ Args:
25
+ items: List of legend items, each with:
26
+ - color: CSS color value (e.g., "#3b82f6", "rgb(59,130,246)")
27
+ - label: Legend label text
28
+ style: Inline CSS styles as a dictionary
29
+ class_name: Tailwind CSS classes
30
+ key: Unique key for the component
31
+
32
+ Example:
33
+ chart_legend(
34
+ items=[
35
+ {"color": "#94a3b8", "label": "Historical"},
36
+ {"color": "#ef4444", "label": "Outlier"},
37
+ {"color": "#8b5cf6", "label": "Prophet"},
38
+ {"color": "#10b981", "label": "ARIMA"}
39
+ ]
40
+ )
41
+ """
42
+ _component(
43
+ component="chart_legend",
44
+ items=items,
45
+ style=style,
46
+ className=class_name,
47
+ key=key,
48
+ default=None,
49
+ )
@@ -0,0 +1,65 @@
1
+ """DataTable component - A styled data table with click support."""
2
+
3
+ import streamlit.components.v1 as components
4
+ from pathlib import Path
5
+ from typing import Dict, Any, List, Optional
6
+
7
+ _FRONTEND_DIR = Path(__file__).parent.parent / "_frontend"
8
+
9
+ _component = components.declare_component(
10
+ "streamlit_react_components",
11
+ path=str(_FRONTEND_DIR),
12
+ )
13
+
14
+
15
+ def data_table(
16
+ columns: List[Dict[str, Any]],
17
+ rows: List[Dict[str, Any]],
18
+ show_header: bool = True,
19
+ style: Optional[Dict[str, Any]] = None,
20
+ class_name: str = "",
21
+ key: Optional[str] = None,
22
+ ) -> Optional[Dict[str, Any]]:
23
+ """
24
+ Display a styled data table with row click support.
25
+
26
+ Args:
27
+ columns: List of column definitions, each with:
28
+ - key: Data key in each row
29
+ - label: Column header text
30
+ - align: "left", "center", or "right" (optional)
31
+ - format: "number" or "percent" (optional)
32
+ - colorByValue: True to color based on status values (optional)
33
+ rows: List of row data dictionaries
34
+ show_header: Whether to show the header row (default True)
35
+ style: Inline CSS styles as a dictionary
36
+ class_name: Tailwind CSS classes
37
+ key: Unique key for the component
38
+
39
+ Returns:
40
+ Dictionary with rowIndex and rowData when a row is clicked, None otherwise
41
+
42
+ Example:
43
+ columns = [
44
+ {"key": "site", "label": "Site"},
45
+ {"key": "util", "label": "Utilization", "align": "right", "format": "percent"},
46
+ {"key": "status", "label": "Status", "colorByValue": True}
47
+ ]
48
+ rows = [
49
+ {"site": "AML_14", "util": 94, "status": "above"},
50
+ {"site": "ADL", "util": 72, "status": "within"}
51
+ ]
52
+ clicked = data_table(columns=columns, rows=rows)
53
+ if clicked:
54
+ st.write(f"Clicked row: {clicked['rowData']}")
55
+ """
56
+ return _component(
57
+ component="data_table",
58
+ columns=columns,
59
+ rows=rows,
60
+ showHeader=show_header,
61
+ style=style,
62
+ className=class_name,
63
+ key=key,
64
+ default=None,
65
+ )
@@ -0,0 +1,47 @@
1
+ """MetricRow component - A key-value display row."""
2
+
3
+ import streamlit.components.v1 as components
4
+ from pathlib import Path
5
+ from typing import Dict, Any, Optional
6
+
7
+ _FRONTEND_DIR = Path(__file__).parent.parent / "_frontend"
8
+
9
+ _component = components.declare_component(
10
+ "streamlit_react_components",
11
+ path=str(_FRONTEND_DIR),
12
+ )
13
+
14
+
15
+ def metric_row(
16
+ label: str,
17
+ value: str,
18
+ value_color: str = "",
19
+ style: Optional[Dict[str, Any]] = None,
20
+ class_name: str = "",
21
+ key: Optional[str] = None,
22
+ ) -> None:
23
+ """
24
+ Display a key-value metric row.
25
+
26
+ Args:
27
+ label: The metric label (left side)
28
+ value: The metric value (right side)
29
+ value_color: Tailwind text color class for the value (e.g., "text-green-400")
30
+ style: Inline CSS styles as a dictionary
31
+ class_name: Tailwind CSS classes
32
+ key: Unique key for the component
33
+
34
+ Example:
35
+ metric_row(label="Mean", value="78.4%")
36
+ metric_row(label="Trend", value="↑ +0.4%/mo", value_color="text-green-400")
37
+ """
38
+ _component(
39
+ component="metric_row",
40
+ label=label,
41
+ value=value,
42
+ valueColor=value_color,
43
+ style=style,
44
+ className=class_name,
45
+ key=key,
46
+ default=None,
47
+ )
@@ -0,0 +1,43 @@
1
+ """Panel component - A styled container wrapper."""
2
+
3
+ import streamlit.components.v1 as components
4
+ from pathlib import Path
5
+ from typing import Dict, Any, Optional
6
+
7
+ _FRONTEND_DIR = Path(__file__).parent.parent / "_frontend"
8
+
9
+ _component = components.declare_component(
10
+ "streamlit_react_components",
11
+ path=str(_FRONTEND_DIR),
12
+ )
13
+
14
+
15
+ def panel(
16
+ children: str = "",
17
+ style: Optional[Dict[str, Any]] = None,
18
+ class_name: str = "",
19
+ key: Optional[str] = None,
20
+ ) -> None:
21
+ """
22
+ Display a styled panel/card container.
23
+
24
+ Args:
25
+ children: HTML content to render inside the panel
26
+ style: Inline CSS styles as a dictionary (e.g., {"background": "#1e293b"})
27
+ class_name: Tailwind CSS classes (e.g., "bg-slate-900 p-4")
28
+ key: Unique key for the component
29
+
30
+ Example:
31
+ panel(
32
+ children="<h3>Title</h3><p>Content here</p>",
33
+ class_name="mt-4"
34
+ )
35
+ """
36
+ _component(
37
+ component="panel",
38
+ children=children,
39
+ style=style,
40
+ className=class_name,
41
+ key=key,
42
+ default=None,
43
+ )
@@ -0,0 +1,216 @@
1
+ """PlotlyChart component - Render Plotly charts with full interactivity."""
2
+
3
+ import streamlit.components.v1 as components
4
+ from pathlib import Path
5
+ from typing import Dict, Any, Optional, List, Union
6
+
7
+ _FRONTEND_DIR = Path(__file__).parent.parent / "_frontend"
8
+
9
+ _component = components.declare_component(
10
+ "streamlit_react_components",
11
+ path=str(_FRONTEND_DIR),
12
+ )
13
+
14
+
15
+ def _dataframe_to_figure(
16
+ data: Any,
17
+ x: Optional[str],
18
+ y: Optional[Union[str, List[str]]],
19
+ color: Optional[str],
20
+ chart_type: str,
21
+ title: Optional[str],
22
+ ) -> Dict[str, Any]:
23
+ """Convert a DataFrame to a Plotly figure dict."""
24
+ traces = []
25
+ layout: Dict[str, Any] = {}
26
+
27
+ if title:
28
+ layout["title"] = title
29
+
30
+ # Determine y columns
31
+ y_cols = [y] if isinstance(y, str) else (y or [])
32
+
33
+ # Color grouping
34
+ if color and color in data.columns:
35
+ groups = data[color].unique()
36
+ for group in groups:
37
+ group_data = data[data[color] == group]
38
+ for y_col in y_cols:
39
+ trace = _create_trace(
40
+ chart_type,
41
+ group_data[x].tolist() if x else list(range(len(group_data))),
42
+ group_data[y_col].tolist(),
43
+ f"{group}" if len(y_cols) == 1 else f"{group} - {y_col}",
44
+ )
45
+ traces.append(trace)
46
+ else:
47
+ # No color grouping
48
+ x_data = data[x].tolist() if x else list(range(len(data)))
49
+ for y_col in y_cols:
50
+ trace = _create_trace(
51
+ chart_type,
52
+ x_data,
53
+ data[y_col].tolist(),
54
+ y_col if len(y_cols) > 1 else None,
55
+ )
56
+ traces.append(trace)
57
+
58
+ return {"data": traces, "layout": layout}
59
+
60
+
61
+ def _create_trace(
62
+ chart_type: str,
63
+ x_data: List[Any],
64
+ y_data: List[Any],
65
+ name: Optional[str],
66
+ ) -> Dict[str, Any]:
67
+ """Create a single Plotly trace based on chart type."""
68
+ base: Dict[str, Any] = {"x": x_data, "y": y_data}
69
+ if name:
70
+ base["name"] = name
71
+
72
+ if chart_type == "line":
73
+ return {"type": "scatter", "mode": "lines", **base}
74
+ elif chart_type == "scatter":
75
+ return {"type": "scatter", "mode": "markers", **base}
76
+ elif chart_type == "bar":
77
+ return {"type": "bar", **base}
78
+ elif chart_type == "area":
79
+ return {"type": "scatter", "mode": "lines", "fill": "tozeroy", **base}
80
+ elif chart_type == "histogram":
81
+ return {"type": "histogram", "x": x_data}
82
+ elif chart_type == "pie":
83
+ return {"type": "pie", "labels": x_data, "values": y_data}
84
+ else:
85
+ # Default to scatter with lines
86
+ return {"type": "scatter", "mode": "lines", **base}
87
+
88
+
89
+ def plotly_chart(
90
+ figure: Optional[Any] = None,
91
+ data: Optional[Any] = None,
92
+ x: Optional[str] = None,
93
+ y: Optional[Union[str, List[str]]] = None,
94
+ color: Optional[str] = None,
95
+ chart_type: str = "line",
96
+ title: Optional[str] = None,
97
+ config: Optional[Dict[str, Any]] = None,
98
+ on_click: bool = False,
99
+ on_select: bool = False,
100
+ on_hover: bool = False,
101
+ on_relayout: bool = False,
102
+ style: Optional[Dict[str, Any]] = None,
103
+ class_name: str = "",
104
+ key: Optional[str] = None,
105
+ ) -> Optional[Dict[str, Any]]:
106
+ """
107
+ Render a Plotly chart with full interactivity and custom styling.
108
+
109
+ Supports two modes:
110
+ 1. Pass a Plotly figure object directly
111
+ 2. Pass a pandas DataFrame with chart configuration
112
+
113
+ Args:
114
+ figure: Plotly figure object (go.Figure) or dict with 'data' and 'layout'.
115
+ Takes precedence over `data` parameter.
116
+ data: pandas DataFrame for quick chart creation
117
+ x: Column name for x-axis (when using DataFrame)
118
+ y: Column name(s) for y-axis - string or list of strings (when using DataFrame)
119
+ color: Column name for color grouping (when using DataFrame)
120
+ chart_type: Chart type when using DataFrame - "line", "bar", "scatter",
121
+ "area", "pie", or "histogram" (default "line")
122
+ title: Chart title (when using DataFrame)
123
+ config: Plotly config options (displayModeBar, scrollZoom, etc.)
124
+ on_click: Enable click events (returns clicked points)
125
+ on_select: Enable selection events (box/lasso selection)
126
+ on_hover: Enable hover events (returns hovered points)
127
+ on_relayout: Enable relayout events (zoom/pan state)
128
+ style: Inline CSS styles as a dictionary
129
+ class_name: Tailwind CSS classes
130
+ key: Unique key for the component
131
+
132
+ Returns:
133
+ Event dict with 'type' and event data, or None if no event.
134
+ Event types: 'click', 'select', 'hover', 'relayout'
135
+
136
+ Example using Plotly figure:
137
+ import plotly.graph_objects as go
138
+
139
+ fig = go.Figure(
140
+ data=[go.Scatter(x=[1,2,3], y=[4,5,6], mode='lines+markers')],
141
+ layout=go.Layout(title='My Chart')
142
+ )
143
+
144
+ event = plotly_chart(
145
+ figure=fig,
146
+ on_click=True,
147
+ on_select=True,
148
+ style={"height": "400px"}
149
+ )
150
+
151
+ if event and event['type'] == 'click':
152
+ st.write(f"Clicked: {event['points']}")
153
+
154
+ Example using DataFrame:
155
+ import pandas as pd
156
+
157
+ df = pd.DataFrame({
158
+ 'month': ['Jan', 'Feb', 'Mar', 'Apr'],
159
+ 'sales': [100, 150, 120, 180],
160
+ 'orders': [50, 75, 60, 90]
161
+ })
162
+
163
+ # Simple line chart
164
+ event = plotly_chart(
165
+ data=df,
166
+ x='month',
167
+ y='sales',
168
+ chart_type='line',
169
+ title='Monthly Sales',
170
+ on_click=True
171
+ )
172
+
173
+ # Multiple y columns as bar chart
174
+ event = plotly_chart(
175
+ data=df,
176
+ x='month',
177
+ y=['sales', 'orders'],
178
+ chart_type='bar',
179
+ title='Sales vs Orders'
180
+ )
181
+
182
+ # Scatter with color grouping
183
+ event = plotly_chart(
184
+ data=df,
185
+ x='sales',
186
+ y='orders',
187
+ color='month',
188
+ chart_type='scatter'
189
+ )
190
+ """
191
+ # Determine figure dict
192
+ if figure is not None:
193
+ # Convert Plotly figure to dict if needed
194
+ if hasattr(figure, "to_dict"):
195
+ figure_dict = figure.to_dict()
196
+ else:
197
+ figure_dict = figure
198
+ elif data is not None:
199
+ # Create figure from DataFrame
200
+ figure_dict = _dataframe_to_figure(data, x, y, color, chart_type, title)
201
+ else:
202
+ raise ValueError("Either 'figure' or 'data' parameter is required")
203
+
204
+ return _component(
205
+ component="plotly_chart",
206
+ figure=figure_dict,
207
+ config=config,
208
+ onClickEnabled=on_click,
209
+ onSelectEnabled=on_select,
210
+ onHoverEnabled=on_hover,
211
+ onRelayoutEnabled=on_relayout,
212
+ style=style,
213
+ className=class_name,
214
+ key=key,
215
+ default=None,
216
+ )
@@ -0,0 +1,89 @@
1
+ """SectionHeader component - A styled section title with optional actions."""
2
+
3
+ import streamlit.components.v1 as components
4
+ from pathlib import Path
5
+ from typing import Dict, Any, List, Optional
6
+
7
+ _FRONTEND_DIR = Path(__file__).parent.parent / "_frontend"
8
+
9
+ _component = components.declare_component(
10
+ "streamlit_react_components",
11
+ path=str(_FRONTEND_DIR),
12
+ )
13
+
14
+
15
+ def section_header(
16
+ title: str,
17
+ icon: str = "",
18
+ actions: Optional[List[Dict[str, Any]]] = None,
19
+ style: Optional[Dict[str, Any]] = None,
20
+ class_name: str = "",
21
+ key: Optional[str] = None,
22
+ ) -> Optional[str]:
23
+ """
24
+ Display a section header with optional action buttons.
25
+
26
+ Args:
27
+ title: The header title text
28
+ icon: Optional emoji or icon to display before the title
29
+ actions: List of action button configs, each with:
30
+ - id: Unique identifier for the action
31
+ - label: Button text (optional)
32
+ - icon: Button icon (optional)
33
+ - color: Preset name ("blue", "green", "red", "yellow", "purple",
34
+ "slate") or hex value like "#94a3b8" (optional)
35
+ - style: Inline CSS styles dict for this button (optional)
36
+ - className: Tailwind CSS classes for this button (optional)
37
+ - href: URL for link actions. External URLs (http/https) open
38
+ in a new tab. Internal paths return the ID for use with
39
+ st.switch_page() (optional)
40
+ style: Inline CSS styles as a dictionary
41
+ class_name: Tailwind CSS classes
42
+ key: Unique key for the component
43
+
44
+ Returns:
45
+ The ID of the clicked action button, or None if no click
46
+
47
+ Example:
48
+ # Using preset colors
49
+ clicked = section_header(
50
+ title="Dashboard",
51
+ icon="📊",
52
+ actions=[{"id": "refresh", "label": "Refresh", "color": "blue"}]
53
+ )
54
+
55
+ # Using hex colors and custom styling
56
+ clicked = section_header(
57
+ title="Dashboard",
58
+ actions=[
59
+ {"id": "custom", "label": "Custom", "color": "#94a3b8"},
60
+ {"id": "styled", "label": "Styled", "style": {"padding": "12px"}}
61
+ ]
62
+ )
63
+
64
+ # External link (opens in new tab)
65
+ clicked = section_header(
66
+ title="Resources",
67
+ actions=[
68
+ {"id": "docs", "label": "Documentation", "href": "https://docs.example.com", "icon": "📚"}
69
+ ]
70
+ )
71
+
72
+ # Internal navigation
73
+ clicked = section_header(
74
+ title="Settings",
75
+ actions=[{"id": "home", "label": "Home", "icon": "🏠"}]
76
+ )
77
+ if clicked == "home":
78
+ st.switch_page("pages/home.py")
79
+ """
80
+ return _component(
81
+ component="section_header",
82
+ title=title,
83
+ icon=icon,
84
+ actions=actions or [],
85
+ style=style,
86
+ className=class_name,
87
+ key=key,
88
+ default=None,
89
+ )
@@ -0,0 +1,63 @@
1
+ """StatCard component - A styled statistics display card."""
2
+
3
+ import streamlit.components.v1 as components
4
+ from pathlib import Path
5
+ from typing import Dict, Any, Optional, Union
6
+
7
+ _FRONTEND_DIR = Path(__file__).parent.parent / "_frontend"
8
+
9
+ _component = components.declare_component(
10
+ "streamlit_react_components",
11
+ path=str(_FRONTEND_DIR),
12
+ )
13
+
14
+
15
+ def stat_card(
16
+ label: str,
17
+ value: Union[str, int, float],
18
+ color: str = "blue",
19
+ icon: str = "",
20
+ style: Optional[Dict[str, Any]] = None,
21
+ class_name: str = "",
22
+ key: Optional[str] = None,
23
+ ) -> None:
24
+ """
25
+ Display a styled statistics card with a label and value.
26
+
27
+ Args:
28
+ label: The description label (e.g., "Total Users")
29
+ value: The statistic value to display
30
+ color: Accent color - preset name ("blue", "green", "red", "yellow",
31
+ "purple", "slate") or hex value (e.g., "#94a3b8")
32
+ icon: Optional emoji or icon to display with the label
33
+ style: Inline CSS styles as a dictionary
34
+ class_name: Tailwind CSS classes
35
+ key: Unique key for the component
36
+
37
+ Example:
38
+ # Using preset color
39
+ stat_card(
40
+ label="Within Threshold",
41
+ value="4",
42
+ color="green",
43
+ style={"minWidth": "150px"}
44
+ )
45
+
46
+ # Using hex color
47
+ stat_card(
48
+ label="Custom Color",
49
+ value="42",
50
+ color="#ff5733"
51
+ )
52
+ """
53
+ _component(
54
+ component="stat_card",
55
+ label=label,
56
+ value=str(value),
57
+ color=color,
58
+ icon=icon,
59
+ style=style,
60
+ className=class_name,
61
+ key=key,
62
+ default=None,
63
+ )