Repository navigation
Conversation
r0b1n
force-pushed
the
feat/combobox-selector-safety-net
branch
from
October 30, 2026 08:34
d7cf817 to
b6e38a2
Compare
r0b1n
force-pushed
the
feat/combobox-mobx-store
branch
2 times, most recently
from
October 30, 2026 08:50
e3126e8 to
f281abc
Compare
r0b1n
force-pushed
the
feat/combobox-selector-safety-net
branch
2 times, most recently
from
October 30, 2026 08:58
e251deb to
ca117d9
Compare
r0b1n
force-pushed
the
feat/combobox-mobx-store
branch
from
October 30, 2026 08:58
f281abc to
ed6c215
Compare
r0b1n
force-pushed
the
feat/combobox-selector-safety-net
branch
from
October 30, 2026 13:30
ca117d9 to
2a2a4ee
Compare
Design docs for the headless widget concept (generic) and the combobox contract with its safety-net rules and the 8-step migration plan.
r0b1n
force-pushed
the
feat/combobox-mobx-store
branch
from
October 30, 2026 14:30
ed6c215 to
7095a5c
Compare
…t action mode Adds mobx 6.12.3, @mendix/widget-plugin-mobx-kit and brandi for the headless combobox plan: the selector store becomes observable (step 1) and the core is assembled from a brandi container like the data grid and gallery widgets (step 2). The package now runs Jest through its own jest.config.js so a setup file can enable enforceActions: always and turn the MobX strict-mode warning into a test failure.
Every selector, options provider, captions provider and the lazy-load provider now declares its state with makeObservable. Mendix values enter as observable.ref only, props updates and setters are actions, derived getters are computed. The Selector interface and the re-render trigger in useGetSelector are unchanged so the characterisation tests pass as they are. StaticOptionsProvider loses three field redeclarations that would have shadowed the base class observables.
…hook useGetSelector no longer registers onAfterSearchTermChange to call setState. It subscribes to the observable search term through useObservableSnapshot, a useSyncExternalStore wrapper around a MobX reaction. The hook is the snapshot hook from the headless design docs and will read the ViewModel in step 2.
Adds the combobox-mobx-store change (proposal, design, tasks) and a status line under step 1 of the headless combobox migration plan.
Migration step 2 of docs/design/headless-combobox.md. The core derives a plain ViewModel from the selector store as cached slices, so a View can memoise on them, and the two selection views render from that snapshot only. The core is assembled by a brandi container like the data grid and gallery widgets: a frozen config for the static Studio Pro properties, a props gate for the Mendix values, the selector family bound per instance, and a setup host for the debounced filter-input action. getSelector and useGetSelector are replaced by the container and useComboboxCore; the editor preview uses the same container over the preview selectors.
Migration step 2, third commit. onAfterSearchTermChange leaves the OptionsProvider interface, the base provider and the two preview providers. The view model subscription covers the search term, so the side channel has no caller. Its three characterisation tests go with it; the remaining defaults test keeps its file.
Adds openspec/changes/combobox-viewmodel with the container, config and gate decisions, ticks task 3.2 of combobox-mobx-store, and records the step 2 status and the composition-root decision in the design docs.
r0b1n
force-pushed
the
feat/combobox-mobx-store
branch
from
October 30, 2026 17:24
7095a5c to
08c22d9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #2499 (
feat/combobox-selector-safety-net). Research branch for the headless combobox; seedocs/design/headless-widgets.mdanddocs/design/headless-combobox.md, both added here. #2499 stays a plain test PR and carries nothing from this one.Migration steps 1 and 2 of the combobox design doc, as commits:
docs: add headless widgets design docs— the two design documents.build(combobox-web): add mobx, mobx-kit and brandi, run jest in strict action mode— dependencies,jest.config.js+jest.setup.tswithenforceActions: "always"and[MobX]warnings turned into errors.refactor(combobox-web): make the selector store observable with mobx— every selector and provider annotated withmakeObservable; thesetState({})trigger kept so this commit is a pure store change.refactor(combobox-web): replace the forced re-render with a snapshot hook—useObservableSnapshot(useSyncExternalStoreover a MobXreaction) subscribed to the search term.docs(combobox-web): record migration step 1 as an openspec change—openspec/changes/combobox-mobx-store.feat(combobox-web): add the combobox core, its container and view model—src/core/: the generic envelope, the combobox ViewModel contract, and the composition root in the style of datagrid-web and gallery-web:comboboxConfig(static properties read once, including the selector family),ComboboxGateProps(the Mendix values the Core derives from),CB_TOKENS,ComboboxContainer+createComboboxContainer,FilterInputEventService(the debounced filter-input action as a setup component, disposed on unmount),ComboboxCore(injected with selector, config, gate and the service; cached slices, bound commands) anduseComboboxCore.SingleSelectionandMultiSelectionread the snapshot only; the downshift hooks take the Core.getSelector,useGetSelectorand the hand-built preview core props are gone; the editor preview usescreatePreviewContainer. Specs: 19 Core and hook tests, 12 container tests, 6 service tests.refactor(combobox-web): drop the deprecated search-term callback—onAfterSearchTermChangeand its three tests.docs(combobox-web): record migration step 2 as an openspec change—openspec/changes/combobox-viewmodel, status lines and the composition-root decision in the design docs.Deferred on purpose, listed in the step 2 change: open state, input value and highlight stay with downshift until step 3 (Behavior), which also replaces the selectors'
updatePropswith derivations over the gate; option content is still rendered by the captions providers until step 4 (classes and parts), so the editor preview overrides survive untouched.brandi-reactis not added: views read a plain snapshot and never resolve from the container.Verification:
pnpm exec tsc --noEmitclean;pnpm run test18 suites, 213 tests, 5 snapshots unchanged, no-u; lint 0 errors;pnpm run buildOK. E2E has not run: the build workflow only triggers for PRs targetingmain, so it runs once #2499 merges and this branch is rebased.