Graflume · Alpha
Carpet · Extreme-environment application
Warp a logical coordinate grid through supplied physical positions and overlay points or contours on that surface. Combine container size, input method, display capability, and user preference instead of guessing a device name. Compare mobile, watch, e-paper, monochrome, dot-matrix, and standards-based extreme environments on the same chart.
Chart family · Advanced families
Carpet
Warp a logical coordinate grid through supplied physical positions and overlay points or contours on that surface.
- Quick API
carpet()- Browser snapshot
graflume/complete- mark
carpet- Presets
- 3
Extreme environments
Reconfigure for display, input, and device capability
Combine container size, input method, display capability, and user preference instead of guessing a device name. Compare mobile, watch, e-paper, monochrome, dot-matrix, and standards-based extreme environments on the same chart.
Fluid responsive
Reflow axes, legends, descriptions, and controls from the available container size.
960×540 · adaptive.profiles=responsive-fluidzoom-reflowshape-rectangledisplay-colorinput-finemotion-fullrenderer-canvas-spatial
Mobile
Prioritize 44px touch targets, tap tooltips, and collapsed secondary information on a narrow portrait screen.
390×844 · adaptive.profiles=mobile-touchzoom-reflowcoarse-touchvirtual-keyboardshape-rectangledisplay-colorinput-coarsemotion-fullrenderer-canvas-spatial
Smartwatch
Keep essential marks, values, and stepped controls on a tiny or round screen, with the remaining detail reflowed below.
184×224 · adaptive.profiles=smartwatchzoom-reflowreduced-effectscoarse-touchlow-resourcecutout-roundshape-rounddisplay-colorinput-coarsemotion-reducedrenderer-canvas-spatialviewport-tiny
E-book and e-paper
Prefer stable frames, strong contrast, and the data table for low-refresh e-paper displays.
758×1024 · adaptive.profiles=ebook-paperprint-pagedreduced-effectslow-resourceshape-pageddisplay-e-inkinput-keyboardmotion-staticrenderer-canvas-spatial
Monochrome
Use strokes, markers, patterns, labels, and the table so color is never the only distinction.
640×400 · adaptive.profiles=monochromereduced-effectsshape-rectangledisplay-monochromeinput-finemotion-reducedrenderer-canvas-spatial
Dot-matrix display
Reduce decoration and mark density while using strong strokes, integer labels, and stepped zoom on a low-resolution display.
320×240 · adaptive.profiles=dot-matrixzoom-reflowreduced-effectskeyboard-switchlow-resourceshape-rectangledisplay-gridinput-keyboardmotion-staticrenderer-canvas-spatialviewport-tiny
400% zoom and reflow
Reflow prose to one dimension at the 320 CSS px equivalent while retaining chart-local zoom and pan.
320×480 · adaptive.profiles=zoom-reflowzoom-reflowshape-rectangledisplay-colorinput-finemotion-fullrenderer-canvas-spatial
Foldable dual screen
Keep the chart and explanation in independent viewport segments without crossing the hinge.
720×640 · adaptive.profiles=foldable-dualfoldable-dualshape-dualdisplay-colorinput-finemotion-fullrenderer-canvas-spatial
TV and remote
Provide strong focus indication and D-pad, Enter, and Escape operation on a hoverless distance display.
1920×1080 · adaptive.profiles=tv-remotetv-remoteshape-rectangledisplay-colorinput-remotemotion-fullrenderer-canvas-spatial
Print and paged media
Pair a static chart with its description and table, hide controls, and avoid page breaks through the figure.
794×1123 · adaptive.profiles=print-pagedprint-pagedshape-pageddisplay-colorinput-finemotion-staticrenderer-canvas-spatial
Forced colors
Honor system colors and borders while retaining patterns, markers, and text as redundant cues.
640×400 · adaptive.profiles=forced-colorsforced-colorsshape-rectangledisplay-high-contrastinput-finemotion-fullrenderer-canvas-spatial
Reduced effects
Complete transitions immediately and use opaque surfaces and deferred work to reduce motion and transparency load.
640×400 · adaptive.profiles=reduced-effectsreduced-effectsshape-rectangledisplay-colorinput-finemotion-reducedrenderer-canvas-spatial
Coarse touch
Inspect values by tap without hover, keep targets at least 44px, and expose explicit zoom buttons.
390×844 · adaptive.profiles=coarse-touchcoarse-touchshape-rectangledisplay-colorinput-coarsemotion-fullrenderer-canvas-spatial
Keyboard and switch input
Reach every operation with Tab, arrows, Enter, Space, and Escape, with no drag-only action.
640×400 · adaptive.profiles=keyboard-switchkeyboard-switchshape-rectangledisplay-colorinput-keyboardmotion-fullrenderer-canvas-spatial
Low resource and slow network
Prefer progressive rendering, sampling, cancellable work, and a static fallback under constrained memory or connectivity.
640×400 · adaptive.profiles=low-resourcelow-resourceshape-rectangledisplay-colorinput-finemotion-fullrenderer-canvas-spatial
RTL document
Follow RTL logical flow for prose and tabs while keeping axes, code, and data identifiers in technical LTR order.
640×400 · adaptive.profiles=rtlrtlshape-rectangledisplay-colorinput-finemotion-fullrenderer-canvas-spatial
Vertical writing
Reflow vertical prose while keeping the chart and technical surfaces in an independent horizontal panel.
640×400 · adaptive.profiles=vertical-writingvertical-writingshape-rectangledisplay-colorinput-finemotion-fullrenderer-canvas-spatial
Ultrawide and projection
Cap chart width instead of stretching indefinitely, using panelization and readable labels on ultrawide or projected surfaces.
1920×720 · adaptive.profiles=ultrawide-projectionultrawide-projectionshape-rectangledisplay-colorinput-finemotion-fullrenderer-canvas-spatial
Screen reader and braille
Provide short and long descriptions, a semantic table, and status so Canvas or color is never the sole information path.
640×400 · adaptive.profiles=screenreader-braillescreenreader-brailleshape-nonvisualdisplay-colorinput-nonvisualmotion-fullrenderer-canvas-spatial
No scripting
A verified static preview, description, and collapsible row-data table preserve the essential information when scripting is unavailable.
640×400 · adaptive.profiles=no-scriptno-scriptshape-nonvisualdisplay-colorinput-finemotion-staticrenderer-static-fallback
XR and see-through display
Fall back safely to the ordinary 2D or WebGL panel when XR APIs are absent, duplicating depth cues in text and the table.
640×400 · adaptive.profiles=spatial-xrspatial-xrshape-rectangledisplay-colorinput-finemotion-fullrenderer-canvas-spatial
Cutout and round display
Inset titles, marks, and controls around safe areas and round display bounds so they are not clipped.
184×224 · adaptive.profiles=cutout-roundcutout-roundshape-rounddisplay-colorinput-finemotion-fullrenderer-canvas-spatialviewport-tiny
Virtual keyboard viewport
Reflow focus controls, the chart, and the active explanation when a virtual keyboard reduces the visual viewport.
390×560 · adaptive.profiles=virtual-keyboardvirtual-keyboardshape-rectangledisplay-colorinput-finemotion-fullrenderer-canvas-spatial
Extreme environment preview
Choose a profile above to preserve the same data and ChartSpec while reconfiguring the chart for display size, input method, display capability, and user preference.
StatusLoading
adaptivecapability-drivenno-user-agent-branching
- Legend:
legend · continuous · value - Point and range highlights:
highlights[] · datum · px - Custom callouts:
annotations[] · datum · px · callout · placement:auto - Interactive selection:
selection · multiple · toggle
Loading
Extreme environment preview · Row data
Row data and zero-copy TypedArray columns share one data contract.
aquantitative | bquantitative | pxquantitative | pyquantitative | valuequantitative |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 18.454 |
| 1 | 0 | 1 | 0.161 | 25.566 |
| 2 | 0 | 2 | 0.279 | 33.429 |
| 3 | 0 | 3 | 0.333 | 37.437 |
| 4 | 0 | 4 | 0.334 | 34.696 |
| 5 | 0 | 5 | 0.317 | 27.231 |
| 6 | 0 | 6 | 0.33 | 19.709 |
| 7 | 0 | 7 | 0.402 | 14.966 |
| 8 | 0 | 8 | 0.535 | 12.882 |
| 0 | 1 | 0.237 | 1 | 23.107 |
| 1 | 1 | 1.237 | 1.161 | 35.347 |
| 2 | 1 | 2.237 | 1.279 | 48.878 |
| 3 | 1 | 3.237 | 1.333 | 55.784 |
| 4 | 1 | 4.237 | 1.334 | 51.103 |
| 5 | 1 | 5.237 | 1.317 | 38.364 |
| 6 | 1 | 6.237 | 1.33 | 25.59 |
| 7 | 1 | 7.237 | 1.402 | 17.544 |
| 8 | 1 | 8.237 | 1.535 | 13.904 |
| 0 | 2 | 0.44 | 2 | 26.364 |
| 1 | 2 | 1.44 | 2.161 | 42.193 |
| 2 | 2 | 2.44 | 2.279 | 59.698 |
| 3 | 2 | 3.44 | 2.333 | 68.668 |
| 4 | 2 | 4.44 | 2.334 | 62.805 |
| 5 | 2 | 5.44 | 2.317 | 46.879 |
| 6 | 2 | 6.44 | 2.33 | 31.246 |
| 7 | 2 | 7.44 | 2.402 | 21.451 |
| 8 | 2 | 8.44 | 2.535 | 16.459 |
| 0 | 3 | 0.594 | 3 | 25.96 |
| 1 | 3 | 1.594 | 3.161 | 41.344 |
| 2 | 3 | 2.594 | 3.279 | 58.373 |
| 3 | 3 | 3.594 | 3.333 | 67.222 |
| 4 | 3 | 4.594 | 3.334 | 62.151 |
| 5 | 3 | 5.594 | 3.317 | 48.474 |
| 6 | 3 | 6.594 | 3.33 | 36.19 |
| 7 | 3 | 7.594 | 3.402 | 28.674 |
| 8 | 3 | 8.594 | 3.535 | 22.887 |
| 0 | 4 | 0.715 | 4 | 22.195 |
| 1 | 4 | 1.715 | 4.161 | 33.433 |
| 2 | 4 | 2.715 | 4.279 | 45.905 |
| 3 | 4 | 3.715 | 4.333 | 52.641 |
| 4 | 4 | 4.715 | 4.334 | 50.238 |
| 5 | 4 | 5.715 | 4.317 | 43.99 |
| 6 | 4 | 6.715 | 4.33 | 41.06 |
| 7 | 4 | 7.715 | 4.402 | 39.729 |
| 8 | 4 | 8.715 | 4.535 | 33.562 |
| 0 | 5 | 0.839 | 5 | 17.595 |
| 1 | 5 | 1.839 | 5.161 | 23.767 |
| 2 | 5 | 2.839 | 5.279 | 30.658 |
| 3 | 5 | 3.839 | 5.333 | 34.711 |
| 4 | 5 | 4.839 | 5.334 | 35.092 |
| 5 | 5 | 5.839 | 5.317 | 36.552 |
| 6 | 5 | 6.839 | 5.33 | 42.841 |
| 7 | 5 | 7.839 | 5.402 | 47.546 |
| 8 | 5 | 8.839 | 5.535 | 41.624 |
| 0 | 6 | 1 | 6 | 14.308 |
| 1 | 6 | 2 | 6.161 | 16.856 |
| 2 | 6 | 3 | 6.279 | 19.736 |
| 3 | 6 | 4 | 6.333 | 21.699 |
| 4 | 6 | 5 | 6.334 | 23.244 |
| 5 | 6 | 6 | 6.317 | 27.839 |
| 6 | 6 | 7 | 6.33 | 36.881 |
| 7 | 6 | 8 | 6.402 | 43.259 |
| 8 | 6 | 9 | 6.535 | 38.745 |
Browser API · Portable schema
Browser API
Graflume.carpet()
const data = [
{
"a": 0,
"b": 0,
"px": 0,
"py": 0,
"value": 18.454
},
{
"a": 1,
"b": 0,
"px": 1,
"py": 0.161,
"value": 25.566
},
{
"a": 2,
"b": 0,
"px": 2,
"py": 0.279,
"value": 33.429
},
{
"a": 3,
"b": 0,
"px": 3,
"py": 0.333,
"value": 37.437
},
{
"a": 4,
"b": 0,
"px": 4,
"py": 0.334,
"value": 34.696
},
{
"a": 5,
"b": 0,
"px": 5,
"py": 0.317,
"value": 27.231
},
{
"a": 6,
"b": 0,
"px": 6,
"py": 0.33,
"value": 19.709
},
{
"a": 7,
"b": 0,
"px": 7,
"py": 0.402,
"value": 14.966
},
{
"a": 8,
"b": 0,
"px": 8,
"py": 0.535,
"value": 12.882
},
{
"a": 0,
"b": 1,
"px": 0.237,
"py": 1,
"value": 23.107
},
{
"a": 1,
"b": 1,
"px": 1.237,
"py": 1.161,
"value": 35.347
},
{
"a": 2,
"b": 1,
"px": 2.237,
"py": 1.279,
"value": 48.878
},
{
"a": 3,
"b": 1,
"px": 3.237,
"py": 1.333,
"value": 55.784
},
{
"a": 4,
"b": 1,
"px": 4.237,
"py": 1.334,
"value": 51.103
},
{
"a": 5,
"b": 1,
"px": 5.237,
"py": 1.317,
"value": 38.364
},
{
"a": 6,
"b": 1,
"px": 6.237,
"py": 1.33,
"value": 25.59
},
{
"a": 7,
"b": 1,
"px": 7.237,
"py": 1.402,
"value": 17.544
},
{
"a": 8,
"b": 1,
"px": 8.237,
"py": 1.535,
"value": 13.904
},
{
"a": 0,
"b": 2,
"px": 0.44,
"py": 2,
"value": 26.364
},
{
"a": 1,
"b": 2,
"px": 1.44,
"py": 2.161,
"value": 42.193
},
{
"a": 2,
"b": 2,
"px": 2.44,
"py": 2.279,
"value": 59.698
},
{
"a": 3,
"b": 2,
"px": 3.44,
"py": 2.333,
"value": 68.668
},
{
"a": 4,
"b": 2,
"px": 4.44,
"py": 2.334,
"value": 62.805
},
{
"a": 5,
"b": 2,
"px": 5.44,
"py": 2.317,
"value": 46.879
},
{
"a": 6,
"b": 2,
"px": 6.44,
"py": 2.33,
"value": 31.246
},
{
"a": 7,
"b": 2,
"px": 7.44,
"py": 2.402,
"value": 21.451
},
{
"a": 8,
"b": 2,
"px": 8.44,
"py": 2.535,
"value": 16.459
},
{
"a": 0,
"b": 3,
"px": 0.594,
"py": 3,
"value": 25.96
},
{
"a": 1,
"b": 3,
"px": 1.594,
"py": 3.161,
"value": 41.344
},
{
"a": 2,
"b": 3,
"px": 2.594,
"py": 3.279,
"value": 58.373
},
{
"a": 3,
"b": 3,
"px": 3.594,
"py": 3.333,
"value": 67.222
},
{
"a": 4,
"b": 3,
"px": 4.594,
"py": 3.334,
"value": 62.151
},
{
"a": 5,
"b": 3,
"px": 5.594,
"py": 3.317,
"value": 48.474
},
{
"a": 6,
"b": 3,
"px": 6.594,
"py": 3.33,
"value": 36.19
},
{
"a": 7,
"b": 3,
"px": 7.594,
"py": 3.402,
"value": 28.674
},
{
"a": 8,
"b": 3,
"px": 8.594,
"py": 3.535,
"value": 22.887
},
{
"a": 0,
"b": 4,
"px": 0.715,
"py": 4,
"value": 22.195
},
{
"a": 1,
"b": 4,
"px": 1.715,
"py": 4.161,
"value": 33.433
},
{
"a": 2,
"b": 4,
"px": 2.715,
"py": 4.279,
"value": 45.905
},
{
"a": 3,
"b": 4,
"px": 3.715,
"py": 4.333,
"value": 52.641
},
{
"a": 4,
"b": 4,
"px": 4.715,
"py": 4.334,
"value": 50.238
},
{
"a": 5,
"b": 4,
"px": 5.715,
"py": 4.317,
"value": 43.99
},
{
"a": 6,
"b": 4,
"px": 6.715,
"py": 4.33,
"value": 41.06
},
{
"a": 7,
"b": 4,
"px": 7.715,
"py": 4.402,
"value": 39.729
},
{
"a": 8,
"b": 4,
"px": 8.715,
"py": 4.535,
"value": 33.562
},
{
"a": 0,
"b": 5,
"px": 0.839,
"py": 5,
"value": 17.595
},
{
"a": 1,
"b": 5,
"px": 1.839,
"py": 5.161,
"value": 23.767
},
{
"a": 2,
"b": 5,
"px": 2.839,
"py": 5.279,
"value": 30.658
},
{
"a": 3,
"b": 5,
"px": 3.839,
"py": 5.333,
"value": 34.711
},
{
"a": 4,
"b": 5,
"px": 4.839,
"py": 5.334,
"value": 35.092
},
{
"a": 5,
"b": 5,
"px": 5.839,
"py": 5.317,
"value": 36.552
},
{
"a": 6,
"b": 5,
"px": 6.839,
"py": 5.33,
"value": 42.841
},
{
"a": 7,
"b": 5,
"px": 7.839,
"py": 5.402,
"value": 47.546
},
{
"a": 8,
"b": 5,
"px": 8.839,
"py": 5.535,
"value": 41.624
},
{
"a": 0,
"b": 6,
"px": 1,
"py": 6,
"value": 14.308
},
{
"a": 1,
"b": 6,
"px": 2,
"py": 6.161,
"value": 16.856
},
{
"a": 2,
"b": 6,
"px": 3,
"py": 6.279,
"value": 19.736
},
{
"a": 3,
"b": 6,
"px": 4,
"py": 6.333,
"value": 21.699
},
{
"a": 4,
"b": 6,
"px": 5,
"py": 6.334,
"value": 23.244
},
{
"a": 5,
"b": 6,
"px": 6,
"py": 6.317,
"value": 27.839
},
{
"a": 6,
"b": 6,
"px": 7,
"py": 6.33,
"value": 36.881
},
{
"a": 7,
"b": 6,
"px": 8,
"py": 6.402,
"value": 43.259
},
{
"a": 8,
"b": 6,
"px": 9,
"py": 6.535,
"value": 38.745
}
];
const options = {
"accessibility": {
"description": "A warped coordinate surface retains two peaks and its underlying topology. The example uses curated, deterministic data and exposes its exact values in a semantic table.",
"label": "Carpet chart: A warped coordinate surface retains two peaks and its underlying topology"
},
"annotations": [
{
"connector": {
"visible": true
},
"detail": "Attach user-authored safe text to a datum, axis range, or normalized plot position.",
"id": "manual-callout",
"placement": "auto",
"style": {
"maxWidth": 220,
"padding": 8
},
"target": {
"field": "px",
"type": "datum",
"value": 4.594
},
"text": "Point and range highlights · 4"
}
],
"axes": {
"x": false,
"y": false
},
"create": {
"adaptive": {
"profiles": "auto"
}
},
"height": 620,
"highlights": [
{
"id": "manual-focus",
"padding": 7,
"target": {
"field": "px",
"type": "datum",
"value": 4.594
}
}
],
"interaction": {
"controls": {
"annotations": true,
"export": true,
"fullscreen": true,
"labels": {
"controls": "Chart controls",
"enterFullscreen": "Enter fullscreen",
"exitFullscreen": "Exit fullscreen",
"exportPng": "Download PNG",
"hideAnnotations": "Hide callouts",
"loop": "Loop playback",
"nextFrame": "Next frame",
"pause": "Pause",
"play": "Play",
"previousFrame": "Previous frame",
"reset": "Reset view",
"seek": "Playback position",
"showAnnotations": "Show callouts",
"speed": "Playback speed",
"zoomIn": "Zoom in",
"zoomOut": "Zoom out"
},
"playback": false,
"reset": true,
"zoom": true
},
"hover": true,
"navigation": {
"drag": true,
"keyboard": true,
"maxZoom": 6,
"minZoom": 1,
"pinch": true,
"wheel": "modifier"
},
"selection": {
"ariaLabel": "Interactive selection",
"clearOnBackground": true,
"clearOnEscape": true,
"highlight": {
"padding": 5
},
"key": "px",
"mode": "multiple",
"toggle": true
},
"tooltip": {
"fields": [
{
"field": "a",
"format": "number",
"label": "A"
},
{
"field": "b",
"format": "number",
"label": "B"
},
{
"field": "px",
"format": "number",
"label": "Px"
},
{
"field": "py",
"format": "number",
"label": "Py"
},
{
"field": "value",
"format": "number",
"label": "Value"
}
],
"title": "Carpet",
"trigger": "mark"
}
},
"legend": {
"field": "value",
"interactive": false,
"labels": {
"hide": "Hide",
"show": "Show"
},
"maxItems": 8,
"mode": "continuous",
"orientation": "horizontal",
"position": "bottom",
"title": "Value",
"visible": true
},
"locale": "en",
"mark": {
"fields": {
"value": "value",
"x": "px",
"y": "py"
},
"options": {
"levels": 4,
"mode": "grid"
}
},
"padding": {
"top": 52
},
"theme": "graflume-light",
"title": {
"subtitle": "A warped coordinate surface retains two peaks and its underlying topology",
"text": "Carpet chart"
},
"width": "container",
"x": {
"field": "a",
"title": "Carpet axis A",
"type": "quantitative"
},
"y": {
"field": "b",
"title": "Carpet axis B",
"type": "quantitative"
}
};
Graflume.carpet('#chart', data, options);Portable schema
ChartSpec 0.1 · options
{
"accessibility": {
"description": "A warped coordinate surface retains two peaks and its underlying topology. The example uses curated, deterministic data and exposes its exact values in a semantic table.",
"label": "Carpet chart: A warped coordinate surface retains two peaks and its underlying topology"
},
"annotations": [
{
"connector": {
"visible": true
},
"detail": "Attach user-authored safe text to a datum, axis range, or normalized plot position.",
"id": "manual-callout",
"placement": "auto",
"style": {
"maxWidth": 220,
"padding": 8
},
"target": {
"field": "px",
"type": "datum",
"value": 4.594
},
"text": "Point and range highlights · 4"
}
],
"axes": {
"x": false,
"y": false
},
"create": {
"adaptive": {
"profiles": "auto"
}
},
"height": 620,
"highlights": [
{
"id": "manual-focus",
"padding": 7,
"target": {
"field": "px",
"type": "datum",
"value": 4.594
}
}
],
"interaction": {
"controls": {
"annotations": true,
"export": true,
"fullscreen": true,
"labels": {
"controls": "Chart controls",
"enterFullscreen": "Enter fullscreen",
"exitFullscreen": "Exit fullscreen",
"exportPng": "Download PNG",
"hideAnnotations": "Hide callouts",
"loop": "Loop playback",
"nextFrame": "Next frame",
"pause": "Pause",
"play": "Play",
"previousFrame": "Previous frame",
"reset": "Reset view",
"seek": "Playback position",
"showAnnotations": "Show callouts",
"speed": "Playback speed",
"zoomIn": "Zoom in",
"zoomOut": "Zoom out"
},
"playback": false,
"reset": true,
"zoom": true
},
"hover": true,
"navigation": {
"drag": true,
"keyboard": true,
"maxZoom": 6,
"minZoom": 1,
"pinch": true,
"wheel": "modifier"
},
"selection": {
"ariaLabel": "Interactive selection",
"clearOnBackground": true,
"clearOnEscape": true,
"highlight": {
"padding": 5
},
"key": "px",
"mode": "multiple",
"toggle": true
},
"tooltip": {
"fields": [
{
"field": "a",
"format": "number",
"label": "A"
},
{
"field": "b",
"format": "number",
"label": "B"
},
{
"field": "px",
"format": "number",
"label": "Px"
},
{
"field": "py",
"format": "number",
"label": "Py"
},
{
"field": "value",
"format": "number",
"label": "Value"
}
],
"title": "Carpet",
"trigger": "mark"
}
},
"legend": {
"field": "value",
"interactive": false,
"labels": {
"hide": "Hide",
"show": "Show"
},
"maxItems": 8,
"mode": "continuous",
"orientation": "horizontal",
"position": "bottom",
"title": "Value",
"visible": true
},
"locale": "en",
"mark": {
"fields": {
"value": "value",
"x": "px",
"y": "py"
},
"options": {
"levels": 4,
"mode": "grid"
}
},
"padding": {
"top": 52
},
"theme": "graflume-light",
"title": {
"subtitle": "A warped coordinate surface retains two peaks and its underlying topology",
"text": "Carpet chart"
},
"width": "container",
"x": {
"field": "a",
"title": "Carpet axis A",
"type": "quantitative"
},
"y": {
"field": "b",
"title": "Carpet axis B",
"type": "quantitative"
}
}