Skip to content

chore(fields): narrow the datetime style cast, and make the #7443 changeset accurate for consumers - #7792

Merged
os-sam merged 1 commit into
mainfrom
claude/issue-7747-datetime-format-nits
Sep 5, 2026
Merged

chore(fields): narrow the datetime style cast, and make the #7443 changeset accurate for consumers#7792
os-sam merged 1 commit into
mainfrom
claude/issue-7747-datetime-format-nits

Conversation

@os-sam

@os-sam os-sam commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

Fixes #7747

Two non-blocking follow-ups recorded from the contract review of #7621. Both are in this one PR because the card carries both; neither ships anything.

Clause-②: no holds and was re-measured, not assumed — see Runtime behaviour is unchanged below.


Item 1 — the #7443 changeset's byte-identity sentence, corrected for consumers

The claim was true measured in this repository (no in-repo datetime field authors a format) but a changeset is a release-note input read by consumers who are not this repository, and #7621 made DateTimeCellRenderer start reading field.format.

What an unrecognised format actually does — MEASURED, not assumed

The card flagged that the value domain is unanswered, so it was measured rather than guessed. A temporary harness rendered DateTimeCellRenderer at one instant (2024-07-04T07:00:00.000Z, en-US) across nine authored values. The harness was deleted after the reading and is not part of this PR.

authored format rendered cell text
absent (no key) 7/4/2024 7:00 am (compact)
'' 7/4/2024 7:00 am (compact)
null 7/4/2024 7:00 am (compact)
'compact' 7/4/2024 7:00 am (compact)
'not-a-real-style' Jul 4, 2024, 07:00 AM (verbose)
'short' Jul 4, 2024, 07:00 AM (verbose)
'relative' Jul 4, 2024, 07:00 AM (verbose)
'YYYY-MM-DD' Jul 4, 2024, 07:00 AM (verbose)
42 (a number) Jul 4, 2024, 07:00 AM (verbose)

An unrecognised value is neither rejected nor passed through, and it does NOT fall back to 'compact' — it silently selects the verbose formatDateTime default. formatDateTime branches on options.style === 'compact' and everything else falls to the default face; the cell's || 'compact' only catches the falsy values, which is why '' and null stay compact.

That matters because before #7621 the cell ignored field entirely and always painted the compact face (git show 81a2eb1fb^:packages/fields/src/index.tsx — it destructured value only). So a consumer that authored any non-empty, non-'compact' format on a datetime field sees its cells change. That is the one visible consequence the changeset did not spell out.

The vocabulary gap — and one correction to the card

The card says @objectstack/spec "declares no format on datetime fields". Measured, that is not quite right, and the accurate finding is a stronger version of the same point. The spec's field schema does carry format, on a single flat (non-discriminated) field schema shared by every field type:

format type: optional | desc: "Format string (e.g. email, phone)"
inner type: string | entries: null      (no enum, no per-type domain)

  "compact"          ACCEPTED
  "not-a-real-style" ACCEPTED
  ""                 ACCEPTED
  "short"            ACCEPTED

So format exists but is an unconstrained free-form string whose documented examples are for other field types entirely. There is no declared datetime vocabulary in either @object-ui/types (format?: string) or the spec to check a value against. The corrected sentence names that gap instead of papering over it, as the card asked.

The diff — prose only, name set unchanged

diff --git a/.changeset/7443-datetime-compact-style.md b/.changeset/7443-datetime-compact-style.md
index c7190f6f2..70900b838 100644
--- a/.changeset/7443-datetime-compact-style.md
+++ b/.changeset/7443-datetime-compact-style.md
@@ -13,8 +13,22 @@ The cell now reads `field.format` (it destructured `value` only, so a
 `datetime` field could not reach the style vocabulary a `date` field has) and
 renders through the shared function, and `data-table`'s `formatCellValue`
 calls `formatDateTime` instead of a third, independently authored option bag.
-Every existing cell renders byte-identically; `'compact'` is today's face
-named and rehoused, not a new one.
+Every existing cell without an authored `format`, and every cell authoring
+`'compact'`, renders byte-identically; `'compact'` is today's face named and
+rehoused, not a new one. A `datetime` field that authors any OTHER non-empty
+`format` does change: the cell previously ignored `field` altogether and always
+painted the compact face, and now anything other than `'compact'` selects the
+verbose `formatDateTime` default — measured as `Jul 4, 2024, 07:00 AM` in
+`en-US` for the instant whose compact face is `7/4/2024 7:00 am`. An
+unrecognised value is neither rejected nor passed through; it silently lands on
+that verbose face. No `datetime` field in this repository authors a `format`, so
+no cell here moves — a consumer that authored one is the case this sentence is
+for. Note that `format` has no declared value vocabulary to check a value
+against: `@object-ui/types` types it `format?: string`, and `@objectstack/spec`
+carries one free-form `format?: string` on its shared field schema, described
+"Format string (e.g. email, phone)" and accepting any string. `'compact'` is
+therefore the only value with a defined `datetime` meaning, and every other
+value means "the verbose face" by fallthrough rather than by design.
 
 Additive, no signature change: `formatDateTime(value, options?)` is unchanged
 and `formatDateTime(v, { locale })` keeps meaning what it meant.

The gate that governs this file prints the checkability itself. node scripts/check-changeset-overwrite.mjs, exit 0:

Compared the working tree with 6771c805a (merge-base with origin/main): 1 changeset(s) added, 1 modified, 0 deleted.

      M  .changeset/7443-datetime-compact-style.md
             declared at base: @object-ui/core: minor, @object-ui/fields: minor, @object-ui/components: patch
             declares now:     @object-ui/core: minor, @object-ui/fields: minor, @object-ui/components: patch

declared at base and declares now are identical: all three package names kept, all three bump levels kept, frontmatter byte-for-byte unchanged. Mechanically:

$ diff  (frontmatter at origin/main, sorted)  (frontmatter now, sorted)
IDENTICAL: frontmatter byte-for-byte unchanged, no package name added or dropped

This is the "factual correction to prose" case the gate's own history measurement counts among its 19-for-19 legitimate modifications, and it keeps the 18-for-19 name-preservation shape.


Item 2 — (field as any)?.format narrowed to the subtype that declares it

diff --git a/packages/fields/src/index.tsx b/packages/fields/src/index.tsx
index bb0974998..c16ba226e 100644
--- a/packages/fields/src/index.tsx
+++ b/packages/fields/src/index.tsx
@@ -7,7 +7,7 @@
  */
 
 import React from 'react';
-import type { FieldMetadata, SelectOptionMetadata } from '@object-ui/types';
+import type { DateTimeFieldMetadata, FieldMetadata, SelectOptionMetadata } from '@object-ui/types';
 import { ComponentRegistry, percentDisplayValue, getRecordDisplayName, humanizeLabel, isMissingForRequired, formatDate, formatDateTime, formatDateTimeCompactParts, formatRelativeDate, type ComponentMeta, type DateDisplayOptions } from '@object-ui/core';
 // The platform's own value-shape contract, asked rather than restated
 // (objectui#6744). See `locationStoredValueSchemaFor` below for why this is a
@@ -882,7 +882,11 @@ export function DateTimeCellRenderer({ value, field }: CellRendererProps): React
   // (objectui#7443). `||`, not `??`, matches the `date` cell and keeps an
   // authored empty string on the compact face rather than dropping it into
   // the verbose default.
-  const style = (field as any)?.format || 'compact';
+  // `FieldMetadata` is a 37-member union and `BaseFieldMetadata` carries no
+  // `format`, so the bare property read is `TS2339` — SOME cast is load-bearing.
+  // `DateTimeFieldMetadata` is the narrowest one that carries it (objectui#7747);
+  // `as any` would also silence a typo in the property name, this does not.
+  const style = (field as DateTimeFieldMetadata | undefined)?.format || 'compact';
 
   // The compact face is painted in two halves — the time is muted and offset
   // — so this branch asks the shared module for the halves rather than the

Some cast is load-bearing: FieldMetadata is a 37-member union, BaseFieldMetadata carries no format, so a bare field.format is TS2339. But as any was wider than the job — DateTimeFieldMetadata is exported from @object-ui/types (packages/types/src/index.ts:465, format?: string at field-types.ts:301) and this file already imports types from there, so the narrow cast cost one word in an existing import.

no-explicit-any is warn-level here, so Lint is green either way; the count still moves and is checkable:

BEFORE  no-explicit-any warnings in packages/fields/src/index.tsx: 46   (one of them line 885)
AFTER   no-explicit-any warnings in packages/fields/src/index.tsx: 45   (none on lines 880-895)

Exactly one warning removed, and it is the line changed here. No other any in the file was touched and the rule was not raised to error — both are other cards.

The narrowing is load-bearing — lit control, not an assertion

as any could never have gone red, so it measures nothing as a control. Instead the cast was temporarily swapped to BooleanFieldMetadata — exported from the same barrel, extends BaseFieldMetadata, and adds only type, so it genuinely does not carry format. The import was swapped with it, otherwise tsc would have answered TS2304 (unknown name) and the reading would have measured the import rather than the property check.

HEAD_BLOB      = c16ba226ee14a60e1cefcc37e8a0ba4e90cc91a7
PRE_MUTATION   = c16ba226ee14a60e1cefcc37e8a0ba4e90cc91a7
MUTATION: injected-text count=1  original-text count=0        ** mutation proven on disk
POST_MUTATION  = a437836f3b699c2e5c57ed13af6a7834be07f461
mutated line   : 889:  const style = (field as BooleanFieldMetadata | undefined)?.format || 'compact';

=== TSC_EXIT=2 ===
src/index.tsx(889,62): error TS2339: Property 'format' does not exist on type 'BooleanFieldMetadata'.

RED, and it names the exact line and column of the cast. That is the property as any was suppressing: tsc really does check .format against the cast type now.

Restoration, proven rather than claimed (restore leg is git checkout HEAD -- ABSOLUTE_PATH, never the bare form, which restores from the index and would hand the mutation back; the script carries trap restore EXIT INT TERM for the crash path, but the proof below is the hash, not the trap firing):

POST_RESTORE   = c16ba226ee14a60e1cefcc37e8a0ba4e90cc91a7
HEAD_BLOB      = c16ba226ee14a60e1cefcc37e8a0ba4e90cc91a7
HASH: EQUAL — byte-identical to the HEAD blob
git diff HEAD: EMPTY (clean tree)
restored text  : 1 occurrence(s) of the real cast

Runtime behaviour is unchanged (the Clause-② void condition, checked)

The cast is erased at emit; the expression (field)?.format || 'compact' is byte-for-byte the same JavaScript. The measured table in item 1 was produced after the narrowing and reproduces the pre-existing behaviour on every row, 'compact', empty, null and unrecognised alike. Nothing in this PR makes DateTimeCellRenderer read a different value at runtime, so the declared Clause-②: no stands.


Changeset

.changeset/7747-datetime-format-cast-narrowing.md is a new file with empty frontmatter — item 2 touches a released package's src/, so AGENTS.md:161 requires a declaration, and a type-level-only change releases nothing. The item 1 correction is a different file and does not satisfy that requirement.

$ node scripts/check-changeset-presence.mjs     # exit 0
1 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s):
.changeset/7747-datetime-format-cast-narrowing.md.
Every one of them has an EMPTY frontmatter — declared as releasing nothing, which
is the explicit exemption and a complete answer to this gate.

Verification

All readings below were taken at the final commit a2ee8a2, on a clean tree (git status --porcelain empty). Heavy runs went through the container's shared verify lock; wall-clock figures are shared-box seconds, so only the pass/fail counts are quoted.

command result
pnpm --filter @object-ui/fields type-check (tsc --noEmit && tsc -p tsconfig.test.json) exit 0 — both legs, so the test tree is type-checked too
pnpm exec vitest run packages/fields/ (repo root, the AGENTS.md canonical form) 133 test files passed (133); 2178 tests passed (2178)
node scripts/check-changeset-presence.mjs exit 0
node scripts/check-changeset-no-major.mjs exit 0 — no major declared
node scripts/check-changeset-fixed.mjs exit 0
node scripts/check-changeset-overwrite.mjs exit 0 (report-only; name set unchanged, quoted above)
node scripts/check-control-bytes.mjs exit 0 — 6345 tracked text files scanned
node scripts/check-phantom-dependencies.mjs exit 0 — @object-ui/types is already a declared dependency of @object-ui/fields
node scripts/check-package-self-import.mjs exit 0
node scripts/check-unreferenced-sources.mjs exit 0
pnpm exec eslint packages/fields/src/index.tsx 0 errors, 136 warnings (was 137; the one removed is the no-explicit-any on the changed line)

Every gate exit code above was captured with the command redirected to a file before the status was read, never after a pipe.

One out-of-scope finding, filed not fixed

Filed as #7791. pnpm --filter @object-ui/fields test reports 2 failures in CapabilityMultiSelectField.specParity-6285.test.tsx on this tree — that test sets VOCABULARY_ROOT = '.' (the process cwd), and the package-level script leaves cwd at packages/fields while --root only moves vitest's root. From the repo root the same file is 7 passed (7). It is unrelated to this diff, which touches neither that test nor its subject: the isolated control (cd packages/fields plus the package script's own vitest form, same tree) reproduces it with cwd as the only variable, and the same file from the repo root is green. A pristine origin/main checkout was not run — the causal argument here is the cwd control, not a baseline comparison. Out of scope for this card, so it was filed rather than fixed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3


Generated by Claude Code

…ngeset accurate for consumers

Two follow-ups recorded from the contract review of objectui#7621, neither of
which gated its PASS (objectui#7747).

The `DateTimeCellRenderer` style cast goes from `as any` to
`(field as DateTimeFieldMetadata | undefined)`. Some cast is load-bearing —
`FieldMetadata` is a 37-member union and `BaseFieldMetadata` carries no
`format`, so the bare read is `TS2339` — but `as any` was wider than the job.
`DateTimeFieldMetadata` is exported from `@object-ui/types` and this file
already imports from there, so the narrow cast cost nothing. It is type-level
only: the emitted expression is unchanged, and the file's
`@typescript-eslint/no-explicit-any` warning count drops 46 to 45, the one
removed being the line changed here.

The `7443-datetime-compact-style.md` changeset claimed every existing cell
renders byte-identically. That is true measured in this repository — no
in-repo `datetime` field authors a `format` — but a changeset is a release-note
input read by consumers who are not this repository, and objectui#7621 made
`DateTimeCellRenderer` start reading `field.format`. The sentence now names its
own precondition and the measured consequence: an authored `format` other than
`'compact'` is neither rejected nor passed through, it silently selects the
verbose `formatDateTime` default. The note also states the gap rather than
papering over it — `format` has no declared value vocabulary on a datetime
field in either `@object-ui/types` or `@objectstack/spec`. Only the prose
changed; the frontmatter and its three package names are byte-identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3187.4 KB 3191.4 KB
Main entry chunk (gzip) 143.2 KB 350 KB
Entry file index-CnaboxA9.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 (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 5.13KB 2.35KB
collaboration (CommentThread.js) 26.08KB 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.68KB 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) 510.60KB 116.20KB
core (index.js) 6.96KB 2.79KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 182.08KB 50.62KB
fields (index.js) 242.44KB 61.25KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.98KB 10.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) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
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) 15.75KB 3.80KB
plugin-calendar (index.js) 47.87KB 13.31KB
plugin-charts (index.js) 70.92KB 19.75KB
plugin-chatbot (index.js) 196.19KB 46.37KB
plugin-dashboard (index.js) 132.88KB 34.69KB
plugin-designer (index.js) 212.86KB 43.19KB
plugin-detail (index.js) 250.55KB 64.06KB
plugin-editor (index.js) 2.46KB 1.10KB
plugin-form (index.js) 132.87KB 32.66KB
plugin-gantt (index.js) 167.26KB 41.00KB
plugin-grid (index.js) 209.29KB 56.78KB
plugin-kanban (index.js) 52.71KB 14.55KB
plugin-list (index.js) 113.28KB 27.59KB
plugin-map (index.js) 20.44KB 6.78KB
plugin-markdown (index.js) 13.93KB 4.81KB
plugin-report (index.js) 43.59KB 11.97KB
plugin-timeline (index.js) 30.84KB 8.85KB
plugin-tree (index.js) 9.20KB 3.19KB
plugin-view (index.js) 85.24KB 20.94KB
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.66KB 3.50KB
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) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 10.35KB 3.60KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.74KB 1.41KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
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) 0.20KB 0.18KB
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) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
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 (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
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

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

Projects

None yet

1 participant