@modular-component/with-conditional-render 0.1.7 → 0.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @modular-component/with-conditional-render
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 09b9673: Update readmes
8
+ - Updated dependencies [09b9673]
9
+ - @modular-component/core@0.2.1
10
+
11
+ ## 0.2.0
12
+
13
+ ### Minor Changes
14
+
15
+ - 83d453f: Rework API for better TypeScript performance and improved DX
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies [83d453f]
20
+ - @modular-component/core@0.2.0
21
+
3
22
  ## 0.1.7
4
23
 
5
24
  ### Patch Changes
package/README.md CHANGED
@@ -1,50 +1,85 @@
1
- # `@modular-component/with-conditional-render`
1
+ # @modular-component/with-conditional-render
2
2
 
3
3
  Provides three stages that allow conditional rendering in `ModularComponent`s:
4
4
 
5
- - `withCondition` will set a `condition` argument to either `true` or `false`, based
5
+ - `with(condition)` will set a customizable argument to either `true` or `false`, based
6
6
  on current arguments,
7
- - `withConditionalFallback` takes a `FunctionComponent` as parameter, and
8
- renders it when the `condition` argument is set to `false`,
9
- - `withConditionalRender` also takes a `FunctionComponent` as parameter, and
10
- renders it when the `condition` argument is _not_ set to `false`.
7
+ - `with(conditionalFallback)` takes a `FunctionComponent` as parameter, and
8
+ renders it when a customizable argument is set to `true`, filling the `render` argument in the process,
9
+ - `with(conditionalRender)` also takes a `FunctionComponent` as parameter, and
10
+ renders it if the `render` argument was not filled earlier.
11
11
 
12
- `withCondition` and `withConditionalFallback` are multiple, so it's possible
13
- to chain multiple conditions with a different fallback for each. Subsequent calls
14
- to `withCondition` will take into account preceding conditions, so that `withConditionalRender`
15
- is only called when all conditions return `true`.
12
+ ## Usage
16
13
 
17
- ## Installation and usage
14
+ ```tsx
15
+ import { ModularComponent } from '@modular-component/core'
16
+ import { condition, conditionalFallback, conditionalRender } from '@modular-component/with-conditional-render'
18
17
 
19
- ```bash
20
- yarn add @modular-component/core @modular-component/with-conditional-render
18
+ const ConditionalComponent = ModularComponent<{ enabled?: boolean }>()
19
+ .with(condition('disabled', ({ props }) => props.enabled !== true))
20
+ .with(conditionalFallback('disabled', () => <>I'm disabled!</>))
21
+ .with(lifecycle(() => {
22
+ // Some data fetching logic...
23
+ return { loading, data }
24
+ }))
25
+ .with(condition('loading', ({ lifecycle }) => lifecycle.loading === false))
26
+ .with(conditionalFallback('loading', () => <>I'm loading!</>))
27
+ .with(conditionalRender(({ lifecycle }) => (
28
+ <>I'm enabled and loaded, here is the content: {lifecycle.data}</>
29
+ )))
21
30
  ```
22
31
 
32
+ ## Multiple conditions and fallbacks
33
+
34
+ You can use the `condition` and `conditionalFallback` multiple times in the same pipeline by providing different
35
+ argument names as the first parameter.
36
+
37
+ ## Implementation
38
+
39
+ The implementation for those stages is a bit more involved than other official extensions. Here, we have restrictions
40
+ for each stage, as well as stage hooks.
41
+
23
42
  ```tsx
24
- import { modularFactory } from '@modular-component/core'
25
- import { WithConditionalRender } from '@modular-component/with-conditional-render'
26
-
27
- const ModularComponent = modularFactory.extend(WithConditionalRender).build()
28
-
29
- const MyModularComponent = ModularComponent<{
30
- isAuthenticated: boolean
31
- isOwner: boolean
32
- }>()
33
- .withCondition(({ props }) => props.isAuthenticated)
34
- .withConditionalFallback(() => (
35
- <div>You need to be authenticated to see this page</div>
36
- ))
37
- .withCondition(({ props }) => props.isOwner)
38
- .withConditionalFallback(() => (
39
- <div>You don't have enough permissions to see this page</div>
40
- ))
41
- .withConditionalRender(({ components }) => (
42
- <>
43
- <h1>Hello, Owner</h1>
44
- </>
45
- ))
46
- ```
43
+ import React, { FunctionComponent } from 'react'
44
+ import { ModularStage } from '@modular-component/core'
47
45
 
48
- ## Learn more
46
+ export function condition<Args, Name extends string>(
47
+ name: Name,
48
+ useCondition: (args: Args) => boolean,
49
+ ): ModularStage<Name, (args: Args) => boolean> {
50
+ return { field: name, useStage: useCondition }
51
+ }
49
52
 
50
- Read the [`ModularComponent` ReadMe](https://github.com/jvdsande/modular-component/blob/master/README.md) for more information about the `ModularComponent` system.
53
+ export function conditionalFallback<
54
+ Args extends { [key in Name]: boolean } & {
55
+ render?: ReturnType<FunctionComponent>
56
+ },
57
+ Name extends string,
58
+ >(
59
+ name: Name,
60
+ useRender: (args: Args) => ReturnType<FunctionComponent>,
61
+ ): ModularStage<`render-${Name}`, (args: Args) => void> {
62
+ return {
63
+ field: `render-${name}`,
64
+ useStage: (args: Args) => {
65
+ args.render = !args[name] || args.render ? args.render : useRender(args)
66
+ },
67
+ }
68
+ }
69
+
70
+ export function conditionalRender<Args, Ref>(
71
+ useRender: (
72
+ args: Args,
73
+ ref: React.ForwardedRef<Ref>,
74
+ ) => ReturnType<FunctionComponent>,
75
+ ): ModularStage<
76
+ 'render',
77
+ (args: Args, ref: React.ForwardedRef<Ref>) => ReturnType<FunctionComponent>
78
+ > {
79
+ return {
80
+ field: 'render',
81
+ useStage: (args: Args, ref: React.ForwardedRef<Ref>) =>
82
+ (args as any).render ?? useRender(args, ref),
83
+ }
84
+ }
85
+ ```
package/dist/index.d.ts CHANGED
@@ -1,47 +1,10 @@
1
- import { FunctionComponent } from 'react';
2
- declare const withCondition: unique symbol;
3
- declare const withConditionalFallback: unique symbol;
4
- declare const withConditionalRender: unique symbol;
5
- declare module '@modular-component/core' {
6
- interface ModularStages<Args, Value> {
7
- [withCondition]: {
8
- restrict: (args: Args) => boolean;
9
- transform: ReturnType<Value extends (args: Args) => boolean ? Value : never>;
10
- };
11
- [withConditionalFallback]: {
12
- restrict: FunctionComponent<Args>;
13
- transform: ReturnType<FunctionComponent<Args>> | null;
14
- };
15
- [withConditionalRender]: {
16
- restrict: FunctionComponent<Args>;
17
- transform: ReturnType<FunctionComponent<Args>> | null;
18
- };
19
- }
20
- }
21
- export declare const WithConditionalRender: {
22
- readonly Condition: {
23
- readonly symbol: typeof withCondition;
24
- readonly field: "condition";
25
- readonly transform: <A extends {
26
- condition?: boolean | undefined;
27
- }, C extends (args: A) => boolean>(args: A, useCondition: C) => boolean;
28
- };
29
- readonly ConditionalRender: {
30
- readonly symbol: typeof withConditionalRender;
31
- readonly field: "render";
32
- readonly transform: <A_1 extends {
33
- condition?: boolean | undefined;
34
- render?: import("react").ReactElement<any, any> | null | undefined;
35
- }, P extends FunctionComponent<A_1>>(args: A_1, useRender: P) => import("react").ReactElement<any, any> | null | undefined;
36
- };
37
- readonly ConditionalFallback: {
38
- readonly symbol: typeof withConditionalFallback;
39
- readonly field: "render";
40
- readonly transform: <A_2 extends {
41
- condition?: boolean | undefined;
42
- render?: import("react").ReactElement<any, any> | null | undefined;
43
- }, P_1 extends FunctionComponent<A_2>>(args: A_2, useRender: P_1) => import("react").ReactElement<any, any> | null | undefined;
44
- };
45
- };
46
- export {};
1
+ import React, { FunctionComponent } from 'react';
2
+ import { ModularStage } from '@modular-component/core';
3
+ export declare function condition<Args, Name extends string>(name: Name, useCondition: (args: Args) => boolean): ModularStage<Name, (args: Args) => boolean>;
4
+ export declare function conditionalFallback<Args extends {
5
+ [key in Name]: boolean;
6
+ } & {
7
+ render?: ReturnType<FunctionComponent>;
8
+ }, Name extends string>(name: Name, useRender: (args: Args) => ReturnType<FunctionComponent>): ModularStage<`render-${Name}`, (args: Args) => void>;
9
+ export declare function conditionalRender<Args, Ref>(useRender: (args: Args, ref: React.ForwardedRef<Ref>) => ReturnType<FunctionComponent>): ModularStage<'render', (args: Args, ref: React.ForwardedRef<Ref>) => ReturnType<FunctionComponent>>;
47
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAA;AAEzC,QAAA,MAAM,aAAa,eAAW,CAAA;AAC9B,QAAA,MAAM,uBAAuB,eAAW,CAAA;AACxC,QAAA,MAAM,qBAAqB,eAAW,CAAA;AAEtC,OAAO,QAAQ,yBAAyB,CAAC;IACvC,UAAiB,aAAa,CAAC,IAAI,EAAE,KAAK;QACxC,CAAC,aAAa,CAAC,EAAE;YACf,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAA;YACjC,SAAS,EAAE,UAAU,CACnB,KAAK,SAAS,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,GAAG,KAAK,GAAG,KAAK,CACtD,CAAA;SACF,CAAA;QACD,CAAC,uBAAuB,CAAC,EAAE;YACzB,QAAQ,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAA;YACjC,SAAS,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAA;SACtD,CAAA;QACD,CAAC,qBAAqB,CAAC,EAAE;YACvB,QAAQ,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAA;YACjC,SAAS,EAAE,UAAU,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAA;SACtD,CAAA;KACF;CACF;AAED,eAAO,MAAM,qBAAqB;;;;;;kCAML,OAAO;;;;;;;;;;;;;;;;;;CAwCzB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAEtD,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,SAAS,MAAM,EACjD,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,GACpC,YAAY,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAE7C;AAED,wBAAgB,mBAAmB,CACjC,IAAI,SAAS;KAAG,GAAG,IAAI,IAAI,GAAG,OAAO;CAAE,GAAG;IACxC,MAAM,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;CACvC,EACD,IAAI,SAAS,MAAM,EAEnB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,UAAU,CAAC,iBAAiB,CAAC,GACvD,YAAY,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC,CAOtD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,EACzC,SAAS,EAAE,CACT,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,KACzB,UAAU,CAAC,iBAAiB,CAAC,GACjC,YAAY,CACb,QAAQ,EACR,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,UAAU,CAAC,iBAAiB,CAAC,CAC5E,CAMA"}
package/dist/index.js CHANGED
@@ -1,32 +1,18 @@
1
- import { createMethodRecord } from '@modular-component/core';
2
- const withCondition = Symbol();
3
- const withConditionalFallback = Symbol();
4
- const withConditionalRender = Symbol();
5
- export const WithConditionalRender = createMethodRecord({
6
- Condition: {
7
- symbol: withCondition,
8
- field: 'condition',
9
- transform: (args, useCondition) => args.condition !== false && useCondition(args),
10
- },
11
- ConditionalRender: {
12
- symbol: withConditionalRender,
13
- field: 'render',
14
- transform: (args, useRender) => {
15
- if (args.condition === false) {
16
- return args.render;
17
- }
18
- return useRender(args);
1
+ export function condition(name, useCondition) {
2
+ return { field: name, useStage: useCondition };
3
+ }
4
+ export function conditionalFallback(name, useRender) {
5
+ return {
6
+ field: `render-${name}`,
7
+ useStage: (args) => {
8
+ args.render = !args[name] || args.render ? args.render : useRender(args);
19
9
  },
20
- },
21
- ConditionalFallback: {
22
- symbol: withConditionalFallback,
10
+ };
11
+ }
12
+ export function conditionalRender(useRender) {
13
+ return {
23
14
  field: 'render',
24
- transform: (args, useRender) => {
25
- if (args.condition !== false || args.render) {
26
- return args.render;
27
- }
28
- return useRender(args);
29
- },
30
- },
31
- });
15
+ useStage: (args, ref) => args.render ?? useRender(args, ref),
16
+ };
17
+ }
32
18
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAI5D,MAAM,aAAa,GAAG,MAAM,EAAE,CAAA;AAC9B,MAAM,uBAAuB,GAAG,MAAM,EAAE,CAAA;AACxC,MAAM,qBAAqB,GAAG,MAAM,EAAE,CAAA;AAqBtC,MAAM,CAAC,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;IACtD,SAAS,EAAE;QACT,MAAM,EAAE,aAAa;QACrB,KAAK,EAAE,WAAW;QAClB,SAAS,EAAE,CAIT,IAAO,EACP,YAAe,EACf,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,KAAK,IAAI,YAAY,CAAC,IAAI,CAAC;KACpD;IACD,iBAAiB,EAAE;QACjB,MAAM,EAAE,qBAAqB;QAC7B,KAAK,EAAE,QAAQ;QACf,SAAS,EAAE,CAIT,IAAO,EACP,SAAY,EACZ,EAAE;YACF,IAAI,IAAI,CAAC,SAAS,KAAK,KAAK,EAAE;gBAC5B,OAAO,IAAI,CAAC,MAAM,CAAA;aACnB;YAED,OAAO,SAAS,CAAC,IAAI,CAAC,CAAA;QACxB,CAAC;KACF;IACD,mBAAmB,EAAE;QACnB,MAAM,EAAE,uBAAuB;QAC/B,KAAK,EAAE,QAAQ;QACf,SAAS,EAAE,CAIT,IAAO,EACP,SAAY,EACZ,EAAE;YACF,IAAI,IAAI,CAAC,SAAS,KAAK,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE;gBAC3C,OAAO,IAAI,CAAC,MAAM,CAAA;aACnB;YAED,OAAO,SAAS,CAAC,IAAI,CAAC,CAAA;QACxB,CAAC;KACF;CACO,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,SAAS,CACvB,IAAU,EACV,YAAqC;IAErC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAA;AAChD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAMjC,IAAU,EACV,SAAwD;IAExD,OAAO;QACL,KAAK,EAAE,UAAU,IAAI,EAAE;QACvB,QAAQ,EAAE,CAAC,IAAU,EAAE,EAAE;YACvB,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;QAC1E,CAAC;KACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,SAGkC;IAKlC,OAAO;QACL,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,CAAC,IAAU,EAAE,GAA4B,EAAE,EAAE,CACpD,IAAY,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC;KAC/C,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "Default",
9
9
  "Conditional"
10
10
  ],
11
- "version": "0.1.7",
11
+ "version": "0.2.1",
12
12
  "type": "module",
13
13
  "license": "MIT",
14
14
  "publishConfig": {
@@ -26,14 +26,14 @@
26
26
  "license": "cp ../../LICENSE ./LICENSE"
27
27
  },
28
28
  "dependencies": {
29
- "@modular-component/core": "0.1.7"
29
+ "@modular-component/core": "0.2.1"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "react": ">=17 <19"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/react": "^18.0.17",
36
- "typescript": "^4.6.4"
36
+ "typescript": "^5.2.2"
37
37
  },
38
38
  "main": "dist/index.js",
39
39
  "types": "dist/index.d.ts"
package/src/index.ts CHANGED
@@ -1,74 +1,42 @@
1
- import { createMethodRecord } from '@modular-component/core'
1
+ import React, { FunctionComponent } from 'react'
2
+ import { ModularStage } from '@modular-component/core'
2
3
 
3
- import { FunctionComponent } from 'react'
4
-
5
- const withCondition = Symbol()
6
- const withConditionalFallback = Symbol()
7
- const withConditionalRender = Symbol()
8
-
9
- declare module '@modular-component/core' {
10
- export interface ModularStages<Args, Value> {
11
- [withCondition]: {
12
- restrict: (args: Args) => boolean
13
- transform: ReturnType<
14
- Value extends (args: Args) => boolean ? Value : never
15
- >
16
- }
17
- [withConditionalFallback]: {
18
- restrict: FunctionComponent<Args>
19
- transform: ReturnType<FunctionComponent<Args>> | null
20
- }
21
- [withConditionalRender]: {
22
- restrict: FunctionComponent<Args>
23
- transform: ReturnType<FunctionComponent<Args>> | null
24
- }
25
- }
4
+ export function condition<Args, Name extends string>(
5
+ name: Name,
6
+ useCondition: (args: Args) => boolean,
7
+ ): ModularStage<Name, (args: Args) => boolean> {
8
+ return { field: name, useStage: useCondition }
26
9
  }
27
10
 
28
- export const WithConditionalRender = createMethodRecord({
29
- Condition: {
30
- symbol: withCondition,
31
- field: 'condition',
32
- transform: <
33
- A extends { condition?: boolean },
34
- C extends (args: A) => boolean,
35
- >(
36
- args: A,
37
- useCondition: C,
38
- ) => args.condition !== false && useCondition(args),
11
+ export function conditionalFallback<
12
+ Args extends { [key in Name]: boolean } & {
13
+ render?: ReturnType<FunctionComponent>
39
14
  },
40
- ConditionalRender: {
41
- symbol: withConditionalRender,
42
- field: 'render',
43
- transform: <
44
- A extends { condition?: boolean; render?: ReturnType<FunctionComponent> },
45
- P extends FunctionComponent<A>,
46
- >(
47
- args: A,
48
- useRender: P,
49
- ) => {
50
- if (args.condition === false) {
51
- return args.render
52
- }
53
-
54
- return useRender(args)
15
+ Name extends string,
16
+ >(
17
+ name: Name,
18
+ useRender: (args: Args) => ReturnType<FunctionComponent>,
19
+ ): ModularStage<`render-${Name}`, (args: Args) => void> {
20
+ return {
21
+ field: `render-${name}`,
22
+ useStage: (args: Args) => {
23
+ args.render = !args[name] || args.render ? args.render : useRender(args)
55
24
  },
56
- },
57
- ConditionalFallback: {
58
- symbol: withConditionalFallback,
59
- field: 'render',
60
- transform: <
61
- A extends { condition?: boolean; render?: ReturnType<FunctionComponent> },
62
- P extends FunctionComponent<A>,
63
- >(
64
- args: A,
65
- useRender: P,
66
- ) => {
67
- if (args.condition !== false || args.render) {
68
- return args.render
69
- }
25
+ }
26
+ }
70
27
 
71
- return useRender(args)
72
- },
73
- },
74
- } as const)
28
+ export function conditionalRender<Args, Ref>(
29
+ useRender: (
30
+ args: Args,
31
+ ref: React.ForwardedRef<Ref>,
32
+ ) => ReturnType<FunctionComponent>,
33
+ ): ModularStage<
34
+ 'render',
35
+ (args: Args, ref: React.ForwardedRef<Ref>) => ReturnType<FunctionComponent>
36
+ > {
37
+ return {
38
+ field: 'render',
39
+ useStage: (args: Args, ref: React.ForwardedRef<Ref>) =>
40
+ (args as any).render ?? useRender(args, ref),
41
+ }
42
+ }