Skip to content

feat: custom field types, expanded schema API, and Volcano Explorer demo #7

Open
armand1m wants to merge 5 commits intomainfrom
feat/custom-field-types
Open

feat: custom field types, expanded schema API, and Volcano Explorer demo #7
armand1m wants to merge 5 commits intomainfrom
feat/custom-field-types

Conversation

@armand1m
Copy link
Copy Markdown
Owner

@armand1m armand1m commented Apr 9, 2026

Library changes

New field types and schema API (src/types.ts, src/operations.ts)

  • Added 10 new built-in field types: date, dateTime, time, select, multiSelect, currency, percent, duration, email,
    and id — each with appropriate valueKind, coercion, and default operators
  • Added defineFieldType() and field.custom() for consumer-defined field types with full type inference
  • Added IS_ANY operator — a no-value boolean operation meaning "match any value"; useful for toggling boolean filters
    without deleting the condition
  • Extended defaultTypeOperationsMap.boolean from [IS] to [IS, IS_NOT, IS_ANY], fixing the UX issue where boolean
    filters could not express negation or "show all" without rebuilding the condition
  • IS_ANY is included in defaultNoValueOperations so the value input is suppressed automatically

useFilterBuilder improvements (src/hooks/useFilterBuilder.ts)

  • schemaFieldToDefinition now passes all schema field properties through (valueKind, operators, options, meta, coerce,
    isEmpty) instead of only mapping three known types
  • Value input controller now switches on valueKind (the rendering contract) rather than type (the semantic name),
    unlocking correct rendering for all new field types
  • Suggestions are pre-split into typed arrays (stringSuggestions, numberSuggestions, booleanSuggestions) so
    controllers receive correctly typed arrays without consumer-side casts

Example app

Site shell (example/src/App.tsx, example/src/styles.css)

  • Added a persistent site header with the library name (gradient), tagline, author pill, and a GitHub icon link to
    armand1m/react-query-filter
  • Tab navigation (Filter Builder Demo / Volcano Explorer) replaces the single-page layout, using underline-indicator
    tabs styled with a bottom-border active state
  • General spacing and visual polish: increased panel padding, improved group nesting with background/border treatment,
    refined control sizes and color palette

Volcano Explorer page (example/src/pages/VolcanoExplorer.tsx)

  • New demo page with 25 real volcanoes (name, country, continent, height, last eruption date, type, active status)
    stored in an in-browser https://github.com/agershun/alasql database
  • Filter schema covers all major field types: string, number, date, select, boolean
  • Filters are translated to SQL via https://knexjs.org/ used purely as a query builder (no DB connection) — the
    generated SQL is displayed live in the UI and executed against alasql with proper parameter binding
  • Results render in a styled table with active/dormant badge chips
  • vite-plugin-node-polyfills added to satisfy knex's dependency on Node built-ins (EventEmitter) in the browser

Filter Builder Demo (example/src/pages/FilterDemo.tsx)

  • Extracted from App.tsx verbatim; no behaviour changes

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 9, 2026

Release Preview

  • Latest release tag: v2.0.0
  • PR commit bump: minor (example×1, feat×1, fix×2, style×1)
  • PR-only next version: v2.1.0
  • Projected next release if merged now: v2.1.0
  • Projected bump across unreleased work on main + this PR: minor (example×1, feat×2, fix×4, style×1)
  • PR title check: ❌ invalid (feat: custom field types, expanded schema API, and Volcano Explorer demo )
  • Title/commit alignment: ⚠️ fix the PR title to match Conventional Commits before merge

Advisory only. Release Please remains the source of truth for the final tag and changelog.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 48684a76e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +637 to +641
...field,
type: definition.type,
valueKind: definition.valueKind,
coerce: definition.coerce,
isEmpty: definition.isEmpty,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve custom field default operators in field.custom

defineFieldType() accepts defaultOperators, but createField() drops that property when constructing schema fields, so field.custom() outputs have no operator defaults unless every call site manually sets operators. As a result, useFilterBuilder/useQueryFilters fall back to generic type maps and custom types cannot control their intended default operator list or starter operator, which breaks the advertised custom-type API behavior.

Useful? React with 👍 / 👎.

Comment on lines 229 to 231
onChange: (event) => {
raw.updateConditionValue(
condition.id,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Emit array values when select operator is IN/NOT_IN

The select controller always writes a scalar string (event.currentTarget.value) even though select fields now expose IN/NOT_IN by default. When users choose those operators in the builder UI, the condition value is not representable as a list, so downstream evaluators that expect array semantics (including this repo's SQL translator, which guards with Array.isArray) silently skip the filter and return unfiltered results.

Useful? React with 👍 / 👎.

OperationType.AFTER,
OperationType.ON_OR_BEFORE,
OperationType.ON_OR_AFTER,
OperationType.BETWEEN,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don’t expose BETWEEN without a range-capable value input

BETWEEN is now included in default date/datetime/time operators, but the builder’s date-like controllers only bind a single input value. In the recommended controller-driven UI path there is no way to enter both bounds, so selecting BETWEEN cannot produce a valid range payload and the condition is effectively unusable without custom out-of-band encoding.

Useful? React with 👍 / 👎.

Resolve all lint failures (no-base-to-string, no-explicit-any,
no-unnecessary-type-assertion, no-floating-promises) across library
and example code. Address three PR review items: preserve custom
field defaultOperators in field.custom(), emit array values for
select IN/NOT_IN operators, and remove BETWEEN from date/datetime/time
defaults since no range input exists in the builder.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant