Repository navigation
fix(components,plugin-view): date / datetime list filters draw the platform date picker (objectui#12743) - #12782
Merged
objectstack-fleet[bot] merged 4 commits intoOct 16, 2026
Conversation
… date widget (objectui#12743) FilterBuilder resolves `field:date` / `field:datetime` from ComponentRegistry at render time, the way the form renderer in this package resolves `field:<type>`. @object-ui/fields registers the platform picker there behind its lazy loader, so this package stays fields-free and the picker stays in its own chunk. With nothing registered the row keeps the native input. The row's value keeps its shape (YYYY-MM-DD; the zoneless local YYYY-MM-DDTHH:mm for datetime). A pointer press outside the editor blurs it first, so the picker's commit-on-blur reads the typed text before a host popover closes. Escape discards. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
…red date widget (objectui#12743) FilterUI resolves `field:date` from ComponentRegistry at render time, as FilterBuilder's date rows do, so plugin-view needs no @object-ui/fields dependency. The value stays YYYY-MM-DD; an outside pointer press blurs the editor first so the picker's commit-on-blur reads the typed text. With nothing registered the native input stays. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
… date picker (objectui#12743) Pins on the real ListView -> FilterBuilder path with @object-ui/fields registered: the picker face and the zh placeholder; a typed day applied on Enter, on blur and on a press outside the panel; a datetime row keeping the zoneless local shape; text and number rows unchanged. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
…icker (objectui#12743) Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB
Contributor
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
This was referenced Oct 16, 2026
Contributor
Author
Review: ACCEPT — objectui PR #12782 ·
|
objectstack-fleet
Bot
deleted the
claude/issue-12743-filter-date-picker
branch
October 16, 2026 20:49
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.
Fixes #12743
Clause-②: no — measured correction of the claim's provisional
yes. No export, prop, type member, dependency or language-pack key is added or removed.@object-ui/componentsstill does not import@object-ui/fields, and@object-ui/plugin-viewgains no dependency. Both filter UIs resolve thefield:date/field:datetimewidget that@object-ui/fieldsalready registers inComponentRegistry, the way the form renderer in@object-ui/componentsalready resolvesfield:TYPE. The value each filter writes keeps its shape.Half 2 of objectui#12664's triage scope (
6216283515). Half 1 (the grid cell seam) landed asd66d7e8.What changed
FilterBuilder(packages/components/src/custom/filter-builder.tsx). Adate/datetimerow, scalar and bothbetweenbounds, draws the widget the host registered asfield:date/field:datetime(registeredTemporalWidget, read at render time). A new module-privateTemporalValueEditorrenders it:Suspense, with a placeholder that holds no input (the widget arrives lazily);Value, orFrom/Toon the bounds). The picker's placeholder is the locale pattern;YYYY-MM-DDfor date. For datetime, the picker's ISO instant is read back onto the zoneless localYYYY-MM-DDTHH:mmthatdatetime-localwrote. It usestoDateTimeInputValuefrom@object-ui/core, the adapter the picker reads with;DataTableuses for injected cell editors). The picker's commit-on-blur therefore reads the typed text before a host popover or drawer closes. Escape does not blur: it discards.@object-ui/fieldsloaded), the row keeps the native input, as the form does.timerows are unchanged.FilterUI(packages/plugin-view/src/FilterUI.tsx). Thedatefilter and bothdate-rangebounds take the same route (DateFilterInput:field:datefrom the registry, its ownSuspense, the same outside-press blur). The value staysYYYY-MM-DD; the native input stays when nothing is registered..changeset/12743-filter-date-picker.md:@object-ui/componentsand@object-ui/plugin-view, patch.Measured at start (PM assumption A1)
plugin-list'sListViewtoolbar Filter panel rendersFilterBuilderfrom@object-ui/components(extraOperators={LIST_VIEW_EXTRA_OPERATORS}).components/src/renderers/complex/filter-builder.tsxis the SDUIfilter-buildernode renderer around the same component, so it needed no edit.plugin-view'sFilterUIis the SDUIfilter-uiblock. A grep ofapps/console,app-shellandplugin-listforfilter-ui/FilterUIfound no renderer of it: it is reached only through authored nodes (docs, the schema catalog).FilterBuilderusedInput type={FILTER_INPUT_TYPE_BY_FAMILY[...]}:date,datetime-localandtime. Thebetweenbounds used the same.FilterUIusedInput type="date".registerAllFields()registersfield:date/field:datetimeaswithFieldCarrier(React.lazy(loader)), the loadersimport()thefields-date-pickerchunk, and@object-ui/fieldsruns it on import. The form renderer in the same package (renderFieldComponent) resolvesfield:TYPEfrom it. So the preferred route needed no new export, prop or dependency. The ruling's fallbacks (a) and (b) were not needed.Tests (A2)
New pins:
packages/plugin-list/src/__tests__/ListView.filterDatePicker-12743.test.tsxruns on the real console path,ListViewtoolbar →FilterBuilder, withregisterAllFields(). Only the data source is faked. It pins:input[type=date](en:MM/DD/YYYY,10/01/2026); azhsession givesYYYY/MM/DD/2026/10/01;10/20/2026is applied as2026-10-20on Enter, on blur, and on a press outside the panel (pointerdown + click; the panel closes);10/01/2026, 09:15 AMand writes2026-10-20T14:30from a typed10/20/2026 14:30;type=text/type=number.packages/components/src/__tests__/filter-builder-date-value-seam-12743.test.tsxtests the seam with a commit-on-blur stand-in widget, becausecomponentscannot importfields. It pins the scalar andbetweenfaces, blur, Enter, an outside press, an inside press that does not blur, Escape discarding, the datetime shape, and two CONTROLs: text/number rows, and no registration keeping the native input.packages/plugin-view/src/__tests__/FilterUI.datePicker-12743.test.tsxcoversdateanddate-range, blur and outside press, plus a CONTROL (the text filter, and the native input with no registration).pnpm check:eager-closureon a consolevite buildof this branch exits 0 and printspackages/fields 88 modules in ui-components and its src/widgets/date-picker subtree 2 in fields-date-picker, exactly.dist/eager-closure.jsondoes not namefields-date-picker.Ablations. Each leg ran at HEAD
3fc88bff0throughscripts/ablation-replace.mjsfrom the objectstack checkout: the anchor was x1 before and x0 after, and each leg was restored with blob == HEAD andgit diff HEADempty. Vitest aliases@object-ui/componentstosrc, so no dist step was needed.registeredTemporalWidgetreturnsundefined; blob3d6f94a→868ba46): 14 failed | 3 passed. Every (a)/(b)/(c) pin in both files went red; the three CONTROLs stayed green.focused.blur()→void focused; blob →9459827): 2 failed | 15 passed: the ListView outside-press pin and the seam outside-press pin.FilterUIwiring (ComponentRegistry.get('date', 'field')→undefined; blob12e4922→4811b31): 2 failed | 1 passed.Runs. Each run used
--maxWorkers=1under the verify lock, with the tree at3fc88bff0or an earlier commit of this branch whose files the later commits did not change:packages/components/src/__tests__/filter-builder*file plusexamples/schema-catalog/test/filter-builder-mirror-6939.test.tsx: 20 files / 417 tests passed;FilterBuilder/config-field-renderer: 4 files / 26 passed;plugin-listtests that open the Filter panel or holdinitialFilters: 13 files / 95 passed;packages/plugin-view/whole dir: 79 files / 723 tests passed.NOT MEASURED: the whole-package run of
packages/components/. It hit its 1500s timeout (exit 124), so the targeted sets above are declared in its place and CI runs the full farm. NOT MEASURED: a real-browser screenshot (no backend booted).Gates (local)
pnpm --workspace-concurrency=2 --filter '@object-ui/components^...' --filter '@object-ui/plugin-view^...' buildand--filter '@object-ui/plugin-list^...' build(which rebuilds components with this change): exit 0.type-check: components 0, plugin-view 0, plugin-list 0. Each package'stsconfig.test.jsonglobssrc/**/*.test.tsx.--no-inline-config, narrowed to the 5 changed.ts/.tsxfiles (the population is the config's**/*.{ts,tsx}block; the JSON format counted 5 files). Result: 0 errors. The two sources carry the same warning counts as their BASE blobs (20 and 7). The config has noproject/projectService, so linting is not type-aware and this diff cannot move a verdict on an untouched file.check:phantom-deps,check:self-import,check:unreferenced-sources,check:doc-example-readers,check:handler-key-reads,check:side-effects-array,check:element-data-source-declaration,check:spec-symbols,check:action-forward-parity,check:designer-field-key-parity,check:icon-record-names,check:i18n-keys,check:i18n-drift,check:i18n-designer-parity,check:control-bytes, andcheck-hand-rolled-comment-mask.mjs.check-changeset-fixed.mjs,check-changeset-presence.mjs,check:new-line-citations,check:eager-closure.Acceptance notes
clickthat follows a primary-button pointerdown (deferPointerDownOutside). In a browser, the mousedown between them moves focus and already blurs the picker. The capture listener makes the commit independent of how a host dismisses: a drawer, another popover version, or a host that unmounts on pointerdown. Ablation B shows it is what carries the commit when nothing else moves focus.error, which drives itsaria-invalid.aria-describedbyis not in the field widget's DOM pass-through list (toDomProps), so the visible "is required" line is not linked to the picker's box as it is to the native input's. The native path is unchanged and its pins still pass.plugin-list(UserFilters.tsx) draw a nativetype="date"pair for a date range. That file is outside this claim's surface. It was read from source only and not reproduced. It is reported to the seat, not built here.Written by the os-dev for this card, session
https://claude.ai/code/session_01XVp19E1MYUTFM3dnkwz8gB.Generated by Claude Code