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,786 @@
1
+ # Internal base theme: _base
2
+ # Internal-only root for the built-in theme cascade. Defines all structural
3
+ # defaults (layout, spacing, sizing, chart geometry) but intentionally omits
4
+ # font families and color values — those are supplied by each named theme.
5
+ # Not meant for direct use; extend this via a named theme that fills in
6
+ # font and color.
7
+
8
+ style:
9
+ # Palette role assignments.
10
+ # Open dict: role → palette file name. Resolver resolves role.alias tokens.
11
+ palettes:
12
+ chrome: dft-grays
13
+ negative: negative
14
+ positive: positive
15
+ warning: warning
16
+ category: category-10
17
+ category_dark: category-10-dark
18
+ category_light: category-10-light
19
+ sequence: dft-seq-blue
20
+ diverge: dft-div-blue-red
21
+
22
+ # Top-level theme role shortcuts. Bare alias → role.alias.
23
+ roles:
24
+ ink: chrome.heading
25
+
26
+ # Format aliases — d3 specs resolved by name at render time.
27
+ formats:
28
+ currency: "$,.2f"
29
+ currency_whole: "$,.0f"
30
+ currency_compact: "$~s"
31
+ percent: ".1%"
32
+ percent_whole: ".0%"
33
+ percent_delta: "+.1%"
34
+ compact: "~s"
35
+ integer: ",.0f"
36
+ number: ",.2f"
37
+ date_short: "%-d %b %Y"
38
+
39
+ opacity: 1.0
40
+
41
+ board:
42
+ width: 1200.0
43
+ default_height: 600.0
44
+ min_height: 0.0
45
+ margin: 24.0
46
+ card_padding: 16.0
47
+ card_gap: 8.0
48
+
49
+ font:
50
+ # Body floor 11px. Anchored — referenced by style.text.font.size,
51
+ # style.title.subtitle.font.size, style.variables.font.size below.
52
+ size: &size_body 11
53
+ weight: '400'
54
+ style: normal
55
+ decoration: none
56
+ case: none
57
+ emoji: monochrome
58
+
59
+ border:
60
+ width: 0.0
61
+ radius: 0.0
62
+
63
+ title:
64
+ position:
65
+ anchor: start
66
+ offset: 10
67
+ overflow: truncate
68
+ # Compute heading level from count of titled ancestors (not structural depth).
69
+ # Set to an integer to lock all face titles to a specific H-level (useful for
70
+ # embedded dashboards where H1/H2 are reserved by the outer page).
71
+ level: auto
72
+ font:
73
+ size: 18
74
+ weight: 500
75
+ case: title
76
+ # Tight headline leading. Convention: larger type wants tighter line-height
77
+ # (Bringhurst, Butterick). At ~24px the body 1.5 multiplier reads too airy
78
+ # between wrapped lines; 1.1 sits in the standard 1.05-1.15 display range.
79
+ line_height: 1.1
80
+ # H1–H6 font-size ramp, indexed by face.level - 1.
81
+ # Paired with width_offsets below — chart_title_spec computes
82
+ # effective_level = clamp(face.level + 1 + width_offset, 1, 6)
83
+ # then returns sizes[effective_level - 1].
84
+ sizes:
85
+ - 24
86
+ - 18
87
+ - 14
88
+ - 14
89
+ - 11
90
+ - 11
91
+ # Additive level offsets by card pixel width. Added to the base heading
92
+ # level before indexing the sizes ramp. Tier boundaries (<360, <560, <1100,
93
+ # ≥1100) live in typography.py as engine constants.
94
+ # Face headers (level=1) are intentionally larger than chart titles (level=2)
95
+ # at medium/wide — H1 > H2 is semantically correct for a hierarchy of headings.
96
+ width_offsets:
97
+ tiny: 3
98
+ narrow: 1
99
+ medium: 0
100
+ wide: 0
101
+ min_height: 24.0
102
+ subtitle:
103
+ font:
104
+ size: *size_body
105
+ weight: 400
106
+ case: sentence
107
+
108
+ charts:
109
+ aspect_ratio: 1.5
110
+ min_height: 150.0
111
+ max_height: 400.0
112
+ padding:
113
+ left: 0.0
114
+ right: 0.0
115
+ top: 0.0
116
+ bottom: 0.0
117
+ animation_duration: 500.0
118
+ border:
119
+ width: 0.0
120
+ color: transparent
121
+ radius: 0.0
122
+
123
+ axis:
124
+ domain:
125
+ visible: false
126
+ width: 1
127
+ ticks:
128
+ visible: false
129
+ size: 6 # default tick size cascades to all axes; matches VL's geometric idiom
130
+ grid:
131
+ visible: true
132
+ opacity: 1
133
+ width: 1.5
134
+ zero:
135
+ width: 2
136
+ label:
137
+ font:
138
+ size: &size_label 11
139
+ padding: 6
140
+ overlap: "smart" # VL adaptive default: per-scale dispatch (omits labelOverlap from spec)
141
+ separation: 16 # 16px minimum gap between adjacent labels
142
+ # bound, flush, offset, line_height, anchor intentionally absent — VL per-axis defaults apply.
143
+ title:
144
+ font:
145
+ size: 0
146
+ weight: &weight_bold 600
147
+ case: title
148
+ padding: 10
149
+ # fill is semantically only active on axis_x (ordinal bucketed-time);
150
+ # required on all AxisStyle instances since the model enforces it.
151
+ fill: "null"
152
+
153
+ axis_x:
154
+ # Only intentional differences from `axis` — everything else cascades.
155
+ grid:
156
+ width: 1 # lighter weight than horizontal grid (axis.grid.width=1.5)
157
+ ticks:
158
+ visible: true
159
+ width: 1
160
+ label:
161
+ # Fit-based tilt ladder for overlap=smart on discrete x-axes.
162
+ # Descending; picker chooses the first angle whose labels fit. Falls
163
+ # through to -90 + overlap="parity" when no angle fits.
164
+ tilt_increments: [0, -30, -45, -60, -90]
165
+ title:
166
+ font:
167
+ size: 0 # x-axis title hidden by default; charts opt back in via style.axis_x.title
168
+ scale:
169
+ padding: 0 # band/point padding around categorical x-axis values
170
+ offset: 1
171
+ # Engine fills missing time buckets on ordinal bucketed-time x-axes.
172
+ # Bar/line/area inherit this global default. Scatter pins null under
173
+ # style.charts.scatter.axis_x (layer 3.5) — scatter should never zero-fill or interpolate.
174
+ fill: "null"
175
+
176
+ axis_y:
177
+ # Y-specific tweaks only — orientation and tick width. Empty
178
+ # grid/domain/label/title cascade from the canonical `axis`
179
+ # block via `_fill_axis` at render time, so face-level patches on
180
+ # `style.axis.*` reach axis_y through the same path.
181
+ # "auto" → "right" by default; flips to "left" when endpoint labels are
182
+ # on the right edge (line charts with style.line.endpoint_labels.visible).
183
+ orient: auto
184
+ categorical_orient: left
185
+ ticks:
186
+ width: 1.5
187
+ fill: "null"
188
+
189
+ axis_quantitative:
190
+ # Quantitative-specific tweaks only — tabular font on numeric labels and
191
+ # tick width matching axis_y. Colors cascade from `axis` via `_fill_axis`.
192
+ ticks:
193
+ width: 1.5
194
+ label:
195
+ font: {}
196
+ fill: "null"
197
+ # Default compact SI format for quantitative axes (6M, 1.5B, etc).
198
+ # Authors override per-chart via chart.format or style.axis_y.format.
199
+ format: "~s"
200
+
201
+ tooltip:
202
+ format: ",.2f"
203
+
204
+ legend:
205
+ orient: right
206
+ direction: vertical
207
+ label:
208
+ font:
209
+ size: *size_label
210
+ padding: 0.0
211
+ title:
212
+ font:
213
+ size: 12
214
+ weight: *weight_bold
215
+ case: title
216
+ padding: 0.0
217
+ interactive_legend: true
218
+
219
+ view:
220
+ continuous_width: 360
221
+ continuous_height: 300
222
+ discrete_width: 360
223
+ discrete_height: 360
224
+ # No bounding box around the plot area by default. Themes can opt back
225
+ # in by setting stroke to a colour token.
226
+ stroke: null
227
+
228
+ autosize:
229
+ type: fit
230
+ contains: padding
231
+ resize: true
232
+
233
+ table:
234
+ outer_padding: 0.0
235
+ bottom_padding: 0.0
236
+ pagination:
237
+ enabled: true
238
+ page_size: 20
239
+ text_baseline_offset: 4.0
240
+ title_baseline_offset: 16.0
241
+ title_subtitle_gap: 14.0
242
+ subtitle:
243
+ font:
244
+ size: 15
245
+ border:
246
+ width: 1.0
247
+ radius: 4.0
248
+ column_layout:
249
+ default_width: 100.0
250
+ cell_padding: 8.0
251
+ width_similarity_threshold: 0.8
252
+ title_row:
253
+ height: 40.0
254
+ more_rows:
255
+ font:
256
+ size: 11.0
257
+ paginator:
258
+ # Right-aligned chevrons + page numbers below the table. Colours come
259
+ # from the scaffold gray ramp so the control reads as foreground text
260
+ # rather than as a divider.
261
+ font:
262
+ size: 11.0
263
+ weight_active: 600
264
+ weight_inactive: 400
265
+ weight_chevron: 800 # heavier than the active page so chevrons read as affordances
266
+ item_width: 18.0 # per-item slot width (hit-rect is narrower; see render code)
267
+ empty_state:
268
+ font:
269
+ size: 14.0
270
+ spark:
271
+ padding:
272
+ top: 4.0
273
+ right: 2.0
274
+ bottom: 4.0
275
+ left: 2.0
276
+ empty:
277
+ inset_x: 4.0
278
+ stroke:
279
+ width: 1.0
280
+ dasharray: '4 2'
281
+ single_value:
282
+ inset_x: 4.0
283
+ marker_radius: 2.5
284
+ columns:
285
+ gap: 1.0
286
+ padding: 2.0
287
+ min_bar_height: 1.0
288
+ border:
289
+ width: 0.0
290
+ color: transparent
291
+ radius: 1.0
292
+ bar:
293
+ default_max: 100.0
294
+ border:
295
+ width: 0.0
296
+ color: transparent
297
+ radius: 0.0
298
+ label:
299
+ inset_x: 4.0
300
+ # Halo knockout: tracks theme canvas so the label backdrop reads
301
+ # against any theme background.
302
+ fill: theme.background
303
+ fill_opacity: 0.9
304
+ min_size: 9.0
305
+ height_offset: 5.0
306
+ area:
307
+ fill_opacity: 0.3
308
+ # Universal default: header rule only. No header fill, no row
309
+ # striping — those compete with cell-background value encoding
310
+ # (heatmap fills, threshold alerts). The rule is the single
311
+ # separator between header and body. Summary/total rules remain
312
+ # on via row typing.
313
+ header:
314
+ # UX-default: header row shown. Authors flip to false for series-keyed
315
+ # tables (e.g. donut-attached) where the column meanings are obvious
316
+ # from context.
317
+ visible: true
318
+ height: 28.0
319
+ overflow: wrap-two
320
+ rule:
321
+ width: 1
322
+ continuous: true
323
+ font:
324
+ # Semibold column headers. Setting weight in theme YAML keeps the
325
+ # cascade authoritative so themes can tune without touching the
326
+ # render layer.
327
+ weight: '600'
328
+ case: title
329
+ wrap: true
330
+ symbol_mode: anchors
331
+ row:
332
+ height: 24.0
333
+ rule:
334
+ width: 0.0
335
+ continuous: false
336
+ roles:
337
+ summary:
338
+ rule_width: 1.0
339
+ total:
340
+ rule_width: 0.0
341
+
342
+ palette: category-10
343
+
344
+ # Global mark defaults — tier-1 of the three-tier mark cascade.
345
+ # Family-specific overrides live under style.charts.<family>.marks.*
346
+ # Face-local overrides live under face.style.marks.* (tier-3).
347
+ marks:
348
+ bar:
349
+ border:
350
+ width: 1
351
+ # Halo knockout: tracks the theme's canvas so adjacent bars separate
352
+ # cleanly on any theme background. Resolved at theme-compile time
353
+ # (see ``_resolve_self_tokens`` in models/style/resolved.py).
354
+ color: theme.background
355
+ radius: 2
356
+ # Bar width is set at the mark layer (band_width = 0.8 → 80% of band
357
+ # step) so it works on both ordinal and temporal x-scales. The band
358
+ # scale gutter (padding) stays at 0 so the two layers don't compound.
359
+ padding: 0
360
+ band_width: 0.8
361
+ size: 20.0
362
+ line:
363
+ stroke:
364
+ width: 3.0
365
+ cap: "round"
366
+ join: "round"
367
+ curve: "linear"
368
+ halo_multiplier: 2.0
369
+ area:
370
+ # Soft tinted fill on a cream-knockout undercoat (when multi-series).
371
+ # The stroke is the colored top edge; values overlap rather than stack
372
+ # so each series reads as its own silhouette.
373
+ opacity: 0.16
374
+ stroke:
375
+ width: 3.0
376
+ # Halo: background-color stroke drawn behind the area's top-edge line.
377
+ halo_multiplier: 2.0
378
+ point:
379
+ size: 0
380
+ opacity: 1
381
+ filled: true
382
+ fill: theme.background
383
+ slice:
384
+ # gap 0 lets the stroke (canvas-color knockout) be the only
385
+ # visible separator between slices.
386
+ gap: 0
387
+ corner_radius: 3
388
+ # Canvas-coupling: ``theme.background`` is a self-reference token
389
+ # resolved at theme-compile time (see ``_resolve_self_tokens`` in
390
+ # models/style/resolved.py).
391
+ stroke:
392
+ color: theme.background
393
+ width: 3
394
+ # Round the inner-vertex spike on pies (acute miter at center where
395
+ # many radial edges converge).
396
+ join: "round"
397
+ # Per-slice labels opt in via ``chart.labels: { template, where? }``.
398
+ labels:
399
+ offset: 6
400
+ block_height: 28
401
+ line_height: 14
402
+ font:
403
+ size: 14
404
+ weight: '500'
405
+ text:
406
+ font:
407
+ size: *size_label
408
+ align: center
409
+ rule:
410
+ stroke:
411
+ width: 1
412
+ rect:
413
+ stroke: null
414
+ circle:
415
+ opacity: 1
416
+ square:
417
+ opacity: 1
418
+ tick:
419
+ stroke:
420
+ width: 2
421
+ trail:
422
+ stroke:
423
+ width: 2
424
+ geoshape:
425
+ # Halo knockout between regions — tracks theme canvas so the borders
426
+ # disappear into the page on any theme.
427
+ stroke:
428
+ color: theme.background
429
+ width: 0.5
430
+ image:
431
+ aspect: true
432
+ boxplot:
433
+ extent: min-max
434
+ errorbar:
435
+ ticks: true
436
+ errorband:
437
+ opacity: 0.3
438
+
439
+ bar:
440
+ endpoint_labels:
441
+ visible: false
442
+ label_offset: 6.0
443
+ axis_x:
444
+ grid:
445
+ visible: false
446
+ ticks:
447
+ visible: false
448
+ label:
449
+ padding: 6.0
450
+
451
+ line:
452
+ endpoint_labels:
453
+ visible: false
454
+ label_offset: 6.0
455
+
456
+ area:
457
+ # Authors who want a stacked area chart opt in via ``chart.stack: "zero"``.
458
+ stack: false
459
+ endpoint_labels:
460
+ visible: false
461
+ label_offset: 6.0
462
+ axis_y:
463
+ ticks:
464
+ visible: true
465
+
466
+ histogram:
467
+ bin_maxbins: 20
468
+ # Histogram bars have no visible border (override the global marks.bar.border).
469
+ marks:
470
+ bar:
471
+ border:
472
+ width: 0.0
473
+ color: transparent
474
+ radius: 2.0
475
+
476
+ kpi:
477
+ # KPI uses the tabular sans by default — digits aligned across cards
478
+ # in a row matter more than text-prose readability for a value card.
479
+ # The editorial parent theme overrides `kpi.value.font.family` to a
480
+ # serif value while keeping support/affixes on the tabular sans
481
+ # (see `themes/editorial.yaml`).
482
+ # Weight 500 (heading-tier) for the whole card text — the per-tier
483
+ # hierarchy is carried by size + color, not weight. This cascades
484
+ # into every slot (value, label, affix, glyph) unless overridden.
485
+ font:
486
+ size: 11
487
+ weight: 500
488
+ value:
489
+ font:
490
+ size: 24
491
+ label:
492
+ font:
493
+ size: 11
494
+ case: title
495
+ affix:
496
+ font:
497
+ size: 11
498
+ glyph:
499
+ # Indicator glyphs (▲▼●) sit next to the value as markers, not
500
+ # second headlines — drawn at body/narrow tier so a triangle's
501
+ # visual mass doesn't compete with the digits.
502
+ font:
503
+ size: 11
504
+ min_card_width: 100.0
505
+ default_width: 300.0
506
+ default_height: 48.0
507
+ # Inner inset. Vertical 4 keeps the three text slots (label / value /
508
+ # support) close enough to read as one unit in the dense default KPI
509
+ # card height (48px). Horizontal 0 lets KPI text sit flush with the
510
+ # card content origin, so it aligns with page headers, text blocks,
511
+ # and chart content above/below — all of which render at the same
512
+ # card_padding offset applied by the layout wrapper.
513
+ # Trade-off: KPI text no longer aligns with a sibling table's first
514
+ # cell content (table.columns.cell_padding 8). Override left/right
515
+ # back to 8.0 in a derived theme if KPI↔table row alignment matters
516
+ # more than KPI↔header alignment for that brand.
517
+ content_padding:
518
+ top: 4.0
519
+ right: 0.0
520
+ bottom: 4.0
521
+ left: 0.0
522
+ border:
523
+ width: 0.0
524
+ color: transparent
525
+ radius: 0.0
526
+ # Semantic tone palette for KPI value/glyph and support rows.
527
+ # Three tones only: positive, negative, warning. Tokens resolved via
528
+ # palette role dispatch (positive.solid → palettes.positive → positive.yml).
529
+ tones:
530
+ positive: positive.solid
531
+ negative: negative.solid
532
+ warning: warning.solid
533
+
534
+ spark_bar:
535
+ bar:
536
+ height: 18.0
537
+ padding: 2.0
538
+ label:
539
+ visible: true
540
+ width: 80.0
541
+ count:
542
+ visible: true
543
+ width: 50.0
544
+ max_bars: 10
545
+ font:
546
+ size: 11.0
547
+ subtitle:
548
+ font:
549
+ size: 10
550
+ border:
551
+ width: 0.0
552
+ color: transparent
553
+ radius: 2.0
554
+
555
+ # Attached chart.data_table primitive (spec §4, ADR-002).
556
+ # Universal tier-1 defaults. Per-chart-type tier-2 lives nested under
557
+ # bar/line/area as data_table: {...}.
558
+ data_table:
559
+ font:
560
+ size: 11
561
+ # No divider rule by default — strip flows directly from the x-axis.
562
+ # Themes that want a visible separator can set width > 0 and color.
563
+ divider:
564
+ width: 0
565
+ continuous: true
566
+ row:
567
+ padding:
568
+ vertical: 2.0
569
+ horizontal: 6.0
570
+ rule:
571
+ width: 0.0
572
+ continuous: true
573
+ label:
574
+ font:
575
+ weight: '500'
576
+ case: title
577
+ number_align: right
578
+ padding_top: 8
579
+ padding_bottom: 4
580
+ # Always reserve 2 axis-label lines above the strip so yearly boundary
581
+ # ticks (e.g. ['Jan', '2024']) don't overlap the strip top edge. Themes
582
+ # that use a year-only label cadence (single line always) can set 1.
583
+ label_max_lines: 2
584
+ # Pre-launch intentional flip: "top" is the universal default.
585
+ # Faces that require below-plot layout set position: bottom explicitly.
586
+ position: top
587
+
588
+ # build_patch_model_ext-based types: TYPE_CHECKING stub shows required fields from
589
+ # _ChartStyleBase, so mypy can't verify zero-arg construction. These stay required.
590
+ scatter:
591
+ # Scatter always breaks at missing buckets (honest dots). Pinned here so a
592
+ # future change to style.charts.axis_x.fill does not connect gaps on point marks.
593
+ # Bar is intentionally NOT pinned: an author who opts into fill: linear on a bar
594
+ # chart is accepting that synthesized bars look identical to real query rows.
595
+ # Line/area inherit the global default and are the primary use case for linear/curve.
596
+ axis_x:
597
+ fill: "null"
598
+ marks:
599
+ point:
600
+ # Global marks.point.size is 0 (hides line-chart point overlays). Scatter
601
+ # needs visible dots — 60 sq px ≈ 4.4px radius, a clean unobtrusive dot.
602
+ size: 60
603
+
604
+ pie:
605
+ aspect_ratio: 1.0
606
+ # Donut center total — the big number on top, smaller caption below.
607
+ # Authors opt in via ``chart.total: { label, format }``; this slot
608
+ # only contributes typography.
609
+ total:
610
+ value:
611
+ font:
612
+ size: 18
613
+ weight: '600'
614
+ label:
615
+ font:
616
+ size: 11
617
+
618
+ # Choropleth (color-encoded) map — renamed from 'map' in ADR-015.
619
+ # geo_source is a chart-root channel (chart.geo_source), not a style field.
620
+ geoshape:
621
+ aspect_ratio: 1.2
622
+ projection:
623
+ type: albersUsa
624
+ color_scheme: blues
625
+
626
+ # Point map (scatter over geography) — renamed from 'geoshape' in ADR-015.
627
+ point_map:
628
+ aspect_ratio: 1.2
629
+ projection:
630
+ type: mercator
631
+
632
+ heatmap:
633
+ cell_padding: 2.0
634
+ color_scheme: blues
635
+
636
+ # See scatter comment above for why these three stay as {}.
637
+ boxplot: {}
638
+ errorbar: {}
639
+ errorband: {}
640
+
641
+ # Series-label primitive. Typography for any text mark that names a
642
+ # data series — endpoint labels, direct stack labels,
643
+ # slice callouts. Placement is family-specific; typography is shared.
644
+ # font.family + font.weight cascade from charts.font; font.color is
645
+ # filled per-series by the renderer's dark-companion palette pairing.
646
+ series_label:
647
+ font:
648
+ size: 14
649
+
650
+ callout:
651
+ background: negative.bg
652
+ padding: 12.0
653
+ section_gap: 10.0
654
+ border:
655
+ width: 1.0
656
+ color: negative.border
657
+ radius: 4.0
658
+ title:
659
+ font:
660
+ color: negative.solid
661
+ size: 13.0
662
+ weight: bold
663
+ case: title
664
+ y_offset: 0.0
665
+ message:
666
+ font:
667
+ color: negative.text
668
+ size: 11.0
669
+ y_offset: 0.0
670
+
671
+
672
+ text:
673
+ font:
674
+ size: *size_body
675
+ # Body leading. Convention: 1.4-1.55 for screen reading (Bringhurst ~1.5,
676
+ # NYT ~1.5, Medium ~1.58). 1.5 sits at the editorial standard.
677
+ line_height: 1.5
678
+ align: left
679
+
680
+ layout:
681
+ rows:
682
+ gap: 8.0
683
+ cols:
684
+ gap: 20.0
685
+ grid:
686
+ columns: 24
687
+ gap: 20.0
688
+ tabs:
689
+ bar_height: 40.0
690
+ active_weight: '600'
691
+ inactive_weight: '400'
692
+ title_baseline_offset: 5.0
693
+ font:
694
+ size: 14.0
695
+ border:
696
+ width: 0.0
697
+ color: transparent
698
+ radius: 4.0
699
+ details:
700
+ summary_height: 36.0
701
+ arrow:
702
+ x: 14.0
703
+ font:
704
+ size: 13.0
705
+ label_x: 32.0
706
+ text_baseline_offset: 5.0
707
+ content_y_offset: 4.0
708
+ font:
709
+ size: 14.0
710
+ border:
711
+ width: 0.0
712
+ color: transparent
713
+ radius: 4.0
714
+
715
+ variables:
716
+ visible: true
717
+ # title-inline is the structural default: face title left, variable controls
718
+ # right, baselines aligned on one horizontal band. Untitled faces fall back
719
+ # to a standalone variables band (render path in faces.py guards on
720
+ # `_face_uses_title_inline_band`, which requires both title and variables).
721
+ position: title-inline
722
+ title_inline_title_max_width: 0.0
723
+ gap: 10.0
724
+ label_position: inline
725
+ line_height: 24.0
726
+ padding: 4.0
727
+ container_height: 36.0
728
+ container_padding: 8.0
729
+ control_gap: 8.0
730
+ # Subtle off-card surface for the daterange popover's preset rail.
731
+ # Warm-canvas themes (cream) override to dft-creams.surface-subtle
732
+ # so the rail reads as the cream canvas peeking past the white popover.
733
+ popover_rail_background: dft-grays.surface-subtle
734
+ font:
735
+ size: *size_body
736
+ label:
737
+ font:
738
+ weight: 500
739
+ case: title
740
+ value:
741
+ font:
742
+ weight: 400
743
+ numeric_variant: tabular-nums
744
+ placeholder:
745
+ # Unselected/hint text reads lighter than selected-value text so the
746
+ # variable strip is scannable. `disabled` is the ramp ladder step
747
+ # semantically for hint / not-your-data text.
748
+ font:
749
+ color: dft-grays.disabled
750
+ border:
751
+ width: 0.0
752
+ radius: 4.0
753
+ input:
754
+ height: 32.0
755
+ # transparent: lets faces paint a continuous header band that shows
756
+ # through the variables strip; faces (or sibling themes) that want
757
+ # an opaque input bg should set this explicitly.
758
+ background: transparent
759
+ padding:
760
+ top: 4.0
761
+ right: 8.0
762
+ bottom: 4.0
763
+ left: 8.0
764
+ widths:
765
+ text: 150.0
766
+ number: 80.0
767
+ range: 120.0
768
+ slider_value_min: 30.0
769
+ checkbox: 16.0
770
+ # Chip is icon + compact label (e.g. "9–28 Apr 2026"); not a full text input.
771
+ daterange: 168.0
772
+ range:
773
+ default_min: 0.0
774
+ default_max: 100.0
775
+ default_step: 1.0
776
+ border:
777
+ width: 1.0
778
+ radius: 4.0
779
+
780
+ placeholder:
781
+ opacity: 0.4
782
+ overlay:
783
+ text: 'add data'
784
+ font:
785
+ size: 16
786
+ weight: 500