@myriadcodelabs/uiflow 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MyriadCode
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,190 @@
1
+ # UIFlow
2
+
3
+ Explicit, code-first UI flow orchestration for React. UIFlow lets you define flows as plain objects with named steps, mix UI and logic steps, and move between them by returning the next step name. It’s useful when you want predictable, testable multi‑step experiences without wiring up routers, wizards, or state machines by hand.
4
+
5
+ ## Why it matters
6
+
7
+ - **Clarity:** Flows are defined in one place with explicit step names and transitions.
8
+ - **Flexibility:** Combine UI steps and async logic steps in the same flow.
9
+ - **Reusability:** Share cross‑flow state through event channels.
10
+
11
+ ## Quick example
12
+
13
+ ```tsx
14
+ import React from "react";
15
+ import { FlowRunner, defineFlow, createFlowChannel } from "@myriadcodelabs/uiflow";
16
+
17
+ type StudyData = {
18
+ deckId: string;
19
+ cards: CardWithState[];
20
+ activeCardId: string | null;
21
+ };
22
+
23
+ type CardWithState = {
24
+ id: string;
25
+ question: string;
26
+ answer: string;
27
+ flipped: boolean;
28
+ rating: "easy" | "medium" | "hard" | null;
29
+ };
30
+
31
+ export type ShowCardOutput =
32
+ | { action: "flip"; cardId: string }
33
+ | { action: "rate"; rating: Rating; cardId: string }
34
+ | { action: "next"; cardId: string };
35
+
36
+ const studiedCounter = createFlowChannel<number>(0);
37
+
38
+
39
+ const studyFlow = defineFlow<StudyData>(
40
+ {
41
+ // step 1
42
+ fetchCards: {
43
+ input: (data) => ({ deckId: data.deckId }),
44
+ action: async ({ deckId }, data) => {
45
+ const cards = await fakeFetchCards(deckId);
46
+ data.cards = cards.map((card) => ({ ...card, flipped: false, rating: null }));
47
+ data.activeCardId = null;
48
+ return { ok: true };
49
+ },
50
+ onOutput: () => "decide",
51
+ },
52
+
53
+ // step 2
54
+ decide: {
55
+ input: (data) => ({ hasCards: data.cards.length > 0 }),
56
+ action: ({ hasCards }) => hasCards,
57
+ onOutput: (_, exists) => (exists ? "study" : "noCard"),
58
+ },
59
+ // if no card present
60
+ noCard: {
61
+ input: () => ({}),
62
+ view: NoCardView,
63
+ onOutput: () => {},
64
+ },
65
+ // step 3
66
+ study: {
67
+ input: (data) => ({ cards: data.cards }),
68
+ view: CardView,
69
+ onOutput: (data, output, events) => {
70
+ const card = data.cards.find((c) => c.id === output.cardId);
71
+ if (!card) return "study";
72
+
73
+ if (output.action === "flip") {
74
+ data.activeCardId = card.id;
75
+ card.flipped = true;
76
+ return "study";
77
+ }
78
+
79
+ if (output.action === "rate") {
80
+ data.activeCardId = card.id;
81
+ card.rating = output.rating ?? null;
82
+ return "review";
83
+ }
84
+
85
+ if (output.action === "next") {
86
+ events?.studiedCounter.emit((c) => c + 1);
87
+ data.activeCardId = null;
88
+ return "fetchCards";
89
+ }
90
+ },
91
+ },
92
+
93
+ // step 4: if user does review
94
+ review: {
95
+ input: (data) => ({
96
+ deckId: data.deckId,
97
+ cardId: data.activeCardId!,
98
+ rating: data.cards.find((c) => c.id === data.activeCardId)?.rating!,
99
+ }),
100
+ action: async ({ deckId, cardId, rating }) => {
101
+ await fakeReviewCard(deckId, cardId, rating);
102
+ return { ok: true };
103
+ },
104
+ onOutput: (data, _, events) => {
105
+ events?.studiedCounter.emit((c) => c + 1);
106
+ data.activeCardId = null;
107
+ return "fetchCards";
108
+ },
109
+ },
110
+ },
111
+ { start: "fetchCards" }
112
+ );
113
+ ```
114
+
115
+ The example components are defined here.
116
+
117
+ ```tsx
118
+ const CardView: React.FC<{
119
+ input: { cards: CardWithState[] };
120
+ output: OutputHandle<ShowCardOutput>;
121
+ }> = ({ input, output }) => (
122
+ <div>
123
+ {input.cards.map((card) => (
124
+ <div key={card.id}>
125
+ <div>{card.question}</div>
126
+ {card.flipped ? <div>{card.answer}</div> : null}
127
+ <button onClick={() => output.emit({ cardId: card.id, action: "flip" })}>Show Answer</button>
128
+ <button onClick={() => output.emit({ cardId: card.id, action: "rate", rating: "easy" })}>Easy</button>
129
+ <button onClick={() => output.emit({ cardId: card.id, action: "rate", rating: "medium" })}>Medium</button>
130
+ <button onClick={() => output.emit({ cardId: card.id, action: "rate", rating: "hard" })}>Hard</button>
131
+ <button onClick={() => output.emit({ cardId: card.id, action: "next" })}>Next</button>
132
+ </div>
133
+ ))}
134
+ </div>
135
+ );
136
+
137
+ const NoCardView: React.FC<{ input: {}; output: { emit: () => void } }> = () => (
138
+ <div>No cards available.</div>
139
+ );
140
+ ```
141
+ The FlowRunner is used to call the flow and set initial data and channels.
142
+
143
+ ```tsx
144
+ export function App() {
145
+ return (
146
+ <FlowRunner
147
+ flow={studyFlow}
148
+ initialData={{ deckId: "deck-1", cards: [], activeCardId: null }}
149
+ eventChannels={{ studiedCounter }}
150
+ />
151
+ );
152
+ }
153
+ ```
154
+
155
+ ## API Reference (exported only)
156
+
157
+ ### 1) Where the flow is called
158
+
159
+ #### `FlowRunner` (React component)
160
+ Runs a flow and renders UI steps.
161
+
162
+ ```tsx
163
+ <FlowRunner flow={flow} initialData={initialData} eventChannels={channels} />
164
+ ```
165
+
166
+ - `flow: FlowDefinition<D>` — created by `defineFlow`.
167
+ - `initialData: D` — shared mutable data for this flow instance.
168
+ - `eventChannels?: EventChannels` — optional shared channels; emitting causes re-render.
169
+
170
+ ### 2) Where the flow is defined
171
+
172
+ #### `defineFlow<D>(steps: FlowSteps<D>, options: DefineFlowOptions): FlowDefinition<D>`
173
+ Creates a flow definition from a steps map and a required `start` step name.
174
+
175
+ - `DefineFlowOptions.start: string` — name of the first step.
176
+
177
+ #### `createFlowChannel<T>(initial: T): FlowChannel<T>`
178
+ Creates a shared channel for cross‑flow communication.
179
+
180
+ - `FlowChannel.get(): T` — read the current value.
181
+ - `FlowChannel.emit(update: T | (prev: T) => T): void` — update value and notify subscribers.
182
+ - `FlowChannel.subscribe(listener: () => void): () => void` — listen for changes.
183
+
184
+
185
+ ### 3) A UI component
186
+
187
+ #### `OutputHandle<O>`
188
+ Used by UI steps to emit output back into the flow.
189
+
190
+ - `OutputHandle.emit(output: O): void`
package/dist/flow.d.ts ADDED
@@ -0,0 +1,89 @@
1
+ import React from "react";
2
+ export type Updater<T> = T | ((prev: T) => T);
3
+ export interface FlowChannel<T> {
4
+ get: () => T;
5
+ emit: (update: Updater<T>) => void;
6
+ subscribe: (listener: () => void) => () => void;
7
+ }
8
+ export type EventChannels = Record<string, FlowChannel<any>>;
9
+ export declare function createFlowChannel<T>(initial: T): FlowChannel<T>;
10
+ /**
11
+ * Shared mutable data for a flow instance.
12
+ * You can refine this to a generic later, e.g. <D>.
13
+ */
14
+ export type FlowData = Record<string, any>;
15
+ /**
16
+ * Output handle given to UI components.
17
+ * They call output.done(...) when they're finished.
18
+ */
19
+ export interface OutputHandle<O = any> {
20
+ emit: (output: O) => void;
21
+ }
22
+ /**
23
+ * UI step:
24
+ * - Prepares `input` from `data`
25
+ * - Renders `view`
26
+ * - Receives `output` from the component via output.done()
27
+ * - `onOutput` decides next step and can mutate data
28
+ */
29
+ export interface UiStep<D extends FlowData = FlowData, I = any, O = any> {
30
+ input: (data: D, events?: EventChannels) => I;
31
+ view: React.ComponentType<{
32
+ input: I;
33
+ output: OutputHandle<O>;
34
+ }>;
35
+ onOutput: (data: D, output: O, events?: EventChannels) => string | void | Promise<string | void>;
36
+ }
37
+ /**
38
+ * Action (logic) step:
39
+ * - Prepares `args` from `data`
40
+ * - Executes `action` (sync/async)
41
+ * - `onOutput` decides next step and can mutate data
42
+ * - No UI
43
+ */
44
+ export interface ActionStep<D extends FlowData = FlowData, I = any, O = any> {
45
+ input: (data: D, events?: EventChannels) => I;
46
+ action: (input: I, data: D, events?: EventChannels) => O | Promise<O>;
47
+ onOutput: (data: D, output: O, events?: EventChannels) => string | void | Promise<string | void>;
48
+ }
49
+ /**
50
+ * A flow step is either:
51
+ * - a UI step (has `view`)
52
+ * - an action step (has `action`)
53
+ * but never both at the same time by convention.
54
+ */
55
+ export type FlowStep<D extends FlowData = FlowData> = UiStep<D, any, any> | ActionStep<D, any, any>;
56
+ /**
57
+ * Map of step names -> step definitions.
58
+ */
59
+ export type FlowSteps<D extends FlowData = FlowData> = Record<string, FlowStep<D>>;
60
+ /**
61
+ * Flow definition object returned by defineFlow.
62
+ */
63
+ export interface FlowDefinition<D extends FlowData = FlowData> {
64
+ steps: FlowSteps<D>;
65
+ start: string;
66
+ }
67
+ /**
68
+ * Options when defining a flow.
69
+ */
70
+ export interface DefineFlowOptions {
71
+ start: string;
72
+ }
73
+ /**
74
+ * Main entry point to define a flow.
75
+ */
76
+ export declare function defineFlow<D extends FlowData = FlowData>(steps: FlowSteps<D>, options: DefineFlowOptions): FlowDefinition<D>;
77
+ export interface FlowRunnerProps<D extends FlowData = FlowData> {
78
+ flow: FlowDefinition<D>;
79
+ initialData: D;
80
+ eventChannels?: EventChannels;
81
+ }
82
+ /**
83
+ * FlowRunner:
84
+ * - drives the current step (UI or action)
85
+ * - manages transitions
86
+ * - renders UI steps
87
+ */
88
+ export declare function FlowRunner<D extends FlowData = FlowData>(props: Readonly<FlowRunnerProps<D>>): import("react/jsx-runtime").JSX.Element;
89
+ //# sourceMappingURL=flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../src/flow.tsx"],"names":[],"mappings":"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"}
package/dist/flow.js ADDED
@@ -0,0 +1,149 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ /* eslint-disable react/no-unescaped-entities */
4
+ // src/flow.tsx
5
+ import React, { useEffect, useRef, useState } from "react";
6
+ // Factory function to create a channel.
7
+ // IMPORTANT: This lives OUTSIDE React, so multiple FlowRunners can share it.
8
+ export function createFlowChannel(initial) {
9
+ let value = initial;
10
+ const listeners = new Set();
11
+ return {
12
+ get: () => value,
13
+ emit: (update) => {
14
+ value = typeof update === "function" ? update(value) : update;
15
+ listeners.forEach((l) => l()); // notify all subscribers
16
+ },
17
+ subscribe: (listener) => {
18
+ listeners.add(listener);
19
+ return () => listeners.delete(listener);
20
+ },
21
+ };
22
+ }
23
+ /**
24
+ * Main entry point to define a flow.
25
+ */
26
+ export function defineFlow(steps, options) {
27
+ if (!options.start || !steps[options.start]) {
28
+ throw new Error(`defineFlow: 'start' must be provided and exist in steps. Got '${options.start}'.`);
29
+ }
30
+ return {
31
+ steps,
32
+ start: options.start,
33
+ };
34
+ }
35
+ /**
36
+ * FlowRunner:
37
+ * - drives the current step (UI or action)
38
+ * - manages transitions
39
+ * - renders UI steps
40
+ */
41
+ export function FlowRunner(props) {
42
+ const eventChannelsRef = useRef(undefined);
43
+ eventChannelsRef.current ?? (eventChannelsRef.current = props.eventChannels);
44
+ const eventChannels = eventChannelsRef.current;
45
+ const { flow, initialData } = props;
46
+ // We keep data and currentStep in state so React re-renders on change.
47
+ const [state, setState] = useState({
48
+ currentStep: flow.start,
49
+ data: { ...initialData },
50
+ });
51
+ const [busy, setBusy] = useState(false); // for action steps
52
+ const isMountedRef = useRef(true);
53
+ // NEW:
54
+ // This state is never used directly.
55
+ // It only exists to force a re-render when event channels change.
56
+ const [_tick, setTick] = useState(0);
57
+ // NEW:
58
+ // Subscribe to every provided channel.
59
+ // When any channel emits, we trigger a re-render of this FlowRunner.
60
+ useEffect(() => {
61
+ if (!eventChannels)
62
+ return;
63
+ const unsubs = Object.values(eventChannels).map((ch) => ch.subscribe(() => setTick((x) => x + 1)));
64
+ return () => unsubs.forEach((u) => u());
65
+ }, []);
66
+ const { currentStep, data } = state;
67
+ const applyTransition = (nextStepName) => {
68
+ if (!isMountedRef.current)
69
+ return;
70
+ if (nextStepName && flow.steps[nextStepName]) {
71
+ setState((prev) => ({
72
+ ...prev,
73
+ currentStep: nextStepName,
74
+ data: { ...prev.data }, // new reference to trigger React updates (memo-safe)
75
+ }));
76
+ }
77
+ else {
78
+ // no next step: just re-render with updated data if any
79
+ setState((prev) => ({
80
+ ...prev,
81
+ data: { ...prev.data },
82
+ }));
83
+ }
84
+ };
85
+ useEffect(() => {
86
+ return () => {
87
+ isMountedRef.current = false;
88
+ };
89
+ }, []);
90
+ const step = flow.steps[currentStep];
91
+ // If the step is an action (no view), run it in an effect.
92
+ const isActionStep = step.action && !step.view;
93
+ useEffect(() => {
94
+ if (!isActionStep)
95
+ return;
96
+ const actionStep = step;
97
+ (async () => {
98
+ try {
99
+ setBusy(true);
100
+ const input = actionStep.input(state.data, eventChannels);
101
+ const output = await actionStep.action(input, state.data, eventChannels);
102
+ const next = await actionStep.onOutput(state.data, output, eventChannels);
103
+ applyTransition(next);
104
+ }
105
+ catch (e) {
106
+ console.error("FlowRunner action step error:", e);
107
+ // In a real lib, route to a dedicated error step or surface error up
108
+ }
109
+ finally {
110
+ if (isMountedRef.current)
111
+ setBusy(false);
112
+ }
113
+ })();
114
+ // We only want to run this when step changes, not on arbitrary data changes.
115
+ // eslint-disable-next-line react-hooks/exhaustive-deps
116
+ }, [currentStep]);
117
+ if (!step) {
118
+ // Fails fast if flow is misconfigured.
119
+ return (_jsxs("div", { children: [_jsx("strong", { children: "FlowRunner error:" }), " Unknown step \"", currentStep, "\"."] }));
120
+ }
121
+ // Helper to apply a next step (if returned) and ensure React re-renders
122
+ // -----------------------
123
+ // ACTION STEP HANDLING
124
+ // -----------------------
125
+ // If it's an action step, show a simple placeholder or nothing.
126
+ if (isActionStep) {
127
+ // You can customize this: spinner, skeleton, etc.
128
+ return _jsx("div", { children: busy ? "Processing..." : null });
129
+ }
130
+ // -----------------------
131
+ // UI STEP HANDLING
132
+ // -----------------------
133
+ const uiStep = step;
134
+ const ViewComponent = uiStep.view;
135
+ const input = uiStep.input(data, eventChannels);
136
+ const outputHandle = {
137
+ emit: async (output) => {
138
+ try {
139
+ const next = await uiStep.onOutput(data, output, eventChannels);
140
+ applyTransition(next);
141
+ }
142
+ catch (e) {
143
+ console.error("FlowRunner UI step onOutput error:", e);
144
+ }
145
+ },
146
+ };
147
+ return _jsx(ViewComponent, { input: input, output: outputHandle });
148
+ }
149
+ //# sourceMappingURL=flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.js","sourceRoot":"","sources":["../src/flow.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export * from "./flow";
2
+ //# sourceMappingURL=uiflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uiflow.d.ts","sourceRoot":"","sources":["../src/uiflow.tsx"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC"}
package/dist/uiflow.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./flow";
2
+ //# sourceMappingURL=uiflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uiflow.js","sourceRoot":"","sources":["../src/uiflow.tsx"],"names":[],"mappings":"AAAA,cAAc,QAAQ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@myriadcodelabs/uiflow",
3
+ "version": "0.1.0",
4
+ "description": "Explicit, code-first UI flow orchestration for React.",
5
+ "keywords": [],
6
+ "author": "Muhammad Ismail Khan",
7
+ "license": "MIT",
8
+ "peerDependencies": {
9
+ "react": ">=18"
10
+ },
11
+ "devDependencies": {
12
+ "@types/react": "^19.2.10",
13
+ "typescript": "^5.9.3"
14
+ },
15
+ "type": "module",
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "main": "./dist/uiflow.js",
20
+ "types": "./dist/uiflow.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/uiflow.d.ts",
24
+ "default": "./dist/uiflow.js"
25
+ }
26
+ },
27
+ "scripts": {
28
+ "test": "echo \"Error: no test specified\" && exit 1",
29
+ "clean": "rimraf dist",
30
+ "build": "pnpm run clean && tsc"
31
+ }
32
+ }