Repository navigation
fix(plugin-view): hand ObjectGallery the gallery block nested, so coverFit, cardSize and visibleFields take effect (objectui#12053) - #12069
Merged
objectstack-fleet[bot] merged 2 commits intoOct 9, 2026
Conversation
…erFit, cardSize and visibleFields take effect (objectui#12053) generateViewSchema's gallery branch built a flat object-gallery node carrying imageField (from coverField) and titleField only. ObjectGallery reads coverFit, cardSize and visibleFields off schema.gallery and nowhere else, so a gallery view handed to plugin-view's ObjectView, through the host views prop or a named listViews entry, drew contain covers cropped, at the default card size, with no card body. The branch now builds the node's own nested gallery block, the shape ListView already hands the same renderer. The keys are picked by name through GALLERY_CONFIG_SPELLING, total over the spec's gallery block, so no raw spread carries an undeclared key or overrides a node key. One spelling per key: the flat imageField / titleField pair is gone (the renderer reads the nested coverField / titleField ahead of them), and the branch's 'name' title floor moves into the block. Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
…ectui#12053) Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
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
|
objectstack-fleet
Bot
deleted the
claude/issue-12053-view-gallery-block
branch
October 9, 2026 19:08
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 #12053
Clause-②: no
Implemented by the os-dev dispatched from seat
domain:ui#3, sessionsession_01CGZy1BGCjdN5cXqL9cnvB8, on the claim in comment6086543001.What changed
generateViewSchema's gallery branch (packages/plugin-view/src/ObjectView.tsx) now handsObjectGallerythe gallery block nested, as the node's owngallery. That is the shapeListViewalready hands the same renderer. Before, the branch built a flat node that carriedimageField(fromcoverField) andtitleFieldonly, so a gallery view handed to plugin-view'sObjectViewlostcoverFit,cardSizeandvisibleFields. That held for the hostviewsprop and for a namedlistViewsentry alike.GALLERY_CONFIG_SPELLING, with the existingpickFlatMapConfighelper. The gantt and timeline branches already use this mechanism (objectui#6152 round 14). The table is asatisfies Recordkeyed by everykeyofof the spec's gallery block (SpecListView['gallery']), so a key the spec adds or drops failstschere. ⛔ No raw spread: an undeclared key in the authored block does not reach the node, and a block key named like a node key cannot override the node's own value.imageFieldandtitleFieldare gone from the node, becauseObjectGalleryreads the nestedcoverFieldandtitleFieldahead of them (measured below). The branch's existing'name'title floor moves into the block with the key it floors, so an undeclared title still resolves toname.ObjectGallery,ListViewand every other branch ofgenerateViewSchemaare untouched. No export, prop, type member or language-pack key changes.GALLERY_CONFIG_SPELLINGis not exported.Dispatch zone 2: the three hypotheses, measured
What
ObjectGalleryreads, and in what order. These are the read points inpackages/plugin-list/src/ObjectGallery.tsx, in the block under the commentResolve GalleryConfig with backwards-compatible fallbacks:coverField:gallery?.coverField ?? schema.imageField ?? 'image'(nested first)coverFit:gallery?.coverFit ?? 'cover'(nested only)cardSize:gallery?.cardSize ?? 'medium'(nested only)titleField:gallery?.titleField ?? schema.titleField(nested first)visibleFields:gallery?.visibleFields(nested only)⇒ once the block is nested, the flat pair can only restate a nested value, so it is dropped (one spelling per key).
The declared set.
@objectstack/spec17.7.0, as plugin-view resolves it, declaresGalleryConfigSchema(strict) asListViewShapeSchema.gallery. That shape feedsListViewSchemaand the named-viewObjectListViewSchema. Its keys arecoverField,coverFit,cardSize,titleFieldandvisibleFields.ObjectGalleryreads exactly these five offschema.gallery. No key is on one side only, so this is not a stop. The objectui node typeObjectGallerySchema.galleryis typed as the spec'sGalleryConfig.Named
listViews.canonicalViewKindBlocks.galleryfolds a named view'sgalleryinto the sameviewOptions.gallerythe hostviewsentry feeds, so both reach the same branch. Pinned: every route pin in the new test file runs on both routes.End-to-end reading through the real
ObjectGalleryThis is a scratch probe and is not committed. It uses the real
SchemaRenderer, imports@object-ui/plugin-list(through the root vitest alias) for itsobject-galleryregistration, and mounts plugin-view'sObjectViewwith the gallery block{ coverField: 'photo', coverFit: 'contain', cardSize: 'small', visibleFields: ['stage'] }and one row that carries a cover URL.viewspropobject-coverimg, medium grid (lg:grid-cols-4), nostageon the cardobject-containimg, small grid (xl:grid-cols-6),stagevalue shownlistViewsentryWhy the probe is not committed: plugin-view does not depend on
@object-ui/plugin-list, and its type-checked test program (tsconfig.test.json,paths: {}) cannot resolve that package. The committed pins read the generated node at theSchemaRendererseam, as every sibling file in this package does. The app-shell import-side run below does reach the realObjectGallerythrough this branch, with no gallery block.Tests
packages/plugin-view/src/__tests__/ObjectView.galleryBlockNested-12053.test.tsx. It holds triage's pins (comment6080379082). Each route pin runs on the hostviewsprop and on a namedlistViewsentry:coverFit: 'contain'reachesgallery.coverFit;cardSizeandvisibleFieldsreachgallerythe same way;ListViewSchema.shape.gallery, reachesgallery;imageFieldortitleField;namefloor inside the block;objectName) reaches neithergallerynor the node.imageFieldthis card retires):ObjectView.readersRetired-6152.test.tsx, section 3 and its header bullet;ObjectView.namedViewProtocolKeys-8980.test.tsx, thegallerycase.ListView), unchanged: plugin-listListView.galleryOptionsBagCanonical-6152,ListView.readersRetired-6152,ListView.test.tsxand the twelveObjectGallery.*files: 15 files, 227 tests passed.Reverse verification (ablation)
Predictions were written before either run. The mutation went through
ablation-replace.mjsfrom the objectstack checkout (objectui has none), in wrap mode, with blob-equal restores. The tests import../ObjectViewrelatively, from source, and no alias ordist/is involved, so no rebuild was needed. Runs were on HEADa31f6aa85, the fix commit.imageFieldfromcoverFieldplus a flattitleField, no nested block). Predicted: all 11 new pins red, both re-spelled pins red, the probe red on both routes. Observed: 16 failed, 48 passed (64). Exactly that set, and the probe readings in the table above. Mutation landed: anchor 1 to 0, blob5fae6dbb4b45toabf92739b839. Restored: blob equals HEAD (5fae6dbb4b45),git diff HEADempty....viewOptions.galleryin place of the pick). Predicted: the new control red, the round-14 gallery arm (objectNamehijack) red, the retired-imageFieldpin red, everything else green. Observed: 3 failed, 61 passed (64). Exactly those three. Restored: blob equals HEAD,git diff HEADempty.Gates (union run after the final commit, HEAD
c346c41f7)pnpm exec vitest run packages/plugin-view/Test Files 74 passed (74),Tests 691 passed (691)ListView/ObjectGallerycontrol setTest Files 15 passed (15),Tests 227 passed (227)PageView.refreshInPlace-10519(drivesdefaultViewType: 'gallery'through this branch into the realObjectGallery), app-shellObjectView.titleFieldConvergence,examples/schema-catalog/test/catalog-gallery-renderTest Files 3 passed (3),Tests 603 passed (603)pnpm --filter @object-ui/plugin-view type-check(afterpnpm --workspace-concurrency=2 --filter '@object-ui/plugin-view^...' build, exit 0)tsc --noEmit && tsc -p tsconfig.test.jsonclean;--listFilescounts all three touched test files in the test programpnpm exec eslinton the 4 touched source filesno-explicit-anyand kin; warnings carry no ratchet)pnpm check:control-bytescheck-control-bytes: OKpnpm check:test-path-rootscheck-test-path-roots: OKpnpm check:changeset-claimsNo pending changeset names a file this change touches.pnpm check:pending-changeset-literalsNo test source names a pending changeset.pnpm check:new-line-citationsVERDICT new-cross-file-line-citations: 0 new citation(s)pnpm check:vi-mock-specifiers/check:vi-mock-inherit/check:vi-mock-override-shapeOKeachpnpm check:shell-escape-residue/check:handler-key-reads/check:unreferenced-sources/check:metadata-write-doorsOKeachnode scripts/check-changeset-presence.mjs/check-changeset-no-major.mjs.changeset/12053-view-gallery-block.md(patch);No changeset declares a major bump.The eslint narrowing is a measurement, not a skip.
eslint.config.jslints**/*.{ts,tsx}.parserOptions.project, noprojectService), and no rule undereslint-rules/reads another file. So this diff cannot move an untouched file's verdict.The repo-wide
pnpm lintis CI's.NOT MEASURED:
check:eager-closure, reason: it needs the console build and belongs to CI. The diff adds one five-entry const and moves no import.check:readme-exports, reason: no export changes.Acceptance notes
ListView's gallery branch (out of scope here) still builds its nested block by spreadingschema.options?.galleryandschema.gallerywhole. It also writes a flattitleFieldbesidegallery.titleField, so there are two spellings on that route. The undeclared keys it carries are inert there:ObjectGalleryreads five keys off the block, and nested keys cannot override node keys. Observation only; there is no wrong answer at a public door. Carrier: none.nametitle floor. Both routes floortitleFieldat the literal'name', whileObjectGallery's own ADR-0079 comment prefersgetRecordDisplayNameto a literal'name'floor. This PR keeps the floor as existing behaviour. Observation, not measured at a public door. Carrier: none.ObjectGallerythrough plugin-view'sObjectView(see the probe section for why). Carrier: none.Generated by Claude Code