@naderikladious/react-flow 0.1.3 → 0.1.7

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/README.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Utilities for declarative control-flow primitives in React, written in TypeScript and packaged for ESM/CJS consumers.
4
4
 
5
+ <p>
6
+ <img src="https://raw.githubusercontent.com/NaderIkladious/react-flow/main/assets/flow-logo.png" alt="Flow logo" width="120" />
7
+ </p>
8
+
5
9
  ## Motivation
6
10
  - Keep conditional and iterative UI logic readable without custom hooks per component.
7
11
  - Provide type-safe, render-prop based building blocks (`Flow.Condition`, `Flow.If`, `Flow.ForEach`, etc.).
@@ -9,7 +13,7 @@ Utilities for declarative control-flow primitives in React, written in TypeScrip
9
13
 
10
14
  ## Installation
11
15
  ```bash
12
- npm install react-flow
16
+ npm install @naderikladious/react-flow
13
17
  ```
14
18
 
15
19
  If working from this repo locally, install and build the library first:
@@ -23,20 +27,31 @@ To explore the Vite example app:
23
27
  cd example
24
28
  npm install
25
29
  npm run dev
30
+ # For GitHub Pages build: GITHUB_PAGES=true npm run build
26
31
  ```
27
32
 
28
33
  ## API
34
+ Preferred namespace is `Flow` (with `ReactFlow` available as an alias).
35
+
29
36
  - `Flow.Condition` — provides a boolean value to descendants.
37
+ - `Flow.AsyncCondition` — resolves a boolean asynchronously and provides it to descendants.
30
38
  - `Flow.If` — renders children when the condition is true (prop overrides context).
31
39
  - `Flow.Else` — renders children when the condition is false (prop overrides context).
40
+ - `Flow.Unless` — renders children when the condition is false (prop overrides context).
32
41
  - `Flow.ForEach<T>` — iterates an array with an optional `keyExtractor` and render-function children `(item, index) => ReactNode`.
33
42
  - `Flow.For` — iterates `count` times with optional `start` and `step`, render-function children `(index) => ReactNode`.
34
43
  - `Flow.Batch<T>` — groups items into chunks of `batchSize` and renders `(batch, batchIndex) => ReactNode` using `Flow.ForEach` under the hood.
44
+ - `Flow.Switch` / `Flow.Case` / `Flow.Default` — declarative branching on a single value.
35
45
  - `useFlowCondition` — hook to read the nearest `Flow.Condition` value (throws if missing).
36
46
 
37
- All components are also available as named exports (tree-shakeable) in addition to the `Flow` namespace object.
47
+ All components are also available as named exports (tree-shakeable) in addition to the namespace object.
38
48
 
39
49
  ## Examples
50
+ Demo video:
51
+ <p>
52
+ <video src="https://raw.githubusercontent.com/NaderIkladious/react-flow/main/assets/flow-demo.webm" controls muted playsinline width="720"></video>
53
+ </p>
54
+
40
55
  Basic conditionals:
41
56
  ```tsx
42
57
  <Flow.Condition value={isEnabled}>
@@ -45,7 +60,7 @@ Basic conditionals:
45
60
  </Flow.If>
46
61
  <Flow.Else>
47
62
  <div>Disabled</div>
48
- </Flow.Else>
63
+ </Flow.Else>
49
64
  </Flow.Condition>
50
65
  ```
51
66
 
package/dist/index.cjs CHANGED
@@ -12,6 +12,38 @@ const FlowConditionContext = React.createContext({
12
12
  const Condition = ({ value, children }) => {
13
13
  return (jsxRuntime.jsx(FlowConditionContext.Provider, { value: { value, hasProvider: true }, children: children }));
14
14
  };
15
+ const AsyncCondition = ({ value, pending = null, error, children, }) => {
16
+ var _a;
17
+ const [state, setState] = React.useState({ status: "pending" });
18
+ React.useEffect(() => {
19
+ let active = true;
20
+ const promise = typeof value === "function" ? value() : value;
21
+ Promise.resolve(promise)
22
+ .then((resolved) => {
23
+ if (!active)
24
+ return;
25
+ setState({ status: "resolved", value: resolved });
26
+ })
27
+ .catch((err) => {
28
+ if (!active)
29
+ return;
30
+ setState({ status: "rejected", error: err });
31
+ });
32
+ return () => {
33
+ active = false;
34
+ };
35
+ }, [value]);
36
+ if (state.status === "pending") {
37
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: pending });
38
+ }
39
+ if (state.status === "rejected") {
40
+ if (error) {
41
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: error(state.error) });
42
+ }
43
+ throw state.error instanceof Error ? state.error : new Error("Flow.AsyncCondition failed.");
44
+ }
45
+ return (jsxRuntime.jsx(FlowConditionContext.Provider, { value: { value: (_a = state.value) !== null && _a !== void 0 ? _a : false, hasProvider: true }, children: children }));
46
+ };
15
47
  const resolveCondition = (condition, context, componentName) => {
16
48
  if (typeof condition === "boolean") {
17
49
  return condition;
@@ -31,6 +63,11 @@ const Else = ({ condition, children }) => {
31
63
  const active = resolveCondition(condition, context, "Flow.Else");
32
64
  return !active ? jsxRuntime.jsx(jsxRuntime.Fragment, { children: children }) : null;
33
65
  };
66
+ const Unless = ({ condition, children }) => {
67
+ const context = React.useContext(FlowConditionContext);
68
+ const active = resolveCondition(condition, context, "Flow.Unless");
69
+ return !active ? jsxRuntime.jsx(jsxRuntime.Fragment, { children: children }) : null;
70
+ };
34
71
  const ForEach = ({ items, keyExtractor, children }) => {
35
72
  return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: items.map((item, index) => (jsxRuntime.jsx(React.Fragment, { children: children(item, index) }, keyExtractor ? keyExtractor(item, index) : index))) }));
36
73
  };
@@ -64,6 +101,46 @@ const Batch = ({ items, batchSize, children }) => {
64
101
  const batches = chunkItems(items, batchSize);
65
102
  return (jsxRuntime.jsx(ForEach, { items: batches, keyExtractor: (_, index) => index, children: (batch, batchIndex) => children(batch, batchIndex) }));
66
103
  };
104
+ const Case = (_props) => {
105
+ throw new Error("Flow.Case must be used within Flow.Switch.");
106
+ };
107
+ const Default = () => {
108
+ throw new Error("Flow.Default must be used within Flow.Switch.");
109
+ };
110
+ const Switch = ({ value, children }) => {
111
+ let match = null;
112
+ let defaultChildren = null;
113
+ const isPredicate = (when) => typeof when === "function";
114
+ const isCaseElement = (node) => React.isValidElement(node) && node.type === Case;
115
+ const isDefaultElement = (node) => React.isValidElement(node) && node.type === Default;
116
+ React.Children.forEach(children, (child) => {
117
+ if (match) {
118
+ return;
119
+ }
120
+ if (isDefaultElement(child)) {
121
+ if (defaultChildren === null) {
122
+ defaultChildren = child.props.children;
123
+ }
124
+ return;
125
+ }
126
+ if (isCaseElement(child)) {
127
+ const { when, children: caseChildren } = child.props;
128
+ const isMatch = isPredicate(when)
129
+ ? when(value)
130
+ : Object.is(when, value);
131
+ if (isMatch) {
132
+ match = caseChildren;
133
+ }
134
+ }
135
+ });
136
+ if (match !== null) {
137
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: match });
138
+ }
139
+ if (defaultChildren !== null) {
140
+ return jsxRuntime.jsx(jsxRuntime.Fragment, { children: defaultChildren });
141
+ }
142
+ return null;
143
+ };
67
144
  const useFlowCondition = () => {
68
145
  const context = React.useContext(FlowConditionContext);
69
146
  if (!context.hasProvider) {
@@ -71,26 +148,39 @@ const useFlowCondition = () => {
71
148
  }
72
149
  return context.value;
73
150
  };
74
- const Flow = {
151
+ const ReactFlow = {
75
152
  Condition,
153
+ AsyncCondition,
76
154
  If,
77
155
  Else,
156
+ Unless,
78
157
  ForEach,
79
158
  For,
80
159
  Batch,
160
+ Switch,
161
+ Case,
162
+ Default,
81
163
  };
82
- const ReactFlow = ({ message = "Hello from react-flow" }) => {
164
+ // Legacy alias
165
+ const Flow = ReactFlow;
166
+ const ReactFlowComponent = ({ message = "Hello from react-flow" }) => {
83
167
  return jsxRuntime.jsx("div", { children: message });
84
168
  };
85
169
 
170
+ exports.AsyncCondition = AsyncCondition;
86
171
  exports.Batch = Batch;
172
+ exports.Case = Case;
87
173
  exports.Condition = Condition;
174
+ exports.Default = Default;
88
175
  exports.Else = Else;
89
176
  exports.Flow = Flow;
90
177
  exports.For = For;
91
178
  exports.ForEach = ForEach;
92
179
  exports.If = If;
93
180
  exports.ReactFlow = ReactFlow;
94
- exports.default = ReactFlow;
181
+ exports.ReactFlowComponent = ReactFlowComponent;
182
+ exports.Switch = Switch;
183
+ exports.Unless = Unless;
184
+ exports.default = ReactFlowComponent;
95
185
  exports.useFlowCondition = useFlowCondition;
96
186
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\n\ntype FlowConditionContextValue = {\n value: boolean;\n hasProvider: boolean;\n};\n\nconst FlowConditionContext = React.createContext<FlowConditionContextValue>({\n value: false,\n hasProvider: false,\n});\n\nexport type FlowConditionProps = {\n value: boolean;\n children?: React.ReactNode;\n};\n\nexport const Condition: React.FC<FlowConditionProps> = ({ value, children }) => {\n return (\n <FlowConditionContext.Provider value={{ value, hasProvider: true }}>\n {children}\n </FlowConditionContext.Provider>\n );\n};\n\nexport type FlowConditionalBranchProps = {\n condition?: boolean;\n children?: React.ReactNode;\n};\n\nconst resolveCondition = (\n condition: boolean | undefined,\n context: FlowConditionContextValue,\n componentName: string\n) => {\n if (typeof condition === \"boolean\") {\n return condition;\n }\n if (context.hasProvider) {\n return context.value;\n }\n throw new Error(`${componentName} requires a condition prop or Flow.Condition parent.`);\n};\n\nexport const If: React.FC<FlowConditionalBranchProps> = ({ condition, children }) => {\n const context = React.useContext(FlowConditionContext);\n const active = resolveCondition(condition, context, \"Flow.If\");\n return active ? <>{children}</> : null;\n};\n\nexport const Else: React.FC<FlowConditionalBranchProps> = ({ condition, children }) => {\n const context = React.useContext(FlowConditionContext);\n const active = resolveCondition(condition, context, \"Flow.Else\");\n return !active ? <>{children}</> : null;\n};\n\nexport type FlowForEachProps<T> = {\n items: T[];\n keyExtractor?: (item: T, index: number) => React.Key;\n children: (item: T, index: number) => React.ReactNode;\n};\n\nexport const ForEach = <T,>({ items, keyExtractor, children }: FlowForEachProps<T>): React.ReactElement => {\n return (\n <>\n {items.map((item, index) => (\n <React.Fragment key={keyExtractor ? keyExtractor(item, index) : index}>{children(item, index)}</React.Fragment>\n ))}\n </>\n );\n};\n\nexport type FlowForProps = {\n count: number;\n start?: number;\n step?: number;\n children: (index: number) => React.ReactNode;\n};\n\nexport const For: React.FC<FlowForProps> = ({ count, start = 0, step = 1, children }) => {\n if (!Number.isFinite(count) || count < 0) {\n console.warn(\"Flow.For received an invalid count; rendering nothing.\");\n return null;\n }\n if (!Number.isFinite(step) || step === 0) {\n throw new Error(\"Flow.For requires a finite non-zero step.\");\n }\n\n const iterations = Math.min(count, 10_000);\n const items = Array.from({ length: iterations }, (_, i) => start + i * step);\n\n if (iterations !== count) {\n // Guardrail against accidental infinite or huge loops.\n console.warn(\"Flow.For capped iterations at 10,000 to avoid infinite loops.\");\n }\n\n return (\n <>\n {items.map((value, idx) => (\n <React.Fragment key={value}>{children(value)}</React.Fragment>\n ))}\n </>\n );\n};\n\nexport type FlowBatchProps<T> = {\n items: T[];\n batchSize: number;\n children: (batch: T[], batchIndex: number) => React.ReactNode;\n};\n\nconst chunkItems = <T,>(items: T[], batchSize: number): T[][] => {\n const batches: T[][] = [];\n for (let i = 0; i < items.length; i += batchSize) {\n batches.push(items.slice(i, i + batchSize));\n }\n return batches;\n};\n\nexport const Batch = <T,>({ items, batchSize, children }: FlowBatchProps<T>): React.ReactElement => {\n if (!Number.isInteger(batchSize) || batchSize <= 0) {\n throw new Error(\"Flow.Batch requires a positive integer batchSize.\");\n }\n\n const batches = chunkItems(items, batchSize);\n\n return (\n <ForEach\n items={batches}\n keyExtractor={(_, index) => index}\n >\n {(batch, batchIndex) => children(batch, batchIndex)}\n </ForEach>\n );\n};\n\nexport const useFlowCondition = () => {\n const context = React.useContext(FlowConditionContext);\n if (!context.hasProvider) {\n throw new Error(\"useFlowCondition must be used within a Flow.Condition.\");\n }\n return context.value;\n};\n\nexport const Flow = {\n Condition,\n If,\n Else,\n ForEach,\n For,\n Batch,\n};\n\nexport type ReactFlowProps = {\n message?: string;\n};\n\nexport const ReactFlow: React.FC<ReactFlowProps> = ({ message = \"Hello from react-flow\" }) => {\n return <div>{message}</div>;\n};\n\nexport default ReactFlow;\n"],"names":["_jsx","_Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\n\ntype FlowConditionContextValue = {\n value: boolean;\n hasProvider: boolean;\n};\n\nconst FlowConditionContext = React.createContext<FlowConditionContextValue>({\n value: false,\n hasProvider: false,\n});\n\nexport type FlowConditionProps = {\n value: boolean;\n children?: React.ReactNode;\n};\n\nexport const Condition: React.FC<FlowConditionProps> = ({ value, children }) => {\n return (\n <FlowConditionContext.Provider value={{ value, hasProvider: true }}>\n {children}\n </FlowConditionContext.Provider>\n );\n};\n\nexport type FlowAsyncConditionProps = {\n value: Promise<boolean> | (() => Promise<boolean>);\n pending?: React.ReactNode;\n error?: (error: unknown) => React.ReactNode;\n children?: React.ReactNode;\n};\n\nexport const AsyncCondition: React.FC<FlowAsyncConditionProps> = ({\n value,\n pending = null,\n error,\n children,\n}) => {\n const [state, setState] = React.useState<{\n status: \"pending\" | \"resolved\" | \"rejected\";\n value?: boolean;\n error?: unknown;\n }>({ status: \"pending\" });\n\n React.useEffect(() => {\n let active = true;\n const promise = typeof value === \"function\" ? value() : value;\n Promise.resolve(promise)\n .then((resolved) => {\n if (!active) return;\n setState({ status: \"resolved\", value: resolved });\n })\n .catch((err) => {\n if (!active) return;\n setState({ status: \"rejected\", error: err });\n });\n return () => {\n active = false;\n };\n }, [value]);\n\n if (state.status === \"pending\") {\n return <>{pending}</>;\n }\n\n if (state.status === \"rejected\") {\n if (error) {\n return <>{error(state.error)}</>;\n }\n throw state.error instanceof Error ? state.error : new Error(\"Flow.AsyncCondition failed.\");\n }\n\n return (\n <FlowConditionContext.Provider value={{ value: state.value ?? false, hasProvider: true }}>\n {children}\n </FlowConditionContext.Provider>\n );\n};\n\nexport type FlowConditionalBranchProps = {\n condition?: boolean;\n children?: React.ReactNode;\n};\n\nconst resolveCondition = (\n condition: boolean | undefined,\n context: FlowConditionContextValue,\n componentName: string\n) => {\n if (typeof condition === \"boolean\") {\n return condition;\n }\n if (context.hasProvider) {\n return context.value;\n }\n throw new Error(`${componentName} requires a condition prop or Flow.Condition parent.`);\n};\n\nexport const If: React.FC<FlowConditionalBranchProps> = ({ condition, children }) => {\n const context = React.useContext(FlowConditionContext);\n const active = resolveCondition(condition, context, \"Flow.If\");\n return active ? <>{children}</> : null;\n};\n\nexport const Else: React.FC<FlowConditionalBranchProps> = ({ condition, children }) => {\n const context = React.useContext(FlowConditionContext);\n const active = resolveCondition(condition, context, \"Flow.Else\");\n return !active ? <>{children}</> : null;\n};\n\nexport const Unless: React.FC<FlowConditionalBranchProps> = ({ condition, children }) => {\n const context = React.useContext(FlowConditionContext);\n const active = resolveCondition(condition, context, \"Flow.Unless\");\n return !active ? <>{children}</> : null;\n};\n\nexport type FlowForEachProps<T> = {\n items: T[];\n keyExtractor?: (item: T, index: number) => React.Key;\n children: (item: T, index: number) => React.ReactNode;\n};\n\nexport const ForEach = <T,>({ items, keyExtractor, children }: FlowForEachProps<T>): React.ReactElement => {\n return (\n <>\n {items.map((item, index) => (\n <React.Fragment key={keyExtractor ? keyExtractor(item, index) : index}>{children(item, index)}</React.Fragment>\n ))}\n </>\n );\n};\n\nexport type FlowForProps = {\n count: number;\n start?: number;\n step?: number;\n children: (index: number) => React.ReactNode;\n};\n\nexport const For: React.FC<FlowForProps> = ({ count, start = 0, step = 1, children }) => {\n if (!Number.isFinite(count) || count < 0) {\n console.warn(\"Flow.For received an invalid count; rendering nothing.\");\n return null;\n }\n if (!Number.isFinite(step) || step === 0) {\n throw new Error(\"Flow.For requires a finite non-zero step.\");\n }\n\n const iterations = Math.min(count, 10_000);\n const items = Array.from({ length: iterations }, (_, i) => start + i * step);\n\n if (iterations !== count) {\n // Guardrail against accidental infinite or huge loops.\n console.warn(\"Flow.For capped iterations at 10,000 to avoid infinite loops.\");\n }\n\n return (\n <>\n {items.map((value, idx) => (\n <React.Fragment key={value}>{children(value)}</React.Fragment>\n ))}\n </>\n );\n};\n\nexport type FlowBatchProps<T> = {\n items: T[];\n batchSize: number;\n children: (batch: T[], batchIndex: number) => React.ReactNode;\n};\n\nconst chunkItems = <T,>(items: T[], batchSize: number): T[][] => {\n const batches: T[][] = [];\n for (let i = 0; i < items.length; i += batchSize) {\n batches.push(items.slice(i, i + batchSize));\n }\n return batches;\n};\n\nexport const Batch = <T,>({ items, batchSize, children }: FlowBatchProps<T>): React.ReactElement => {\n if (!Number.isInteger(batchSize) || batchSize <= 0) {\n throw new Error(\"Flow.Batch requires a positive integer batchSize.\");\n }\n\n const batches = chunkItems(items, batchSize);\n\n return (\n <ForEach\n items={batches}\n keyExtractor={(_, index) => index}\n >\n {(batch, batchIndex) => children(batch, batchIndex)}\n </ForEach>\n );\n};\n\nexport type FlowSwitchProps<T> = {\n value: T;\n children?: React.ReactNode;\n};\n\nexport type FlowCaseProps<T> = {\n when: T | ((value: T) => boolean);\n children?: React.ReactNode;\n};\n\nexport type FlowDefaultProps = {\n children?: React.ReactNode;\n};\n\nexport const Case = <T,>(_props: FlowCaseProps<T>): React.ReactElement | null => {\n throw new Error(\"Flow.Case must be used within Flow.Switch.\");\n};\n\nexport const Default: React.FC<FlowDefaultProps> = () => {\n throw new Error(\"Flow.Default must be used within Flow.Switch.\");\n};\n\nexport const Switch = <T,>({ value, children }: FlowSwitchProps<T>): React.ReactElement | null => {\n let match: React.ReactNode | null = null;\n let defaultChildren: React.ReactNode | null = null;\n\n const isPredicate = (when: FlowCaseProps<T>[\"when\"]): when is (value: T) => boolean =>\n typeof when === \"function\";\n const isCaseElement = (node: React.ReactNode): node is React.ReactElement<FlowCaseProps<T>> =>\n React.isValidElement(node) && node.type === Case;\n const isDefaultElement = (node: React.ReactNode): node is React.ReactElement<FlowDefaultProps> =>\n React.isValidElement(node) && node.type === Default;\n\n React.Children.forEach(children, (child) => {\n if (match) {\n return;\n }\n if (isDefaultElement(child)) {\n if (defaultChildren === null) {\n defaultChildren = child.props.children;\n }\n return;\n }\n\n if (isCaseElement(child)) {\n const { when, children: caseChildren } = child.props;\n const isMatch = isPredicate(when)\n ? (when as (value: T) => boolean)(value)\n : Object.is(when, value);\n if (isMatch) {\n match = caseChildren;\n }\n }\n });\n\n if (match !== null) {\n return <>{match}</>;\n }\n\n if (defaultChildren !== null) {\n return <>{defaultChildren}</>;\n }\n\n return null;\n};\n\nexport const useFlowCondition = () => {\n const context = React.useContext(FlowConditionContext);\n if (!context.hasProvider) {\n throw new Error(\"useFlowCondition must be used within a Flow.Condition.\");\n }\n return context.value;\n};\n\nexport const ReactFlow = {\n Condition,\n AsyncCondition,\n If,\n Else,\n Unless,\n ForEach,\n For,\n Batch,\n Switch,\n Case,\n Default,\n};\n\n// Legacy alias\nexport const Flow = ReactFlow;\n\nexport type ReactFlowProps = {\n message?: string;\n};\n\nexport const ReactFlowComponent: React.FC<ReactFlowProps> = ({ message = \"Hello from react-flow\" }) => {\n return <div>{message}</div>;\n};\n\nexport default ReactFlowComponent;\n"],"names":["_jsx","_Fragment"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -5,12 +5,20 @@ type FlowConditionProps = {
5
5
  children?: React.ReactNode;
6
6
  };
7
7
  declare const Condition: React.FC<FlowConditionProps>;
8
+ type FlowAsyncConditionProps = {
9
+ value: Promise<boolean> | (() => Promise<boolean>);
10
+ pending?: React.ReactNode;
11
+ error?: (error: unknown) => React.ReactNode;
12
+ children?: React.ReactNode;
13
+ };
14
+ declare const AsyncCondition: React.FC<FlowAsyncConditionProps>;
8
15
  type FlowConditionalBranchProps = {
9
16
  condition?: boolean;
10
17
  children?: React.ReactNode;
11
18
  };
12
19
  declare const If: React.FC<FlowConditionalBranchProps>;
13
20
  declare const Else: React.FC<FlowConditionalBranchProps>;
21
+ declare const Unless: React.FC<FlowConditionalBranchProps>;
14
22
  type FlowForEachProps<T> = {
15
23
  items: T[];
16
24
  keyExtractor?: (item: T, index: number) => React.Key;
@@ -30,19 +38,51 @@ type FlowBatchProps<T> = {
30
38
  children: (batch: T[], batchIndex: number) => React.ReactNode;
31
39
  };
32
40
  declare const Batch: <T>({ items, batchSize, children }: FlowBatchProps<T>) => React.ReactElement;
41
+ type FlowSwitchProps<T> = {
42
+ value: T;
43
+ children?: React.ReactNode;
44
+ };
45
+ type FlowCaseProps<T> = {
46
+ when: T | ((value: T) => boolean);
47
+ children?: React.ReactNode;
48
+ };
49
+ type FlowDefaultProps = {
50
+ children?: React.ReactNode;
51
+ };
52
+ declare const Case: <T>(_props: FlowCaseProps<T>) => React.ReactElement | null;
53
+ declare const Default: React.FC<FlowDefaultProps>;
54
+ declare const Switch: <T>({ value, children }: FlowSwitchProps<T>) => React.ReactElement | null;
33
55
  declare const useFlowCondition: () => boolean;
56
+ declare const ReactFlow: {
57
+ Condition: React.FC<FlowConditionProps>;
58
+ AsyncCondition: React.FC<FlowAsyncConditionProps>;
59
+ If: React.FC<FlowConditionalBranchProps>;
60
+ Else: React.FC<FlowConditionalBranchProps>;
61
+ Unless: React.FC<FlowConditionalBranchProps>;
62
+ ForEach: <T>({ items, keyExtractor, children }: FlowForEachProps<T>) => React.ReactElement;
63
+ For: React.FC<FlowForProps>;
64
+ Batch: <T>({ items, batchSize, children }: FlowBatchProps<T>) => React.ReactElement;
65
+ Switch: <T>({ value, children }: FlowSwitchProps<T>) => React.ReactElement | null;
66
+ Case: <T>(_props: FlowCaseProps<T>) => React.ReactElement | null;
67
+ Default: React.FC<FlowDefaultProps>;
68
+ };
34
69
  declare const Flow: {
35
70
  Condition: React.FC<FlowConditionProps>;
71
+ AsyncCondition: React.FC<FlowAsyncConditionProps>;
36
72
  If: React.FC<FlowConditionalBranchProps>;
37
73
  Else: React.FC<FlowConditionalBranchProps>;
74
+ Unless: React.FC<FlowConditionalBranchProps>;
38
75
  ForEach: <T>({ items, keyExtractor, children }: FlowForEachProps<T>) => React.ReactElement;
39
76
  For: React.FC<FlowForProps>;
40
77
  Batch: <T>({ items, batchSize, children }: FlowBatchProps<T>) => React.ReactElement;
78
+ Switch: <T>({ value, children }: FlowSwitchProps<T>) => React.ReactElement | null;
79
+ Case: <T>(_props: FlowCaseProps<T>) => React.ReactElement | null;
80
+ Default: React.FC<FlowDefaultProps>;
41
81
  };
42
82
  type ReactFlowProps = {
43
83
  message?: string;
44
84
  };
45
- declare const ReactFlow: React.FC<ReactFlowProps>;
85
+ declare const ReactFlowComponent: React.FC<ReactFlowProps>;
46
86
 
47
- export { Batch, Condition, Else, Flow, For, ForEach, If, ReactFlow, ReactFlow as default, useFlowCondition };
48
- export type { FlowBatchProps, FlowConditionProps, FlowConditionalBranchProps, FlowForEachProps, FlowForProps, ReactFlowProps };
87
+ export { AsyncCondition, Batch, Case, Condition, Default, Else, Flow, For, ForEach, If, ReactFlow, ReactFlowComponent, Switch, Unless, ReactFlowComponent as default, useFlowCondition };
88
+ export type { FlowAsyncConditionProps, FlowBatchProps, FlowCaseProps, FlowConditionProps, FlowConditionalBranchProps, FlowDefaultProps, FlowForEachProps, FlowForProps, FlowSwitchProps, ReactFlowProps };
package/dist/index.mjs CHANGED
@@ -8,6 +8,38 @@ const FlowConditionContext = React.createContext({
8
8
  const Condition = ({ value, children }) => {
9
9
  return (jsx(FlowConditionContext.Provider, { value: { value, hasProvider: true }, children: children }));
10
10
  };
11
+ const AsyncCondition = ({ value, pending = null, error, children, }) => {
12
+ var _a;
13
+ const [state, setState] = React.useState({ status: "pending" });
14
+ React.useEffect(() => {
15
+ let active = true;
16
+ const promise = typeof value === "function" ? value() : value;
17
+ Promise.resolve(promise)
18
+ .then((resolved) => {
19
+ if (!active)
20
+ return;
21
+ setState({ status: "resolved", value: resolved });
22
+ })
23
+ .catch((err) => {
24
+ if (!active)
25
+ return;
26
+ setState({ status: "rejected", error: err });
27
+ });
28
+ return () => {
29
+ active = false;
30
+ };
31
+ }, [value]);
32
+ if (state.status === "pending") {
33
+ return jsx(Fragment, { children: pending });
34
+ }
35
+ if (state.status === "rejected") {
36
+ if (error) {
37
+ return jsx(Fragment, { children: error(state.error) });
38
+ }
39
+ throw state.error instanceof Error ? state.error : new Error("Flow.AsyncCondition failed.");
40
+ }
41
+ return (jsx(FlowConditionContext.Provider, { value: { value: (_a = state.value) !== null && _a !== void 0 ? _a : false, hasProvider: true }, children: children }));
42
+ };
11
43
  const resolveCondition = (condition, context, componentName) => {
12
44
  if (typeof condition === "boolean") {
13
45
  return condition;
@@ -27,6 +59,11 @@ const Else = ({ condition, children }) => {
27
59
  const active = resolveCondition(condition, context, "Flow.Else");
28
60
  return !active ? jsx(Fragment, { children: children }) : null;
29
61
  };
62
+ const Unless = ({ condition, children }) => {
63
+ const context = React.useContext(FlowConditionContext);
64
+ const active = resolveCondition(condition, context, "Flow.Unless");
65
+ return !active ? jsx(Fragment, { children: children }) : null;
66
+ };
30
67
  const ForEach = ({ items, keyExtractor, children }) => {
31
68
  return (jsx(Fragment, { children: items.map((item, index) => (jsx(React.Fragment, { children: children(item, index) }, keyExtractor ? keyExtractor(item, index) : index))) }));
32
69
  };
@@ -60,6 +97,46 @@ const Batch = ({ items, batchSize, children }) => {
60
97
  const batches = chunkItems(items, batchSize);
61
98
  return (jsx(ForEach, { items: batches, keyExtractor: (_, index) => index, children: (batch, batchIndex) => children(batch, batchIndex) }));
62
99
  };
100
+ const Case = (_props) => {
101
+ throw new Error("Flow.Case must be used within Flow.Switch.");
102
+ };
103
+ const Default = () => {
104
+ throw new Error("Flow.Default must be used within Flow.Switch.");
105
+ };
106
+ const Switch = ({ value, children }) => {
107
+ let match = null;
108
+ let defaultChildren = null;
109
+ const isPredicate = (when) => typeof when === "function";
110
+ const isCaseElement = (node) => React.isValidElement(node) && node.type === Case;
111
+ const isDefaultElement = (node) => React.isValidElement(node) && node.type === Default;
112
+ React.Children.forEach(children, (child) => {
113
+ if (match) {
114
+ return;
115
+ }
116
+ if (isDefaultElement(child)) {
117
+ if (defaultChildren === null) {
118
+ defaultChildren = child.props.children;
119
+ }
120
+ return;
121
+ }
122
+ if (isCaseElement(child)) {
123
+ const { when, children: caseChildren } = child.props;
124
+ const isMatch = isPredicate(when)
125
+ ? when(value)
126
+ : Object.is(when, value);
127
+ if (isMatch) {
128
+ match = caseChildren;
129
+ }
130
+ }
131
+ });
132
+ if (match !== null) {
133
+ return jsx(Fragment, { children: match });
134
+ }
135
+ if (defaultChildren !== null) {
136
+ return jsx(Fragment, { children: defaultChildren });
137
+ }
138
+ return null;
139
+ };
63
140
  const useFlowCondition = () => {
64
141
  const context = React.useContext(FlowConditionContext);
65
142
  if (!context.hasProvider) {
@@ -67,17 +144,24 @@ const useFlowCondition = () => {
67
144
  }
68
145
  return context.value;
69
146
  };
70
- const Flow = {
147
+ const ReactFlow = {
71
148
  Condition,
149
+ AsyncCondition,
72
150
  If,
73
151
  Else,
152
+ Unless,
74
153
  ForEach,
75
154
  For,
76
155
  Batch,
156
+ Switch,
157
+ Case,
158
+ Default,
77
159
  };
78
- const ReactFlow = ({ message = "Hello from react-flow" }) => {
160
+ // Legacy alias
161
+ const Flow = ReactFlow;
162
+ const ReactFlowComponent = ({ message = "Hello from react-flow" }) => {
79
163
  return jsx("div", { children: message });
80
164
  };
81
165
 
82
- export { Batch, Condition, Else, Flow, For, ForEach, If, ReactFlow, ReactFlow as default, useFlowCondition };
166
+ export { AsyncCondition, Batch, Case, Condition, Default, Else, Flow, For, ForEach, If, ReactFlow, ReactFlowComponent, Switch, Unless, ReactFlowComponent as default, useFlowCondition };
83
167
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\n\ntype FlowConditionContextValue = {\n value: boolean;\n hasProvider: boolean;\n};\n\nconst FlowConditionContext = React.createContext<FlowConditionContextValue>({\n value: false,\n hasProvider: false,\n});\n\nexport type FlowConditionProps = {\n value: boolean;\n children?: React.ReactNode;\n};\n\nexport const Condition: React.FC<FlowConditionProps> = ({ value, children }) => {\n return (\n <FlowConditionContext.Provider value={{ value, hasProvider: true }}>\n {children}\n </FlowConditionContext.Provider>\n );\n};\n\nexport type FlowConditionalBranchProps = {\n condition?: boolean;\n children?: React.ReactNode;\n};\n\nconst resolveCondition = (\n condition: boolean | undefined,\n context: FlowConditionContextValue,\n componentName: string\n) => {\n if (typeof condition === \"boolean\") {\n return condition;\n }\n if (context.hasProvider) {\n return context.value;\n }\n throw new Error(`${componentName} requires a condition prop or Flow.Condition parent.`);\n};\n\nexport const If: React.FC<FlowConditionalBranchProps> = ({ condition, children }) => {\n const context = React.useContext(FlowConditionContext);\n const active = resolveCondition(condition, context, \"Flow.If\");\n return active ? <>{children}</> : null;\n};\n\nexport const Else: React.FC<FlowConditionalBranchProps> = ({ condition, children }) => {\n const context = React.useContext(FlowConditionContext);\n const active = resolveCondition(condition, context, \"Flow.Else\");\n return !active ? <>{children}</> : null;\n};\n\nexport type FlowForEachProps<T> = {\n items: T[];\n keyExtractor?: (item: T, index: number) => React.Key;\n children: (item: T, index: number) => React.ReactNode;\n};\n\nexport const ForEach = <T,>({ items, keyExtractor, children }: FlowForEachProps<T>): React.ReactElement => {\n return (\n <>\n {items.map((item, index) => (\n <React.Fragment key={keyExtractor ? keyExtractor(item, index) : index}>{children(item, index)}</React.Fragment>\n ))}\n </>\n );\n};\n\nexport type FlowForProps = {\n count: number;\n start?: number;\n step?: number;\n children: (index: number) => React.ReactNode;\n};\n\nexport const For: React.FC<FlowForProps> = ({ count, start = 0, step = 1, children }) => {\n if (!Number.isFinite(count) || count < 0) {\n console.warn(\"Flow.For received an invalid count; rendering nothing.\");\n return null;\n }\n if (!Number.isFinite(step) || step === 0) {\n throw new Error(\"Flow.For requires a finite non-zero step.\");\n }\n\n const iterations = Math.min(count, 10_000);\n const items = Array.from({ length: iterations }, (_, i) => start + i * step);\n\n if (iterations !== count) {\n // Guardrail against accidental infinite or huge loops.\n console.warn(\"Flow.For capped iterations at 10,000 to avoid infinite loops.\");\n }\n\n return (\n <>\n {items.map((value, idx) => (\n <React.Fragment key={value}>{children(value)}</React.Fragment>\n ))}\n </>\n );\n};\n\nexport type FlowBatchProps<T> = {\n items: T[];\n batchSize: number;\n children: (batch: T[], batchIndex: number) => React.ReactNode;\n};\n\nconst chunkItems = <T,>(items: T[], batchSize: number): T[][] => {\n const batches: T[][] = [];\n for (let i = 0; i < items.length; i += batchSize) {\n batches.push(items.slice(i, i + batchSize));\n }\n return batches;\n};\n\nexport const Batch = <T,>({ items, batchSize, children }: FlowBatchProps<T>): React.ReactElement => {\n if (!Number.isInteger(batchSize) || batchSize <= 0) {\n throw new Error(\"Flow.Batch requires a positive integer batchSize.\");\n }\n\n const batches = chunkItems(items, batchSize);\n\n return (\n <ForEach\n items={batches}\n keyExtractor={(_, index) => index}\n >\n {(batch, batchIndex) => children(batch, batchIndex)}\n </ForEach>\n );\n};\n\nexport const useFlowCondition = () => {\n const context = React.useContext(FlowConditionContext);\n if (!context.hasProvider) {\n throw new Error(\"useFlowCondition must be used within a Flow.Condition.\");\n }\n return context.value;\n};\n\nexport const Flow = {\n Condition,\n If,\n Else,\n ForEach,\n For,\n Batch,\n};\n\nexport type ReactFlowProps = {\n message?: string;\n};\n\nexport const ReactFlow: React.FC<ReactFlowProps> = ({ message = \"Hello from react-flow\" }) => {\n return <div>{message}</div>;\n};\n\nexport default ReactFlow;\n"],"names":["_jsx","_Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\n\ntype FlowConditionContextValue = {\n value: boolean;\n hasProvider: boolean;\n};\n\nconst FlowConditionContext = React.createContext<FlowConditionContextValue>({\n value: false,\n hasProvider: false,\n});\n\nexport type FlowConditionProps = {\n value: boolean;\n children?: React.ReactNode;\n};\n\nexport const Condition: React.FC<FlowConditionProps> = ({ value, children }) => {\n return (\n <FlowConditionContext.Provider value={{ value, hasProvider: true }}>\n {children}\n </FlowConditionContext.Provider>\n );\n};\n\nexport type FlowAsyncConditionProps = {\n value: Promise<boolean> | (() => Promise<boolean>);\n pending?: React.ReactNode;\n error?: (error: unknown) => React.ReactNode;\n children?: React.ReactNode;\n};\n\nexport const AsyncCondition: React.FC<FlowAsyncConditionProps> = ({\n value,\n pending = null,\n error,\n children,\n}) => {\n const [state, setState] = React.useState<{\n status: \"pending\" | \"resolved\" | \"rejected\";\n value?: boolean;\n error?: unknown;\n }>({ status: \"pending\" });\n\n React.useEffect(() => {\n let active = true;\n const promise = typeof value === \"function\" ? value() : value;\n Promise.resolve(promise)\n .then((resolved) => {\n if (!active) return;\n setState({ status: \"resolved\", value: resolved });\n })\n .catch((err) => {\n if (!active) return;\n setState({ status: \"rejected\", error: err });\n });\n return () => {\n active = false;\n };\n }, [value]);\n\n if (state.status === \"pending\") {\n return <>{pending}</>;\n }\n\n if (state.status === \"rejected\") {\n if (error) {\n return <>{error(state.error)}</>;\n }\n throw state.error instanceof Error ? state.error : new Error(\"Flow.AsyncCondition failed.\");\n }\n\n return (\n <FlowConditionContext.Provider value={{ value: state.value ?? false, hasProvider: true }}>\n {children}\n </FlowConditionContext.Provider>\n );\n};\n\nexport type FlowConditionalBranchProps = {\n condition?: boolean;\n children?: React.ReactNode;\n};\n\nconst resolveCondition = (\n condition: boolean | undefined,\n context: FlowConditionContextValue,\n componentName: string\n) => {\n if (typeof condition === \"boolean\") {\n return condition;\n }\n if (context.hasProvider) {\n return context.value;\n }\n throw new Error(`${componentName} requires a condition prop or Flow.Condition parent.`);\n};\n\nexport const If: React.FC<FlowConditionalBranchProps> = ({ condition, children }) => {\n const context = React.useContext(FlowConditionContext);\n const active = resolveCondition(condition, context, \"Flow.If\");\n return active ? <>{children}</> : null;\n};\n\nexport const Else: React.FC<FlowConditionalBranchProps> = ({ condition, children }) => {\n const context = React.useContext(FlowConditionContext);\n const active = resolveCondition(condition, context, \"Flow.Else\");\n return !active ? <>{children}</> : null;\n};\n\nexport const Unless: React.FC<FlowConditionalBranchProps> = ({ condition, children }) => {\n const context = React.useContext(FlowConditionContext);\n const active = resolveCondition(condition, context, \"Flow.Unless\");\n return !active ? <>{children}</> : null;\n};\n\nexport type FlowForEachProps<T> = {\n items: T[];\n keyExtractor?: (item: T, index: number) => React.Key;\n children: (item: T, index: number) => React.ReactNode;\n};\n\nexport const ForEach = <T,>({ items, keyExtractor, children }: FlowForEachProps<T>): React.ReactElement => {\n return (\n <>\n {items.map((item, index) => (\n <React.Fragment key={keyExtractor ? keyExtractor(item, index) : index}>{children(item, index)}</React.Fragment>\n ))}\n </>\n );\n};\n\nexport type FlowForProps = {\n count: number;\n start?: number;\n step?: number;\n children: (index: number) => React.ReactNode;\n};\n\nexport const For: React.FC<FlowForProps> = ({ count, start = 0, step = 1, children }) => {\n if (!Number.isFinite(count) || count < 0) {\n console.warn(\"Flow.For received an invalid count; rendering nothing.\");\n return null;\n }\n if (!Number.isFinite(step) || step === 0) {\n throw new Error(\"Flow.For requires a finite non-zero step.\");\n }\n\n const iterations = Math.min(count, 10_000);\n const items = Array.from({ length: iterations }, (_, i) => start + i * step);\n\n if (iterations !== count) {\n // Guardrail against accidental infinite or huge loops.\n console.warn(\"Flow.For capped iterations at 10,000 to avoid infinite loops.\");\n }\n\n return (\n <>\n {items.map((value, idx) => (\n <React.Fragment key={value}>{children(value)}</React.Fragment>\n ))}\n </>\n );\n};\n\nexport type FlowBatchProps<T> = {\n items: T[];\n batchSize: number;\n children: (batch: T[], batchIndex: number) => React.ReactNode;\n};\n\nconst chunkItems = <T,>(items: T[], batchSize: number): T[][] => {\n const batches: T[][] = [];\n for (let i = 0; i < items.length; i += batchSize) {\n batches.push(items.slice(i, i + batchSize));\n }\n return batches;\n};\n\nexport const Batch = <T,>({ items, batchSize, children }: FlowBatchProps<T>): React.ReactElement => {\n if (!Number.isInteger(batchSize) || batchSize <= 0) {\n throw new Error(\"Flow.Batch requires a positive integer batchSize.\");\n }\n\n const batches = chunkItems(items, batchSize);\n\n return (\n <ForEach\n items={batches}\n keyExtractor={(_, index) => index}\n >\n {(batch, batchIndex) => children(batch, batchIndex)}\n </ForEach>\n );\n};\n\nexport type FlowSwitchProps<T> = {\n value: T;\n children?: React.ReactNode;\n};\n\nexport type FlowCaseProps<T> = {\n when: T | ((value: T) => boolean);\n children?: React.ReactNode;\n};\n\nexport type FlowDefaultProps = {\n children?: React.ReactNode;\n};\n\nexport const Case = <T,>(_props: FlowCaseProps<T>): React.ReactElement | null => {\n throw new Error(\"Flow.Case must be used within Flow.Switch.\");\n};\n\nexport const Default: React.FC<FlowDefaultProps> = () => {\n throw new Error(\"Flow.Default must be used within Flow.Switch.\");\n};\n\nexport const Switch = <T,>({ value, children }: FlowSwitchProps<T>): React.ReactElement | null => {\n let match: React.ReactNode | null = null;\n let defaultChildren: React.ReactNode | null = null;\n\n const isPredicate = (when: FlowCaseProps<T>[\"when\"]): when is (value: T) => boolean =>\n typeof when === \"function\";\n const isCaseElement = (node: React.ReactNode): node is React.ReactElement<FlowCaseProps<T>> =>\n React.isValidElement(node) && node.type === Case;\n const isDefaultElement = (node: React.ReactNode): node is React.ReactElement<FlowDefaultProps> =>\n React.isValidElement(node) && node.type === Default;\n\n React.Children.forEach(children, (child) => {\n if (match) {\n return;\n }\n if (isDefaultElement(child)) {\n if (defaultChildren === null) {\n defaultChildren = child.props.children;\n }\n return;\n }\n\n if (isCaseElement(child)) {\n const { when, children: caseChildren } = child.props;\n const isMatch = isPredicate(when)\n ? (when as (value: T) => boolean)(value)\n : Object.is(when, value);\n if (isMatch) {\n match = caseChildren;\n }\n }\n });\n\n if (match !== null) {\n return <>{match}</>;\n }\n\n if (defaultChildren !== null) {\n return <>{defaultChildren}</>;\n }\n\n return null;\n};\n\nexport const useFlowCondition = () => {\n const context = React.useContext(FlowConditionContext);\n if (!context.hasProvider) {\n throw new Error(\"useFlowCondition must be used within a Flow.Condition.\");\n }\n return context.value;\n};\n\nexport const ReactFlow = {\n Condition,\n AsyncCondition,\n If,\n Else,\n Unless,\n ForEach,\n For,\n Batch,\n Switch,\n Case,\n Default,\n};\n\n// Legacy alias\nexport const Flow = ReactFlow;\n\nexport type ReactFlowProps = {\n message?: string;\n};\n\nexport const ReactFlowComponent: React.FC<ReactFlowProps> = ({ message = \"Hello from react-flow\" }) => {\n return <div>{message}</div>;\n};\n\nexport default ReactFlowComponent;\n"],"names":["_jsx","_Fragment"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naderikladious/react-flow",
3
- "version": "0.1.3",
3
+ "version": "0.1.7",
4
4
  "description": "Declarative control-flow primitives for React (Condition/If/Else, For/ForEach, Batch) with TypeScript types.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
@@ -15,13 +15,15 @@
15
15
  "bugs": {
16
16
  "url": "https://github.com/NaderIkladious/react-flow/issues"
17
17
  },
18
- "homepage": "https://github.com/NaderIkladious/react-flow#readme",
18
+ "homepage": "https://naderikladious.github.io/react-flow/",
19
19
  "scripts": {
20
20
  "build": "npm run clean && rollup -c",
21
21
  "clean": "rm -rf dist && mkdir -p dist",
22
22
  "dev": "npm run build -- --watch",
23
23
  "lint": "echo 'No linter configured yet'",
24
- "release": "npm run build"
24
+ "release": "npm run build",
25
+ "changelog": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -s",
26
+ "changelog:first": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -s -r 0"
25
27
  },
26
28
  "keywords": [
27
29
  "react",
@@ -43,6 +45,7 @@
43
45
  "@rollup/plugin-commonjs": "^25.0.7",
44
46
  "@rollup/plugin-node-resolve": "^15.2.3",
45
47
  "@rollup/plugin-typescript": "^11.1.6",
48
+ "conventional-changelog-cli": "^4.1.0",
46
49
  "rollup": "^4.9.1",
47
50
  "rollup-plugin-dts": "^6.1.0",
48
51
  "typescript": "^5.3.0"