@modular-component/with-default-props 0.2.3 → 0.3.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-default-props
2
2
 
3
+ ## 0.3.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 6fa514f: Fix exports compatibility with some bundlers
8
+ - Updated dependencies [6fa514f]
9
+ - @modular-component/core@0.3.1
10
+
11
+ ## 0.3.0
12
+
13
+ ### Minor Changes
14
+
15
+ - 1784a2b: Add a clean way to extend the ModularComponent API with new dedicated stage functions
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies [1784a2b]
20
+ - @modular-component/core@0.3.0
21
+
3
22
  ## 0.2.3
4
23
 
5
24
  ### Patch Changes
package/README.md CHANGED
@@ -1,74 +1,103 @@
1
1
  # @modular-component/with-default-props
2
2
 
3
- Provides a `with(defaultProps)` stage allowing to set default value for props. Contrary to the standard React `defaultProps`
4
- field, the `with(defaultProps)` stage can also _set new props_ that are not surfaced by the component, and react to passed
3
+ Provides a `defaultProps()` stage allowing to set default value for props. Contrary to the standard React `defaultProps`
4
+ field, the `defaultProps()` stage can also _set new props_ that are not surfaced by the component, and react to passed
5
5
  props (or other previous stages) to dynamically compute a default value.
6
6
 
7
7
  ## Usage
8
8
 
9
+ **Stage function imports**
10
+
9
11
  ```tsx
10
- import { ModularComponent } from '@modular-component/core'
12
+ import { ModularComponent, render } from '@modular-component/core'
11
13
  import { defaultProps } from '@modular-component/with-default-props'
12
14
 
13
15
  const MyComponent = ModularComponent<{ someFlag?: boolean }>()
14
- .with(defaultProps({
16
+ .with(
17
+ defaultProps({
18
+ someFlag: false,
19
+ someNewProp: 'hello world',
20
+ }),
21
+ )
22
+ .with(
23
+ render(({ props }) => {
24
+ // props is inferred as { someFlag: boolean; someNewProp: string } at this point
25
+ }),
26
+ )
27
+
28
+ const MyDynamicProps = ModularComponent<{
29
+ role: 'user' | 'owner' | 'admin'
30
+ canEdit?: boolean
31
+ canDelete?: boolean
32
+ }>()
33
+ .with(
34
+ defaultProps(({ props }) => ({
35
+ canEdit: ['owner', 'admin'].includes(props.role),
36
+ canDelete: ['owner'].includes(props.role),
37
+ })),
38
+ )
39
+ .with(
40
+ render(({ props }) => {
41
+ // props is inferred as { role: 'user' | 'owner' | 'admin'; canEdit: boolean; canDelete: boolean }
42
+ // canEdit defaults to true if the role is not "user", false otherwise
43
+ // canDelete defaults to true if the role is "admin", false otherwise
44
+ // canEdit and canDelete can still be controlled by explicitely setting the property
45
+ }),
46
+ )
47
+ ```
48
+
49
+ **Stage registration**
50
+
51
+ ```tsx
52
+ import { ModularComponent } from '@modular-component/core'
53
+ import '@modular-component/core/register'
54
+ import '@modular-component/with-default-props/register'
55
+
56
+ const MyComponent = ModularComponent<{ someFlag?: boolean }>()
57
+ .withDefaultProps({
15
58
  someFlag: false,
16
- someNewProp: 'hello world'
17
- }))
18
- .with(render(({ props }) => (
59
+ someNewProp: 'hello world',
60
+ })
61
+ .withRender(({ props }) => {
19
62
  // props is inferred as { someFlag: boolean; someNewProp: string } at this point
20
- )))
63
+ })
21
64
 
22
65
  const MyDynamicProps = ModularComponent<{
23
- role: 'user' | 'owner' | 'admin',
24
- canEdit?: boolean,
66
+ role: 'user' | 'owner' | 'admin'
67
+ canEdit?: boolean
25
68
  canDelete?: boolean
26
69
  }>()
27
- .with(defaultProps(({ props }) => ({
70
+ .withDefaultProps(({ props }) => ({
28
71
  canEdit: ['owner', 'admin'].includes(props.role),
29
- canDelete: ['owner'].includes(props.role)
72
+ canDelete: ['owner'].includes(props.role),
30
73
  }))
31
- .with(render(({ props }) => {
74
+ .withRender(({ props }) => {
32
75
  // props is inferred as { role: 'user' | 'owner' | 'admin'; canEdit: boolean; canDelete: boolean }
33
76
  // canEdit defaults to true if the role is not "user", false otherwise
34
77
  // canDelete defaults to true if the role is "admin", false otherwise
35
78
  // canEdit and canDelete can still be controlled by explicitely setting the property
36
- })))
79
+ })
37
80
  ```
38
81
 
39
- ## Implementation
82
+ ## Stage registration
40
83
 
41
- `with(defaultProps)` runs a custom stage hook to shallowly merge the default props to the received component props.
42
- Accepted values are restricted to a partial map of the original props to only accept correct types for defined props.
43
- The value can also be a function of the current args.
84
+ You can either automatically register the stage on `withDefaultProps` by importing `@modular-component/with-default-props/register`,
85
+ or handle the registration manually thanks to the `defaultProps` function and `WithDefaultProps` type exports.
44
86
 
45
- ```tsx
46
- import { ModularStage } from '@modular-component/core'
87
+ ```ts
88
+ import { ModularComponent, ModularContext } from '@modular-component/core'
89
+ import {
90
+ defaultProps,
91
+ WithDefaultProps,
92
+ } from '@modular-component/with-default-props'
47
93
 
48
- type Merge<Props, DefaultProps extends Partial<Props>> = {
49
- [key in keyof Props | keyof DefaultProps]-?: key extends keyof Props
50
- ? key extends keyof DefaultProps
51
- ? NonNullable<Props[key]>
52
- : Props[key]
53
- : DefaultProps[key]
54
- }
94
+ // Register the stage on the factory
95
+ ModularComponent.register({ defaultProps })
55
96
 
56
- export function defaultProps<
57
- Args extends { props: {} },
58
- Props extends Args extends { props: infer U } ? U : {},
59
- DefaultProps extends Partial<Props>,
60
- >(
61
- defaultProps: DefaultProps | ((args: Args) => DefaultProps),
62
- ): ModularStage<'props', (args: Args) => Merge<Props, DefaultProps>> {
63
- return {
64
- field: 'props',
65
- useStage: (args: Args) =>
66
- ({
67
- ...(typeof defaultProps === 'function'
68
- ? defaultProps(args)
69
- : defaultProps),
70
- ...args.props,
71
- } as Merge<Props, DefaultProps>),
97
+ // Extend the type definition
98
+ declare module '@modular-component/stages' {
99
+ export interface ModularComponentStages<Context extends ModularContext> {
100
+ withDefaultProps: WithDefaultProps<Context>
72
101
  }
73
102
  }
74
103
  ```
package/dist/index.d.ts CHANGED
@@ -1,11 +1,30 @@
1
- import { ModularStage } from '@modular-component/core';
2
- type Merge<Props, DefaultProps extends Partial<Props>> = {
3
- [key in keyof Props | keyof DefaultProps]-?: key extends keyof Props ? key extends keyof DefaultProps ? NonNullable<Props[key]> : Props[key] : DefaultProps[key];
1
+ import { ModularContext, GetConstraintFor, GetValueGetterFor, StageParams, StageReturn } from '@modular-component/core/extend';
2
+ type NonNullableFields<Type> = {
3
+ [key in keyof Type]-?: undefined extends Type[key] ? never : key;
4
+ }[keyof Type];
5
+ type NullableFields<Type> = {
6
+ [key in keyof Type]: undefined extends Type[key] ? key : never;
7
+ }[keyof Type];
8
+ type OptionalNullable<Type> = {
9
+ [key in NonNullableFields<Type>]: Type[key];
10
+ } & {
11
+ [key in NullableFields<Type>]?: Type[key];
4
12
  };
5
- export declare function defaultProps<Args extends {
6
- props: {};
7
- }, Props extends Args extends {
8
- props: infer U;
9
- } ? U : {}, DefaultProps extends Partial<Props>>(defaultProps: DefaultProps | ((args: Args) => DefaultProps)): ModularStage<'props', (args: Args) => Merge<Props, DefaultProps>>;
13
+ type Merge<Props, DefaultProps extends Partial<Props>> = OptionalNullable<{
14
+ [key in keyof Props | keyof DefaultProps]-?: key extends keyof Props ? key extends keyof DefaultProps ? Props[key] extends undefined | infer U ? U : Props[key] : Props[key] : DefaultProps[key];
15
+ }> extends infer U ? {
16
+ [key in keyof U]: U[key];
17
+ } : never;
18
+ type OnlyRequiredInConstraint<Original, Constraint> = {
19
+ [key in keyof Constraint & keyof Original]: undefined extends Original[key] ? undefined extends Constraint[key] ? never : key : never;
20
+ }[keyof Constraint & keyof Original];
21
+ type Constraint<Context extends ModularContext> = Partial<Context['props']> & Pick<GetConstraintFor<Context, 'props'>, OnlyRequiredInConstraint<Context['props'], GetConstraintFor<Context, 'props'>>> extends infer U ? {
22
+ [key in keyof U]: U[key];
23
+ } : never;
24
+ export declare function defaultProps<Context extends ModularContext, Default extends Constraint<Context>>(useDefault: GetValueGetterFor<Context, 'props', Default>): (_?: Context | undefined) => {
25
+ field: "props";
26
+ provide: (args: import("@modular-component/core/extend").GetArgsFor<Context, "props">) => Merge<Context["props"], Default>;
27
+ };
28
+ export type WithDefaultProps<Context extends ModularContext> = <Default extends Constraint<Context>>(...args: StageParams<typeof defaultProps<Context, Default>>) => StageReturn<typeof defaultProps<Context, Default>>;
10
29
  export {};
11
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAA;AAEtD,KAAK,KAAK,CAAC,KAAK,EAAE,YAAY,SAAS,OAAO,CAAC,KAAK,CAAC,IAAI;KACtD,GAAG,IAAI,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,CAAC,GAAG,GAAG,SAAS,MAAM,KAAK,GAChE,GAAG,SAAS,MAAM,YAAY,GAC5B,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GACvB,KAAK,CAAC,GAAG,CAAC,GACZ,YAAY,CAAC,GAAG,CAAC;CACtB,CAAA;AAED,wBAAgB,YAAY,CAC1B,IAAI,SAAS;IAAE,KAAK,EAAE,EAAE,CAAA;CAAE,EAC1B,KAAK,SAAS,IAAI,SAAS;IAAE,KAAK,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,CAAC,GAAG,EAAE,EACtD,YAAY,SAAS,OAAO,CAAC,KAAK,CAAC,EAEnC,YAAY,EAAE,YAAY,GAAG,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,YAAY,CAAC,GAC1D,YAAY,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAWnE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,EACX,WAAW,EACZ,MAAM,gCAAgC,CAAA;AAEvC,KAAK,iBAAiB,CAAC,IAAI,IAAI;KAC5B,GAAG,IAAI,MAAM,IAAI,CAAC,CAAC,GAAG,SAAS,SAAS,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,GAAG,GAAG;CACjE,CAAC,MAAM,IAAI,CAAC,CAAA;AACb,KAAK,cAAc,CAAC,IAAI,IAAI;KACzB,GAAG,IAAI,MAAM,IAAI,GAAG,SAAS,SAAS,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,KAAK;CAC/D,CAAC,MAAM,IAAI,CAAC,CAAA;AACb,KAAK,gBAAgB,CAAC,IAAI,IAAI;KAC3B,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC;CAC5C,GAAG;KACD,GAAG,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC;CAC1C,CAAA;AAED,KAAK,KAAK,CAAC,KAAK,EAAE,YAAY,SAAS,OAAO,CAAC,KAAK,CAAC,IAAI,gBAAgB,CAAC;KACvE,GAAG,IAAI,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,CAAC,GAAG,GAAG,SAAS,MAAM,KAAK,GAChE,GAAG,SAAS,MAAM,YAAY,GAC5B,KAAK,CAAC,GAAG,CAAC,SAAS,SAAS,GAAG,MAAM,CAAC,GACpC,CAAC,GACD,KAAK,CAAC,GAAG,CAAC,GACZ,KAAK,CAAC,GAAG,CAAC,GACZ,YAAY,CAAC,GAAG,CAAC;CACtB,CAAC,SAAS,MAAM,CAAC,GACd;KAAG,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;CAAE,GAC5B,KAAK,CAAA;AAET,KAAK,wBAAwB,CAAC,QAAQ,EAAE,UAAU,IAAI;KACnD,GAAG,IAAI,MAAM,UAAU,GAAG,MAAM,QAAQ,GAAG,SAAS,SAAS,QAAQ,CAAC,GAAG,CAAC,GACvE,SAAS,SAAS,UAAU,CAAC,GAAG,CAAC,GAC/B,KAAK,GACL,GAAG,GACL,KAAK;CACV,CAAC,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,CAAA;AAEpC,KAAK,UAAU,CAAC,OAAO,SAAS,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,GACzE,IAAI,CACF,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,EAClC,wBAAwB,CACtB,OAAO,CAAC,OAAO,CAAC,EAChB,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CACnC,CACF,SAAS,MAAM,CAAC,GACf;KAAG,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;CAAE,GAC5B,KAAK,CAAA;AAET,wBAAgB,YAAY,CAC1B,OAAO,SAAS,cAAc,EAC9B,OAAO,SAAS,UAAU,CAAC,OAAO,CAAC,EACnC,UAAU,EAAE,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC;;8FAGrC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;EAcpD;AAED,MAAM,MAAM,gBAAgB,CAAC,OAAO,SAAS,cAAc,IAAI,CAC7D,OAAO,SAAS,UAAU,CAAC,OAAO,CAAC,EAEnC,GAAG,IAAI,EAAE,WAAW,CAAC,OAAO,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,KACxD,WAAW,CAAC,OAAO,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA"}
package/dist/index.js CHANGED
@@ -1,12 +1,18 @@
1
- export function defaultProps(defaultProps) {
2
- return {
3
- field: 'props',
4
- useStage: (args) => ({
5
- ...(typeof defaultProps === 'function'
6
- ? defaultProps(args)
7
- : defaultProps),
8
- ...args.props,
9
- }),
10
- };
1
+ import { addTo, wrap, } from '@modular-component/core/extend';
2
+ export function defaultProps(useDefault) {
3
+ return addTo()
4
+ .on('props')
5
+ .provide((args) => {
6
+ const defaultProps = wrap(useDefault)(args);
7
+ const merged = {
8
+ ...args.props
9
+ };
10
+ Object.entries(defaultProps).forEach(([prop, value]) => {
11
+ if (merged[prop] === undefined) {
12
+ merged[prop] = value;
13
+ }
14
+ });
15
+ return merged;
16
+ });
11
17
  }
12
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":"AAUA,MAAM,UAAU,YAAY,CAK1B,YAA2D;IAE3D,OAAO;QACL,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE,CAAC,IAAU,EAAE,EAAE,CACvB,CAAC;YACC,GAAG,CAAC,OAAO,YAAY,KAAK,UAAU;gBACpC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC;gBACpB,CAAC,CAAC,YAAY,CAAC;YACjB,GAAG,IAAI,CAAC,KAAK;SACiB,CAAA;KACnC,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,IAAI,GAML,MAAM,gCAAgC,CAAA;AA6CvC,MAAM,UAAU,YAAY,CAG1B,UAAwD;IACxD,OAAO,KAAK,EAAW;SACpB,EAAE,CAAC,OAAO,CAAC;SACX,OAAO,CAAC,CAAC,IAAI,EAAoC,EAAE;QAClD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAA;QAC3C,MAAM,MAAM,GAAG;YACb,GAAI,IAAoC,CAAC,KAAK;SAC/C,CAAA;QAED,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE;YACrD,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;YACtB,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,OAAO,MAAM,CAAA;IACf,CAAC,CAAC,CAAA;AACN,CAAC"}
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "Default",
9
9
  "Conditional"
10
10
  ],
11
- "version": "0.2.3",
11
+ "version": "0.3.1",
12
12
  "type": "module",
13
13
  "license": "MIT",
14
14
  "publishConfig": {
@@ -17,20 +17,27 @@
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": {
23
25
  "build": "yarn build:core && yarn build:self",
24
26
  "build:core": "yarn workspace @modular-component/core build",
25
- "build:self": "tsc -p tsconfig.build.json",
27
+ "build:self": "tsc -p tsconfig.build.json && tsc --noEmit register",
26
28
  "license": "cp ../../LICENSE ./LICENSE"
27
29
  },
28
- "dependencies": {
29
- "@modular-component/core": "0.2.3"
30
+ "peerDependencies": {
31
+ "@modular-component/core": "0.3.1"
30
32
  },
31
33
  "devDependencies": {
32
- "typescript": "^5.2.2"
34
+ "@modular-component/core": "*",
35
+ "typescript": "^5.9.3"
33
36
  },
34
37
  "main": "dist/index.js",
35
- "types": "dist/index.d.ts"
38
+ "types": "dist/index.d.ts",
39
+ "exports": {
40
+ ".": "./dist/index.js",
41
+ "./register": "./register.js"
42
+ }
36
43
  }
package/register.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { ModularContext } from '@modular-component/core'
2
+ import { WithDefaultProps } from '@modular-component/with-default-props'
3
+
4
+ declare module '@modular-component/stages' {
5
+ export interface ModularComponentStages<Context extends ModularContext> {
6
+ withDefaultProps: WithDefaultProps<Context>
7
+ }
8
+ }
package/register.js ADDED
@@ -0,0 +1,4 @@
1
+ import { ModularComponent } from '@modular-component/core'
2
+ import { defaultProps } from '@modular-component/with-default-props'
3
+
4
+ ModularComponent.register({ defaultProps })
package/src/index.ts CHANGED
@@ -1,28 +1,80 @@
1
- import { ModularStage } from '@modular-component/core'
1
+ import {
2
+ addTo,
3
+ wrap,
4
+ ModularContext,
5
+ GetConstraintFor,
6
+ GetValueGetterFor,
7
+ StageParams,
8
+ StageReturn,
9
+ } from '@modular-component/core/extend'
2
10
 
3
- type Merge<Props, DefaultProps extends Partial<Props>> = {
11
+ type NonNullableFields<Type> = {
12
+ [key in keyof Type]-?: undefined extends Type[key] ? never : key
13
+ }[keyof Type]
14
+ type NullableFields<Type> = {
15
+ [key in keyof Type]: undefined extends Type[key] ? key : never
16
+ }[keyof Type]
17
+ type OptionalNullable<Type> = {
18
+ [key in NonNullableFields<Type>]: Type[key]
19
+ } & {
20
+ [key in NullableFields<Type>]?: Type[key]
21
+ }
22
+
23
+ type Merge<Props, DefaultProps extends Partial<Props>> = OptionalNullable<{
4
24
  [key in keyof Props | keyof DefaultProps]-?: key extends keyof Props
5
25
  ? key extends keyof DefaultProps
6
- ? NonNullable<Props[key]>
26
+ ? Props[key] extends undefined | infer U
27
+ ? U
28
+ : Props[key]
7
29
  : Props[key]
8
30
  : DefaultProps[key]
9
- }
31
+ }> extends infer U
32
+ ? { [key in keyof U]: U[key] }
33
+ : never
34
+
35
+ type OnlyRequiredInConstraint<Original, Constraint> = {
36
+ [key in keyof Constraint & keyof Original]: undefined extends Original[key]
37
+ ? undefined extends Constraint[key]
38
+ ? never
39
+ : key
40
+ : never
41
+ }[keyof Constraint & keyof Original]
42
+
43
+ type Constraint<Context extends ModularContext> = Partial<Context['props']> &
44
+ Pick<
45
+ GetConstraintFor<Context, 'props'>,
46
+ OnlyRequiredInConstraint<
47
+ Context['props'],
48
+ GetConstraintFor<Context, 'props'>
49
+ >
50
+ > extends infer U
51
+ ? { [key in keyof U]: U[key] }
52
+ : never
10
53
 
11
54
  export function defaultProps<
12
- Args extends { props: {} },
13
- Props extends Args extends { props: infer U } ? U : {},
14
- DefaultProps extends Partial<Props>,
15
- >(
16
- defaultProps: DefaultProps | ((args: Args) => DefaultProps),
17
- ): ModularStage<'props', (args: Args) => Merge<Props, DefaultProps>> {
18
- return {
19
- field: 'props',
20
- useStage: (args: Args) =>
21
- ({
22
- ...(typeof defaultProps === 'function'
23
- ? defaultProps(args)
24
- : defaultProps),
25
- ...args.props,
26
- } as Merge<Props, DefaultProps>),
27
- }
55
+ Context extends ModularContext,
56
+ Default extends Constraint<Context>,
57
+ >(useDefault: GetValueGetterFor<Context, 'props', Default>) {
58
+ return addTo<Context>()
59
+ .on('props')
60
+ .provide((args): Merge<Context['props'], Default> => {
61
+ const defaultProps = wrap(useDefault)(args)
62
+ const merged = {
63
+ ...(args as { props: Context['props'] }).props
64
+ }
65
+
66
+ Object.entries(defaultProps).forEach(([prop, value]) => {
67
+ if (merged[prop] === undefined) {
68
+ merged[prop] = value
69
+ }
70
+ })
71
+
72
+ return merged
73
+ })
28
74
  }
75
+
76
+ export type WithDefaultProps<Context extends ModularContext> = <
77
+ Default extends Constraint<Context>,
78
+ >(
79
+ ...args: StageParams<typeof defaultProps<Context, Default>>
80
+ ) => StageReturn<typeof defaultProps<Context, Default>>