|
1 | | -import { type FlowsProperties } from "./components"; |
| 1 | +import type { |
| 2 | + FlowsProperties, |
| 3 | + ComponentProps, |
| 4 | + SurveyComponentProps, |
| 5 | + TourComponentProps, |
| 6 | +} from "./components"; |
2 | 7 |
|
3 | | -export interface ActiveBlock { |
| 8 | +type ActiveBlockBase<T extends string, P extends { __flows: FlowsProperties }> = { |
4 | 9 | /** |
5 | | - * Unique identifier of the block, useful for stable key during rendering. Keep in mind each workflow version will have a different id for each block. |
| 10 | + * Unique identifier of the block. Useful as a stable `key` during rendering. |
| 11 | + * |
| 12 | + * Note: each workflow version assigns different ids to each block, so this value changes on workflow publish. |
6 | 13 | */ |
7 | 14 | id: string; |
8 | 15 | /** |
9 | | - * Unique identifier of the tour block this tour-component belongs to. Keep in mind each workflow version will have a different id for each block. |
| 16 | + * Discriminant that identifies the block variant. Use this to narrow the type and access type-safe `props`. |
| 17 | + * |
| 18 | + * - `"component"` — a standalone workflow block |
| 19 | + * - `"tour-component"` — a single step within a tour |
| 20 | + * - `"survey"` — a survey block |
10 | 21 | */ |
11 | | - tourBlockId?: string; |
| 22 | + type: T; |
12 | 23 | /** |
13 | | - * Type of the block, either "component" or "tour-component" or "survey". |
| 24 | + * The key of the registered UI component used to render this block. |
| 25 | + * Must match a key registered in `FlowsProvider` (React) or `init` (JS). |
14 | 26 | */ |
15 | | - type: "component" | "tour-component" | "survey"; |
| 27 | + component: string; |
16 | 28 | /** |
17 | | - * The UI Component used to render this block. |
| 29 | + * Props to pass to the component. The exact shape depends on the block `type`: |
| 30 | + * |
| 31 | + * - `"component"` → `ComponentProps` |
| 32 | + * - `"tour-component"` → `TourComponentProps` — includes `continue`, `previous?`, and `cancel` |
| 33 | + * - `"survey"` → `SurveyComponentProps` — includes `survey`, `complete`, and `cancel` |
18 | 34 | */ |
19 | | - component: string; |
| 35 | + props: P; |
| 36 | +}; |
| 37 | + |
| 38 | +/** |
| 39 | + * An `ActiveBlock` representing a standalone workflow component block. |
| 40 | + * |
| 41 | + * Narrow to this type by checking `block.type === "component"`. |
| 42 | + */ |
| 43 | +export type ComponentActiveBlock = ActiveBlockBase< |
| 44 | + "component", |
| 45 | + ComponentProps<Record<string, unknown>> |
| 46 | +>; |
| 47 | + |
| 48 | +/** |
| 49 | + * An `ActiveBlock` representing a single step within a tour. |
| 50 | + * |
| 51 | + * Narrow to this type by checking `block.type === "tour-component"`. |
| 52 | + */ |
| 53 | +export type TourComponentActiveBlock = ActiveBlockBase< |
| 54 | + "tour-component", |
| 55 | + TourComponentProps<Record<string, unknown>> |
| 56 | +> & { |
20 | 57 | /** |
21 | | - * Props to be passed to the component including both data and exit node methods. |
| 58 | + * Unique identifier of the parent tour block this step belongs to. Useful as a stable `key` during rendering. |
| 59 | + * |
| 60 | + * Prefer this over `id` when rendering tour steps — reusing the same key across steps lets the browser |
| 61 | + * reuse the DOM element rather than unmounting and remounting it between individual steps. |
| 62 | + * |
| 63 | + * Note: each workflow version assigns different ids to each block, so this value changes on workflow publish. |
22 | 64 | */ |
23 | | - props: { __flows: FlowsProperties } & Record<string, unknown>; |
24 | | -} |
| 65 | + tourBlockId?: string; |
| 66 | +}; |
| 67 | + |
| 68 | +/** |
| 69 | + * An `ActiveBlock` representing a survey block. |
| 70 | + * |
| 71 | + * Narrow to this type by checking `block.type === "survey"`. |
| 72 | + */ |
| 73 | +export type SurveyActiveBlock = ActiveBlockBase< |
| 74 | + "survey", |
| 75 | + SurveyComponentProps<Record<string, unknown>> |
| 76 | +>; |
| 77 | + |
| 78 | +/** |
| 79 | + * A block that is currently active and ready to render. |
| 80 | + * |
| 81 | + * Use `block.type` to narrow to a specific variant and access type-safe `props`: |
| 82 | + * |
| 83 | + * ```ts |
| 84 | + * if (block.type === "tour-component") { |
| 85 | + * // props is TourComponentProps — includes continue, previous?, cancel |
| 86 | + * block.props.continue(); |
| 87 | + * } |
| 88 | + * ``` |
| 89 | + * |
| 90 | + * @see {@link ComponentActiveBlock} for `"component"` blocks |
| 91 | + * @see {@link TourComponentActiveBlock} for `"tour-component"` blocks |
| 92 | + * @see {@link SurveyActiveBlock} for `"survey"` blocks |
| 93 | + */ |
| 94 | +export type ActiveBlock = ComponentActiveBlock | TourComponentActiveBlock | SurveyActiveBlock; |
25 | 95 |
|
26 | 96 | export const createActiveBlockProxy = ( |
27 | 97 | block: ActiveBlock, |
|
0 commit comments