@astrato-io/visualizations 0.0.0-stage → 0.6.4

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 (145) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE +93 -0
  3. package/README.md +843 -2
  4. package/THIRD_PARTY_NOTICES.md +8387 -0
  5. package/VISUALIZATION_DEFINITIONS.md +2378 -0
  6. package/chunks/LinearProgress-CUZ0D8_t.js +253 -0
  7. package/chunks/Radio-Ciu-F4CU.js +957 -0
  8. package/chunks/ToggleButton-BCJc3Jlc.js +153 -0
  9. package/chunks/_baseFlatten-DPXPOrea.js +7076 -0
  10. package/chunks/accessors-DemrDevR.js +128 -0
  11. package/chunks/app-filter-bar.compiler-j_CVoWTa.js +55 -0
  12. package/chunks/bar.compiler-oqaPzIut.js +370 -0
  13. package/chunks/color-settings-ZIvgNTq1.js +10 -0
  14. package/chunks/coloring-C16AUZEi.js +663 -0
  15. package/chunks/data-item-resolution-1lvYB5ln.js +53 -0
  16. package/chunks/debounce-fn-CUixuz45.js +7 -0
  17. package/chunks/escobar-BGqT1EsE.js +34580 -0
  18. package/chunks/event-bus-KiSiCJrC.js +2683 -0
  19. package/chunks/events-WZut5Ow6.js +4 -0
  20. package/chunks/extend-BKUkc4_i.js +37 -0
  21. package/chunks/filter.compiler-CuLtc_02.js +60 -0
  22. package/chunks/filtering-Yq4DEa0t.js +953 -0
  23. package/chunks/gauge-target-type-BkKXAqkX.js +4 -0
  24. package/chunks/grouping-type-BX_9Ix5q.js +3 -0
  25. package/chunks/interfaces-VUY4_yVO.js +8742 -0
  26. package/chunks/line-settings-DfYTUyPz.js +4 -0
  27. package/chunks/line.compiler-BpA_6Tc7.js +188 -0
  28. package/chunks/metadata-CPXdYoln.js +28 -0
  29. package/chunks/number.compiler-DbkWcG4S.js +44 -0
  30. package/chunks/pie-uv42Eqal.js +10 -0
  31. package/chunks/range-DrzdfBX4.js +22 -0
  32. package/chunks/registry-CExpGJ1N.js +920 -0
  33. package/chunks/requirements-DNhuShLS.js +6 -0
  34. package/chunks/rolldown-runtime-DleVn1XH.js +28 -0
  35. package/chunks/set-coloring-datafield-B3uIS1Pe.js +8 -0
  36. package/chunks/shared-CKDL4hx9.js +1171 -0
  37. package/chunks/src-BC7cGcJ-.js +2024 -0
  38. package/chunks/src-BOS6SqkZ.js +67 -0
  39. package/chunks/src-C0LgoUWY.js +26105 -0
  40. package/chunks/src-Cum_2NLV.js +12145 -0
  41. package/chunks/src-D9XogOrc.js +422 -0
  42. package/chunks/src-Dun_jXtz.js +10295 -0
  43. package/chunks/src-DvX5LU9T.js +14742 -0
  44. package/chunks/standalone-87YV_m9n.js +687 -0
  45. package/chunks/standalone-BDCwI6Hn.js +4619 -0
  46. package/chunks/standalone-BH5NqDwp.js +1763 -0
  47. package/chunks/standalone-BLVAWLNJ.js +385 -0
  48. package/chunks/standalone-BPomtAVs.js +2 -0
  49. package/chunks/standalone-BXyBcUOQ.js +2 -0
  50. package/chunks/standalone-BYm1UjLr.js +140 -0
  51. package/chunks/standalone-BllF4rDp.js +383 -0
  52. package/chunks/standalone-BmfMt74U.js +726 -0
  53. package/chunks/standalone-BqWyrnZI.js +281 -0
  54. package/chunks/standalone-C85u7U6I.js +340 -0
  55. package/chunks/standalone-CCNtaJ7s.js +741 -0
  56. package/chunks/standalone-CDQnr6qT.js +345 -0
  57. package/chunks/standalone-CNyNHKVx.js +674 -0
  58. package/chunks/standalone-CY57qwZ-.js +1129 -0
  59. package/chunks/standalone-CZynjFG7.js +12979 -0
  60. package/chunks/standalone-D5vnf-9y.js +3943 -0
  61. package/chunks/standalone-DFPva_ku.js +299 -0
  62. package/chunks/standalone-DQxxNwF8.js +675 -0
  63. package/chunks/standalone-DS9T0FZ-.js +830 -0
  64. package/chunks/standalone-Dx3MLlrO.js +512 -0
  65. package/chunks/standalone-DzixzZAL.js +411 -0
  66. package/chunks/standalone-QJ1kKMnO.js +6 -0
  67. package/chunks/standalone-jiz0L2Dg.js +3855 -0
  68. package/chunks/standalone-lBm9hQ-q.js +179 -0
  69. package/chunks/standalone-rJ45Zfl1.js +68 -0
  70. package/chunks/stroke-dash-UgMEcCS4.js +6 -0
  71. package/chunks/table.compiler-BrXkm4Fz.js +213 -0
  72. package/chunks/toInteger-DVZr-D1j.js +11 -0
  73. package/chunks/treemap-x_zmJoG7.js +23 -0
  74. package/chunks/typeof-CJDtcySz.js +13 -0
  75. package/chunks/types-dVVCsDWD.js +4 -0
  76. package/chunks/ui-D1HQNIBy.js +54039 -0
  77. package/chunks/url-utils-B17gj_mr.js +5501 -0
  78. package/chunks/useFieldName-oqQ3bvnO.js +7 -0
  79. package/chunks/utils-Ba9T0TqC.js +31097 -0
  80. package/chunks/view-CLqWMV7Z.js +156 -0
  81. package/definitions.js +3 -0
  82. package/docs/operations/astrato-app-filter-bar.md +161 -0
  83. package/docs/operations/bar.md +7050 -0
  84. package/docs/operations/combo.md +5825 -0
  85. package/docs/operations/date-picker.md +644 -0
  86. package/docs/operations/distribution-gauge.md +3218 -0
  87. package/docs/operations/dot.md +5662 -0
  88. package/docs/operations/filter.md +1507 -0
  89. package/docs/operations/gauge.md +3452 -0
  90. package/docs/operations/heatMap.md +6026 -0
  91. package/docs/operations/histogram.md +1870 -0
  92. package/docs/operations/iframe.md +56 -0
  93. package/docs/operations/image.md +177 -0
  94. package/docs/operations/index.md +46 -0
  95. package/docs/operations/line.md +6468 -0
  96. package/docs/operations/number.md +3969 -0
  97. package/docs/operations/pie.md +6089 -0
  98. package/docs/operations/radar.md +4646 -0
  99. package/docs/operations/sankey.md +3210 -0
  100. package/docs/operations/scatter.md +6075 -0
  101. package/docs/operations/shape.md +315 -0
  102. package/docs/operations/simpleTextObject.md +706 -0
  103. package/docs/operations/slider.md +230 -0
  104. package/docs/operations/table.md +8790 -0
  105. package/docs/operations/tree.md +2874 -0
  106. package/docs/operations/treemap.md +3619 -0
  107. package/docs/operations/waterfall.md +2938 -0
  108. package/docs/operations/word-cloud.md +3071 -0
  109. package/getters.js +18 -0
  110. package/index.js +1183 -0
  111. package/metadata.js +20 -0
  112. package/operations.js +64 -0
  113. package/package.json +191 -4
  114. package/src/definitions/index.d.ts +2 -0
  115. package/src/definitions/shared/index.d.ts +5 -0
  116. package/src/definitions/shared/lib/available-fields.d.ts +36 -0
  117. package/src/definitions/shared/lib/compilers/index.d.ts +7 -0
  118. package/src/definitions/shared/lib/registry/compile.d.ts +2 -0
  119. package/src/definitions/shared/lib/registry/descriptor-registry.d.ts +587 -0
  120. package/src/definitions/shared/lib/registry/index.d.ts +3 -0
  121. package/src/definitions/shared/lib/registry/validation.d.ts +3 -0
  122. package/src/definitions/shared/lib/schemas/app-filter-bar.schema.d.ts +22 -0
  123. package/src/definitions/shared/lib/schemas/bar.schema.d.ts +73 -0
  124. package/src/definitions/shared/lib/schemas/broad-chart.schema.d.ts +68 -0
  125. package/src/definitions/shared/lib/schemas/common.schema.d.ts +304 -0
  126. package/src/definitions/shared/lib/schemas/filter.schema.d.ts +22 -0
  127. package/src/definitions/shared/lib/schemas/index.d.ts +9 -0
  128. package/src/definitions/shared/lib/schemas/line.schema.d.ts +72 -0
  129. package/src/definitions/shared/lib/schemas/number.schema.d.ts +21 -0
  130. package/src/definitions/shared/lib/schemas/object.schema.d.ts +215 -0
  131. package/src/definitions/shared/lib/schemas/table.schema.d.ts +458 -0
  132. package/src/definitions/shared/lib/types/compilation.types.d.ts +36 -0
  133. package/src/definitions/shared/lib/types/definition.types.d.ts +2 -0
  134. package/src/definitions/shared/lib/types/descriptor.types.d.ts +39 -0
  135. package/src/definitions/shared/lib/types/index.d.ts +3 -0
  136. package/src/getters/index.d.ts +30 -0
  137. package/src/index.d.ts +4 -0
  138. package/src/metadata/index.d.ts +4 -0
  139. package/src/operations/index.d.ts +30 -0
  140. package/src/registry/index.d.ts +6 -0
  141. package/src/runtime/index.d.ts +2 -0
  142. package/src/types.d.ts +307 -0
  143. package/src/visualization-catalog.d.ts +82 -0
  144. package/src/web-components/index.d.ts +12 -0
  145. package/styles.css +2 -0
@@ -0,0 +1,2378 @@
1
+ # Visualization Definition Reference
2
+
3
+ This reference documents version 1 of the public `VisualizationDefinition` creation contract exposed from `@astrato-io/visualizations/definitions`.
4
+
5
+ The reference and the public per-type descriptors share the same metadata catalog.
6
+
7
+ ## How To Use This Reference
8
+
9
+ - Use a definition only to create a visualization from a fresh default or preset vSpec.
10
+ - Use exact, opaque engine `fieldKey` values. Never parse, reconstruct, or replace them with view/name pairs.
11
+ - Definition-local `ref` values let sorting, Top N, and similar settings refer to data items before internal identities exist.
12
+ - Raw fields used as measures require `aggregation`. Semantic dimensions, predefined measures, and calculations retain their engine semantics.
13
+ - Unsupported sections and properties are rejected instead of ignored.
14
+ - The compiler returns one complete vSpec or structured issues; it never returns partial state.
15
+ - Settings a definition cannot express are applied with `applyOperations` on the compiled vSpec before mounting. See "Finishing A Chart Before Mounting".
16
+
17
+ ## Integrating With AI
18
+
19
+ When building an AI integration, first choose the visualization type, such as `bar` or `table`. The compact `supportedFeatures` list can help with this discovery step without loading every full schema.
20
+
21
+ After selecting the type, give the model only:
22
+
23
+ 1. `descriptor.jsonSchema`, which defines the allowed JSON structure.
24
+ 2. `descriptor.documentation`, which explains what the properties mean and lists chart-specific rules.
25
+ 3. `descriptor.examples`, which shows valid definitions.
26
+ 4. The compatible available fields, including their exact engine keys.
27
+
28
+ Do not send schemas for every visualization or ask the model to generate a raw vSpec. That would give the model unrelated information and require it to understand internal vSpec properties and generated data-item IDs.
29
+
30
+ After the model returns a definition, pass it to `compileVisualizationDefinition()`. On success, use the returned vSpec. On failure, give the structured issues back to the model so it can correct the definition and try again.
31
+
32
+ Use `getVisualizationDefinitionDescriptor(type, 1)` to get the descriptor for one selected type. Use `listVisualizationDefinitionDescriptors()` to discover the available visualization types and compare their `supportedFeatures`.
33
+
34
+ A definition does not cover every setting yet. If the chart needs a setting the definition cannot express, finish it with operations before mounting, as described in the next section.
35
+
36
+ ## Finishing A Chart Before Mounting
37
+
38
+ A definition covers a subset of the operation catalogue. For settings outside it, apply operations to the compiled vSpec with `applyOperations` from `@astrato-io/visualizations/operations`, in one batch and before creating the instance. This runs in memory: it needs no runtime and makes no engine requests.
39
+
40
+ Use `compilation.resolvedRefs` to get the data-item identity that operation payloads expect for a definition `ref`:
41
+
42
+ ```ts
43
+ import { applyOperations } from '@astrato-io/visualizations/operations';
44
+
45
+ const compilation = await compileVisualizationDefinition({ definition, availableFields, baseVSpec });
46
+ if (!compilation.success) throw new Error(JSON.stringify(compilation.issues));
47
+
48
+ const { dataItemInternalKey, dataItemUniqueSignature } = compilation.resolvedRefs.sales;
49
+ const finished = await applyOperations({
50
+ instance: { id: 'sales-by-manufacturer', type: 'bar', vSpec: compilation.vSpec },
51
+ operationRequests: [
52
+ { id: 'radius', name: 'setBarChartBarRadius', payload: 4 },
53
+ {
54
+ id: 'color',
55
+ name: 'setMeasureGraphColor',
56
+ payload: { dataItemInternalKey, dataItemUniqueSignature, graphColor: '#0f766e' },
57
+ },
58
+ ],
59
+ });
60
+
61
+ // a batch is not transactional: a request that fails while running is reported here;
62
+ // an unsupported operation name or a missing vSpec throws before any result is returned
63
+ const failures = Object.values(finished.results as Record<string, { success: boolean }>).filter(
64
+ (result) => !result.success,
65
+ );
66
+ if (failures.length) throw new Error(JSON.stringify(failures));
67
+
68
+ runtime.createInstance({ id: 'sales-by-manufacturer', type: 'bar', vSpec: finished.vSpec, dataBinding });
69
+ ```
70
+
71
+ Get operation names and payload schemas from `getVisualizationMetadata(type).operations`.
72
+
73
+ Avoid finishing a chart by applying operations one at a time after it is mounted. Each change to a mounted instance's vSpec can trigger a new data request, so a dashboard built that way makes one engine request per operation per chart.
74
+
75
+ ## Common Feature Names
76
+
77
+ | Feature | Meaning |
78
+ | -------------------- | ------------------------------------------------------------------------------ |
79
+ | `axes` | Semantic dimension/primary-measure/secondary-measure axis presentation. |
80
+ | `axis-bands` | Shaded ranges between two primary measure axis values. |
81
+ | `axis-range` | Measure-axis range (min, max, starts at zero) and inversion. |
82
+ | `axis-scale` | Linear or logarithmic measure axis. |
83
+ | `content` | User-visible content such as text, image, or URL. |
84
+ | `data-labels` | Chart or measure label visibility and supported label settings. |
85
+ | `dimensions` | Dimension or field-backed data items. |
86
+ | `filter-settings` | Settings of an interactive filter-like object. |
87
+ | `filters` | Static visualization filters applied at creation. |
88
+ | `input-settings` | Variable-backed input behavior and presentation. |
89
+ | `legend` | Legend visibility, position, and title. |
90
+ | `measures` | Aggregated raw fields, predefined measures, or calculations. |
91
+ | `object-settings` | Object-specific non-data presentation settings. |
92
+ | `orientation` | Horizontal or vertical chart orientation. |
93
+ | `query-limit` | Maximum number of rows requested by the visualization. |
94
+ | `selection-settings` | Selection behavior and available filter controls for a shared selection group. |
95
+ | `sorting` | Ordered sorting rules referencing definition-local refs. |
96
+ | `table-structure` | Normal, expandable, or pivot table data arrangement. |
97
+ | `top-n` | Top N limiting referencing a definition-local measure ref. |
98
+ | `totals` | Table totals behavior and presentation. |
99
+ | `value-formatting` | Dimension, measure, or table-column value formatting. |
100
+
101
+ ## Capability Index
102
+
103
+ | Type | Name | Data requirements | Supported features |
104
+ | ------------------------ | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
105
+ | `bar` | Bar chart | At least one dimension. At least one measure. | `axes`, `axis-bands`, `axis-range`, `axis-scale`, `conditional-coloring`, `data-labels`, `dimensions`, `filters`, `legend`, `measure-axis`, `measures`, `orientation`, `query-limit`, `sorting`, `top-n`, `value-formatting` |
106
+ | `combo` | Combo chart | Exactly one dimension. Between one and ten measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `axes`, `axis-bands`, `axis-range`, `axis-scale`, `data-labels`, `legend`, `measure-axis`, `orientation`, `query-limit`, `series-type`, `sorting` |
107
+ | `distribution-gauge` | Distribution gauge | Zero or one dimension. Between one and twenty measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `display-mode`, `legend` |
108
+ | `dot` | Dot chart | Exactly two dimensions. Exactly one measure. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `axis-range`, `legend`, `orientation` |
109
+ | `gauge` | Gauge chart | Zero or one dimension. Between one and twenty measures; with one dimension, at most two measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `display-mode`, `legend` |
110
+ | `heatMap` | Heat map | Exactly two dimensions. One or two measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `legend`, `query-limit`, `sorting` |
111
+ | `histogram` | Histogram | Exactly one numeric dimension. No caller-supplied measures. | `axes`, `axis-bands`, `axis-range`, `dimensions`, `filters`, `legend`, `orientation`, `value-formatting` |
112
+ | `line` | Line chart | At least one dimension. At least one measure. | `axes`, `axis-bands`, `axis-range`, `axis-scale`, `conditional-coloring`, `data-labels`, `data-points`, `dimensions`, `filters`, `legend`, `measure-axis`, `measures`, `orientation`, `query-limit`, `sorting`, `value-formatting` |
113
+ | `radar` | Radar chart | Zero to two dimensions. Two to five measures without dimensions, or one with dimensions. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend` |
114
+ | `pie` | Pie chart | Exactly one dimension. One or two measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend`, `query-limit`, `sorting` |
115
+ | `tree` | Tree chart | Zero to ten dimensions. Zero to one hundred measures, or at most one with dimensions. | `dimensions`, `filters`, `measures`, `value-formatting`, `layout`, `query-limit`, `sorting` |
116
+ | `treemap` | Treemap | Between one and ten dimensions. Exactly one measure. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend` |
117
+ | `sankey` | Sankey chart | Between two and fifteen dimensions. Exactly one measure. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring` |
118
+ | `scatter` | Scatter chart | One or two dimensions. Two or three measures. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `axis-range`, `legend`, `query-limit`, `sorting` |
119
+ | `table` | Table | Normal tables require at least one ordered dimension or measure column. Expandable tables require at least one dimension and one measure. Pivot tables require at least one row dimension, one column dimension, and one measure. | `dimensions`, `filters`, `layout`, `measures`, `query-limit`, `sorting`, `table-structure`, `totals`, `value-formatting` |
120
+ | `waterfall` | Waterfall chart | Between one and one hundred measures. | `axes`, `axis-bands`, `axis-range`, `data-labels`, `filters`, `measures`, `orientation`, `value-formatting` |
121
+ | `word-cloud` | Word cloud | Exactly one dimension. Exactly one measure. | `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring` |
122
+ | `date-picker` | Date picker | Exactly one field. | `dimensions`, `filter-settings` |
123
+ | `filter` | Filter | Exactly one field. | `dimensions`, `filter-settings` |
124
+ | `iframe` | Iframe | No query data. | `content` |
125
+ | `image` | Image | No query data. | `content`, `object-settings` |
126
+ | `number` | Number | Exactly one measure. | `filters`, `measures`, `value-formatting` |
127
+ | `shape` | Shape | No query data. | `object-settings` |
128
+ | `simpleTextObject` | Text object | No query data. | `content`, `object-settings` |
129
+ | `atomic-input` | Atomic input | No query data; variable-backed input. | `input-settings` |
130
+ | `astrato-app-filter-bar` | Astrato App Filter Bar | No query data; uses field metadata and selections supplied by the host. | `selection-settings` |
131
+ | `slider` | Slider | Exactly one field. | `dimensions`, `filter-settings` |
132
+
133
+ ## `bar`: Bar chart
134
+
135
+ Categorical comparison chart with sorting, limiting, per-measure axes, labels, and orientation controls.
136
+
137
+ **Data requirements**
138
+
139
+ - At least one dimension.
140
+ - At least one measure.
141
+
142
+ **Supported features**
143
+
144
+ `axes`, `axis-bands`, `axis-range`, `axis-scale`, `conditional-coloring`, `data-labels`, `dimensions`, `filters`, `legend`, `measure-axis`, `measures`, `orientation`, `query-limit`, `sorting`, `top-n`, `value-formatting`
145
+
146
+ **Constraints and semantics**
147
+
148
+ - Sorting and Top N refer to definition-local refs, not generated data-item IDs.
149
+ - Every dimension and measure must resolve to an available field with a compatible role.
150
+ - Set axis per measure to plot it against the primary or the secondary measure axis.
151
+ - presentation.axes.primaryMeasure.bands shades the plot between two primary measure axis values; start and end are measure values, and the bands replace any on the base vSpec.
152
+ - Set range on a measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on a measure axis to reverse its values, for example to put rank 1 at the top.
153
+ - Set scale to log on a measure axis to draw it logarithmically, with gridlines at powers of ten. Zero and negative values are drawn at the floor of a log axis.
154
+
155
+ **Canonical example**
156
+
157
+ ```json
158
+ {
159
+ "data": {
160
+ "dimensions": [
161
+ {
162
+ "fieldKey": "[Cars].[Manufacturer]",
163
+ "format": {
164
+ "formatType": "none"
165
+ },
166
+ "ref": "manufacturer",
167
+ "showNullValues": false
168
+ }
169
+ ],
170
+ "measures": [
171
+ {
172
+ "aggregation": "SUM",
173
+ "fieldKey": "[Cars].[Sales In Thousands]",
174
+ "format": {
175
+ "formatType": "number2Decimal",
176
+ "negativeType": "parenthesis"
177
+ },
178
+ "ref": "sales",
179
+ "dataLabels": {
180
+ "placements": ["outside", "inside"],
181
+ "visible": true
182
+ }
183
+ }
184
+ ]
185
+ },
186
+ "filterGroup": {
187
+ "filters": [
188
+ {
189
+ "fieldKey": "[Cars].[Manufacturer]",
190
+ "operator": "inList",
191
+ "values": ["Acura", "Audi", "BMW"]
192
+ }
193
+ ],
194
+ "operator": "and"
195
+ },
196
+ "limiting": {
197
+ "queryLimit": 100,
198
+ "topN": {
199
+ "by": "sales",
200
+ "count": 10,
201
+ "direction": "desc",
202
+ "showOthers": false
203
+ }
204
+ },
205
+ "presentation": {
206
+ "axes": {
207
+ "dimension": {
208
+ "labelsVisible": true,
209
+ "title": "Manufacturer",
210
+ "titleVisible": true
211
+ },
212
+ "primaryMeasure": {
213
+ "labelsVisible": true,
214
+ "title": "Sales",
215
+ "titleVisible": true,
216
+ "bands": [
217
+ {
218
+ "color": "#E6E6E6",
219
+ "end": 150000,
220
+ "label": "Target range",
221
+ "start": 100000
222
+ }
223
+ ]
224
+ },
225
+ "secondaryMeasure": {
226
+ "labelsVisible": true,
227
+ "title": "Horsepower",
228
+ "titleVisible": true
229
+ }
230
+ },
231
+ "legend": {
232
+ "position": "right",
233
+ "title": "Cars comparison",
234
+ "visible": true
235
+ },
236
+ "orientation": "vertical"
237
+ },
238
+ "sorting": [
239
+ {
240
+ "by": "sales",
241
+ "direction": "desc"
242
+ }
243
+ ],
244
+ "type": "bar",
245
+ "version": 1
246
+ }
247
+ ```
248
+
249
+ **Additional scenarios**
250
+
251
+ ### Colors bound to dimension values and a measure threshold
252
+
253
+ ```json
254
+ {
255
+ "data": {
256
+ "dimensions": [
257
+ {
258
+ "fieldKey": "[Cars].[Manufacturer]",
259
+ "format": {
260
+ "formatType": "none"
261
+ },
262
+ "ref": "manufacturer"
263
+ }
264
+ ],
265
+ "measures": [
266
+ {
267
+ "aggregation": "SUM",
268
+ "fieldKey": "[Cars].[Sales In Thousands]",
269
+ "format": {
270
+ "formatType": "number2Decimal",
271
+ "negativeType": "parenthesis"
272
+ },
273
+ "ref": "sales"
274
+ }
275
+ ]
276
+ },
277
+ "presentation": {
278
+ "coloring": {
279
+ "overwrites": [
280
+ {
281
+ "color": "#0F766E",
282
+ "value": "Audi"
283
+ },
284
+ {
285
+ "color": "#D97706",
286
+ "operator": "inList",
287
+ "values": ["BMW", "Buick"]
288
+ }
289
+ ],
290
+ "rules": [
291
+ {
292
+ "color": "#DC2626",
293
+ "measure": "sales",
294
+ "operator": "less",
295
+ "value": 20
296
+ }
297
+ ]
298
+ }
299
+ },
300
+ "type": "bar",
301
+ "version": 1
302
+ }
303
+ ```
304
+
305
+ ## `combo`: Combo chart
306
+
307
+ Combined categorical chart supporting multiple measures, per-measure axes, sorting, limiting, labels, legend, and orientation.
308
+
309
+ **Data requirements**
310
+
311
+ - Exactly one dimension.
312
+ - Between one and ten measures.
313
+
314
+ **Supported features**
315
+
316
+ `dimensions`, `filters`, `measures`, `value-formatting`, `axes`, `axis-bands`, `axis-range`, `axis-scale`, `data-labels`, `legend`, `measure-axis`, `orientation`, `query-limit`, `series-type`, `sorting`
317
+
318
+ **Constraints and semantics**
319
+
320
+ - The single dimension is assigned the combo category role.
321
+ - Set seriesType per measure to create bar, line, or point series; omission keeps the existing line default.
322
+ - Data labels apply only to bar series.
323
+ - Sorting refers to definition-local refs, not generated data-item IDs.
324
+ - Set axis per measure to plot it against the primary or the secondary measure axis. Bar series share one axis: state it on any bar measure, and every bar measure that states one must state the same axis.
325
+ - presentation.axes.primaryMeasure.bands shades the plot between two primary measure axis values; start and end are measure values, and the bands replace any on the base vSpec.
326
+ - Set range on a measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on a measure axis to reverse its values, for example to put rank 1 at the top.
327
+ - Set scale to log on a measure axis to draw it logarithmically, with gridlines at powers of ten. Zero and negative values are drawn at the floor of a log axis.
328
+
329
+ **Canonical example**
330
+
331
+ ```json
332
+ {
333
+ "data": {
334
+ "dimensions": [
335
+ {
336
+ "fieldKey": "[Cars].[Manufacturer]",
337
+ "format": {
338
+ "formatType": "none"
339
+ },
340
+ "ref": "manufacturer"
341
+ }
342
+ ],
343
+ "measures": [
344
+ {
345
+ "aggregation": "SUM",
346
+ "fieldKey": "[Cars].[Sales In Thousands]",
347
+ "format": {
348
+ "formatType": "number2Decimal",
349
+ "negativeType": "parenthesis"
350
+ },
351
+ "ref": "sales",
352
+ "dataLabels": {
353
+ "visible": true
354
+ },
355
+ "seriesType": "bar"
356
+ },
357
+ {
358
+ "aggregation": "AVG",
359
+ "fieldKey": "[Cars].[Horsepower]",
360
+ "format": {
361
+ "formatType": "number2Decimal",
362
+ "negativeType": "parenthesis"
363
+ },
364
+ "ref": "horsepower",
365
+ "axis": "secondary",
366
+ "seriesType": "line"
367
+ }
368
+ ]
369
+ },
370
+ "filterGroup": {
371
+ "filters": [
372
+ {
373
+ "fieldKey": "[Cars].[Manufacturer]",
374
+ "operator": "inList",
375
+ "values": ["Acura", "Audi", "BMW"]
376
+ }
377
+ ],
378
+ "operator": "and"
379
+ },
380
+ "limiting": {
381
+ "queryLimit": 100
382
+ },
383
+ "presentation": {
384
+ "axes": {
385
+ "dimension": {
386
+ "labelsVisible": true,
387
+ "title": "Manufacturer",
388
+ "titleVisible": true
389
+ },
390
+ "primaryMeasure": {
391
+ "labelsVisible": true,
392
+ "title": "Sales",
393
+ "titleVisible": true
394
+ }
395
+ },
396
+ "dataLabels": {
397
+ "visible": true
398
+ },
399
+ "legend": {
400
+ "position": "right",
401
+ "title": "Cars comparison",
402
+ "visible": true
403
+ },
404
+ "orientation": "vertical"
405
+ },
406
+ "sorting": [
407
+ {
408
+ "by": "sales",
409
+ "direction": "desc"
410
+ }
411
+ ],
412
+ "type": "combo",
413
+ "version": 1
414
+ }
415
+ ```
416
+
417
+ ## `distribution-gauge`: Distribution gauge
418
+
419
+ Gauge distribution across one or more values, optionally grouped by a dimension.
420
+
421
+ **Data requirements**
422
+
423
+ - Zero or one dimension.
424
+ - Between one and twenty measures.
425
+
426
+ **Supported features**
427
+
428
+ `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `display-mode`, `legend`
429
+
430
+ **Constraints and semantics**
431
+
432
+ - All measures are assigned the gauge-value role.
433
+ - Distribution definitions enable the established gauge comparison mode.
434
+
435
+ **Canonical example**
436
+
437
+ ```json
438
+ {
439
+ "data": {
440
+ "dimensions": [
441
+ {
442
+ "fieldKey": "[Cars].[Manufacturer]",
443
+ "format": {
444
+ "formatType": "none"
445
+ },
446
+ "ref": "manufacturer"
447
+ }
448
+ ],
449
+ "measures": [
450
+ {
451
+ "aggregation": "SUM",
452
+ "fieldKey": "[Cars].[Sales In Thousands]",
453
+ "format": {
454
+ "formatType": "number2Decimal",
455
+ "negativeType": "parenthesis"
456
+ },
457
+ "ref": "sales"
458
+ },
459
+ {
460
+ "aggregation": "AVG",
461
+ "fieldKey": "[Cars].[Sales In Thousands]",
462
+ "format": {
463
+ "formatType": "number2Decimal",
464
+ "negativeType": "parenthesis"
465
+ },
466
+ "ref": "averageSales"
467
+ }
468
+ ]
469
+ },
470
+ "filterGroup": {
471
+ "filters": [
472
+ {
473
+ "fieldKey": "[Cars].[Manufacturer]",
474
+ "operator": "inList",
475
+ "values": ["Acura", "Audi", "BMW"]
476
+ }
477
+ ],
478
+ "operator": "and"
479
+ },
480
+ "presentation": {
481
+ "displayMode": "bar",
482
+ "legend": {
483
+ "position": "right",
484
+ "title": "Cars comparison",
485
+ "visible": true
486
+ }
487
+ },
488
+ "type": "distribution-gauge",
489
+ "version": 1
490
+ }
491
+ ```
492
+
493
+ ## `dot`: Dot chart
494
+
495
+ Dot comparison using two categorical dimensions and one measure.
496
+
497
+ **Data requirements**
498
+
499
+ - Exactly two dimensions.
500
+ - Exactly one measure.
501
+
502
+ **Supported features**
503
+
504
+ `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `axis-range`, `legend`, `orientation`
505
+
506
+ **Constraints and semantics**
507
+
508
+ - Dimension order is significant and maps to the two dot-chart dimension roles.
509
+ - Set range on the primary measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on the primary measure axis to reverse its values.
510
+
511
+ **Canonical example**
512
+
513
+ ```json
514
+ {
515
+ "data": {
516
+ "dimensions": [
517
+ {
518
+ "fieldKey": "[Cars].[Manufacturer]",
519
+ "format": {
520
+ "formatType": "none"
521
+ },
522
+ "ref": "manufacturer"
523
+ },
524
+ {
525
+ "fieldKey": "[Cars].[Model]",
526
+ "format": {
527
+ "formatType": "none"
528
+ },
529
+ "ref": "model"
530
+ }
531
+ ],
532
+ "measures": [
533
+ {
534
+ "aggregation": "SUM",
535
+ "fieldKey": "[Cars].[Sales In Thousands]",
536
+ "format": {
537
+ "formatType": "number2Decimal",
538
+ "negativeType": "parenthesis"
539
+ },
540
+ "ref": "sales"
541
+ }
542
+ ]
543
+ },
544
+ "filterGroup": {
545
+ "filters": [
546
+ {
547
+ "fieldKey": "[Cars].[Manufacturer]",
548
+ "operator": "inList",
549
+ "values": ["Acura", "Audi", "BMW"]
550
+ }
551
+ ],
552
+ "operator": "and"
553
+ },
554
+ "presentation": {
555
+ "axes": {
556
+ "dimension": {
557
+ "labelsVisible": true,
558
+ "title": "Manufacturer",
559
+ "titleVisible": true
560
+ },
561
+ "primaryMeasure": {
562
+ "labelsVisible": true,
563
+ "title": "Sales",
564
+ "titleVisible": true
565
+ }
566
+ },
567
+ "legend": {
568
+ "position": "right",
569
+ "title": "Cars comparison",
570
+ "visible": true
571
+ },
572
+ "orientation": "horizontal"
573
+ },
574
+ "type": "dot",
575
+ "version": 1
576
+ }
577
+ ```
578
+
579
+ ## `gauge`: Gauge chart
580
+
581
+ Gauge values with an optional grouping dimension and optional data target.
582
+
583
+ **Data requirements**
584
+
585
+ - Zero or one dimension.
586
+ - Between one and twenty measures; with one dimension, at most two measures.
587
+
588
+ **Supported features**
589
+
590
+ `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `display-mode`, `legend`
591
+
592
+ **Constraints and semantics**
593
+
594
+ - With a dimension, the first measure is the gauge value and the optional second measure is the target.
595
+ - Without a dimension, supplied measures are gauge values.
596
+ - When a target measure is supplied, the compiler enables the established data-target mode.
597
+
598
+ **Canonical example**
599
+
600
+ ```json
601
+ {
602
+ "data": {
603
+ "dimensions": [
604
+ {
605
+ "fieldKey": "[Cars].[Manufacturer]",
606
+ "format": {
607
+ "formatType": "none"
608
+ },
609
+ "ref": "manufacturer"
610
+ }
611
+ ],
612
+ "measures": [
613
+ {
614
+ "aggregation": "SUM",
615
+ "fieldKey": "[Cars].[Sales In Thousands]",
616
+ "format": {
617
+ "formatType": "number2Decimal",
618
+ "negativeType": "parenthesis"
619
+ },
620
+ "ref": "sales"
621
+ },
622
+ {
623
+ "aggregation": "AVG",
624
+ "fieldKey": "[Cars].[Sales In Thousands]",
625
+ "format": {
626
+ "formatType": "number2Decimal",
627
+ "negativeType": "parenthesis"
628
+ },
629
+ "ref": "targetSales"
630
+ }
631
+ ]
632
+ },
633
+ "filterGroup": {
634
+ "filters": [
635
+ {
636
+ "fieldKey": "[Cars].[Manufacturer]",
637
+ "operator": "inList",
638
+ "values": ["Acura", "Audi", "BMW"]
639
+ }
640
+ ],
641
+ "operator": "and"
642
+ },
643
+ "presentation": {
644
+ "displayMode": "radial",
645
+ "legend": {
646
+ "position": "right",
647
+ "title": "Cars comparison",
648
+ "visible": true
649
+ }
650
+ },
651
+ "type": "gauge",
652
+ "version": 1
653
+ }
654
+ ```
655
+
656
+ ## `heatMap`: Heat map
657
+
658
+ Two-dimensional matrix colored and optionally sized by measures.
659
+
660
+ **Data requirements**
661
+
662
+ - Exactly two dimensions.
663
+ - One or two measures.
664
+
665
+ **Supported features**
666
+
667
+ `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `legend`, `query-limit`, `sorting`
668
+
669
+ **Constraints and semantics**
670
+
671
+ - Dimension order maps to horizontal then vertical roles.
672
+ - Measure order maps to color then optional size roles.
673
+
674
+ **Canonical example**
675
+
676
+ ```json
677
+ {
678
+ "data": {
679
+ "dimensions": [
680
+ {
681
+ "fieldKey": "[Cars].[Manufacturer]",
682
+ "format": {
683
+ "formatType": "none"
684
+ },
685
+ "ref": "manufacturer"
686
+ },
687
+ {
688
+ "fieldKey": "[Cars].[Model]",
689
+ "format": {
690
+ "formatType": "none"
691
+ },
692
+ "ref": "model"
693
+ }
694
+ ],
695
+ "measures": [
696
+ {
697
+ "aggregation": "SUM",
698
+ "fieldKey": "[Cars].[Sales In Thousands]",
699
+ "format": {
700
+ "formatType": "number2Decimal",
701
+ "negativeType": "parenthesis"
702
+ },
703
+ "ref": "sales"
704
+ },
705
+ {
706
+ "aggregation": "AVG",
707
+ "fieldKey": "[Cars].[Horsepower]",
708
+ "format": {
709
+ "formatType": "number2Decimal",
710
+ "negativeType": "parenthesis"
711
+ },
712
+ "ref": "horsepower"
713
+ }
714
+ ]
715
+ },
716
+ "filterGroup": {
717
+ "filters": [
718
+ {
719
+ "fieldKey": "[Cars].[Manufacturer]",
720
+ "operator": "inList",
721
+ "values": ["Acura", "Audi", "BMW"]
722
+ }
723
+ ],
724
+ "operator": "and"
725
+ },
726
+ "limiting": {
727
+ "queryLimit": 100
728
+ },
729
+ "presentation": {
730
+ "axes": {
731
+ "dimension": {
732
+ "labelsVisible": true,
733
+ "title": "Manufacturer",
734
+ "titleVisible": true
735
+ },
736
+ "primaryMeasure": {
737
+ "labelsVisible": true,
738
+ "title": "Sales",
739
+ "titleVisible": true
740
+ },
741
+ "secondaryDimension": {
742
+ "labelsVisible": true,
743
+ "title": "Model",
744
+ "titleVisible": true
745
+ }
746
+ },
747
+ "legend": {
748
+ "position": "right",
749
+ "title": "Cars comparison",
750
+ "visible": true
751
+ }
752
+ },
753
+ "sorting": [
754
+ {
755
+ "by": "sales",
756
+ "direction": "desc"
757
+ }
758
+ ],
759
+ "type": "heatMap",
760
+ "version": 1
761
+ }
762
+ ```
763
+
764
+ ## `histogram`: Histogram
765
+
766
+ Distribution of a numeric field into generated bins and counts.
767
+
768
+ **Data requirements**
769
+
770
+ - Exactly one numeric dimension.
771
+ - No caller-supplied measures.
772
+
773
+ **Supported features**
774
+
775
+ `axes`, `axis-bands`, `axis-range`, `dimensions`, `filters`, `legend`, `orientation`, `value-formatting`
776
+
777
+ **Constraints and semantics**
778
+
779
+ - The compiler creates the canonical generated count measure; callers do not provide measures.
780
+ - presentation.axes.primaryMeasure.bands shades the plot between two primary measure axis values; start and end are measure values, and the bands replace any on the base vSpec.
781
+ - Set range on the primary measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on the primary measure axis to reverse its values.
782
+
783
+ **Canonical example**
784
+
785
+ ```json
786
+ {
787
+ "data": {
788
+ "dimensions": [
789
+ {
790
+ "fieldKey": "[Cars].[Horsepower]",
791
+ "format": {
792
+ "formatType": "none"
793
+ },
794
+ "ref": "horsepower"
795
+ }
796
+ ]
797
+ },
798
+ "filterGroup": {
799
+ "filters": [
800
+ {
801
+ "fieldKey": "[Cars].[Manufacturer]",
802
+ "operator": "inList",
803
+ "values": ["Acura", "Audi", "BMW"]
804
+ }
805
+ ],
806
+ "operator": "and"
807
+ },
808
+ "presentation": {
809
+ "axes": {
810
+ "dimension": {
811
+ "labelsVisible": true,
812
+ "title": "Horsepower",
813
+ "titleVisible": true
814
+ },
815
+ "primaryMeasure": {
816
+ "labelsVisible": true,
817
+ "title": "Count",
818
+ "titleVisible": true
819
+ }
820
+ },
821
+ "legend": {
822
+ "position": "right",
823
+ "title": "Cars comparison",
824
+ "visible": true
825
+ },
826
+ "orientation": "vertical"
827
+ },
828
+ "type": "histogram",
829
+ "version": 1
830
+ }
831
+ ```
832
+
833
+ ## `line`: Line chart
834
+
835
+ Trend chart with sorting, query limiting, dual measure axes, labels, legend, and orientation.
836
+
837
+ **Data requirements**
838
+
839
+ - At least one dimension.
840
+ - At least one measure.
841
+
842
+ **Supported features**
843
+
844
+ `axes`, `axis-bands`, `axis-range`, `axis-scale`, `conditional-coloring`, `data-labels`, `data-points`, `dimensions`, `filters`, `legend`, `measure-axis`, `measures`, `orientation`, `query-limit`, `sorting`, `value-formatting`
845
+
846
+ **Constraints and semantics**
847
+
848
+ - Each measure may select the primary or secondary axis using its axis property.
849
+ - Visible data labels require dataPointShape on every measure.
850
+ - presentation.axes.primaryMeasure.bands shades the plot between two primary measure axis values; start and end are measure values, and the bands replace any on the base vSpec.
851
+ - Set range on a measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on a measure axis to reverse its values, for example to put rank 1 at the top.
852
+ - Set scale to log on a measure axis to draw it logarithmically, with gridlines at powers of ten. Zero and negative values are drawn at the floor of a log axis.
853
+ - Value colors in presentation.coloring require at least two dimensions; measure color rules are not supported.
854
+
855
+ **Canonical example**
856
+
857
+ ```json
858
+ {
859
+ "data": {
860
+ "dimensions": [
861
+ {
862
+ "fieldKey": "[Cars].[Manufacturer]",
863
+ "format": {
864
+ "formatType": "none"
865
+ },
866
+ "ref": "manufacturer"
867
+ }
868
+ ],
869
+ "measures": [
870
+ {
871
+ "aggregation": "SUM",
872
+ "fieldKey": "[Cars].[Sales In Thousands]",
873
+ "format": {
874
+ "formatType": "number2Decimal",
875
+ "negativeType": "parenthesis"
876
+ },
877
+ "ref": "sales",
878
+ "axis": "primary",
879
+ "dataPointShape": "circle"
880
+ },
881
+ {
882
+ "aggregation": "AVG",
883
+ "fieldKey": "[Cars].[Horsepower]",
884
+ "format": {
885
+ "formatType": "number2Decimal",
886
+ "negativeType": "parenthesis"
887
+ },
888
+ "ref": "horsepower",
889
+ "axis": "secondary",
890
+ "dataPointShape": "square"
891
+ }
892
+ ]
893
+ },
894
+ "filterGroup": {
895
+ "filters": [
896
+ {
897
+ "fieldKey": "[Cars].[Manufacturer]",
898
+ "operator": "inList",
899
+ "values": ["Acura", "Audi", "BMW"]
900
+ }
901
+ ],
902
+ "operator": "and"
903
+ },
904
+ "limiting": {
905
+ "queryLimit": 100
906
+ },
907
+ "presentation": {
908
+ "axes": {
909
+ "dimension": {
910
+ "labelsVisible": true,
911
+ "title": "Manufacturer",
912
+ "titleVisible": true
913
+ },
914
+ "primaryMeasure": {
915
+ "labelsVisible": true,
916
+ "title": "Sales",
917
+ "titleVisible": true
918
+ },
919
+ "secondaryMeasure": {
920
+ "labelsVisible": true,
921
+ "title": "Horsepower",
922
+ "titleVisible": true
923
+ }
924
+ },
925
+ "dataLabels": {
926
+ "density": "medium",
927
+ "visible": true
928
+ },
929
+ "legend": {
930
+ "position": "right",
931
+ "title": "Cars comparison",
932
+ "visible": true
933
+ },
934
+ "orientation": "vertical"
935
+ },
936
+ "sorting": [
937
+ {
938
+ "by": "sales",
939
+ "direction": "desc"
940
+ }
941
+ ],
942
+ "type": "line",
943
+ "version": 1
944
+ }
945
+ ```
946
+
947
+ **Additional scenarios**
948
+
949
+ ### Fixed, inverted measure axis
950
+
951
+ ```json
952
+ {
953
+ "data": {
954
+ "dimensions": [
955
+ {
956
+ "fieldKey": "[Cars].[Manufacturer]",
957
+ "format": {
958
+ "formatType": "none"
959
+ },
960
+ "ref": "manufacturer"
961
+ }
962
+ ],
963
+ "measures": [
964
+ {
965
+ "aggregation": "SUM",
966
+ "fieldKey": "[Cars].[Sales In Thousands]",
967
+ "format": {
968
+ "formatType": "number2Decimal",
969
+ "negativeType": "parenthesis"
970
+ },
971
+ "ref": "sales",
972
+ "dataPointShape": "circle"
973
+ }
974
+ ]
975
+ },
976
+ "presentation": {
977
+ "axes": {
978
+ "primaryMeasure": {
979
+ "inverted": true,
980
+ "range": {
981
+ "max": 100,
982
+ "min": 1
983
+ },
984
+ "title": "Rank"
985
+ }
986
+ }
987
+ },
988
+ "type": "line",
989
+ "version": 1
990
+ }
991
+ ```
992
+
993
+ ### Series colored by dimension value
994
+
995
+ ```json
996
+ {
997
+ "data": {
998
+ "dimensions": [
999
+ {
1000
+ "fieldKey": "[Cars].[Manufacturer]",
1001
+ "format": {
1002
+ "formatType": "none"
1003
+ },
1004
+ "ref": "manufacturer"
1005
+ },
1006
+ {
1007
+ "fieldKey": "[Cars].[Model]",
1008
+ "format": {
1009
+ "formatType": "none"
1010
+ },
1011
+ "ref": "model"
1012
+ }
1013
+ ],
1014
+ "measures": [
1015
+ {
1016
+ "aggregation": "SUM",
1017
+ "fieldKey": "[Cars].[Sales In Thousands]",
1018
+ "format": {
1019
+ "formatType": "number2Decimal",
1020
+ "negativeType": "parenthesis"
1021
+ },
1022
+ "ref": "sales",
1023
+ "dataPointShape": "circle"
1024
+ }
1025
+ ]
1026
+ },
1027
+ "presentation": {
1028
+ "coloring": {
1029
+ "overwrites": [
1030
+ {
1031
+ "color": "#7C3AED",
1032
+ "operator": "startsWith",
1033
+ "value": "A"
1034
+ }
1035
+ ]
1036
+ }
1037
+ },
1038
+ "type": "line",
1039
+ "version": 1
1040
+ }
1041
+ ```
1042
+
1043
+ ## `radar`: Radar chart
1044
+
1045
+ Radial comparison chart for one or more measures with optional categorical dimensions.
1046
+
1047
+ **Data requirements**
1048
+
1049
+ - Zero to two dimensions.
1050
+ - Two to five measures without dimensions, or one with dimensions.
1051
+
1052
+ **Supported features**
1053
+
1054
+ `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend`
1055
+
1056
+ **Constraints and semantics**
1057
+
1058
+ - Without dimensions, at least two measures are required.
1059
+ - With dimensions, exactly one measure is supported.
1060
+ - Value colors in presentation.coloring require two dimensions; measure color rules are not supported.
1061
+
1062
+ **Canonical example**
1063
+
1064
+ ```json
1065
+ {
1066
+ "data": {
1067
+ "dimensions": [
1068
+ {
1069
+ "fieldKey": "[Cars].[Manufacturer]",
1070
+ "format": {
1071
+ "formatType": "none"
1072
+ },
1073
+ "ref": "manufacturer"
1074
+ }
1075
+ ],
1076
+ "measures": [
1077
+ {
1078
+ "aggregation": "SUM",
1079
+ "fieldKey": "[Cars].[Sales In Thousands]",
1080
+ "format": {
1081
+ "formatType": "number2Decimal",
1082
+ "negativeType": "parenthesis"
1083
+ },
1084
+ "ref": "sales"
1085
+ }
1086
+ ]
1087
+ },
1088
+ "filterGroup": {
1089
+ "filters": [
1090
+ {
1091
+ "fieldKey": "[Cars].[Manufacturer]",
1092
+ "operator": "inList",
1093
+ "values": ["Acura", "Audi", "BMW"]
1094
+ }
1095
+ ],
1096
+ "operator": "and"
1097
+ },
1098
+ "presentation": {
1099
+ "legend": {
1100
+ "position": "right",
1101
+ "title": "Cars comparison",
1102
+ "visible": true
1103
+ }
1104
+ },
1105
+ "type": "radar",
1106
+ "version": 1
1107
+ }
1108
+ ```
1109
+
1110
+ ## `pie`: Pie chart
1111
+
1112
+ Part-to-whole chart with optional secondary radial measure.
1113
+
1114
+ **Data requirements**
1115
+
1116
+ - Exactly one dimension.
1117
+ - One or two measures.
1118
+
1119
+ **Supported features**
1120
+
1121
+ `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend`, `query-limit`, `sorting`
1122
+
1123
+ **Constraints and semantics**
1124
+
1125
+ - The first measure is the slice value; the optional second measure receives the length role.
1126
+
1127
+ **Canonical example**
1128
+
1129
+ ```json
1130
+ {
1131
+ "data": {
1132
+ "dimensions": [
1133
+ {
1134
+ "fieldKey": "[Cars].[Manufacturer]",
1135
+ "format": {
1136
+ "formatType": "none"
1137
+ },
1138
+ "ref": "manufacturer"
1139
+ }
1140
+ ],
1141
+ "measures": [
1142
+ {
1143
+ "aggregation": "SUM",
1144
+ "fieldKey": "[Cars].[Sales In Thousands]",
1145
+ "format": {
1146
+ "formatType": "number2Decimal",
1147
+ "negativeType": "parenthesis"
1148
+ },
1149
+ "ref": "sales"
1150
+ }
1151
+ ]
1152
+ },
1153
+ "filterGroup": {
1154
+ "filters": [
1155
+ {
1156
+ "fieldKey": "[Cars].[Manufacturer]",
1157
+ "operator": "inList",
1158
+ "values": ["Acura", "Audi", "BMW"]
1159
+ }
1160
+ ],
1161
+ "operator": "and"
1162
+ },
1163
+ "limiting": {
1164
+ "queryLimit": 100
1165
+ },
1166
+ "presentation": {
1167
+ "legend": {
1168
+ "position": "right",
1169
+ "title": "Cars comparison",
1170
+ "visible": true
1171
+ }
1172
+ },
1173
+ "sorting": [
1174
+ {
1175
+ "by": "sales",
1176
+ "direction": "desc"
1177
+ }
1178
+ ],
1179
+ "type": "pie",
1180
+ "version": 1
1181
+ }
1182
+ ```
1183
+
1184
+ **Additional scenarios**
1185
+
1186
+ ### Ordered bands colored along a ramp
1187
+
1188
+ ```json
1189
+ {
1190
+ "data": {
1191
+ "dimensions": [
1192
+ {
1193
+ "fieldKey": "[Cars].[Manufacturer]",
1194
+ "format": {
1195
+ "formatType": "none"
1196
+ },
1197
+ "ref": "manufacturer"
1198
+ }
1199
+ ],
1200
+ "measures": [
1201
+ {
1202
+ "aggregation": "SUM",
1203
+ "fieldKey": "[Cars].[Sales In Thousands]",
1204
+ "format": {
1205
+ "formatType": "number2Decimal",
1206
+ "negativeType": "parenthesis"
1207
+ },
1208
+ "ref": "sales"
1209
+ }
1210
+ ]
1211
+ },
1212
+ "presentation": {
1213
+ "coloring": {
1214
+ "overwrites": [
1215
+ {
1216
+ "color": "#134E4A",
1217
+ "value": "Audi"
1218
+ },
1219
+ {
1220
+ "color": "#2DD4BF",
1221
+ "value": "BMW"
1222
+ },
1223
+ {
1224
+ "color": "#CCFBF1",
1225
+ "value": "Buick"
1226
+ }
1227
+ ]
1228
+ }
1229
+ },
1230
+ "type": "pie",
1231
+ "version": 1
1232
+ }
1233
+ ```
1234
+
1235
+ ## `tree`: Tree chart
1236
+
1237
+ Hierarchical tree built from dimensions, measures, or both.
1238
+
1239
+ **Data requirements**
1240
+
1241
+ - Zero to ten dimensions.
1242
+ - Zero to one hundred measures, or at most one with dimensions.
1243
+
1244
+ **Supported features**
1245
+
1246
+ `dimensions`, `filters`, `measures`, `value-formatting`, `layout`, `query-limit`, `sorting`
1247
+
1248
+ **Constraints and semantics**
1249
+
1250
+ - At least one dimension or measure must be supplied.
1251
+ - Trees with dimensions support at most one measure; measure-only trees may contain multiple measures.
1252
+
1253
+ **Canonical example**
1254
+
1255
+ ```json
1256
+ {
1257
+ "data": {
1258
+ "dimensions": [
1259
+ {
1260
+ "fieldKey": "[Cars].[Manufacturer]",
1261
+ "format": {
1262
+ "formatType": "none"
1263
+ },
1264
+ "ref": "manufacturer"
1265
+ },
1266
+ {
1267
+ "fieldKey": "[Cars].[Model]",
1268
+ "format": {
1269
+ "formatType": "none"
1270
+ },
1271
+ "ref": "model"
1272
+ }
1273
+ ],
1274
+ "measures": [
1275
+ {
1276
+ "aggregation": "SUM",
1277
+ "fieldKey": "[Cars].[Sales In Thousands]",
1278
+ "format": {
1279
+ "formatType": "number2Decimal",
1280
+ "negativeType": "parenthesis"
1281
+ },
1282
+ "ref": "sales"
1283
+ }
1284
+ ]
1285
+ },
1286
+ "filterGroup": {
1287
+ "filters": [
1288
+ {
1289
+ "fieldKey": "[Cars].[Manufacturer]",
1290
+ "operator": "inList",
1291
+ "values": ["Acura", "Audi", "BMW"]
1292
+ }
1293
+ ],
1294
+ "operator": "and"
1295
+ },
1296
+ "limiting": {
1297
+ "queryLimit": 100
1298
+ },
1299
+ "presentation": {
1300
+ "layout": {
1301
+ "compact": true,
1302
+ "direction": "top",
1303
+ "forceAutoFit": false,
1304
+ "initialExpandedLevels": 1
1305
+ }
1306
+ },
1307
+ "sorting": [
1308
+ {
1309
+ "by": "sales",
1310
+ "direction": "desc"
1311
+ }
1312
+ ],
1313
+ "type": "tree",
1314
+ "version": 1
1315
+ }
1316
+ ```
1317
+
1318
+ ## `treemap`: Treemap
1319
+
1320
+ Hierarchical area chart using ordered dimensions and one size measure.
1321
+
1322
+ **Data requirements**
1323
+
1324
+ - Between one and ten dimensions.
1325
+ - Exactly one measure.
1326
+
1327
+ **Supported features**
1328
+
1329
+ `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `legend`
1330
+
1331
+ **Constraints and semantics**
1332
+
1333
+ - Dimension order defines hierarchy depth.
1334
+
1335
+ **Canonical example**
1336
+
1337
+ ```json
1338
+ {
1339
+ "data": {
1340
+ "dimensions": [
1341
+ {
1342
+ "fieldKey": "[Cars].[Manufacturer]",
1343
+ "format": {
1344
+ "formatType": "none"
1345
+ },
1346
+ "ref": "manufacturer"
1347
+ },
1348
+ {
1349
+ "fieldKey": "[Cars].[Model]",
1350
+ "format": {
1351
+ "formatType": "none"
1352
+ },
1353
+ "ref": "model"
1354
+ }
1355
+ ],
1356
+ "measures": [
1357
+ {
1358
+ "aggregation": "SUM",
1359
+ "fieldKey": "[Cars].[Sales In Thousands]",
1360
+ "format": {
1361
+ "formatType": "number2Decimal",
1362
+ "negativeType": "parenthesis"
1363
+ },
1364
+ "ref": "sales"
1365
+ }
1366
+ ]
1367
+ },
1368
+ "filterGroup": {
1369
+ "filters": [
1370
+ {
1371
+ "fieldKey": "[Cars].[Manufacturer]",
1372
+ "operator": "inList",
1373
+ "values": ["Acura", "Audi", "BMW"]
1374
+ }
1375
+ ],
1376
+ "operator": "and"
1377
+ },
1378
+ "presentation": {
1379
+ "legend": {
1380
+ "position": "right",
1381
+ "title": "Cars comparison",
1382
+ "visible": true
1383
+ }
1384
+ },
1385
+ "type": "treemap",
1386
+ "version": 1
1387
+ }
1388
+ ```
1389
+
1390
+ ## `sankey`: Sankey chart
1391
+
1392
+ Flow chart across an ordered sequence of categorical dimensions.
1393
+
1394
+ **Data requirements**
1395
+
1396
+ - Between two and fifteen dimensions.
1397
+ - Exactly one measure.
1398
+
1399
+ **Supported features**
1400
+
1401
+ `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`
1402
+
1403
+ **Constraints and semantics**
1404
+
1405
+ - Dimension order defines the source-to-target flow stages.
1406
+ - Every value color in presentation.coloring must name the dimension it applies to.
1407
+
1408
+ **Canonical example**
1409
+
1410
+ ```json
1411
+ {
1412
+ "data": {
1413
+ "dimensions": [
1414
+ {
1415
+ "fieldKey": "[Cars].[Manufacturer]",
1416
+ "format": {
1417
+ "formatType": "none"
1418
+ },
1419
+ "ref": "manufacturer"
1420
+ },
1421
+ {
1422
+ "fieldKey": "[Cars].[Model]",
1423
+ "format": {
1424
+ "formatType": "none"
1425
+ },
1426
+ "ref": "model"
1427
+ }
1428
+ ],
1429
+ "measures": [
1430
+ {
1431
+ "aggregation": "SUM",
1432
+ "fieldKey": "[Cars].[Sales In Thousands]",
1433
+ "format": {
1434
+ "formatType": "number2Decimal",
1435
+ "negativeType": "parenthesis"
1436
+ },
1437
+ "ref": "sales"
1438
+ }
1439
+ ]
1440
+ },
1441
+ "filterGroup": {
1442
+ "filters": [
1443
+ {
1444
+ "fieldKey": "[Cars].[Manufacturer]",
1445
+ "operator": "inList",
1446
+ "values": ["Acura", "Audi", "BMW"]
1447
+ }
1448
+ ],
1449
+ "operator": "and"
1450
+ },
1451
+ "type": "sankey",
1452
+ "version": 1
1453
+ }
1454
+ ```
1455
+
1456
+ **Additional scenarios**
1457
+
1458
+ ### A color bound to a value of one flow stage
1459
+
1460
+ ```json
1461
+ {
1462
+ "data": {
1463
+ "dimensions": [
1464
+ {
1465
+ "fieldKey": "[Cars].[Manufacturer]",
1466
+ "format": {
1467
+ "formatType": "none"
1468
+ },
1469
+ "ref": "manufacturer"
1470
+ },
1471
+ {
1472
+ "fieldKey": "[Cars].[Model]",
1473
+ "format": {
1474
+ "formatType": "none"
1475
+ },
1476
+ "ref": "model"
1477
+ }
1478
+ ],
1479
+ "measures": [
1480
+ {
1481
+ "aggregation": "SUM",
1482
+ "fieldKey": "[Cars].[Sales In Thousands]",
1483
+ "format": {
1484
+ "formatType": "number2Decimal",
1485
+ "negativeType": "parenthesis"
1486
+ },
1487
+ "ref": "sales"
1488
+ }
1489
+ ]
1490
+ },
1491
+ "presentation": {
1492
+ "coloring": {
1493
+ "overwrites": [
1494
+ {
1495
+ "color": "#CA8A04",
1496
+ "dimension": "manufacturer",
1497
+ "value": "Audi"
1498
+ }
1499
+ ]
1500
+ }
1501
+ },
1502
+ "type": "sankey",
1503
+ "version": 1
1504
+ }
1505
+ ```
1506
+
1507
+ ## `scatter`: Scatter chart
1508
+
1509
+ Relationship chart using horizontal and vertical measures with optional size and image roles.
1510
+
1511
+ **Data requirements**
1512
+
1513
+ - One or two dimensions.
1514
+ - Two or three measures.
1515
+
1516
+ **Supported features**
1517
+
1518
+ `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`, `axes`, `axis-range`, `legend`, `query-limit`, `sorting`
1519
+
1520
+ **Constraints and semantics**
1521
+
1522
+ - Measure order maps to horizontal, vertical, and optional size roles.
1523
+ - The optional second dimension receives the image role.
1524
+ - Roles come from item order only; a ref is a label and does not select a role.
1525
+ - With a size measure, points scale between the setPointSize and setMaxPointSize operation values.
1526
+ - Set range on a measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on a measure axis to reverse its values, for example to put rank 1 at the top.
1527
+
1528
+ **Canonical example**
1529
+
1530
+ ```json
1531
+ {
1532
+ "data": {
1533
+ "dimensions": [
1534
+ {
1535
+ "fieldKey": "[Cars].[Manufacturer]",
1536
+ "format": {
1537
+ "formatType": "none"
1538
+ },
1539
+ "ref": "manufacturer"
1540
+ }
1541
+ ],
1542
+ "measures": [
1543
+ {
1544
+ "aggregation": "SUM",
1545
+ "fieldKey": "[Cars].[Sales In Thousands]",
1546
+ "format": {
1547
+ "formatType": "number2Decimal",
1548
+ "negativeType": "parenthesis"
1549
+ },
1550
+ "ref": "sales"
1551
+ },
1552
+ {
1553
+ "aggregation": "AVG",
1554
+ "fieldKey": "[Cars].[Horsepower]",
1555
+ "format": {
1556
+ "formatType": "number2Decimal",
1557
+ "negativeType": "parenthesis"
1558
+ },
1559
+ "ref": "horsepower"
1560
+ },
1561
+ {
1562
+ "aggregation": "AVG",
1563
+ "fieldKey": "[Cars].[Sales In Thousands]",
1564
+ "format": {
1565
+ "formatType": "number2Decimal",
1566
+ "negativeType": "parenthesis"
1567
+ },
1568
+ "ref": "size"
1569
+ }
1570
+ ]
1571
+ },
1572
+ "filterGroup": {
1573
+ "filters": [
1574
+ {
1575
+ "fieldKey": "[Cars].[Manufacturer]",
1576
+ "operator": "inList",
1577
+ "values": ["Acura", "Audi", "BMW"]
1578
+ }
1579
+ ],
1580
+ "operator": "and"
1581
+ },
1582
+ "presentation": {
1583
+ "axes": {
1584
+ "primaryMeasure": {
1585
+ "labelsVisible": true,
1586
+ "title": "Sales",
1587
+ "titleVisible": true
1588
+ },
1589
+ "secondaryMeasure": {
1590
+ "labelsVisible": true,
1591
+ "title": "Horsepower",
1592
+ "titleVisible": true
1593
+ }
1594
+ },
1595
+ "legend": {
1596
+ "position": "right",
1597
+ "title": "Cars comparison",
1598
+ "visible": true
1599
+ }
1600
+ },
1601
+ "type": "scatter",
1602
+ "version": 1
1603
+ }
1604
+ ```
1605
+
1606
+ ## `table`: Table
1607
+
1608
+ Normal, expandable, or pivot tabular output with formatting, filtering, sorting, query limiting, and totals.
1609
+
1610
+ **Data requirements**
1611
+
1612
+ - Normal tables require at least one ordered dimension or measure column.
1613
+ - Expandable tables require at least one dimension and one measure.
1614
+ - Pivot tables require at least one row dimension, one column dimension, and one measure.
1615
+
1616
+ **Supported features**
1617
+
1618
+ `dimensions`, `filters`, `layout`, `measures`, `query-limit`, `sorting`, `table-structure`, `totals`, `value-formatting`
1619
+
1620
+ **Constraints and semantics**
1621
+
1622
+ - Normal table column order is preserved, and each column declares whether it is a dimension or measure.
1623
+ - Expandable table dimension order defines the expansion hierarchy.
1624
+ - Pivot tables explicitly separate row dimensions, column dimensions, and measures.
1625
+ - Measure definitions require valid aggregation for raw fields.
1626
+ - Presentation settings initialize table appearance and layout; later runtime operations preserve them.
1627
+ - Totals settings are optional; omitted totals properties preserve their values from the fresh default or preset vSpec.
1628
+
1629
+ **Canonical example**
1630
+
1631
+ ```json
1632
+ {
1633
+ "data": {
1634
+ "columns": [
1635
+ {
1636
+ "fieldKey": "[Cars].[Manufacturer]",
1637
+ "format": {
1638
+ "formatType": "none"
1639
+ },
1640
+ "ref": "manufacturer",
1641
+ "role": "dimension"
1642
+ },
1643
+ {
1644
+ "fieldKey": "[Cars].[Model]",
1645
+ "format": {
1646
+ "formatType": "none"
1647
+ },
1648
+ "ref": "model",
1649
+ "role": "dimension"
1650
+ },
1651
+ {
1652
+ "aggregation": "SUM",
1653
+ "fieldKey": "[Cars].[Sales In Thousands]",
1654
+ "format": {
1655
+ "formatType": "number2Decimal",
1656
+ "negativeType": "parenthesis"
1657
+ },
1658
+ "ref": "sales",
1659
+ "role": "measure"
1660
+ }
1661
+ ],
1662
+ "structure": "normal"
1663
+ },
1664
+ "filterGroup": {
1665
+ "filters": [
1666
+ {
1667
+ "fieldKey": "[Cars].[Manufacturer]",
1668
+ "operator": "inList",
1669
+ "values": ["Acura", "Audi", "BMW"]
1670
+ }
1671
+ ],
1672
+ "operator": "and"
1673
+ },
1674
+ "limiting": {
1675
+ "queryLimit": 100
1676
+ },
1677
+ "presentation": {
1678
+ "background": {
1679
+ "color": "#ffffff",
1680
+ "type": "single"
1681
+ },
1682
+ "body": {
1683
+ "fontColor": "#1f1c3b",
1684
+ "fontFamily": "Roboto",
1685
+ "fontSize": 13,
1686
+ "horizontalAlign": "center",
1687
+ "verticalAlign": "middle"
1688
+ },
1689
+ "borders": {
1690
+ "color": "#e0e0e0",
1691
+ "dividerColor": "#e0e0e0",
1692
+ "dividers": "all",
1693
+ "enabled": true,
1694
+ "lineStyle": "line",
1695
+ "radius": 4,
1696
+ "strokeWidth": 1
1697
+ },
1698
+ "header": {
1699
+ "backgroundColor": "#ffffff",
1700
+ "borderColor": "#e0e0e0",
1701
+ "fontColor": "#1f1c3b",
1702
+ "fontFamily": "Roboto",
1703
+ "fontSize": 13
1704
+ },
1705
+ "highlight": {
1706
+ "backgroundColor": "#f2f2f2",
1707
+ "mode": "row"
1708
+ },
1709
+ "layout": {
1710
+ "columnWidthBehavior": "responsive",
1711
+ "rowHeight": 41
1712
+ }
1713
+ },
1714
+ "sorting": [
1715
+ {
1716
+ "by": "sales",
1717
+ "direction": "desc"
1718
+ }
1719
+ ],
1720
+ "totals": {
1721
+ "applyTo": "both",
1722
+ "enabled": true,
1723
+ "showRecordsCount": true,
1724
+ "style": {
1725
+ "backgroundColor": "#f3f4f6",
1726
+ "fontColor": "#111827",
1727
+ "fontStyle": {
1728
+ "bold": true
1729
+ },
1730
+ "position": "bottom",
1731
+ "responsiveHeight": true
1732
+ }
1733
+ },
1734
+ "type": "table",
1735
+ "version": 1
1736
+ }
1737
+ ```
1738
+
1739
+ **Additional scenarios**
1740
+
1741
+ ### Expandable table
1742
+
1743
+ ```json
1744
+ {
1745
+ "data": {
1746
+ "dimensions": [
1747
+ {
1748
+ "fieldKey": "[Cars].[Manufacturer]",
1749
+ "format": {
1750
+ "formatType": "none"
1751
+ },
1752
+ "ref": "manufacturer"
1753
+ },
1754
+ {
1755
+ "fieldKey": "[Cars].[Model]",
1756
+ "format": {
1757
+ "formatType": "none"
1758
+ },
1759
+ "ref": "model"
1760
+ }
1761
+ ],
1762
+ "measures": [
1763
+ {
1764
+ "aggregation": "SUM",
1765
+ "fieldKey": "[Cars].[Sales In Thousands]",
1766
+ "format": {
1767
+ "formatType": "number2Decimal",
1768
+ "negativeType": "parenthesis"
1769
+ },
1770
+ "ref": "sales"
1771
+ }
1772
+ ],
1773
+ "structure": "expandable"
1774
+ },
1775
+ "filterGroup": {
1776
+ "filters": [
1777
+ {
1778
+ "fieldKey": "[Cars].[Manufacturer]",
1779
+ "operator": "inList",
1780
+ "values": ["Acura", "Audi", "BMW"]
1781
+ }
1782
+ ],
1783
+ "operator": "and"
1784
+ },
1785
+ "limiting": {
1786
+ "queryLimit": 100
1787
+ },
1788
+ "sorting": [
1789
+ {
1790
+ "by": "sales",
1791
+ "direction": "desc"
1792
+ }
1793
+ ],
1794
+ "type": "table",
1795
+ "version": 1
1796
+ }
1797
+ ```
1798
+
1799
+ ### Pivot table
1800
+
1801
+ ```json
1802
+ {
1803
+ "data": {
1804
+ "columnDimensions": [
1805
+ {
1806
+ "fieldKey": "[Cars].[Model]",
1807
+ "format": {
1808
+ "formatType": "none"
1809
+ },
1810
+ "ref": "model"
1811
+ }
1812
+ ],
1813
+ "measures": [
1814
+ {
1815
+ "aggregation": "SUM",
1816
+ "fieldKey": "[Cars].[Sales In Thousands]",
1817
+ "format": {
1818
+ "formatType": "number2Decimal",
1819
+ "negativeType": "parenthesis"
1820
+ },
1821
+ "ref": "sales"
1822
+ }
1823
+ ],
1824
+ "rowDimensions": [
1825
+ {
1826
+ "fieldKey": "[Cars].[Manufacturer]",
1827
+ "format": {
1828
+ "formatType": "none"
1829
+ },
1830
+ "ref": "manufacturer"
1831
+ }
1832
+ ],
1833
+ "structure": "pivot"
1834
+ },
1835
+ "filterGroup": {
1836
+ "filters": [
1837
+ {
1838
+ "fieldKey": "[Cars].[Manufacturer]",
1839
+ "operator": "inList",
1840
+ "values": ["Acura", "Audi", "BMW"]
1841
+ }
1842
+ ],
1843
+ "operator": "and"
1844
+ },
1845
+ "limiting": {
1846
+ "queryLimit": 100
1847
+ },
1848
+ "sorting": [
1849
+ {
1850
+ "by": "sales",
1851
+ "direction": "desc"
1852
+ }
1853
+ ],
1854
+ "type": "table",
1855
+ "version": 1
1856
+ }
1857
+ ```
1858
+
1859
+ ## `waterfall`: Waterfall chart
1860
+
1861
+ Sequential contribution chart composed from one or more measures.
1862
+
1863
+ **Data requirements**
1864
+
1865
+ - Between one and one hundred measures.
1866
+
1867
+ **Supported features**
1868
+
1869
+ `axes`, `axis-bands`, `axis-range`, `data-labels`, `filters`, `measures`, `orientation`, `value-formatting`
1870
+
1871
+ **Constraints and semantics**
1872
+
1873
+ - Dimensions are not supported. Measure order defines the waterfall sequence.
1874
+ - Set range on the primary measure axis to fix its min, max, or both, for example to give several charts one shared scale; leave both unset and set startsAtZero to keep an auto-fitted axis anchored at zero. Set inverted on the primary measure axis to reverse its values.
1875
+ - presentation.axes.primaryMeasure.bands shades the plot between two primary measure axis values; start and end are measure values, and the bands replace any on the base vSpec.
1876
+
1877
+ **Canonical example**
1878
+
1879
+ ```json
1880
+ {
1881
+ "data": {
1882
+ "measures": [
1883
+ {
1884
+ "aggregation": "SUM",
1885
+ "fieldKey": "[Cars].[Sales In Thousands]",
1886
+ "format": {
1887
+ "formatType": "number2Decimal",
1888
+ "negativeType": "parenthesis"
1889
+ },
1890
+ "ref": "sales",
1891
+ "dataLabels": {
1892
+ "visible": true
1893
+ }
1894
+ },
1895
+ {
1896
+ "aggregation": "AVG",
1897
+ "fieldKey": "[Cars].[Horsepower]",
1898
+ "format": {
1899
+ "formatType": "number2Decimal",
1900
+ "negativeType": "parenthesis"
1901
+ },
1902
+ "ref": "horsepower",
1903
+ "dataLabels": {
1904
+ "visible": true
1905
+ }
1906
+ }
1907
+ ]
1908
+ },
1909
+ "filterGroup": {
1910
+ "filters": [
1911
+ {
1912
+ "fieldKey": "[Cars].[Manufacturer]",
1913
+ "operator": "inList",
1914
+ "values": ["Acura", "Audi", "BMW"]
1915
+ }
1916
+ ],
1917
+ "operator": "and"
1918
+ },
1919
+ "presentation": {
1920
+ "axes": {
1921
+ "dimension": {
1922
+ "labelsVisible": true,
1923
+ "title": "Measure",
1924
+ "titleVisible": true
1925
+ },
1926
+ "primaryMeasure": {
1927
+ "labelsVisible": true,
1928
+ "title": "Value",
1929
+ "titleVisible": true
1930
+ }
1931
+ },
1932
+ "dataLabels": {
1933
+ "visible": true
1934
+ },
1935
+ "orientation": "vertical"
1936
+ },
1937
+ "type": "waterfall",
1938
+ "version": 1
1939
+ }
1940
+ ```
1941
+
1942
+ ## `word-cloud`: Word cloud
1943
+
1944
+ Weighted word display using one label dimension and one measure.
1945
+
1946
+ **Data requirements**
1947
+
1948
+ - Exactly one dimension.
1949
+ - Exactly one measure.
1950
+
1951
+ **Supported features**
1952
+
1953
+ `dimensions`, `filters`, `measures`, `value-formatting`, `conditional-coloring`
1954
+
1955
+ **Constraints and semantics**
1956
+
1957
+ - The dimension supplies words and the measure supplies their weight.
1958
+
1959
+ **Canonical example**
1960
+
1961
+ ```json
1962
+ {
1963
+ "data": {
1964
+ "dimensions": [
1965
+ {
1966
+ "fieldKey": "[Cars].[Manufacturer]",
1967
+ "format": {
1968
+ "formatType": "none"
1969
+ },
1970
+ "ref": "manufacturer"
1971
+ }
1972
+ ],
1973
+ "measures": [
1974
+ {
1975
+ "aggregation": "SUM",
1976
+ "fieldKey": "[Cars].[Sales In Thousands]",
1977
+ "format": {
1978
+ "formatType": "number2Decimal",
1979
+ "negativeType": "parenthesis"
1980
+ },
1981
+ "ref": "sales"
1982
+ }
1983
+ ]
1984
+ },
1985
+ "filterGroup": {
1986
+ "filters": [
1987
+ {
1988
+ "fieldKey": "[Cars].[Manufacturer]",
1989
+ "operator": "inList",
1990
+ "values": ["Acura", "Audi", "BMW"]
1991
+ }
1992
+ ],
1993
+ "operator": "and"
1994
+ },
1995
+ "type": "word-cloud",
1996
+ "version": 1
1997
+ }
1998
+ ```
1999
+
2000
+ ## `date-picker`: Date picker
2001
+
2002
+ Date selection control with single/range modes, labels, quick select, and responsive settings.
2003
+
2004
+ **Data requirements**
2005
+
2006
+ - Exactly one field.
2007
+
2008
+ **Supported features**
2009
+
2010
+ `dimensions`, `filter-settings`
2011
+
2012
+ **Constraints and semantics**
2013
+
2014
+ - The selected field must be date- or timestamp-compatible.
2015
+
2016
+ **Canonical example**
2017
+
2018
+ ```json
2019
+ {
2020
+ "data": {
2021
+ "field": {
2022
+ "fieldKey": "[Cars].[Latest Launch]",
2023
+ "ref": "latestLaunch"
2024
+ }
2025
+ },
2026
+ "settings": {
2027
+ "endDateLabel": "To",
2028
+ "pickerState": "expanded",
2029
+ "pickerType": "range",
2030
+ "quickSelect": true,
2031
+ "responsive": true,
2032
+ "startDateLabel": "From",
2033
+ "timePickerVisibility": "never",
2034
+ "weekStart": "1"
2035
+ },
2036
+ "type": "date-picker",
2037
+ "version": 1
2038
+ }
2039
+ ```
2040
+
2041
+ ## `filter`: Filter
2042
+
2043
+ Interactive field filter with list/dropdown presentation and search/quick-select controls.
2044
+
2045
+ **Data requirements**
2046
+
2047
+ - Exactly one field.
2048
+
2049
+ **Supported features**
2050
+
2051
+ `dimensions`, `filter-settings`
2052
+
2053
+ **Constraints and semantics**
2054
+
2055
+ - The selected field is used as a filter dimension.
2056
+
2057
+ **Canonical example**
2058
+
2059
+ ```json
2060
+ {
2061
+ "data": {
2062
+ "field": {
2063
+ "fieldKey": "[Cars].[Manufacturer]",
2064
+ "ref": "manufacturer"
2065
+ }
2066
+ },
2067
+ "presentation": {
2068
+ "mode": "listbox",
2069
+ "quickSelect": true,
2070
+ "responsive": true,
2071
+ "searchable": true,
2072
+ "showProgressBar": false
2073
+ },
2074
+ "type": "filter",
2075
+ "version": 1
2076
+ }
2077
+ ```
2078
+
2079
+ ## `iframe`: Iframe
2080
+
2081
+ Embedded external web content.
2082
+
2083
+ **Data requirements**
2084
+
2085
+ - No query data.
2086
+
2087
+ **Supported features**
2088
+
2089
+ `content`
2090
+
2091
+ **Constraints and semantics**
2092
+
2093
+ - The URL must be absolute and valid; null clears the source.
2094
+
2095
+ **Canonical example**
2096
+
2097
+ ```json
2098
+ {
2099
+ "settings": {
2100
+ "url": "https://example.com"
2101
+ },
2102
+ "type": "iframe",
2103
+ "version": 1
2104
+ }
2105
+ ```
2106
+
2107
+ ## `image`: Image
2108
+
2109
+ Image content with fit, opacity, blur, saturation, and shadow controls.
2110
+
2111
+ **Data requirements**
2112
+
2113
+ - No query data.
2114
+
2115
+ **Supported features**
2116
+
2117
+ `content`, `object-settings`
2118
+
2119
+ **Constraints and semantics**
2120
+
2121
+ - The source must use one of the supported image source variants.
2122
+
2123
+ **Canonical example**
2124
+
2125
+ ```json
2126
+ {
2127
+ "settings": {
2128
+ "blur": 0,
2129
+ "fit": "contain",
2130
+ "opacity": 0.95,
2131
+ "saturation": 0.9,
2132
+ "shadow": true,
2133
+ "source": {
2134
+ "imageUrl": "https://example.com/image.png",
2135
+ "sourceKind": "url"
2136
+ }
2137
+ },
2138
+ "type": "image",
2139
+ "version": 1
2140
+ }
2141
+ ```
2142
+
2143
+ ## `number`: Number
2144
+
2145
+ Single aggregated or semantic value with value formatting and static filters.
2146
+
2147
+ **Data requirements**
2148
+
2149
+ - Exactly one measure.
2150
+
2151
+ **Supported features**
2152
+
2153
+ `filters`, `measures`, `value-formatting`
2154
+
2155
+ **Constraints and semantics**
2156
+
2157
+ - A raw field measure requires aggregation; semantic measures and calculations omit it.
2158
+
2159
+ **Canonical example**
2160
+
2161
+ ```json
2162
+ {
2163
+ "data": {
2164
+ "measure": {
2165
+ "aggregation": "SUM",
2166
+ "fieldKey": "[Cars].[Sales In Thousands]",
2167
+ "format": {
2168
+ "formatType": "number2Decimal",
2169
+ "negativeType": "parenthesis"
2170
+ },
2171
+ "ref": "sales"
2172
+ }
2173
+ },
2174
+ "filterGroup": {
2175
+ "filters": [
2176
+ {
2177
+ "fieldKey": "[Cars].[Manufacturer]",
2178
+ "operator": "inList",
2179
+ "values": ["Acura", "Audi", "BMW"]
2180
+ }
2181
+ ],
2182
+ "operator": "and"
2183
+ },
2184
+ "type": "number",
2185
+ "version": 1
2186
+ }
2187
+ ```
2188
+
2189
+ ## `shape`: Shape
2190
+
2191
+ Decorative shape with fill, stroke, sizing, rotation, and border controls.
2192
+
2193
+ **Data requirements**
2194
+
2195
+ - No query data.
2196
+
2197
+ **Supported features**
2198
+
2199
+ `object-settings`
2200
+
2201
+ **Constraints and semantics**
2202
+
2203
+ - Image-specific settings apply only when the selected shape/background mode supports them.
2204
+
2205
+ **Canonical example**
2206
+
2207
+ ```json
2208
+ {
2209
+ "settings": {
2210
+ "backgroundColor": {
2211
+ "code": "#2e6e9e"
2212
+ },
2213
+ "backgroundType": "color",
2214
+ "borderEnabled": true,
2215
+ "borderRadius": 8,
2216
+ "heightBasedSize": false,
2217
+ "lineThickness": 4,
2218
+ "preserveAspectRatio": true,
2219
+ "rotate": 12,
2220
+ "scale": 0.7,
2221
+ "shape": "hexagon",
2222
+ "strokeColor": {
2223
+ "code": "#18212b"
2224
+ }
2225
+ },
2226
+ "type": "shape",
2227
+ "version": 1
2228
+ }
2229
+ ```
2230
+
2231
+ ## `simpleTextObject`: Text object
2232
+
2233
+ Text or Markdown content with typography, alignment, wrapping, and responsive controls.
2234
+
2235
+ **Data requirements**
2236
+
2237
+ - No query data.
2238
+
2239
+ **Supported features**
2240
+
2241
+ `content`, `object-settings`
2242
+
2243
+ **Constraints and semantics**
2244
+
2245
+ - Content interpretation follows the selected representation.
2246
+
2247
+ **Canonical example**
2248
+
2249
+ ```json
2250
+ {
2251
+ "settings": {
2252
+ "align": "center",
2253
+ "content": "## Revenue overview",
2254
+ "fontFamily": "Arial",
2255
+ "fontSize": 30,
2256
+ "position": "middle",
2257
+ "representation": "markdown",
2258
+ "responsive": true,
2259
+ "textColor": "#18212b",
2260
+ "wordWrap": true
2261
+ },
2262
+ "type": "simpleTextObject",
2263
+ "version": 1
2264
+ }
2265
+ ```
2266
+
2267
+ ## `atomic-input`: Atomic input
2268
+
2269
+ Variable input control with input type, label, placeholder, and responsive settings.
2270
+
2271
+ **Data requirements**
2272
+
2273
+ - No query data; variable-backed input.
2274
+
2275
+ **Supported features**
2276
+
2277
+ `input-settings`
2278
+
2279
+ **Constraints and semantics**
2280
+
2281
+ - The referenced variable must exist in the host variable service when variable behavior is used.
2282
+
2283
+ **Canonical example**
2284
+
2285
+ ```json
2286
+ {
2287
+ "settings": {
2288
+ "customLabel": {
2289
+ "enabled": true,
2290
+ "text": "Target"
2291
+ },
2292
+ "inputType": "text",
2293
+ "placeholder": "Enter target",
2294
+ "responsive": true,
2295
+ "variableId": "target-variable"
2296
+ },
2297
+ "type": "atomic-input",
2298
+ "version": 1
2299
+ }
2300
+ ```
2301
+
2302
+ ## `astrato-app-filter-bar`: Astrato App Filter Bar
2303
+
2304
+ App filter bar settings for selection behavior, filter creation, associative filtering, and selectable fields.
2305
+
2306
+ **Data requirements**
2307
+
2308
+ - No query data; uses field metadata and selections supplied by the host.
2309
+
2310
+ **Supported features**
2311
+
2312
+ `selection-settings`
2313
+
2314
+ **Constraints and semantics**
2315
+
2316
+ - Orientation defaults to horizontal. Use vertical for stacked sidebar filters; editors open beside the sidebar when space permits.
2317
+ - The bar displays active selections from its selection group, regardless of the fields allowed for creating new filters.
2318
+ - An empty selectableFieldKeys list allows users to create filters on any selectable field.
2319
+ - Selection mode overrides apply only to selections created by this bar; apply, cancel, and clear affect the shared selection group.
2320
+ - Chart breakdown switching is hidden by default. Enable showChartBreakdown only when the app uses dimension groups; a group must have multiple available fields for the control to appear.
2321
+
2322
+ **Canonical example**
2323
+
2324
+ ```json
2325
+ {
2326
+ "settings": {
2327
+ "enableAddingNewFilters": true,
2328
+ "enableAssociativeFilter": true,
2329
+ "selectableFieldKeys": ["[Cars].[Manufacturer]", "[Cars].[Model]"],
2330
+ "selectionMode": "inherit",
2331
+ "showChartBreakdown": false,
2332
+ "showClearAll": true
2333
+ },
2334
+ "type": "astrato-app-filter-bar",
2335
+ "version": 1
2336
+ }
2337
+ ```
2338
+
2339
+ ## `slider`: Slider
2340
+
2341
+ Numeric or date range control with single/multi layout, step, and quick select.
2342
+
2343
+ **Data requirements**
2344
+
2345
+ - Exactly one field.
2346
+
2347
+ **Supported features**
2348
+
2349
+ `dimensions`, `filter-settings`
2350
+
2351
+ **Constraints and semantics**
2352
+
2353
+ - The field must be numeric or date-compatible with the configured range and step.
2354
+ - Providing range enables manual bounds; omitting it keeps data-derived bounds.
2355
+
2356
+ **Canonical example**
2357
+
2358
+ ```json
2359
+ {
2360
+ "data": {
2361
+ "field": {
2362
+ "fieldKey": "[Cars].[Horsepower]",
2363
+ "ref": "horsepower"
2364
+ }
2365
+ },
2366
+ "settings": {
2367
+ "layout": "multi",
2368
+ "quickSelect": true,
2369
+ "range": {
2370
+ "max": 500,
2371
+ "min": 0
2372
+ },
2373
+ "step": 10
2374
+ },
2375
+ "type": "slider",
2376
+ "version": 1
2377
+ }
2378
+ ```