Decision

<aside> ✅ Option: Why?

</aside>

Context

We have been discussing the purpose, visibility, and restrictions of the @mui/utils package for a long time. Let’s gather all the ideas here and make a decision.

The @mui/utils package currently is a mixture of utilities that could be helpful for 3rd party developers (like useForkRef), functions used mostly in MUI for building components (useControlled, all prop-types related helpers), and build-time Babel macros.

MUI X has created its own utils package, see the discussion in ‣. It uses @mui/x-internals

Previous conversation around this:

Problems

  1. Confusion for MUI X on what they should import / have as dependency
  2. Confusion about which product/team owns which utils
  3. Confusion on what’s private / public
  4. Avoid duplication so we can learn once, fix once
  5. How should dependencies flow?
    1. Should we re-export or not? Example: Where does X import useForkRef from?
      1. Re-exported form @mui/utils ?
      2. Directly from @base/utils ?
    2. What happens if we decide to “hoist” a util from mui to base? How do we maintain backwards compatibility?

Options

A. @ Layer of @xxx/utils and @xxx/internals modules

Terminology:

Name On npm Imported by developers Follow semver Use cases API Notes
public Our product. Nothing special.
unstable No API we want to try out with the community. They could become stable. Same package, but modules exported with a prefix: unstable_ . Dependencies using must pin their version.
internals No No Avoid duplication of code between npm packages. package name:
*-internals for logic used by public packages.
@newco/internal-* for infra Dependencies using must pin their version.
private No No No Workspace local packages, examples. private: true value in package.json.

Playbook: