react-ternary-be-gone 0.1.2 → 0.1.4
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 +41 -14
- package/dist/Case.js +8 -0
- package/dist/Conditional.js +323 -0
- package/dist/Else.js +8 -0
- package/dist/ElseIf.js +8 -0
- package/dist/If.js +8 -0
- package/dist/index.js +44 -0
- package/dist/markers.js +42 -0
- package/dist/useConditionalHelpers.js +59 -0
- package/package.json +18 -5
- package/.babelrc +0 -3
- package/Case.js +0 -8
- package/Conditional.js +0 -328
- package/Else.js +0 -8
- package/ElseIf.js +0 -8
- package/If.js +0 -8
- package/babel.config.js +0 -3
- package/index.js +0 -9
- package/useConditionalHelpers.js +0 -36
package/README.md
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
```markdown
|
|
2
1
|
# React Conditional Component
|
|
3
2
|
|
|
4
3
|
A React component designed to simplify conditional rendering and list iteration, providing a more readable and maintainable alternative to ternary operators and verbose conditional logic.
|
|
@@ -42,9 +41,9 @@ const items = ['Item 1', 'Item 2', 'Item 3'];
|
|
|
42
41
|
const value = 'b';
|
|
43
42
|
|
|
44
43
|
<Conditional switch={value}>
|
|
45
|
-
<Case when="a">A
|
|
46
|
-
<Case when="b">B
|
|
47
|
-
<Case default>
|
|
44
|
+
<Case when="a">A selected</Case>
|
|
45
|
+
<Case when="b">B selected</Case>
|
|
46
|
+
<Case default>None selected</Case>
|
|
48
47
|
</Conditional>
|
|
49
48
|
|
|
50
49
|
// If-ElseIf-Else rendering
|
|
@@ -52,13 +51,13 @@ const status = 'loading';
|
|
|
52
51
|
|
|
53
52
|
<Conditional>
|
|
54
53
|
<If when={status === 'loading'}>
|
|
55
|
-
|
|
54
|
+
<p>Loading...</p>
|
|
56
55
|
</If>
|
|
57
56
|
<ElseIf when={status === 'success'}>
|
|
58
|
-
|
|
57
|
+
<p>Success!</p>
|
|
59
58
|
</ElseIf>
|
|
60
59
|
<Else>
|
|
61
|
-
|
|
60
|
+
<p>Status unknown.</p>
|
|
62
61
|
</Else>
|
|
63
62
|
</Conditional>
|
|
64
63
|
|
|
@@ -70,7 +69,7 @@ const users = [{ id: 1, name: 'Alice', active: true }, { id: 2, name: 'Bob', act
|
|
|
70
69
|
{(user) => <p>{user.name}</p>}
|
|
71
70
|
</If>
|
|
72
71
|
<Else>
|
|
73
|
-
|
|
72
|
+
<p>No users found.</p>
|
|
74
73
|
</Else>
|
|
75
74
|
</Conditional>
|
|
76
75
|
```
|
|
@@ -147,9 +146,9 @@ Child component for use with `switch` prop. Use `when` for matching value, and `
|
|
|
147
146
|
|
|
148
147
|
```javascript
|
|
149
148
|
<Conditional switch={status}>
|
|
150
|
-
<Case when="loading">
|
|
151
|
-
<Case when="success">
|
|
152
|
-
<Case default>
|
|
149
|
+
<Case when="loading">Loading...</Case>
|
|
150
|
+
<Case when="success">Success!</Case>
|
|
151
|
+
<Case default>Status unknown.</Case>
|
|
153
152
|
</Conditional>
|
|
154
153
|
```
|
|
155
154
|
|
|
@@ -241,7 +240,7 @@ const emptyList = [];
|
|
|
241
240
|
|
|
242
241
|
### `loading`
|
|
243
242
|
|
|
244
|
-
A boolean value indicating whether the component is in a loading state. If true,
|
|
243
|
+
A boolean value indicating whether the component is in a loading state. If true, `loadingFallback` (or `fallback`, or a default loading message) will be rendered instead of `children`.
|
|
245
244
|
|
|
246
245
|
**Type:** `boolean`
|
|
247
246
|
|
|
@@ -253,11 +252,25 @@ A boolean value indicating whether the component is in a loading state. If true,
|
|
|
253
252
|
</Conditional>
|
|
254
253
|
```
|
|
255
254
|
|
|
255
|
+
### `loadingFallback`
|
|
256
|
+
|
|
257
|
+
Content to render while `loading` is true, taking priority over `fallback`. Use this when a route or component needs a distinct loading state instead of reusing its "nothing to show" fallback.
|
|
258
|
+
|
|
259
|
+
**Type:** `ReactNode`
|
|
260
|
+
|
|
261
|
+
**Example:**
|
|
262
|
+
|
|
263
|
+
```javascript
|
|
264
|
+
<Conditional loading={isLoading} loadingFallback={<Spinner />} fallback={<p>No data.</p>}>
|
|
265
|
+
<p>Data loaded!</p>
|
|
266
|
+
</Conditional>
|
|
267
|
+
```
|
|
268
|
+
|
|
256
269
|
### `error`
|
|
257
270
|
|
|
258
|
-
An error
|
|
271
|
+
An error value to be displayed if an error occurs. Falsy values (`null`, `undefined`, `false`, `''`) are treated as "no error".
|
|
259
272
|
|
|
260
|
-
**Type:** `string`
|
|
273
|
+
**Type:** `string | Error | any`
|
|
261
274
|
|
|
262
275
|
**Example:**
|
|
263
276
|
|
|
@@ -267,6 +280,20 @@ An error message to be displayed if an error occurs.
|
|
|
267
280
|
</Conditional>
|
|
268
281
|
```
|
|
269
282
|
|
|
283
|
+
### `errorFallback`
|
|
284
|
+
|
|
285
|
+
Content to render instead of the default `Error: ...` message when `error` is set. Accepts a `ReactNode`, or a function that receives the `error` value and returns one.
|
|
286
|
+
|
|
287
|
+
**Type:** `ReactNode | (error: any) => ReactNode`
|
|
288
|
+
|
|
289
|
+
**Example:**
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
<Conditional error={errorMessage} errorFallback={(err) => <Alert>{err}</Alert>}>
|
|
293
|
+
<p>Content.</p>
|
|
294
|
+
</Conditional>
|
|
295
|
+
```
|
|
296
|
+
|
|
270
297
|
### `keyExtractor`
|
|
271
298
|
|
|
272
299
|
A function to extract a unique key for each item when iterating over the `each` array.
|
package/dist/Case.js
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _markers = require("./markers");
|
|
9
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
11
|
+
// Pure helper: apply filter/sort/reverse/limit to an `each` array without
|
|
12
|
+
// mutating the caller's array (Array.prototype.sort/reverse mutate in place,
|
|
13
|
+
// so every step works off a copy).
|
|
14
|
+
const processArray = (array, {
|
|
15
|
+
filter,
|
|
16
|
+
sort,
|
|
17
|
+
reverse,
|
|
18
|
+
limit
|
|
19
|
+
}) => {
|
|
20
|
+
if (!Array.isArray(array)) return [];
|
|
21
|
+
let result = [...array];
|
|
22
|
+
if (typeof filter === 'function') result = result.filter(filter);
|
|
23
|
+
if (typeof sort === 'function') result = result.sort(sort);
|
|
24
|
+
if (reverse) result = result.reverse();
|
|
25
|
+
if (typeof limit === 'number') result = result.slice(0, limit);
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Pure helper: render one React.Fragment per item, guarding the render-prop
|
|
30
|
+
// call so static children (a plain element instead of a function) don't
|
|
31
|
+
// crash when they reach an iteration path.
|
|
32
|
+
const renderIterableChildren = (items, children, keyExtractor) => items.map((item, index) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_react.default.Fragment, {
|
|
33
|
+
children: typeof children === 'function' ? children(item, index, items) : children
|
|
34
|
+
}, keyExtractor ? keyExtractor(item, index) : index));
|
|
35
|
+
|
|
36
|
+
// `React.Children.toArray` flattens arrays produced by `.map()`, but an
|
|
37
|
+
// author-written `<>...</>` around a set of branches is itself a single
|
|
38
|
+
// Fragment element in the tree - its contents need an explicit unwrap or
|
|
39
|
+
// `<If>`/`<ElseIf>`/`<Else>`/`<Case>` inside one are never seen as branches.
|
|
40
|
+
const flattenBranches = children => {
|
|
41
|
+
const result = [];
|
|
42
|
+
_react.default.Children.toArray(children).forEach(child => {
|
|
43
|
+
if (child && child.type === _react.default.Fragment) {
|
|
44
|
+
result.push(...flattenBranches(child.props.children));
|
|
45
|
+
} else {
|
|
46
|
+
result.push(child);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
const Conditional = props => {
|
|
52
|
+
const {
|
|
53
|
+
when,
|
|
54
|
+
each,
|
|
55
|
+
children,
|
|
56
|
+
fallback = null,
|
|
57
|
+
empty = null,
|
|
58
|
+
loading = false,
|
|
59
|
+
loadingFallback = null,
|
|
60
|
+
error = null,
|
|
61
|
+
errorFallback = null,
|
|
62
|
+
keyExtractor = (item, index) => index,
|
|
63
|
+
// New features
|
|
64
|
+
filter = null,
|
|
65
|
+
sort = null,
|
|
66
|
+
limit = null,
|
|
67
|
+
reverse = false,
|
|
68
|
+
animate = false,
|
|
69
|
+
wrapper: Wrapper = _react.default.Fragment,
|
|
70
|
+
debug = false,
|
|
71
|
+
onRender = null,
|
|
72
|
+
// Conditional rendering helpers
|
|
73
|
+
gt = null,
|
|
74
|
+
// greater than
|
|
75
|
+
lt = null,
|
|
76
|
+
// less than
|
|
77
|
+
eq = null,
|
|
78
|
+
// equal
|
|
79
|
+
ne = null,
|
|
80
|
+
// not equal
|
|
81
|
+
includes = null,
|
|
82
|
+
startsWith = null,
|
|
83
|
+
endsWith = null,
|
|
84
|
+
match: matchProp = null,
|
|
85
|
+
// regex match
|
|
86
|
+
// Switch-case feature
|
|
87
|
+
switch: switchValue,
|
|
88
|
+
...rest
|
|
89
|
+
} = props;
|
|
90
|
+
if (process.env.NODE_ENV !== 'production' && Object.keys(rest).length > 0) {
|
|
91
|
+
(0, _markers.warnOnce)(`[react-ternary-be-gone] <Conditional> received unrecognised prop(s): ${Object.keys(rest).join(', ')}. ` + 'Check for a typo - they were ignored.');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// `each={undefined}` (e.g. `each={data?.items}` before data loads) must
|
|
95
|
+
// still enter iteration mode so `empty`/fallback render instead of trying
|
|
96
|
+
// to hand a render-prop function to React as a child. Distinguishing "each
|
|
97
|
+
// was never passed" from "each was passed as undefined" needs the raw
|
|
98
|
+
// props object - destructuring can't tell them apart.
|
|
99
|
+
const hasIteration = 'each' in props;
|
|
100
|
+
const hasComparisonProp = [gt, lt, eq, ne, includes, startsWith, endsWith, matchProp].some(value => value !== null && typeof value === 'object');
|
|
101
|
+
const hasCondition = when !== undefined || hasComparisonProp;
|
|
102
|
+
|
|
103
|
+
// Advanced condition evaluation
|
|
104
|
+
const evaluateCondition = (0, _react.useMemo)(() => {
|
|
105
|
+
if (when !== undefined) return Boolean(when);
|
|
106
|
+
|
|
107
|
+
// Numerical comparisons
|
|
108
|
+
if (gt !== null && typeof gt === 'object') {
|
|
109
|
+
const {
|
|
110
|
+
value,
|
|
111
|
+
target
|
|
112
|
+
} = gt;
|
|
113
|
+
return value > target;
|
|
114
|
+
}
|
|
115
|
+
if (lt !== null && typeof lt === 'object') {
|
|
116
|
+
const {
|
|
117
|
+
value,
|
|
118
|
+
target
|
|
119
|
+
} = lt;
|
|
120
|
+
return value < target;
|
|
121
|
+
}
|
|
122
|
+
if (eq !== null && typeof eq === 'object') {
|
|
123
|
+
const {
|
|
124
|
+
value,
|
|
125
|
+
target
|
|
126
|
+
} = eq;
|
|
127
|
+
return value === target;
|
|
128
|
+
}
|
|
129
|
+
if (ne !== null && typeof ne === 'object') {
|
|
130
|
+
const {
|
|
131
|
+
value,
|
|
132
|
+
target
|
|
133
|
+
} = ne;
|
|
134
|
+
return value !== target;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// String operations
|
|
138
|
+
if (includes !== null && typeof includes === 'object') {
|
|
139
|
+
const {
|
|
140
|
+
value,
|
|
141
|
+
target
|
|
142
|
+
} = includes;
|
|
143
|
+
return String(value).includes(target);
|
|
144
|
+
}
|
|
145
|
+
if (startsWith !== null && typeof startsWith === 'object') {
|
|
146
|
+
const {
|
|
147
|
+
value,
|
|
148
|
+
target
|
|
149
|
+
} = startsWith;
|
|
150
|
+
return String(value).startsWith(target);
|
|
151
|
+
}
|
|
152
|
+
if (endsWith !== null && typeof endsWith === 'object') {
|
|
153
|
+
const {
|
|
154
|
+
value,
|
|
155
|
+
target
|
|
156
|
+
} = endsWith;
|
|
157
|
+
return String(value).endsWith(target);
|
|
158
|
+
}
|
|
159
|
+
if (matchProp !== null && typeof matchProp === 'object') {
|
|
160
|
+
const {
|
|
161
|
+
value,
|
|
162
|
+
pattern
|
|
163
|
+
} = matchProp;
|
|
164
|
+
return new RegExp(pattern).test(String(value));
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
}, [when, gt, lt, eq, ne, includes, startsWith, endsWith, matchProp]);
|
|
168
|
+
|
|
169
|
+
// Array processing
|
|
170
|
+
const processedArray = (0, _react.useMemo)(() => {
|
|
171
|
+
const result = processArray(each, {
|
|
172
|
+
filter,
|
|
173
|
+
sort,
|
|
174
|
+
reverse,
|
|
175
|
+
limit
|
|
176
|
+
});
|
|
177
|
+
if (debug) {
|
|
178
|
+
console.log('Conditional Debug:', {
|
|
179
|
+
original: each,
|
|
180
|
+
processed: result,
|
|
181
|
+
filter: !!filter,
|
|
182
|
+
sort: !!sort,
|
|
183
|
+
reverse,
|
|
184
|
+
limit
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}, [each, filter, sort, reverse, limit, debug]);
|
|
189
|
+
|
|
190
|
+
// Render callback
|
|
191
|
+
(0, _react.useEffect)(() => {
|
|
192
|
+
if (onRender && typeof onRender === 'function') {
|
|
193
|
+
onRender({
|
|
194
|
+
condition: evaluateCondition,
|
|
195
|
+
itemCount: processedArray.length,
|
|
196
|
+
hasCondition,
|
|
197
|
+
hasIteration
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}, [evaluateCondition, processedArray.length, hasCondition, hasIteration, onRender]);
|
|
201
|
+
|
|
202
|
+
// Loading state
|
|
203
|
+
if (loading) {
|
|
204
|
+
return loadingFallback || fallback || /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
205
|
+
className: "conditional-loading",
|
|
206
|
+
children: "Loading..."
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Error state
|
|
211
|
+
if (error) {
|
|
212
|
+
if (errorFallback) {
|
|
213
|
+
return typeof errorFallback === 'function' ? errorFallback(error) : errorFallback;
|
|
214
|
+
}
|
|
215
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
216
|
+
className: "conditional-error",
|
|
217
|
+
children: ["Error: ", error]
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Switch-case logic. Presence, not strict inequality to `undefined`, is
|
|
222
|
+
// what enters this mode - `switch={status}` must still honour `default`
|
|
223
|
+
// while `status` is legitimately undefined before data loads, the same
|
|
224
|
+
// reasoning as the `each` presence check above.
|
|
225
|
+
if ('switch' in props) {
|
|
226
|
+
const caseChildren = flattenBranches(children).filter(child => child && (0, _markers.markerKindOf)(child) === _markers.CASE);
|
|
227
|
+
// `.find()` stops at the first hit, matching how a real `switch` picks
|
|
228
|
+
// the first matching branch instead of the last one.
|
|
229
|
+
const matchedCase = caseChildren.find(child => !child.props.default && child.props.when === switchValue);
|
|
230
|
+
const defaultCase = caseChildren.find(child => child.props.default);
|
|
231
|
+
if (matchedCase) {
|
|
232
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapper, {
|
|
233
|
+
children: matchedCase.props.children
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
if (defaultCase) {
|
|
237
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapper, {
|
|
238
|
+
children: defaultCase.props.children
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
return fallback;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// If-ElseIf-Else logic
|
|
245
|
+
const branches = flattenBranches(children).filter(child => child && [_markers.IF, _markers.ELSE_IF, _markers.ELSE].includes((0, _markers.markerKindOf)(child)));
|
|
246
|
+
if (branches.length > 0) {
|
|
247
|
+
let rendered = fallback;
|
|
248
|
+
for (const branch of branches) {
|
|
249
|
+
const kind = (0, _markers.markerKindOf)(branch);
|
|
250
|
+
const {
|
|
251
|
+
when: branchWhen,
|
|
252
|
+
each: branchEach,
|
|
253
|
+
filter: branchFilter,
|
|
254
|
+
sort: branchSort,
|
|
255
|
+
limit: branchLimit,
|
|
256
|
+
reverse: branchReverse,
|
|
257
|
+
wrapper: BranchWrapper = _react.default.Fragment,
|
|
258
|
+
keyExtractor: branchKeyExtractor,
|
|
259
|
+
empty: branchEmpty,
|
|
260
|
+
fallback: branchFallback,
|
|
261
|
+
children: branchChildren
|
|
262
|
+
} = branch.props;
|
|
263
|
+
const matches = kind === _markers.ELSE || Boolean(branchWhen);
|
|
264
|
+
if (!matches) continue;
|
|
265
|
+
if ('each' in branch.props) {
|
|
266
|
+
const items = processArray(branchEach, {
|
|
267
|
+
filter: branchFilter,
|
|
268
|
+
sort: branchSort,
|
|
269
|
+
reverse: branchReverse,
|
|
270
|
+
limit: branchLimit
|
|
271
|
+
});
|
|
272
|
+
rendered = items.length === 0 ? branchEmpty || branchFallback || null : /*#__PURE__*/(0, _jsxRuntime.jsx)(BranchWrapper, {
|
|
273
|
+
children: renderIterableChildren(items, branchChildren, branchKeyExtractor)
|
|
274
|
+
});
|
|
275
|
+
} else {
|
|
276
|
+
rendered = /*#__PURE__*/(0, _jsxRuntime.jsx)(BranchWrapper, {
|
|
277
|
+
children: branchChildren
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
return rendered;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Only condition
|
|
286
|
+
if (hasCondition && !hasIteration) {
|
|
287
|
+
return evaluateCondition ? /*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapper, {
|
|
288
|
+
children: children
|
|
289
|
+
}) : fallback;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Only iteration
|
|
293
|
+
if (!hasCondition && hasIteration) {
|
|
294
|
+
if (processedArray.length === 0) {
|
|
295
|
+
return empty || fallback;
|
|
296
|
+
}
|
|
297
|
+
const elements = renderIterableChildren(processedArray, children, keyExtractor);
|
|
298
|
+
// React.Fragment rejects unknown props like `className`, so the default
|
|
299
|
+
// wrapper is swapped for a real host element whenever `animate` needs
|
|
300
|
+
// somewhere to put the class.
|
|
301
|
+
const AnimatedWrapper = animate && Wrapper === _react.default.Fragment ? 'div' : Wrapper;
|
|
302
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(AnimatedWrapper, {
|
|
303
|
+
...(animate ? {
|
|
304
|
+
className: 'conditional-animated'
|
|
305
|
+
} : null),
|
|
306
|
+
children: elements
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Both condition and iteration
|
|
311
|
+
if (hasCondition && hasIteration) {
|
|
312
|
+
if (!evaluateCondition) return fallback;
|
|
313
|
+
if (processedArray.length === 0) return empty || fallback;
|
|
314
|
+
const elements = renderIterableChildren(processedArray, children, keyExtractor);
|
|
315
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapper, {
|
|
316
|
+
children: elements
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Wrapper, {
|
|
320
|
+
children: children
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
var _default = exports.default = Conditional;
|
package/dist/Else.js
ADDED
package/dist/ElseIf.js
ADDED
package/dist/If.js
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "Case", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _Case.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "Else", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _Else.default;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "ElseIf", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _ElseIf.default;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "If", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _If.default;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
exports.default = void 0;
|
|
31
|
+
Object.defineProperty(exports, "useConditionalHelpers", {
|
|
32
|
+
enumerable: true,
|
|
33
|
+
get: function () {
|
|
34
|
+
return _useConditionalHelpers.useConditionalHelpers;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
var _Conditional = _interopRequireDefault(require("./Conditional"));
|
|
38
|
+
var _Case = _interopRequireDefault(require("./Case"));
|
|
39
|
+
var _If = _interopRequireDefault(require("./If"));
|
|
40
|
+
var _ElseIf = _interopRequireDefault(require("./ElseIf"));
|
|
41
|
+
var _Else = _interopRequireDefault(require("./Else"));
|
|
42
|
+
var _useConditionalHelpers = require("./useConditionalHelpers");
|
|
43
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
44
|
+
var _default = exports.default = _Conditional.default;
|
package/dist/markers.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.warnOnce = exports.markerKindOf = exports.createMarker = exports.IF = exports.ELSE_IF = exports.ELSE = exports.CASE = void 0;
|
|
7
|
+
// Branch markers (`If`, `ElseIf`, `Else`, `Case`) are never rendered by React
|
|
8
|
+
// when they are used correctly: `Conditional` reads their props and renders the
|
|
9
|
+
// winning branch itself. They exist only so that JSX can express the shape.
|
|
10
|
+
//
|
|
11
|
+
// Identifying them by reference (`child.type === If`) breaks as soon as two
|
|
12
|
+
// copies of this package end up in node_modules, so each marker carries a
|
|
13
|
+
// static tag instead.
|
|
14
|
+
|
|
15
|
+
const IF = exports.IF = 'if';
|
|
16
|
+
const ELSE_IF = exports.ELSE_IF = 'elseif';
|
|
17
|
+
const ELSE = exports.ELSE = 'else';
|
|
18
|
+
const CASE = exports.CASE = 'case';
|
|
19
|
+
const TAG = '$$rtbgMarker';
|
|
20
|
+
const warned = new Set();
|
|
21
|
+
const warnOnce = message => {
|
|
22
|
+
if (warned.has(message)) return;
|
|
23
|
+
warned.add(message);
|
|
24
|
+
console.warn(message);
|
|
25
|
+
};
|
|
26
|
+
exports.warnOnce = warnOnce;
|
|
27
|
+
const createMarker = (name, kind) => {
|
|
28
|
+
// Rendering nothing is the safe default: a marker that slipped outside a
|
|
29
|
+
// `Conditional` must not leak the content it was meant to gate.
|
|
30
|
+
const Marker = () => {
|
|
31
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
32
|
+
warnOnce(`[react-ternary-be-gone] <${name}> only works as a child of <Conditional>. ` + 'It rendered nothing.');
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
};
|
|
36
|
+
Marker.displayName = name;
|
|
37
|
+
Marker[TAG] = kind;
|
|
38
|
+
return Marker;
|
|
39
|
+
};
|
|
40
|
+
exports.createMarker = createMarker;
|
|
41
|
+
const markerKindOf = element => element && element.type && element.type[TAG] || null;
|
|
42
|
+
exports.markerKindOf = markerKindOf;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useConditionalHelpers = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
const useConditionalHelpers = () => {
|
|
9
|
+
return (0, _react.useMemo)(() => ({
|
|
10
|
+
// Quick condition helpers
|
|
11
|
+
isEmpty: array => ({
|
|
12
|
+
when: !array || array.length === 0
|
|
13
|
+
}),
|
|
14
|
+
isNotEmpty: array => ({
|
|
15
|
+
when: Boolean(array && array.length > 0)
|
|
16
|
+
}),
|
|
17
|
+
hasLength: (array, length) => ({
|
|
18
|
+
when: Boolean(array && array.length === length)
|
|
19
|
+
}),
|
|
20
|
+
isEven: num => ({
|
|
21
|
+
when: num % 2 === 0
|
|
22
|
+
}),
|
|
23
|
+
isOdd: num => ({
|
|
24
|
+
when: num % 2 !== 0
|
|
25
|
+
}),
|
|
26
|
+
// Array processing helpers
|
|
27
|
+
sortBy: (field, order = 'asc') => (a, b) => {
|
|
28
|
+
const aValue = a[field];
|
|
29
|
+
const bValue = b[field];
|
|
30
|
+
|
|
31
|
+
// `<`/`>` compare strings by raw UTF-16 code unit, which misorders
|
|
32
|
+
// accented letters (Ç, Ğ, İ, Ö, Ş, Ü, ...). localeCompare sorts them
|
|
33
|
+
// the way a person reading the list would expect.
|
|
34
|
+
let comparison;
|
|
35
|
+
if (typeof aValue === 'string' && typeof bValue === 'string') {
|
|
36
|
+
comparison = aValue.localeCompare(bValue);
|
|
37
|
+
} else if (aValue < bValue) {
|
|
38
|
+
comparison = -1;
|
|
39
|
+
} else if (aValue > bValue) {
|
|
40
|
+
comparison = 1;
|
|
41
|
+
} else {
|
|
42
|
+
comparison = 0;
|
|
43
|
+
}
|
|
44
|
+
return order === 'asc' ? comparison : -comparison;
|
|
45
|
+
},
|
|
46
|
+
filterBy: (field, value) => item => item[field] === value,
|
|
47
|
+
unique: (array, key) => {
|
|
48
|
+
if (!array) return [];
|
|
49
|
+
const seen = new Set();
|
|
50
|
+
return array.filter(item => {
|
|
51
|
+
const keyValue = typeof key === 'function' ? key(item) : item[key];
|
|
52
|
+
const isNew = !seen.has(keyValue);
|
|
53
|
+
seen.add(keyValue);
|
|
54
|
+
return isNew;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}), []);
|
|
58
|
+
};
|
|
59
|
+
exports.useConditionalHelpers = useConditionalHelpers;
|
package/package.json
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-ternary-be-gone",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "A React component designed to simplify conditional rendering and list iteration, providing a more readable and maintainable alternative to ternary operators and verbose conditional logic.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
6
9
|
"scripts": {
|
|
7
|
-
"test": "
|
|
8
|
-
"
|
|
10
|
+
"test": "vitest run",
|
|
11
|
+
"test:watch": "vitest",
|
|
12
|
+
"build": "babel src --out-dir dist --out-file-extension .js",
|
|
13
|
+
"prepublishOnly": "npm test && npm run build"
|
|
9
14
|
},
|
|
10
15
|
"peerDependencies": {
|
|
11
16
|
"react": ">=16.8.0"
|
|
@@ -26,7 +31,15 @@
|
|
|
26
31
|
},
|
|
27
32
|
"homepage": "https://github.com/sundowatch/react-ternary-be-gone#readme",
|
|
28
33
|
"devDependencies": {
|
|
29
|
-
"@babel/cli": "^
|
|
30
|
-
"@babel/
|
|
34
|
+
"@babel/cli": "^8.0.0",
|
|
35
|
+
"@babel/core": "^8.0.0",
|
|
36
|
+
"@babel/preset-env": "^8.0.0",
|
|
37
|
+
"@babel/preset-react": "^8.0.0",
|
|
38
|
+
"@testing-library/react": "^16.3.3",
|
|
39
|
+
"@vitejs/plugin-react": "^5.0.0",
|
|
40
|
+
"jsdom": "^30.1.1",
|
|
41
|
+
"react": "^19.3.0",
|
|
42
|
+
"react-dom": "^19.3.0",
|
|
43
|
+
"vitest": "^5.0.1"
|
|
31
44
|
}
|
|
32
45
|
}
|
package/.babelrc
DELETED
package/Case.js
DELETED
package/Conditional.js
DELETED
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
import React, { useMemo, useEffect } from 'react';
|
|
2
|
-
import Case from './Case';
|
|
3
|
-
import If from './If';
|
|
4
|
-
import ElseIf from './ElseIf';
|
|
5
|
-
import Else from './Else';
|
|
6
|
-
|
|
7
|
-
const Conditional = ({
|
|
8
|
-
when,
|
|
9
|
-
each,
|
|
10
|
-
children,
|
|
11
|
-
fallback = null,
|
|
12
|
-
empty = null,
|
|
13
|
-
loading = false,
|
|
14
|
-
error = null,
|
|
15
|
-
keyExtractor = (item, index) => index,
|
|
16
|
-
// New features
|
|
17
|
-
filter = null,
|
|
18
|
-
sort = null,
|
|
19
|
-
limit = null,
|
|
20
|
-
reverse = false,
|
|
21
|
-
animate = false,
|
|
22
|
-
wrapper = React.Fragment,
|
|
23
|
-
debug = false,
|
|
24
|
-
onRender = null,
|
|
25
|
-
// Conditional rendering helpers
|
|
26
|
-
gt = null, // greater than
|
|
27
|
-
lt = null, // less than
|
|
28
|
-
eq = null, // equal
|
|
29
|
-
ne = null, // not equal
|
|
30
|
-
includes = null,
|
|
31
|
-
startsWith = null,
|
|
32
|
-
endsWith = null,
|
|
33
|
-
match = null, // regex match
|
|
34
|
-
// Switch-case feature
|
|
35
|
-
switch: switchValue,
|
|
36
|
-
}) => {
|
|
37
|
-
const hasCondition = when !== undefined;
|
|
38
|
-
const hasIteration = each !== undefined;
|
|
39
|
-
|
|
40
|
-
// Advanced condition evaluation
|
|
41
|
-
const evaluateCondition = useMemo(() => {
|
|
42
|
-
if (when !== undefined) return Boolean(when);
|
|
43
|
-
|
|
44
|
-
// Numerical comparisons
|
|
45
|
-
if (gt !== null && typeof gt === 'object') {
|
|
46
|
-
const { value, target } = gt;
|
|
47
|
-
return value > target;
|
|
48
|
-
}
|
|
49
|
-
if (lt !== null && typeof lt === 'object') {
|
|
50
|
-
const { value, target } = lt;
|
|
51
|
-
return value < target;
|
|
52
|
-
}
|
|
53
|
-
if (eq !== null && typeof eq === 'object') {
|
|
54
|
-
const { value, target } = eq;
|
|
55
|
-
return value === target;
|
|
56
|
-
}
|
|
57
|
-
if (ne !== null && typeof ne === 'object') {
|
|
58
|
-
const { value, target } = ne;
|
|
59
|
-
return value !== target;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// String operations
|
|
63
|
-
if (includes !== null && typeof includes === 'object') {
|
|
64
|
-
const { value, target } = includes;
|
|
65
|
-
return String(value).includes(target);
|
|
66
|
-
}
|
|
67
|
-
if (startsWith !== null && typeof startsWith === 'object') {
|
|
68
|
-
const { value, target } = startsWith;
|
|
69
|
-
return String(value).startsWith(target);
|
|
70
|
-
}
|
|
71
|
-
if (endsWith !== null && typeof endsWith === 'object') {
|
|
72
|
-
const { value, target } = endsWith;
|
|
73
|
-
return String(value).endsWith(target);
|
|
74
|
-
}
|
|
75
|
-
if (match !== null && typeof match === 'object') {
|
|
76
|
-
const { value, pattern } = match;
|
|
77
|
-
return new RegExp(pattern).test(String(value));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return true;
|
|
81
|
-
}, [when, gt, lt, eq, ne, includes, startsWith, endsWith, match]);
|
|
82
|
-
|
|
83
|
-
// Array processing
|
|
84
|
-
const processedArray = useMemo(() => {
|
|
85
|
-
if (!hasIteration || !Array.isArray(each)) return [];
|
|
86
|
-
|
|
87
|
-
let result = [...each];
|
|
88
|
-
|
|
89
|
-
// Apply filter
|
|
90
|
-
if (filter && typeof filter === 'function') {
|
|
91
|
-
result = result.filter(filter);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Apply sort
|
|
95
|
-
if (sort && typeof sort === 'function') {
|
|
96
|
-
result = result.sort(sort);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Apply reverse
|
|
100
|
-
if (reverse) {
|
|
101
|
-
result = result.reverse();
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Apply limit
|
|
105
|
-
if (limit && typeof limit === 'number') {
|
|
106
|
-
result = result.slice(0, limit);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
if (debug) {
|
|
110
|
-
console.log('Conditional Debug:', {
|
|
111
|
-
original: each,
|
|
112
|
-
processed: result,
|
|
113
|
-
filter: !!filter,
|
|
114
|
-
sort: !!sort,
|
|
115
|
-
reverse,
|
|
116
|
-
limit
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return result;
|
|
121
|
-
}, [each, filter, sort, reverse, limit, hasIteration, debug]);
|
|
122
|
-
|
|
123
|
-
// Render callback
|
|
124
|
-
useEffect(() => {
|
|
125
|
-
if (onRender && typeof onRender === 'function') {
|
|
126
|
-
onRender({
|
|
127
|
-
condition: evaluateCondition,
|
|
128
|
-
itemCount: processedArray.length,
|
|
129
|
-
hasCondition,
|
|
130
|
-
hasIteration
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}, [evaluateCondition, processedArray.length, hasCondition, hasIteration, onRender]);
|
|
134
|
-
|
|
135
|
-
// Loading state
|
|
136
|
-
if (loading) {
|
|
137
|
-
return fallback || <div className="conditional-loading">Loading...</div>;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Error state
|
|
141
|
-
if (error) {
|
|
142
|
-
return <div className="conditional-error">Error: {error}</div>;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Wrapper component
|
|
146
|
-
const WrapperComponent = wrapper;
|
|
147
|
-
|
|
148
|
-
// Switch-case logic
|
|
149
|
-
if (switchValue !== undefined) {
|
|
150
|
-
// Find all Case children
|
|
151
|
-
const caseChildren = React.Children.toArray(children).filter(
|
|
152
|
-
child => child && child.type === Case
|
|
153
|
-
);
|
|
154
|
-
// Find matching case
|
|
155
|
-
let match = null;
|
|
156
|
-
let defaultCase = null;
|
|
157
|
-
caseChildren.forEach(child => {
|
|
158
|
-
if (child.props.default) {
|
|
159
|
-
defaultCase = child;
|
|
160
|
-
} else if (child.props.when === switchValue) {
|
|
161
|
-
match = child;
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
if (match) {
|
|
165
|
-
return <WrapperComponent>{match.props.children}</WrapperComponent>;
|
|
166
|
-
} else if (defaultCase) {
|
|
167
|
-
return <WrapperComponent>{defaultCase.props.children}</WrapperComponent>;
|
|
168
|
-
} else {
|
|
169
|
-
return fallback;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// If-ElseIf-Else logic
|
|
174
|
-
const childrenArray = React.Children.toArray(children);
|
|
175
|
-
const ifElseBlocks = childrenArray.filter(child =>
|
|
176
|
-
child && (child.type === If || child.type === ElseIf || child.type === Else)
|
|
177
|
-
);
|
|
178
|
-
if (ifElseBlocks.length > 0) {
|
|
179
|
-
let rendered = null;
|
|
180
|
-
for (let i = 0; i < ifElseBlocks.length; i++) {
|
|
181
|
-
const child = ifElseBlocks[i];
|
|
182
|
-
// Extract Conditional props from child
|
|
183
|
-
const {
|
|
184
|
-
when,
|
|
185
|
-
each,
|
|
186
|
-
filter,
|
|
187
|
-
sort,
|
|
188
|
-
limit,
|
|
189
|
-
reverse,
|
|
190
|
-
animate,
|
|
191
|
-
wrapper: childWrapper,
|
|
192
|
-
keyExtractor: childKeyExtractor,
|
|
193
|
-
empty: childEmpty,
|
|
194
|
-
fallback: childFallback,
|
|
195
|
-
...rest
|
|
196
|
-
} = child.props;
|
|
197
|
-
|
|
198
|
-
// Evaluate condition
|
|
199
|
-
let condition = true;
|
|
200
|
-
if (child.type === If || child.type === ElseIf) {
|
|
201
|
-
condition = Boolean(when);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Array processing for each
|
|
205
|
-
let arrayItems = [];
|
|
206
|
-
if (each && Array.isArray(each)) {
|
|
207
|
-
arrayItems = [...each];
|
|
208
|
-
if (filter && typeof filter === 'function') {
|
|
209
|
-
arrayItems = arrayItems.filter(filter);
|
|
210
|
-
}
|
|
211
|
-
if (sort && typeof sort === 'function') {
|
|
212
|
-
arrayItems = arrayItems.sort(sort);
|
|
213
|
-
}
|
|
214
|
-
if (reverse) {
|
|
215
|
-
arrayItems = arrayItems.reverse();
|
|
216
|
-
}
|
|
217
|
-
if (limit && typeof limit === 'number') {
|
|
218
|
-
arrayItems = arrayItems.slice(0, limit);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Render logic
|
|
223
|
-
if ((child.type === If || child.type === ElseIf) && condition) {
|
|
224
|
-
if (each && Array.isArray(each)) {
|
|
225
|
-
if (arrayItems.length === 0) {
|
|
226
|
-
rendered = childEmpty || childFallback || null;
|
|
227
|
-
break;
|
|
228
|
-
}
|
|
229
|
-
const elements = arrayItems.map((item, idx) => (
|
|
230
|
-
<React.Fragment key={childKeyExtractor ? childKeyExtractor(item, idx) : idx}>
|
|
231
|
-
{typeof child.props.children === 'function'
|
|
232
|
-
? child.props.children(item, idx, arrayItems)
|
|
233
|
-
: child.props.children}
|
|
234
|
-
</React.Fragment>
|
|
235
|
-
));
|
|
236
|
-
rendered = childWrapper
|
|
237
|
-
? React.createElement(childWrapper, null, elements)
|
|
238
|
-
: <>{elements}</>;
|
|
239
|
-
break;
|
|
240
|
-
} else {
|
|
241
|
-
rendered = childWrapper
|
|
242
|
-
? React.createElement(childWrapper, null, child.props.children)
|
|
243
|
-
: <>{child.props.children}</>;
|
|
244
|
-
break;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
if (child.type === Else) {
|
|
248
|
-
if (each && Array.isArray(each)) {
|
|
249
|
-
if (arrayItems.length === 0) {
|
|
250
|
-
rendered = childEmpty || childFallback || null;
|
|
251
|
-
break;
|
|
252
|
-
}
|
|
253
|
-
const elements = arrayItems.map((item, idx) => (
|
|
254
|
-
<React.Fragment key={childKeyExtractor ? childKeyExtractor(item, idx) : idx}>
|
|
255
|
-
{typeof child.props.children === 'function'
|
|
256
|
-
? child.props.children(item, idx, arrayItems)
|
|
257
|
-
: child.props.children}
|
|
258
|
-
</React.Fragment>
|
|
259
|
-
));
|
|
260
|
-
rendered = childWrapper
|
|
261
|
-
? React.createElement(childWrapper, null, elements)
|
|
262
|
-
: <>{elements}</>;
|
|
263
|
-
break;
|
|
264
|
-
} else {
|
|
265
|
-
rendered = childWrapper
|
|
266
|
-
? React.createElement(childWrapper, null, child.props.children)
|
|
267
|
-
: <>{child.props.children}</>;
|
|
268
|
-
break;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
return rendered;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// Only condition
|
|
276
|
-
if (hasCondition && !hasIteration) {
|
|
277
|
-
return evaluateCondition ? (
|
|
278
|
-
<WrapperComponent>
|
|
279
|
-
{children}
|
|
280
|
-
</WrapperComponent>
|
|
281
|
-
) : fallback;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Only iteration
|
|
285
|
-
if (!hasCondition && hasIteration) {
|
|
286
|
-
if (processedArray.length === 0) {
|
|
287
|
-
return empty || fallback;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const elements = processedArray.map((item, index) => (
|
|
291
|
-
<React.Fragment key={keyExtractor(item, index)}>
|
|
292
|
-
{typeof children === 'function' ? children(item, index, processedArray) : children}
|
|
293
|
-
</React.Fragment>
|
|
294
|
-
));
|
|
295
|
-
|
|
296
|
-
return animate ? (
|
|
297
|
-
<WrapperComponent className="conditional-animated">
|
|
298
|
-
{elements}
|
|
299
|
-
</WrapperComponent>
|
|
300
|
-
) : (
|
|
301
|
-
<WrapperComponent>
|
|
302
|
-
{elements}
|
|
303
|
-
</WrapperComponent>
|
|
304
|
-
);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Both condition and iteration
|
|
308
|
-
if (hasCondition && hasIteration) {
|
|
309
|
-
if (!evaluateCondition) return fallback;
|
|
310
|
-
if (processedArray.length === 0) return empty || fallback;
|
|
311
|
-
|
|
312
|
-
const elements = processedArray.map((item, index) => (
|
|
313
|
-
<React.Fragment key={keyExtractor(item, index)}>
|
|
314
|
-
{children(item, index, processedArray)}
|
|
315
|
-
</React.Fragment>
|
|
316
|
-
));
|
|
317
|
-
|
|
318
|
-
return (
|
|
319
|
-
<WrapperComponent>
|
|
320
|
-
{elements}
|
|
321
|
-
</WrapperComponent>
|
|
322
|
-
);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
return <WrapperComponent>{children}</WrapperComponent>;
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
export default Conditional;
|
package/Else.js
DELETED
package/ElseIf.js
DELETED
package/If.js
DELETED
package/babel.config.js
DELETED
package/index.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import Conditional from './Conditional';
|
|
2
|
-
import Case from './Case';
|
|
3
|
-
import If from './If';
|
|
4
|
-
import ElseIf from './ElseIf';
|
|
5
|
-
import Else from './Else';
|
|
6
|
-
import { useConditionalHelpers } from './useConditionalHelpers';
|
|
7
|
-
|
|
8
|
-
export default Conditional;
|
|
9
|
-
export { Case, If, ElseIf, Else, useConditionalHelpers };
|
package/useConditionalHelpers.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
|
|
3
|
-
export const useConditionalHelpers = () => {
|
|
4
|
-
return useMemo(() => ({
|
|
5
|
-
// Quick condition helpers
|
|
6
|
-
isEmpty: (array) => ({ when: !array || array.length === 0 }),
|
|
7
|
-
isNotEmpty: (array) => ({ when: array && array.length > 0 }),
|
|
8
|
-
hasLength: (array, length) => ({ when: array && array.length === length }),
|
|
9
|
-
isEven: (num) => ({ when: num % 2 === 0 }),
|
|
10
|
-
isOdd: (num) => ({ when: num % 2 !== 0 }),
|
|
11
|
-
|
|
12
|
-
// Array processing helpers
|
|
13
|
-
sortBy: (field, order = 'asc') => (a, b) => {
|
|
14
|
-
const aValue = a[field];
|
|
15
|
-
const bValue = b[field];
|
|
16
|
-
|
|
17
|
-
if (aValue < bValue) {
|
|
18
|
-
return order === 'asc' ? -1 : 1;
|
|
19
|
-
}
|
|
20
|
-
if (aValue > bValue) {
|
|
21
|
-
return order === 'asc' ? 1 : -1;
|
|
22
|
-
}
|
|
23
|
-
return 0;
|
|
24
|
-
},
|
|
25
|
-
filterBy: (field, value) => (item) => item[field] === value,
|
|
26
|
-
unique: (array, key) => {
|
|
27
|
-
const seen = new Set();
|
|
28
|
-
return array.filter(item => {
|
|
29
|
-
const keyValue = typeof key === 'function' ? key(item) : item[key];
|
|
30
|
-
const isNew = !seen.has(keyValue);
|
|
31
|
-
seen.add(keyValue);
|
|
32
|
-
return isNew;
|
|
33
|
-
});
|
|
34
|
-
},
|
|
35
|
-
}), []);
|
|
36
|
-
};
|