/** * Defines the type for acceptable targets for mounting *CollageJS* pieces. */ export type AcceptableTarget = HTMLElement | ShadowRoot; /** * Properties passed to `mount()` functions of `CorePiece` objects. It extends the piece's supported objects with a * property of type `symbol` that carries the piece parent's `mountPiece()` function. */ export type MountProps = Record> = TProps & { [x: symbol]: MountPiece; }; /** * Defines the acceptable falsy values that can pass as a "valid" lifecycle function for DX purposes. The values are * merely skipped in the relevant algorithms. */ export type FalsyLifecycle = undefined | null | false; /** * Signature for unmount (cleanup) functions, including the ones returned by `CorePiece.mount()`. */ export type UnmountFn = () => Promise; /** * Type that defines the signature of the functions accepted in `CorePiece.mount`. * @param target The HTML or shadow root target where the piece will be mounted as a child. * @param props The piece's initial property values. * @returns A promise to the cleanup function that unmounts the piece. */ export type MountFn = Record> = (target: AcceptableTarget, props: MountProps) => Promise; /** * Supported return values of `CorePiece.relocate` functions. */ export type RelocationResultValue = 'supported' | 'unsupported' | 'done'; /** * Defines the signature of rollback functions that can be returned by `CorePiece.relocate` functions. These functions * can be provided when returning `done` or `supported` from a relocation function, and will be called if the * relocation chain fails. * @returns A promise that resolves once the rollback process concludes. */ export type RelocationRollbackFn = () => Promise; /** * Defines the possible return values of `CorePiece.relocate`. */ export type RelocationResult = RelocationResultValue | readonly [Exclude, RelocationRollbackFn]; /** * Type that defines the signature of the functions accepted in `CorePiece.relocate`. * @param parent The current parent of the piece's root element(s). * @param newParent The new parent where the piece's root element(s) will be relocated. * @returns A promise that resolves to one of the acceptable values. See `RelocationResult` and related types for * details. */ export type RelocateFn = (parent: AcceptableTarget, newParent: AcceptableTarget) => Promise; /** * Type that defines the signature of the functions accepted in `CorePiece.update`. * @param props The new property values for the mounted piece. * @returns A promise that resolves once the process of updating property values concludes. */ export type UpdateFn = Record> = (props: Partial) => Promise; /** * Defines the accepted shapes for `CorePiece.mount`. */ export type Mount = Record> = MountFn | FalsyLifecycle | (MountFn | FalsyLifecycle)[] | Mount[]; /** * Defines the accepted shapes for `CorePiece.update`. */ export type Update = Record> = UpdateFn | FalsyLifecycle | (UpdateFn | FalsyLifecycle)[] | Update[]; /** * Defines the accepted shapes for `CorePiece.relocate`. */ export type Relocate = RelocateFn | FalsyLifecycle | (RelocateFn | FalsyLifecycle)[] | Relocate[]; /** * Defines the base metadata interface of `CorePiece` objects. *CollageJS* projects are free to extend this interface * with their own metadata properties, making sure the stock properties remain untouched. */ export interface CorePieceMeta { /** * Informative only: Indicates that the piece can be mounted more than once. * * Since `@collagejs/core` never injects code into `CorePiece` objects, it cannot enforce this behavior. The * only place where this can be enforced is at `CorePiece.mount`. The core library provides the `preventRemount()` * function to help developers create mount functions that throw an error if called more than once. * * **💡TIP**: Official framework adapters provide this functionality by explicitly setting this meta value to * `false` when calling the adapter's `buildPiece` function. */ remountable?: boolean; /** * Informative only: Indicates that the piece can be relocated to a new parent without unmounting, or that at least * it is its intention. * * **💡TIP**: Official framework adapters always set this property according to the options specified during core * piece construction. * * ### Composition of the `relocate` Lifecycle Function * * Because lifecycle functions can be composed by stacking functions in an array, the mere existence of a `relocate` * function in a `CorePiece` object does not guarantee that the piece can be relocated. The piece may have been * composed with other functionality, maybe even a layer that attempts to give the piece relocation capabilities. * * There are many other cases, but in short: Composition code should use this property to decide whether to * compose the `relocate` lifecycle function or not, and should explicitly change its value to reflect the end * result of the composition process, assuming it took place. */ relocatable?: boolean | undefined; } /** * Defines the contract that objects must follow in order to be mountable as *CollageJS* pieces (micro-frontends). */ export interface CorePiece = Record, TMeta extends Record = {}> { /** * Mounts the piece (micro-frontend) in the document. Every mount function should always return a cleanup function * that, when called, unmounts the piece. */ mount: Mount; /** * Updates the piece property values. This is optional. If not provided, the piece won't support property updates * while mounted in the document, and all property values must have been passed during mounting. */ update?: Update; /** * Either relocates the root element(s) of the piece to a new parent, or prepares the piece for relocation. This * is optional. If not provided, the piece won't support relocation of its root element(s) to a new parent, and * the piece will be unmounted and remounted instead in pertinent cases. * * ### Return Values * * + `done`: The relocation succeeded and was made entirely by the piece. * + `unsupported`: The piece does not support relocation. * + `supported`: The piece supports relocation, but the relocation must be performed by the caller. * * Additionally, the values `done` and `supported` can be returned as a tuple with a rollback function that will be * called if the relocation chain fails after this function has returned `done` or `supported`. * * ### Rollback Functions * * If a relocation function returns a rollback function, it will be called if any of the following occurs: * * + Another relocation function returns `unsupported` after this one returned `done` or `supported`. * + Another relocation function throws an error after this one returned `done` or `supported`. * * ### When Using Multiple Relocation Functions * * If multiple relocation functions are provided, they will be called in order: * * + If the first of them returns `unsupported`, the relocation process will stop. * + If all of them return `done`, the relocation is considered successful. * + If any of them returns `'supported'`, the remaining functions are still called, but the caller will * run its relocation process after all functions have been called, even if they return `'done'`. * + If any of them returns `unsupported` after one or more of them returned `'supported'` or `done` without a * rollback function, the piece's state is considered inconsistent and an error will be thrown. */ relocate?: Relocate; /** * Carries the core piece's metadata. This is optional, but when provided, *CollageJS* libraries will attempt to * use its information depending on the situation and available data. * * ### Official Framework Adapters * * Framework adapters make use of the stock `meta.remountable` property to conditionally enforce the behavior, * taking into account the individual framework's features. Official framework adapters are therefore free to * choose which default value for `meta.remountable` they will use while creating `CorePiece` objects. * * Still, if the value of `meta.remountable` is explicitly set to `false`, the framework adapter will enforce the * behavior by injecting the `preventRemount()` function at the beginning of the `CorePiece.mount` array. */ readonly meta?: CorePieceMeta & TMeta; } /** * Defines the shape of the object returned by the process of mounting a `CorePiece` object. */ export interface MountedPiece = Record, TMeta extends Record = {}> { /** * Function used to apply updated property values to the mounted `CorePiece` object. */ update: UpdateFn; /** * Function used to unmount the `CorePiece` object. */ unmount: UnmountFn; /** * Function used to relocate the `CorePiece` object to a new parent without unmounting. */ relocate: (source: AcceptableTarget, target: AcceptableTarget, customRelocate?: (source: AcceptableTarget, target: AcceptableTarget) => Promise) => Promise; /** * The version of the global `mountPiece` function that tracks mounted children so their unmounting is * synchronized with this piece's unmount event. * * **IMPORTANT:** Always use this function instead of the global `mountPiece` function when mounting other * `CorePiece` objects inside the mounted `CorePiece` object to prevent lifecycle issues. */ mountPiece = Record, UMeta extends Record = {}>(piece: CorePiece | Promise>, target: AcceptableTarget, props?: UProps): Promise>; /** * The declared metadata of the mounted `CorePiece` object. */ readonly meta: (CorePieceMeta & TMeta) | undefined; } /** * Type definition for the `mountPiece` functions that mount *CollageJS* pieces in the HTML document. * * **NOTE:** There is a global `mountPiece` function, and then every mounted *CollageJS* piece that gets mounted * generates a version of the global function that works identically, except that it tracks the `CollageJS` pieces * mounted with it so these are unmounted automatically as soon as the parent is unmounted. * @param piece `CorePiece` object to mount in the provided target, or a promise that resolves said object. * @param target HTML element or shadow root where to mount. * @param props Optional properties for the `CorePiece` object. */ export type MountPiece = Record, TMeta extends Record = {}> = (piece: CorePiece | Promise>, target: AcceptableTarget, props?: TProps) => Promise>; declare global { /** * Defines the features in the global `CollageJs` object. */ interface CollageJs { } /** * Global object that provides functionality outside bundling. */ var CollageJs: CollageJs; }