Skip to content

[internals] Move the exported internals to a new folder and remove private Calendar component#4505

Merged
flaviendelangle merged 30 commits intomui:masterfrom
flaviendelangle:internals-folder
Apr 13, 2026
Merged

[internals] Move the exported internals to a new folder and remove private Calendar component#4505
flaviendelangle merged 30 commits intomui:masterfrom
flaviendelangle:internals-folder

Conversation

@flaviendelangle
Copy link
Copy Markdown
Member

@flaviendelangle flaviendelangle commented Apr 2, 2026

Applied on external codebases ✔️

@flaviendelangle flaviendelangle self-assigned this Apr 2, 2026
@flaviendelangle flaviendelangle added type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature. scope: all components Widespread work has an impact on almost all components. labels Apr 2, 2026
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 2, 2026

commit: 2477f34

@mui-bot
Copy link
Copy Markdown

mui-bot commented Apr 2, 2026

Bundle size report

Bundle Parsed size Gzip size
@base-ui/react 🔺+31B(+0.01%) ▼-66B(-0.05%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@flaviendelangle flaviendelangle force-pushed the internals-folder branch 2 times, most recently from 1ded326 to c4f4dbf Compare April 2, 2026 13:16
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 2, 2026

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit c4f4dbf
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/69ce6c4a765f3300086846dc
😎 Deploy Preview https://deploy-preview-4505--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 2, 2026

Deploy Preview for base-ui ready!

Name Link
🔨 Latest commit 2477f34
🔍 Latest deploy log https://app.netlify.com/projects/base-ui/deploys/69dcd0c85a448e0008f98eb2
😎 Deploy Preview https://deploy-preview-4505--base-ui.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@flaviendelangle flaviendelangle marked this pull request as ready for review April 3, 2026 05:09
Copy link
Copy Markdown
Contributor

@atomiks atomiks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex Review (GPT-5.4)

This is primarily a refactor, but it also expands the published subpath surface under ./internals/* and ./localization-provider. The runtime move looks mechanically safe; the remaining risk is in public-contract and guardrail consistency around those new entrypoints.

1. Bugs / Issues

1. 🟡 Temporal type augmentation still points at the old module (non-blocking)

In packages/react/src/internals/temporal/temporal.ts, the example for registering TemporalSupportedObjectLookup still tells consumers to augment @base-ui/react/types, but this PR moves the live augmentation target to @base-ui/react/internals/temporal.

From packages/react/src/internals/temporal/temporal.ts and packages/react/src/temporal-adapter-date-fns/TemporalAdapterDateFns.ts:

// packages/react/src/internals/temporal/temporal.ts
declare module '@base-ui/react/types' {
  interface TemporalSupportedObjectLookup {
    'date-fns': Date;
  }
}

// packages/react/src/temporal-adapter-date-fns/TemporalAdapterDateFns.ts
declare module '@base-ui/react/internals/temporal' {
  interface TemporalSupportedObjectLookup {
    'date-fns': Date;
  }
}

This matters because ./internals/temporal is now a published export. Anyone following the example will augment the wrong module and silently fail to register their temporal object type.

Fix: Update the example in packages/react/src/internals/temporal/temporal.ts to match @base-ui/react/internals/temporal.

2. ℹ️ The deep-import lint exemption is broader than the published export map (informational)

In eslint.config.mjs, the new regex exempts every @base-ui/react/internals/... import from the deep-import restriction, while packages/react/package.json only exports a fixed set of one-level ./internals/* entrypoints.

From eslint.config.mjs:

{
  regex: '@base-ui/react/(?!internals/).+/.+',
  message: OneLevelImportMessage,
}

This matters because imports like @base-ui/react/internals/temporal/getDateManager would now lint clean in-repo even though the published package would not resolve them. That weakens the guardrail this refactor is supposed to establish.

Recommendation: Narrow the exemption to exactly one level under internals, or add an explicit restriction for @base-ui/react/internals/*/*.

2. Behavior Preservation Assessment

I did not see evidence of meaningful runtime churn beyond the export-surface move. Most of the diff is mechanical import rewriting, and the targeted validation I ran passed: pnpm typescript, pnpm test:jsdom index --no-watch, and pnpm --filter @base-ui/react build.

3. Ownership / Architecture Assessment

This is no longer just an internal folder move: packages/react/package.json now publishes ownership/context primitives such as ./internals/field-root-context, ./internals/field-register-control, and ./internals/form-context. That may be intentional, but it turns future cleanup of those boundaries into semver-governed work, so I would call that out explicitly rather than framing the PR as only a relocation.

4. Test Coverage Assessment

The main coverage gap is export-surface validation. packages/react/src/index.test.ts now explicitly skips ./localization-provider and every ./internals/* subpath:

![
  '.',
  './utils',
  './temporal-adapter-luxon',
  './temporal-adapter-date-fns',
  './localization-provider',
  './types',
].includes(key) &&
!key.startsWith('./unstable-') &&
!key.startsWith('./internals/')

That means the new published entrypoints are not being smoke-tested through @base-ui/react/... specifiers for packaged resolution or declaration shape. I would add a small import smoke test for the exported ./internals/* and ./localization-provider subpaths before merging.

Merge Confidence Score

Overall merge confidence is 3/5. The refactor itself looks low-risk and the targeted typecheck, test, and build validation passed, but the new public subpath surface still has one stale consumer-facing type example, one guardrail mismatch, and no direct smoke coverage for the newly published exports. I would fix finding 1 and tighten either the lint rule or the export-surface test coverage before merging.

Copy link
Copy Markdown
Member Author

@flaviendelangle flaviendelangle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm migrating all the other repos to use this PR in order to make sure everything is correctly migrated 👍

import { animated as springAnimated, useSpring, useSpringRef } from '@react-spring/web';
import { SettingsMetadata, useExperimentSettings } from '../_components/SettingsPanel';
import { useTransitionStatus } from '../../../../../../packages/react/src/utils/useTransitionStatus';
import { useTransitionStatus } from '../../../../../../packages/react/src/internals/useTransitionStatus';
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use the new internal import now.
But if it's used in an experiment, maybe we could consider moving it to @base-ui/utils

flaviendelangle added a commit to flaviendelangle/mui-x that referenced this pull request Apr 3, 2026
…rnals imports

Update @base-ui/react to a build from PR mui/base-ui#4505
which exposes internal utilities under @base-ui/react/internals/*.

Replace ~46 files' imports from base-ui-copy/ with proper imports:
- useRenderElement → @base-ui/react/internals/useRenderElement
- BaseUIComponentProps, NonNativeButtonProps → @base-ui/react/internals/types
- useButton → @base-ui/react/internals/use-button
- createChangeEventDetails → @base-ui/react/internals/createBaseUIEventDetails
- TemporalAdapter, TemporalSupportedObject, TemporalTimezone → @base-ui/react/internals/temporal

Delete 11 now-redundant copy files (utils/ and types/ directories).

Remaining in base-ui-copy/ (not yet available in internals):
- composite/ (CompositeList, CompositeRootContext, useCompositeListItem)
- temporal-adapter-date-fns/ (UnstableTemporalAdapterDateFns)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Apr 9, 2026
@code-infra-dashboard
Copy link
Copy Markdown

code-infra-dashboard Bot commented Apr 9, 2026

Bundle size

Bundle Parsed size Gzip size
@base-ui/react 🔺+74B(+0.02%) ▼-60B(-0.04%)

Details of bundle changes

Deploy preview

https://deploy-preview-4505--base-ui.netlify.app/

Performance

Total duration: 1,101.13 ms ▼-103.63 ms(-8.6%) | Renders: 53 (+0) | Paint: 1,661.51 ms ▼-183.13 ms(-9.9%)

Test Duration Renders
Menu open (500 items) 61.21 ms 🔺+1.70 ms(+2.9%) 12 (+0)
Tooltip mount (300 contained roots) 56.69 ms 🔺+0.09 ms(+0.2%) 2 (+0)
Dialog mount (300 instances) 69.85 ms ▼-22.14 ms(-24.1%) 2 (+0)
Checkbox mount (500 instances) 72.98 ms ▼-19.24 ms(-20.9%) 1 (+0)
Popover mount (300 instances) 87.95 ms ▼-13.29 ms(-13.1%) 2 (+0)

...and 7 more. View full report

Details of benchmark changes


Check out the code infra dashboard for more information about this PR.

@michaldudak
Copy link
Copy Markdown
Member

michaldudak commented Apr 9, 2026

1. Missing React import in constants.ts

[code-reviewer] packages/react/src/internals/constants.ts:34 — The constant ownerVisuallyHidden is typed as React.CSSProperties but the file has no import * as React from 'react'. This will fail pnpm typescript.

Fix: Add import type * as React from 'react'; at the top of the file.

2. luxon missing from peerDependencies

[code-reviewer] packages/react/src/internals/temporal-adapter-luxon/TemporalAdapterLuxon.ts:6 — The export ./internals/temporal-adapter-luxon runtime-imports from luxon, but luxon is only in devDependencies.
Consumers would get a runtime error. Compare: date-fns is correctly in both devDependencies and peerDependencies. The file also has // @ts-nocheck and a TODO suggesting it's not production-ready.

3. Roundabout self-referencing imports in labelable-provider/

[type-design] Three files inside packages/react/src/internals/labelable-provider/ import from ../../internals/useBaseUiId instead of ../useBaseUiId. Both resolve to the same file, but the longer path navigates up
to src/ and back down, which is misleading:

  • LabelableProvider.tsx:7
  • useAriaLabelledBy.ts:4
  • useLabelableId.ts:8

Suggestions (2 found)

4. Dead re-export shim: utils/serializeValue.ts

[code-reviewer] packages/react/src/utils/serializeValue.ts — Contains only export { serializeValue } from '../internals/serializeValue'. Nothing in the codebase imports from this path anymore. Can be removed.

@flaviendelangle
Copy link
Copy Markdown
Member Author

  1. luxon missing from peerDependencies

That one is expected
Fixing the others

@github-actions github-actions Bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Apr 9, 2026
@github-actions github-actions Bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Apr 10, 2026
Copy link
Copy Markdown
Contributor

atomiks commented Apr 10, 2026

Codex Review (GPT-5.4)

This is a refactor-dominant PR with public internal export, docs, and test-surface implications. I reviewed the full branch against freshly fetched upstream/master; the main blockers are mergeability and one newly exported type surface.

1. Bugs / Issues

1. 🔴 Branch currently conflicts with latest master (blocking)

A merge simulation against the freshly fetched base reports modify/delete conflicts in two docs demo files that this PR deletes while master has since modified them:

CONFLICT (modify/delete): docs/src/app/(docs)/react/components/calendar/demos/hero/index.ts deleted in refs/remotes/upstream/pr/4505 and modified in upstream/master.
CONFLICT (modify/delete): docs/src/app/(docs)/react/utils/localization-provider/demos/hero/index.ts deleted in refs/remotes/upstream/pr/4505 and modified in upstream/master.

This means the branch cannot be merged cleanly until it is rebased or updated against the current base branch.

Fix: Rebase/update the PR on latest master and resolve the two modify/delete conflicts by preserving the intended Calendar/LocalizationProvider removal while incorporating any relevant docs infrastructure changes from master.

2. 🔴 temporal-adapter-luxon emits declarations that import temporal types from the wrong module (blocking)

packages/react/package.json now exposes the Luxon adapter as a shipped internal subpath:

"./internals/temporal-adapter-luxon": "./src/internals/temporal-adapter-luxon/index.ts"

But the moved adapter still imports temporal types from ../types:

import {
  TemporalAdapterFormats,
  DateBuilderReturnType,
  TemporalTimezone,
  TemporalAdapter,
} from '../types';

After the move, ../types resolves to packages/react/src/internals/types.ts, which does not export those temporal types. pnpm typescript passes because the file is @ts-nocheck, but the emitted declaration keeps the bad import, so consumers of @base-ui/react/internals/temporal-adapter-luxon get a broken type surface. The date-fns sibling correctly imports these from ../temporal.

Fix: Change the Luxon adapter import to ../temporal, preferably as a type import where possible.

3. 🟡 Filter API docs lost method descriptions (non-blocking)

The shared filter extraction dropped the property JSDoc that used to document how contains, startsWith, and endsWith differ. The generated public API docs now show the methods without descriptions in docs/src/app/(docs)/react/components/combobox/types.md and docs/src/app/(docs)/react/components/autocomplete/types.md:

type ComboboxFilter = {
  contains: <Item>(item: Item, query: string, itemToString?: (item: Item) => string) => boolean;
  startsWith: <Item>(item: Item, query: string, itemToString?: (item: Item) => string) => boolean;
  endsWith: <Item>(item: Item, query: string, itemToString?: (item: Item) => string) => boolean;
};

Fix: Move the previous method comments onto packages/react/src/internals/filter.ts’s Filter interface and regenerate the API docs.

4. 🟡 New exported internals only have resolution coverage (non-blocking)

RequestQueue and TimeoutManager are new exported internal subpaths, but the added coverage only verifies that internals resolve through the package export map. There are no focused tests for queue deduping/concurrency/status behavior or timeout replacement/cleanup.

Recommendation: Add small unit tests for packages/react/src/internals/RequestQueue.ts and packages/react/src/internals/TimeoutManager.ts, or keep them out of the exported internals surface until their behavior is covered.

Test Coverage Assessment

I ran pnpm test:jsdom index --no-watch, pnpm test:jsdom TemporalAdapterLuxon --no-watch, and pnpm typescript on the PR head in an isolated worktree after installing dependencies. They passed, but they do not catch the emitted-declaration import problem above or the missing behavioral coverage for the two new internal utilities.

Recommendation

Request changes 🔴

The branch needs a rebase/conflict resolution before it can merge, and the newly exported Luxon adapter declaration currently points at the wrong type module. The docs JSDoc regression and missing tests are smaller follow-ups, but the first two issues should be fixed before approval.

@flaviendelangle
Copy link
Copy Markdown
Member Author

flaviendelangle commented Apr 10, 2026

Point 1 is already fixed
I'll fix the other ones 👍

1 => ok
2 => ok
3 => ok
4 => ok

@github-actions github-actions Bot added the PR: out-of-date The pull request has merge conflicts and can't be merged. label Apr 10, 2026
@github-actions github-actions Bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged. label Apr 10, 2026
@flaviendelangle flaviendelangle merged commit 04e3a82 into mui:master Apr 13, 2026
24 checks passed
@flaviendelangle flaviendelangle deleted the internals-folder branch April 13, 2026 11:21
LukasTy added a commit to LukasTy/base-ui that referenced this pull request Apr 17, 2026
The `date-fns` and `@date-fns/tz` entries in `docs/package.json` are no
longer imported anywhere in docs after the Calendar demos were removed
in mui#4505.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: all components Widespread work has an impact on almost all components. type: enhancement It’s an improvement, but we can’t make up our mind whether it's a bug fix or a new feature.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants