diff --git a/packages/react-native/package.json b/packages/react-native/package.json index bf6a02391a3..554d7c61cbe 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -49,6 +49,11 @@ "default": "./src/asset-registry.js" }, "./setup-env": "./src/setup-env.js", + "./unstable-internals-do-not-use": { + "react-native-unstable-internals": "./src/unstable-internals-do-not-use.d.ts", + "types": null, + "default": "./src/unstable-internals-do-not-use.js" + }, "./src/fb_internal/*": "./src/fb_internal/*", "./package.json": "./package.json" }, diff --git a/packages/react-native/src/unstable-internals-do-not-use.d.ts b/packages/react-native/src/unstable-internals-do-not-use.d.ts new file mode 100644 index 00000000000..6c1f3bf54c4 --- /dev/null +++ b/packages/react-native/src/unstable-internals-do-not-use.d.ts @@ -0,0 +1,214 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +// ---------------------------------------------------------------------------- +// Types entry point for react-native/unstable-internals-do-not-use. +// +// IMPORTANT: Keep this file in sync with unstable-internals-do-not-use.js. +// ---------------------------------------------------------------------------- + +import type * as React from 'react'; + +// #region AppContainer + +interface AppContainerProps { + children?: React.ReactNode | undefined; + rootTag: number; + initialProps?: object | undefined; + WrapperComponent?: React.ComponentType | null | undefined; + rootViewStyle?: unknown | undefined; + internal_excludeLogBox?: boolean | undefined; + internal_excludeInspector?: boolean | undefined; +} + +/** Root component that wraps and mounts a React Native app tree. */ +export const AppContainer: React.ComponentType; + +// #endregion +// #region AssetSourceResolver + +interface ResolvedAssetSource { + readonly __packager_asset: boolean; + readonly width: number | null | undefined; + readonly height: number | null | undefined; + readonly uri: string; + readonly scale: number; +} + +/** Resolves a packager asset descriptor to a loadable source for the current platform. */ +export class AssetSourceResolver { + serverUrl: string | null | undefined; + jsbundleUrl: string | null | undefined; + asset: unknown; + constructor( + serverUrl: string | null | undefined, + jsbundleUrl: string | null | undefined, + asset: unknown, + ); + isLoadedFromServer(): boolean; + isLoadedFromFileSystem(): boolean; + defaultAsset(): ResolvedAssetSource; + getAssetUsingResolver(resolver: 'android' | 'generic'): ResolvedAssetSource; + assetServerURL(): ResolvedAssetSource; + scaledAssetPath(): ResolvedAssetSource; + scaledAssetURLNearBundle(): ResolvedAssetSource; + resourceIdentifierWithoutScale(): ResolvedAssetSource; + drawableFolderInBundle(): ResolvedAssetSource; + fromSource(source: string): ResolvedAssetSource; + static pickScale(scales: number[], deviceScale?: number): number; +} + +// #endregion +// #region customDirectEventTypes + +/** Registry mapping custom direct (non-bubbling) event names to their registration names. */ +export const customDirectEventTypes: { + [eventName: string]: Readonly<{ + registrationName: string; + }>; +}; + +// #endregion +// #region DevLoadingView + +/** Dev-only overlay banner showing bundle load, refresh, and error status. */ +export const DevLoadingView: { + showMessage( + message: string, + type: 'load' | 'refresh' | 'error', + options?: {dismissButton?: boolean | undefined}, + ): void; + hide(): void; +}; + +// #endregion +// #region getDevServer + +interface DevServerInfo { + url: string; + fullBundleUrl: string | null; + bundleLoadedFromServer: boolean; +} + +/** Returns information about the running dev server. */ +export function getDevServer(): DevServerInfo; + +// #endregion +// #region HMRClient + +/** Client that receives Fast Refresh updates and applies them at runtime. */ +export class HMRClient { + enable(): void; + disable(): void; + registerBundle(requestUrl: string): void; + log( + level: + | 'trace' + | 'info' + | 'warn' + | 'error' + | 'log' + | 'group' + | 'groupCollapsed' + | 'groupEnd' + | 'debug', + data: ReadonlyArray, + ): void; + setup( + platform: string, + bundleEntry: string, + host: string, + port: number | string, + isEnabled: boolean, + scheme?: string, + ): void; +} + +// #endregion +// #region NativeExceptionsManager + +interface StackFrame { + column: number | null; + file: string | null; + lineNumber: number | null; + methodName: string; + collapse?: boolean | undefined; +} + +interface ExceptionData { + message: string; + originalMessage: string | null; + name: string | null; + componentStack: string | null; + stack: StackFrame[]; + id: number; + isFatal: boolean; + extraData?: object | undefined; +} + +/** Reports JS exceptions to native and manages RedBox. */ +export const NativeExceptionsManager: { + reportFatalException( + message: string, + stack: StackFrame[], + exceptionId: number, + ): void; + reportSoftException( + message: string, + stack: StackFrame[], + exceptionId: number, + ): void; + dismissRedbox(): void; + reportException(data: ExceptionData): void; +}; + +// #endregion +// #region NativeRedBox + +interface NativeRedBoxSpec { + setExtraData(extraData: object, forIdentifier: string): void; + dismiss(): void; +} + +/** Native module for the RedBox error overlay; null when unavailable. */ +export const NativeRedBox: NativeRedBoxSpec | null; + +// #endregion +// #region NativeSourceCode + +interface SourceCodeConstants { + scriptURL: string; +} + +/** Native module exposing source-code constants such as the bundle scriptURL. */ +export const NativeSourceCode: { + getConstants(): SourceCodeConstants; +}; + +// #endregion +// #region PressabilityDebugView + +type Rect = Readonly<{ + bottom?: number | null | undefined; + left?: number | null | undefined; + right?: number | null | undefined; + top?: number | null | undefined; +}>; + +type RectOrSize = Rect | number; + +interface PressabilityDebugViewProps { + color: unknown; + hitSlop: RectOrSize | null | undefined; +} + +/** Debug overlay that visualizes press targets when enabled via the Inspector. */ +export const PressabilityDebugView: React.ComponentType; + +// #endregion diff --git a/packages/react-native/src/unstable-internals-do-not-use.js b/packages/react-native/src/unstable-internals-do-not-use.js new file mode 100644 index 00000000000..20cb19edaec --- /dev/null +++ b/packages/react-native/src/unstable-internals-do-not-use.js @@ -0,0 +1,76 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @noflow + * @format + */ + +'use strict'; +'use client'; + +// ---------------------------------------------------------------------------- +// react-native/unstable-internals-do-not-use +// +// UNSTABLE WITH NO SEMVER GUARANTEES. +// SHOULD NOT BE DEPENDED ON BY NEW CODE. +// +// This is a secondary entry point for frameworks and libraries that depend on +// specific React Native internals, serving as a compatibility bridge. +// +// Consuming codebases must opt in via tsconfig.json: +// "customConditions": ["react-native-unstable-internals"] +// +// Having this entry point: +// - Maintains a known list of which React Native internals are in use. +// - Enables us to relocate supporting files more freely. +// - Gives us time to decide on the future of these APIs (independent from +// removal of the Strict API opt out). +// +// The long term future of these exports is to formalize/delete them where +// appropriate, and collapse this entry point. +// +// Replaces RFC0985 +// https://github.com/react-native-community/discussions-and-proposals/pull/985 +// where we reviewed internal APIs used in the ecosystem. +// +// IMPORTANT: Keep this file in sync with unstable-internals-do-not-use.d.ts. +// ---------------------------------------------------------------------------- + +// eslint-disable-next-line @react-native/monorepo/no-commonjs-exports +module.exports = { + get AppContainer() { + return require('../Libraries/ReactNative/AppContainer').default; + }, + get AssetSourceResolver() { + return require('../Libraries/Image/AssetSourceResolver').default; + }, + get customDirectEventTypes() { + return require('../Libraries/Renderer/shims/ReactNativeViewConfigRegistry') + .customDirectEventTypes; + }, + get DevLoadingView() { + return require('../Libraries/Utilities/DevLoadingView').default; + }, + get getDevServer() { + return require('../Libraries/Core/Devtools/getDevServer').default; + }, + get HMRClient() { + return require('../Libraries/Utilities/HMRClient').default; + }, + get NativeExceptionsManager() { + return require('../Libraries/Core/NativeExceptionsManager').default; + }, + get NativeRedBox() { + return require('../Libraries/NativeModules/specs/NativeRedBox').default; + }, + get NativeSourceCode() { + return require('../Libraries/NativeModules/specs/NativeSourceCode').default; + }, + get PressabilityDebugView() { + return require('../Libraries/Pressability/PressabilityDebug') + .PressabilityDebugView; + }, +};