react-ternary-be-gone 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/Conditional.js ADDED
@@ -0,0 +1,195 @@
1
+ import React, { useMemo, useEffect } from 'react';
2
+
3
+ const Conditional = ({
4
+ when,
5
+ each,
6
+ children,
7
+ fallback = null,
8
+ empty = null,
9
+ loading = false,
10
+ error = null,
11
+ keyExtractor = (item, index) => index,
12
+ // New features
13
+ filter = null,
14
+ sort = null,
15
+ limit = null,
16
+ reverse = false,
17
+ animate = false,
18
+ wrapper = React.Fragment,
19
+ debug = false,
20
+ onRender = null,
21
+ // Conditional rendering helpers
22
+ gt = null, // greater than
23
+ lt = null, // less than
24
+ eq = null, // equal
25
+ ne = null, // not equal
26
+ includes = null,
27
+ startsWith = null,
28
+ endsWith = null,
29
+ match = null, // regex match
30
+ }) => {
31
+ const hasCondition = when !== undefined;
32
+ const hasIteration = each !== undefined;
33
+
34
+ // Advanced condition evaluation
35
+ const evaluateCondition = useMemo(() => {
36
+ if (when !== undefined) return Boolean(when);
37
+
38
+ // Numerical comparisons
39
+ if (gt !== null && typeof gt === 'object') {
40
+ const { value, target } = gt;
41
+ return value > target;
42
+ }
43
+ if (lt !== null && typeof lt === 'object') {
44
+ const { value, target } = lt;
45
+ return value < target;
46
+ }
47
+ if (eq !== null && typeof eq === 'object') {
48
+ const { value, target } = eq;
49
+ return value === target;
50
+ }
51
+ if (ne !== null && typeof ne === 'object') {
52
+ const { value, target } = ne;
53
+ return value !== target;
54
+ }
55
+
56
+ // String operations
57
+ if (includes !== null && typeof includes === 'object') {
58
+ const { value, target } = includes;
59
+ return String(value).includes(target);
60
+ }
61
+ if (startsWith !== null && typeof startsWith === 'object') {
62
+ const { value, target } = startsWith;
63
+ return String(value).startsWith(target);
64
+ }
65
+ if (endsWith !== null && typeof endsWith === 'object') {
66
+ const { value, target } = endsWith;
67
+ return String(value).endsWith(target);
68
+ }
69
+ if (match !== null && typeof match === 'object') {
70
+ const { value, pattern } = match;
71
+ return new RegExp(pattern).test(String(value));
72
+ }
73
+
74
+ return true;
75
+ }, [when, gt, lt, eq, ne, includes, startsWith, endsWith, match]);
76
+
77
+ // Array processing
78
+ const processedArray = useMemo(() => {
79
+ if (!hasIteration || !Array.isArray(each)) return [];
80
+
81
+ let result = [...each];
82
+
83
+ // Apply filter
84
+ if (filter && typeof filter === 'function') {
85
+ result = result.filter(filter);
86
+ }
87
+
88
+ // Apply sort
89
+ if (sort && typeof sort === 'function') {
90
+ result = result.sort(sort);
91
+ }
92
+
93
+ // Apply reverse
94
+ if (reverse) {
95
+ result = result.reverse();
96
+ }
97
+
98
+ // Apply limit
99
+ if (limit && typeof limit === 'number') {
100
+ result = result.slice(0, limit);
101
+ }
102
+
103
+ if (debug) {
104
+ console.log('Conditional Debug:', {
105
+ original: each,
106
+ processed: result,
107
+ filter: !!filter,
108
+ sort: !!sort,
109
+ reverse,
110
+ limit
111
+ });
112
+ }
113
+
114
+ return result;
115
+ }, [each, filter, sort, reverse, limit, hasIteration, debug]);
116
+
117
+ // Render callback
118
+ useEffect(() => {
119
+ if (onRender && typeof onRender === 'function') {
120
+ onRender({
121
+ condition: evaluateCondition,
122
+ itemCount: processedArray.length,
123
+ hasCondition,
124
+ hasIteration
125
+ });
126
+ }
127
+ }, [evaluateCondition, processedArray.length, hasCondition, hasIteration, onRender]);
128
+
129
+ // Loading state
130
+ if (loading) {
131
+ return fallback || <div className="conditional-loading">Loading...</div>;
132
+ }
133
+
134
+ // Error state
135
+ if (error) {
136
+ return <div className="conditional-error">Error: {error}</div>;
137
+ }
138
+
139
+ // Wrapper component
140
+ const WrapperComponent = wrapper;
141
+
142
+ // Only condition
143
+ if (hasCondition && !hasIteration) {
144
+ return evaluateCondition ? (
145
+ <WrapperComponent>
146
+ {children}
147
+ </WrapperComponent>
148
+ ) : fallback;
149
+ }
150
+
151
+ // Only iteration
152
+ if (!hasCondition && hasIteration) {
153
+ if (processedArray.length === 0) {
154
+ return empty || fallback;
155
+ }
156
+
157
+ const elements = processedArray.map((item, index) => (
158
+ <React.Fragment key={keyExtractor(item, index)}>
159
+ {typeof children === 'function' ? children(item, index, processedArray) : children}
160
+ </React.Fragment>
161
+ ));
162
+
163
+ return animate ? (
164
+ <WrapperComponent className="conditional-animated">
165
+ {elements}
166
+ </WrapperComponent>
167
+ ) : (
168
+ <WrapperComponent>
169
+ {elements}
170
+ </WrapperComponent>
171
+ );
172
+ }
173
+
174
+ // Both condition and iteration
175
+ if (hasCondition && hasIteration) {
176
+ if (!evaluateCondition) return fallback;
177
+ if (processedArray.length === 0) return empty || fallback;
178
+
179
+ const elements = processedArray.map((item, index) => (
180
+ <React.Fragment key={keyExtractor(item, index)}>
181
+ {children(item, index, processedArray)}
182
+ </React.Fragment>
183
+ ));
184
+
185
+ return (
186
+ <WrapperComponent>
187
+ {elements}
188
+ </WrapperComponent>
189
+ );
190
+ }
191
+
192
+ return <WrapperComponent>{children}</WrapperComponent>;
193
+ };
194
+
195
+ export default Conditional;
package/README.md ADDED
@@ -0,0 +1,639 @@
1
+ ```markdown
2
+ # React Conditional Component
3
+
4
+ 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
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ npm install react-ternary-be-gone
10
+ # or
11
+ yarn add react-ternary-be-gone
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ ```javascript
17
+ import Conditional from 'react-ternary-be-gone';
18
+
19
+ // Basic conditional rendering
20
+ <Conditional when={true}>
21
+ <p>This will be rendered.</p>
22
+ </Conditional>
23
+
24
+ <Conditional when={55>33}>
25
+ <p>55 is bigger than 33</p>
26
+ </Conditional>
27
+
28
+ <Conditional when={false} fallback={<p>This is the fallback.</p>}>
29
+ <p>This will not be rendered.</p>
30
+ </Conditional>
31
+
32
+ // Iterating over a list
33
+ const items = ['Item 1', 'Item 2', 'Item 3'];
34
+
35
+ <Conditional each={items}>
36
+ {(item, index) => <p key={index}>{item}</p>}
37
+ </Conditional>
38
+ ```
39
+
40
+ ## Props
41
+
42
+ ### `when`
43
+
44
+ A boolean value that determines whether the children should be rendered.
45
+
46
+ **Type:** `boolean`
47
+
48
+ **Example:**
49
+
50
+ ```javascript
51
+ <Conditional when={isLoggedIn}>
52
+ <p>Welcome, user!</p>
53
+ </Conditional>
54
+ ```
55
+
56
+ ### `each`
57
+
58
+ An array to iterate over and render children for each item.
59
+
60
+ **Type:** `array`
61
+
62
+ **Example:**
63
+
64
+ ```javascript
65
+ const data = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
66
+
67
+ <Conditional each={data}>
68
+ {(item, index) => <p key={item.id}>{item.name}</p>}
69
+ </Conditional>
70
+ ```
71
+
72
+ ### `children`
73
+
74
+ The content to be rendered based on the `when` condition or for each item in the `each` array. Can be a React node or a render prop function.
75
+
76
+ **Type:** `ReactNode | (item: any, index: number, array: any[]) => ReactNode`
77
+
78
+ **Example (ReactNode):**
79
+
80
+ ```javascript
81
+ <Conditional when={true}>
82
+ <p>This is a simple paragraph.</p>
83
+ </Conditional>
84
+ ```
85
+
86
+ **Example (Render Prop):**
87
+
88
+ ```javascript
89
+ const items = ['A', 'B', 'C'];
90
+
91
+ <Conditional each={items}>
92
+ {(item, index) => <p key={index}>Item {index + 1}: {item}</p>}
93
+ </Conditional>
94
+ ```
95
+
96
+ ### `fallback`
97
+
98
+ The content to be rendered if the `when` condition is false or the `each` array is empty.
99
+
100
+ **Type:** `ReactNode`
101
+
102
+ **Example:**
103
+
104
+ ```javascript
105
+ <Conditional when={false} fallback={<p>Not logged in.</p>}>
106
+ <p>Welcome!</p>
107
+ </Conditional>
108
+ ```
109
+
110
+ ### `empty`
111
+
112
+ The content to be rendered if the `each` array is empty. Overrides `fallback` when iterating.
113
+
114
+ **Type:** `ReactNode`
115
+
116
+ **Example:**
117
+
118
+ ```javascript
119
+ const emptyList = [];
120
+
121
+ <Conditional each={emptyList} empty={<p>No items found.</p>}>
122
+ {(item) => <p>{item}</p>}
123
+ </Conditional>
124
+ ```
125
+
126
+ ### `loading`
127
+
128
+ A boolean value indicating whether the component is in a loading state. If true, the `fallback` prop (or a default loading message) will be rendered.
129
+
130
+ **Type:** `boolean`
131
+
132
+ **Example:**
133
+
134
+ ```javascript
135
+ <Conditional loading={isLoading} fallback={<p>Loading data...</p>}>
136
+ <p>Data loaded!</p>
137
+ </Conditional>
138
+ ```
139
+
140
+ ### `error`
141
+
142
+ An error message to be displayed if an error occurs.
143
+
144
+ **Type:** `string`
145
+
146
+ **Example:**
147
+
148
+ ```javascript
149
+ <Conditional error={errorMessage}>
150
+ <p>Content.</p>
151
+ </Conditional>
152
+ ```
153
+
154
+ ### `keyExtractor`
155
+
156
+ A function to extract a unique key for each item when iterating over the `each` array.
157
+
158
+ **Type:** `(item: any, index: number) => string | number`
159
+
160
+ **Default:** `(item, index) => index`
161
+
162
+ **Example:**
163
+
164
+ ```javascript
165
+ const users = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }];
166
+
167
+ <Conditional each={users} keyExtractor={(user) => user.id}>
168
+ {(user) => <p key={user.id}>{user.name}</p>}
169
+ </Conditional>
170
+ ```
171
+
172
+ ### `filter`
173
+
174
+ A function to filter the `each` array before rendering.
175
+
176
+ **Type:** `(item: any) => boolean`
177
+
178
+ **Example:**
179
+
180
+ ```javascript
181
+ const numbers = [1, 2, 3, 4, 5, 6];
182
+
183
+ <Conditional each={numbers} filter={(num) => num % 2 === 0}>
184
+ {(num) => <p>{num}</p>} {/* Renders 2, 4, 6 */}
185
+ </Conditional>
186
+ ```
187
+
188
+ ### `sort`
189
+
190
+ A function to sort the `each` array before rendering.
191
+
192
+ **Type:** `(a: any, b: any) => number`
193
+
194
+ **Example:**
195
+
196
+ ```javascript
197
+ const items = [{ name: 'Charlie' }, { name: 'Alice' }, { name: 'Bob' }];
198
+
199
+ <Conditional each={items} sort={(a, b) => a.name.localeCompare(b.name)}>
200
+ {(item) => <p>{item.name}</p>} {/* Renders Alice, Bob, Charlie */}
201
+ </Conditional>
202
+ ```
203
+
204
+ ### `limit`
205
+
206
+ A number to limit the number of items rendered from the `each` array.
207
+
208
+ **Type:** `number`
209
+
210
+ **Example:**
211
+
212
+ ```javascript
213
+ const items = ['A', 'B', 'C', 'D', 'E'];
214
+
215
+ <Conditional each={items} limit={3}>
216
+ {(item) => <p>{item}</p>} {/* Renders A, B, C */}
217
+ </Conditional>
218
+ ```
219
+
220
+ ### `reverse`
221
+
222
+ A boolean value indicating whether to reverse the order of the `each` array before rendering.
223
+
224
+ **Type:** `boolean`
225
+
226
+ **Example:**
227
+
228
+ ```javascript
229
+ const items = ['A', 'B', 'C'];
230
+
231
+ <Conditional each={items} reverse>
232
+ {(item) => <p>{item}</p>} {/* Renders C, B, A */}
233
+ </Conditional>
234
+ ```
235
+
236
+ ### `animate`
237
+
238
+ A boolean value indicating whether to add a CSS class for animation purposes. You'll need to define the `.conditional-animated` CSS class in your project.
239
+
240
+ **Type:** `boolean`
241
+
242
+ **Example:**
243
+
244
+ ```javascript
245
+ <Conditional each={items} animate>
246
+ {(item) => <p>{item}</p>}
247
+ </Conditional>
248
+
249
+ /* CSS (Example) */
250
+ .conditional-animated {
251
+ /* Your animation styles here */
252
+ transition: all 0.3s ease-in-out;
253
+ }
254
+ ```
255
+
256
+ ### `wrapper`
257
+
258
+ A React component or element to wrap the rendered children. Defaults to `React.Fragment`.
259
+
260
+ **Type:** `React.ComponentType`
261
+
262
+ **Example:**
263
+
264
+ ```javascript
265
+ <Conditional each={items} wrapper="ul">
266
+ {(item) => <li key={item}>{item}</li>}
267
+ </Conditional>
268
+
269
+ // Or with a custom component:
270
+ const MyWrapper = ({ children }) => <div className="my-wrapper">{children}</div>;
271
+
272
+ <Conditional each={items} wrapper={MyWrapper}>
273
+ {(item) => <p>{item}</p>}
274
+ </Conditional>
275
+ ```
276
+
277
+ ### `debug`
278
+
279
+ A boolean value that, when true, logs debugging information to the console, including the original and processed arrays.
280
+
281
+ **Type:** `boolean`
282
+
283
+ **Example:**
284
+
285
+ ```javascript
286
+ <Conditional each={items} debug>
287
+ {(item) => <p>{item}</p>}
288
+ </Conditional>
289
+ ```
290
+
291
+ ### `onRender`
292
+
293
+ A callback function that is called after the component renders. Provides information about the condition, item count, and whether the component is rendering conditionally or iterating.
294
+
295
+ **Type:** `(data: { condition: boolean, itemCount: number, hasCondition: boolean, hasIteration: boolean }) => void`
296
+
297
+ **Example:**
298
+
299
+ ```javascript
300
+ <Conditional
301
+ each={items}
302
+ onRender={({ itemCount }) => console.log(`Rendered ${itemCount} items`)}
303
+ >
304
+ {(item) => <p>{item}</p>}
305
+ </Conditional>
306
+ ```
307
+
308
+ ### Advanced Condition Evaluation Props
309
+
310
+ These props allow for more complex conditional checks without needing to define a separate `when` prop. Only one of these props should be used at a time.
311
+
312
+ #### `gt` (Greater Than)
313
+
314
+ Renders children if `value` is greater than `target`.
315
+
316
+ **Type:** `{ value: number, target: number }`
317
+
318
+ **Example:**
319
+
320
+ ```javascript
321
+ <Conditional gt={{ value: 10, target: 5 }}>
322
+ <p>10 is greater than 5</p>
323
+ </Conditional>
324
+ ```
325
+
326
+ #### `lt` (Less Than)
327
+
328
+ Renders children if `value` is less than `target`.
329
+
330
+ **Type:** `{ value: number, target: number }`
331
+
332
+ **Example:**
333
+
334
+ ```javascript
335
+ <Conditional lt={{ value: 3, target: 7 }}>
336
+ <p>3 is less than 7</p>
337
+ </Conditional>
338
+ ```
339
+
340
+ #### `eq` (Equal)
341
+
342
+ Renders children if `value` is equal to `target`.
343
+
344
+ **Type:** `{ value: any, target: any }`
345
+
346
+ **Example:**
347
+
348
+ ```javascript
349
+ <Conditional eq={{ value: 'hello', target: 'hello' }}>
350
+ <p>The strings are equal</p>
351
+ </Conditional>
352
+ ```
353
+
354
+ #### `ne` (Not Equal)
355
+
356
+ Renders children if `value` is not equal to `target`.
357
+
358
+ **Type:** `{ value: any, target: any }`
359
+
360
+ **Example:**
361
+
362
+ ```javascript
363
+ <Conditional ne={{ value: 1, target: 2 }}>
364
+ <p>1 is not equal to 2</p>
365
+ </Conditional>
366
+ ```
367
+
368
+ #### `includes`
369
+
370
+ Renders children if `value` (converted to a string) includes `target`.
371
+
372
+ **Type:** `{ value: string, target: string }`
373
+
374
+ **Example:**
375
+
376
+ ```javascript
377
+ <Conditional includes={{ value: 'hello world', target: 'world' }}>
378
+ <p>The string includes "world"</p>
379
+ </Conditional>
380
+ ```
381
+
382
+ #### `startsWith`
383
+
384
+ Renders children if `value` (converted to a string) starts with `target`.
385
+
386
+ **Type:** `{ value: string, target: string }`
387
+
388
+ **Example:**
389
+
390
+ ```javascript
391
+ <Conditional startsWith={{ value: 'hello world', target: 'hello' }}>
392
+ <p>The string starts with "hello"</p>
393
+ </Conditional>
394
+ ```
395
+
396
+ #### `endsWith`
397
+
398
+ Renders children if `value` (converted to a string) ends with `target`.
399
+
400
+ **Type:** `{ value: string, target: string }`
401
+
402
+ **Example:**
403
+
404
+ ```javascript
405
+ <Conditional endsWith={{ value: 'hello world', target: 'world' }}>
406
+ <p>The string ends with "world"</p>
407
+ </Conditional>
408
+ ```
409
+
410
+ #### `match`
411
+
412
+ Renders children if `value` (converted to a string) matches the provided regular expression `pattern`.
413
+
414
+ **Type:** `{ value: string, pattern: string }`
415
+
416
+ **Example:**
417
+
418
+ ```javascript
419
+ <Conditional match={{ value: 'hello 123', pattern: '\\d+' }}>
420
+ <p>The string contains a number</p>
421
+ </Conditional>
422
+ ```
423
+
424
+ ---
425
+
426
+ ## `useConditionalHelpers` Hook
427
+
428
+ A hook providing helper functions to simplify common conditional logic and array manipulation tasks.
429
+
430
+ ### Usage
431
+
432
+ ```javascript
433
+ import { useConditionalHelpers } from 'react-ternary-be-gone';
434
+
435
+ const MyComponent = () => {
436
+ const { isEmpty, isNotEmpty, hasLength, isEven, isOdd, sortBy, filterBy, unique } = useConditionalHelpers();
437
+ const myArray = [1, 2, 3];
438
+
439
+ return (
440
+ <>
441
+ <Conditional {...isEmpty(myArray)}>
442
+ <p>Array is empty</p>
443
+ </Conditional>
444
+ <Conditional {...isNotEmpty(myArray)}>
445
+ <p>Array is not empty</p>
446
+ </Conditional>
447
+ </>
448
+ );
449
+ };
450
+ ```
451
+
452
+ ### Helper Functions
453
+
454
+ #### `isEmpty(array)`
455
+
456
+ Checks if an array is empty or null/undefined. Returns an object suitable for the `when` prop.
457
+
458
+ **Parameters:**
459
+
460
+ * `array`: The array to check.
461
+
462
+ **Returns:** `{ when: boolean }`
463
+
464
+ **Example:**
465
+
466
+ ```javascript
467
+ const { isEmpty } = useConditionalHelpers();
468
+ const emptyArray = [];
469
+
470
+ <Conditional {...isEmpty(emptyArray)}>
471
+ <p>This array is empty.</p>
472
+ </Conditional>
473
+ ```
474
+
475
+ #### `isNotEmpty(array)`
476
+
477
+ Checks if an array is not empty. Returns an object suitable for the `when` prop.
478
+
479
+ **Parameters:**
480
+
481
+ * `array`: The array to check.
482
+
483
+ **Returns:** `{ when: boolean }`
484
+
485
+ **Example:**
486
+
487
+ ```javascript
488
+ const { isNotEmpty } = useConditionalHelpers();
489
+ const myArray = [1, 2, 3];
490
+
491
+ <Conditional {...isNotEmpty(myArray)}>
492
+ <p>This array is not empty.</p>
493
+ </Conditional>
494
+ ```
495
+
496
+ #### `hasLength(array, length)`
497
+
498
+ Checks if an array has a specific length. Returns an object suitable for the `when` prop.
499
+
500
+ **Parameters:**
501
+
502
+ * `array`: The array to check.
503
+ * `length`: The expected length.
504
+
505
+ **Returns:** `{ when: boolean }`
506
+
507
+ **Example:**
508
+
509
+ ```javascript
510
+ const { hasLength } = useConditionalHelpers();
511
+ const myArray = [1, 2, 3];
512
+
513
+ <Conditional {...hasLength(myArray, 3)}>
514
+ <p>This array has a length of 3.</p>
515
+ </Conditional>
516
+ ```
517
+
518
+ #### `isEven(num)`
519
+
520
+ Checks if a number is even. Returns an object suitable for the `when` prop.
521
+
522
+ **Parameters:**
523
+
524
+ * `num`: The number to check.
525
+
526
+ **Returns:** `{ when: boolean }`
527
+
528
+ **Example:**
529
+
530
+ ```javascript
531
+ const { isEven } = useConditionalHelpers();
532
+
533
+ <Conditional {...isEven(4)}>
534
+ <p>4 is an even number.</p>
535
+ </Conditional>
536
+ ```
537
+
538
+ #### `isOdd(num)`
539
+
540
+ Checks if a number is odd. Returns an object suitable for the `when` prop.
541
+
542
+ **Parameters:**
543
+
544
+ * `num`: The number to check.
545
+
546
+ **Returns:** `{ when: boolean }`
547
+
548
+ **Example:**
549
+
550
+ ```javascript
551
+ const { isOdd } = useConditionalHelpers();
552
+
553
+ <Conditional {...isOdd(5)}>
554
+ <p>5 is an odd number.</p>
555
+ </Conditional>
556
+ ```
557
+
558
+ #### `sortBy(field, order = 'asc')`
559
+
560
+ Returns a sort function to sort an array of objects by a specific field. Suitable for the `sort` prop.
561
+
562
+ **Parameters:**
563
+
564
+ * `field`: The field to sort by.
565
+ * `order`: The sort order ('asc' or 'desc'). Defaults to 'asc'.
566
+
567
+ **Returns:** `(a: any, b: any) => number`
568
+
569
+ **Example:**
570
+
571
+ ```javascript
572
+ const { sortBy } = useConditionalHelpers();
573
+ const items = [{ name: 'Charlie' }, { name: 'Alice' }, { name: 'Bob' }];
574
+
575
+ <Conditional each={items} sort={sortBy('name')}>
576
+ {(item) => <p>{item.name}</p>} {/* Renders Alice, Bob, Charlie */}
577
+ </Conditional>
578
+
579
+ <Conditional each={items} sort={sortBy('name', 'desc')}>
580
+ {(item) => <p>{item.name}</p>} {/* Renders Charlie, Bob, Alice */}
581
+ </Conditional>
582
+ ```
583
+
584
+ #### `filterBy(field, value)`
585
+
586
+ Returns a filter function to filter an array of objects by a specific field and value. Suitable for the `filter` prop.
587
+
588
+ **Parameters:**
589
+
590
+ * `field`: The field to filter by.
591
+ * `value`: The value to filter for.
592
+
593
+ **Returns:** `(item: any) => boolean`
594
+
595
+ **Example:**
596
+
597
+ ```javascript
598
+ const { filterBy } = useConditionalHelpers();
599
+ const users = [{ id: 1, name: 'Alice', active: true }, { id: 2, name: 'Bob', active: false }];
600
+
601
+ <Conditional each={users} filter={filterBy('active', true)}>
602
+ {(user) => <p>{user.name}</p>} {/* Renders Alice */}
603
+ </Conditional>
604
+ ```
605
+
606
+ #### `unique(array, key)`
607
+
608
+ Returns a new array with only unique items, based on a key or a key extractor function.
609
+
610
+ **Parameters:**
611
+
612
+ * `array`: The array to process.
613
+ * `key`: The key to use for uniqueness (string) or a function that extracts the key (function).
614
+
615
+ **Returns:** `any[]`
616
+
617
+ **Example:**
618
+
619
+ ```javascript
620
+ const { unique } = useConditionalHelpers();
621
+ const items = [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }, { id: 1, name: 'Charlie' }];
622
+
623
+ const uniqueItems = unique(items, 'id'); // Removes the duplicate ID 1
624
+ // uniqueItems will be: [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
625
+
626
+ const items2 = [{name: "Apple", color: "red"}, {name: "Banana", color: "yellow"}, {name: "Cherry", color: "red"}];
627
+ const uniqueItems2 = unique(items2, (item) => item.color);
628
+ // uniqueItems2 will be: [{name: "Apple", color: "red"}, {name: "Banana", color: "yellow"}]
629
+ ```
630
+
631
+ ---
632
+
633
+ ## Contributing
634
+
635
+ Contributions are welcome! Please fork the repository and submit a pull request.
636
+
637
+ ## License
638
+
639
+ MIT
package/index.js ADDED
@@ -0,0 +1,5 @@
1
+ import Conditional from './Conditional';
2
+ import { useConditionalHelpers } from './useConditionalHelpers';
3
+
4
+ export default Conditional;
5
+ export { useConditionalHelpers };
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "react-ternary-be-gone",
3
+ "version": "0.1.0",
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
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "peerDependencies": {
10
+ "react": ">=16.8.0"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/sundowatch/react-ternary-be-gone.git"
15
+ },
16
+ "keywords": [
17
+ "react",
18
+ "no",
19
+ "ternary"
20
+ ],
21
+ "author": "Ibrahim Sanduvaç",
22
+ "license": "MIT",
23
+ "bugs": {
24
+ "url": "https://github.com/sundowatch/react-ternary-be-gone/issues"
25
+ },
26
+ "homepage": "https://github.com/sundowatch/react-ternary-be-gone#readme"
27
+ }
@@ -0,0 +1,36 @@
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
+ };