Skip to content

feat: custom chart and component with vega lite ejection - #9850

Open
djbarnwal wants to merge 17 commits into
mainfrom
feat/custom-viz-flint
Open

feat: custom chart and component with vega lite ejection#9850
djbarnwal wants to merge 17 commits into
mainfrom
feat/custom-viz-flint

Conversation

@djbarnwal

Copy link
Copy Markdown
Member

Uses flint for creating a gallery of custom viz with an option to eject to a vega lite spec for more granular control.

Checklist:

  • Covered by tests
  • Ran it and it works as intended
  • Reviewed the diff before requesting a review
  • Checked for unhandled edge cases
  • Linked the issues it closes
  • Checked if the docs need to be updated. If so, create a separate Linear DOCS issue
  • Intend to cherry-pick into the release branch
  • I'm proud of this work!

nishantmonu51 and others added 17 commits July 15, 2026 01:57
Extract inline canvas custom charts into reusable component resources:

- Components declare typed params (metrics_view, measure, dimension,
  time_dimension, scalars) validated at parse and reconcile time
- Canvas items reference components via 'component:' + 'params:' bindings;
  param-bound metrics views flow through transitive access security
- ResolveComponent merges defaults, validates bindings, resolves templates,
  and injects scalar params as native Vega-Lite params
- Component workspace with live preview, test bindings, used-by panel, and
  breaking-change warnings
- 'Save as custom viz' extraction from inline charts and 'Detach copy' inverse
- Vega-Lite examples gallery (vendored snapshot with static SVG thumbnails)
  with AI-first import: spec-in-prompt generation, placeholder file, and a
  self-healing validation loop with static structure/consistency checks
- Generated components include customizable order_by and limit params with
  density-based defaults; order_by follows re-bound fields in the editor
- Dev-agent instructions for authoring components (metrics_sql dialect rules,
  encoding/param type matching, row-local calculate preservation for
  diverging charts)

Gated behind the customComponents frontend flag and custom_components
runtime flag.
- Format touched files with prettier
- Fix svelte-check errors: Extract string keys in AllKeys so ComponentRefSpec's
  index signature doesn't widen keys to string | number; narrow the index
  signature values to scalars (matching the parser's scalar-only bindings);
  type initializeRow over AddableItem; pass the required editor binding in
  ComponentWorkspace; remove unused imports and cast union field accesses
- Add customComponents to the expected maps in Test_ResolveFeatureFlags
- Add the component_extract_title message key (en/es)
- Bind the required viewVL prop on the preview's inline VegaLiteRenderer
- Cast metrics_view access in FiltersMapper to string | null
- ResolveCanvas: skip templated metrics_view renderer properties instead of
  looking them up as literal resource names (param-bound metrics views are
  collected from the canvas items)
- Frontend: give canvas items referencing an external component their
  positional instance id as component.id, so two references to the same
  component get distinct DOM ids and consistent selection/cleanup; make the
  drag-move reselect path instance-aware and use getElementById for ids
  containing '::'
- Transitive access: scan metrics_sql lists (multi-query custom charts) for
  metrics view refs, not just single query strings
- Parser: components declaring a metrics_view param with a default now get a
  ref to the default metrics view for DAG ordering and invalidation
# Conflicts:
#	proto/gen/rill/runtime/v1/queries.pb.go
#	proto/gen/rill/runtime/v1/resources.pb.go
#	runtime/parser/parser_test.go
…ct time_dimension picker

- Renderer validators now run structural checks (required keys, types, enums)
  on parameterized components with templated properties; only field-membership
  checks against the metrics view are skipped for unresolvable values.
- The time_dimension param picker now only offers time fields (the primary
  time dimension and time-typed dimensions) and supports search, instead of
  listing every dimension and returning no results for any search term.
@nishantmonu51 nishantmonu51 added Type:Feature New feature request Area:Dashboard Size:XL Very large change: 2,000+ lines labels Sep 4, 2026
@nishantmonu51

Copy link
Copy Markdown
Collaborator

Existing canvases that reference a non-chart component file will break. getComponentInstanceType routes every item with component: <name> and !definedInCanvas to component_ref, and CanvasComponentRef renders only custom_chart. A canvas referencing a standalone markdown/image/kpi/table component now shows "Components with renderer X cannot be referenced on a canvas yet". The render path is not behind custom_components — the flag only gates the add menu and the workspace. web-common/src/features/canvas/components/util.ts:233

The chart recompiles on every resize frame. compiled is reactive on chartWidth/chartHeight from bind:clientWidth/bind:clientHeight, so each frame yields a new spec object and svelte-vega re-embeds. VegaLiteRenderer keeps options identity stable across width/height for exactly this reason (#9859); a fresh spec defeats it. web-common/src/features/components/charts/flint/FlintChartRenderer.svelte:148

The metrics_view naming rule is enforced in one direction only. parseComponentParams requires the name only when type: metrics_view, but both ref-extraction sites key purely off the binding's key name. A component declaring - name: metrics_view, type: string plus a canvas binding metrics_view: anything adds a ref to a nonexistent metrics view and the canvas fails to reconcile. runtime/parser/parse_component.go:337, runtime/parser/parse_canvas.go:350, runtime/reconcilers/canvas.go:220

AddComponentDropdown lists every standalone component regardless of renderer, so a user can add a reference that renders as an unsupported-renderer error. Filter on renderer === "custom_chart". web-common/src/features/canvas/AddComponentDropdown.svelte:66

Duplication. The metrics_view / *_metrics_view key-pattern extraction is copy-pasted (comment included) in parse_canvas.go:349 and reconcilers/canvas.go:217. normalizeMetricsSQL is defined three times — CanvasComponentRef.svelte, ComponentPreview.svelte, eject-component.ts — and the canvas copy differs (no trim(), so a whitespace-only query counts as present).

ResolveComponent passes nil metricsViews to ValidateParamBindings, so field-typed params accept any client-supplied string and are interpolated into metrics_sql. Access control still holds via the resolver's security policy, but the reconciler's field-membership check is worth repeating here.

ResourceKindMap[Component].folderName changes componentsviz_library unconditionally, not behind custom_components. Intentional? web-common/src/features/entity-management/add/new-files.ts:119

Minor: canvas_custom_viz is added to both locales but never used; the Spanish component_examples_description has a typo ("vincúblo" → "vincúlalo"); FlintChartRenderer, WorkspaceDispatcher, AddAssetButton and import-with-ai.ts carry hardcoded English while the rest of the feature is migrated; preview-state.ts never prunes its module-level store map, so entries survive file deletion and rename.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area:Dashboard Size:XL Very large change: 2,000+ lines Type:Feature New feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants