@aweebit/react-essentials 0.10.0 → 0.10.1
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 +470 -26
- package/dist/misc/contextualize.d.ts +71 -0
- package/dist/misc/contextualize.d.ts.map +1 -0
- package/dist/misc/contextualize.js +63 -0
- package/dist/misc/contextualize.js.map +1 -0
- package/dist/misc/createSafeContext.d.ts +2 -2
- package/dist/misc/createSafeContext.js +2 -2
- package/dist/misc/index.d.ts +2 -0
- package/dist/misc/index.d.ts.map +1 -1
- package/dist/misc/index.js +2 -0
- package/dist/misc/index.js.map +1 -1
- package/dist/misc/wrapJSX.d.ts +76 -0
- package/dist/misc/wrapJSX.d.ts.map +1 -0
- package/dist/misc/wrapJSX.js +61 -0
- package/dist/misc/wrapJSX.js.map +1 -0
- package/package.json +3 -2
- package/scripts/fixReadmeLinks.js +23 -0
- package/src/misc/contextualize.tsx +90 -0
- package/src/misc/createSafeContext.ts +2 -2
- package/src/misc/index.ts +2 -0
- package/src/misc/wrapJSX.tsx +107 -0
package/README.md
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
- [useEventListener()](#useeventlistener)
|
|
6
6
|
- [useReducerWithDeps()](#usereducerwithdeps)
|
|
7
7
|
- [useStateWithDeps()](#usestatewithdeps)
|
|
8
|
+
- [contextualize()](#contextualize)
|
|
8
9
|
- [createSafeContext()](#createsafecontext)
|
|
10
|
+
- [wrapJSX()](#wrapjsx)
|
|
9
11
|
|
|
10
12
|
### Requirements
|
|
11
13
|
|
|
@@ -18,7 +20,7 @@
|
|
|
18
20
|
const useEventListener: UseEventListener;
|
|
19
21
|
```
|
|
20
22
|
|
|
21
|
-
Defined in: [hooks/useEventListener.ts:135](https://github.com/aweebit/react-essentials/blob/v0.10.
|
|
23
|
+
Defined in: [hooks/useEventListener.ts:135](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/hooks/useEventListener.ts#L135)
|
|
22
24
|
|
|
23
25
|
Adds `handler` as a listener for the event `eventName` of `target` with the
|
|
24
26
|
provided `options` applied
|
|
@@ -30,7 +32,7 @@ function useEventListener(eventName, handler, options?): void;
|
|
|
30
32
|
function useEventListener(target, eventName, handler, options?): void;
|
|
31
33
|
```
|
|
32
34
|
|
|
33
|
-
For the full definition of the hook's type, see [`UseEventListener`](#useeventlistener).
|
|
35
|
+
For the full definition of the hook's type, see [`UseEventListener`](#useeventlistener-1).
|
|
34
36
|
|
|
35
37
|
If `target` is not provided, `window` is used instead.
|
|
36
38
|
|
|
@@ -55,7 +57,7 @@ useEventListener(buttonRef, 'click', () => console.log('click'));
|
|
|
55
57
|
|
|
56
58
|
### See
|
|
57
59
|
|
|
58
|
-
[`UseEventListener`](#useeventlistener)
|
|
60
|
+
[`UseEventListener`](#useeventlistener-1)
|
|
59
61
|
|
|
60
62
|
---
|
|
61
63
|
|
|
@@ -69,7 +71,7 @@ function useReducerWithDeps<S, A>(
|
|
|
69
71
|
): [S, ActionDispatch<A>];
|
|
70
72
|
```
|
|
71
73
|
|
|
72
|
-
Defined in: [hooks/useReducerWithDeps.ts:59](https://github.com/aweebit/react-essentials/blob/v0.10.
|
|
74
|
+
Defined in: [hooks/useReducerWithDeps.ts:59](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/hooks/useReducerWithDeps.ts#L59)
|
|
73
75
|
|
|
74
76
|
`useReducer` hook with an additional dependency array `deps` that resets the
|
|
75
77
|
state to `initialState` when dependencies change
|
|
@@ -212,7 +214,7 @@ function useStateWithDeps<S>(
|
|
|
212
214
|
): [S, Dispatch<SetStateAction<S>>];
|
|
213
215
|
```
|
|
214
216
|
|
|
215
|
-
Defined in: [hooks/useStateWithDeps.ts:62](https://github.com/aweebit/react-essentials/blob/v0.10.
|
|
217
|
+
Defined in: [hooks/useStateWithDeps.ts:62](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/hooks/useStateWithDeps.ts#L62)
|
|
216
218
|
|
|
217
219
|
`useState` hook with an additional dependency array `deps` that resets the
|
|
218
220
|
state to `initialState` when dependencies change
|
|
@@ -336,17 +338,113 @@ Dependencies that reset the state to `initialState`
|
|
|
336
338
|
|
|
337
339
|
---
|
|
338
340
|
|
|
341
|
+
## contextualize()
|
|
342
|
+
|
|
343
|
+
```ts
|
|
344
|
+
function contextualize(jsx): ContextualizePipe;
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Defined in: [misc/contextualize.tsx:79](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/misc/contextualize.tsx#L79)
|
|
348
|
+
|
|
349
|
+
An alternative way to provide context values to component trees that avoids
|
|
350
|
+
ever-increasing indentation
|
|
351
|
+
|
|
352
|
+
A context-specific version of the more general [`wrapJSX`](#wrapjsx) function.
|
|
353
|
+
|
|
354
|
+
### Example
|
|
355
|
+
|
|
356
|
+
```tsx
|
|
357
|
+
// Before:
|
|
358
|
+
return (
|
|
359
|
+
<CourseIdContext.Provider value={courseId}>
|
|
360
|
+
<DeckIdContext.Provider value={deckId}>
|
|
361
|
+
<FlashcardsContext.Provider value={flashcards}>
|
|
362
|
+
<EventHandlersContext.Provider value={eventHandlers}>
|
|
363
|
+
<Header />
|
|
364
|
+
<Main />
|
|
365
|
+
<Footer />
|
|
366
|
+
</EventHandlersContext.Provider>
|
|
367
|
+
</FlashcardsContext.Provider>
|
|
368
|
+
</DeckIdContext.Provider>
|
|
369
|
+
</CourseIdContext.Provider>
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
// After:
|
|
373
|
+
const jsx = (
|
|
374
|
+
<>
|
|
375
|
+
<Header />
|
|
376
|
+
<Main />
|
|
377
|
+
<Footer />
|
|
378
|
+
</>
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
return contextualize(jsx)
|
|
382
|
+
.with(EventHandlersContext, eventHandlers)
|
|
383
|
+
.with(FlashcardsContext, flashcards)
|
|
384
|
+
.with(DeckIdContext, deckId)
|
|
385
|
+
.with(CourseIdContext, courseId)
|
|
386
|
+
.end();
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
### Parameters
|
|
390
|
+
|
|
391
|
+
<table>
|
|
392
|
+
<thead>
|
|
393
|
+
<tr>
|
|
394
|
+
<th>Parameter</th>
|
|
395
|
+
<th>Type</th>
|
|
396
|
+
<th>Description</th>
|
|
397
|
+
</tr>
|
|
398
|
+
</thead>
|
|
399
|
+
<tbody>
|
|
400
|
+
<tr>
|
|
401
|
+
<td>
|
|
402
|
+
|
|
403
|
+
`jsx`
|
|
404
|
+
|
|
405
|
+
</td>
|
|
406
|
+
<td>
|
|
407
|
+
|
|
408
|
+
`Element`
|
|
409
|
+
|
|
410
|
+
</td>
|
|
411
|
+
<td>
|
|
412
|
+
|
|
413
|
+
The JSX to contextualize
|
|
414
|
+
|
|
415
|
+
</td>
|
|
416
|
+
</tr>
|
|
417
|
+
</tbody>
|
|
418
|
+
</table>
|
|
419
|
+
|
|
420
|
+
### Returns
|
|
421
|
+
|
|
422
|
+
[`ContextualizePipe`](#contextualizepipe)
|
|
423
|
+
|
|
424
|
+
An object with the following properties:
|
|
425
|
+
|
|
426
|
+
- `with`: a function that accepts a context `Context` and a value `value` for
|
|
427
|
+
it as arguments and returns
|
|
428
|
+
`contextualize(<Context.Provider value={value}>{jsx}</Context.Provider>)`
|
|
429
|
+
- `end`: a function that returns `jsx`
|
|
430
|
+
|
|
431
|
+
### See
|
|
432
|
+
|
|
433
|
+
[`ContextualizePipe`](#contextualizepipe)
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
339
437
|
## createSafeContext()
|
|
340
438
|
|
|
341
439
|
```ts
|
|
342
|
-
function createSafeContext<T>(): <DisplayName>(
|
|
343
|
-
|
|
344
|
-
|
|
440
|
+
function createSafeContext<T>(): <DisplayName>(displayName) => {
|
|
441
|
+
[K in `${string}Context`]: Context<T>;
|
|
442
|
+
} & {
|
|
345
443
|
[K in `use${string}`]: () => T;
|
|
346
444
|
};
|
|
347
445
|
```
|
|
348
446
|
|
|
349
|
-
Defined in: [misc/createSafeContext.ts:62](https://github.com/aweebit/react-essentials/blob/v0.10.
|
|
447
|
+
Defined in: [misc/createSafeContext.ts:62](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/misc/createSafeContext.ts#L62)
|
|
350
448
|
|
|
351
449
|
For a given type `T`, returns a function that produces both a context of that
|
|
352
450
|
type and a hook that returns the current context value if one was provided,
|
|
@@ -366,7 +464,7 @@ enum Direction {
|
|
|
366
464
|
Right,
|
|
367
465
|
}
|
|
368
466
|
|
|
369
|
-
// Before
|
|
467
|
+
// Before:
|
|
370
468
|
const DirectionContext = createContext<Direction | undefined>(undefined);
|
|
371
469
|
DirectionContext.displayName = 'DirectionContext';
|
|
372
470
|
|
|
@@ -383,7 +481,7 @@ const useDirection = () => {
|
|
|
383
481
|
return direction;
|
|
384
482
|
};
|
|
385
483
|
|
|
386
|
-
// After
|
|
484
|
+
// After:
|
|
387
485
|
const { DirectionContext, useDirection } =
|
|
388
486
|
createSafeContext<Direction>()('Direction'); // That's it :)
|
|
389
487
|
|
|
@@ -485,6 +583,100 @@ A function that accepts a single string argument `displayName` (e.g.
|
|
|
485
583
|
|
|
486
584
|
---
|
|
487
585
|
|
|
586
|
+
## wrapJSX()
|
|
587
|
+
|
|
588
|
+
```ts
|
|
589
|
+
function wrapJSX(jsx): JSXWrapPipe;
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
Defined in: [misc/wrapJSX.tsx:93](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/misc/wrapJSX.tsx#L93)
|
|
593
|
+
|
|
594
|
+
An alternative way to compose JSX that avoids ever-increasing indentation
|
|
595
|
+
|
|
596
|
+
A more general version of the context-specific [`contextualize`](#contextualize)
|
|
597
|
+
function.
|
|
598
|
+
|
|
599
|
+
### Example
|
|
600
|
+
|
|
601
|
+
```tsx
|
|
602
|
+
// Before:
|
|
603
|
+
createRoot(document.getElementById('root')!).render(
|
|
604
|
+
<StrictMode>
|
|
605
|
+
<I18nextProvider i18n={i18n}>
|
|
606
|
+
<QueryClientProvider client={queryClient}>
|
|
607
|
+
<NuqsAdapter>
|
|
608
|
+
<ThemeProvider theme={theme}>
|
|
609
|
+
<ToasterProvider>
|
|
610
|
+
<App />
|
|
611
|
+
</ToasterProvider>
|
|
612
|
+
</ThemeProvider>
|
|
613
|
+
</NuqsAdapter>
|
|
614
|
+
</QueryClientProvider>
|
|
615
|
+
</I18nextProvider>
|
|
616
|
+
</StrictMode>,
|
|
617
|
+
);
|
|
618
|
+
|
|
619
|
+
// After:
|
|
620
|
+
createRoot(document.getElementById('root')!).render(
|
|
621
|
+
wrapJSX(<App />)
|
|
622
|
+
.with(ToasterProvider)
|
|
623
|
+
.with(ThemeProvider, { theme })
|
|
624
|
+
.with(NuqsAdapter)
|
|
625
|
+
.with(QueryClientProvider, { client: queryClient })
|
|
626
|
+
.with(I18nextProvider, { i18n })
|
|
627
|
+
.with(StrictMode)
|
|
628
|
+
.end(),
|
|
629
|
+
);
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
### Parameters
|
|
633
|
+
|
|
634
|
+
<table>
|
|
635
|
+
<thead>
|
|
636
|
+
<tr>
|
|
637
|
+
<th>Parameter</th>
|
|
638
|
+
<th>Type</th>
|
|
639
|
+
<th>Description</th>
|
|
640
|
+
</tr>
|
|
641
|
+
</thead>
|
|
642
|
+
<tbody>
|
|
643
|
+
<tr>
|
|
644
|
+
<td>
|
|
645
|
+
|
|
646
|
+
`jsx`
|
|
647
|
+
|
|
648
|
+
</td>
|
|
649
|
+
<td>
|
|
650
|
+
|
|
651
|
+
`Element`
|
|
652
|
+
|
|
653
|
+
</td>
|
|
654
|
+
<td>
|
|
655
|
+
|
|
656
|
+
The JSX to wrap
|
|
657
|
+
|
|
658
|
+
</td>
|
|
659
|
+
</tr>
|
|
660
|
+
</tbody>
|
|
661
|
+
</table>
|
|
662
|
+
|
|
663
|
+
### Returns
|
|
664
|
+
|
|
665
|
+
[`JSXWrapPipe`](#jsxwrappipe)
|
|
666
|
+
|
|
667
|
+
An object with the following properties:
|
|
668
|
+
|
|
669
|
+
- `with`: a function that accepts a component `Component` and props `props`
|
|
670
|
+
for it as arguments and returns
|
|
671
|
+
`wrapJSX(<Component {...props}>{jsx}</Component>)`
|
|
672
|
+
- `end`: a function that returns `jsx`
|
|
673
|
+
|
|
674
|
+
### See
|
|
675
|
+
|
|
676
|
+
[`JSXWrapPipe`](#jsxwrappipe)
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
488
680
|
## UseEventListener
|
|
489
681
|
|
|
490
682
|
```ts
|
|
@@ -493,13 +685,13 @@ type UseEventListener = UseEventListenerWithImplicitWindowTarget &
|
|
|
493
685
|
UseEventListenerWithAnyExplicitTarget;
|
|
494
686
|
```
|
|
495
687
|
|
|
496
|
-
Defined in: [hooks/useEventListener.ts:12](https://github.com/aweebit/react-essentials/blob/v0.10.
|
|
688
|
+
Defined in: [hooks/useEventListener.ts:12](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/hooks/useEventListener.ts#L12)
|
|
497
689
|
|
|
498
|
-
The type of [`useEventListener`](#useeventlistener
|
|
690
|
+
The type of [`useEventListener`](#useeventlistener)
|
|
499
691
|
|
|
500
692
|
### See
|
|
501
693
|
|
|
502
|
-
[`useEventListener`](#useeventlistener
|
|
694
|
+
[`useEventListener`](#useeventlistener),
|
|
503
695
|
[`UseEventListenerWithImplicitWindowTarget`](#useeventlistenerwithimplicitwindowtarget),
|
|
504
696
|
[`UseEventListenerWithExplicitGlobalTarget`](#useeventlistenerwithexplicitglobaltarget),
|
|
505
697
|
[`UseEventListenerWithAnyExplicitTarget`](#useeventlistenerwithanyexplicittarget)
|
|
@@ -512,7 +704,7 @@ The type of [`useEventListener`](#useeventlistener-1)
|
|
|
512
704
|
type UseEventListenerWithImplicitWindowTarget = <K>(...args) => void;
|
|
513
705
|
```
|
|
514
706
|
|
|
515
|
-
Defined in: [hooks/useEventListener.ts:21](https://github.com/aweebit/react-essentials/blob/v0.10.
|
|
707
|
+
Defined in: [hooks/useEventListener.ts:21](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/hooks/useEventListener.ts#L21)
|
|
516
708
|
|
|
517
709
|
### Type Parameters
|
|
518
710
|
|
|
@@ -564,7 +756,7 @@ Defined in: [hooks/useEventListener.ts:21](https://github.com/aweebit/react-esse
|
|
|
564
756
|
|
|
565
757
|
### See
|
|
566
758
|
|
|
567
|
-
[`useEventListener`](#useeventlistener
|
|
759
|
+
[`useEventListener`](#useeventlistener),
|
|
568
760
|
[`UseEventListenerWithImplicitWindowTargetArgs`](#useeventlistenerwithimplicitwindowtargetargs)
|
|
569
761
|
|
|
570
762
|
---
|
|
@@ -580,11 +772,11 @@ type UseEventListenerWithExplicitGlobalTarget =
|
|
|
580
772
|
UseEventListenerWithExplicitTarget<MathMLElement, MathMLElementEventMap>;
|
|
581
773
|
```
|
|
582
774
|
|
|
583
|
-
Defined in: [hooks/useEventListener.ts:32](https://github.com/aweebit/react-essentials/blob/v0.10.
|
|
775
|
+
Defined in: [hooks/useEventListener.ts:32](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/hooks/useEventListener.ts#L32)
|
|
584
776
|
|
|
585
777
|
### See
|
|
586
778
|
|
|
587
|
-
[`useEventListener`](#useeventlistener
|
|
779
|
+
[`useEventListener`](#useeventlistener),
|
|
588
780
|
[`UseEventListenerWithExplicitTarget`](#useeventlistenerwithexplicittarget)
|
|
589
781
|
|
|
590
782
|
---
|
|
@@ -597,7 +789,7 @@ type UseEventListenerWithExplicitTarget<Target, EventMap> = <T, K>(
|
|
|
597
789
|
) => void;
|
|
598
790
|
```
|
|
599
791
|
|
|
600
|
-
Defined in: [hooks/useEventListener.ts:44](https://github.com/aweebit/react-essentials/blob/v0.10.
|
|
792
|
+
Defined in: [hooks/useEventListener.ts:44](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/hooks/useEventListener.ts#L44)
|
|
601
793
|
|
|
602
794
|
### Type Parameters
|
|
603
795
|
|
|
@@ -682,7 +874,7 @@ Defined in: [hooks/useEventListener.ts:44](https://github.com/aweebit/react-esse
|
|
|
682
874
|
|
|
683
875
|
### See
|
|
684
876
|
|
|
685
|
-
[`useEventListener`](#useeventlistener
|
|
877
|
+
[`useEventListener`](#useeventlistener),
|
|
686
878
|
[`UseEventListenerWithExplicitTargetArgs`](#useeventlistenerwithexplicittargetargs)
|
|
687
879
|
|
|
688
880
|
---
|
|
@@ -696,11 +888,11 @@ type UseEventListenerWithAnyExplicitTarget = UseEventListenerWithExplicitTarget<
|
|
|
696
888
|
>;
|
|
697
889
|
```
|
|
698
890
|
|
|
699
|
-
Defined in: [hooks/useEventListener.ts:56](https://github.com/aweebit/react-essentials/blob/v0.10.
|
|
891
|
+
Defined in: [hooks/useEventListener.ts:56](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/hooks/useEventListener.ts#L56)
|
|
700
892
|
|
|
701
893
|
### See
|
|
702
894
|
|
|
703
|
-
[`useEventListener`](#useeventlistener
|
|
895
|
+
[`useEventListener`](#useeventlistener),
|
|
704
896
|
[`UseEventListenerWithExplicitTarget`](#useeventlistenerwithexplicittarget)
|
|
705
897
|
|
|
706
898
|
---
|
|
@@ -717,7 +909,7 @@ type UseEventListenerWithImplicitWindowTargetArgs<K> =
|
|
|
717
909
|
: never;
|
|
718
910
|
```
|
|
719
911
|
|
|
720
|
-
Defined in: [hooks/useEventListener.ts:64](https://github.com/aweebit/react-essentials/blob/v0.10.
|
|
912
|
+
Defined in: [hooks/useEventListener.ts:64](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/hooks/useEventListener.ts#L64)
|
|
721
913
|
|
|
722
914
|
### Type Parameters
|
|
723
915
|
|
|
@@ -740,7 +932,7 @@ Defined in: [hooks/useEventListener.ts:64](https://github.com/aweebit/react-esse
|
|
|
740
932
|
|
|
741
933
|
### See
|
|
742
934
|
|
|
743
|
-
[`useEventListener`](#useeventlistener
|
|
935
|
+
[`useEventListener`](#useeventlistener),
|
|
744
936
|
[`UseEventListenerWithExplicitTargetArgs`](#useeventlistenerwithexplicittargetargs)
|
|
745
937
|
|
|
746
938
|
---
|
|
@@ -762,7 +954,7 @@ type UseEventListenerWithExplicitTargetArgs<EventMap, T, K> = [
|
|
|
762
954
|
];
|
|
763
955
|
```
|
|
764
956
|
|
|
765
|
-
Defined in: [hooks/useEventListener.ts:78](https://github.com/aweebit/react-essentials/blob/v0.10.
|
|
957
|
+
Defined in: [hooks/useEventListener.ts:78](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/hooks/useEventListener.ts#L78)
|
|
766
958
|
|
|
767
959
|
### Type Parameters
|
|
768
960
|
|
|
@@ -799,4 +991,256 @@ Defined in: [hooks/useEventListener.ts:78](https://github.com/aweebit/react-esse
|
|
|
799
991
|
|
|
800
992
|
### See
|
|
801
993
|
|
|
802
|
-
[`useEventListener`](#useeventlistener
|
|
994
|
+
[`useEventListener`](#useeventlistener)
|
|
995
|
+
|
|
996
|
+
---
|
|
997
|
+
|
|
998
|
+
## ContextualizePipe
|
|
999
|
+
|
|
1000
|
+
```ts
|
|
1001
|
+
type ContextualizePipe = {
|
|
1002
|
+
with: ContextualizeWith;
|
|
1003
|
+
end: () => React.JSX.Element;
|
|
1004
|
+
};
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
Defined in: [misc/contextualize.tsx:13](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/misc/contextualize.tsx#L13)
|
|
1008
|
+
|
|
1009
|
+
The return type of [`contextualize`](#contextualize)
|
|
1010
|
+
|
|
1011
|
+
### See
|
|
1012
|
+
|
|
1013
|
+
[`contextualize`](#contextualize),
|
|
1014
|
+
[`ContextualizeWith`](#contextualizewith)
|
|
1015
|
+
|
|
1016
|
+
### Properties
|
|
1017
|
+
|
|
1018
|
+
<table>
|
|
1019
|
+
<thead>
|
|
1020
|
+
<tr>
|
|
1021
|
+
<th>Property</th>
|
|
1022
|
+
<th>Type</th>
|
|
1023
|
+
</tr>
|
|
1024
|
+
</thead>
|
|
1025
|
+
<tbody>
|
|
1026
|
+
<tr>
|
|
1027
|
+
<td>
|
|
1028
|
+
|
|
1029
|
+
<a id="with"></a> `with`
|
|
1030
|
+
|
|
1031
|
+
</td>
|
|
1032
|
+
<td>
|
|
1033
|
+
|
|
1034
|
+
[`ContextualizeWith`](#contextualizewith)
|
|
1035
|
+
|
|
1036
|
+
</td>
|
|
1037
|
+
</tr>
|
|
1038
|
+
<tr>
|
|
1039
|
+
<td>
|
|
1040
|
+
|
|
1041
|
+
<a id="end"></a> `end`
|
|
1042
|
+
|
|
1043
|
+
</td>
|
|
1044
|
+
<td>
|
|
1045
|
+
|
|
1046
|
+
() => `React.JSX.Element`
|
|
1047
|
+
|
|
1048
|
+
</td>
|
|
1049
|
+
</tr>
|
|
1050
|
+
</tbody>
|
|
1051
|
+
</table>
|
|
1052
|
+
|
|
1053
|
+
---
|
|
1054
|
+
|
|
1055
|
+
## ContextualizeWith()
|
|
1056
|
+
|
|
1057
|
+
```ts
|
|
1058
|
+
type ContextualizeWith = <T>(Context, value) => ContextualizePipe;
|
|
1059
|
+
```
|
|
1060
|
+
|
|
1061
|
+
Defined in: [misc/contextualize.tsx:23](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/misc/contextualize.tsx#L23)
|
|
1062
|
+
|
|
1063
|
+
### Type Parameters
|
|
1064
|
+
|
|
1065
|
+
<table>
|
|
1066
|
+
<thead>
|
|
1067
|
+
<tr>
|
|
1068
|
+
<th>Type Parameter</th>
|
|
1069
|
+
</tr>
|
|
1070
|
+
</thead>
|
|
1071
|
+
<tbody>
|
|
1072
|
+
<tr>
|
|
1073
|
+
<td>
|
|
1074
|
+
|
|
1075
|
+
`T`
|
|
1076
|
+
|
|
1077
|
+
</td>
|
|
1078
|
+
</tr>
|
|
1079
|
+
</tbody>
|
|
1080
|
+
</table>
|
|
1081
|
+
|
|
1082
|
+
### Parameters
|
|
1083
|
+
|
|
1084
|
+
<table>
|
|
1085
|
+
<thead>
|
|
1086
|
+
<tr>
|
|
1087
|
+
<th>Parameter</th>
|
|
1088
|
+
<th>Type</th>
|
|
1089
|
+
</tr>
|
|
1090
|
+
</thead>
|
|
1091
|
+
<tbody>
|
|
1092
|
+
<tr>
|
|
1093
|
+
<td>
|
|
1094
|
+
|
|
1095
|
+
`Context`
|
|
1096
|
+
|
|
1097
|
+
</td>
|
|
1098
|
+
<td>
|
|
1099
|
+
|
|
1100
|
+
`Context`\<`T`\>
|
|
1101
|
+
|
|
1102
|
+
</td>
|
|
1103
|
+
</tr>
|
|
1104
|
+
<tr>
|
|
1105
|
+
<td>
|
|
1106
|
+
|
|
1107
|
+
`value`
|
|
1108
|
+
|
|
1109
|
+
</td>
|
|
1110
|
+
<td>
|
|
1111
|
+
|
|
1112
|
+
`NoInfer`\<`T`\>
|
|
1113
|
+
|
|
1114
|
+
</td>
|
|
1115
|
+
</tr>
|
|
1116
|
+
</tbody>
|
|
1117
|
+
</table>
|
|
1118
|
+
|
|
1119
|
+
### Returns
|
|
1120
|
+
|
|
1121
|
+
[`ContextualizePipe`](#contextualizepipe)
|
|
1122
|
+
|
|
1123
|
+
### See
|
|
1124
|
+
|
|
1125
|
+
[`contextualize`](#contextualize),
|
|
1126
|
+
[`ContextualizePipe`](#contextualizepipe)
|
|
1127
|
+
|
|
1128
|
+
---
|
|
1129
|
+
|
|
1130
|
+
## JSXWrapPipe
|
|
1131
|
+
|
|
1132
|
+
```ts
|
|
1133
|
+
type JSXWrapPipe = {
|
|
1134
|
+
with: WrapJSXWith;
|
|
1135
|
+
end: () => React.JSX.Element;
|
|
1136
|
+
};
|
|
1137
|
+
```
|
|
1138
|
+
|
|
1139
|
+
Defined in: [misc/wrapJSX.tsx:17](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/misc/wrapJSX.tsx#L17)
|
|
1140
|
+
|
|
1141
|
+
The return type of [`wrapJSX`](#wrapjsx)
|
|
1142
|
+
|
|
1143
|
+
### See
|
|
1144
|
+
|
|
1145
|
+
[`wrapJSX`](#wrapjsx),
|
|
1146
|
+
[`WrapJSXWith`](#wrapjsxwith)
|
|
1147
|
+
|
|
1148
|
+
### Properties
|
|
1149
|
+
|
|
1150
|
+
<table>
|
|
1151
|
+
<thead>
|
|
1152
|
+
<tr>
|
|
1153
|
+
<th>Property</th>
|
|
1154
|
+
<th>Type</th>
|
|
1155
|
+
</tr>
|
|
1156
|
+
</thead>
|
|
1157
|
+
<tbody>
|
|
1158
|
+
<tr>
|
|
1159
|
+
<td>
|
|
1160
|
+
|
|
1161
|
+
<a id="with-1"></a> `with`
|
|
1162
|
+
|
|
1163
|
+
</td>
|
|
1164
|
+
<td>
|
|
1165
|
+
|
|
1166
|
+
[`WrapJSXWith`](#wrapjsxwith)
|
|
1167
|
+
|
|
1168
|
+
</td>
|
|
1169
|
+
</tr>
|
|
1170
|
+
<tr>
|
|
1171
|
+
<td>
|
|
1172
|
+
|
|
1173
|
+
<a id="end-1"></a> `end`
|
|
1174
|
+
|
|
1175
|
+
</td>
|
|
1176
|
+
<td>
|
|
1177
|
+
|
|
1178
|
+
() => `React.JSX.Element`
|
|
1179
|
+
|
|
1180
|
+
</td>
|
|
1181
|
+
</tr>
|
|
1182
|
+
</tbody>
|
|
1183
|
+
</table>
|
|
1184
|
+
|
|
1185
|
+
---
|
|
1186
|
+
|
|
1187
|
+
## WrapJSXWith()
|
|
1188
|
+
|
|
1189
|
+
```ts
|
|
1190
|
+
type WrapJSXWith = <C>(...args) => JSXWrapPipe;
|
|
1191
|
+
```
|
|
1192
|
+
|
|
1193
|
+
Defined in: [misc/wrapJSX.tsx:27](https://github.com/aweebit/react-essentials/blob/v0.10.1/src/misc/wrapJSX.tsx#L27)
|
|
1194
|
+
|
|
1195
|
+
### Type Parameters
|
|
1196
|
+
|
|
1197
|
+
<table>
|
|
1198
|
+
<thead>
|
|
1199
|
+
<tr>
|
|
1200
|
+
<th>Type Parameter</th>
|
|
1201
|
+
</tr>
|
|
1202
|
+
</thead>
|
|
1203
|
+
<tbody>
|
|
1204
|
+
<tr>
|
|
1205
|
+
<td>
|
|
1206
|
+
|
|
1207
|
+
`C` _extends_ keyof `JSX.IntrinsicElements` \| `JSXElementConstructor`\<`any`\>
|
|
1208
|
+
|
|
1209
|
+
</td>
|
|
1210
|
+
</tr>
|
|
1211
|
+
</tbody>
|
|
1212
|
+
</table>
|
|
1213
|
+
|
|
1214
|
+
### Parameters
|
|
1215
|
+
|
|
1216
|
+
<table>
|
|
1217
|
+
<thead>
|
|
1218
|
+
<tr>
|
|
1219
|
+
<th>Parameter</th>
|
|
1220
|
+
<th>Type</th>
|
|
1221
|
+
</tr>
|
|
1222
|
+
</thead>
|
|
1223
|
+
<tbody>
|
|
1224
|
+
<tr>
|
|
1225
|
+
<td>
|
|
1226
|
+
|
|
1227
|
+
...`args`
|
|
1228
|
+
|
|
1229
|
+
</td>
|
|
1230
|
+
<td>
|
|
1231
|
+
|
|
1232
|
+
\[`C`, `...(Record<never, unknown> extends Omit<ComponentProps<C>, "children"> ? [props?: React.JSX.IntrinsicAttributes & Omit<ComponentProps<C>, "children">] : [props: React.JSX.IntrinsicAttributes & Omit<ComponentProps<C>, "children">])`\]
|
|
1233
|
+
|
|
1234
|
+
</td>
|
|
1235
|
+
</tr>
|
|
1236
|
+
</tbody>
|
|
1237
|
+
</table>
|
|
1238
|
+
|
|
1239
|
+
### Returns
|
|
1240
|
+
|
|
1241
|
+
[`JSXWrapPipe`](#jsxwrappipe)
|
|
1242
|
+
|
|
1243
|
+
### See
|
|
1244
|
+
|
|
1245
|
+
[`wrapJSX`](#wrapjsx),
|
|
1246
|
+
[`JSXWrapPipe`](#jsxwrappipe)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Context, default as React } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The return type of {@linkcode contextualize}
|
|
4
|
+
*
|
|
5
|
+
* @see
|
|
6
|
+
* {@linkcode contextualize},
|
|
7
|
+
* {@linkcode ContextualizeWith}
|
|
8
|
+
*/
|
|
9
|
+
export type ContextualizePipe = {
|
|
10
|
+
with: ContextualizeWith;
|
|
11
|
+
end: () => React.JSX.Element;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* @see
|
|
15
|
+
* {@linkcode contextualize},
|
|
16
|
+
* {@linkcode ContextualizePipe}
|
|
17
|
+
*/
|
|
18
|
+
export type ContextualizeWith = <T>(Context: Context<T>, value: NoInfer<T>) => ContextualizePipe;
|
|
19
|
+
/**
|
|
20
|
+
* An alternative way to provide context values to component trees that avoids
|
|
21
|
+
* ever-increasing indentation
|
|
22
|
+
*
|
|
23
|
+
* A context-specific version of the more general {@linkcode wrapJSX} function.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* // Before:
|
|
28
|
+
* return (
|
|
29
|
+
* <CourseIdContext.Provider value={courseId}>
|
|
30
|
+
* <DeckIdContext.Provider value={deckId}>
|
|
31
|
+
* <FlashcardsContext.Provider value={flashcards}>
|
|
32
|
+
* <EventHandlersContext.Provider value={eventHandlers}>
|
|
33
|
+
* <Header />
|
|
34
|
+
* <Main />
|
|
35
|
+
* <Footer />
|
|
36
|
+
* </EventHandlersContext.Provider>
|
|
37
|
+
* </FlashcardsContext.Provider>
|
|
38
|
+
* </DeckIdContext.Provider>
|
|
39
|
+
* </CourseIdContext.Provider>
|
|
40
|
+
* );
|
|
41
|
+
*
|
|
42
|
+
* // After:
|
|
43
|
+
* const jsx = (
|
|
44
|
+
* <>
|
|
45
|
+
* <Header />
|
|
46
|
+
* <Main />
|
|
47
|
+
* <Footer />
|
|
48
|
+
* </>
|
|
49
|
+
* );
|
|
50
|
+
*
|
|
51
|
+
* return contextualize(jsx)
|
|
52
|
+
* .with(EventHandlersContext, eventHandlers)
|
|
53
|
+
* .with(FlashcardsContext, flashcards)
|
|
54
|
+
* .with(DeckIdContext, deckId)
|
|
55
|
+
* .with(CourseIdContext, courseId)
|
|
56
|
+
* .end();
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @param jsx The JSX to contextualize
|
|
60
|
+
*
|
|
61
|
+
* @returns An object with the following properties:
|
|
62
|
+
* - `with`: a function that accepts a context `Context` and a value `value` for
|
|
63
|
+
* it as arguments and returns
|
|
64
|
+
* `contextualize(<Context.Provider value={value}>{jsx}</Context.Provider>)`
|
|
65
|
+
* - `end`: a function that returns `jsx`
|
|
66
|
+
*
|
|
67
|
+
* @see
|
|
68
|
+
* {@linkcode ContextualizePipe}
|
|
69
|
+
*/
|
|
70
|
+
export declare function contextualize(jsx: React.JSX.Element): ContextualizePipe;
|
|
71
|
+
//# sourceMappingURL=contextualize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextualize.d.ts","sourceRoot":"","sources":["../../src/misc/contextualize.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC;AAKvD;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,iBAAiB,CAAC;IACxB,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;CAC9B,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,EAChC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KACd,iBAAiB,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,iBAAiB,CAWvE"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* An alternative way to provide context values to component trees that avoids
|
|
4
|
+
* ever-increasing indentation
|
|
5
|
+
*
|
|
6
|
+
* A context-specific version of the more general {@linkcode wrapJSX} function.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* // Before:
|
|
11
|
+
* return (
|
|
12
|
+
* <CourseIdContext.Provider value={courseId}>
|
|
13
|
+
* <DeckIdContext.Provider value={deckId}>
|
|
14
|
+
* <FlashcardsContext.Provider value={flashcards}>
|
|
15
|
+
* <EventHandlersContext.Provider value={eventHandlers}>
|
|
16
|
+
* <Header />
|
|
17
|
+
* <Main />
|
|
18
|
+
* <Footer />
|
|
19
|
+
* </EventHandlersContext.Provider>
|
|
20
|
+
* </FlashcardsContext.Provider>
|
|
21
|
+
* </DeckIdContext.Provider>
|
|
22
|
+
* </CourseIdContext.Provider>
|
|
23
|
+
* );
|
|
24
|
+
*
|
|
25
|
+
* // After:
|
|
26
|
+
* const jsx = (
|
|
27
|
+
* <>
|
|
28
|
+
* <Header />
|
|
29
|
+
* <Main />
|
|
30
|
+
* <Footer />
|
|
31
|
+
* </>
|
|
32
|
+
* );
|
|
33
|
+
*
|
|
34
|
+
* return contextualize(jsx)
|
|
35
|
+
* .with(EventHandlersContext, eventHandlers)
|
|
36
|
+
* .with(FlashcardsContext, flashcards)
|
|
37
|
+
* .with(DeckIdContext, deckId)
|
|
38
|
+
* .with(CourseIdContext, courseId)
|
|
39
|
+
* .end();
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @param jsx The JSX to contextualize
|
|
43
|
+
*
|
|
44
|
+
* @returns An object with the following properties:
|
|
45
|
+
* - `with`: a function that accepts a context `Context` and a value `value` for
|
|
46
|
+
* it as arguments and returns
|
|
47
|
+
* `contextualize(<Context.Provider value={value}>{jsx}</Context.Provider>)`
|
|
48
|
+
* - `end`: a function that returns `jsx`
|
|
49
|
+
*
|
|
50
|
+
* @see
|
|
51
|
+
* {@linkcode ContextualizePipe}
|
|
52
|
+
*/
|
|
53
|
+
export function contextualize(jsx) {
|
|
54
|
+
return {
|
|
55
|
+
with(Context, value) {
|
|
56
|
+
return contextualize(_jsx(Context.Provider, { value: value, children: jsx }));
|
|
57
|
+
},
|
|
58
|
+
end() {
|
|
59
|
+
return jsx;
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=contextualize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextualize.js","sourceRoot":"","sources":["../../src/misc/contextualize.tsx"],"names":[],"mappings":";AA2BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,MAAM,UAAU,aAAa,CAAC,GAAsB;IAClD,OAAO;QACL,IAAI,CAAI,OAAmB,EAAE,KAAQ;YACnC,OAAO,aAAa,CAClB,KAAC,OAAO,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,GAAG,GAAoB,CACzD,CAAC;QACJ,CAAC;QACD,GAAG;YACD,OAAO,GAAG,CAAC;QACb,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -18,7 +18,7 @@ import type { ArgumentFallback } from '../utils.js';
|
|
|
18
18
|
* Right,
|
|
19
19
|
* }
|
|
20
20
|
*
|
|
21
|
-
* // Before
|
|
21
|
+
* // Before:
|
|
22
22
|
* const DirectionContext = createContext<Direction | undefined>(undefined);
|
|
23
23
|
* DirectionContext.displayName = 'DirectionContext';
|
|
24
24
|
*
|
|
@@ -35,7 +35,7 @@ import type { ArgumentFallback } from '../utils.js';
|
|
|
35
35
|
* return direction;
|
|
36
36
|
* };
|
|
37
37
|
*
|
|
38
|
-
* // After
|
|
38
|
+
* // After:
|
|
39
39
|
* const { DirectionContext, useDirection } =
|
|
40
40
|
* createSafeContext<Direction>()('Direction'); // That's it :)
|
|
41
41
|
*
|
|
@@ -18,7 +18,7 @@ const moValueSymbol = Symbol('noValue');
|
|
|
18
18
|
* Right,
|
|
19
19
|
* }
|
|
20
20
|
*
|
|
21
|
-
* // Before
|
|
21
|
+
* // Before:
|
|
22
22
|
* const DirectionContext = createContext<Direction | undefined>(undefined);
|
|
23
23
|
* DirectionContext.displayName = 'DirectionContext';
|
|
24
24
|
*
|
|
@@ -35,7 +35,7 @@ const moValueSymbol = Symbol('noValue');
|
|
|
35
35
|
* return direction;
|
|
36
36
|
* };
|
|
37
37
|
*
|
|
38
|
-
* // After
|
|
38
|
+
* // After:
|
|
39
39
|
* const { DirectionContext, useDirection } =
|
|
40
40
|
* createSafeContext<Direction>()('Direction'); // That's it :)
|
|
41
41
|
*
|
package/dist/misc/index.d.ts
CHANGED
package/dist/misc/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/misc/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/misc/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC"}
|
package/dist/misc/index.js
CHANGED
package/dist/misc/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/misc/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/misc/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { ComponentProps, JSXElementConstructor, default as React } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The return type of {@linkcode wrapJSX}
|
|
4
|
+
*
|
|
5
|
+
* @see
|
|
6
|
+
* {@linkcode wrapJSX},
|
|
7
|
+
* {@linkcode WrapJSXWith}
|
|
8
|
+
*/
|
|
9
|
+
export type JSXWrapPipe = {
|
|
10
|
+
with: WrapJSXWith;
|
|
11
|
+
end: () => React.JSX.Element;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* @see
|
|
15
|
+
* {@linkcode wrapJSX},
|
|
16
|
+
* {@linkcode JSXWrapPipe}
|
|
17
|
+
*/
|
|
18
|
+
export type WrapJSXWith = <C extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>>(...args: [
|
|
19
|
+
Component: C,
|
|
20
|
+
...(Record<never, unknown> extends Omit<ComponentProps<C>, 'children'> ? [
|
|
21
|
+
props?: React.JSX.IntrinsicAttributes & Omit<ComponentProps<C>, 'children'>
|
|
22
|
+
] : [
|
|
23
|
+
props: React.JSX.IntrinsicAttributes & Omit<ComponentProps<C>, 'children'>
|
|
24
|
+
])
|
|
25
|
+
]) => JSXWrapPipe;
|
|
26
|
+
/**
|
|
27
|
+
* An alternative way to compose JSX that avoids ever-increasing indentation
|
|
28
|
+
*
|
|
29
|
+
* A more general version of the context-specific {@linkcode contextualize}
|
|
30
|
+
* function.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* // Before:
|
|
35
|
+
* createRoot(document.getElementById('root')!).render(
|
|
36
|
+
* <StrictMode>
|
|
37
|
+
* <I18nextProvider i18n={i18n}>
|
|
38
|
+
* <QueryClientProvider client={queryClient}>
|
|
39
|
+
* <NuqsAdapter>
|
|
40
|
+
* <ThemeProvider theme={theme}>
|
|
41
|
+
* <ToasterProvider>
|
|
42
|
+
* <App />
|
|
43
|
+
* </ToasterProvider>
|
|
44
|
+
* </ThemeProvider>
|
|
45
|
+
* </NuqsAdapter>
|
|
46
|
+
* </QueryClientProvider>
|
|
47
|
+
* </I18nextProvider>
|
|
48
|
+
* </StrictMode>,
|
|
49
|
+
* );
|
|
50
|
+
*
|
|
51
|
+
* // After:
|
|
52
|
+
* createRoot(document.getElementById('root')!).render(
|
|
53
|
+
* wrapJSX(<App />)
|
|
54
|
+
* .with(ToasterProvider)
|
|
55
|
+
* .with(ThemeProvider, { theme })
|
|
56
|
+
* .with(NuqsAdapter)
|
|
57
|
+
* .with(QueryClientProvider, { client: queryClient })
|
|
58
|
+
* .with(I18nextProvider, { i18n })
|
|
59
|
+
* .with(StrictMode)
|
|
60
|
+
* .end(),
|
|
61
|
+
* );
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @param jsx The JSX to wrap
|
|
65
|
+
*
|
|
66
|
+
* @returns An object with the following properties:
|
|
67
|
+
* - `with`: a function that accepts a component `Component` and props `props`
|
|
68
|
+
* for it as arguments and returns
|
|
69
|
+
* `wrapJSX(<Component {...props}>{jsx}</Component>)`
|
|
70
|
+
* - `end`: a function that returns `jsx`
|
|
71
|
+
*
|
|
72
|
+
* @see
|
|
73
|
+
* {@linkcode JSXWrapPipe}
|
|
74
|
+
*/
|
|
75
|
+
export declare function wrapJSX(jsx: React.JSX.Element): JSXWrapPipe;
|
|
76
|
+
//# sourceMappingURL=wrapJSX.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrapJSX.d.ts","sourceRoot":"","sources":["../../src/misc/wrapJSX.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,OAAO,IAAI,KAAK,EACjB,MAAM,OAAO,CAAC;AAKf;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,GAAG,EAAE,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;CAC9B,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAErB,CAAC,CAAC,SAAS,MAAM,GAAG,CAAC,iBAAiB,GAAG,qBAAqB,CAAC,GAAG,CAAC,EACjE,GAAG,IAAI,EAAE;IACP,SAAS,EAAE,CAAC;IACZ,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,GAClE;QACE,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,mBAAmB,GACnC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC;KACtC,GACD;QACE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,mBAAmB,GAClC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC;KACtC,CAAC;CACP,KACE,WAAW,CAAC;AAEnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,WAAW,CAc3D"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* An alternative way to compose JSX that avoids ever-increasing indentation
|
|
4
|
+
*
|
|
5
|
+
* A more general version of the context-specific {@linkcode contextualize}
|
|
6
|
+
* function.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* // Before:
|
|
11
|
+
* createRoot(document.getElementById('root')!).render(
|
|
12
|
+
* <StrictMode>
|
|
13
|
+
* <I18nextProvider i18n={i18n}>
|
|
14
|
+
* <QueryClientProvider client={queryClient}>
|
|
15
|
+
* <NuqsAdapter>
|
|
16
|
+
* <ThemeProvider theme={theme}>
|
|
17
|
+
* <ToasterProvider>
|
|
18
|
+
* <App />
|
|
19
|
+
* </ToasterProvider>
|
|
20
|
+
* </ThemeProvider>
|
|
21
|
+
* </NuqsAdapter>
|
|
22
|
+
* </QueryClientProvider>
|
|
23
|
+
* </I18nextProvider>
|
|
24
|
+
* </StrictMode>,
|
|
25
|
+
* );
|
|
26
|
+
*
|
|
27
|
+
* // After:
|
|
28
|
+
* createRoot(document.getElementById('root')!).render(
|
|
29
|
+
* wrapJSX(<App />)
|
|
30
|
+
* .with(ToasterProvider)
|
|
31
|
+
* .with(ThemeProvider, { theme })
|
|
32
|
+
* .with(NuqsAdapter)
|
|
33
|
+
* .with(QueryClientProvider, { client: queryClient })
|
|
34
|
+
* .with(I18nextProvider, { i18n })
|
|
35
|
+
* .with(StrictMode)
|
|
36
|
+
* .end(),
|
|
37
|
+
* );
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @param jsx The JSX to wrap
|
|
41
|
+
*
|
|
42
|
+
* @returns An object with the following properties:
|
|
43
|
+
* - `with`: a function that accepts a component `Component` and props `props`
|
|
44
|
+
* for it as arguments and returns
|
|
45
|
+
* `wrapJSX(<Component {...props}>{jsx}</Component>)`
|
|
46
|
+
* - `end`: a function that returns `jsx`
|
|
47
|
+
*
|
|
48
|
+
* @see
|
|
49
|
+
* {@linkcode JSXWrapPipe}
|
|
50
|
+
*/
|
|
51
|
+
export function wrapJSX(jsx) {
|
|
52
|
+
return {
|
|
53
|
+
with(Component, props = {}) {
|
|
54
|
+
return wrapJSX(_jsx(Component, { ...props, children: jsx }));
|
|
55
|
+
},
|
|
56
|
+
end() {
|
|
57
|
+
return jsx;
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=wrapJSX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wrapJSX.js","sourceRoot":"","sources":["../../src/misc/wrapJSX.tsx"],"names":[],"mappings":";AA2CA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,MAAM,UAAU,OAAO,CAAC,GAAsB;IAC5C,OAAO;QACL,IAAI,CACF,SAEiC,EACjC,QAAgB,EAAE;YAElB,OAAO,OAAO,CAAC,KAAC,SAAS,OAAK,KAAK,YAAG,GAAG,GAAa,CAAC,CAAC;QAC1D,CAAC;QACD,GAAG;YACD,OAAO,GAAG,CAAC;QACb,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aweebit/react-essentials",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": "github:aweebit/react-essentials",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"prettier": "npm run prettier:base -- .",
|
|
11
11
|
"lint": "eslint --max-warnings=0",
|
|
12
12
|
"build": "rimraf dist && tsc -b -f",
|
|
13
|
-
"doc": "rimraf README.md && typedoc",
|
|
13
|
+
"doc": "rimraf README.md && typedoc && node scripts/fixReadmeLinks.js && npm run prettier:base -- README.md",
|
|
14
14
|
"prepack": "npm run build && npm run doc",
|
|
15
15
|
"prepare": "husky"
|
|
16
16
|
},
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@eslint/js": "^9.36.0",
|
|
32
|
+
"@types/node": "^22.18.6",
|
|
32
33
|
"@types/react": "^18.3.24",
|
|
33
34
|
"eslint": "^9.36.0",
|
|
34
35
|
"eslint-config-prettier": "^10.1.8",
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
const rootDir = join(import.meta.dirname, '..');
|
|
5
|
+
|
|
6
|
+
const headerPath = join(rootDir, 'README-header.md');
|
|
7
|
+
const readmePath = join(rootDir, 'README.md');
|
|
8
|
+
|
|
9
|
+
const header = await readFile(headerPath, 'utf8');
|
|
10
|
+
const readme = await readFile(readmePath, 'utf8');
|
|
11
|
+
|
|
12
|
+
const newReadme =
|
|
13
|
+
header +
|
|
14
|
+
readme
|
|
15
|
+
.slice(header.length)
|
|
16
|
+
.replaceAll(
|
|
17
|
+
/\(#useeventlistener((?:-1)?)\)/g,
|
|
18
|
+
(match, /** @type {string} */ suffix) => {
|
|
19
|
+
return `(#useeventlistener${suffix ? '' : '-1'})`;
|
|
20
|
+
},
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
await writeFile(readmePath, newReadme);
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { Context, default as React } from 'react';
|
|
2
|
+
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
4
|
+
import type { wrapJSX } from './wrapJSX.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The return type of {@linkcode contextualize}
|
|
8
|
+
*
|
|
9
|
+
* @see
|
|
10
|
+
* {@linkcode contextualize},
|
|
11
|
+
* {@linkcode ContextualizeWith}
|
|
12
|
+
*/
|
|
13
|
+
export type ContextualizePipe = {
|
|
14
|
+
with: ContextualizeWith;
|
|
15
|
+
end: () => React.JSX.Element;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @see
|
|
20
|
+
* {@linkcode contextualize},
|
|
21
|
+
* {@linkcode ContextualizePipe}
|
|
22
|
+
*/
|
|
23
|
+
export type ContextualizeWith = <T>(
|
|
24
|
+
Context: Context<T>,
|
|
25
|
+
value: NoInfer<T>,
|
|
26
|
+
) => ContextualizePipe;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* An alternative way to provide context values to component trees that avoids
|
|
30
|
+
* ever-increasing indentation
|
|
31
|
+
*
|
|
32
|
+
* A context-specific version of the more general {@linkcode wrapJSX} function.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```tsx
|
|
36
|
+
* // Before:
|
|
37
|
+
* return (
|
|
38
|
+
* <CourseIdContext.Provider value={courseId}>
|
|
39
|
+
* <DeckIdContext.Provider value={deckId}>
|
|
40
|
+
* <FlashcardsContext.Provider value={flashcards}>
|
|
41
|
+
* <EventHandlersContext.Provider value={eventHandlers}>
|
|
42
|
+
* <Header />
|
|
43
|
+
* <Main />
|
|
44
|
+
* <Footer />
|
|
45
|
+
* </EventHandlersContext.Provider>
|
|
46
|
+
* </FlashcardsContext.Provider>
|
|
47
|
+
* </DeckIdContext.Provider>
|
|
48
|
+
* </CourseIdContext.Provider>
|
|
49
|
+
* );
|
|
50
|
+
*
|
|
51
|
+
* // After:
|
|
52
|
+
* const jsx = (
|
|
53
|
+
* <>
|
|
54
|
+
* <Header />
|
|
55
|
+
* <Main />
|
|
56
|
+
* <Footer />
|
|
57
|
+
* </>
|
|
58
|
+
* );
|
|
59
|
+
*
|
|
60
|
+
* return contextualize(jsx)
|
|
61
|
+
* .with(EventHandlersContext, eventHandlers)
|
|
62
|
+
* .with(FlashcardsContext, flashcards)
|
|
63
|
+
* .with(DeckIdContext, deckId)
|
|
64
|
+
* .with(CourseIdContext, courseId)
|
|
65
|
+
* .end();
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @param jsx The JSX to contextualize
|
|
69
|
+
*
|
|
70
|
+
* @returns An object with the following properties:
|
|
71
|
+
* - `with`: a function that accepts a context `Context` and a value `value` for
|
|
72
|
+
* it as arguments and returns
|
|
73
|
+
* `contextualize(<Context.Provider value={value}>{jsx}</Context.Provider>)`
|
|
74
|
+
* - `end`: a function that returns `jsx`
|
|
75
|
+
*
|
|
76
|
+
* @see
|
|
77
|
+
* {@linkcode ContextualizePipe}
|
|
78
|
+
*/
|
|
79
|
+
export function contextualize(jsx: React.JSX.Element): ContextualizePipe {
|
|
80
|
+
return {
|
|
81
|
+
with<T>(Context: Context<T>, value: T) {
|
|
82
|
+
return contextualize(
|
|
83
|
+
<Context.Provider value={value}>{jsx}</Context.Provider>,
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
end() {
|
|
87
|
+
return jsx;
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -21,7 +21,7 @@ const moValueSymbol = Symbol('noValue');
|
|
|
21
21
|
* Right,
|
|
22
22
|
* }
|
|
23
23
|
*
|
|
24
|
-
* // Before
|
|
24
|
+
* // Before:
|
|
25
25
|
* const DirectionContext = createContext<Direction | undefined>(undefined);
|
|
26
26
|
* DirectionContext.displayName = 'DirectionContext';
|
|
27
27
|
*
|
|
@@ -38,7 +38,7 @@ const moValueSymbol = Symbol('noValue');
|
|
|
38
38
|
* return direction;
|
|
39
39
|
* };
|
|
40
40
|
*
|
|
41
|
-
* // After
|
|
41
|
+
* // After:
|
|
42
42
|
* const { DirectionContext, useDirection } =
|
|
43
43
|
* createSafeContext<Direction>()('Direction'); // That's it :)
|
|
44
44
|
*
|
package/src/misc/index.ts
CHANGED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ComponentProps,
|
|
3
|
+
JSXElementConstructor,
|
|
4
|
+
default as React,
|
|
5
|
+
} from 'react';
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
8
|
+
import type { contextualize } from './contextualize.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The return type of {@linkcode wrapJSX}
|
|
12
|
+
*
|
|
13
|
+
* @see
|
|
14
|
+
* {@linkcode wrapJSX},
|
|
15
|
+
* {@linkcode WrapJSXWith}
|
|
16
|
+
*/
|
|
17
|
+
export type JSXWrapPipe = {
|
|
18
|
+
with: WrapJSXWith;
|
|
19
|
+
end: () => React.JSX.Element;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @see
|
|
24
|
+
* {@linkcode wrapJSX},
|
|
25
|
+
* {@linkcode JSXWrapPipe}
|
|
26
|
+
*/
|
|
27
|
+
export type WrapJSXWith =
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
+
<C extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>>(
|
|
30
|
+
...args: [
|
|
31
|
+
Component: C,
|
|
32
|
+
...(Record<never, unknown> extends Omit<ComponentProps<C>, 'children'>
|
|
33
|
+
? [
|
|
34
|
+
props?: React.JSX.IntrinsicAttributes &
|
|
35
|
+
Omit<ComponentProps<C>, 'children'>,
|
|
36
|
+
]
|
|
37
|
+
: [
|
|
38
|
+
props: React.JSX.IntrinsicAttributes &
|
|
39
|
+
Omit<ComponentProps<C>, 'children'>,
|
|
40
|
+
]),
|
|
41
|
+
]
|
|
42
|
+
) => JSXWrapPipe;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* An alternative way to compose JSX that avoids ever-increasing indentation
|
|
46
|
+
*
|
|
47
|
+
* A more general version of the context-specific {@linkcode contextualize}
|
|
48
|
+
* function.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```tsx
|
|
52
|
+
* // Before:
|
|
53
|
+
* createRoot(document.getElementById('root')!).render(
|
|
54
|
+
* <StrictMode>
|
|
55
|
+
* <I18nextProvider i18n={i18n}>
|
|
56
|
+
* <QueryClientProvider client={queryClient}>
|
|
57
|
+
* <NuqsAdapter>
|
|
58
|
+
* <ThemeProvider theme={theme}>
|
|
59
|
+
* <ToasterProvider>
|
|
60
|
+
* <App />
|
|
61
|
+
* </ToasterProvider>
|
|
62
|
+
* </ThemeProvider>
|
|
63
|
+
* </NuqsAdapter>
|
|
64
|
+
* </QueryClientProvider>
|
|
65
|
+
* </I18nextProvider>
|
|
66
|
+
* </StrictMode>,
|
|
67
|
+
* );
|
|
68
|
+
*
|
|
69
|
+
* // After:
|
|
70
|
+
* createRoot(document.getElementById('root')!).render(
|
|
71
|
+
* wrapJSX(<App />)
|
|
72
|
+
* .with(ToasterProvider)
|
|
73
|
+
* .with(ThemeProvider, { theme })
|
|
74
|
+
* .with(NuqsAdapter)
|
|
75
|
+
* .with(QueryClientProvider, { client: queryClient })
|
|
76
|
+
* .with(I18nextProvider, { i18n })
|
|
77
|
+
* .with(StrictMode)
|
|
78
|
+
* .end(),
|
|
79
|
+
* );
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* @param jsx The JSX to wrap
|
|
83
|
+
*
|
|
84
|
+
* @returns An object with the following properties:
|
|
85
|
+
* - `with`: a function that accepts a component `Component` and props `props`
|
|
86
|
+
* for it as arguments and returns
|
|
87
|
+
* `wrapJSX(<Component {...props}>{jsx}</Component>)`
|
|
88
|
+
* - `end`: a function that returns `jsx`
|
|
89
|
+
*
|
|
90
|
+
* @see
|
|
91
|
+
* {@linkcode JSXWrapPipe}
|
|
92
|
+
*/
|
|
93
|
+
export function wrapJSX(jsx: React.JSX.Element): JSXWrapPipe {
|
|
94
|
+
return {
|
|
95
|
+
with(
|
|
96
|
+
Component:
|
|
97
|
+
| keyof React.JSX.IntrinsicElements
|
|
98
|
+
| JSXElementConstructor<object>,
|
|
99
|
+
props: object = {},
|
|
100
|
+
) {
|
|
101
|
+
return wrapJSX(<Component {...props}>{jsx}</Component>);
|
|
102
|
+
},
|
|
103
|
+
end() {
|
|
104
|
+
return jsx;
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|