Skip to content

fix(plugin-view): a named view's sort array rides the canonical grid slot, so the grid shows it and $orderby stops saying 'undefined undefined' (#5270) - #5294

Merged
os-support-ai merged 3 commits into
mainfrom
claude/issue-5270-named-view-sort-array
Aug 19, 2026
Merged

fix(plugin-view): a named view's sort array rides the canonical grid slot, so the grid shows it and $orderby stops saying 'undefined undefined' (#5270)#5294
os-support-ai merged 3 commits into
mainfrom
claude/issue-5270-named-view-sort-array

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes#5270

Re-derived on the post-#5102 ref (triage's first binding note)

Triage asked for the premise to be re-checked on the merged ref, because PR #5274 (#5102) touched these very forwarding clusters. Re-derived on origin/main @ 12841b617: the defect is still present, unchanged in mechanism, and #5274 moved where it lives without resolving it.

What #5274 changed: it split gridSchema into a preamble plus a return, hoisted the two view precedence segments into locals, and added the canonical keys. The two lines that matter here came out of it as

const viewSort = currentNamedViewConfig?.sort || activeView?.sort;
...
defaultSort: viewSort || schema.table?.defaultSort,
sort: viewSort ? undefined : schema.table?.sort,

so the view sort was still written into defaultSort, and the canonical sort slot was deliberately blanked whenever a view was active. That was the correct call for #5102's scope — it kept the table segment from outranking a named view — but it also meant the one slot with the right arity was guaranteed empty in exactly the case this card is about.

Measured, not inferred. The reverse verification below reverts this PR's source and keeps its tests; on the pre-fix source the fetch assertion reports

Expected: "status asc, name desc"
Received: "undefined undefined"

which is the issue's 'undefined undefined' claim reproduced verbatim on the post-#5102 tree.

The defect

NamedListView.sort is Array< { field, order } >. ObjectGridSchema.defaultSort is a single{ field, order }. An array was being placed in the single-object slot, with no compile-time witness (ObjectViewSchema.table collapses to a bare index signature). Both of ObjectGrid's readers then failed, differently:

  • Header.parseSchemaSort(schemaSort ?? (schema.defaultSort ? [schema.defaultSort] : undefined)) re-wraps an already-array defaultSort to [[{ field, order }]]. Each entry must be a string or an object with a string field; a nested array is neither, so the entry is skipped and the parse is [] — no arrow, and the first click on that column asks for asc on a list already desc.
  • Fetch.`${(schema.defaultSort as any).field} ${(schema.defaultSort as any).order}` reads two absent keys off an array. serializeOrderBy passes a non-empty string through untouched, so "undefined undefined" reached the wire.

The fix, and how it relates to #4869's normalized shape (triage's second binding note)

#4869 is the sort-sink convergence card: convertSortToQueryParams is the shared sink, it accepts exactly two authored spellings — string and SortConfig[] ({ field, order }) — and it says in so many words that a spelling the sink does not accept must be adjudicated at the producer, never tolerated at the consumer.

ObjectGridSchema.sort is declared string | SortConfig[] — the same pair the sink accepts. So the fix is to route the view segments into that slot:

- defaultSort: viewSort || schema.table?.defaultSort,
- sort: viewSort ? undefined : schema.table?.sort,
+ defaultSort: schema.table?.defaultSort,
+ sort: viewSort || schema.table?.sort,

No new dialect is introduced, nothing is normalized in-line, and no consumer gains a tolerant fallback. When #4869 lands $orderby: convertSortToQueryParams(sort), a named view's sort is already in a shape that sink accepts — this card removes one of the mismatches that card would otherwise have to fold in.

Precedence is unchanged.ObjectGrid resolves schemaSort ?? (schema.defaultSort ? [...] : undefined), so a view sort still outranks both table.sort and table.defaultSort, and table.sort still outranks table.defaultSort — the same order mergedSort (:1243) and the non-grid fetch (:611) already express. A view that supplies no sort forwards byte-for-byte what it forwarded before.

The filter half deliberately did not move. The issue flagged that filter/defaultFilters are not interchangeable downstream — ObjectGrid lowers the canonical slot through toFilterNode and raw-assigns the legacy one — so moving a named-view filter across would change that path's wire shape. The sort pair has no such asymmetry (both slots reach $orderby unlowered), which is why only sort moves here.

The #5102 pin: updated, not deleted

#5274's author wrote that the pin recording the current defaultSort behaviour should be updated, not deleted, by whoever took this card. Found and updated: ObjectView.canonicalTableKeys.test.tsx, block a named view still outranks the table segment, test keeps the named view sort in force over a table.sort. It asserted grid.sort === undefined + grid.defaultSort === [{ field: 'name', order: 'desc' }]; it now asserts the array in the canonical slot and the legacy slot empty. What that block exists to pin — the precedence — is asserted more strongly than before: a second case was added covering a view sort against a legacy table.defaultSort, the direction the original pin did not cover.

Tests

New: packages/plugin-view/src/__tests__/ObjectView.namedViewSortArity.test.tsx, 4 tests, driving the realObjectGrid rather than a probe that records the forwarded schema. That choice is load-bearing: the array was plainly visible in the forwarded object, just in the wrong slot, so a forwarded-shape assertion would have re-pinned the bug. Both halves the verification bar asks for are pinned end-to-end:

  • the header draws the declared descending arrow on the sorted column;
  • $orderby is 'name desc', asserted not.toBe('undefined undefined') and not.toContain('undefined');
  • a two-key sort survives ('status asc, name desc') — an arity the legacy slot structurally cannot hold;
  • control: a table.defaultSort with no view still works, unchanged.

Reverse verification

Ablation: git checkout origin/main -- packages/plugin-view/src/ObjectView.tsx, tests kept. Prediction recorded before running; predicted and observed match exactly, 5 red / 26 green.

testpredictedobserved
draws the declared sort indicator before anyone clicksREDRED
sends the declared sort as $orderby, not "undefined undefined"REDRED (Received: "undefined undefined")
carries every key of a multi-key sortREDRED
still honours a table.defaultSort when no view supplies one (control)GREENGREEN
keeps the named view sort in force over a table.sort (updated pin)REDRED
keeps the named view sort in force over a legacy table.defaultSort too (new pin)REDRED
the other 25 canonicalTableKeys assertions (#5102's own pins)GREENGREEN

No rebuild is in the ablation's resolution path, and none can hide a stale result.../ObjectView is a relative source import, and @object-ui/plugin-grid, @object-ui/components, @object-ui/core, @object-ui/react and @object-ui/types all resolve through the resolve.alias map in the root vitest.config.mts to each package's own src directory. There is no package-exports-to-dist hop on either leg, so a stale build can neither keep the ablated leg green nor keep the restored leg red. Restored afterwards; git status clean against the commit, and both files re-ran 31/31 green.

Gates run locally, all at 49ff25a71 (the final commit)

commandresult
pnpm exec vitest run packages/plugin-view packages/plugin-grid (from repo root)93 files, 858 passed
pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-view^...' buildpass
pnpm --filter @object-ui/plugin-view type-checkpass (script name echoed, not a zero-match run)
pnpm --filter @object-ui/plugin-view lint0 errors
node scripts/check-control-bytes.mjspass (4684 files)
node scripts/check-changeset-presence.mjspass
node scripts/check-phantom-dependencies.mjspass
pnpm changeset:checkpass, no major

Plus a manual control-byte sweep of the four changed files (grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]') — clean.

Changeset: patch on @object-ui/plugin-view (defect repair; never major, per AGENTS.md §版本号策略).

Scope

Four files: ObjectView.tsx, two of its test files, one changeset.

Generated by Claude Code


Generated by Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-C9y2HR2U.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.27KB113.31KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.80KB44.34KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)29.43KB7.15KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)127.97KB32.84KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)123.77KB30.07KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.27KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)19.96KB6.56KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.84KB11.77KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.33KB20.61KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)36.10KB12.26KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

MetricValueBudget
Main entry (gzip)25.3 KB350 KB
Entry fileindex-C9y2HR2U.js
StatusPASS

📦 Bundle Size Report

PackageSizeGzipped
app-shell (index.js)9.83KB3.70KB
app-shell (runtime-config.js)7.42KB2.32KB
app-shell (types.js)0.01KB0.04KB
app-shell (urlParams.js)8.92KB3.41KB
auth (AuthContext.js)0.31KB0.24KB
auth (AuthGuard.js)1.17KB0.53KB
auth (AuthProvider.js)29.33KB7.05KB
auth (AuthShell.js)3.49KB1.40KB
auth (ForgotPasswordForm.js)12.21KB3.45KB
auth (LoginForm.js)18.13KB5.39KB
auth (PreviewBanner.js)0.90KB0.50KB
auth (RegisterForm.js)6.64KB2.21KB
auth (SocialSignInButtons.js)9.60KB3.89KB
auth (UserMenu.js)3.40KB1.22KB
auth (auth-gate-events.js)1.29KB0.66KB
auth (authStyles.js)5.04KB1.72KB
auth (createAuthClient.js)40.21KB10.79KB
auth (createAuthenticatedFetch.js)6.34KB2.43KB
auth (index.js)2.71KB1.22KB
auth (invitation-status.js)1.22KB0.70KB
auth (org-roles.js)6.66KB2.78KB
auth (phone-identifier.js)1.11KB0.66KB
auth (types.js)0.59KB0.35KB
auth (useAuth.js)5.02KB0.88KB
auth (useIsWorkspaceAdmin.js)1.61KB0.85KB
collaboration (CommentThread.js)26.07KB7.56KB
collaboration (LiveCursors.js)3.17KB1.27KB
collaboration (PresenceAvatars.js)6.49KB2.64KB
collaboration (PresenceProvider.js)2.79KB1.13KB
collaboration (index.js)1.65KB0.73KB
collaboration (useCollaborationTranslation.js)6.05KB2.52KB
collaboration (useCommentSearch.js)1.98KB0.88KB
collaboration (useConflictResolution.js)7.75KB1.86KB
collaboration (useMentionNotifications.js)1.81KB0.68KB
collaboration (usePresence.js)6.33KB1.84KB
collaboration (useRealtimeSubscription.js)7.91KB2.01KB
components (index.js)506.27KB113.31KB
core (index.js)4.11KB1.62KB
create-plugin (index.js)10.08KB3.26KB
data-objectstack (index.js)159.80KB44.34KB
fields (index.js)237.07KB59.46KB
i18n (LocalizationContext.js)1.76KB0.96KB
i18n (currency.js)1.22KB0.64KB
i18n (i18n.js)4.28KB1.75KB
i18n (index.js)3.42KB1.39KB
i18n (pickLocalized.js)3.69KB1.73KB
i18n (provider.js)23.13KB7.63KB
i18n (useDisplayLocale.js)2.85KB1.45KB
i18n (useObjectLabel.js)29.43KB7.15KB
i18n (useSafeTranslation.js)7.77KB3.13KB
layout (index.js)39.16KB10.97KB
mobile (MobileProvider.js)0.92KB0.49KB
mobile (ResponsiveContainer.js)0.94KB0.38KB
mobile (breakpoints.js)1.51KB0.70KB
mobile (createOfflineDataSource.js)5.61KB1.74KB
mobile (index.js)1.50KB0.62KB
mobile (offlineQueue.js)3.91KB1.35KB
mobile (pwa.js)0.97KB0.49KB
mobile (serviceWorker.js)1.48KB0.62KB
mobile (serviceWorkerSource.js)3.41KB1.48KB
mobile (useBreakpoint.js)1.54KB0.65KB
mobile (useGesture.js)6.96KB1.98KB
mobile (useOfflineSync.js)1.99KB0.72KB
mobile (usePullToRefresh.js)2.53KB0.85KB
mobile (useResponsive.js)0.71KB0.42KB
mobile (useResponsiveConfig.js)1.36KB0.63KB
mobile (useSpecGesture.js)4.32KB1.64KB
mobile (useTouchTarget.js)1.01KB0.54KB
permissions (MePermissionsProvider.js)9.35KB3.31KB
permissions (PermissionContext.js)0.31KB0.25KB
permissions (PermissionGuard.js)0.89KB0.45KB
permissions (PermissionProvider.js)4.42KB1.42KB
permissions (evaluator.js)5.12KB1.74KB
permissions (index.js)0.91KB0.41KB
permissions (store.js)0.91KB0.42KB
permissions (useFieldPermissions.js)1.28KB0.52KB
permissions (usePermissions.js)1.81KB0.83KB
plugin-ai (index.js)15.75KB3.80KB
plugin-calendar (index.js)46.62KB12.83KB
plugin-charts (index.js)64.75KB18.37KB
plugin-chatbot (index.js)181.21KB43.14KB
plugin-dashboard (index.js)127.97KB32.84KB
plugin-designer (index.js)212.39KB42.83KB
plugin-detail (index.js)241.46KB60.56KB
plugin-editor (index.js)2.46KB1.10KB
plugin-form (index.js)123.77KB30.07KB
plugin-gantt (index.js)164.10KB39.87KB
plugin-grid (index.js)198.22KB53.27KB
plugin-kanban (index.js)52.93KB14.60KB
plugin-list (index.js)111.66KB27.13KB
plugin-map (index.js)19.96KB6.56KB
plugin-markdown (index.js)13.72KB4.69KB
plugin-report (index.js)42.84KB11.77KB
plugin-timeline (index.js)26.68KB7.66KB
plugin-tree (index.js)8.50KB2.88KB
plugin-view (index.js)84.33KB20.61KB
providers (DataSourceProvider.js)0.75KB0.39KB
providers (MetadataProvider.js)1.37KB0.59KB
providers (ThemeProvider.js)1.90KB0.85KB
providers (UploadProvider.js)11.66KB3.50KB
providers (index.js)0.44KB0.22KB
providers (types.js)0.01KB0.04KB
react-runtime (index.js)5.62KB2.34KB
react (LazyPluginLoader.js)3.77KB1.33KB
react (SchemaRenderer.js)36.10KB12.26KB
react (data-invalidation.js)5.05KB2.08KB
react (index.js)1.33KB0.69KB
react (schema-input.js)1.45KB0.83KB
react (spec-input.js)0.20KB0.18KB
sdui-parser (codegen.js)5.41KB2.34KB
sdui-parser (index.js)4.77KB2.16KB
sdui-parser (input-type.js)2.84KB1.40KB
sdui-parser (parse.js)10.76KB3.17KB
sdui-parser (provenance.js)3.66KB1.82KB
sdui-parser (types.js)0.29KB0.24KB
sdui-parser (validate.js)6.92KB2.40KB
types (ai.js)0.20KB0.17KB
types (api-types.js)0.20KB0.18KB
types (app.js)2.87KB0.99KB
types (base.js)0.20KB0.18KB
types (blocks.js)0.20KB0.18KB
types (complex.js)0.20KB0.18KB
types (crud.js)0.20KB0.18KB
types (dashboard-filter-alias.js)6.23KB2.74KB
types (data-display.js)0.20KB0.18KB
types (data-protocol.js)0.20KB0.19KB
types (data.js)0.20KB0.18KB
types (designer.js)1.87KB0.85KB
types (disclosure.js)0.20KB0.18KB
types (error-code.js)1.54KB0.88KB
types (feedback.js)0.20KB0.18KB
types (field-types.js)0.20KB0.18KB
types (form.js)0.20KB0.18KB
types (http-retry.js)4.32KB2.02KB
types (index.js)3.08KB1.53KB
types (layout.js)0.20KB0.18KB
types (managed-by.js)0.19KB0.18KB
types (mobile.js)2.59KB1.31KB
types (navigation.js)0.20KB0.18KB
types (objectql.js)0.20KB0.18KB
types (overlay.js)0.20KB0.18KB
types (permissions.js)0.20KB0.18KB
types (plugin-scope.js)0.20KB0.18KB
types (record-components.js)0.20KB0.19KB
types (record-semantics.js)1.28KB0.67KB
types (registry.js)0.20KB0.18KB
types (reports.js)0.20KB0.18KB
types (spec-report.js)5.05KB1.93KB
types (system-fields.js)3.33KB1.54KB
types (theme.js)0.20KB0.18KB
types (ui-action.js)3.40KB1.71KB
types (views.js)0.20KB0.18KB
types (widget.js)0.20KB0.18KB

Size Limits

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

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

Labels

Projects

None yet

1 participant

@os-support-ai