@modular-component/with-fragment 0.2.2 → 0.3.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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @modular-component/with-fragment
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1784a2b: Add a clean way to extend the ModularComponent API with new dedicated stage functions
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [1784a2b]
12
+ - @modular-component/core@0.3.0
13
+
14
+ ## 0.2.3
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies [208e156]
19
+ - @modular-component/core@0.2.3
20
+
3
21
  ## 0.2.2
4
22
 
5
23
  ### Patch Changes
package/README.md CHANGED
@@ -8,60 +8,114 @@ specifying a field key to use and returning a single React node.
8
8
 
9
9
  ## Usage
10
10
 
11
+ **Stage function imports**
12
+
11
13
  ```tsx
12
14
  import { ModularComponent, render } from '@modular-component/core'
13
- import { fragment } from '@modular-component/with-fragment'
15
+ import { fragment, fragments } from '@modular-component/with-fragment'
16
+
17
+ // Through multiple calls
18
+ const MultipleCalls = ModularComponent<{ loading: boolean }>()
19
+ .with(fragment('loading', <div>Loading...</div>))
20
+ .with(fragment('loaded', <div>Loaded</div>))
21
+ .with(
22
+ render(({ props, loading, loaded }) => (
23
+ <div>Current status: {props.loading ? loading : loaded}</div>
24
+ )),
25
+ )
26
+
27
+ // Through a single call
28
+ const SingleCall = ModularComponent<{ loading: boolean }>()
29
+ .with(
30
+ fragments({
31
+ loading: <div>Loading...</div>,
32
+ loaded: <div>Loaded</div>,
33
+ }),
34
+ )
35
+ .with(
36
+ render(({ props, fragments }) => (
37
+ <div>
38
+ Current status: {props.loading ? fragments.loading : fragments.loaded}
39
+ </div>
40
+ )),
41
+ )
42
+ ```
43
+
44
+ **Stage registration**
45
+
46
+ ```tsx
47
+ import { ModularComponent } from '@modular-component/core'
48
+ import '@modular-component/core/register'
49
+ import '@modular-component/with-fragment/register'
14
50
 
15
51
  // Through multiple calls
16
52
  const MultipleCalls = ModularComponent<{ loading: boolean }>()
17
- .with(fragment('loading', () => <div>Loading...</div>))
18
- .with(fragment('loaded', () => <div>Loaded</div>))
19
- .with(render(({ props, loading, loaded }) => (
53
+ .withFragment('loading', <div>Loading...</div>)
54
+ .withFragment('loaded', <div>Loaded</div>)
55
+ .withRender(({ props, loading, loaded }) => (
20
56
  <div>Current status: {props.loading ? loading : loaded}</div>
21
- )))
57
+ ))
22
58
 
23
59
  // Through a single call
24
60
  const SingleCall = ModularComponent<{ loading: boolean }>()
25
- .with(fragment(() => ({
61
+ .withFragments({
26
62
  loading: <div>Loading...</div>,
27
63
  loaded: <div>Loaded</div>,
28
- }))
29
- .with(render(({ props, fragments }) => (
30
- <div>Current status: {props.loading ? fragments.loading : fragments.loaded}</div>
31
- ))))
64
+ })
65
+ .withRender(({ props, fragments }) => (
66
+ <div>
67
+ Current status: {props.loading ? fragments.loading : fragments.loaded}
68
+ </div>
69
+ ))
32
70
  ```
33
71
 
34
- ## Implementation
72
+ ## Reacting to previous stages
73
+
74
+ The fragment argument can either be a JSX fragment, or a function
75
+ receiving the previous stages arguments and returning a JSX fragment:
35
76
 
36
- `with(fragment)` receives a function taking the current arguments map as parameter and returns either a map of React node
37
- or a single React node, to set as stage function, and optionally a key to be used as the field.
77
+ ```tsx
78
+ const UserCard = ModularComponent<{
79
+ firstName: string
80
+ lastName: string
81
+ email: string
82
+ }>()
83
+ .withFragment('name', ({ props }) => (
84
+ <p>
85
+ {props.firstName} {props.lastName}
86
+ </p>
87
+ ))
88
+ .withFragment('email', ({ props }) => <p>{props.email}</p>)
89
+ .withRender(({ name, email }) => (
90
+ <article>
91
+ {name}
92
+ {email}
93
+ </article>
94
+ ))
95
+ ```
96
+
97
+ ## Stage registration
98
+
99
+ You can either automatically register the stages on `withFragment` and `withFragments` by importing `@modular-component/with-fragment/register`,
100
+ or handle the registration manually thanks to the `fragment` and `fragments` functions, and `WithFragment` and `WithFragments` type exports.
38
101
 
39
102
  ```ts
40
- import { ReactNode } from 'react'
41
- import { ModularStage } from '@modular-component/core'
42
-
43
- export function fragment<
44
- Args extends {},
45
- Fragments extends Record<string, ReactNode>,
46
- >(
47
- useFragment: (args: Args) => Fragments,
48
- ): ModularStage<'fragments', (args: Args) => Fragments>
49
- export function fragment<
50
- Args extends {},
51
- Fragment extends ReactNode,
52
- Key extends string,
53
- >(
54
- key: Key,
55
- useFragment: (args: Args) => Fragment,
56
- ): ModularStage<Key, (args: Args) => Fragment>
57
-
58
- export function fragment<Key extends string, Stage extends () => unknown>(
59
- key: Key | Stage,
60
- useFragment?: Stage,
61
- ): ModularStage<Key, Stage> {
62
- return {
63
- field: (typeof key === 'string' ? key : 'fragments') as Key,
64
- useStage: (typeof key === 'string' ? useFragment : key) as Stage,
103
+ import { ModularComponent, ModularContext } from '@modular-component/core'
104
+ import {
105
+ fragment,
106
+ fragments,
107
+ WithFragment,
108
+ WithFragments,
109
+ } from '@modular-component/with-fragment'
110
+
111
+ // Register the stages on the factory
112
+ ModularComponent.register({ fragment, fragments })
113
+
114
+ // Extend the type definition
115
+ declare module '@modular-component/stages' {
116
+ export interface ModularComponentStages<Context extends ModularContext> {
117
+ withFragment: WithFragment<Context>
118
+ withFragments: WithFragment<Context>
65
119
  }
66
120
  }
67
121
  ```
package/dist/index.d.ts CHANGED
@@ -1,5 +1,15 @@
1
- import { ReactNode } from 'react';
2
- import { ModularStage } from '@modular-component/core';
3
- export declare function fragment<Args extends {}, Fragments extends Record<string, ReactNode>>(useFragment: (args: Args) => Fragments): ModularStage<'fragments', (args: Args) => Fragments>;
4
- export declare function fragment<Args extends {}, Fragment extends ReactNode, Key extends string>(key: Key, useFragment: (args: Args) => Fragment): ModularStage<Key, (args: Args) => Fragment>;
1
+ import { FunctionComponent } from 'react';
2
+ import { ModularContext, GetConstraintFor, GetValueGetterFor, StageParams, StageReturn } from '@modular-component/core/extend';
3
+ export declare function fragment<Context extends ModularContext, Field extends string>(field: Field, fragment: GetValueGetterFor<Context, Field, ReturnType<FunctionComponent>>): (_?: Context | undefined) => {
4
+ field: Field;
5
+ provide: (args: import("@modular-component/core/extend").GetArgsFor<Context, Field>) => import("react").ReactElement<any, any> | null;
6
+ };
7
+ export type WithFragment<Context extends ModularContext> = <Field extends string>(...args: StageParams<typeof fragment<Context, Field>>) => StageReturn<typeof fragment<Context, Field>>;
8
+ type Constraint<Context extends ModularContext> = GetConstraintFor<Context, 'fragments', Record<string, ReturnType<FunctionComponent>>>;
9
+ export declare function fragments<Context extends ModularContext, Type extends Constraint<Context>>(fragments: GetValueGetterFor<Context, 'fragments', Type>): (_?: Context | undefined) => {
10
+ field: "fragments";
11
+ provide: (args: import("@modular-component/core/extend").GetArgsFor<Context, "fragments">) => Type;
12
+ };
13
+ export type WithFragments<Context extends ModularContext> = <Type extends Constraint<Context>>(...args: StageParams<typeof fragments<Context, Type>>) => StageReturn<typeof fragments<Context, Type>>;
14
+ export {};
5
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAEtD,wBAAgB,QAAQ,CACtB,IAAI,SAAS,EAAE,EACf,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,EAE3C,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,GACrC,YAAY,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,CAAA;AACvD,wBAAgB,QAAQ,CACtB,IAAI,SAAS,EAAE,EACf,QAAQ,SAAS,SAAS,EAC1B,GAAG,SAAS,MAAM,EAElB,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,QAAQ,GACpC,YAAY,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,EAGL,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,WAAW,EACZ,MAAM,gCAAgC,CAAA;AAEvC,wBAAgB,QAAQ,CAAC,OAAO,SAAS,cAAc,EAAE,KAAK,SAAS,MAAM,EAC3E,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,iBAAiB,CAAC,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC;;;EAG3E;AAED,MAAM,MAAM,YAAY,CAAC,OAAO,SAAS,cAAc,IAAI,CACzD,KAAK,SAAS,MAAM,EAEpB,GAAG,IAAI,EAAE,WAAW,CAAC,OAAO,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,KAClD,WAAW,CAAC,OAAO,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAA;AAEjD,KAAK,UAAU,CAAC,OAAO,SAAS,cAAc,IAAI,gBAAgB,CAChE,OAAO,EACP,WAAW,EACX,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAC9C,CAAA;AAED,wBAAgB,SAAS,CACvB,OAAO,SAAS,cAAc,EAC9B,IAAI,SAAS,UAAU,CAAC,OAAO,CAAC,EAChC,SAAS,EAAE,iBAAiB,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC;;;EAEzD;AAED,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,cAAc,IAAI,CAC1D,IAAI,SAAS,UAAU,CAAC,OAAO,CAAC,EAEhC,GAAG,IAAI,EAAE,WAAW,CAAC,OAAO,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,KAClD,WAAW,CAAC,OAAO,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAA"}
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
- export function fragment(key, useFragment) {
2
- return {
3
- field: (typeof key === 'string' ? key : 'fragments'),
4
- useStage: (typeof key === 'string' ? useFragment : key),
5
- };
1
+ import { addTo, wrap, } from '@modular-component/core/extend';
2
+ export function fragment(field, fragment) {
3
+ return addTo().on(field).provide(wrap(fragment));
4
+ }
5
+ export function fragments(fragments) {
6
+ return addTo().on('fragments').provide(wrap(fragments));
6
7
  }
7
8
  //# 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":"AAkBA,MAAM,UAAU,QAAQ,CACtB,GAAgB,EAChB,WAAmB;IAEnB,OAAO;QACL,KAAK,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAQ;QAC3D,QAAQ,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAU;KACjE,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,EACL,IAAI,GAML,MAAM,gCAAgC,CAAA;AAEvC,MAAM,UAAU,QAAQ,CACtB,KAAY,EACZ,QAA0E;IAE1E,OAAO,KAAK,EAAW,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;AAC3D,CAAC;AAcD,MAAM,UAAU,SAAS,CAGvB,SAAwD;IACxD,OAAO,KAAK,EAAW,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAA;AAClE,CAAC"}
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "Default",
9
9
  "Conditional"
10
10
  ],
11
- "version": "0.2.2",
11
+ "version": "0.3.0",
12
12
  "type": "module",
13
13
  "license": "MIT",
14
14
  "publishConfig": {
@@ -17,6 +17,8 @@
17
17
  "files": [
18
18
  "src",
19
19
  "dist",
20
+ "register.js",
21
+ "register.d.ts",
20
22
  "CHANGELOG.md"
21
23
  ],
22
24
  "scripts": {
@@ -25,15 +27,14 @@
25
27
  "build:self": "tsc -p tsconfig.build.json",
26
28
  "license": "cp ../../LICENSE ./LICENSE"
27
29
  },
28
- "dependencies": {
29
- "@modular-component/core": "0.2.2"
30
- },
31
30
  "peerDependencies": {
31
+ "@modular-component/core": "0.3.0",
32
32
  "react": ">=17 <19"
33
33
  },
34
34
  "devDependencies": {
35
+ "@modular-component/core": "*",
35
36
  "@types/react": "^18.0.17",
36
- "typescript": "^5.2.2"
37
+ "typescript": "^5.9.3"
37
38
  },
38
39
  "main": "dist/index.js",
39
40
  "types": "dist/index.d.ts"
package/register.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { ModularContext } from '@modular-component/core'
2
+ import { WithFragment, WithFragments } from '@modular-component/with-fragment'
3
+
4
+ declare module '@modular-component/stages' {
5
+ export interface ModularComponentStages<Context extends ModularContext> {
6
+ withFragment: WithFragment<Context>
7
+ withFragments: WithFragments<Context>
8
+ }
9
+ }
package/register.js ADDED
@@ -0,0 +1,4 @@
1
+ import { ModularComponent } from '@modular-component/core'
2
+ import { fragment, fragments } from '@modular-component/with-fragment'
3
+
4
+ ModularComponent.register({ fragment, fragments })
package/src/index.ts CHANGED
@@ -1,27 +1,42 @@
1
- import { ReactNode } from 'react'
2
- import { ModularStage } from '@modular-component/core'
1
+ import { FunctionComponent } from 'react'
2
+ import {
3
+ addTo,
4
+ wrap,
5
+ ModularContext,
6
+ GetConstraintFor,
7
+ GetValueGetterFor,
8
+ StageParams,
9
+ StageReturn,
10
+ } from '@modular-component/core/extend'
3
11
 
4
- export function fragment<
5
- Args extends {},
6
- Fragments extends Record<string, ReactNode>,
7
- >(
8
- useFragment: (args: Args) => Fragments,
9
- ): ModularStage<'fragments', (args: Args) => Fragments>
10
- export function fragment<
11
- Args extends {},
12
- Fragment extends ReactNode,
13
- Key extends string,
12
+ export function fragment<Context extends ModularContext, Field extends string>(
13
+ field: Field,
14
+ fragment: GetValueGetterFor<Context, Field, ReturnType<FunctionComponent>>,
15
+ ) {
16
+ return addTo<Context>().on(field).provide(wrap(fragment))
17
+ }
18
+
19
+ export type WithFragment<Context extends ModularContext> = <
20
+ Field extends string,
14
21
  >(
15
- key: Key,
16
- useFragment: (args: Args) => Fragment,
17
- ): ModularStage<Key, (args: Args) => Fragment>
22
+ ...args: StageParams<typeof fragment<Context, Field>>
23
+ ) => StageReturn<typeof fragment<Context, Field>>
18
24
 
19
- export function fragment<Key extends string, Stage extends () => unknown>(
20
- key: Key | Stage,
21
- useFragment?: Stage,
22
- ): ModularStage<Key, Stage> {
23
- return {
24
- field: (typeof key === 'string' ? key : 'fragments') as Key,
25
- useStage: (typeof key === 'string' ? useFragment : key) as Stage,
26
- }
25
+ type Constraint<Context extends ModularContext> = GetConstraintFor<
26
+ Context,
27
+ 'fragments',
28
+ Record<string, ReturnType<FunctionComponent>>
29
+ >
30
+
31
+ export function fragments<
32
+ Context extends ModularContext,
33
+ Type extends Constraint<Context>,
34
+ >(fragments: GetValueGetterFor<Context, 'fragments', Type>) {
35
+ return addTo<Context>().on('fragments').provide(wrap(fragments))
27
36
  }
37
+
38
+ export type WithFragments<Context extends ModularContext> = <
39
+ Type extends Constraint<Context>,
40
+ >(
41
+ ...args: StageParams<typeof fragments<Context, Type>>
42
+ ) => StageReturn<typeof fragments<Context, Type>>