dataface 0.1.2__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.
Files changed (455) hide show
  1. d3_format/__init__.py +14 -0
  2. d3_format/errors.py +19 -0
  3. d3_format/format.py +551 -0
  4. d3_format/spec.py +159 -0
  5. dataface/DATAFACE_SYNTAX.md +1135 -0
  6. dataface/__init__.py +93 -0
  7. dataface/_docs_site.py +20 -0
  8. dataface/_install_hint.py +26 -0
  9. dataface/agent_api/__init__.py +79 -0
  10. dataface/agent_api/_init_templates/__init__.py +0 -0
  11. dataface/agent_api/_init_templates/agents_dft_snippet.md +26 -0
  12. dataface/agent_api/_init_templates/dataface.yml +15 -0
  13. dataface/agent_api/_init_templates/faces-dataface.yml +144 -0
  14. dataface/agent_api/_init_templates/index.md +24 -0
  15. dataface/agent_api/_paths.py +118 -0
  16. dataface/agent_api/_project_agents_md.py +43 -0
  17. dataface/agent_api/_session_store.py +486 -0
  18. dataface/agent_api/_state.py +28 -0
  19. dataface/agent_api/chat.py +221 -0
  20. dataface/agent_api/dashboards.py +257 -0
  21. dataface/agent_api/describe.py +366 -0
  22. dataface/agent_api/describe_query.py +120 -0
  23. dataface/agent_api/docs/__init__.py +25 -0
  24. dataface/agent_api/docs/_loader.py +292 -0
  25. dataface/agent_api/docs/yaml-reference.md +2757 -0
  26. dataface/agent_api/file_refs.py +118 -0
  27. dataface/agent_api/init.py +126 -0
  28. dataface/agent_api/inspect.py +128 -0
  29. dataface/agent_api/mcp_install.py +170 -0
  30. dataface/agent_api/query.py +274 -0
  31. dataface/agent_api/schema.py +658 -0
  32. dataface/agent_api/schema_search.py +284 -0
  33. dataface/agent_api/search.py +270 -0
  34. dataface/agent_api/skill_install.py +141 -0
  35. dataface/agent_api/skill_render.py +90 -0
  36. dataface/agent_api/skills.py +293 -0
  37. dataface/agent_api/surface_aliases.yaml +128 -0
  38. dataface/agent_api/validate.py +175 -0
  39. dataface/agent_api/validate_query.py +84 -0
  40. dataface/ai/__init__.py +39 -0
  41. dataface/ai/agent.py +139 -0
  42. dataface/ai/context.py +45 -0
  43. dataface/ai/events.py +62 -0
  44. dataface/ai/external_mcp.py +610 -0
  45. dataface/ai/generate_sql.py +96 -0
  46. dataface/ai/llm.py +403 -0
  47. dataface/ai/mcp/__init__.py +51 -0
  48. dataface/ai/mcp/server.py +289 -0
  49. dataface/ai/memories.py +85 -0
  50. dataface/ai/prompts.py +177 -0
  51. dataface/ai/schema_context.py +138 -0
  52. dataface/ai/skills/before-after-comparison/SKILL.md +102 -0
  53. dataface/ai/skills/before-after-comparison/examples/before-after-comparison.yml +24 -0
  54. dataface/ai/skills/dashboard-build/SKILL.md +212 -0
  55. dataface/ai/skills/dashboard-build/examples/_smoke.yml +15 -0
  56. dataface/ai/skills/dashboard-design/SKILL.md +182 -0
  57. dataface/ai/skills/dashboard-review/SKILL.md +113 -0
  58. dataface/ai/skills/dashboard-structural-review/SKILL.md +173 -0
  59. dataface/ai/skills/dashboard-visual-review/SKILL.md +139 -0
  60. dataface/ai/skills/dataface-mcp-setup/SKILL.md +177 -0
  61. dataface/ai/skills/dataface-troubleshooting/SKILL.md +225 -0
  62. dataface/ai/skills/drill-down-link/SKILL.md +112 -0
  63. dataface/ai/skills/drill-down-link/examples/drill-down-link.yml +27 -0
  64. dataface/ai/skills/faceted-small-multiples/SKILL.md +116 -0
  65. dataface/ai/skills/faceted-small-multiples/examples/faceted-small-multiples.yml +33 -0
  66. dataface/ai/skills/filter-bar-with-variables/SKILL.md +105 -0
  67. dataface/ai/skills/filter-bar-with-variables/examples/filter-bar-with-variables.yml +49 -0
  68. dataface/ai/skills/kpi-row/SKILL.md +101 -0
  69. dataface/ai/skills/kpi-row/examples/kpi-row.yml +55 -0
  70. dataface/ai/skills/report-design/SKILL.md +184 -0
  71. dataface/ai/skills/single-metric-bignum/SKILL.md +90 -0
  72. dataface/ai/skills/single-metric-bignum/examples/single-metric-bignum.yml +27 -0
  73. dataface/ai/skills/table-heavy-ops-dashboard/SKILL.md +114 -0
  74. dataface/ai/skills/table-heavy-ops-dashboard/examples/table-heavy-ops-dashboard.yml +48 -0
  75. dataface/ai/skills/time-series-trend/SKILL.md +93 -0
  76. dataface/ai/skills/time-series-trend/examples/time-series-trend.yml +26 -0
  77. dataface/ai/skills/top-n-with-detail/SKILL.md +98 -0
  78. dataface/ai/skills/top-n-with-detail/examples/top-n-with-detail.yml +45 -0
  79. dataface/ai/skills/two-by-two-grid-overview/SKILL.md +78 -0
  80. dataface/ai/skills/two-by-two-grid-overview/examples/two-by-two-grid-overview.yml +64 -0
  81. dataface/ai/tool_schemas.py +132 -0
  82. dataface/ai/tools/__init__.py +312 -0
  83. dataface/ai/yaml_utils.py +57 -0
  84. dataface/cli/__init__.py +3 -0
  85. dataface/cli/_console.py +48 -0
  86. dataface/cli/_error_format.py +83 -0
  87. dataface/cli/_extras.py +190 -0
  88. dataface/cli/_json_output.py +8 -0
  89. dataface/cli/_parsing.py +17 -0
  90. dataface/cli/_version_info.py +56 -0
  91. dataface/cli/commands/__init__.py +3 -0
  92. dataface/cli/commands/_agent_input.py +205 -0
  93. dataface/cli/commands/_agent_server.py +115 -0
  94. dataface/cli/commands/chat.py +645 -0
  95. dataface/cli/commands/describe.py +107 -0
  96. dataface/cli/commands/docs.py +131 -0
  97. dataface/cli/commands/extension.py +179 -0
  98. dataface/cli/commands/init.py +240 -0
  99. dataface/cli/commands/inspect.py +94 -0
  100. dataface/cli/commands/mcp_init.py +167 -0
  101. dataface/cli/commands/query.py +386 -0
  102. dataface/cli/commands/render.py +291 -0
  103. dataface/cli/commands/schema.py +411 -0
  104. dataface/cli/commands/search.py +49 -0
  105. dataface/cli/commands/serve.py +114 -0
  106. dataface/cli/commands/skills.py +133 -0
  107. dataface/cli/commands/skills_init.py +161 -0
  108. dataface/cli/commands/validate.py +63 -0
  109. dataface/cli/main.py +1501 -0
  110. dataface/core/__init__.py +75 -0
  111. dataface/core/compile/__init__.py +244 -0
  112. dataface/core/compile/_jinja_helpers.py +78 -0
  113. dataface/core/compile/channel.py +222 -0
  114. dataface/core/compile/chart_focus.py +101 -0
  115. dataface/core/compile/chart_resolved.py +169 -0
  116. dataface/core/compile/chart_type_detection.py +489 -0
  117. dataface/core/compile/chart_update.py +261 -0
  118. dataface/core/compile/colors.py +64 -0
  119. dataface/core/compile/compiler.py +904 -0
  120. dataface/core/compile/config.py +823 -0
  121. dataface/core/compile/custom_chart_types.py +208 -0
  122. dataface/core/compile/data_table_attachment.py +1287 -0
  123. dataface/core/compile/detect.py +110 -0
  124. dataface/core/compile/errors.py +302 -0
  125. dataface/core/compile/filter_injection.py +319 -0
  126. dataface/core/compile/introspection.py +527 -0
  127. dataface/core/compile/jinja.py +511 -0
  128. dataface/core/compile/labels_env.py +52 -0
  129. dataface/core/compile/markdown.py +154 -0
  130. dataface/core/compile/meta.py +388 -0
  131. dataface/core/compile/models/__init__.py +0 -0
  132. dataface/core/compile/models/chart/__init__.py +0 -0
  133. dataface/core/compile/models/chart/authored.py +2137 -0
  134. dataface/core/compile/models/chart/compiled.py +398 -0
  135. dataface/core/compile/models/config.py +347 -0
  136. dataface/core/compile/models/face/__init__.py +0 -0
  137. dataface/core/compile/models/face/authored.py +659 -0
  138. dataface/core/compile/models/face/compiled.py +522 -0
  139. dataface/core/compile/models/factories.py +201 -0
  140. dataface/core/compile/models/markers.py +40 -0
  141. dataface/core/compile/models/palette.py +36 -0
  142. dataface/core/compile/models/primitives.py +415 -0
  143. dataface/core/compile/models/query/__init__.py +0 -0
  144. dataface/core/compile/models/query/authored.py +246 -0
  145. dataface/core/compile/models/query/compiled.py +710 -0
  146. dataface/core/compile/models/refs.py +137 -0
  147. dataface/core/compile/models/source.py +611 -0
  148. dataface/core/compile/models/style/__init__.py +0 -0
  149. dataface/core/compile/models/style/authored.py +481 -0
  150. dataface/core/compile/models/style/compiled.py +3399 -0
  151. dataface/core/compile/models/style/merged.py +1682 -0
  152. dataface/core/compile/models/theme.py +362 -0
  153. dataface/core/compile/models/variable/__init__.py +0 -0
  154. dataface/core/compile/models/variable/authored.py +254 -0
  155. dataface/core/compile/models/vega_lite/__init__.py +0 -0
  156. dataface/core/compile/models/vega_lite/config.py +510 -0
  157. dataface/core/compile/models/vega_lite/contracts.py +171 -0
  158. dataface/core/compile/normalize_charts.py +494 -0
  159. dataface/core/compile/normalize_layout.py +1000 -0
  160. dataface/core/compile/normalize_queries.py +297 -0
  161. dataface/core/compile/normalize_variables.py +489 -0
  162. dataface/core/compile/normalizer.py +543 -0
  163. dataface/core/compile/palette.py +1100 -0
  164. dataface/core/compile/parameterized.py +658 -0
  165. dataface/core/compile/parser.py +228 -0
  166. dataface/core/compile/schema.py +20 -0
  167. dataface/core/compile/schema_renderers/__init__.py +0 -0
  168. dataface/core/compile/schema_renderers/json_schema.py +163 -0
  169. dataface/core/compile/schema_renderers/prompt.py +152 -0
  170. dataface/core/compile/schema_renderers/vscode_schema.py +301 -0
  171. dataface/core/compile/sizing.py +2126 -0
  172. dataface/core/compile/sources.py +518 -0
  173. dataface/core/compile/sql_authoring_lint.py +56 -0
  174. dataface/core/compile/style_cascade.py +471 -0
  175. dataface/core/compile/typography.py +299 -0
  176. dataface/core/compile/validator.py +301 -0
  177. dataface/core/compile/variables.py +53 -0
  178. dataface/core/compile/vega_config.py +98 -0
  179. dataface/core/compile/vega_lite/__init__.py +6 -0
  180. dataface/core/compile/vega_lite/validation.py +95 -0
  181. dataface/core/compile/yaml_error_formatter.py +838 -0
  182. dataface/core/connections.py +38 -0
  183. dataface/core/dashboard.py +358 -0
  184. dataface/core/defaults/default_config.yml +101 -0
  185. dataface/core/defaults/palettes/categorical/category-10-dark.yml +32 -0
  186. dataface/core/defaults/palettes/categorical/category-10-light.yml +43 -0
  187. dataface/core/defaults/palettes/categorical/category-10.yml +31 -0
  188. dataface/core/defaults/palettes/categorical/category-6-tonal-blue.yml +22 -0
  189. dataface/core/defaults/palettes/categorical/category-6-tonal-brown.yml +29 -0
  190. dataface/core/defaults/palettes/categorical/category-6-tonal-green.yml +20 -0
  191. dataface/core/defaults/palettes/categorical/category-6-tonal-orange.yml +21 -0
  192. dataface/core/defaults/palettes/categorical/category-6-tonal-purple.yml +20 -0
  193. dataface/core/defaults/palettes/categorical/editorial-10-dark.yml +32 -0
  194. dataface/core/defaults/palettes/categorical/editorial-10.yml +40 -0
  195. dataface/core/defaults/palettes/categorical/hero-6.yml +17 -0
  196. dataface/core/defaults/palettes/categorical/single-blue.yml +11 -0
  197. dataface/core/defaults/palettes/categorical/tableau.yml +20 -0
  198. dataface/core/defaults/palettes/data/xkcd_colors.json +3803 -0
  199. dataface/core/defaults/palettes/diverging/blue-red.yml +25 -0
  200. dataface/core/defaults/palettes/diverging/coolwarm.yml +24 -0
  201. dataface/core/defaults/palettes/diverging/crimson-green.yml +23 -0
  202. dataface/core/defaults/palettes/diverging/orange-teal.yml +23 -0
  203. dataface/core/defaults/palettes/diverging/sunset.yml +24 -0
  204. dataface/core/defaults/palettes/scaffold/dft-creams.yml +38 -0
  205. dataface/core/defaults/palettes/scaffold/dft-grays.yml +53 -0
  206. dataface/core/defaults/palettes/sequential/amber.yml +22 -0
  207. dataface/core/defaults/palettes/sequential/blue.yml +22 -0
  208. dataface/core/defaults/palettes/sequential/brown.yml +22 -0
  209. dataface/core/defaults/palettes/sequential/gray.yml +22 -0
  210. dataface/core/defaults/palettes/sequential/green.yml +22 -0
  211. dataface/core/defaults/palettes/sequential/purple.yml +22 -0
  212. dataface/core/defaults/palettes/sequential/rust.yml +22 -0
  213. dataface/core/defaults/palettes/sequential/teal.yml +22 -0
  214. dataface/core/defaults/palettes/tone/negative.yml +32 -0
  215. dataface/core/defaults/palettes/tone/positive.yml +22 -0
  216. dataface/core/defaults/palettes/tone/warning.yml +22 -0
  217. dataface/core/defaults/themes/_base.yaml +786 -0
  218. dataface/core/defaults/themes/bi.yaml +16 -0
  219. dataface/core/defaults/themes/carbong100.yaml +41 -0
  220. dataface/core/defaults/themes/cream.yaml +122 -0
  221. dataface/core/defaults/themes/dark.yaml +40 -0
  222. dataface/core/defaults/themes/diagnostics-title-angle-extreme.yaml +9 -0
  223. dataface/core/defaults/themes/diagnostics-title-baseline-extreme.yaml +9 -0
  224. dataface/core/defaults/themes/diagnostics-title-baseline.yaml +24 -0
  225. dataface/core/defaults/themes/diagnostics-title-center.yaml +8 -0
  226. dataface/core/defaults/themes/diagnostics-title-color-extreme.yaml +24 -0
  227. dataface/core/defaults/themes/diagnostics-title-font-extreme.yaml +25 -0
  228. dataface/core/defaults/themes/diagnostics-title-left.yaml +8 -0
  229. dataface/core/defaults/themes/diagnostics-title-offset-extreme.yaml +9 -0
  230. dataface/core/defaults/themes/diagnostics-title-size-extreme.yaml +24 -0
  231. dataface/core/defaults/themes/diagnostics-title-weight-extreme.yaml +24 -0
  232. dataface/core/defaults/themes/editorial.yaml +147 -0
  233. dataface/core/defaults/themes/light.yaml +30 -0
  234. dataface/core/defaults/themes/looker.yaml +17 -0
  235. dataface/core/defaults/themes/stark.yaml +134 -0
  236. dataface/core/errors/__init__.py +67 -0
  237. dataface/core/errors/codes_compile.py +56 -0
  238. dataface/core/errors/codes_execute.py +177 -0
  239. dataface/core/errors/codes_render.py +106 -0
  240. dataface/core/errors/codes_unknown.py +15 -0
  241. dataface/core/errors/hints.py +74 -0
  242. dataface/core/errors/registry.py +42 -0
  243. dataface/core/errors/structured.py +92 -0
  244. dataface/core/execute/__init__.py +91 -0
  245. dataface/core/execute/adapters/__init__.py +49 -0
  246. dataface/core/execute/adapters/adapter_registry.py +400 -0
  247. dataface/core/execute/adapters/base.py +245 -0
  248. dataface/core/execute/adapters/csv_adapter.py +239 -0
  249. dataface/core/execute/adapters/dbt_adapter.py +283 -0
  250. dataface/core/execute/adapters/dbt_adapter_factory.py +212 -0
  251. dataface/core/execute/adapters/dbt_macro_loader.py +95 -0
  252. dataface/core/execute/adapters/dbt_utils.py +150 -0
  253. dataface/core/execute/adapters/http_adapter.py +224 -0
  254. dataface/core/execute/adapters/metricflow_adapter.py +94 -0
  255. dataface/core/execute/adapters/schema_resolver_adapter.py +144 -0
  256. dataface/core/execute/adapters/sql_adapter.py +710 -0
  257. dataface/core/execute/adapters/values_adapter.py +58 -0
  258. dataface/core/execute/batch.py +744 -0
  259. dataface/core/execute/cache_backend.py +135 -0
  260. dataface/core/execute/cache_keys.py +66 -0
  261. dataface/core/execute/dbt_jinja.py +21 -0
  262. dataface/core/execute/dialects/__init__.py +121 -0
  263. dataface/core/execute/dialects/athena.py +75 -0
  264. dataface/core/execute/dialects/base.py +302 -0
  265. dataface/core/execute/dialects/bigquery.py +38 -0
  266. dataface/core/execute/dialects/databricks.py +68 -0
  267. dataface/core/execute/dialects/duckdb.py +35 -0
  268. dataface/core/execute/dialects/mysql.py +68 -0
  269. dataface/core/execute/dialects/postgres.py +39 -0
  270. dataface/core/execute/dialects/redshift.py +12 -0
  271. dataface/core/execute/dialects/snowflake.py +51 -0
  272. dataface/core/execute/dialects/sqlserver.py +92 -0
  273. dataface/core/execute/duckdb_cache.py +712 -0
  274. dataface/core/execute/duckdb_config.py +26 -0
  275. dataface/core/execute/errors.py +213 -0
  276. dataface/core/execute/executor.py +1249 -0
  277. dataface/core/execute/parallel.py +162 -0
  278. dataface/core/execute/setup_sql.py +58 -0
  279. dataface/core/execute/source_registry.py +72 -0
  280. dataface/core/execute/source_resolver.py +255 -0
  281. dataface/core/execute/sql_guard.py +387 -0
  282. dataface/core/execute/sql_literals.py +199 -0
  283. dataface/core/fonts.py +52 -0
  284. dataface/core/inspect/__init__.py +32 -0
  285. dataface/core/inspect/cache_factory.py +98 -0
  286. dataface/core/inspect/db_types.py +162 -0
  287. dataface/core/inspect/dbt_schema.py +96 -0
  288. dataface/core/inspect/defaults.yml +37 -0
  289. dataface/core/inspect/fanout_risk.py +109 -0
  290. dataface/core/inspect/manifest_utils.py +77 -0
  291. dataface/core/inspect/partials/categorical.yml +40 -0
  292. dataface/core/inspect/partials/date.yml +40 -0
  293. dataface/core/inspect/partials/numeric.yml +55 -0
  294. dataface/core/inspect/partition_types.py +38 -0
  295. dataface/core/inspect/query_validator.py +975 -0
  296. dataface/core/inspect/renderer.py +354 -0
  297. dataface/core/inspect/resolver.py +808 -0
  298. dataface/core/inspect/search.py +461 -0
  299. dataface/core/inspect/sources/__init__.py +32 -0
  300. dataface/core/inspect/sources/dbt.py +738 -0
  301. dataface/core/inspect/sources/duckdb_utils.py +66 -0
  302. dataface/core/inspect/templates/__init__.py +1 -0
  303. dataface/core/inspect/templates/categorical_column.yml +196 -0
  304. dataface/core/inspect/templates/charts.yml +109 -0
  305. dataface/core/inspect/templates/date_column.yml +248 -0
  306. dataface/core/inspect/templates/model.yml +138 -0
  307. dataface/core/inspect/templates/numeric_column.yml +261 -0
  308. dataface/core/inspect/templates/quality.yml +80 -0
  309. dataface/core/inspect/templates/string_column.yml +263 -0
  310. dataface/core/project_roots.py +165 -0
  311. dataface/core/render/__init__.py +87 -0
  312. dataface/core/render/board_links.py +176 -0
  313. dataface/core/render/chart/__init__.py +27 -0
  314. dataface/core/render/chart/arc_attached_table.py +251 -0
  315. dataface/core/render/chart/artifacts.py +16 -0
  316. dataface/core/render/chart/callout.py +225 -0
  317. dataface/core/render/chart/decisions.py +358 -0
  318. dataface/core/render/chart/geo.py +700 -0
  319. dataface/core/render/chart/kpi.py +916 -0
  320. dataface/core/render/chart/labels.py +76 -0
  321. dataface/core/render/chart/pipeline.py +818 -0
  322. dataface/core/render/chart/presentation.py +36 -0
  323. dataface/core/render/chart/profile.py +3438 -0
  324. dataface/core/render/chart/render_single.py +347 -0
  325. dataface/core/render/chart/renderers.py +193 -0
  326. dataface/core/render/chart/rendering.py +565 -0
  327. dataface/core/render/chart/serialization.py +90 -0
  328. dataface/core/render/chart/spark.py +496 -0
  329. dataface/core/render/chart/spark_bar.py +370 -0
  330. dataface/core/render/chart/spec_builders.py +154 -0
  331. dataface/core/render/chart/standard_renderer.py +2645 -0
  332. dataface/core/render/chart/table.py +2957 -0
  333. dataface/core/render/chart/table_support.py +1452 -0
  334. dataface/core/render/chart/tick_values.py +66 -0
  335. dataface/core/render/chart/time_unit_detect.py +809 -0
  336. dataface/core/render/chart/title_overflow.py +157 -0
  337. dataface/core/render/chart/type_inference.py +122 -0
  338. dataface/core/render/chart/validation.py +99 -0
  339. dataface/core/render/chart/vega_lite.py +125 -0
  340. dataface/core/render/chart/vega_lite_types.py +268 -0
  341. dataface/core/render/chart/vl_field_maps.py +346 -0
  342. dataface/core/render/chart_interactivity.py +24 -0
  343. dataface/core/render/control_registry.py +287 -0
  344. dataface/core/render/converters/__init__.py +24 -0
  345. dataface/core/render/converters/chart.py +276 -0
  346. dataface/core/render/converters/html.py +98 -0
  347. dataface/core/render/converters/pdf.py +40 -0
  348. dataface/core/render/converters/png.py +41 -0
  349. dataface/core/render/errors.py +144 -0
  350. dataface/core/render/face_api.py +160 -0
  351. dataface/core/render/faces.py +1194 -0
  352. dataface/core/render/font_measurement.py +48 -0
  353. dataface/core/render/font_support.py +197 -0
  354. dataface/core/render/fonts/DFTSansTabular-Regular.ttf +0 -0
  355. dataface/core/render/fonts/DFTSansTabular-Regular.woff2 +0 -0
  356. dataface/core/render/fonts/DFTSerifOldstyleProportional-Regular.ttf +0 -0
  357. dataface/core/render/fonts/DFTSerifOldstyleTabular-Regular.ttf +0 -0
  358. dataface/core/render/fonts/InterVariable.ttf +0 -0
  359. dataface/core/render/fonts/InterVariable.woff2 +0 -0
  360. dataface/core/render/fonts/NOTO_COLOR_EMOJI_LICENSE.txt +93 -0
  361. dataface/core/render/fonts/NOTO_EMOJI_LICENSE.txt +93 -0
  362. dataface/core/render/fonts/NotoColorEmoji-Regular.ttf +0 -0
  363. dataface/core/render/fonts/NotoColorEmoji-Regular.woff2 +0 -0
  364. dataface/core/render/fonts/NotoEmoji-Regular.ttf +0 -0
  365. dataface/core/render/fonts/NotoEmoji-Regular.woff2 +0 -0
  366. dataface/core/render/fonts/SOURCE_CODE_PRO_LICENSE.txt +93 -0
  367. dataface/core/render/fonts/SOURCE_SERIF_4_LICENSE.txt +98 -0
  368. dataface/core/render/fonts/SourceCodePro-Regular.ttf +0 -0
  369. dataface/core/render/fonts/SourceSerif4-Regular.ttf +0 -0
  370. dataface/core/render/fonts/_emoji_font_face.css +43 -0
  371. dataface/core/render/fonts/source-serif-4-variable-latin.woff2 +0 -0
  372. dataface/core/render/format_utils.py +329 -0
  373. dataface/core/render/geo_defaults.yml +28 -0
  374. dataface/core/render/json_format.py +146 -0
  375. dataface/core/render/layout_sizing.py +865 -0
  376. dataface/core/render/layouts.py +541 -0
  377. dataface/core/render/markdown_defaults.yml +16 -0
  378. dataface/core/render/missing_vars_prompt.py +79 -0
  379. dataface/core/render/placeholder.py +389 -0
  380. dataface/core/render/render_result.py +14 -0
  381. dataface/core/render/renderer.py +467 -0
  382. dataface/core/render/script_embedding.py +16 -0
  383. dataface/core/render/svg_utils.py +212 -0
  384. dataface/core/render/template_loader.py +69 -0
  385. dataface/core/render/templates/controls/_styles.css +606 -0
  386. dataface/core/render/templates/controls/checkbox.html +16 -0
  387. dataface/core/render/templates/controls/date.html +16 -0
  388. dataface/core/render/templates/controls/number.html +19 -0
  389. dataface/core/render/templates/controls/readonly.html +9 -0
  390. dataface/core/render/templates/controls/select.html +21 -0
  391. dataface/core/render/templates/controls/slider.html +22 -0
  392. dataface/core/render/templates/controls/text.html +16 -0
  393. dataface/core/render/templates/scripts/chart_interactivity.js +191 -0
  394. dataface/core/render/templates/scripts/variables.js +976 -0
  395. dataface/core/render/templates/svg/grid_pattern.svg +3 -0
  396. dataface/core/render/templates/svg/styles.css +51 -0
  397. dataface/core/render/terminal.py +311 -0
  398. dataface/core/render/terminal_charts.py +563 -0
  399. dataface/core/render/terminal_defaults.yml +2 -0
  400. dataface/core/render/terminal_layouts.py +299 -0
  401. dataface/core/render/terminal_text.py +31 -0
  402. dataface/core/render/text/__init__.py +1 -0
  403. dataface/core/render/text/case.py +113 -0
  404. dataface/core/render/text_format.py +129 -0
  405. dataface/core/render/utils.py +106 -0
  406. dataface/core/render/variable_controls.py +946 -0
  407. dataface/core/render/variable_input_refinement.py +140 -0
  408. dataface/core/render/warnings/__init__.py +15 -0
  409. dataface/core/render/warnings/bar_color_1_to_1_with_x.py +80 -0
  410. dataface/core/render/warnings/base.py +44 -0
  411. dataface/core/render/warnings/fanout_risk.py +15 -0
  412. dataface/core/render/warnings/from_query_diagnostic.py +56 -0
  413. dataface/core/render/warnings/missing_join_predicate.py +13 -0
  414. dataface/core/render/warnings/query_parse_error.py +14 -0
  415. dataface/core/render/warnings/query_returned_zero_rows.py +42 -0
  416. dataface/core/render/warnings/reaggregation.py +14 -0
  417. dataface/core/render/warnings/registry.py +45 -0
  418. dataface/core/render/warnings/suppression.py +46 -0
  419. dataface/core/render/warnings/temporal_single_point.py +63 -0
  420. dataface/core/render/warnings/unreferenced_chart.py +15 -0
  421. dataface/core/render/warnings/y_encoding_mostly_null.py +76 -0
  422. dataface/core/render/yaml_format.py +167 -0
  423. dataface/core/resolve_face.py +195 -0
  424. dataface/core/schema/__init__.py +0 -0
  425. dataface/core/schema/guidance.py +151 -0
  426. dataface/core/scoped_paths.py +59 -0
  427. dataface/core/serve/__init__.py +14 -0
  428. dataface/core/serve/bootstrap.py +39 -0
  429. dataface/core/serve/embedded.py +57 -0
  430. dataface/core/serve/port.py +129 -0
  431. dataface/core/serve/server.py +938 -0
  432. dataface/core/serve/templates/__init__.py +0 -0
  433. dataface/core/serve/templates/directory.yml +6 -0
  434. dataface/core/serve/templates/error.html.j2 +217 -0
  435. dataface/core/utils.py +121 -0
  436. dataface/core/validate.py +64 -0
  437. dataface/integrations/__init__.py +0 -0
  438. dataface/integrations/highlighting.py +351 -0
  439. dataface/integrations/markdown.py +537 -0
  440. dataface/py.typed +0 -0
  441. dataface-0.1.2.dist-info/METADATA +375 -0
  442. dataface-0.1.2.dist-info/RECORD +455 -0
  443. dataface-0.1.2.dist-info/WHEEL +4 -0
  444. dataface-0.1.2.dist-info/entry_points.txt +2 -0
  445. dataface-0.1.2.dist-info/licenses/LICENSE +202 -0
  446. mdsvg/__init__.py +168 -0
  447. mdsvg/fonts.py +656 -0
  448. mdsvg/images.py +299 -0
  449. mdsvg/parser.py +629 -0
  450. mdsvg/playground.py +284 -0
  451. mdsvg/py.typed +2 -0
  452. mdsvg/renderer.py +1623 -0
  453. mdsvg/style.py +355 -0
  454. mdsvg/types.py +200 -0
  455. mdsvg/utils.py +86 -0
@@ -0,0 +1,225 @@
1
+ ---
2
+ name: dataface-troubleshooting
3
+ kind: workflow
4
+ description: >
5
+ Diagnose and fix Dataface dashboard errors. Use when validation, query
6
+ execution, query inspection, or dashboard rendering returns an error, when a
7
+ dashboard renders but looks wrong, when SQL fails, when YAML won't validate,
8
+ or when the user says 'fix this error', 'debug this dashboard', 'why is this
9
+ broken', 'chart shows no data'. Covers YAML validation failures, SQL
10
+ execution errors, rendering issues, and variable misconfiguration. Do NOT
11
+ use for building new dashboards from scratch (use dashboard-build). Do NOT
12
+ use for design quality review (use dashboard-design).
13
+ metadata:
14
+ author: fivetran
15
+ ---
16
+
17
+ # Troubleshooting Dataface
18
+
19
+ Systematically diagnose and fix errors when building Dataface dashboards. Never guess — use the tools to confirm.
20
+
21
+ ## The Iron Rule
22
+
23
+ **Never change working YAML to "fix" a problem you haven't diagnosed.** Read the error message. Reproduce it. Understand the cause. Then fix it.
24
+
25
+ ## Diagnostic Workflow
26
+
27
+ ```
28
+ Error occurs
29
+ → Read the full error message (not just the first line)
30
+ → Classify: YAML error, SQL error, or rendering issue?
31
+ → Apply the relevant fix pattern below
32
+ → Validate again to confirm the fix
33
+ ```
34
+
35
+ ## YAML Validation Errors
36
+
37
+ These come from `{{ s_validate_dashboard }}`. The error message tells you exactly what's wrong.
38
+
39
+ ### "must have at least one layout"
40
+
41
+ Every face needs a layout element. Add `rows: []`, `cols: []`, `grid: {...}`, `tabs: {...}`, or `text: "..."`.
42
+
43
+ ### "references unknown chart 'X'"
44
+
45
+ **The most common error.** Layout references *charts*, not queries. The fix:
46
+
47
+ ```yaml
48
+ # WRONG — referencing a query name in layout
49
+ queries:
50
+ my_query:
51
+ sql: SELECT ...
52
+ rows:
53
+ - my_query # ❌ This is a query, not a chart
54
+
55
+ # RIGHT — create a chart that references the query
56
+ queries:
57
+ my_query:
58
+ sql: SELECT ...
59
+ charts:
60
+ my_chart:
61
+ query: my_query # Chart references query
62
+ type: table
63
+ rows:
64
+ - my_chart # ✅ Layout references chart
65
+ ```
66
+
67
+ **Structure order: Queries → Charts → Layout.** You cannot skip the Charts layer.
68
+
69
+ ### "missing required: query"
70
+
71
+ Charts need a `query:` field. Either reference a named query or define one inline:
72
+
73
+ ```yaml
74
+ charts:
75
+ my_chart:
76
+ query: my_query # Reference a named query
77
+ type: bar
78
+ x: category
79
+ y: value
80
+
81
+ # OR inline
82
+ my_chart:
83
+ query:
84
+ sql: SELECT ...
85
+ source: my_profile
86
+ type: bar
87
+ x: category
88
+ y: value
89
+ ```
90
+
91
+ ### "source required" / "missing source"
92
+
93
+ SQL queries must specify which data source to use. Either set a top-level `source:` or specify per-query:
94
+
95
+ ```yaml
96
+ source: my_profile # Top-level default
97
+
98
+ queries:
99
+ uses_default:
100
+ sql: SELECT ... # Inherits top-level source
101
+
102
+ explicit:
103
+ sql: SELECT ...
104
+ source: other_profile # Overrides for this query
105
+ ```
106
+
107
+ ### Variable Options Errors
108
+
109
+ The `default` field goes at the variable level, NOT inside `options`:
110
+
111
+ ```yaml
112
+ # WRONG
113
+ variables:
114
+ region:
115
+ input: select
116
+ options:
117
+ static: [North, South]
118
+ default: North # ❌
119
+
120
+ # RIGHT
121
+ variables:
122
+ region:
123
+ input: select
124
+ options:
125
+ static: [North, South]
126
+ default: North # ✅
127
+ ```
128
+
129
+ Use `options.static` for static values, not `options.values`.
130
+
131
+ ## SQL Execution Errors
132
+
133
+ These come from `{{ s_query_face }}`, `{{ s_execute_query }}`, or `{{ s_render_dashboard }}`.
134
+
135
+ ### "table does not exist"
136
+
137
+ Discover available tables first via `{{ s_schema }}` (hierarchy drill-down) or `{{ s_schema_search }}` (keyword search). For ad-hoc SQL against the information schema:
138
+
139
+ ```sql
140
+ -- PostgreSQL / Redshift
141
+ SELECT table_schema, table_name FROM information_schema.tables;
142
+
143
+ -- BigQuery
144
+ SELECT table_name FROM `project.dataset.INFORMATION_SCHEMA.TABLES`;
145
+
146
+ -- Snowflake
147
+ SHOW TABLES IN SCHEMA my_schema;
148
+ ```
149
+
150
+ ### "column does not exist"
151
+
152
+ Check actual column names — don't guess. Use `{{ s_schema }}` at the table/column level for profiling details when available, or:
153
+
154
+ ```sql
155
+ SELECT column_name, data_type
156
+ FROM information_schema.columns
157
+ WHERE table_name = 'my_table';
158
+ ```
159
+
160
+ ### Type mismatches
161
+
162
+ Common causes:
163
+
164
+ - Comparing a string column to an unquoted value: `WHERE status = active` → `WHERE status = 'active'`
165
+ - Date functions that differ between databases (BigQuery vs Postgres vs Snowflake)
166
+ - Aggregating a non-numeric column
167
+
168
+ ## Rendering Issues
169
+
170
+ These show up when `{{ s_render_dashboard }}` produces unexpected visual results.
171
+
172
+ ### Chart shows no data
173
+
174
+ - Verify the query returns rows: `{{ s_execute_query }}` with the same SQL
175
+ - Check that `x:` and `y:` column names match the query's SELECT aliases exactly (case-sensitive)
176
+ - Check variable defaults — a restrictive filter might exclude all data
177
+
178
+ ### Chart axes are wrong
179
+
180
+ - Ensure `x:` is the categorical/time column and `y:` is the numeric column
181
+ - For time series, ensure the date column is sorted in the SQL: `ORDER BY date`
182
+
183
+ ### Layout doesn't look right
184
+
185
+ - Check column spans: `cols: [chart_a, 2]` means chart_a spans 2 columns
186
+ - Charts in a `cols:` array share the row equally unless spans are specified
187
+ - Too many items in one `cols:` array = each gets too narrow
188
+
189
+ ## Debugging Checklist
190
+
191
+ When stuck, work through this in order:
192
+
193
+ 1. **Read the full error** — not just the first line. The details matter.
194
+ 2. **Validate the YAML** — `{{ s_validate_dashboard }}` catches structural issues before SQL runs.
195
+ 3. **Test one query at a time** — `{{ s_query_face }}` for saved face queries, `{{ s_execute_query }}` for raw SQL.
196
+ 4. **Check column names** — `{{ s_schema }}`, `{{ s_schema_search }}`, or `{{ s_describe_query }}` to verify.
197
+ 5. **Simplify** — Remove charts until you find the one that's broken.
198
+ 6. **Re-render** — Confirm the fix visually.
199
+ 7. **Restore metadata** — Ensure `description` fields remain populated for queries/charts/variables/layout sections.
200
+
201
+ ## Common Mistakes
202
+
203
+ | Mistake | Fix |
204
+ |---------|-----|
205
+ | Changing YAML randomly until errors stop | Read the error. Diagnose first, then fix. |
206
+ | Referencing queries in layout | Create a chart that references the query. Layout references charts. |
207
+ | Assuming column names | Use `{{ s_schema }}`, `{{ s_schema_search }}`, or `{{ s_execute_query }}` to verify |
208
+ | Wrong `source` | Call `{{ s_schema }}` (no args) to see available sources |
209
+ | Variable `default` inside `options` | `default` goes at the variable level, not nested inside `options` |
210
+
211
+ ## Rationalizations to Resist
212
+
213
+ | Excuse | Reality |
214
+ |--------|---------|
215
+ | "The error message is confusing, I'll try something else" | Read it again carefully — it tells you what's wrong. |
216
+ | "I'll just change the chart type, maybe that'll fix it" | Chart type doesn't fix SQL or YAML structure errors. |
217
+ | "It works for similar dashboards" | This data source may have different column names. Verify. |
218
+ | "I'll skip validation and just render" | Validation is instant and catches errors before the slow SQL runs. |
219
+
220
+ ## Red Flags — STOP
221
+
222
+ - About to make a change without understanding the error message
223
+ - Changing multiple things at once (change one thing, validate, repeat)
224
+ - Guessing column names instead of checking the schema
225
+ - The same error keeps coming back (you're not fixing the root cause)
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: drill-down-link
3
+ kind: pattern
4
+ description: >
5
+ Pattern for cross-face navigation: a chart or table whose elements link to a
6
+ detail face, passing a row value as a URL path segment or query parameter.
7
+ Use when users need to click from a summary view into a per-item detail face.
8
+ Triggers on: 'drill down', 'click through', 'detail page', 'per-item face',
9
+ 'link to detail', 'cross-face navigation'. Do NOT use for filtering within
10
+ the same face (use filter-bar-with-variables). Do NOT use for tabs within a
11
+ single face (use the tabs layout).
12
+ metadata:
13
+ author: fivetran
14
+ ---
15
+
16
+ # Drill-Down Link
17
+
18
+ Two faces wired together: a *source* face whose chart elements are clickable
19
+ links, and a *target* face that receives the clicked value as a URL parameter
20
+ and filters its queries accordingly.
21
+
22
+ The source uses `link:` on a chart (channel placeholder substitution) or
23
+ `link:` on a table column (per-row URL). The target reads the URL parameter
24
+ via a `variables:` entry with `input: text`.
25
+
26
+ ## When to reach for this
27
+
28
+ - Users need to click from a ranking or list into a per-item detail view
29
+ - The detail content is rich enough to justify its own face (not just a tooltip)
30
+ - The linking dimension is a natural identifier (region, product, customer ID)
31
+
32
+ ## When NOT to use this
33
+
34
+ - Filtering within the same face → `filter-bar-with-variables`
35
+ - Show/hide sections → tabs layout
36
+ - Simple tooltip detail → hover tooltips work automatically, no extra YAML
37
+
38
+ ## The pattern — source face
39
+
40
+ ```yaml
41
+ charts:
42
+ region_bars:
43
+ type: bar
44
+ query: revenue_by_region
45
+ x: region
46
+ y: revenue
47
+ title: Revenue by Region — click to drill
48
+ link: "/region-detail?region={{ x }}" # {{ x }} = clicked bar's region
49
+ ```
50
+
51
+ For tables, use `link:` at the chart root (applies to all cells) or per-column
52
+ in `style.columns` (overrides the root for that column):
53
+
54
+ ```yaml
55
+ charts:
56
+ customers_table:
57
+ type: table
58
+ query: top_customers
59
+ link: "/customer-detail?id={{ customer_id }}" # default for all cells
60
+ style:
61
+ columns:
62
+ customer_name:
63
+ label: Customer
64
+ # inherits chart-root link
65
+ status:
66
+ label: Status
67
+ link: "/status-detail?status={{ status }}" # overrides root for this column
68
+ ```
69
+
70
+ ## The pattern — target face
71
+
72
+ ```yaml
73
+ variables:
74
+ region:
75
+ input: text # populated from ?region= query param
76
+ default: "North" # fallback when opened standalone
77
+
78
+ queries:
79
+ region_detail:
80
+ sql: SELECT * FROM orders WHERE {{ filter('region', region) }}
81
+ ```
82
+
83
+ See `examples/drill-down-link.yml` for the source face worked example.
84
+
85
+ ## Variations
86
+
87
+ | Variation | YAML knob | When |
88
+ |---|---|---|
89
+ | Path segment | `link: "/detail/{{ x }}"` | Clean URLs, server-side routing |
90
+ | Query param | `link: "/detail?id={{ x }}"` | Multiple params, easier debugging |
91
+ | Table cell link | `link:` on column in `style.columns` | Per-row links in a table |
92
+ | In-page filter | `link: "?var={{ x }}"` | Update a variable without navigation |
93
+ | External link | `link: "https://external.com/{{ x }}"` | Link out to another system |
94
+
95
+ ## Common pitfalls
96
+
97
+ | Pitfall | Why it breaks | Fix |
98
+ |---|---|---|
99
+ | Using `{{ color }}` placeholder on a chart with no color channel | Compile error: `link template references channel 'color' but chart has no 'color' encoding assigned` | Use only the chart's mapped channels: `x`, `y`, `color`, `theta` |
100
+ | Target face has no matching variable | Parameter ignored, shows all data | Add a `variables:` entry on the target with the same name |
101
+ | Using `href:` instead of `link:` | Compile error: `'href:' was renamed to 'link:'` | Use `link:` on all chart types |
102
+
103
+ ## Worked example
104
+
105
+ See `examples/drill-down-link.yml` — the source face: a bar chart with
106
+ `link:` that passes the clicked region to a detail face. Inline data, no
107
+ warehouse required. The target face is documented in the body above — author
108
+ it as a separate YAML file in the same `faces/` directory.
109
+
110
+ ## YAML Reference
111
+
112
+ For syntax and field details: {{ s_yaml_reference_footer }}
@@ -0,0 +1,27 @@
1
+ title: Revenue by Region
2
+ description: >
3
+ Drill-down link pattern — source face. Each bar links to a per-region detail
4
+ face via link. The {{ x }} placeholder is replaced with the clicked region.
5
+
6
+ queries:
7
+ by_region:
8
+ description: Revenue totals by region, pre-ranked
9
+ columns: [region, revenue, orders]
10
+ values:
11
+ - [North, 85000, 320]
12
+ - [East, 71000, 268]
13
+ - [South, 62000, 241]
14
+ - [West, 54000, 198]
15
+
16
+ charts:
17
+ region_bars:
18
+ description: Clickable bar chart — each bar links to the region detail face
19
+ type: bar
20
+ query: by_region
21
+ x: region
22
+ y: revenue
23
+ title: Revenue by Region — click to drill
24
+ link: "/region-detail?region={{ x }}"
25
+
26
+ rows:
27
+ - region_bars
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: faceted-small-multiples
3
+ kind: pattern
4
+ description: >
5
+ Pattern for showing the same metric sliced by a categorical dimension —
6
+ either as one multi-series chart (color encoding) or as N side-by-side
7
+ charts (manual small multiples). Use when comparing a trend or distribution
8
+ across segments. Triggers on: 'by segment', 'by region', 'by category',
9
+ 'small multiples', 'faceted', 'breakdown', 'compare across groups',
10
+ 'stacked area'. Use color encoding for ≤5 segments in one chart; use manual
11
+ multiples when segments need separate y-scales or spatial separation. Do NOT
12
+ use for aggregate totals (use kpi-row or two-by-two-grid-overview). Do NOT
13
+ use for two-series comparison (use before-after-comparison).
14
+ metadata:
15
+ author: fivetran
16
+ ---
17
+
18
+ # Faceted Small Multiples
19
+
20
+ Two approaches for showing the same metric broken down by a category:
21
+
22
+ **Option A — Color encoding (one chart):** Add `color: segment_col` to any
23
+ chart. Dataface renders one series per segment value, with a legend. Best for
24
+ ≤5 segments, same y-scale.
25
+
26
+ **Option B — Manual multiples (side-by-side charts):** Author N separate
27
+ charts — one per segment — and arrange them in `cols:` or a `grid:`. Best
28
+ when segments need independent y-scales or when you want spatial separation.
29
+
30
+ ## When to reach for this
31
+
32
+ - "Show me revenue by region across months" (time × segment)
33
+ - "Compare the distribution of orders across product categories" (category × count)
34
+ - Segments are the primary lens; aggregate total is secondary
35
+
36
+ ## When NOT to use this
37
+
38
+ - Two series only → `before-after-comparison`
39
+ - Composition (parts add to 100%) → stacked area (`type: area` + `color:`)
40
+ - More than 8 segments → group the long tail into "Other" in SQL
41
+
42
+ ## The pattern — Option A (color encoding)
43
+
44
+ ```yaml
45
+ queries:
46
+ revenue_by_segment:
47
+ sql: |
48
+ SELECT month, region, SUM(revenue) AS revenue
49
+ FROM orders
50
+ GROUP BY month, region
51
+ ORDER BY month, region
52
+
53
+ charts:
54
+ region_trend:
55
+ type: line
56
+ query: revenue_by_segment
57
+ x: month
58
+ y: revenue
59
+ color: region # one series per region value
60
+ title: Revenue by Region
61
+ ```
62
+
63
+ ## The pattern — Option B (manual multiples)
64
+
65
+ ```yaml
66
+ queries:
67
+ east_data:
68
+ sql: SELECT month, SUM(revenue) AS revenue FROM orders WHERE region='East' GROUP BY 1
69
+ west_data:
70
+ sql: SELECT month, SUM(revenue) AS revenue FROM orders WHERE region='West' GROUP BY 1
71
+
72
+ charts:
73
+ east_chart:
74
+ type: line
75
+ query: east_data
76
+ x: month
77
+ y: revenue
78
+ title: East
79
+ west_chart:
80
+ type: line
81
+ query: west_data
82
+ x: month
83
+ y: revenue
84
+ title: West
85
+
86
+ rows:
87
+ - cols: [east_chart, west_chart] # same visual encoding, side by side
88
+ ```
89
+
90
+ See `examples/faceted-small-multiples.yml` for the worked example (Option A).
91
+
92
+ ## Variations
93
+
94
+ | Variation | YAML knob | When |
95
+ |---|---|---|
96
+ | Stacked area | `type: area` + `color:` | Show composition — parts of a whole over time |
97
+ | Side-by-side bar | `type: bar` + `color:` | Grouped bars per category |
98
+ | Manual N-up | N charts in a `cols:` row | Independent scales per segment |
99
+ | Grid layout | `grid: columns: 24, col_span: 8` | 3+ multiples in a row |
100
+
101
+ ## Common pitfalls
102
+
103
+ | Pitfall | Why it breaks | Fix |
104
+ |---|---|---|
105
+ | Too many color segments (>8) | Legend overflows, colors repeat | Limit to top-N in SQL + "Other" bucket |
106
+ | Stacked area with `color:` but no GROUP BY | Wrong aggregation, chart errors | Ensure one row per (x, color) combination |
107
+ | Manual multiples with different y-scales | Misleading comparisons | Use same y-axis domain, or make the difference visible in chart titles |
108
+
109
+ ## Worked example
110
+
111
+ See `examples/faceted-small-multiples.yml` — monthly signups by channel using
112
+ color encoding (Option A). Inline data, no warehouse required.
113
+
114
+ ## YAML Reference
115
+
116
+ For syntax and field details: {{ s_yaml_reference_footer }}
@@ -0,0 +1,33 @@
1
+ title: Signups by Channel
2
+ description: Faceted small multiples pattern — one series per segment via color encoding
3
+
4
+ queries:
5
+ signups_by_channel:
6
+ description: Monthly signups broken down by acquisition channel
7
+ columns: [month, channel, signups]
8
+ values:
9
+ - ["2026-01-01", Organic, 90]
10
+ - ["2026-01-01", Paid, 40]
11
+ - ["2026-01-01", Partner, 18]
12
+ - ["2026-02-01", Organic, 105]
13
+ - ["2026-02-01", Paid, 48]
14
+ - ["2026-02-01", Partner, 22]
15
+ - ["2026-03-01", Organic, 118]
16
+ - ["2026-03-01", Paid, 52]
17
+ - ["2026-03-01", Partner, 29]
18
+ - ["2026-04-01", Organic, 134]
19
+ - ["2026-04-01", Paid, 58]
20
+ - ["2026-04-01", Partner, 34]
21
+
22
+ charts:
23
+ signups_trend:
24
+ description: Signup trend faceted by channel — one colored series per channel
25
+ type: area
26
+ query: signups_by_channel
27
+ x: month
28
+ y: signups
29
+ color: channel
30
+ title: Monthly Signups by Channel
31
+
32
+ rows:
33
+ - signups_trend
@@ -0,0 +1,105 @@
1
+ ---
2
+ name: filter-bar-with-variables
3
+ kind: pattern
4
+ description: >
5
+ Pattern for interactive dashboards with dropdown/date/numeric filter controls
6
+ wired into queries via Jinja variable substitution. Use when users need to
7
+ slice data by dimension, date range, or threshold without editing YAML.
8
+ Triggers on: 'filter', 'dropdown', 'date range', 'interactive', 'variable',
9
+ 'select', 'picker', 'parameterized'. Variables render as UI controls above
10
+ the charts. Do NOT use for drill-through navigation between faces (use
11
+ drill-down-link). Do NOT use when all data fits on one chart without
12
+ filtering.
13
+ metadata:
14
+ author: fivetran
15
+ ---
16
+
17
+ # Filter Bar with Variables
18
+
19
+ Variables add interactive controls to a face. Each `variables:` entry renders
20
+ a UI widget (select, date picker, number slider). Queries reference variables
21
+ with `{{ var_name }}` Jinja placeholders — Dataface substitutes the current
22
+ widget value at query time.
23
+
24
+ ## When to reach for this
25
+
26
+ - Users need to slice the data by region, category, time window, or threshold
27
+ - The same face serves multiple audiences who want different views
28
+ - Query results would be too large without a default filter
29
+
30
+ ## When NOT to use this
31
+
32
+ - Cross-face navigation → `drill-down-link`
33
+ - Static content, no user controls needed
34
+
35
+ ## The pattern
36
+
37
+ ```yaml
38
+ variables:
39
+ region:
40
+ label: Region
41
+ description: Filter all charts to this region
42
+ options:
43
+ static: [North, South, East, West]
44
+
45
+ date_range:
46
+ label: Date Range
47
+ input: daterange
48
+ column: orders.order_date
49
+ default: ["2025-01-01", "2025-12-31"]
50
+
51
+ queries:
52
+ monthly:
53
+ description: Monthly revenue filtered by region and date window
54
+ sql: |
55
+ SELECT DATE_TRUNC('month', order_date) AS month,
56
+ SUM(revenue) AS revenue
57
+ FROM orders
58
+ WHERE {{ filter('region', region) }}
59
+ AND {{ filter_date_range('order_date', date_range) }}
60
+ GROUP BY 1
61
+ ORDER BY 1
62
+ ```
63
+
64
+ See `examples/filter-bar-with-variables.yml` for the worked example.
65
+
66
+ ## Variable input types
67
+
68
+ | Input | YAML | Widget |
69
+ |---|---|---|
70
+ | Dropdown (static list) | `options: static: [A, B, C]` | Select element |
71
+ | Date range | `input: daterange` | Two date pickers |
72
+ | Single date | `input: date` | One date picker |
73
+ | Numeric input | `input: number` | Free numeric entry |
74
+ | Range slider | `input: slider` (or `range`), `min:`, `max:`, `step:` | Bounded numeric range |
75
+ | Free text | `input: text` | Text input |
76
+
77
+ ## Filtering helpers in SQL
78
+
79
+ | Helper | Use for |
80
+ |---|---|
81
+ | `{{ filter('col', var) }}` | Single-value dropdown — emits `col = 'val'` or `1=1` when unset |
82
+ | `{{ filter_date_range('col', date_range) }}` | Date range variable |
83
+ | `{{ filter('col', var, '>=') }}` | Numeric threshold with operator |
84
+
85
+ Always use these helpers — never write `WHERE col = '{{ var }}'` directly. The
86
+ helpers are null-safe (emit `1=1` when the variable is unset) and handle quoting
87
+ correctly.
88
+
89
+ ## Common pitfalls
90
+
91
+ | Pitfall | Why it breaks | Fix |
92
+ |---|---|---|
93
+ | Variable name contains a hyphen | Jinja can't parse `{{ my-var }}` | Use underscores: `my_var` |
94
+ | No `default:` on a required variable | Blank widget, query may fail | Add a sensible `default:` value |
95
+ | Scoping variables globally but only one chart needs them | Re-queries all charts | Nest variables + queries + charts in a nested board |
96
+
97
+ ## Worked example
98
+
99
+ See `examples/filter-bar-with-variables.yml` — region dropdown and date
100
+ pickers wired to a sales query. Uses inline data to compile without a
101
+ warehouse; swap `columns/values` for `sql:` when connecting to a live source.
102
+
103
+ ## YAML Reference
104
+
105
+ For syntax and field details: {{ s_yaml_reference_footer }}
@@ -0,0 +1,49 @@
1
+ title: Sales Dashboard with Filters
2
+ description: |
3
+ Filter-bar pattern — region dropdown and date controls wired to queries. Inline data used here; in production, replace with sql: + WHERE {{ filter(...) }}.
4
+
5
+ variables:
6
+ region:
7
+ label: Region
8
+ description: Filter to a single region, or leave blank for all
9
+ options:
10
+ static:
11
+ - North
12
+ - South
13
+ - East
14
+ - West
15
+ start_date:
16
+ label: Start Date
17
+ input: date
18
+ default: "2025-07-01"
19
+ end_date:
20
+ label: End Date
21
+ input: date
22
+ default: "2025-12-31"
23
+ queries:
24
+ monthly_revenue:
25
+ description: Monthly revenue — replace with sql and {{ filter }} for a live source
26
+ columns:
27
+ - month
28
+ - region
29
+ - revenue
30
+ values:
31
+ - ['2025-07-01', 'North', 32000]
32
+ - ['2025-08-01', 'North', 35000]
33
+ - ['2025-09-01', 'North', 38000]
34
+ - ['2025-07-01', 'South', 21000]
35
+ - ['2025-08-01', 'South', 23000]
36
+ - ['2025-09-01', 'South', 26000]
37
+ charts:
38
+ revenue_by_month:
39
+ description: Monthly revenue trend by region
40
+ type: bar
41
+ query: monthly_revenue
42
+ x: month
43
+ y: revenue
44
+ color: region
45
+ title: Monthly Revenue by Region
46
+ style:
47
+ stack: zero
48
+ rows:
49
+ - revenue_by_month