Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

fix(grid): a lookup or master_detail cell draws no tooltip carrying the raw id (objectui#13377) - #13401

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-13377-lookup-cell-tooltip
Oct 23, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-13377-lookup-cell-tooltip

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Closes #13377
Clause-②: yes (widening: TableColumn gains optional foreignKey; nothing is refused)

What changed

data-table's plain cell wrapper set its title tooltip to String(cellValue) for every value that is not masked and not an object. For a lookup / master_detail column that value is the referenced record's raw id, so hovering beside the drawn name, or beside "Restricted record" (PR #13376), showed the id. The column reached the table untyped (normalizeTableColumnType keeps only the table's own types), so the table could not tell.

  • @object-ui/types: TableColumn gains one optional boolean, foreignKey, declared next to masked and chips. Doc: the column's raw value is a foreign key (the id of a referenced record: a lookup, master_detail, tree or user field) while its cell draws the record's name; the cell carries no title tooltip; unlike masked it withholds nothing else (copy, CSV export, inline edit, search and sort unchanged); written by ObjectGrid from the column's field type. Mirrored the way chips is: TableColumnSchema types it z.boolean().optional() (a non-strict object would strip it otherwise), and the static table column tombstones it in both faces (StaticTableColumn.foreignKey?: never, retirementTombstone(...) in StaticTableColumnSchema), which the _SameKeySet lockstep pin requires.
  • @object-ui/components: the cell wrapper's title expression adds !col.foreignKey. No other path reads the flag.
  • @object-ui/plugin-grid: ObjectGrid's last column pass (the emit seam beside the masked and chip flags) stamps foreignKey: true when isExpandableFieldType (from @object-ui/core, the grid's existing reference family: lookup, master_detail, tree, user) holds for the column's type, read the same way as the chip flag (the authored type first, then the object's). Written only when true; a masked column carries masked alone, as before. chips and foreignKey are stamped independently.
  • One changeset: @object-ui/types minor (a new optional published member, as for masked and chips), @object-ui/components and @object-ui/plugin-grid patch.

Tests

New pins:

  • packages/plugin-grid/src/__tests__/lookupCellTooltip-13377.test.tsx, through the real ObjectGrid with a readable and a restricted reference in a lookup column (authored type: 'lookup') and a master_detail column (no authored type, typed by the object): no title in any of those cells carries either id, the table's wrapper has no title, and neither id is anywhere in the grid's DOM. Controls: the plain text column of the same grid keeps its value as its tooltip; a view column that authors type: 'text' over the same lookup field draws the id as its text and keeps its tooltip (the flag follows the type the cell is drawn by).
  • packages/components/src/renderers/complex/__tests__/data-table-foreign-key-tooltip-13377.test.tsx: foreignKey: true drops the tooltip while an ordinary column keeps its own; Ctrl+C still copies the raw value (only the tooltip is withheld); the flag absent and false both keep the tooltip; the zod mirror keeps the flag and refuses a non-boolean.
  • packages/types/src/__tests__/static-table-narrow-surface.test.ts: foreignKey joins the rich key list, the retired-key fixture and the tombstone-message loop.
  • The comment in lookupRestrictedRecord-13335.test.tsx that said the wrapper still puts the raw value in its title now points to the new pin.

Results, at head 3114b300d:

  • pnpm exec vitest run --maxWorkers=2 packages/types/ packages/components/src/renderers/complex/ packages/plugin-grid/ plus lookupCell.restrictedRecord-13335, lookupCell.unresolvedReference-8695 (fields), DetailSection.restrictedLookup-13335, RelatedList.maskedColumn-10657 (plugin-detail) and ObjectDataTable.maskedColumn-10657 (plugin-dashboard), under the verify lock: Test Files 670 passed (670), Tests 13048 passed (13048), lock VERDICT command-exit 0.
  • turbo run type-check --concurrency=2 --filter=@object-ui/types --filter=@object-ui/components --filter=@object-ui/plugin-grid: Tasks: 17 successful, 17 total, VERDICT command-exit 0.
  • check:new-line-citations (0 new), check:control-bytes, check:spec-symbols, check:component-surface-parity, check:changeset-claims, check:pending-changeset-literals, check:test-path-roots, check:doc-types, check:handler-key-reads, check-changeset-no-major, check-changeset-presence: all exit 0.
  • ESLint on the touched files: 0 new errors. The two errors it prints (Cannot create components during render, one in data-table.tsx, one in ObjectGrid.tsx) are on the base commit too (same count when the base blobs are linted), not on lines this PR touches.

Ablation (fix committed first, each leg restored with git checkout HEAD -- and verified by blob hash):

  • Drop !col.foreignKey && from the data-table title expression: the flagged data-table test and the grid pin go red (2 failed | 5 passed); the controls stay green.
  • Replace the grid's stamp with false: the grid pin goes red (1 failed | 1 passed).

Acceptance notes

  • Docs not updated (outside the claimed file surface). content/docs/components/complex/data-table.mdx lists TableColumn members including masked and chips in its Schema block, and has "Chip columns" / "Masked columns" sections. It does not yet list foreignKey. A one-line Schema entry (plus, optionally, a sentence) is the follow-up; this PR does not touch docs because the claim did not declare them.

  • Not measured: the other producers of data-table columns. RelatedList (@object-ui/plugin-detail) and ObjectDataTable (@object-ui/plugin-dashboard) also stamp masked on the columns they hand data-table, and do not stamp foreignKey. If their lookup cells carry a raw id as the cell value, the same tooltip shows it there. This is read from source only, not reproduced.

  • The object-type half of the stamp (objectFields[...]?.type when the column has no type of its own) is not exercised by the grid pin: the master_detail column with no authored type is typed before this pass, so it is flagged by the producer type. The fallback is kept for parity with the chip flag.

  • Not checked in a real browser; the observable is the DOM title attribute.

  • Adds no product-specific widget, dialog, hook or string (see AGENTS.md › Product-neutral renderer)

🤖 Generated with Claude Code

https://claude.ai/code/session_01WJozybDmRH8z2c5SD7vJkj

…he raw id (objectui#13377)

data-table's cell wrapper set its title tooltip to String(cellValue), and for
a reference column that value is the referenced record's id, so hovering
beside the drawn name, or beside "Restricted record", showed the id.

- @object-ui/types: TableColumn gains optional `foreignKey` (zod mirror
  typed; the static table column tombstones it, like masked and chips).
- @object-ui/components: data-table skips the title tooltip for it.
- @object-ui/plugin-grid: ObjectGrid's last column pass stamps it on
  lookup / master_detail / tree / user columns (isExpandableFieldType over
  the authored and the object-declared type).

Claude-Session: https://claude.ai/code/session_01WJozybDmRH8z2c5SD7vJkj
Co-authored-by: Claude <noreply@anthropic.com>
…by (objectui#13377)

Same precedence as the chip flag (authored type first, then the object's):
a view column that authors `type: 'text'` over a lookup draws the id as its
text, so it keeps its tooltip. Pinned as a second control in the grid test.

Claude-Session: https://claude.ai/code/session_01WJozybDmRH8z2c5SD7vJkj
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 77 chunks) 3242.6 KB 3744.1 KB
Main entry chunk (gzip) 81.8 KB 350 KB
Entry file index-DKfPmXx2.js —
Status PASS —

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

Package Size Gzipped
app-shell (buildIdentity.js) 0.80KB 0.49KB
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 21.41KB 7.90KB
app-shell (runtime-config.js) 24.52KB 8.48KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 45.59KB 12.03KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 20.67KB 6.12KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.74KB 3.94KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.62KB 0.83KB
auth (authStyles.js) 5.27KB 1.86KB
auth (createAuthClient.js) 42.84KB 11.66KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 617.55KB 150.59KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 253.04KB 70.68KB
fields (index.js) 296.30KB 75.73KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 41.33KB 11.98KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (ServerReadScope.js) 4.03KB 1.82KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.99KB 0.43KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 55.56KB 16.21KB
plugin-charts (index.js) 86.08KB 23.67KB
plugin-chatbot (index.js) 238.47KB 56.30KB
plugin-dashboard (index.js) 147.76KB 40.03KB
plugin-designer (index.js) 233.95KB 50.08KB
plugin-detail (index.js) 267.63KB 71.14KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 186.64KB 48.54KB
plugin-gantt (index.js) 178.46KB 45.13KB
plugin-grid (index.js) 278.46KB 77.50KB
plugin-kanban (index.js) 64.49KB 19.83KB
plugin-list (index.js) 149.89KB 39.29KB
plugin-map (index.js) 27.17KB 9.00KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 46.66KB 13.13KB
plugin-timeline (index.js) 39.31KB 11.88KB
plugin-tree (index.js) 15.27KB 5.40KB
plugin-view (index.js) 94.54KB 24.33KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 129.13KB 42.23KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.71KB 2.11KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (product-blocks.js) 0.20KB 0.19KB
types (record-approval-decision.js) 0.20KB 0.20KB
types (record-components.js) 0.20KB 0.19KB
types (record-panels.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Oct 23, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: TIER_DEFAULT
Head-sha: 615a7656cf01b148355db7ea842aae264a1441ba
Local-runs: probe — scripts/check-governed-queue-guard.mjs --test over the committed file list, to read the face (NOT GOVERNED, 10 paths)

Face: the Clause-②: yes declaration alone (no published schema, no governed path), so the lane seat reviews at TIER_DEFAULT. Inputs read: the card objectui#13377, its claim 6369090519 and the seat's amendment adding the docs page, and the PR diff at this head. Check conclusions are taken from this head's check-runs.

① Derived judgments

The diff adds one public member and changes no existing one: @object-ui/types TableColumn.foreignKey?: boolean.

  1. Meaning. The column's raw value is the id of a referenced record (lookup, master_detail, tree or user), while the cell draws that record's name. The only reader is data-table's cell wrapper, which then draws no title tooltip.
    • Unlike masked, it withholds nothing else: copy, CSV export, inline edit, search and sort are unchanged.
    • Absent or false, the table behaves exactly as before.
    • Correct.
  2. Mirrors. The zod TableColumnSchema types it as z.boolean().optional(), as it does masked and chips; the object is non-strict, so without the line it would be stripped silently.
    • The static table column refuses it by name in both faces (foreignKey?: never and a retirementTombstone), as for masked and chips. The _SameKeySet type pin requires that pair.
    • Correct.
  3. Writer. ObjectGrid's last column pass sets it only when true and never on a masked column. It reads the authored type first, then the object's field type (the chip flag's precedence), through isExpandableFieldType, the grid's existing reference set.
    • A view that authors type: 'text' over a lookup draws the id as visible text and keeps its tooltip, which is correct: hiding the tooltip there would protect nothing. A control pins this case.
    • Correct.

The new member is a display hint, not an access control. The visible cell text and copy are governed as before, and the restricted-record rendering of objectui#13335 is unchanged.

② Semver level

The changeset declares minor for @object-ui/types (one new optional published member, the precedent of masked and chips) and patch for @object-ui/components and @object-ui/plugin-grid. That matches the diff, and no major is declared.

③ Boundary flags

  • The docs page content/docs/components/complex/data-table.mdx joined the file surface by the seat's claim amendment. It lists the member in its Schema block (commit 615a765; check:doc-snippets compiles that block). The PR body's Acceptance notes still call the docs not updated; that note is superseded by this commit, and this record and the seat's ACCEPT carry it.
  • RelatedList (@object-ui/plugin-detail) and ObjectDataTable (@object-ui/plugin-dashboard) also hand columns to data-table and stamp masked but not foreignKey. The dev did not reproduce the tooltip there, so it is noted in the PR's Acceptance notes rather than filed. It moves no floor.
  • No open questions from the dev.

Implemented-by: claude/issue-13377-lookup-cell-tooltip
Reviewed-by: session_01WJozybDmRH8z2c5SD7vJkj

VERDICT: PASS

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 77 chunks) 3242.9 KB 3744.1 KB
Main entry chunk (gzip) 81.8 KB 350 KB
Entry file index-C2CkxplI.js —
Status PASS —

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

Package Size Gzipped
app-shell (buildIdentity.js) 0.80KB 0.49KB
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 21.41KB 7.90KB
app-shell (runtime-config.js) 24.52KB 8.48KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 45.59KB 12.03KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 20.67KB 6.12KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.74KB 3.94KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.62KB 0.83KB
auth (authStyles.js) 5.27KB 1.86KB
auth (createAuthClient.js) 42.84KB 11.66KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.26KB 8.03KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (commentAuthorship.js) 1.39KB 0.78KB
collaboration (index.js) 1.93KB 0.85KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 617.55KB 150.59KB
core (index.js) 10.18KB 4.04KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 253.04KB 70.68KB
fields (index.js) 296.30KB 75.73KB
i18n (LocalizationContext.js) 2.92KB 1.42KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.52KB 2.39KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 36.87KB 9.88KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 41.33KB 11.98KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 15.35KB 5.51KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.82KB 2.38KB
permissions (ServerReadScope.js) 4.03KB 1.82KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.99KB 0.43KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 55.56KB 16.21KB
plugin-charts (index.js) 86.08KB 23.67KB
plugin-chatbot (index.js) 238.47KB 56.30KB
plugin-dashboard (index.js) 147.76KB 40.03KB
plugin-designer (index.js) 233.95KB 50.08KB
plugin-detail (index.js) 267.63KB 71.14KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 186.64KB 48.54KB
plugin-gantt (index.js) 178.46KB 45.13KB
plugin-grid (index.js) 278.46KB 77.50KB
plugin-kanban (index.js) 64.49KB 19.83KB
plugin-list (index.js) 149.89KB 39.29KB
plugin-map (index.js) 27.17KB 9.00KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 46.66KB 13.13KB
plugin-timeline (index.js) 39.31KB 11.88KB
plugin-tree (index.js) 15.27KB 5.40KB
plugin-view (index.js) 94.54KB 24.33KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 12.07KB 3.68KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 129.13KB 42.23KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.71KB 2.11KB
react (schema-input.js) 4.31KB 2.07KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.07KB 1.30KB
sdui-parser (index.js) 7.30KB 3.12KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.81KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 23.87KB 7.83KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.44KB 2.07KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 1.13KB 0.65KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.78KB 2.70KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (node-slots.js) 7.18KB 2.34KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (product-blocks.js) 0.20KB 0.19KB
types (record-approval-decision.js) 0.20KB 0.20KB
types (record-components.js) 0.20KB 0.19KB
types (record-panels.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.26KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.48KB 3.50KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对

ACCEPT — objectui#13377 (p3, S), head 615a7656cf01b148355db7ea842aae264a1441ba, reviewed 2026-10-23T17:18Z.

Seat: domain:ui#1 · Clause-②: yes(合同复核见本 PR 上的 ## Contract review,VERDICT: PASS)

项 读数
形态 10 个文件:@object-ui/types 的 data-display.ts 和 zod 镜像及其测试、data-table.tsx 和新测试、ObjectGrid.tsx 和新测试、#13335 测试里一行已不属实的注释、文档 data-table.mdx 一行、一个 changeset(types minor,components、plugin-grid patch)。都在认领加修正后申报的文件面内。NOT GOVERNED。与当前 main 无冲突(本次读取时 git merge-tree 无冲突)。
改动核对 读了 diff。TableColumn 新增可选 foreignKey:列的原始值是被引用记录的 id,单元格画的是记录名(读不到时为「Restricted record」)。data-table 对它不画 title 悬停提示,其他一切(复制、CSV 导出、行内编辑、搜索、排序)不变。ObjectGrid 在最后一遍列处理里按字段类型写入(lookup、master_detail、tree、user,即表格已有的引用类型集),先读视图写的类型、再读对象字段类型,与 chips 同序;被遮罩的列不写。zod 镜像同步,静态 table 列按名拒绝它,与 masked、chips 一致。
新钉测 表格钉测:foreignKey 为真时不画提示、普通列照常、Ctrl+C 仍复制原始值、缺省和 false 都保留提示、zod 保留该字段并拒绝非布尔值。网格钉测(真实 ObjectGrid):lookup 和 master_detail 列各有可读与受限引用,单元格提示和整个网格 DOM 里都没有 id;对照一,纯文本列保留提示;对照二,视图把查找字段写成 type: 'text' 时 id 作为文字显示,提示保留。反向验证:去掉 data-table 的判断,两个钉测变红;网格写入换成 false,网格钉测变红。
门禁 dev 本地:packages/types/、packages/components/src/renderers/complex/、packages/plugin-grid/ 加 #13335 等相关测试共 670 个文件 13048 项通过;types、components、plugin-grid type-check 17/17;check:spec-symbols、check:component-surface-parity、check-changeset-no-major 等通过;文档提交后 check:doc-snippets(编译该 Schema 块)、check:doc-types、check:new-line-citations 通过。CI 全绿后由席位转 ready、进合并队列。
正文更正 PR 正文 Acceptance notes 第一条说文档没有更新;已由提交 615a765 补上(文件面经认领修正加入 data-table.mdx),以本条为准,正文不再改动。
不在本卡内 dev 记下、未复现:RelatedList(plugin-detail)和 ObjectDataTable(plugin-dashboard)也把列交给 data-table,打了 masked 但没打 foreignKey;若其查找单元格的值是原始 id,同样的提示会出现。
落地条款 Closes #13377:合并后关卡。

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 23, 2026 17:20
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 23, 2026 17:20
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 23, 2026
Merged via the queue into main with commit f1a4b08 Oct 23, 2026
37 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-13377-lookup-cell-tooltip branch October 23, 2026 17:37
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

2 participants