dataface 0.3.2.dev22__py3-none-any.whl → 0.3.2.dev111__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 (185) hide show
  1. dataface/__init__.py +70 -23
  2. dataface/agent_api/__init__.py +162 -68
  3. dataface/agent_api/_paths.py +9 -3
  4. dataface/agent_api/docs/yaml-reference.md +240 -106
  5. dataface/agent_api/init.py +1 -1
  6. dataface/agent_api/project_session.py +2 -1
  7. dataface/agent_api/serve.py +115 -0
  8. dataface/ai/agent.py +28 -2
  9. dataface/cli/_project.py +100 -1
  10. dataface/cli/commands/board_artifact.py +5 -2
  11. dataface/cli/commands/describe.py +7 -3
  12. dataface/cli/commands/docs.py +12 -3
  13. dataface/cli/commands/init.py +7 -14
  14. dataface/cli/commands/inspect.py +6 -1
  15. dataface/cli/commands/mcp_init.py +23 -43
  16. dataface/cli/commands/migrate.py +8 -3
  17. dataface/cli/commands/query.py +11 -8
  18. dataface/cli/commands/render.py +20 -9
  19. dataface/cli/commands/search.py +8 -2
  20. dataface/cli/commands/serve.py +26 -76
  21. dataface/cli/commands/skills_init.py +2 -19
  22. dataface/cli/commands/validate.py +7 -2
  23. dataface/cli/filesystem_project.py +5 -4
  24. dataface/cli/main.py +2 -19
  25. dataface/core/__init__.py +73 -28
  26. dataface/core/{compile/colors.py → colors.py} +20 -5
  27. dataface/core/compile/compiler.py +97 -34
  28. dataface/core/compile/data_table.py +7 -2
  29. dataface/core/compile/enrich.py +18 -44
  30. dataface/core/compile/face_warnings.py +46 -8
  31. dataface/core/compile/format.py +47 -1
  32. dataface/core/compile/inherit_graph.py +3 -3
  33. dataface/core/compile/inherit_registry.yaml +1 -1
  34. dataface/core/compile/migrations.py +112 -9
  35. dataface/core/compile/models/chart/normalized/kpi.py +0 -4
  36. dataface/core/compile/models/chart/resolved/_base.py +28 -10
  37. dataface/core/compile/models/chart/resolved/callout.py +2 -3
  38. dataface/core/compile/models/chart/resolved/kpi.py +7 -3
  39. dataface/core/compile/models/chart/resolved/table.py +16 -2
  40. dataface/core/compile/models/markers.py +1 -1
  41. dataface/core/compile/models/primitives.py +175 -2
  42. dataface/core/compile/models/source.py +5 -5
  43. dataface/core/compile/models/style/authored/__init__.py +32 -8
  44. dataface/core/compile/models/style/authored/_base.py +126 -69
  45. dataface/core/compile/models/style/authored/table.py +61 -3
  46. dataface/core/compile/models/style/resolved/__init__.py +12 -2
  47. dataface/core/compile/models/style/resolved/_base.py +142 -57
  48. dataface/core/compile/models/style/resolved/_cartesian.py +6 -11
  49. dataface/core/compile/models/style/resolved/_cascade.py +141 -54
  50. dataface/core/compile/models/style/resolved/area.py +1 -1
  51. dataface/core/compile/models/style/resolved/bar.py +1 -1
  52. dataface/core/compile/models/style/resolved/line.py +1 -1
  53. dataface/core/compile/models/style/resolved/scatter.py +3 -2
  54. dataface/core/compile/models/style/theme/__init__.py +36 -14
  55. dataface/core/compile/models/style/theme/_chart_base.py +17 -9
  56. dataface/core/compile/models/style/theme/axis.py +432 -312
  57. dataface/core/compile/models/style/theme/charts.py +10 -6
  58. dataface/core/compile/models/style/theme/kpi.py +2 -1
  59. dataface/core/compile/models/style/theme/page.py +5 -2
  60. dataface/core/compile/models/style/theme/table.py +2 -2
  61. dataface/core/compile/models/vega_lite/config.py +1 -1
  62. dataface/core/compile/normalize_charts.py +6 -2
  63. dataface/core/compile/normalize_queries.py +21 -7
  64. dataface/core/compile/resolve/__init__.py +2 -0
  65. dataface/core/compile/resolve/_axes.py +147 -44
  66. dataface/core/compile/resolve/_channels.py +1 -1
  67. dataface/core/compile/resolve/_dispatch.py +1 -1
  68. dataface/core/compile/resolve/_domain.py +49 -32
  69. dataface/core/compile/resolve/_kwargs.py +39 -12
  70. dataface/core/compile/resolve/_marks.py +8 -3
  71. dataface/core/compile/resolve/_palette.py +7 -3
  72. dataface/core/compile/resolve/_table.py +124 -33
  73. dataface/core/compile/resolve/area.py +48 -18
  74. dataface/core/compile/resolve/bar.py +245 -64
  75. dataface/core/compile/resolve/geo.py +10 -3
  76. dataface/core/compile/resolve/heatmap.py +16 -8
  77. dataface/core/compile/resolve/line.py +35 -12
  78. dataface/core/compile/resolve/pie.py +4 -1
  79. dataface/core/compile/resolve/pie_attachment.py +1 -1
  80. dataface/core/compile/resolve/scatter.py +25 -13
  81. dataface/core/compile/resolve/simple.py +25 -2
  82. dataface/core/compile/schema_renderers/prompt.py +1 -1
  83. dataface/core/compile/schema_renderers/textmate_grammar.py +8 -1
  84. dataface/core/compile/source_map.py +211 -28
  85. dataface/core/compile/style_cascade.py +126 -55
  86. dataface/core/compile/yaml_error_formatter.py +1 -1
  87. dataface/core/connections.py +10 -3
  88. dataface/core/dashboard.py +24 -18
  89. dataface/core/defaults/themes/_base.yaml +49 -39
  90. dataface/core/defaults/themes/cream.yaml +4 -4
  91. dataface/core/defaults/themes/diagnostics-title-baseline.yaml +1 -1
  92. dataface/core/defaults/themes/diagnostics-title-color-extreme.yaml +1 -1
  93. dataface/core/defaults/themes/diagnostics-title-font-extreme.yaml +1 -1
  94. dataface/core/defaults/themes/diagnostics-title-size-extreme.yaml +1 -1
  95. dataface/core/defaults/themes/diagnostics-title-weight-extreme.yaml +1 -1
  96. dataface/core/defaults/themes/editorial.yaml +6 -6
  97. dataface/core/defaults/themes/neon.yaml +15 -8
  98. dataface/core/defaults/themes/plain.yaml +6 -4
  99. dataface/core/defaults/themes/stark.yaml +16 -7
  100. dataface/core/defaults/themes/vivid.yaml +15 -8
  101. dataface/core/diagnostics/__init__.py +2 -2
  102. dataface/core/diagnostics/codes_compile.py +13 -31
  103. dataface/core/diagnostics/codes_execute.py +79 -0
  104. dataface/core/diagnostics/codes_render.py +87 -28
  105. dataface/core/diagnostics/diagnostic.py +30 -0
  106. dataface/core/diagnostics/hints.py +19 -0
  107. dataface/core/dialects/base.py +17 -0
  108. dataface/core/dialects/postgres.py +14 -0
  109. dataface/core/dialects/redshift.py +5 -0
  110. dataface/core/execute/__init__.py +59 -14
  111. dataface/core/execute/adapters/dbt_adapter.py +4 -1
  112. dataface/core/execute/adapters/dbt_adapter_factory.py +19 -0
  113. dataface/core/execute/adapters/dbt_utils.py +84 -20
  114. dataface/core/execute/adapters/postgres_connection_manager.py +48 -0
  115. dataface/core/execute/adapters/sql_adapter.py +72 -4
  116. dataface/core/execute/dbt_jinja.py +65 -10
  117. dataface/core/execute/executor.py +69 -16
  118. dataface/core/font_measure.py +28 -0
  119. dataface/core/fonts.py +8 -5
  120. dataface/core/inspect/__init__.py +46 -6
  121. dataface/core/project.py +13 -1
  122. dataface/core/render/chart/data_table_attachment.py +14 -12
  123. dataface/core/render/chart/emitters/_cartesian.py +21 -18
  124. dataface/core/render/chart/emitters/_channels.py +56 -8
  125. dataface/core/render/chart/emitters/_label_overlap.py +18 -15
  126. dataface/core/render/chart/emitters/_measured_label_padding.py +4 -4
  127. dataface/core/render/chart/emitters/area.py +3 -3
  128. dataface/core/render/chart/emitters/bar.py +60 -35
  129. dataface/core/render/chart/emitters/geo.py +8 -13
  130. dataface/core/render/chart/emitters/heatmap.py +20 -26
  131. dataface/core/render/chart/emitters/line.py +2 -2
  132. dataface/core/render/chart/emitters/scatter.py +7 -30
  133. dataface/core/render/chart/features/baseline.py +22 -9
  134. dataface/core/render/chart/features/endpoint_labels.py +55 -32
  135. dataface/core/render/chart/features/mirror_axis.py +12 -9
  136. dataface/core/render/chart/features/value_labels.py +1 -1
  137. dataface/core/render/chart/kpi.py +11 -90
  138. dataface/core/render/chart/presentation.py +6 -8
  139. dataface/core/render/chart/rendering.py +3 -12
  140. dataface/core/render/chart/session.py +10 -0
  141. dataface/core/render/chart/spec.py +3 -0
  142. dataface/core/render/chart/spec_builders.py +18 -18
  143. dataface/core/render/chart/table.py +81 -36
  144. dataface/core/render/chart/table_support.py +2 -53
  145. dataface/core/render/chart/time_unit_detect.py +3 -2
  146. dataface/core/render/chart/translate.py +82 -44
  147. dataface/core/render/chart/type_inference.py +45 -25
  148. dataface/core/render/chart/validation.py +91 -0
  149. dataface/core/render/chart/vega_lite.py +30 -11
  150. dataface/core/render/chart/vl_field_maps.py +111 -76
  151. dataface/core/render/converters/chart.py +16 -6
  152. dataface/core/render/faces.py +3 -2
  153. dataface/core/render/fonts/DFTSerifOldstyleProportional-Regular.woff2 +0 -0
  154. dataface/core/render/fonts/DFTSerifOldstyleTabular-Regular.woff2 +0 -0
  155. dataface/core/render/fonts/SOURCE_CODE_PRO_LICENSE.txt +93 -93
  156. dataface/core/render/fonts/_font_face.css +10 -0
  157. dataface/core/render/layout_sizing.py +267 -238
  158. dataface/core/render/numeral_expr.py +80 -0
  159. dataface/core/render/warnings/bar_band_width_too_narrow.py +64 -6
  160. dataface/core/render/warnings/layered_chart_shared_y_axis_scale_mismatch.py +25 -3
  161. dataface/core/render/warnings/likely_currency_or_percent_missing_formatter.py +12 -6
  162. dataface/core/render/warnings/palette_unsupported.py +6 -0
  163. dataface/core/render/warnings/pie_dominant_segment.py +1 -0
  164. dataface/core/render/warnings/pie_too_many_segments.py +1 -0
  165. dataface/core/render/warnings/point_map_out_of_projection.py +1 -0
  166. dataface/core/render/warnings/query_returned_zero_rows.py +1 -0
  167. dataface/core/render/warnings/redundant_encoding.py +20 -1
  168. dataface/core/render/warnings/registry.py +7 -3
  169. dataface/core/render/warnings/temporal_single_point.py +1 -0
  170. dataface/core/render/warnings/too_many_color_categories.py +1 -0
  171. dataface/core/render/warnings/too_many_x_categories.py +18 -2
  172. dataface/core/render/warnings/value_labels_crowd_width.py +9 -0
  173. dataface/core/render/warnings/y_encoding_mostly_null.py +1 -0
  174. dataface/core/render_format.py +18 -0
  175. dataface/core/text/format_d3.py +56 -0
  176. dataface/core/text/numeral_scale.py +218 -0
  177. dataface/core/utils.py +103 -10
  178. dataface/data/schemas/board-resolved/board-resolved.schema.json +9487 -7978
  179. dataface/data/schemas/yaml/0.3.2.json +1 -0
  180. dataface/data/schemas/yaml/manifest.json +7 -0
  181. {dataface-0.3.2.dev22.dist-info → dataface-0.3.2.dev111.dist-info}/METADATA +1 -1
  182. {dataface-0.3.2.dev22.dist-info → dataface-0.3.2.dev111.dist-info}/RECORD +185 -177
  183. {dataface-0.3.2.dev22.dist-info → dataface-0.3.2.dev111.dist-info}/WHEEL +0 -0
  184. {dataface-0.3.2.dev22.dist-info → dataface-0.3.2.dev111.dist-info}/entry_points.txt +0 -0
  185. {dataface-0.3.2.dev22.dist-info → dataface-0.3.2.dev111.dist-info}/licenses/LICENSE +0 -0
@@ -28,8 +28,12 @@ from dataface.core.compile.models.primitives import (
28
28
  SpacingValues,
29
29
  )
30
30
  from dataface.core.compile.models.style.authored import (
31
- AxisStylePatch,
31
+ AxisXStylePatch,
32
+ AxisYStylePatch,
33
+ BandAxisStylePatch,
34
+ BaseAxisStylePatch,
32
35
  PaginationConfig,
36
+ QuantitativeAxisStylePatch,
33
37
  )
34
38
  from dataface.core.compile.models.style.resolved.callout import (
35
39
  ResolvedCalloutElementStyle,
@@ -38,8 +42,10 @@ from dataface.core.compile.models.style.resolved.callout import (
38
42
  from dataface.core.compile.models.style.theme import (
39
43
  AreaChartStyle,
40
44
  AxisMirrorStyle,
41
- AxisStyle,
45
+ AxisXStyle,
46
+ AxisYStyle,
42
47
  BarChartStyle,
48
+ BaseAxisStyle,
43
49
  BoardStyle,
44
50
  DataTableStyle,
45
51
  FooterStyle,
@@ -57,7 +63,7 @@ from dataface.core.compile.models.style.theme import (
57
63
  PieChartStyle,
58
64
  PlaceholderStyle,
59
65
  PointMapChartStyle,
60
- ScaleStyle,
66
+ QuantitativeAxisStyle,
61
67
  ScatterChartStyle,
62
68
  SeriesLabelStyle,
63
69
  SparkBarChartStyle,
@@ -76,6 +82,72 @@ from dataface.core.compile.models.style.theme import (
76
82
  _VLConfig = dict[str, Any]
77
83
 
78
84
 
85
+ # ── Resolved scale classes ────────────────────────────────────────────────────
86
+ # Pydantic BaseModels (not dataclasses) — keeps map_fields(scale, FIELD_MAP)
87
+ # working and .model_copy() working at resolve call sites in _resolve.py.
88
+
89
+
90
+ class ResolvedScaleLogStyle(BaseModel):
91
+ """Resolved log-scale param."""
92
+
93
+ model_config = ConfigDict(extra="forbid", frozen=True)
94
+
95
+ base: float | None = None
96
+
97
+
98
+ class ResolvedScalePowStyle(BaseModel):
99
+ """Resolved power-scale param."""
100
+
101
+ model_config = ConfigDict(extra="forbid", frozen=True)
102
+
103
+ exponent: float | None = None
104
+
105
+
106
+ class ResolvedScaleSymlogStyle(BaseModel):
107
+ """Resolved symlog-scale param."""
108
+
109
+ model_config = ConfigDict(extra="forbid", frozen=True)
110
+
111
+ constant: float | None = None
112
+
113
+
114
+ class ResolvedScaleContinuousStyle(BaseModel):
115
+ """Resolved continuous-scale config."""
116
+
117
+ model_config = ConfigDict(extra="forbid", frozen=True)
118
+
119
+ zero: bool | Literal["auto"] | None = None
120
+ type: Literal["linear", "log", "pow", "sqrt", "symlog", "temporal"] | None = None
121
+ domain: list[Any] | None = None
122
+ domain_strategy: Literal["stable", "auto"] | None = None
123
+ log: ResolvedScaleLogStyle | None = None
124
+ pow: ResolvedScalePowStyle | None = None
125
+ symlog: ResolvedScaleSymlogStyle | None = None
126
+
127
+
128
+ class ResolvedScaleStyle(BaseModel):
129
+ """Resolved scale config — universal + continuous-only superset.
130
+
131
+ Populated by build_resolved_scale() in _cascade.py. Render consumers read
132
+ grouped paths (e.g. .scale.continuous.zero, .scale.continuous.log.base)
133
+ not flat paths. x_reverse is populated only when resolving an x-channel scale.
134
+ band/point/quantize/mark_size were deleted (2026-08 trim) along with the
135
+ authoring surface for them.
136
+ """
137
+
138
+ model_config = ConfigDict(extra="forbid", frozen=True)
139
+
140
+ round: bool | None = None
141
+ clamp: bool | None = None
142
+ nice: bool | None = None
143
+ padding: float | None = None
144
+ headroom: float | None = None
145
+ values: list[Any] | None = None
146
+ continuous: ResolvedScaleContinuousStyle | None = None
147
+ # Populated only when resolving an x-channel scale (XScaleStyle source).
148
+ x_reverse: bool | None = None
149
+
150
+
79
151
  @dataclasses.dataclass(frozen=True)
80
152
  class ResolvedAxisLabelOverlapConfig:
81
153
  """Resolved axis label overlap strategy enablement — all fields required.
@@ -91,19 +163,25 @@ class ResolvedAxisLabelOverlapConfig:
91
163
 
92
164
  @dataclasses.dataclass(frozen=True)
93
165
  class ResolvedAxisElementStyle:
94
- """Resolved axis label or title — all fields required, no defaults.
166
+ """Resolved axis label or title — one shared superset dataclass.
95
167
 
96
- Chart-local Patch fields (label.angle, label.padding, etc.) flow through
168
+ Chart-local Patch fields (labels.angle, labels.padding, etc.) flow through
97
169
  the typed ``axis_overrides_*`` sentinels on ``ResolvedChartsStyle`` and
98
170
  are merged at emit time by ``resolved_axis_style``. They never land on a
99
171
  Resolved axis directly.
172
+
173
+ Title's source type (``AxisTitleStyle``) only has font/angle/align/visible
174
+ — its resolved instance leaves every other field at its default (usually
175
+ None), same as how x-only/y-only fields already work on ``ResolvedAxisStyle``
176
+ itself. ``padding`` is optional (not required) for exactly this reason:
177
+ title has no padding concept post-trim.
100
178
  """
101
179
 
102
180
  font: ResolvedFontStyle
103
- padding: float
181
+ padding: float | None = None
104
182
  # Optional VL-passthrough fields — carried from theme through resolve boundary.
105
183
  # None means "use VL default"; build_resolved_axis carries them through to
106
- # the VL emit layer. Mirrors AxisElementStyle passthrough fields.
184
+ # the VL emit layer. Mirrors AxisLabelStyle passthrough fields.
107
185
  max_width: float | None = None
108
186
  angle: float | None = None
109
187
  # Narrower than the authored Literal["left","right","center","inward",
@@ -114,19 +192,17 @@ class ResolvedAxisElementStyle:
114
192
  # before #5845 (center still needs its own away-from-plot fallback on a
115
193
  # left/right axis — see bar.py / vl_field_maps.py).
116
194
  align: Literal["left", "right", "center"] | None = None
117
- baseline: str | None = None
118
195
  # Resolved overlap strategy enablement. None = cascade did not populate
119
196
  # (resolver skips). Three required bools after cascade from _base.yaml.
120
197
  overlap: ResolvedAxisLabelOverlapConfig | None = None
121
- separation: float | None = None
198
+ min_gap: float | None = None # renamed from `separation`, same meaning
122
199
  visible: bool | None = None # None = cascade-inherit from parent axis slot
123
200
  time_unit: str | None = None
124
201
  expr: str | None = None
125
202
  bound: bool | float | None = None
126
203
  flush: bool | float | None = None
127
204
  offset: float | None = None
128
- line_height: float | None = None
129
- anchor: str | None = None
205
+ format: str | None = None # tick-label format string; None uses VL auto-format
130
206
  tilt_increments: list[float] | None = None
131
207
  # Sparse label-only cadence override — None labels every tick per
132
208
  # the usual smart cadence/format; a list blanks every tick not in it.
@@ -148,11 +224,13 @@ class ResolvedAxisGridStyle:
148
224
  width: float
149
225
  color: str
150
226
  dash: list[float] | None # None → solid line (VL default)
151
- zero: ResolvedAxisGridZeroStyle
227
+ # None on non-measure axes (axis_x, axis_quantitative, axis_band):
228
+ # zero-baseline gridline only makes sense on the measure (y) axis.
229
+ zero: ResolvedAxisGridZeroStyle | None
152
230
 
153
231
 
154
232
  @dataclasses.dataclass(frozen=True)
155
- class ResolvedAxisDomainStyle:
233
+ class ResolvedAxisLineStyle:
156
234
  visible: bool
157
235
  width: float
158
236
  color: str
@@ -164,16 +242,18 @@ class ResolvedAxisTicksStyle:
164
242
  color: str
165
243
  # None means "use VL default" — kept distinct from a numeric override.
166
244
  width: float | None
167
- size: float | None
245
+ length: float | None
246
+ offset: float | None
168
247
  # Target tick count. Quantitative: baked into explicit tick_values at
169
248
  # resolve(). Temporal axis_x: passed through as VL axis.tickCount at emit.
170
249
  # None → VL picks automatically.
171
250
  count: int | None
172
- # Step-anchored cadence unit/multiple. Continuous temporal axis_x only;
251
+ step: int | None
252
+ # Step-anchored cadence unit. Continuous temporal axis_x only (populated
253
+ # only when the source is DimensionTicksStyle — see build_resolved_axis);
173
254
  # passed through as VL axis.tickCount: {interval, step} at emit. None →
174
255
  # no cadence override (falls back to count, then VL's own default).
175
- interval: Literal["year", "quarter", "month"] | None
176
- step: int | None
256
+ time_unit: str | None = None
177
257
 
178
258
 
179
259
  @dataclasses.dataclass(frozen=True)
@@ -187,29 +267,31 @@ class ResolvedAxisStyle:
187
267
  """
188
268
 
189
269
  grid: ResolvedAxisGridStyle
190
- domain: ResolvedAxisDomainStyle
270
+ line: ResolvedAxisLineStyle
191
271
  ticks: ResolvedAxisTicksStyle
192
- label: ResolvedAxisElementStyle
272
+ labels: ResolvedAxisElementStyle
193
273
  title: ResolvedAxisElementStyle
194
274
  position: str | None # None is a valid concrete value ("use VL default")
195
- categorical_orient: str | None
196
275
  # y-axis only: draw the y-scale on both edges. An AxisMirrorStyle object
197
276
  # additionally relabels the mirrored edge (format/expr); see AxisMirrorStyle.
198
277
  mirror: bool | AxisMirrorStyle | None
199
278
  band_position: float | None
200
- offset: float | None
201
- scale: ScaleStyle | None # per-axis scale override (board cascade only)
202
- fill: Literal[
203
- "null",
204
- "zero",
205
- "linear",
206
- "step-after",
207
- "step-before",
208
- "step-center",
209
- "curve",
210
- ] # only active on axis_x ordinal bucketed-time charts
211
- format: str | None # tick-label format string; None uses VL auto-format
212
- values: list[Any] | None # explicit tick values; None uses VL auto
279
+ scale: ResolvedScaleStyle | None # per-axis scale override (board cascade only)
280
+ # None on non-dimension axes (axis_y, axis_quantitative, axis_band):
281
+ # fill only exists on axis_x (AxisXStyle.fill). Theme supplies the x default;
282
+ # the resolver carries it through to the emitter; non-x axes get None here.
283
+ fill: (
284
+ Literal[
285
+ "null",
286
+ "zero",
287
+ "linear",
288
+ "step-after",
289
+ "step-before",
290
+ "step-center",
291
+ "curve",
292
+ ]
293
+ | None
294
+ )
213
295
  time_unit: str | None # time-unit bucketing for temporal x-axes
214
296
  type: Literal["auto", "ordinal", "temporal"] | None # scale type for bucketed-time
215
297
  # Fiscal-year-start month (1=Jan..12=Dec) for year/yearquarter bucket
@@ -303,18 +385,17 @@ class ResolvedChartsStyle:
303
385
  default_chart_height: float
304
386
  default_table_height: float
305
387
  label_usable_ratio: float
306
- # Theme axis layers. `axis` is Layer 1+2's required-complete base (every
307
- # leaf filled by apply_inherit from non-axis theme fields). `axis_x`/
308
- # `axis_y`/`axis_quantitative` are authored-only overlays — sparse by
309
- # design (SkipInheritSlots means apply_inherit never fills their None
310
- # leaves from `axis`). resolved_axis_style() merges them onto `axis` in
311
- # the canonical cascade order at emit time; build_resolved_style does NOT
312
- # pre-merge chart-local axis Patches into these — those live on
313
- # axis_overrides_* below.
314
- axis: ResolvedAxisStyle
315
- axis_x: AxisStyle
316
- axis_y: AxisStyle
317
- axis_quantitative: AxisStyle
388
+ # Theme axis layers.
389
+ # `axis` is Layer 1's channel-agnostic base (BaseAxisStyle — raw passthrough,
390
+ # not eagerly resolved). `axis_x`/`axis_y`/`axis_quantitative` are
391
+ # authored-only overlays — sparse by design (SkipInheritSlots means
392
+ # apply_inherit never fills their None leaves from `axis`).
393
+ # resolved_axis_style() merges them onto a starting AxisXStyle/AxisYStyle
394
+ # in the canonical cascade order at emit time.
395
+ axis: BaseAxisStyle
396
+ axis_x: AxisXStyle
397
+ axis_y: AxisYStyle
398
+ axis_quantitative: QuantitativeAxisStyle
318
399
  legend: ResolvedLegendStyle
319
400
  # Global mark defaults (tier 1 of the three-tier cascade).
320
401
  # apply_inherit pre-applies these into every per-family marks container
@@ -360,19 +441,18 @@ class ResolvedChartsStyle:
360
441
  # resolve_format() so aliases resolve through the face→theme cascade.
361
442
  formats: dict[str, str] | None = None
362
443
 
363
- # Chart-local axis overrides (Layers 4/5/6) as typed AxisStylePatch
364
- # sentinels — populated only by build_resolved_style from the chart's
365
- # ChartStylePatch. None = no chart-local override on that axis variant.
366
- # These are NOT exposed to chart emit code directly; resolved_axis_style is
367
- # the single canonical reader, returning a fully-merged AxisStyle.
368
- axis_overrides_global: AxisStylePatch | None = None
369
- axis_overrides_x: AxisStylePatch | None = None
370
- axis_overrides_y: AxisStylePatch | None = None
371
- axis_overrides_quantitative: AxisStylePatch | None = None
372
- axis_overrides_band: AxisStylePatch | None = None
444
+ # Chart-local axis overrides (Layers 4/5/6) as typed patches — populated
445
+ # only by build_resolved_style from the chart's ChartStylePatch. None = no
446
+ # chart-local override on that axis variant. These are NOT exposed to chart
447
+ # emit code directly; resolved_axis_style is the single canonical reader.
448
+ axis_overrides_global: BaseAxisStylePatch | None = None
449
+ axis_overrides_x: AxisXStylePatch | None = None
450
+ axis_overrides_y: AxisYStylePatch | None = None
451
+ axis_overrides_quantitative: QuantitativeAxisStylePatch | None = None
452
+ axis_overrides_band: BandAxisStylePatch | None = None
373
453
  # Chart-level scale override — populated only by build_resolved_style from
374
454
  # style.scale. None = no chart-local global scale override.
375
- scale: ScaleStyle | None = None
455
+ scale: ResolvedScaleStyle | None = None
376
456
  # Chart-local-only Vega passthrough — populated by build_resolved_style
377
457
  # from style.color. None = no chart-local color override.
378
458
  color: str | None = None
@@ -445,10 +525,10 @@ def effective_padding(resolved: ResolvedStyle) -> SpacingValues:
445
525
 
446
526
 
447
527
  __all__ = [
448
- "ResolvedAxisDomainStyle",
449
528
  "ResolvedAxisElementStyle",
450
529
  "ResolvedAxisGridStyle",
451
530
  "ResolvedAxisGridZeroStyle",
531
+ "ResolvedAxisLineStyle",
452
532
  "ResolvedAxisStyle",
453
533
  "ResolvedAxisTicksStyle",
454
534
  "ResolvedCalloutElementStyle",
@@ -456,6 +536,11 @@ __all__ = [
456
536
  "ResolvedChartsStyle",
457
537
  "ResolvedLegendElementStyle",
458
538
  "ResolvedLegendStyle",
539
+ "ResolvedScaleContinuousStyle",
540
+ "ResolvedScaleLogStyle",
541
+ "ResolvedScalePowStyle",
542
+ "ResolvedScaleStyle",
543
+ "ResolvedScaleSymlogStyle",
459
544
  "ResolvedStyle",
460
545
  "effective_padding",
461
546
  ]
@@ -11,7 +11,7 @@ _CartesianResolvedStyle
11
11
 
12
12
  _SeriesCartesianResolvedStyle (_CartesianResolvedStyle)
13
13
  bar / line / area — the "standard series" families that share a common
14
- series-label contract, endpoint-label feature gate, and the background /
14
+ series-label contract, endpoint-label feature gate, and the
15
15
  fill / ratio / format fields the feature layer reads.
16
16
  """
17
17
 
@@ -29,10 +29,11 @@ from ._marks import ResolvedSeriesLabelStyle
29
29
  class _CartesianResolvedStyle(BaseModel):
30
30
  """Shared resolved fields for all cartesian chart families.
31
31
 
32
- All six cartesian style slices inherit this so axes, tooltip_format, and
33
- background are declared once. background is board-level (every chart lives
34
- against the same canvas color) even when a particular family's emitter
35
- doesn't currently consume it.
32
+ All six cartesian style slices inherit this so axes and tooltip_format
33
+ are declared once. The chart's effective canvas color (used by halo
34
+ strokes, inside-mark value labels, and the VL spec root) lives on the
35
+ resolved chart envelope (``ResolvedChart.background``), not here — see
36
+ ``_SharedResolvedChartFields`` in ``compile/models/chart/resolved/_base.py``.
36
37
  """
37
38
 
38
39
  model_config = ConfigDict(frozen=True, extra="forbid")
@@ -46,12 +47,6 @@ class _CartesianResolvedStyle(BaseModel):
46
47
  tooltip_format: str = Field(
47
48
  description="Resolved d3 tooltip number format ('' = VL default).",
48
49
  )
49
- background: str = Field(
50
- description=(
51
- "Board effective background color. Used for halo strokes, "
52
- "inside-mark value labels, and any future per-chart overlay."
53
- ),
54
- )
55
50
  title_font: ResolvedFontStyle | None = Field(
56
51
  default=None,
57
52
  description="Baked title font (size/weight/family/…) from the width tier.",