first commit
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022-2025 Poimandres
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
# its-fine
|
||||
|
||||
[](https://bundlephobia.com/package/its-fine)
|
||||
[](https://npmjs.com/package/its-fine)
|
||||
[](https://npmjs.com/package/its-fine)
|
||||
[](https://twitter.com/pmndrs)
|
||||
[](https://discord.gg/poimandres)
|
||||
|
||||
<p align="left">
|
||||
<a id="cover" href="#cover">
|
||||
<img src=".github/itsfine.jpg" alt="It's gonna be alright" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
A collection of escape hatches for React.
|
||||
|
||||
As such, you can go beyond React's component abstraction; components are self-aware and can tap into the [React Fiber](https://youtu.be/ZCuYPiUIONs) tree. This enables powerful abstractions that can modify or extend React behavior without explicitly taking reconciliation into your own hands.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Components](#components)
|
||||
- [FiberProvider](#fiberprovider)
|
||||
- [Hooks](#hooks)
|
||||
- [useFiber](#useFiber)
|
||||
- [useContainer](#useContainer)
|
||||
- [useNearestChild](#useNearestChild)
|
||||
- [useNearestParent](#useNearestParent)
|
||||
- [useContextMap](#useContextMap)
|
||||
- [useContextBridge](#useContextBridge)
|
||||
- [useActivityBridge](#useActivityBridge)
|
||||
- [Utils](#utils)
|
||||
- [traverseFiber](#traverseFiber)
|
||||
|
||||
## Components
|
||||
|
||||
### FiberProvider
|
||||
|
||||
A react-internal `Fiber` provider. This component binds React children to the React Fiber tree. Call its-fine hooks within this.
|
||||
|
||||
> **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`.
|
||||
|
||||
```tsx
|
||||
import * as ReactDOM from 'react-dom/client'
|
||||
import { FiberProvider, useFiber } from 'its-fine'
|
||||
|
||||
function App() {
|
||||
const fiber = useFiber()
|
||||
}
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<FiberProvider>
|
||||
<App />
|
||||
</FiberProvider>,
|
||||
)
|
||||
```
|
||||
|
||||
## Hooks
|
||||
|
||||
Useful React hook abstractions for manipulating and querying from a component. These must be called within a [`FiberProvider`](#fiberprovider) component.
|
||||
|
||||
### useFiber
|
||||
|
||||
Returns the current react-internal `Fiber`. This is an implementation detail of [react-reconciler](https://github.com/facebook/react/tree/main/packages/react-reconciler).
|
||||
|
||||
```tsx
|
||||
import * as React from 'react'
|
||||
import { type Fiber, useFiber } from 'its-fine'
|
||||
|
||||
function Component() {
|
||||
// Returns the current component's react-internal Fiber
|
||||
const fiber: Fiber<null> | undefined = useFiber()
|
||||
|
||||
// function Component() {}
|
||||
if (fiber) console.log(fiber.type)
|
||||
}
|
||||
```
|
||||
|
||||
### useContainer
|
||||
|
||||
Returns the current react-reconciler container info passed to `Reconciler.createContainer`.
|
||||
|
||||
In react-dom, a container will point to the root DOM element; in react-three-fiber, it will point to the root Zustand store.
|
||||
|
||||
```tsx
|
||||
import * as React from 'react'
|
||||
import { useContainer } from 'its-fine'
|
||||
|
||||
function Component() {
|
||||
// Returns the current renderer's root container
|
||||
const container: HTMLDivElement | undefined = useContainer<HTMLDivElement>()
|
||||
|
||||
// <div> (e.g. react-dom)
|
||||
if (container) console.log(container)
|
||||
}
|
||||
```
|
||||
|
||||
### useNearestChild
|
||||
|
||||
Returns the nearest react-reconciler child instance or the node created from `Reconciler.createInstance`.
|
||||
|
||||
In react-dom, this would be a DOM element; in react-three-fiber this would be an `Instance` descriptor.
|
||||
|
||||
```tsx
|
||||
import * as React from 'react'
|
||||
import { useNearestChild } from 'its-fine'
|
||||
|
||||
function Component() {
|
||||
// Returns a React Ref which points to the nearest child <div /> element.
|
||||
// Omit the element type to match the nearest element of any kind
|
||||
const childRef: React.MutableRefObject<HTMLDivElement | undefined> = useNearestChild<HTMLDivElement>('div')
|
||||
|
||||
// Access child Ref on mount
|
||||
React.useEffect(() => {
|
||||
// <div> (e.g. react-dom)
|
||||
const child = childRef.current
|
||||
if (child) console.log(child)
|
||||
}, [])
|
||||
|
||||
// A child element, can live deep down another component
|
||||
return <div />
|
||||
}
|
||||
```
|
||||
|
||||
### useNearestParent
|
||||
|
||||
Returns the nearest react-reconciler parent instance or the node created from `Reconciler.createInstance`.
|
||||
|
||||
In react-dom, this would be a DOM element; in react-three-fiber this would be an instance descriptor.
|
||||
|
||||
```tsx
|
||||
import * as React from 'react'
|
||||
import { useNearestParent } from 'its-fine'
|
||||
|
||||
function Component() {
|
||||
// Returns a React Ref which points to the nearest parent <div /> element.
|
||||
// Omit the element type to match the nearest element of any kind
|
||||
const parentRef: React.MutableRefObject<HTMLDivElement | undefined> = useNearestParent<HTMLDivElement>('div')
|
||||
|
||||
// Access parent Ref on mount
|
||||
React.useEffect(() => {
|
||||
// <div> (e.g. react-dom)
|
||||
const parent = parentRef.current
|
||||
if (parent) console.log(parent)
|
||||
}, [])
|
||||
}
|
||||
|
||||
// A parent element wrapping Component, can live deep up another component
|
||||
;<div>
|
||||
<Component />
|
||||
</div>
|
||||
```
|
||||
|
||||
### useContextMap
|
||||
|
||||
Returns a map of all contexts and their values.
|
||||
|
||||
```tsx
|
||||
import * as React from 'react'
|
||||
import { useContextMap } from 'its-fine'
|
||||
|
||||
const SomeContext = React.createContext<string>(null!)
|
||||
|
||||
function Component() {
|
||||
const contextMap = useContextMap()
|
||||
return contextMap.get(SomeContext)
|
||||
}
|
||||
```
|
||||
|
||||
### useContextBridge
|
||||
|
||||
React 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.
|
||||
|
||||
Pass `ContextBridge` as a component to a secondary renderer to enable context-sharing within its children.
|
||||
|
||||
```tsx
|
||||
import * as React from 'react'
|
||||
// react-nil is a secondary renderer that is usually used for testing.
|
||||
// This also includes Fabric, react-three-fiber, etc
|
||||
import * as ReactNil from 'react-nil'
|
||||
// react-dom is a primary renderer that works on top of a secondary renderer.
|
||||
// This also includes react-native, react-pixi, etc.
|
||||
import * as ReactDOM from 'react-dom/client'
|
||||
import { type ContextBridge, useContextBridge, FiberProvider } from 'its-fine'
|
||||
|
||||
function Canvas(props: { children: React.ReactNode }) {
|
||||
// Returns a bridged context provider that forwards context
|
||||
const Bridge: ContextBridge = useContextBridge()
|
||||
// Renders children with bridged context into a secondary renderer
|
||||
ReactNil.render(<Bridge>{props.children}</Bridge>)
|
||||
}
|
||||
|
||||
// A React Context whose provider lives in react-dom
|
||||
const DOMContext = React.createContext<string>(null!)
|
||||
|
||||
// A component that reads from DOMContext
|
||||
function Component() {
|
||||
// "Hello from react-dom"
|
||||
console.log(React.useContext(DOMContext))
|
||||
}
|
||||
|
||||
// Renders into a primary renderer like react-dom or react-native,
|
||||
// DOMContext wraps Canvas and is bridged into Component
|
||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||
<FiberProvider>
|
||||
<DOMContext.Provider value="Hello from react-dom">
|
||||
<Canvas>
|
||||
<Component />
|
||||
</Canvas>
|
||||
</DOMContext.Provider>
|
||||
</FiberProvider>,
|
||||
)
|
||||
```
|
||||
|
||||
### useActivityBridge
|
||||
|
||||
Returns a stable `ActivityBridge` that forwards ancestor `<Activity>` visibility into another React root while preserving child state. Requires React 19.2+ and an Activity capable renderer.
|
||||
|
||||
```tsx
|
||||
import * as React from 'react'
|
||||
import * as ReactDOM from 'react-dom/client'
|
||||
import { useActivityBridge, FiberProvider } from 'its-fine'
|
||||
|
||||
// The application owns the destination root and its cleanup
|
||||
const destination = ReactDOM.createRoot(document.getElementById('destination')!)
|
||||
|
||||
function Canvas(props: { children: React.ReactNode }) {
|
||||
// Forwards Activity visibility. Use useContextBridge separately for context
|
||||
const Bridge = useActivityBridge()
|
||||
// Render after the source commits. Removing Canvas hides the destination
|
||||
React.useLayoutEffect(() => {
|
||||
destination.render(<Bridge>{props.children}</Bridge>)
|
||||
})
|
||||
return null
|
||||
}
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('source')!).render(
|
||||
<FiberProvider>
|
||||
{/* Set mode to "hidden" to hide both roots' children while preserving state */}
|
||||
<React.Activity mode="visible">
|
||||
<Canvas>
|
||||
<div>Scene</div>
|
||||
</Canvas>
|
||||
</React.Activity>
|
||||
</FiberProvider>,
|
||||
)
|
||||
```
|
||||
|
||||
If the source shows a Suspense loading fallback, the destination stays visible unless an ancestor Activity is hidden.
|
||||
|
||||
## Utils
|
||||
|
||||
Additional exported utility functions for raw handling of Fibers.
|
||||
|
||||
### traverseFiber
|
||||
|
||||
Traverses up or down a `Fiber`, return `true` to stop and select a node.
|
||||
|
||||
```ts
|
||||
import { type Fiber, traverseFiber } from 'its-fine'
|
||||
|
||||
// Traverses through the Fiber tree, returns the current node when `true` is passed via selector
|
||||
const parentDiv: Fiber<HTMLDivElement> | undefined = traverseFiber<HTMLDivElement>(
|
||||
// Input Fiber to traverse
|
||||
fiber as Fiber,
|
||||
// Whether to ascend and walk up the tree. Will walk down if `false`
|
||||
true,
|
||||
// A Fiber node selector, returns the first match when `true` is passed
|
||||
(node: Fiber<HTMLDivElement | null>) => node.type === 'div',
|
||||
)
|
||||
```
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("react"),v=(()=>{var e,t;return typeof window!="undefined"&&(((e=window.document)==null?void 0:e.createElement)||((t=window.navigator)==null?void 0:t.product)==="ReactNative")})()?n.useLayoutEffect:n.useEffect;function f(e,t,i){if(!e)return;if(i(e)===!0)return e;let r=t?e.return:e.child;for(;r;){const s=f(r,t,i);if(s)return s;r=t?null:r.sibling}}function p(e){try{return Object.defineProperties(e,{_currentRenderer:{get(){return null},set(){}},_currentRenderer2:{get(){return null},set(){}}})}catch(t){return e}}const b=p(n.createContext(null));class h extends n.Component{render(){return n.createElement(b.Provider,{value:this._reactInternals},this.props.children)}}function d(){const e=n.useContext(b);if(e===null)throw new Error("its-fine: useFiber must be called within a <FiberProvider />!");const t=n.useId();return n.useMemo(()=>{for(const r of[e,e==null?void 0:e.alternate]){if(!r)continue;const s=f(r,!1,m=>{let o=m.memoizedState;for(;o;){if(o.memoizedState===t)return!0;o=o.next}});if(s)return s}},[e,t])}function g(){const e=d(),t=n.useMemo(()=>f(e,!0,i=>{var r;return((r=i.stateNode)==null?void 0:r.containerInfo)!=null}),[e]);return t==null?void 0:t.stateNode.containerInfo}function E(e){const t=d(),i=n.useRef(void 0);return v(()=>{var r;i.current=(r=f(t,!1,s=>typeof s.type=="string"&&(e===void 0||s.type===e)))==null?void 0:r.stateNode},[t]),i}function C(e){const t=d(),i=n.useRef(void 0);return v(()=>{var r;i.current=(r=f(t,!0,s=>typeof s.type=="string"&&(e===void 0||s.type===e)))==null?void 0:r.stateNode},[t]),i}const x=Symbol.for("react.context"),F=e=>e!==null&&typeof e=="object"&&"$$typeof"in e&&e.$$typeof===x;function w(){const e=d(),[t]=n.useState(()=>new Map);t.clear();let i=e;for(;i;){const r=i.type;F(r)&&r!==b&&!t.has(r)&&t.set(r,n.use(p(r))),i=i.return}return t}function A(){const e=w();return n.useMemo(()=>Array.from(e.keys()).reduce((t,i)=>r=>n.createElement(t,null,n.createElement(i.Provider,{...r,value:e.get(i)})),t=>n.createElement(h,{...t})),[e])}function M(e){if(typeof requestAnimationFrame=="function"){const i=requestAnimationFrame(e);return()=>cancelAnimationFrame(i)}const t=setTimeout(e,16);return()=>clearTimeout(t)}function N(){if(!n.Activity)throw new Error("its-fine: useActivityBridge requires React 19.2 or later!");const e=d(),[t]=n.useState(()=>{const i=[];let r=!1;f(e,!0,u=>{var c,l;if(u.elementType===n.Activity){const y=((c=u.child)==null?void 0:c.tag)===22?u.child.stateNode:null;if(typeof(y==null?void 0:y._visibility)!="number")throw new Error("its-fine: unsupported React Activity internals!");i.push(y)}else u.tag===22&&((l=u.return)==null?void 0:l.elementType)!==n.Activity&&(r=!0)});let s="hidden";const m=new Set;let o;const a={mounted:!1,connected:!1,subscribe(u){return m.add(u),()=>{m.delete(u)}},sync(u){a.mounted&&!a.connected&&r&&i.length>0?o||(o=M(()=>{o=void 0,a.sync(!0)})):(o==null||o(),o=void 0);let c=s;if(a.mounted?a.connected?c="visible":u&&(c=i.every(l=>(l._visibility&1)!==0)?"visible":"hidden"):c="hidden",s!==c){s=c;for(const l of m)l()}},Bridge({children:u}){return n.createElement(n.Activity,{mode:n.useSyncExternalStore(a.subscribe,()=>s,()=>"hidden")},u)}};return a});return n.useInsertionEffect(()=>(t.mounted=!0,queueMicrotask(()=>t.sync(!1)),()=>{t.mounted=!1,queueMicrotask(()=>t.sync(!1))}),[t]),n.useLayoutEffect(()=>(t.connected=!0,t.sync(!1),()=>{t.connected=!1,t.sync(!0)}),[t]),t.Bridge}exports.FiberProvider=h;exports.traverseFiber=f;exports.useActivityBridge=N;exports.useContainer=g;exports.useContextBridge=A;exports.useContextMap=w;exports.useFiber=d;exports.useNearestChild=E;exports.useNearestParent=C;
|
||||
//# sourceMappingURL=index.cjs.map
|
||||
+1
File diff suppressed because one or more lines are too long
+93
@@ -0,0 +1,93 @@
|
||||
import React from 'react';
|
||||
import type ReactReconciler from 'react-reconciler';
|
||||
/**
|
||||
* Represents a react-internal Fiber node.
|
||||
*/
|
||||
export type Fiber<T = any> = Omit<ReactReconciler.Fiber, 'stateNode'> & {
|
||||
stateNode: T;
|
||||
};
|
||||
/**
|
||||
* Represents a {@link Fiber} node selector for traversal.
|
||||
*/
|
||||
export type FiberSelector<T = any> = (
|
||||
/** The current {@link Fiber} node. */
|
||||
node: Fiber<T | null>) => boolean | void;
|
||||
/**
|
||||
* Traverses up or down a {@link Fiber}, return `true` to stop and select a node.
|
||||
*/
|
||||
export declare function traverseFiber<T = any>(
|
||||
/** Input {@link Fiber} to traverse. */
|
||||
fiber: Fiber | undefined,
|
||||
/** Whether to ascend and walk up the tree. Will walk down if `false`. */
|
||||
ascending: boolean,
|
||||
/** A {@link Fiber} node selector, returns the first match when `true` is passed. */
|
||||
selector: FiberSelector<T>): Fiber<T> | undefined;
|
||||
/**
|
||||
* A react-internal {@link Fiber} provider. This component binds React children to the React Fiber tree. Call its-fine hooks within this.
|
||||
*/
|
||||
export declare class FiberProvider extends React.Component<{
|
||||
children?: React.ReactNode;
|
||||
}> {
|
||||
private _reactInternals;
|
||||
render(): React.JSX.Element;
|
||||
}
|
||||
/**
|
||||
* Returns the current react-internal {@link Fiber}. This is an implementation detail of [react-reconciler](https://github.com/facebook/react/tree/main/packages/react-reconciler).
|
||||
*/
|
||||
export declare function useFiber(): Fiber<null> | undefined;
|
||||
/**
|
||||
* Represents a react-reconciler container instance.
|
||||
*/
|
||||
export interface ContainerInstance<T = any> {
|
||||
containerInfo: T;
|
||||
}
|
||||
/**
|
||||
* Returns the current react-reconciler container info passed to {@link ReactReconciler.Reconciler.createContainer}.
|
||||
*
|
||||
* In react-dom, a container will point to the root DOM element; in react-three-fiber, it will point to the root Zustand store.
|
||||
*/
|
||||
export declare function useContainer<T = any>(): T | undefined;
|
||||
/**
|
||||
* Returns the nearest react-reconciler child instance or the node created from {@link ReactReconciler.HostConfig.createInstance}.
|
||||
*
|
||||
* In react-dom, this would be a DOM element; in react-three-fiber this would be an instance descriptor.
|
||||
*/
|
||||
export declare function useNearestChild<T = any>(
|
||||
/** An optional element type to filter to. */
|
||||
type?: keyof React.JSX.IntrinsicElements): React.RefObject<T | undefined>;
|
||||
/**
|
||||
* Returns the nearest react-reconciler parent instance or the node created from {@link ReactReconciler.HostConfig.createInstance}.
|
||||
*
|
||||
* In react-dom, this would be a DOM element; in react-three-fiber this would be an instance descriptor.
|
||||
*/
|
||||
export declare function useNearestParent<T = any>(
|
||||
/** An optional element type to filter to. */
|
||||
type?: keyof React.JSX.IntrinsicElements): React.RefObject<T | undefined>;
|
||||
export type ContextMap = Map<React.Context<any>, any> & {
|
||||
get<T>(context: React.Context<T>): T | undefined;
|
||||
};
|
||||
/**
|
||||
* Returns a map of all contexts and their values.
|
||||
*/
|
||||
export declare function useContextMap(): ContextMap;
|
||||
/**
|
||||
* Represents a react-context bridge provider component.
|
||||
*/
|
||||
export type ContextBridge = React.FC<React.PropsWithChildren<{}>>;
|
||||
/**
|
||||
* React 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 {@link ContextBridge} of live context providers to pierce Context across renderers.
|
||||
*
|
||||
* Pass {@link ContextBridge} as a component to a secondary renderer to enable context-sharing within its children.
|
||||
*/
|
||||
export declare function useContextBridge(): ContextBridge;
|
||||
/** A component that forwards ancestor Activity visibility into another React root. */
|
||||
export type ActivityBridge = React.FC<React.PropsWithChildren<{}>>;
|
||||
/**
|
||||
* Forwards ancestor Activity visibility into another root. Requires React 19.2+,
|
||||
* an Activity capable destination renderer, and a {@link FiberProvider}.
|
||||
*
|
||||
* Suspense does not hide the destination. While Suspense hides the source,
|
||||
* visibility is sampled once per frame and changes between samples can be missed.
|
||||
* Source deletion hides the destination without unmounting its root.
|
||||
*/
|
||||
export declare function useActivityBridge(): ActivityBridge;
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
import r from "react";
|
||||
const v = /* @__PURE__ */ (() => {
|
||||
var e, t;
|
||||
return typeof window != "undefined" && (((e = window.document) == null ? void 0 : e.createElement) || ((t = window.navigator) == null ? void 0 : t.product) === "ReactNative");
|
||||
})() ? r.useLayoutEffect : r.useEffect;
|
||||
function l(e, t, i) {
|
||||
if (!e) return;
|
||||
if (i(e) === !0) return e;
|
||||
let n = t ? e.return : e.child;
|
||||
for (; n; ) {
|
||||
const o = l(n, t, i);
|
||||
if (o) return o;
|
||||
n = t ? null : n.sibling;
|
||||
}
|
||||
}
|
||||
function b(e) {
|
||||
try {
|
||||
return Object.defineProperties(e, {
|
||||
_currentRenderer: {
|
||||
get() {
|
||||
return null;
|
||||
},
|
||||
set() {
|
||||
}
|
||||
},
|
||||
_currentRenderer2: {
|
||||
get() {
|
||||
return null;
|
||||
},
|
||||
set() {
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (t) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
const p = /* @__PURE__ */ b(/* @__PURE__ */ r.createContext(null));
|
||||
class h extends r.Component {
|
||||
render() {
|
||||
return /* @__PURE__ */ r.createElement(p.Provider, { value: this._reactInternals }, this.props.children);
|
||||
}
|
||||
}
|
||||
function m() {
|
||||
const e = r.useContext(p);
|
||||
if (e === null) throw new Error("its-fine: useFiber must be called within a <FiberProvider />!");
|
||||
const t = r.useId();
|
||||
return r.useMemo(() => {
|
||||
for (const n of [e, e == null ? void 0 : e.alternate]) {
|
||||
if (!n) continue;
|
||||
const o = l(n, !1, (d) => {
|
||||
let s = d.memoizedState;
|
||||
for (; s; ) {
|
||||
if (s.memoizedState === t) return !0;
|
||||
s = s.next;
|
||||
}
|
||||
});
|
||||
if (o) return o;
|
||||
}
|
||||
}, [e, t]);
|
||||
}
|
||||
function C() {
|
||||
const e = m(), t = r.useMemo(
|
||||
() => l(e, !0, (i) => {
|
||||
var n;
|
||||
return ((n = i.stateNode) == null ? void 0 : n.containerInfo) != null;
|
||||
}),
|
||||
[e]
|
||||
);
|
||||
return t == null ? void 0 : t.stateNode.containerInfo;
|
||||
}
|
||||
function F(e) {
|
||||
const t = m(), i = r.useRef(void 0);
|
||||
return v(() => {
|
||||
var n;
|
||||
i.current = (n = l(
|
||||
t,
|
||||
!1,
|
||||
(o) => typeof o.type == "string" && (e === void 0 || o.type === e)
|
||||
)) == null ? void 0 : n.stateNode;
|
||||
}, [t]), i;
|
||||
}
|
||||
function R(e) {
|
||||
const t = m(), i = r.useRef(void 0);
|
||||
return v(() => {
|
||||
var n;
|
||||
i.current = (n = l(
|
||||
t,
|
||||
!0,
|
||||
(o) => typeof o.type == "string" && (e === void 0 || o.type === e)
|
||||
)) == null ? void 0 : n.stateNode;
|
||||
}, [t]), i;
|
||||
}
|
||||
const w = Symbol.for("react.context"), E = (e) => e !== null && typeof e == "object" && "$$typeof" in e && e.$$typeof === w;
|
||||
function g() {
|
||||
const e = m(), [t] = r.useState(() => /* @__PURE__ */ new Map());
|
||||
t.clear();
|
||||
let i = e;
|
||||
for (; i; ) {
|
||||
const n = i.type;
|
||||
E(n) && n !== p && !t.has(n) && t.set(n, r.use(b(n))), i = i.return;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
function M() {
|
||||
const e = g();
|
||||
return r.useMemo(
|
||||
() => Array.from(e.keys()).reduce(
|
||||
(t, i) => (n) => /* @__PURE__ */ r.createElement(t, null, /* @__PURE__ */ r.createElement(i.Provider, { ...n, value: e.get(i) })),
|
||||
(t) => /* @__PURE__ */ r.createElement(h, { ...t })
|
||||
),
|
||||
[e]
|
||||
);
|
||||
}
|
||||
function x(e) {
|
||||
if (typeof requestAnimationFrame == "function") {
|
||||
const i = requestAnimationFrame(e);
|
||||
return () => cancelAnimationFrame(i);
|
||||
}
|
||||
const t = setTimeout(e, 16);
|
||||
return () => clearTimeout(t);
|
||||
}
|
||||
function N() {
|
||||
if (!r.Activity) throw new Error("its-fine: useActivityBridge requires React 19.2 or later!");
|
||||
const e = m(), [t] = r.useState(() => {
|
||||
const i = [];
|
||||
let n = !1;
|
||||
l(e, !0, (u) => {
|
||||
var c, a;
|
||||
if (u.elementType === r.Activity) {
|
||||
const y = ((c = u.child) == null ? void 0 : c.tag) === 22 ? u.child.stateNode : null;
|
||||
if (typeof (y == null ? void 0 : y._visibility) != "number")
|
||||
throw new Error("its-fine: unsupported React Activity internals!");
|
||||
i.push(y);
|
||||
} else u.tag === 22 && ((a = u.return) == null ? void 0 : a.elementType) !== r.Activity && (n = !0);
|
||||
});
|
||||
let o = "hidden";
|
||||
const d = /* @__PURE__ */ new Set();
|
||||
let s;
|
||||
const f = {
|
||||
mounted: !1,
|
||||
connected: !1,
|
||||
subscribe(u) {
|
||||
return d.add(u), () => {
|
||||
d.delete(u);
|
||||
};
|
||||
},
|
||||
sync(u) {
|
||||
f.mounted && !f.connected && n && i.length > 0 ? s || (s = x(() => {
|
||||
s = void 0, f.sync(!0);
|
||||
})) : (s == null || s(), s = void 0);
|
||||
let c = o;
|
||||
if (f.mounted ? f.connected ? c = "visible" : u && (c = i.every((a) => (a._visibility & 1) !== 0) ? "visible" : "hidden") : c = "hidden", o !== c) {
|
||||
o = c;
|
||||
for (const a of d) a();
|
||||
}
|
||||
},
|
||||
Bridge({ children: u }) {
|
||||
return /* @__PURE__ */ r.createElement(
|
||||
r.Activity,
|
||||
{
|
||||
mode: r.useSyncExternalStore(
|
||||
f.subscribe,
|
||||
() => o,
|
||||
() => "hidden"
|
||||
)
|
||||
},
|
||||
u
|
||||
);
|
||||
}
|
||||
};
|
||||
return f;
|
||||
});
|
||||
return r.useInsertionEffect(() => (t.mounted = !0, queueMicrotask(() => t.sync(!1)), () => {
|
||||
t.mounted = !1, queueMicrotask(() => t.sync(!1));
|
||||
}), [t]), r.useLayoutEffect(() => (t.connected = !0, t.sync(!1), () => {
|
||||
t.connected = !1, t.sync(!0);
|
||||
}), [t]), t.Bridge;
|
||||
}
|
||||
export {
|
||||
h as FiberProvider,
|
||||
l as traverseFiber,
|
||||
N as useActivityBridge,
|
||||
C as useContainer,
|
||||
M as useContextBridge,
|
||||
g as useContextMap,
|
||||
m as useFiber,
|
||||
F as useNearestChild,
|
||||
R as useNearestParent
|
||||
};
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# Installation
|
||||
> `npm install --save @types/react-reconciler`
|
||||
|
||||
# Summary
|
||||
This package contains type definitions for react-reconciler (https://reactjs.org/).
|
||||
|
||||
# Details
|
||||
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-reconciler.
|
||||
|
||||
### Additional Details
|
||||
* Last updated: Wed, 11 Dec 2024 14:36:56 GMT
|
||||
* Dependencies: none
|
||||
* Peer dependencies: [@types/react](https://npmjs.com/package/@types/react)
|
||||
|
||||
# Credits
|
||||
These definitions were written by [Nathan Bierema](https://github.com/Methuselah96), [Zhang Haocong](https://github.com/zhanghaocong), and [Mathieu Dutour](https://github.com/mathieudutour).
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
export const DiscreteEventPriority = 0b0000000000000000000000000000001;
|
||||
export const ContinuousEventPriority = 0b0000000000000000000000000000100;
|
||||
export const DefaultEventPriority = 0b0000000000000000000000000010000;
|
||||
export const IdleEventPriority = 0b0100000000000000000000000000000;
|
||||
export const LegacyRoot = 0;
|
||||
export const ConcurrentRoot = 1;
|
||||
+1028
File diff suppressed because it is too large
Load Diff
+38
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "@types/react-reconciler",
|
||||
"version": "0.28.9",
|
||||
"description": "TypeScript definitions for react-reconciler",
|
||||
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/react-reconciler",
|
||||
"license": "MIT",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Nathan Bierema",
|
||||
"githubUsername": "Methuselah96",
|
||||
"url": "https://github.com/Methuselah96"
|
||||
},
|
||||
{
|
||||
"name": "Zhang Haocong",
|
||||
"githubUsername": "zhanghaocong",
|
||||
"url": "https://github.com/zhanghaocong"
|
||||
},
|
||||
{
|
||||
"name": "Mathieu Dutour",
|
||||
"githubUsername": "mathieudutour",
|
||||
"url": "https://github.com/mathieudutour"
|
||||
}
|
||||
],
|
||||
"main": "",
|
||||
"types": "index.d.ts",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||
"directory": "types/react-reconciler"
|
||||
},
|
||||
"scripts": {},
|
||||
"dependencies": {},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*"
|
||||
},
|
||||
"typesPublisherContentHash": "08ff2948d78f7616f151a26a7f4a9f847bd190e3ea194516a4dc517cea40cb6e",
|
||||
"typeScriptVersion": "5.0"
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "its-fine",
|
||||
"version": "2.1.1",
|
||||
"description": "A collection of escape hatches for React.",
|
||||
"keywords": [
|
||||
"react",
|
||||
"fiber",
|
||||
"internal",
|
||||
"reconciler",
|
||||
"hooks"
|
||||
],
|
||||
"author": "Cody Bennett (https://github.com/codyjasonbennett)",
|
||||
"maintainers": [
|
||||
"Paul Henschel (https://github.com/drcmda)"
|
||||
],
|
||||
"homepage": "https://github.com/pmndrs/its-fine",
|
||||
"repository": "https://github.com/pmndrs/its-fine",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"dist/*"
|
||||
],
|
||||
"type": "module",
|
||||
"types": "./dist/index.d.ts",
|
||||
"main": "./dist/index.cjs",
|
||||
"module": "./dist/index.js",
|
||||
"react-native": "./dist/index.js",
|
||||
"sideEffects": false,
|
||||
"devDependencies": {
|
||||
"@rsbuild/core": "2.2.9",
|
||||
"@types/node": "^22.13.4",
|
||||
"@types/react": "19.2.0",
|
||||
"@types/react-dom": "19.2.0",
|
||||
"@types/react-test-renderer": "^19.0.0",
|
||||
"jsdom": "26.1.0",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
"react-nil": "^2.0.0",
|
||||
"react-test-renderer": "19.2.0",
|
||||
"rimraf": "^6.0.1",
|
||||
"typescript": "^5.7.3",
|
||||
"vite": "^6.1.0",
|
||||
"vitest": "^3.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/react-reconciler": "^0.28.9"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^19.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rimraf dist && vite build && tsc",
|
||||
"test": "vitest run",
|
||||
"test:bundle": "node scripts/check-bundle.mjs"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user