Skip to content

finding(plugin-charts): the ObjectChart drill-down spread mis-composes the filter ARRAY arm into index keys, silently dropping the widget's own filter #8944

Description

@claude

Found while reworking PR objectui#8884 (card objectui#7946), and named as a successor by that PR's
contract review. Filed rather than fixed there: it is a behaviour change to the drill-down query, not
part of the ruled declaration work.

The defect

ObjectChartSchema.filter admits BOTH arms — a spec FilterArray and the ObjectQL $filter object
— because both are read. The drill-down composition in
packages/plugin-charts/src/ObjectChart.tsx handles only one of them:

const drillFilter = useMemo(() => {
  if (!drillEvent) return undefined;
  return {
    ...(schema.filter || {}),
    ...computeDrillFilter(drillDown, drillEvent, { groupByField }),
  };
}, [...]);

Spreading an ARRAY into an object literal does not produce conditions — it produces index keys.
An author who writes the arm @objectstack/spec publishes for this prop, and whom this component's
own registry inputs advertise ({ name: 'filter', type: 'array' }):

{ "filter": [["stage", "=", "won"]] }

drills with

{ "0": ["stage", "=", "won"], "stage": "won" }

The widget's own filter is silently lost — the "0" key means nothing to the query layer — so the
drilled list is scoped by the clicked category ALONE and shows records the chart itself excludes.
Nothing errors; the drawer opens and looks right.

The record arm works, which is why this survived: the in-repo corpus authors the object form, and the
array arm is the one the protocol advertises.

Why this blocks something else

ObjectChartSchema.filter is the only object-* widget filter on packages/types/src/objectql.ts
carrying a record arm — the six siblings are already array-only. Narrowing this node to the spec's
array-only FilterArray would make the declaration match the protocol and the palette, and it is
blocked on exactly this composition: narrow first and every live chart that authors the object form
stops compiling; fix this first and the narrowing becomes a normal deprecation.

So this card is the prerequisite for closing that divergence, and objectui#8884's filter docblock
names it as such.

Acceptance

  • A drill-down on a chart whose filter is the ARRAY arm produces a filter that still carries the
    widget's own conditions, in whatever spelling the query layer takes.
  • Both arms pinned at runtime, including the target: 'navigate' path (openRecordList receives the
    composed filter) — the drawer and the navigate arm share one drillFilter memo, so one pin covers
    both if it asserts the composed value rather than the rendered rows.
  • The pin fails on the current code. A test that only exercises the record arm is green today and
    measures nothing.

Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions