Skip to content

fix(plugin-grid): the cross-page select-all banner works under external pagination (#4464) - #4503

Merged
yinlianghui merged 3 commits into
mainfrom
claude/issue-4464-crosspage-totalmatching
Aug 13, 2026
Merged

fix(plugin-grid): the cross-page select-all banner works under external pagination (#4464)#4503
yinlianghui merged 3 commits into
mainfrom
claude/issue-4464-crosspage-totalmatching

Conversation

@yinlianghui

Copy link
Copy Markdown
Collaborator

Closes #4464

The defect

BulkActionBar gates the cross-page banner on totalMatching, and the only writer of that state is setTotalMatching(...) inside ObjectGrid's own data loader. In the console the grid never runs that loader: ListView fetches the rows itself and hands the window down as data plus manualPagination / rowCount / page / onPageChange, so the grid takes the inline-data path, the state stays undefined, and the banner condition is permanently false — for any match-set size.

The tell the issue records is exact: the pager was already correct, because it reads a derived total (externalManualPagination ? rowCount : totalMatching). The grid had the real number on the external path; it just never reached the bar.

The fix — one derived value, three consumers

The pager's derivation is hoisted to a single resolvedTotalMatching, and the pager plus both BulkActionBar render sites now read it. The conditional is written once and only once — two copies of the fallback is how one of them gets missed again (this defect, and #4138 before it). The singleSelection ? undefined : ... suppression is unchanged, and the value resolves to the SERVER total (rowCount, the 26 the reproduction measured), never the page window.

No public type moved: dist/**/*.d.ts is byte-identical built both with and without the change, so this is runtime wiring only — patch for @object-ui/plugin-grid.

Red-first

The pin is a ListView-hosted composition test, not an ObjectGrid unit test: ObjectGrid in isolation fetches its own rows, which runs the internal loader and populates totalMatching — precisely the path the console does not take, so a unit test there stays green either side of the fix. The new file renders the REAL object-grid under ListView with a server that pages for real (26 records, pageSize 10).

Before the fix, with 10 selected on screen and the whole page ticked:

 × offers the cross-page banner when the whole server page is selected
 × carries the SERVER total in the escalation, not the page window
 × escalates the selection past the page when "Select all matching" is clicked

TestingLibraryElementError: Unable to find an element by: [data-testid="bulk-cross-page-banner"]
TestingLibraryElementError: Unable to find an element by: [data-testid="bulk-select-all-matching"]

 Test Files  1 failed (1)
      Tests  3 failed | 3 passed (6)

The three that PASSED pre-fix are the must-not-change cases, green on both sides: a partial page selection shows no banner, selection.type: 'single' suppresses, and a standalone grid on the internal-loader path still offers "Select all 26 matching". After the fix: Test Files 1 passed (1) / Tests 6 passed (6), and packages/plugin-grid/ + packages/plugin-list/ are 95 passed (95) / 1100 passed (1100).

The file is listed in heavyDomTests (vitest.config.mts) so the setup's plugin-grid side-effect registration provides the real renderer — the alternative was a plugin-list to plugin-grid dependency purely for a test. That is the only file touched outside the fix, the test and the changeset.

Reachability note — please read before merging

The census this issue asks for turned up two more members of the same class, filed as #4501. One of them is not merely adjacent: lastFindParamsRef also has a single writer inside that same loader, and it is what resolveBulkRows replays when the user accepts "Select all N matching". On the external path it is null, so the fan-out queries the object with no filter, sort or search, and apps/app-shell's ObjectView wires onBulkDelete to that result.

That path was unreachable before this PR precisely because the banner never appeared. This PR is what makes it reachable, which is what the checklist item asks for — but it means #4501 clause 1 should be graded against this merge rather than triaged at leisure. I did not fix it here: it is outside the ruled surface, and the fix needs a decision (the host has no way to hand its params down today, so it likely wants a prop rather than a fallback inside the grid).

Scope

packages/plugin-grid/src/ObjectGrid.tsx, one new composition test in packages/plugin-list/src/__tests__/, one changeset, and the heavyDomTests entry. plugin-list/src/ListView.tsx source is untouched (imported read-only by the test).


Generated by Claude Code

…al pagination (#4464)

`BulkActionBar`'s cross-page affordance was gated on the `totalMatching` STATE,
whose only writer is ObjectGrid's own data loader. Under a host that fetches the
rows itself (ListView passing `manualPagination` + `rowCount` — the console) that
loader never runs, so the total stayed `undefined` and the banner was permanently
absent for any match-set size, while the pager two lines away already showed the
correct page count from the host's total.

Hoist the pager's derivation to a single `resolvedTotalMatching` and have both
the pager and both `BulkActionBar` sites consume it — one derived value, one
answer, no second copy of the conditional. `singleSelection` gating unchanged.

The pin is a ListView-hosted composition test: ObjectGrid in isolation runs the
internal loader, which is precisely the path the console does not take, so a
unit test there is structurally blind to this defect.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectui Ignored Ignored Aug 13, 2026 3:49am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 24.7 KB 350 KB
Entry file index-C-BfMZSK.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 9.56KB 3.59KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 8.92KB 3.41KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 22.10KB 4.37KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.13KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.64KB 2.21KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 36.76KB 9.60KB
auth (createAuthenticatedFetch.js) 4.37KB 1.69KB
auth (index.js) 2.35KB 1.07KB
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) 4.91KB 0.87KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 26.07KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.65KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 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) 489.32KB 108.45KB
core (index.js) 3.37KB 1.34KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 153.79KB 41.35KB
fields (index.js) 230.07KB 57.07KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 3.35KB 1.38KB
i18n (pickLocalized.js) 3.69KB 1.73KB
i18n (provider.js) 23.12KB 7.62KB
i18n (useDisplayLocale.js) 2.33KB 1.20KB
i18n (useObjectLabel.js) 27.59KB 6.63KB
i18n (useSafeTranslation.js) 7.77KB 3.13KB
layout (index.js) 38.98KB 10.85KB
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.74KB
mobile (index.js) 1.50KB 0.62KB
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) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 8.75KB 3.06KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.13KB 12.76KB
plugin-charts (index.js) 62.07KB 17.65KB
plugin-chatbot (index.js) 181.21KB 43.14KB
plugin-dashboard (index.js) 120.85KB 31.41KB
plugin-designer (index.js) 212.58KB 42.83KB
plugin-detail (index.js) 239.03KB 59.77KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 114.58KB 27.68KB
plugin-gantt (index.js) 164.14KB 39.98KB
plugin-grid (index.js) 188.13KB 50.00KB
plugin-kanban (index.js) 48.62KB 13.42KB
plugin-list (index.js) 111.07KB 27.08KB
plugin-map (index.js) 18.16KB 5.81KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 41.16KB 10.96KB
plugin-timeline (index.js) 26.21KB 7.52KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 84.08KB 20.55KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 23.73KB 7.96KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.23KB 0.66KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 4.47KB 2.03KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 3.05KB 1.52KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.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 (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
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

Copy link
Copy Markdown
Collaborator Author

ACCEPT — but HELD IN DRAFT, deliberately not armed — step-7 复核 by PM session session_017Qqyix2QcnpUC9XeYVDzx3.

The fix itself is accepted in full: one derived value with three consumers and zero second copies (the rename-in-place is exactly the no-alias-pair shape the ruling wanted), red-first reproducing the card's symptom verbatim (bar with the page count, both testids absent), the honest pin-limit notes on single-mode and the collected-set clause, byte-identical .d.ts, and the heavyDomTests config deviation is measured-necessary (both alternatives fail mechanically — TS2307 + phantom-dep on one side, a stub grid that makes the pin worthless on the other).

Why it does not arm yet — the dev's own headline, and it is right: this PR makes a previously-unreachable DESTRUCTIVE path reachable. On the external-pagination path lastFindParamsRef is null, so the select-all-matching fan-out this banner now exposes collects up to 5000 records from the UNFILTERED object, and ObjectView hands that set to bulk delete — the bar would claim "All 26 matching selected" while the confirm dialog quotes a four-digit count. Filed as #4501 clause 1; report-only was the correct discipline (the fix needs a ruling: a host-params prop, not a tolerant grid-side fallback).

Sequencing ruling: #4501 clause 1 is being dispatched NOW with priority. This PR flips ready + arms only after #4501's guard is in origin/main — landing them in that order means the banner is never live while the fan-out is wrong. The census's clause 2 (stale escalation across filter changes) rides #4501's card; the export observation stays recorded.


Generated by Claude Code


Generated by Claude Code

claude added 2 commits August 13, 2026 03:24
…l compose

PR #4510 (#4501's abstain floor) landed on the same two `BulkActionBar` prop
sites this branch rewrites, so both hunks conflicted. Composed rather than
picked: the offer requires #4510's FLOOR (`canOfferSelectAllMatching` — no
escalation without a query to replay) and carries #4503's RESOLVED total
(`resolvedTotalMatching` — the host's `rowCount` on the external path), i.e.

  totalMatching={canOfferSelectAllMatching ? resolvedTotalMatching : undefined}

at both sites. The floor subsumes the `singleSelection ? undefined : …`
suppression the incoming side spelled there — `!singleSelection` is its first
conjunct — so no gating is lost; a host with a real total but no `findParams`
still gets no offer, which is the safety semantics winning the tie.

Follow-through, ruled in both PRs: the composition test gains the full-path
fan-out assertion #4510 made possible. The real ListView issues a real filtered
query, the real grid offers the escalation off the host's `rowCount`, and the
dispatched bulk action's fan-out is asserted to replay ListView's own params
verbatim — measured against what went on the wire, not a hand-written literal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qqyix2QcnpUC9XeYVDzx3
@yinlianghui
yinlianghui added this pull request to the merge queue Aug 13, 2026
Merged via the queue into main with commit 77d6f28 Aug 13, 2026
21 checks passed
@yinlianghui
yinlianghui deleted the claude/issue-4464-crosspage-totalmatching branch August 13, 2026 03:49

Copy link
Copy Markdown
Collaborator Author

Conflict with #4510 resolved — the two changes COMPOSE

#4510 (#4501's safety guard) landed on the same two BulkActionBar prop sites this branch rewrites, so both hunks conflicted. GitHub's update-branch returned 422 and auto-merge was silently ineffective. Merged by hand (merge commit appended, no force-push); origin/main advanced again mid-run, so the newer tip is merged in too.

The composed shape

ObjectGrid.tsx was the only conflicted file, and both hunks are the same line at the two render sites:

side contributes
#4503 (this branch) resolvedTotalMatching — the real match total from whichever side owns the fetch
#4510 (main) canOfferSelectAllMatching — the abstain floor: no offer without a query to replay

Resolved to, at both sites:

totalMatching={canOfferSelectAllMatching ? resolvedTotalMatching : undefined}

The floor decides whether the escalation is offered; the resolved total says how many it covers. Neither substitutes for the other, and the safety semantics win the tie: a host with a real rowCount but no findParams still gets no offer — a number to display is not a query to replay.

The incoming side spelled singleSelection ? undefined : ... at these sites; that gating is not lost, it is subsumed — !singleSelection is canOfferSelectAllMatching's first conjunct. onSelectAllMatching was not conflicted (this branch never touched it) and keeps #4510's floor verbatim.

Both halves reverse-verified as load-bearing at the merged sites

Each half removed in turn, restored byte-identical afterwards (sha256-verified, 6052c8db…):

  • Drop the resolved total (canOfferSelectAllMatching ? totalMatching : undefined) — composition test 4 failed / 3 passed: the three banner cases plus the new fan-out case, all Unable to find an element by: [data-testid="bulk-select-all-matching"]. The 3 negative controls stay green.
  • Drop the floor (back to singleSelection ? undefined : ... at both props) — plugin-grid's bulkFanoutHostParams goes red on exactly one case, does NOT offer the escalation when the host hands down no params: expected document not to contain element, found ....

Follow-through — the assertion #4510 made possible

Both PRs ruled it: with #4510 landed, ListView hands findParams down, so this file's composition test gains the full-path assertion. New case, ListView.crossPageSelectAll.test.tsx:

Real ListView issues a real filtered query (26 of 40 records match), the real grid offers the escalation off the host's rowCount, the escalation is accepted, and a dispatched bulk action's fan-out is asserted to replay ListView's own params verbatim — measured against what actually went on the wire, not a hand-written literal:

const { $top, $skip, ...replayed } = hostParams;   // what ListView asked
expect(fanout[0]).toEqual({ ...replayed, $top: 500, $skip: 0 });

…and therefore the executor receives the match set only (26 active, c-0 absent). This is the composition neither of #4510's seam tests could make: its producer test stubs the grid, its consumer test synthesizes HOST_PARAMS and reaches the affordance only by starting on the internal path and re-rendering — because on main the pure host path could not reach it at all, which was this PR's defect. The pre-existing scope note that deferred this to "a separate, filed finding (#4501)" now points at the new block instead.

The selection-state escalation was already pinned; the fan-out params assertion is the addition.

Re-verification on the merged tree

gate result
dependency-closure build first green (no gate read a stale .d.ts)
composition test 7 passed (7) — was 6, +1 follow-through
plugin-grid + plugin-list suites 97 files, 1119 passed
type-check both packages (src + tests) Done
eslint both packages 0 errors (398 pre-existing warnings)
check:control-bytes OK (4239 files)
changeset:check OK — fixed group, no major

.d.ts grading unchanged. plugin-grid's emitted .d.ts measured both ways against the current origin/main — built with this branch's ObjectGrid.tsx, then with main's — all 28 files byte-identical. The findParams published member is already in main (#4510's minor); this branch adds no type surface, so the existing patch changeset stands and no second changeset is needed.

Auto-merge deliberately not re-enabled — leaving that to the PM. PR stays ready, not draft.


Generated by Claude Code


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Main entry (gzip) 24.7 KB 350 KB
Entry file index-BYvkOimE.js
Status PASS

📦 Bundle Size Report

Package Size Gzipped
app-shell (index.js) 9.56KB 3.59KB
app-shell (runtime-config.js) 7.42KB 2.32KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 8.92KB 3.41KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 1.17KB 0.53KB
auth (AuthProvider.js) 25.13KB 5.40KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.13KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.64KB 2.21KB
auth (SocialSignInButtons.js) 9.60KB 3.89KB
auth (UserMenu.js) 3.40KB 1.22KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 38.46KB 10.17KB
auth (createAuthenticatedFetch.js) 6.34KB 2.43KB
auth (index.js) 2.35KB 1.07KB
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.02KB 0.88KB
auth (useIsWorkspaceAdmin.js) 1.61KB 0.85KB
collaboration (CommentThread.js) 26.07KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.65KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 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) 489.32KB 108.45KB
core (index.js) 3.37KB 1.34KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 153.79KB 41.35KB
fields (index.js) 230.14KB 57.12KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (currency.js) 1.22KB 0.64KB
i18n (i18n.js) 4.32KB 1.77KB
i18n (index.js) 3.35KB 1.38KB
i18n (pickLocalized.js) 3.69KB 1.73KB
i18n (provider.js) 23.12KB 7.62KB
i18n (useDisplayLocale.js) 2.84KB 1.45KB
i18n (useObjectLabel.js) 27.59KB 6.63KB
i18n (useSafeTranslation.js) 7.77KB 3.13KB
layout (index.js) 38.98KB 10.85KB
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.74KB
mobile (index.js) 1.50KB 0.62KB
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) 2.53KB 0.85KB
mobile (useResponsive.js) 0.71KB 0.42KB
mobile (useResponsiveConfig.js) 1.36KB 0.63KB
mobile (useSpecGesture.js) 4.32KB 1.64KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 8.75KB 3.06KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 3.67KB 1.12KB
permissions (evaluator.js) 4.41KB 1.44KB
permissions (index.js) 0.91KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.52KB
permissions (usePermissions.js) 1.55KB 0.71KB
plugin-ai (index.js) 15.75KB 3.80KB
plugin-calendar (index.js) 46.86KB 12.91KB
plugin-charts (index.js) 62.07KB 17.65KB
plugin-chatbot (index.js) 181.21KB 43.14KB
plugin-dashboard (index.js) 120.95KB 31.53KB
plugin-designer (index.js) 212.58KB 42.83KB
plugin-detail (index.js) 239.88KB 59.99KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 114.58KB 27.68KB
plugin-gantt (index.js) 164.14KB 39.98KB
plugin-grid (index.js) 188.40KB 50.10KB
plugin-kanban (index.js) 48.62KB 13.42KB
plugin-list (index.js) 111.13KB 27.12KB
plugin-map (index.js) 18.16KB 5.81KB
plugin-markdown (index.js) 13.72KB 4.69KB
plugin-report (index.js) 41.16KB 10.96KB
plugin-timeline (index.js) 26.21KB 7.52KB
plugin-tree (index.js) 8.50KB 2.88KB
plugin-view (index.js) 84.08KB 20.55KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.71KB 3.53KB
providers (index.js) 0.44KB 0.22KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.67KB 2.37KB
react (LazyPluginLoader.js) 3.77KB 1.33KB
react (SchemaRenderer.js) 23.73KB 7.96KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 1.23KB 0.66KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 4.09KB 1.74KB
sdui-parser (index.js) 4.47KB 2.03KB
sdui-parser (parse.js) 10.04KB 2.82KB
sdui-parser (types.js) 0.29KB 0.24KB
sdui-parser (validate.js) 4.69KB 1.48KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 0.99KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 0.20KB 0.18KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 0.20KB 0.18KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.87KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-retry.js) 4.32KB 2.02KB
types (index.js) 3.05KB 1.52KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 2.59KB 1.31KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.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 (spec-report.js) 5.05KB 1.93KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 0.20KB 0.18KB
types (ui-action.js) 3.40KB 1.71KB
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

Copy link
Copy Markdown
Collaborator Author

Post-merge record — PM session session_017Qqyix2QcnpUC9XeYVDzx3. The conflict-resolution continuation is accepted retroactively (the PR merged via the still-armed auto-merge 18s after the push; the resolver did not merge it):

#4464 closes with this merge. The #4501 family is fully landed: guard (#4510), banner (#4503), composition pin.


Generated by Claude Code


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants