Repository navigation
fix(plugin-detail): the inline date editor marks an impossible stored day instead of blanking it (objectui#10625) - #10648
Conversation
…impossible day (objectui#10625) Red against the unfixed editor: a stored 2026-02-30 on a date field, and 2026-02-30T10:00:00Z on a datetime field, render an empty input type=date with aria-invalid null and no notice. The real-day and no-emit pins pass. Co-Authored-By: Claude <noreply@anthropic.com>
… day instead of blanking it (objectui#10625) InlineFieldInput's date branch (date and datetime fields) now routes to @object-ui/fields' DateField, the editor objectui#10567 already fixed: a stored nonexistent day (2026-02-30, or 2026-02-30T10:00:00Z on a datetime field) opens an empty control marked aria-invalid, described by a notice naming the stored string (isImpossibleStoredDay + fields.date.impossibleDay). No second predicate. The write side keeps this editor's own shape: the picked YYYY-MM-DD is re-emitted as full ISO at local midnight, on user edit only. The data-table half of the card is not in this commit: @object-ui/components cannot depend on @object-ui/fields (fields already depends on components). Co-Authored-By: Claude <noreply@anthropic.com>
…line-date-impossible-day
✅ 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
|
✅ ACCEPTED — PR objectui#10648 at
|
…InlineFieldInput call site (objectui#10625)
The inline date branch no longer calls d.toLocaleDateString('en-CA'); it
routes to DateField. The census's DECLARED entry for that site (count 1)
now finds 0 and reds "every declared exemption matches exactly the sites
it declares", so the entry goes with the call site.
Co-Authored-By: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ ACCEPTED (round 2) — PR objectui#10648 at
|
…5 removed the InlineFieldInput en-CA exemption The pending body said the census declares InlineFieldInput's en-CA as an exemption and carries it forward. objectui#10625 deleted that call (the inline date editor now renders @object-ui/fields' DateField) and the exemption with it. Prose only; frontmatter unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
… the InlineFieldInput entry's removal (objectui#10625) Its reason read "the same ISO-8601 formatter", pointing at the InlineFieldInput entry removed earlier on this branch. Reworded to name what it is on its own. Prose only: file, expression and count unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
✅ ACCEPTED (round 3) — PR objectui#10648 at
|
✅ 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
|
Part of #10625 (the
plugin-detailhalf). Thedata-tablehalf is NOT in this PR: it is a dependency-graph fork that needs a PM or maintainer decision, described below. #10625 remains open for it.What changed
InlineFieldInput's date branch (fordateANDdatetimefields) now renders@object-ui/fields' publicDateFieldwidget instead of a hand-rolledinput type=date.DateFieldalready answers a stored day that does not exist the objectui#10026 direction A way, since objectui#10567 (PR objectui#10618): the control is handed an empty value, markedaria-invalid, and itsaria-describedbypoints at a notice naming the stored string. The judgement isisImpossibleStoredDayand the notice key isfields.date.impossibleDay, both reused through the widget. There is no second predicate and no new export.toDateInputValue. A leadingYYYY-MM-DDpasses through verbatim, so an ISO timestamp is still sliced to its date, as before. A non-string value goes through local calendar getters, which gives the same day the oldtoLocaleDateString('en-CA')gave.YYYY-MM-DD, which is re-emitted as full ISO at local midnight, exactly as before. It emits only on a user edit, never on mount.isDateternaries. Its behaviour is unchanged.Input(the form's control) rather than the plain bordered input. On click it opens the native picker (openNativePicker), and it carries an explicitaria-invalid="false"when valid, as everyfieldswidget does.Reach measurement for the data table (measured before any edit)
Setup: the registered
data-tablerenderer,editable: true, one columntype: dateand onetype: datetime,onCellChangerecording what was staged, happy-dom,TZ=UTC,origin/main4a3d500fd. The probe was a throwaway test file, not committed.2026-02-30(date)''(value attribute2026-02-30)2026-02-302026-02-30T10:00:00Z(datetime)2026-03-02T10:002026-02-30T10:00:00Z2026-03-02T10:05:00.000Z2026-02-14(date)2026-02-142026-02-142026-02-14T10:00:00Z(datetime)2026-02-14T10:002026-02-14T10:00:00ZSo on a directly authored
data-tablethe private copies do what the card says. The date copy blanks silently. The datetime copy shows the rolled day, and any user edit of the time writes the rolled day. Committing with no edit re-stages the stored string unchanged, so nothing rolls on mount or on a bare commit.Scope of that reach:
ObjectGrid(the object-view grid) injectsrenderCellEditor, which rendersFieldEditWidgetfor every field type that has a widget,dateanddatetimeincluded. So the object grid never reaches these private copies, and it already gets the repairedDateField/DateTimeField. The copies are reached by a schema-authoreddata-tablenode witheditable: trueand adate/datetimecolumn, and by anObjectGridcolumn that has no matching field definition.The data-table fork (not implemented; PM decision needed)
The ruling says to replace the private
toDateInputValue/toDateTimeInputValuecopies inpackages/components/src/renderers/complex/data-table.tsxwith the shared@object-ui/fieldsadapters. That import cannot exist.@object-ui/fieldsdeclares@object-ui/componentsas a dependency, and 55 files underpackages/fields/srcimport from it, socomponentsimportingfieldsis a package cycle. AGENTS.md section 3 also placescomponentsbelowfields(Atoms, then Fields). Per the dispatch, the work stopped there. Options are in the report on the card.Red, then green
61f0c0727against the unfixed editor:pnpm exec vitest run packages/plugin-detail/src/__tests__/InlineFieldInput.impossibleDay-10625.test.tsxgivesTests 2 failed | 2 passed (4). Both impossible-day cases fail withAssertionError: expected null to be 'true'onaria-invalid. The control value was already empty (the silent blank). The real-day and no-emit pins pass.1e1a2cc14: the same file plusInlineFieldInput.test.tsx,InlineFieldInput.delegation.test.tsxandinlineEditTypeCoverage.test.tsxgiveTest Files 4 passed (4),Tests 117 passed (117).Gates
pnpm --filter @object-ui/plugin-detail test:Test Files 212 passed | 1 skipped (213),Tests 2082 passed | 8 skipped (2090). This ran on the fix commit, before the merge oforigin/main. The merge touched none ofplugin-detail,fields,core,componentsori18n.pnpm --filter @object-ui/plugin-detail type-check: exit 0, after building the@object-ui/plugin-detail^...dependency closure with turbo.pnpm --filter @object-ui/plugin-detail lint: exit 0,0 errors.check:changeset-claims,check:pending-changeset-literals,check:new-line-citations(0 new),check:control-bytes,check:i18n-keys,scripts/check-changeset-presence.mjsandscripts/check-changeset-no-major.mjs: all exit 0.pnpm lint/pnpm testare left to CI.Session
https://claude.ai/code/session_01D486C1axmXnrkJMNUfz2eb, seatdomain:ui#3.Generated by Claude Code