@agnos-ui/core
Version:
Framework-agnostic headless component library.
261 lines (260 loc) • 11.2 kB
TypeScript
import type { ReadableSignal, StoreOptions, SubscribableStore, WritableSignal } from '@amadeus-it-group/tansu';
/**
* A type that maps each property of an object type `T` to either a `ReadableSignal` of that property type or the property type itself.
*
* @template T - The object type whose properties are being mapped.
*/
export type ValuesOrReadableSignals<T extends object> = {
[K in keyof T]?: ReadableSignal<T[K] | undefined> | T[K];
};
/**
* A type that maps the properties of an object type `T` to either a `WritableSignal` of the property type or the property type itself.
*
* @template T - The object type whose properties are being mapped.
*/
export type ValuesOrWritableSignals<T extends object> = {
[K in keyof T]?: WritableSignal<T[K] | undefined> | T[K];
};
/**
* Interface representing the configuration for properties.
*
* @template U - An object type representing the properties.
*/
export interface PropsConfig<U extends object> {
/**
* Object containing, for each property, either its initial value, or a store that will contain the value at any time.
* When the value of a property is undefined or invalid, the value from the config is used.
*/
props?: ValuesOrWritableSignals<U>;
/**
* Either a store of objects containing, for each property, the default value,
* or an object containing, for each property, either a store containing the default value or the default value itself.
*/
config?: ReadableSignal<Partial<U>> | ValuesOrReadableSignals<Partial<U>>;
}
/**
* Represents a generic widget with reactive state, stores, and various functionalities.
*
* @template Props - The type of the properties that can be passed to the widget.
* @template State - The type of the state managed by the widget.
* @template Api - The type of the API functions available for interacting with the widget.
* @template Actions - The type of the action handlers for user interactions.
* @template Directives - The type of the directives used in the widget's template.
*/
export interface Widget<Props extends object = object, State extends object = object, Api extends object = object, Directives extends object = object> {
/**
* the reactive state of the widget, combining all the values served by the stores
*/
state$: ReadableSignal<State>;
/**
* the different stores of the widget, all reactive
*/
stores: {
[K in keyof State as `${K & string}$`]: ReadableSignal<State[K]>;
};
/**
* Modify the parameter values, and recalculate the stores accordingly
*/
patch(parameters: Partial<Props>): void;
/**
* directives to be used on html elements in the template of the widget or in the slots
*/
directives: Directives;
/**
* all the api functions to interact with the widget
*/
api: Api;
}
/**
* Represents the context for a widget slot, providing access to the widget and its state.
*
* @template W - The type of the widget.
*
*/
export interface WidgetSlotContext<W extends Widget> extends Pick<W, 'api' | 'directives'> {
/**
* the state of the widget
*/
state: WidgetState<W>;
}
/**
* Extracts the state type from a widget type that contains a `state$` property.
*
* @template T - A type that extends an object with a `state$` property of type `SubscribableStore<any>`.
* @returns The type of the state contained within the `state$` property if it extends an object, otherwise `never`.
*/
export type WidgetState<T extends {
state$: SubscribableStore<any>;
}> = T extends {
state$: SubscribableStore<infer U extends object>;
} ? U : never;
/**
* Extracts the type of the argument expected by the `patch` method of a given type `T`.
*
* This utility type takes a generic type `T` which must have a `patch` method. The `patch` method
* should accept an argument that is a partial of some object type `U`. If `T` meets this condition,
* `WidgetProps` will resolve to the type `U`. Otherwise, it will resolve to `never`.
*
* @template T - A type that includes a `patch` method accepting a partial object.
*/
export type WidgetProps<T extends {
patch: (arg: any) => void;
}> = T extends {
patch: (arg: Partial<infer U extends object>) => void;
} ? U : never;
/**
* A unique symbol representing a widget factory widget name.
*/
export declare const FACTORY_WIDGET_NAME: unique symbol;
/**
* A factory function type for creating instances of a widget.
*
* @template W - The type of the widget that extends the base Widget type.
* @template T - The type of the factory function that creates the widget. Useful when the factory function has a generic
* @param props - Optional configuration properties for the widget.
* @returns An instance of the widget.
*/
export type WidgetFactory<W extends Widget, T extends (props?: PropsConfig<WidgetProps<W>>) => W = (props?: PropsConfig<WidgetProps<W>>) => W> = T & {
[FACTORY_WIDGET_NAME]?: string;
};
/**
* Represents a server-side rendered HTML element with limited functionality.
*
* This interface extends a subset of the {@link HTMLElement} interface, providing
* methods to set and remove attributes, manipulate the element's classes, and
* partially manipulate the element's style.
*
* It inherits the {@link https://developer.mozilla.org/docs/Web/API/Element/setAttribute | setAttribute} and {@link https://developer.mozilla.org/docs/Web/API/Element/getAttribute | getAttribute} methods from the {@link HTMLElement} interface.
*
*/
export interface SSRHTMLElement extends Pick<HTMLElement, 'setAttribute' | 'removeAttribute'> {
/**
* Object allowing to manipulate the classes of the element.
*/
classList: Pick<HTMLElement['classList'], 'add' | 'remove' | 'toggle'>;
/**
* Object allowing to manipulate the style of the element.
*/
style: Partial<Record<StyleKey, StyleValue>>;
}
/**
* Represents a directive function that can be applied to an SSRHTMLElement.
*
* @template T - The type of the arguments passed to the directive.
* @template U - The type of the SSRHTMLElement, defaults to SSRHTMLElement.
*
* @param node - The SSRHTMLElement to which the directive is applied.
* @param args - The arguments passed to the directive.
*
* @returns An optional object that may contain:
* - `update`: A function to update the directive with new arguments.
* - `destroy`: A function to clean up when the directive is no longer needed.
*/
export type Directive<T = void, U extends SSRHTMLElement = SSRHTMLElement> = (node: U, args: T) => void | {
update?: (args: T) => void;
destroy?: () => void;
};
/**
* Represents a tuple containing a directive and its associated parameter.
*
* @template T - The type of the parameter associated with the directive.
* @template U - The type of the SSRHTMLElement, defaults to SSRHTMLElement.
*/
export type DirectiveAndParam<T, U extends SSRHTMLElement = SSRHTMLElement> = [Directive<T, U>, T];
/**
* Represents a mapping of directives and their optional parameters.
*
* @template T - An array type representing the parameters for the directives.
* @template U - The type of the SSR HTML element, defaults to `SSRHTMLElement`.
*/
export type DirectivesAndOptParam<T extends any[], U extends SSRHTMLElement = SSRHTMLElement> = {
[K in keyof T]: Directive<void, U> | DirectiveAndParam<T[K], U>;
};
/**
* Represents the content that can be used in a slot.
* The content can be one of the following:
* - `undefined`
* - `null`
* - A `string`
* - A function that takes `props` of type `Props` and returns a `string`
*
* @template Props - The type of the props when the slot is a function
*/
export type SlotContent<Props extends object = object> = undefined | null | string | ((props: Props) => string);
/**
* A unique symbol representing an invalid value.
* This can be used as a sentinel value to indicate that a variable or property
* does not hold a valid value.
*/
export declare const INVALID_VALUE: unique symbol;
/**
* A type alias for a function that normalizes a value of type `T`.
* The function takes a value of type `T` and returns either a normalized value of type `T`
* or a special constant `INVALID_VALUE` indicating that the value is invalid.
*
* @template T - The type of the value to be normalized.
* @param value - The value to be normalized.
* @returns The normalized value of type `T` or `INVALID_VALUE` if the value is invalid.
*/
export type NormalizeValue<T> = (value: T) => T | typeof INVALID_VALUE;
/**
* Interface representing options for a writable store with default values.
*
* @template T - The type of the value stored.
*/
export interface WritableWithDefaultOptions<T> {
/**
* the normalize value function. should return the {@link INVALID_VALUE} symbol when the provided value is invalid
*/
normalizeValue?: NormalizeValue<T>;
/**
* the equal function, allowing to compare two values. used to check if a previous and current values are equals.
*/
equal?: StoreOptions<T>['equal'];
}
/**
* Represents a type that validates a configuration object.
*
* @template T - The type of the configuration object to be validated.
*
* This type maps each key of the configuration object `T` to an optional
* `WritableWithDefaultOptions` type, allowing for partial validation.
*/
export type ConfigValidator<T extends object> = {
[K in keyof T]: WritableWithDefaultOptions<T[K]> | undefined;
};
/**
* Represents a value that can be assigned to an attribute.
*/
export type AttributeValue = string | number | boolean | undefined;
/**
* Represents a key of the CSSStyleDeclaration interface, excluding certain properties and methods.
*
* This is useful for scenarios where you need to work with CSS properties directly without
* dealing with the methods and other non-style properties of CSSStyleDeclaration.
*/
export type StyleKey = Exclude<keyof CSSStyleDeclaration, 'length' | 'item' | 'parentRule' | 'getPropertyValue' | 'getPropertyPriority' | 'setProperty' | 'removeProperty' | typeof Symbol.iterator | number | 'cssText'>;
/**
* Represents a value that can be used for styling purposes.
* @remarks
* This type can be a string representing a style value, or it can be undefined or null.
* It is useful for scenarios where a style value might be optional or not set.
*/
export type StyleValue = string | undefined | null;
/**
* A conditional type that checks if type `T` extends type `U`.
* @template T - The type to check.
* @template U - The type to check against.
* @returns `1` if `T` extends `U`, otherwise `0`.
*/
export type Extends<T, U> = T extends U ? 1 : 0;
/**
* Type utility to determine if a given type `T` is or extends `SlotContent<any>`.
*
* This utility uses conditional types to check if `T` extends `SlotContent<any>` or if `SlotContent<any>` extends `T`.
* If either condition is true, it returns `T`, otherwise it returns `0`.
*
* @template T - The type to be checked.
* @returns `T` if `T` is or extends `SlotContent<any>`, otherwise `0`.
*/
export type IsSlotContent<T> = Extends<T, SlotContent<any>> | Extends<SlotContent<any>, T> extends 1 ? T : 0;