diff --git a/packages/effect-fc/src/Async.ts b/packages/effect-fc/src/Async.ts index 98ec0e9..527d1af 100644 --- a/packages/effect-fc/src/Async.ts +++ b/packages/effect-fc/src/Async.ts @@ -4,42 +4,21 @@ import * as React from "react" import * as Component from "./Component.js" -/** - * A unique symbol representing the Async component type. - * Used as a type brand to identify Async components. - * - * @experimental - */ export const AsyncTypeId: unique symbol = Symbol.for("@effect-fc/Async/Async") +export type AsyncTypeId = typeof AsyncTypeId + /** - * The type of the Async type ID symbol. - */ -export type AsyncTypeId = typeof AsyncTypeId -/** - * An Async component that supports suspense and promise-based async operations. - * Combines Component behavior with Async-specific options. - * - * @example - * ```ts - * const MyAsyncComponent = async(component({ ... })) - * ``` + * A trait for `Component`'s that allows them running asynchronous effects. */ export interface Async extends AsyncPrototype, AsyncOptions {} - -/** - * The prototype object for Async components containing their methods and behaviors. - */ export interface AsyncPrototype { - /** - * The Async type ID brand. - */ readonly [AsyncTypeId]: AsyncTypeId } /** - * Configuration options for Async components. + * Configuration options for `Async` components. */ export interface AsyncOptions { /** @@ -50,34 +29,14 @@ export interface AsyncOptions { } /** - * Props for Async components, extending React.SuspenseProps without the children prop. - * The children are managed internally by the Async component. + * Props for `Async` components. */ export type AsyncProps = Omit -/** - * The prototype object for Async components. - * Provides the `asFunctionComponent` method for converting async components to React function components. - * - * @internal Use the `async` function to create Async components instead of accessing this directly. - */ export const AsyncPrototype: AsyncPrototype = Object.freeze({ [AsyncTypeId]: AsyncTypeId, - /** - * Converts an Async component to a React function component. - * - * @param runtimeRef - A reference to the Effect runtime for executing effects - * @returns A React function component that suspends while the async operation is executing - * - * @example - * ```ts - * const MyComponent = component({ ... }) - * const AsyncMyComponent = async(MyComponent) - * const FunctionComponent = AsyncMyComponent.asFunctionComponent(runtimeRef) - * ``` - */ asFunctionComponent

( this: Component.Component & Async, runtimeRef: React.RefObject>>, @@ -102,14 +61,8 @@ export const AsyncPrototype: AsyncPrototype = Object.freeze({ } as const) /** - * An equivalence function for comparing AsyncProps that ignores the `fallback` property. - * Useful for memoization and re-render optimization. - * - * @param self - The first props object to compare - * @param that - The second props object to compare - * @returns `true` if the props are equivalent (excluding fallback), `false` otherwise - * - * @internal + * An equivalence function for comparing `AsyncProps` that ignores the `fallback` property. + * Used by default by async components with `Memoized.memoized` applied. */ export const defaultPropsEquivalence: Equivalence.Equivalence = ( self: Record, @@ -136,42 +89,22 @@ export const defaultPropsEquivalence: Equivalence.Equivalence = ( } -/** - * A type guard to check if a value is an Async component. - * - * @param u - The value to check - * @returns `true` if the value is an Async component, `false` otherwise - * - * @example - * ```ts - * if (isAsync(component)) { - * // component is an Async component - * } - * ``` - */ export const isAsync = (u: unknown): u is Async => Predicate.hasProperty(u, AsyncTypeId) /** - * Converts a Component into an Async component that supports suspense and promise-based async operations. - * - * The resulting component will wrap the original component with React.Suspense, - * allowing async Effect computations to suspend and resolve properly. + * Converts a Component into an `Async` component that supports running asynchronous effects. * * Note: The component cannot have a prop named "promise" as it's reserved for internal use. * * @param self - The component to convert to an Async component - * @returns An Async component with the same body, error, and context types as the input + * @returns A new Async component with the same body, error, and context types as the input * * @example * ```ts - * const MyComponent = component({ - * body: (props) => // ... - * }) - * - * const AsyncMyComponent = async(MyComponent) + * const MyAsyncComponent = Component.make("MyComponent")(function*() { ... }).pipe( + * Async.async, + * ) * ``` - * - * @throws Will produce a type error if the component has a "promise" prop */ export const async = >( self: T & ( @@ -207,14 +140,19 @@ export const async = >( * * @example * ```ts - * const AsyncComponent = async(myComponent) + * // Curried + * const MyAsyncComponent = Component.make("MyComponent")(function*() { ... }).pipe( + * Async.async, + * Async.withOptions({ defaultFallback:

Loading...

}), + * ) * * // Uncurried - * const configured = withOptions(AsyncComponent, { defaultFallback: }) - * - * // Curried - * const configurer = withOptions({ defaultFallback: }) - * const configured = configurer(AsyncComponent) + * const MyAsyncComponent = Component.make("MyComponent")(function*() { ... }).pipe( + * Async.async, + * ) + * const MyAsyncComponentWithOptions = Async.withOptions(MyAsyncComponent, { + * defaultFallback:

Loading...

, + * }) * ``` */ export const withOptions: {