dashui
DashUI — shared ipywidgets component library for the Dashlibs suite. Import from here in any dash-* package instead of duplicating widget code.
1""" 2DashUI — shared ipywidgets component library for the Dashlibs suite. 3Import from here in any dash-* package instead of duplicating widget code. 4""" 5from dashui.components import ( 6 SourceSelector, 7 action_button, 8 card, 9 header, 10 html, 11 output_panel, 12 running_list, 13 section, 14 source_selector, 15 status_line, 16) 17from dashui.schema import list_columns, list_columns_safe 18from dashui.theme import ( 19 BORDER, 20 CARD, 21 DANGER, 22 FONT_MONO, 23 FONT_SANS, 24 MUTED, 25 PRIMARY, 26 SUCCESS, 27 WARNING, 28 accent, 29) 30 31__version__ = "0.1.3" 32__all__ = [ 33 "SourceSelector", 34 "action_button", 35 "card", 36 "header", 37 "html", 38 "output_panel", 39 "running_list", 40 "section", 41 "source_selector", 42 "status_line", 43 "list_columns", 44 "list_columns_safe", 45 "accent", 46 "PRIMARY", 47 "SUCCESS", 48 "DANGER", 49 "WARNING", 50 "BORDER", 51 "CARD", 52 "MUTED", 53 "FONT_SANS", 54 "FONT_MONO", 55]
132@dataclass 133class SourceSelector: 134 """ 135 The UC Table / DataFrame variable / SQL Query picker used by every 136 Dashlibs UI that reads from Databricks. 137 138 Usage:: 139 src = source_selector() 140 ui = card([src.toggle, src.box, ...]) 141 kind, value = src.value() 142 """ 143 toggle: object 144 box: object 145 table_input: object 146 df_input: object 147 sql_input: object 148 149 def value(self) -> tuple[str, str]: 150 """Returns (kind, value) where kind is 'table' | 'dataframe' | 'sql'.""" 151 if self.toggle.value == "UC Table": 152 return "table", self.table_input.value.strip() 153 if self.toggle.value == "DataFrame variable": 154 return "dataframe", self.df_input.value.strip() 155 return "sql", self.sql_input.value.strip() 156 157 def resolve_df(self): 158 """Resolve the selected source to a Spark DataFrame (for direct use in core classes).""" 159 kind, value = self.value() 160 if kind == "dataframe": 161 import IPython 162 shell = IPython.get_ipython() 163 df = shell.user_ns.get(value) if shell else None 164 if df is None: 165 raise ValueError(f"Variable '{value}' not found") 166 return df 167 from pyspark.sql import SparkSession 168 spark = SparkSession.getActiveSession() 169 if kind == "table": 170 return spark.table(value) 171 return spark.sql(value)
The UC Table / DataFrame variable / SQL Query picker used by every Dashlibs UI that reads from Databricks.
Usage:: src = source_selector() ui = card([src.toggle, src.box, ...]) kind, value = src.value()
149 def value(self) -> tuple[str, str]: 150 """Returns (kind, value) where kind is 'table' | 'dataframe' | 'sql'.""" 151 if self.toggle.value == "UC Table": 152 return "table", self.table_input.value.strip() 153 if self.toggle.value == "DataFrame variable": 154 return "dataframe", self.df_input.value.strip() 155 return "sql", self.sql_input.value.strip()
Returns (kind, value) where kind is 'table' | 'dataframe' | 'sql'.
157 def resolve_df(self): 158 """Resolve the selected source to a Spark DataFrame (for direct use in core classes).""" 159 kind, value = self.value() 160 if kind == "dataframe": 161 import IPython 162 shell = IPython.get_ipython() 163 df = shell.user_ns.get(value) if shell else None 164 if df is None: 165 raise ValueError(f"Variable '{value}' not found") 166 return df 167 from pyspark.sql import SparkSession 168 spark = SparkSession.getActiveSession() 169 if kind == "table": 170 return spark.table(value) 171 return spark.sql(value)
Resolve the selected source to a Spark DataFrame (for direct use in core classes).
120def card(children, padding: str = "20px"): 121 """Bordered, shadowed VBox container — the outer shell for every launch() UI.""" 122 w = _require_widgets() 123 global _STYLE_INJECTED 124 body = [_global_style(), *children] if not _STYLE_INJECTED else list(children) 125 _STYLE_INJECTED = True 126 box = w.VBox(body, layout=w.Layout(padding=padding)) 127 box.add_class("dashui-card") 128 box.add_class("dashui-root") 129 return box
Bordered, shadowed VBox container — the outer shell for every launch() UI.
95def header(title: str, library: str = "default", emoji: str = "", subtitle: str = ""): 96 """Top banner used at the start of every launch() UI.""" 97 color = accent(library) 98 sub = ( 99 f"<div style='font-size:12px;color:{MUTED_FOREGROUND};margin-top:2px;" 100 f"font-family:{FONT_SANS}'>{subtitle}</div>" 101 ) if subtitle else "" 102 return html( 103 f"<h2 style='color:{color};margin-bottom:0;font-weight:700;" 104 f"letter-spacing:-0.01em;font-family:{FONT_SANS}'>{emoji} {title}</h2>{sub}" 105 )
Top banner used at the start of every launch() UI.
203def output_panel(): 204 """Standard scrollable output area for run/profile results and errors.""" 205 w = _require_widgets() 206 out = w.Output(layout=w.Layout(padding="12px")) 207 out.add_class("dashui-output") 208 return out
Standard scrollable output area for run/profile results and errors.
211def running_list(formatter): 212 """ 213 A live-updating numbered list display, the pattern used for 'added entities' 214 / 'added relationships' style accumulators. 215 216 Usage:: 217 items = [] 218 out, render = running_list(lambda i, item: f"{i}. {item['name']}") 219 items.append({"name": "Customer"}) 220 render(items) 221 """ 222 w = _require_widgets() 223 out = w.Output(layout=w.Layout(padding="8px 12px")) 224 out.add_class("dashui-output") 225 226 def render(items: list): 227 with out: 228 out.clear_output() 229 for i, item in enumerate(items, 1): 230 print(formatter(i, item)) 231 232 return out, render
A live-updating numbered list display, the pattern used for 'added entities' / 'added relationships' style accumulators.
Usage:: items = [] out, render = running_list(lambda i, item: f"{i}. {item['name']}") items.append({"name": "Customer"}) render(items)
108def section(title: str): 109 """Step/section divider, styled like the datapal-access card label convention.""" 110 return html(f"<div class='dashui-section'>{title}</div>")
Step/section divider, styled like the datapal-access card label convention.
174def source_selector(label: str = "Source:") -> SourceSelector: 175 w = _require_widgets() 176 toggle = w.ToggleButtons(options=["UC Table", "DataFrame variable", "SQL Query"], description=label) 177 table_input = w.Text(placeholder="catalog.schema.table", description="Table:") 178 df_input = w.Text(placeholder="df", description="Variable:") 179 sql_input = w.Textarea(placeholder="SELECT * FROM ...", description="SQL:", rows=3) 180 box = w.VBox([table_input]) 181 182 def on_change(change): 183 if change["new"] == "UC Table": 184 box.children = [table_input] 185 elif change["new"] == "DataFrame variable": 186 box.children = [df_input] 187 else: 188 box.children = [sql_input] 189 190 toggle.observe(on_change, names="value") 191 return SourceSelector(toggle, box, table_input, df_input, sql_input)
113def status_line(text: str, kind: str = "info"): 114 """One-line colored status message: kind in success|error|warning|info.""" 115 color = {"success": SUCCESS, "error": DANGER, "warning": WARNING, "info": MUTED_FOREGROUND}.get(kind, MUTED_FOREGROUND) 116 prefix = {"success": "✅", "error": "❌", "warning": "⚠️", "info": "ℹ️"}.get(kind, "") 117 return html(f"<span style='color:{color};font-family:{FONT_SANS}'>{prefix} {text}</span>")
One-line colored status message: kind in success|error|warning|info.
6def list_columns(table: str) -> list[str]: 7 """Return column names for a UC table, without loading any data.""" 8 from pyspark.sql import SparkSession 9 spark = SparkSession.getActiveSession() 10 return [f.name for f in spark.table(table).schema.fields]
Return column names for a UC table, without loading any data.
13def list_columns_safe(table: str) -> list[str]: 14 """Like list_columns, but returns [] instead of raising — for UI dropdowns.""" 15 try: 16 return list_columns(table) 17 except Exception: 18 return []
Like list_columns, but returns [] instead of raising — for UI dropdowns.
57def accent(library: str) -> str: 58 """Look up the accent color for a Dashlibs package name (e.g. 'dashsynthetic').""" 59 return ACCENTS.get(library, ACCENTS["default"])
Look up the accent color for a Dashlibs package name (e.g. 'dashsynthetic').