UNPKG

@tempots/dom

Version:

Fully-typed frontend framework alternative to React and Angular

92 lines (91 loc) 3.66 kB
import { TNode, Renderable } from '../types/domain'; import { Signal } from '../std/signal'; import { Value } from '../std/value'; export type NillifyValue<T> = Value<T | null | undefined> | Value<T | undefined> | Value<T | null>; export type Id<T> = {} & { [P in keyof T]: T[P]; }; export type Merge<A, B> = Id<A & B>; export type NonNillable<T> = Merge<T, {}>; /** * Conditionally renders content based on whether a value is non-null/non-undefined. * * This function provides a type-safe way to handle nullable values in your UI. It only * renders the `then` content when the value is not null or undefined, and optionally * renders alternative content when the value is null/undefined. * * @example * ```typescript * // With a signal that might be null * const user = prop<User | null>(null) * * Ensure(user, * (userSignal) => html.div('Welcome, ', userSignal.map(u => u.name)), * () => html.div('Please log in') * ) * ``` * * @example * ```typescript * // With a literal value * const maybeData = getData() // returns string | null * * Ensure(maybeData, * (dataSignal) => html.div('Data: ', dataSignal), * () => html.div('No data available') * ) * ``` * * @typeParam T - The type of the value when it's not null/undefined * @param value - A signal or literal value that may be null or undefined * @param then - Function that receives a signal of the non-nullable value and returns content to render * @param otherwise - Optional function that returns content to render when value is null/undefined * @returns A renderable that conditionally displays content based on the value's nullability * @public */ export declare const Ensure: <T>(value: NillifyValue<T>, then: (value: Signal<NonNillable<T>>) => TNode, otherwise?: () => TNode) => Renderable; /** * Conditionally renders content only when ALL provided values are non-null/non-undefined. * * This function is useful when you need multiple values to be present before rendering content. * It waits for all values to be non-null/non-undefined before calling the callback function. * If any value becomes null/undefined, it will render the `otherwise` content instead. * * @example * ```typescript * const user = prop<User | null>(null) * const profile = prop<Profile | null>(null) * const settings = prop<Settings | null>(null) * * EnsureAll(user, profile, settings)( * (userSignal, profileSignal, settingsSignal) => html.div( * html.h1('Dashboard'), * html.div('User: ', userSignal.map(u => u.name)), * html.div('Profile: ', profileSignal.map(p => p.bio)), * html.div('Theme: ', settingsSignal.map(s => s.theme)) * ), * () => html.div('Loading user data...') * ) * ``` * * @example * ```typescript * // Mix of signals and literal values * const apiData = prop<Data | null>(null) * const staticConfig = { theme: 'dark' } * * EnsureAll(apiData, staticConfig)( * (dataSignal, configSignal) => html.div( * 'Data loaded with theme: ', * configSignal.map(c => c.theme) * ), * () => html.div('Waiting for data...') * ) * ``` * * @typeParam T - Tuple type representing the types of all input values * @param signals - Variable number of values (signals or literals) that may be null/undefined * @returns A function that takes a callback and optional otherwise function, returning a renderable * @public */ export declare const EnsureAll: <T extends readonly Value<any>[]>(...signals: { [K in keyof T]: NillifyValue<T[K]>; }) => (callback: (...values: { [K in keyof T]: Signal<NonNillable<T[K] extends Value<infer U> ? U : never>>; }) => TNode, otherwise?: () => TNode) => Renderable;