import { Effect, Schema } from 'effect';
import type { InjectionKey, Ref } from 'vue';
/** A descendant button asking an ancestor instance to run an operation. */
export type OpRequest = Readonly<{
    /** Instance id of the ancestor that should handle this request. */
    target: string;
    /** Operation id from that component type's capability manifest. */
    operation: string;
}>;
/**
 * The persisted form of a trigger — one stored row addressing an ancestor
 * instance's operation. At runtime each row is dispatched verbatim as an
 * `OpRequest`.
 */
export declare const Trigger: Schema.Struct<{
    target: Schema.refine<string, typeof Schema.String>;
    operation: Schema.SchemaClass<string, string, never>;
}>;
/**
 * An ordered list of triggers. A button that fires triggers embeds this as
 * one of its own config fields — re-annotated for that button's own
 * semantics (e.g. a network button's "请求成功后" / "请求失败后"). There is no
 * host-level trigger field; what triggers a button carries, and when they
 * fire, is decided by the button type. List order is execution order.
 */
export declare const Triggers: Schema.Array$<Schema.Struct<{
    target: Schema.refine<string, typeof Schema.String>;
    operation: Schema.SchemaClass<string, string, never>;
}>>;
/** One stored trigger row. */
export type TriggerValue = Schema.Schema.Type<typeof Trigger>;
/**
 * One node of the bubbling channel. `dispatch` runs the matching operation
 * when a request targets this node's instance, then always forwards to the
 * parent — requests bubble to the tree root with no interception. It returns
 * an Effect (the handler then the bubble) instead of running eagerly, so
 * callers can sequence requests.
 */
export type EventChannel = Readonly<{
    dispatch: (request: OpRequest) => Effect.Effect<void>;
}>;
/**
 * Operation id → handler, for one operation-exposing instance. Handlers
 * return an Effect so the bus can run them serially and in order.
 *
 * The `void` error channel pins handlers as infallible *failures* — a handler
 * that hits a recoverable hiccup must swallow/log it internally (mirrors the
 * table's fetch-error contract) rather than surface it, since the bus has no
 * error channel to carry it.
 *
 * A handler MAY still *halt* the chain — the "guard" shape: stop everything
 * queued after it. `dispatchTriggers` runs the list with `Effect.forEach`,
 * which short-circuits the moment one request's effect aborts, so triggers
 * after the guard never dispatch. Two ops use this: the page's `close` (halts
 * unconditionally — nothing should run after a close) and the form's `validate`
 * (halts only when an `error`-severity result remains, gating a submit). Both
 * halt with `Effect.die`, not `Effect.fail`: a defect aborts the chain without
 * widening the `void` error channel here (and `ActionEffect`'s `catchTags`
 * union over in `actions/components/group.vue`). The defect propagates to that
 * runner's `runPromise`, whose outer try/catch absorbs it silently — `catchTags`
 * only intercepts typed failures, so no toast.
 *
 * Pre-submit form validation rides this bus as that `validate` guard: a
 * submit-style button (e.g. the HTTP-request buttons) puts it first in its own
 * pre-request trigger list, so validation is explicit and configured rather
 * than an implicit host gate.
 */
export type OperationHandlers = Readonly<Record<string, () => Effect.Effect<void>>>;
export declare const EVENT_CHANNEL_KEY: InjectionKey<EventChannel>;
/**
 * Build a channel node for an operation-exposing instance. `dispatch` runs
 * the handler for requests addressed to `instanceId`, then bubbles every
 * request — handled or not — up to `parent`. Handler-then-bubble is one
 * Effect, so the whole delivery is sequenced.
 */
export declare function createEventChannel(instanceId: string, operations: OperationHandlers, parent: EventChannel | undefined): EventChannel;
/**
 * Register the current component as an operation target for its descendants.
 * Only works across the normal Vue inject tree — detached subtrees (a modal
 * slot rendered in an overlay container) must bridge explicitly with
 * `createEventChannel` + a manual `provide(EVENT_CHANNEL_KEY, …)`.
 */
export declare function provideEventTarget(instanceId: string, operations: OperationHandlers): void;
/**
 * Inject the nearest channel, for emitters (button hosts). `undefined` when
 * no operation-exposing ancestor exists — dispatching is then a no-op.
 */
export declare function useEventChannel(): EventChannel | undefined;
/**
 * Bubble a list of triggers through `channel`, one after another — list
 * order is execution order and each request's Effect is awaited before the
 * next, so async handlers (e.g. a table refetch) stay sequenced. A no-op
 * when there is no channel (no operation-exposing ancestor) or the list is
 * empty.
 *
 * A button that fires triggers composes this into its runtime effect at the
 * lifecycle point the triggers should fire — the bus no longer runs them.
 */
export declare function dispatchTriggers(channel: EventChannel | undefined, triggers: ReadonlyArray<TriggerValue> | undefined): Effect.Effect<void>;
/**
 * One operation a component type exposes. `id` is what the trigger stores;
 * `name`/`icon` are display only.
 */
export type OperationDescriptor = Readonly<{
    id: string;
    name: string;
    icon?: string;
}>;
/** An operation-exposing ancestor instance, as seen by the trigger config UI. */
export type EventAncestor = Readonly<{
    /** Instance id stored as the trigger `target`. */
    instanceId: string;
    /**
     * Instance display name from config — a table's 内部名称, a button's title.
     * `undefined` when the configurer left it blank; the trigger UI then shows
     * the type name alone instead of an empty `「」`.
     */
    name?: string;
    /** Component type display name (from type metadata). */
    typeName: string;
    /** Component type icon (from type metadata). */
    typeIcon?: string;
    /** Operations this instance exposes. */
    operations: ReadonlyArray<OperationDescriptor>;
}>;
/**
 * Contribute one ancestor frame. Descendant editors see it prepended
 * (nearest first) to whatever chain was inherited from further up. A `null`
 * value contributes nothing — for editors whose current selection may or
 * may not expose operations.
 */
export declare function provideEventAncestor(ancestor: Ref<EventAncestor | null>): void;
/**
 * The operation-exposing ancestors of the current editing position, nearest
 * first. Empty when nothing up the tree exposes operations.
 */
export declare function useEventAncestry(): Ref<ReadonlyArray<EventAncestor>>;
