import { ActionCreator, Action } from 'ts-action';
import { LoaderStyle } from '@progressive-development/pd-content';
/**
* Configuration for loading state and toast messages.
*/
export interface AsyncActionConfig {
/** Unique key for identifying the loading state */
actionKey: string;
/** Text shown during loading */
loadingTxt: string;
/** Text shown on success (empty string = no toast) */
successTxt?: string;
/** Show modal overlay during loading */
modal?: boolean;
/** Show small background loader */
smallBackground?: boolean;
/** Duration for success toast in ms */
successDuration?: number;
/** Override loader style for this action (overrides app default) */
loaderStyle?: LoaderStyle;
}
/**
* Typed action creator that preserves payload type for ts-action compatibility.
* This enables proper type inference with on() and ofType().
*/
type TypedActionCreator
= ActionCreator {
type: string;
payload: P;
}>;
/**
* Action creator without payload.
*/
type TypedActionCreatorVoid = ActionCreator {
type: string;
}>;
/**
* Base interface for async action groups.
* Use this type for arrays containing groups with different payload types.
*
* @example
* ```typescript
* const allGroups: AsyncActionGroupBase[] = [
* loadProfile, // AsyncActionGroup
* sendRequest, // AsyncActionGroup
* ];
* ```
*/
export interface AsyncActionGroupBase {
/** Loading state and toast configuration */
config: AsyncActionConfig;
/** Base action type (e.g., "LOAD_PROFILE") */
baseType: string;
/** All action types for this group */
types: {
action: string;
success: string;
fail: string;
};
}
/**
* An async action group containing action, success, and fail action creators
* plus the associated configuration.
*
* The action creators preserve their full ts-action types for compatibility
* with on() and ofType().
*/
export interface AsyncActionGroup extends AsyncActionGroupBase {
/** The initiating action creator - typed for ts-action compatibility */
action: TPayload extends void ? TypedActionCreatorVoid : TypedActionCreator;
/** The success action creator - typed for ts-action compatibility */
success: TypedActionCreator;
/** The fail action creator - typed for ts-action compatibility */
fail: TypedActionCreator;
}
/**
* Options for creating an async action group.
* actionKey is derived from baseType if not provided.
*/
export type AsyncActionOptions = Omit & {
actionKey?: string;
};
/**
* Creates an async action group with action/success/fail creators and config.
*
* @param baseType - Base action type (e.g., "LOAD_PROFILE")
* @param options - Loading state and toast configuration
* @returns AsyncActionGroup with all creators and config
*
* @example
* ```typescript
* // Without payload on action
* export const loadProfile = createAsyncAction("LOAD_PROFILE", {
* loadingTxt: msg("Loading profile...", { id: "..." }),
* modal: true,
* });
*
* // With typed payloads
* export const updateProfile = createAsyncActionGroup<
* UpdateData, // Action payload
* ProfileData, // Success payload
* >("UPDATE_PROFILE", {
* loadingTxt: "Updating...",
* successTxt: "Profile updated!",
* modal: true,
* });
*
* // Usage in effect with ofType():
* actions$.pipe(
* ofType(loadProfile.action),
* mergeMap(() => profileService.load().pipe(
* map((data) => loadProfile.success(data)),
* catchError((err) => of(loadProfile.fail(err)))
* ))
* );
*
* // Usage in reducer with on():
* reducer(
* initialState,
* on(loadProfile.success, (state, { payload }) => ({
* ...state,
* profile: payload
* }))
* );
* ```
*/
export declare function createAsyncActionGroup(baseType: string, options: AsyncActionOptions): AsyncActionGroup;
/**
* Creates an async action group without payload on the initiating action.
* This is a convenience wrapper for the common case.
*
* @example
* ```typescript
* export const loadProfile = createAsyncAction("LOAD_PROFILE", {
* loadingTxt: "Loading...",
* modal: true,
* });
*
* // loadProfile.action() - no payload
* // loadProfile.success(data) - ProfileData payload
* // loadProfile.fail(error) - Error payload
* ```
*/
export declare function createAsyncAction(baseType: string, options: AsyncActionOptions): AsyncActionGroup;
/**
* Type guard to check if an action belongs to an async action group.
*/
export declare function isActionFromGroup(actionObj: Action, group: AsyncActionGroupBase): boolean;
/**
* Gets the config for an action from a list of groups.
* Returns undefined if no matching group is found.
*/
export declare function getConfigForAction(actionObj: Action, groups: AsyncActionGroupBase[]): AsyncActionConfig | undefined;
export {};
//# sourceMappingURL=async-action-utils.d.ts.map