All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Breaking:
createRuleContextandcreateRuleGroupContextare no longer exported. Each was a single-linecreateMemoaroundQueryManager#getRuleContext/#getRuleGroupContextkeyed on query identity, with no consumer inside the package. Callers should read the manager directly —createMemo(() => (query(), manager.getRuleContext(path())))is the whole implementation.
@react-querybuilder/coreis bumped to 8.23.0, and the conformance fixtures with it (CONFORMANCE_TAGv8.22.4 → v8.23.0,schemaVersion2 → 3). Schema 3 adds a per-elementtextchannel — the element's own direct text-node children, verbatim — soextract.tsnow emits it. Both walkers here go through a real DOM, so entity decoding is free. All 237 conformance assertions stay green; the new channel was proved live (a leading space added to everyActionElementlabel turns 100 cases red, a change the class-only schema-2 surface could not see).controlKeysis now re-exported explicitly from the barrel. Core 8.23.0 exports acontrolKeysof its own, and two star exports cannot disambiguate themselves (TS2308). This package's list is the deliberate delta — it omitsdragHandle,ruleGroupHeaderElements, andruleGroupBodyElements, matching this package'sControls— so it wins.- Breaking:
createQueryBuilderStateis renamedcreateQueryBuilderand is now documented as the package's headless entry point (see "Headless usage" in the README). It already was one — it returns query, tree, manager, schema, actions and context and renders nothing — so this is a naming change only.CreateQueryBuilderStateOptionsis renamedCreateQueryBuilderOptions; the returnedQueryBuilderStateinterface keeps its name. No alias is kept. - Breaking (source path only):
createRuleActionsmoved fromsrc/reactive/tosrc/actions.ts. It is the one module in the reactive layer with no reactive primitives — a pureQueryManager→QueryActionsadapter. The public barrel export is unchanged. - Internal:
createQueryBuilder.ts(767 lines) is split along its existing#regionseams intomanager-options.ts(the option builders andvaluesEqual),manager-bridge.ts(manager construction, query seeding, the version signals, the store projection, the subscription and the three effects),schema.ts(the option lists, the resolvers and theSchemagetter object) andcontext-value.ts. Pure moves; the assembly file is ~200 lines and the new modules are internal. - Internal: ~20
createMemocalls that wrapped a single property read or a primitive-returning boolean expression are now plain closures. Solid props are already lazy getters, so those memos allocated a computation node to cache a property access. Memos that allocate an object, run a user callback (validator,accessibleDescriptionGenerator), or exist for identity stability (disabledPaths, theconfigVersion-keyed option lists) are untouched.createRuleState'sresolversmemo is inlined into thectxmemo it exclusively fed. createRuleStateandcreateRuleGroupStatetake a plainRuleProps/RuleGroupPropsinstead ofProps | Accessor<Props>. A getter-object literal is equally reactive, which is what the one internal accessor caller (RuleSubQuery) was already passing.
0.1.0 - 2026-08-08
- Retargeted the port to Solid 2.0 exclusively.
peerDependenciesis nowsolid-js@^2.0.0-rc.0and@solidjs/web@^2.0.0-rc.0— in Solid 2 the DOM runtime is its own package. The^1.9peer leg and the non-gatingsolid-nextCI job are both gone; CI is a single gating job on the pinned beta, preceded by acheck:versionsstep that asserts the resolved prerelease toolchain has not drifted.jsxImportSourceis now@solidjs/web, and the SSR smoke test renders through Solid 2's synchronousrenderToString. Theexportsmap is unchanged. A v1-target port, should demand warrant one, will be a separate repo publishing as@react-querybuilder/solid1; this package will not carrysolid-js@1compatibility shims. 0.1.0still publishes to thelatestdist-tag. The prerelease peer is documented here and inREADME.mdrather than encoded in the version.
- Repo bootstrap: Bun workspaces, root tooling config (
oxfmt,oxlint,.editorconfig,.npmrc), rootvitest.config.tswithv8coverage (80% lines), and CI. packages/solid-querybuilderscaffold: the Solid tripleexportsmap (solid→types→import), build pipeline (vite builddom bundle,tsc --jsx preservesource bundle, types, css),check:exportsspecifier guard, andscripts/ssr-smoke.tsas a real gate from day one — it asserts thesolidcondition is first in the exports map and confirms that with Node's real resolver run with and without--conditions=solid, then renders through Vite's SSR pipeline inside a single Solid instance and asserts the exact markup.examples/demo— a Vite + Solid 2 playground aliased to the library's source (HMR without a build). Eight fields covering all seven value editors, two separately bound queries (RuleGroupTypeandRuleGroupTypeIC) behind an independent-combinators toggle that swaps query shapes, every display flag, undo/redo, and liveformatQueryinsql/json/mongodb/cel.examples/ssr— a hand-rolled Vite SSR consumer that depends onsolid-querybuilderby workspace specifier, so it exercises the publishabledistthrough the realexportsmap. It server-renders a nested independent-combinators query withrenderToString, passes one control throughcontrolElements, prints a server-sideformatQueryresult into the markup, and hydrates on the client.examples/ssr/ssr-smoke-test.ts, wired into roottest:ssrafter (not instead of)scripts/ssr-smoke.ts. It builds both bundles, serves them programmatically on an ephemeral port, asserts the status code and 20 markup claims, then loads the served page into jsdom, runs the client entry, and asserts hydration produced no errors and left the conformance surface unchanged.- Root
checknow fans out to@solid-querybuilder/example-*, so an example type error breaks CI. README.mdgains a prominent "Requires Solid 2.0" note, documentation links, and an examples section; newdocs/differences-from-react-querybuilder.md,docs/styling.md, anddocs/customization.md.- Accessibility suite (
src/components/a11y.test.tsx):vitest-axeover all eight conformance scenarios plus an all-controls independent-combinator case (nine cases), each asserted twice — WCAG 2.0/2.1 A+AA must be empty, and best-practice must equal exactly['label-title-only'], so any other best-practice regression still fails. Plus keyboard tests: tab order through a rule row, Enter/Space activation, and the not-toggle label association. It importstest/conformance/{scenarios,queries}rather than duplicating them, so a11y is asserted against exactly the prop combinations DOM parity is, and it still runs in a fresh clone (both modules are fixture-independent).
label-title-only(axe best-practice) fires on every selector and text editor. React Query Builder labels these controls withtitlealone, and full DOM parity is a locked decision for this port, so addingaria-labelwould break the conformance harness. It is not a WCAG failure:titleproduces an accessible name, and the level-Alabel/aria-*rules pass across all nine a11y cases. Consumers who need a visible label can supply one throughcontrolElements.
src/index.tsxre-exports@react-querybuilder/coreat runtime, not just at the type level.examples/ssrfound the gap by failing to build onimport { formatQuery } from 'solid-querybuilder'. Consumers can now use core's formatters, defaults, andQueryManagerwithout depending on core directly, as React Query Builder's own barrel allows.
Authoritative list: docs/differences-from-react-querybuilder.md.
- No SolidStart SSR gate.
@solidjs/start@2.0.0is a Solid 1 release (it depends onsolid-js@^1.9.14) and there is no Solid-2 line on any dist-tag, so the planned SolidStart example is replaced byexamples/ssr. Known gap: no router, no server functions, no meta-framework build pipeline, and the server-sideformatQuerycall is a plain call in the SSR entry rather than a server function or API route.examples/ssris replaced by SolidStart when a Solid-2 line ships; tracked post-0.1.0, and0.1.0is not held for it. - No Redux store, no
qbId, nodispatchQuery, nopreserveQueryStateOnUnmount. External control is themanagerprop plus the veto callbacks. - No slot or snippet customization tier —
controlElementsis the only one, because a component is the Solid idiom. - Not ported: drag and drop, UI compatibility packages,
expr/datetimevalue editor UI, async option lists, deprecated props,ruleGroupHeaderElements/ruleGroupBodyElements,DragHandle. - Type substitutions:
ReactNode→LabelNode,ComponentType→ Solid'sComponent,JSXfrom@solidjs/web, React syntheticMouseEvent→ the DOMMouseEvent,Controls.undoRedoActionsnon-nullable,RuleProps.fieldabsent.