{"_id":"@bubblydoo/its-fine","_rev":"9-f1fb50bb2d34901ab9b5865f524dcf81","name":"@bubblydoo/its-fine","dist-tags":{"latest":"1.0.10-bubblydoo.0"},"versions":{"1.0.10-bubblydoo.0":{"name":"@bubblydoo/its-fine","version":"1.0.10-bubblydoo.0","keywords":["react","fiber","internal","reconciler","hooks"],"author":{"url":"https://github.com/codyjasonbennett","name":"Cody Bennett"},"license":"MIT","_id":"@bubblydoo/its-fine@1.0.10-bubblydoo.0","maintainers":[{"name":"siemenvdm","email":"siemen.vdmv@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"},{"name":"oliverobrien","email":"oliver.ian.obrien@gmail.com"},{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"}],"homepage":"https://github.com/pmndrs/its-fine","bugs":{"url":"https://github.com/pmndrs/its-fine/issues"},"dist":{"shasum":"9dc7fec6b0fe170da7936b7d5eafbdc1dd0a727c","tarball":"https://registry.npmjs.org/@bubblydoo/its-fine/-/its-fine-1.0.10-bubblydoo.0.tgz","fileCount":9,"integrity":"sha512-affaKwJUwIEn8Qr/QrN2560T5EYWcqhAsfCx+zTPErhFG8IbYDfK6502bhkEV2/IRUxV6w1+rmHw+wmE+v3vDQ==","signatures":[{"sig":"MEUCIG8ucVZziNKn0LWxLOCBL3KidBUZg2EE8n2xX+C3bS4HAiEA/l4McTB5IWex/ZYYor8pH7GAquQii6z22xiWM9Zy3MQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":37485,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJkD63mACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrpIw//aDwty881GOFfsFVZwQgI2SbkiiWKoZlDXsfGxRm1UUveR03E\r\nVfw8tmRp5jv9scSxYiZpQknuvGiCVoKaBkm/Bia+odAb5kw5V0rp2Nsj4nlO\r\nSPjIIYnFdawqrj4JU7ejVtMf2aczEao1mQk5VOTRC+OfESIPXhnTAbwQWmwy\r\nlH7daykZ+ughwTfRi06rkgngj6/QfkcWe9kGWZEkVcG1gZ3dUxnrQiUUPCMU\r\nUIeJ5zh9i97NNBthBKYXGMEFhgMtPCuwBj+0mlVfSDzrjMQpi9Lqybkf3EN1\r\nAkYwa/w0pggGl0IhJ8G7yCcno8s2wq3PyLbvJZWB4PJnFx9QuojIf+SAhIUA\r\nMtOCSvuIewkzb/F7vrqRJVq2gOeUGIoZKMKAvfSfNzusY3N1Ak1V/MoOhcBI\r\n+3OvMog2uu0M6yM3sRtNB8LML98+WhorYzWgT3Ug3LhIUQ0zJD2O28I77GWF\r\n9faxwR8Of3oTPMU6J0chLvzIe3jb75kkqnjMXEFZF4OkzIEZ0jKC3iiiBMWw\r\nxahYaUJrH5gO826klAX6GjIceU+QXYV7JOTn9EN4oDCSq7uBniNJN2ev2gUa\r\nrayjZN6rmt+RGwQyxCDT1aEr7RhytrRVpV/7IZ/43AYBJnGZc7zVMMoxRrpV\r\nP/3CvCIiRPgrKl2W7EOPB977Uj9yoNywbOk=\r\n=5PE+\r\n-----END PGP SIGNATURE-----\r\n"},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","gitHead":"b56782684cb0dbe022649651f9298ef19d30c39d","scripts":{"test":"vitest run","build":"rimraf dist && vite build && tsc"},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"repository":{"url":"git+https://github.com/pmndrs/its-fine.git","type":"git"},"_npmVersion":"8.19.2","description":"A collection of escape hatches for React.","directories":{},"sideEffects":false,"_nodeVersion":"18.12.1","dependencies":{"@types/react-reconciler":"^0.28.0"},"react-native":"./dist/index.js","_hasShrinkwrap":false,"devDependencies":{"vite":"^3.1.0","react":"^18.2.0","rimraf":"^3.0.2","vitest":"^0.23.1","react-nil":"^1.2.0","typescript":"^4.7.4","@types/node":"^18.7.15","@types/react":"^18.0.17","suspend-react":"^0.0.8","react-test-renderer":"^18.2.0","@types/react-test-renderer":"^18.0.0"},"peerDependencies":{"react":">=18.0"},"_npmOperationalInternal":{"tmp":"tmp/its-fine_1.0.10-bubblydoo.0_1678749158358_0.14974113121591448","host":"s3://npm-registry-packages"}}},"time":{"created":"2023-03-13T23:12:38.357Z","modified":"2026-05-11T13:53:36.903Z","1.0.10-bubblydoo.0":"2023-03-13T23:12:38.646Z"},"bugs":{"url":"https://github.com/pmndrs/its-fine/issues"},"author":{"url":"https://github.com/codyjasonbennett","name":"Cody Bennett"},"license":"MIT","homepage":"https://github.com/pmndrs/its-fine","keywords":["react","fiber","internal","reconciler","hooks"],"repository":{"url":"git+https://github.com/pmndrs/its-fine.git","type":"git"},"description":"A collection of escape hatches for React.","maintainers":[{"email":"hansottowirtz@gmail.com","name":"hansottowirtz"},{"email":"krystianpiatkowski@bubbly-doo.com","name":"krystianpiatkowski"},{"email":"leonardoescuer@bubbly-doo.com","name":"leo-bubblydoo"},{"email":"jeremynavarro@bubbly-doo.com","name":"jeremy_navarro"}],"readme":"# its-fine\n\n[![Size](https://img.shields.io/bundlephobia/minzip/its-fine?label=gzip&style=flat&colorA=000000&colorB=000000)](https://bundlephobia.com/package/its-fine)\n[![Version](https://img.shields.io/npm/v/its-fine?style=flat&colorA=000000&colorB=000000)](https://npmjs.com/package/its-fine)\n[![Downloads](https://img.shields.io/npm/dt/its-fine.svg?style=flat&colorA=000000&colorB=000000)](https://npmjs.com/package/its-fine)\n[![Twitter](https://img.shields.io/twitter/follow/pmndrs?label=%40pmndrs&style=flat&colorA=000000&colorB=000000&logo=twitter&logoColor=000000)](https://twitter.com/pmndrs)\n[![Discord](https://img.shields.io/discord/740090768164651008?style=flat&colorA=000000&colorB=000000&label=discord&logo=discord&logoColor=000000)](https://discord.gg/poimandres)\n\n<p align=\"left\">\n  <a id=\"cover\" href=\"#cover\">\n    <img src=\".github/itsfine.jpg\" alt=\"It's gonna be alright\" />\n  </a>\n</p>\n\nA collection of escape hatches exploring `React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED`. I'm sure you want me to tell you how safe and stable this all is.\n\nAs such, you can go beyond React's component abstraction; components are self-aware and can tap into the React Fiber tree. This enables powerful abstractions like stateless queries and sharing React Context across concurrent renderers.\n\n## Table of Contents\n\n- [Components](#components)\n  - [FiberProvider](#fiberprovider)\n- [Hooks](#hooks)\n  - [useFiber](#useFiber)\n  - [useContainer](#useContainer)\n  - [useNearestChild](#useNearestChild)\n  - [useNearestParent](#useNearestParent)\n  - [useContextBridge](#useContextBridge)\n- [Utils](#utils)\n  - [traverseFiber](#traverseFiber)\n\n## Components\n\n### FiberProvider\n\nA react-internal `Fiber` provider. This component binds React children to the React Fiber tree. Call its-fine hooks within this.\n\n> **Note**: pmndrs renderers like react-three-fiber implement this internally to make use of [`useContextBridge`](#usecontextbridge), so you would only need this when using hooks inside of `react-dom` or `react-native`.\n\n```tsx\nimport * as ReactDOM from 'react-dom/client'\nimport { FiberProvider, useFiber } from 'its-fine'\n\nfunction App() {\n  const fiber = useFiber()\n}\n\ncreateRoot(document.getElementById('root')!).render(\n  <FiberProvider>\n    <App />\n  </FiberProvider>,\n)\n```\n\n## Hooks\n\nUseful React hook abstractions for manipulating and querying from a component. These must be called within a [`FiberProvider`](#fiberprovider) component.\n\n### useFiber\n\nReturns the current react-internal `Fiber`. This is an implementation detail of [react-reconciler](https://github.com/facebook/react/tree/main/packages/react-reconciler).\n\n```tsx\nimport * as React from 'react'\nimport { type Fiber, useFiber } from 'its-fine'\n\nfunction Component() {\n  // Returns the current component's react-internal Fiber\n  const fiber: Fiber<null> | undefined = useFiber()\n\n  // function Component() {}\n  if (fiber) console.log(fiber.type)\n}\n```\n\n### useContainer\n\nReturns the current react-reconciler container info passed to `Reconciler.createContainer`.\n\nIn react-dom, a container will point to the root DOM element; in react-three-fiber, it will point to the root Zustand store.\n\n```tsx\nimport * as React from 'react'\nimport { useContainer } from 'its-fine'\n\nfunction Component() {\n  // Returns the current renderer's root container\n  const container: HTMLDivElement | undefined = useContainer<HTMLDivElement>()\n\n  // <div> (e.g. react-dom)\n  if (container) console.log(container)\n}\n```\n\n### useNearestChild\n\nReturns the nearest react-reconciler child instance or the node created from `Reconciler.createInstance`.\n\nIn react-dom, this would be a DOM element; in react-three-fiber this would be an `Instance` descriptor.\n\n```tsx\nimport * as React from 'react'\nimport { useNearestChild } from 'its-fine'\n\nfunction Component() {\n  // Returns a React Ref which points to the nearest child <div /> element.\n  // Omit the element type to match the nearest element of any kind\n  const childRef: React.MutableRefObject<HTMLDivElement | undefined> = useNearestChild<HTMLDivElement>('div')\n\n  // Access child Ref on mount\n  React.useEffect(() => {\n    // <div> (e.g. react-dom)\n    const child = childRef.current\n    if (child) console.log(child)\n  }, [])\n\n  // A child element, can live deep down another component\n  return <div />\n}\n```\n\n### useNearestParent\n\nReturns the nearest react-reconciler parent instance or the node created from `Reconciler.createInstance`.\n\nIn react-dom, this would be a DOM element; in react-three-fiber this would be an instance descriptor.\n\n```tsx\nimport * as React from 'react'\nimport { useNearestParent } from 'its-fine'\n\nfunction Component() {\n  // Returns a React Ref which points to the nearest parent <div /> element.\n  // Omit the element type to match the nearest element of any kind\n  const parentRef: React.MutableRefObject<HTMLDivElement | undefined> = useNearestParent<HTMLDivElement>('div')\n\n  // Access parent Ref on mount\n  React.useEffect(() => {\n    // <div> (e.g. react-dom)\n    const parent = parentRef.current\n    if (parent) console.log(parent)\n  }, [])\n}\n\n// A parent element wrapping Component, can live deep up another component\n;<div>\n  <Component />\n</div>\n```\n\n### useContextBridge\n\nReact Context currently cannot be shared across [React renderers](https://reactjs.org/docs/codebase-overview.html#renderers) but explicitly forwarded between providers (see [react#17275](https://github.com/facebook/react/issues/17275)). This hook returns a `ContextBridge` of live context providers to pierce Context across renderers.\n\nPass `ContextBridge` as a component to a secondary renderer to enable context-sharing within its children.\n\n```tsx\nimport * as React from 'react'\n// react-nil is a secondary renderer that is usually used for testing.\n// This also includes Fabric, react-three-fiber, etc\nimport * as ReactNil from 'react-nil'\n// react-dom is a primary renderer that works on top of a secondary renderer.\n// This also includes react-native, react-pixi, etc.\nimport * as ReactDOM from 'react-dom/client'\nimport { type ContextBridge, useContextBridge, FiberProvider } from 'its-fine'\n\nfunction Canvas(props: { children: React.ReactNode }) {\n  // Returns a bridged context provider that forwards context\n  const Bridge: ContextBridge = useContextBridge()\n  // Renders children with bridged context into a secondary renderer\n  ReactNil.render(<Bridge>{props.children}</Bridge>)\n}\n\n// A React Context whose provider lives in react-dom\nconst DOMContext = React.createContext<string>(null!)\n\n// A component that reads from DOMContext\nfunction Component() {\n  // \"Hello from react-dom\"\n  console.log(React.useContext(DOMContext))\n}\n\n// Renders into a primary renderer like react-dom or react-native,\n// DOMContext wraps Canvas and is bridged into Component\nReactDOM.createRoot(document.getElementById('root')!).render(\n  <FiberProvider>\n    <DOMContext.Provider value=\"Hello from react-dom\">\n      <Canvas>\n        <Component />\n      </Canvas>\n    </DOMContext.Provider>\n  </FiberProvider>,\n)\n```\n\n## Utils\n\nAdditional exported utility functions for raw handling of Fibers.\n\n### traverseFiber\n\nTraverses up or down a `Fiber`, return `true` to stop and select a node.\n\n```ts\nimport { type Fiber, traverseFiber } from 'its-fine'\n\n// Traverses through the Fiber tree, returns the current node when `true` is passed via selector\nconst parentDiv: Fiber<HTMLDivElement> | undefined = traverseFiber<HTMLDivElement>(\n  // Input Fiber to traverse\n  fiber as Fiber,\n  // Whether to ascend and walk up the tree. Will walk down if `false`\n  true,\n  // A Fiber node selector, returns the first match when `true` is passed\n  (node: Fiber<HTMLDivElement | null>) => node.type === 'div',\n)\n```\n","readmeFilename":"README.md"}