Skip to content

filter-builder: FilterFieldSchema still refuses seven live field types, requires a type the renderer and the docs both make optional, and its condition shape omits the id four read sites match on #7562

Description

@claude

Found by the os-dev seat while implementing the filter-builder group of #6939 (PR #7560). Out of that group's scope: the ruling in #6939 comment 5510084784 names the six value-family members for FilterFieldSchema.type and says nothing about the three gaps below, each of which is an accept-set change of its own. Grading and domain:* are the triage seat's.

PR #7560 pins all three with assertions rather than leaving them as absences, so they are recorded decisions; this card is where they get decided.

1. Seven live field types the mirror refuses

After #7560, FilterFieldSchema.type is text | number | boolean | date | datetime | time | select. The component buckets seven more spellings and draws a DISTINCT control for each — measured, one condition row per spelling, through the real SchemaRenderer:

type source of the bucket value control drawn
currency, percent, rating numberLikeTypes input type="number"
status selectLikeTypes no input — the option-driven Select
lookup, master_detail, user lookupLikeTypes no input — the option Select, or the remote search picker without static options

All seven were refused BEFORE #7560 as well, so this is a pre-existing gap and not a regression that PR introduces — but it is the same class as #6939 itself: the mirror refuses a document the renderer draws.

2. type is REQUIRED on the mirror and optional everywhere else

FilterBuilderProps.fields declares type?: string. valueFamilyForFieldType reads fieldType || "text" and operatorsForFieldType reads fieldType || "text", so an entry with no type is a text column. Measured: deleting type from every field of product-search still renders all three rows (76 elements, identical text; only the value inputs degrade from text/number/number to three text boxes). The mirror refuses { value, label }.

3. The published doc already declares the wider shape

content/docs/components/complex/filter-builder.mdx publishes

type?:
  | 'text' | 'number' | 'currency' | 'percent' | 'rating'
  | 'date' | 'datetime' | 'time'
  | 'boolean'
  | 'select' | 'status'
  | 'lookup' | 'master_detail' | 'user';

— fourteen members and OPTIONAL. So the doc, the component and the mirror are three declarations of one authoring surface and the mirror is the odd one out on both counts. @object-ui/fields' deriveFilterFields, the producer that builds this list from a real object schema, passes ANY object field type through except thirteen it names non-filterable, which is the population the wide vocabulary exists for.

4. FilterBuilderConditionSchema omits id, which the component reads at four sites

The mirror declares a condition as { field, operator, value? }. The component's FilterBuilderCondition is { id, field, operator, value } and id is the identity every mutation matches on: removeCondition (c.id !== conditionId), updateCondition, changeOperator, changeField, plus the row's React key. All five catalog entries author it. Because a plain z.object STRIPS unknown keys, id is accepted-and-discarded today rather than refused — undeclared and unvalidated while being read, which is the shape #6150 closed for tree-view.title.

A row with no id still renders, but nothing on it can be removed or edited, so "required" is a defensible answer here in a way it is not for the GROUP's id (which has zero read sites — see #7560).

Reproduce

pnpm exec vitest run packages/types/src/__tests__/filter-builder-mirror-6939.test.ts

still refuses the live-but-unruled spelling ... (x7) and the gap is measured against the PUBLISHED doc, not against a private opinion are the measurements for 1-3.

Related


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:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanefindingpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions