diff --git a/packages/context/src/index.ts b/packages/context/src/index.ts index 1448525a7..5a8d806b1 100644 --- a/packages/context/src/index.ts +++ b/packages/context/src/index.ts @@ -1,4 +1,12 @@ -import { createContext, createComponent, useContext, JSX, Context, FlowComponent } from "solid-js"; +import { + Accessor, + Context, + FlowComponent, + JSX, + createComponent, + createContext, + useContext, +} from "solid-js"; import type { ContextProviderComponent } from "solid-js/types/reactive/signal"; export type ContextProviderProps = { @@ -119,3 +127,94 @@ export function MultiProvider(props }; return fn(0); } + +/** + * A utility-function to provide context to components. + * + * @param children Accessor of Children + * @param context Context + * @param value T + * + * @example + * ```tsx + * const NumberContext = createContext + * + * const children = withContext( + * () => props.children, + * NumberContext, + * 1 + * ) + * ``` + */ + +export function withContext( + children: Accessor, + context: Context, + value: T, +) { + let result: JSX.Element | JSX.Element[]; + + context.Provider({ + value, + children: (() => { + result = children(); + return ""; + }) as any as JSX.Element, + }); + + return () => result; +} + +/* + +Type validation of the `values` array thanks to the amazing @otonashixav (https://github.com/otonashixav) + +*/ + +/** + * A utility-function to provide multiple context to components. + * + * @param children Accessor of Children + * @param values Array of tuples of `[Context, value T]`. + * + * @example + * ```tsx + * const NumberContext = createContext + * const StringContext = createContext + * const children = withContext( + * () => props.children, + * [ + * [NumberContext, 1], + * [StringContext, "string"] + * ] + * ) + * ``` + */ + +export function withMultiContexts( + children: Accessor, + values: { + [K in keyof T]: readonly [Context, [T[K]][T extends unknown ? 0 : never]]; + }, +) { + let result: JSX.Element | JSX.Element[]; + + const fn = (index: number) => { + const [context, value] = values[index]!; + context.Provider({ + value, + children: (() => { + if (index < values.length - 1) { + fn(index + 1); + } else { + result = children(); + } + return ""; + }) as any as JSX.Element, + }); + }; + + fn(0); + + return () => result; +}