@aweebit/react-essentials 0.9.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.
@@ -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
+ }