Skip to content

Commit 912a1a1

Browse files
committed
feat: default impl for factory (viewModelsConfig property);docs: improved
1 parent ee16d18 commit 912a1a1

File tree

15 files changed

+115
-58
lines changed

15 files changed

+115
-58
lines changed

.changeset/silly-moons-matter.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"mobx-view-model": minor
3+
---
4+
5+
Added default implementation of `factory` property in `viewModelsConfig` global config object

.changeset/solid-games-invite.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"mobx-view-model": patch
3+
---
4+
5+
update documentation for all view models, add more links to source code

docs/.vitepress/theme/style.css

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,13 @@ html.dark {
133133

134134
:root {
135135
--vp-custom-block-tip-border: transparent;
136-
--vp-custom-block-tip-text: var(--vp-c-text-1);
137-
--vp-custom-block-tip-bg: var(--vp-c-brand-soft);
138-
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
136+
--vp-custom-block-tip-bg: #dbebfdc2;
139137
}
140138

139+
html.dark {
140+
--vp-custom-block-tip-bg: #273646c2;
141+
}
142+
141143
.i-logos\:mobx-icon {
142144
background: url(/mobx.svg) no-repeat;
143145
background-size: 100% 100%;
@@ -153,3 +155,10 @@ html.dark {
153155
.DocSearch {
154156
--docsearch-primary-color: var(--vp-c-brand-1) !important;
155157
}
158+
159+
.custom-block > .custom-block-title:first-child:last-child {
160+
margin-top: -8px;
161+
}
162+
p:has(>em:first-child:last-child) + div[class*=language-] {
163+
margin-top: -10px;
164+
}

docs/api/other/view-model-lookup.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ It can be:
88
- `ViewModel class reference`
99
- [`React`](https://react.dev) component created with [`withViewModel()`](/react/api/with-view-model) or [`withLazyViewModel()`](/react/api/with-lazy-view-model)
1010

11-
[Reference to source code type](/src/view-model/view-model.store.types.ts#L35)
12-
[Reference to source code with internal usage of this value](/src/view-model/view-model.store.base.ts#L149)
11+
[Reference to source code type](/src/view-model/view-model.store.types.ts#L42)
12+
[Reference to source code with internal usage of this value](/src/view-model/view-model.store.base.ts#L220)
1313

1414
# Example
1515

docs/api/view-model-store/interface.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ title: View Model Store interface
66

77
Interface represeting a store for managing [`ViewModels`](/api/view-models/interface)
88

9-
::: tip
10-
Not required entity for targeted usage of this package, but can be helpful for accessing [ViewModel](/api/view-models/overview)s from everywhere by [ViewModel](/api/view-models/overview) id or [ViewModel](/api/view-models/overview) class name.
9+
::: tip OPTIONAL USE
10+
This is not required for targeted usage of this package, but can be helpful for accessing [ViewModels](/api/view-models/overview) from everywhere by [ViewModelLookup](api/other/view-model-lookup)
1111
:::
1212

13+
[Reference to source code](/src/view-model/view-model.store.ts)
1314

1415
## Method and properties
1516

docs/api/view-models/view-model-simple.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
# ViewModelSimple
1+
# `ViewModelSimple`
22

33
`ViewModelSimple` is a minimalistic implementation of the [ViewModel interface](/api/view-models/interface), designed for lightweight state management with **MobX**. It simplifies reactive state initialization using `makeAutoObservable` while enforcing a consistent instance lifecycle in React applications.
44

5+
[Reference to source code](/src/view-model/view-model-simple.ts)
6+
57
## When to Use
68
Use `ViewModelSimple` when:
79
1. You need `direct control over MobX observability` (e.g., using `makeAutoObservable`)
@@ -43,7 +45,7 @@ export class FruitViewModel implements ViewModelSimple {
4345

4446
### Instance creation
4547

46-
**Recommend** (but not required) to create instances using the [`useCreateViewModel`](/react/api/use-create-view-model) hook. This ensures proper lifecycle management and reactivity:
48+
Create instances using the [`useCreateViewModel`](/react/api/use-create-view-model) hook. This ensures proper lifecycle management and reactivity:
4749

4850
```tsx
4951
import { observer } from "mobx-react-lite";

docs/api/view-models/view-models-config.md

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,25 @@ new ViewModelStoreBase({
2727
})
2828
```
2929

30+
[Reference to source code](/src/config/global-config.ts#L9)
3031

32+
## Recommendations
33+
34+
These are the recommended settings for the global configuration `viewModelsConfig`,
35+
which contain the most optimal values.
36+
37+
```ts
38+
import { loadableDefaultConfig } from '@one-web/uikit-7';
39+
import { viewModelsConfig, ViewModelStoreBase } from 'mobx-view-model';
40+
41+
viewModelsConfig.comparePayload = false;
42+
viewModelsConfig.payloadComputed = 'struct';
43+
viewModelsConfig.payloadObservable = 'ref';
44+
viewModelsConfig.wrapViewsInObserver = true;
45+
46+
viewModelsConfig.observable.viewModels.useDecorators = true; //false
47+
viewModelsConfig.observable.viewModelStores.useDecorators = true; // false
48+
```
3149

3250
## `startViewTransitions`
3351
Indicates whether to enable transitions for the start view.
@@ -64,12 +82,13 @@ Indicates type of observable for `ViewModel` payload.
6482
## `generateId()`
6583
Generates an unique identifier for a [`ViewModel`](/api/view-models/interface).
6684

67-
Default library implementation is [here](/src/utils/create-vm-id-generator.ts#L16)
85+
::: tip This property has default implementation [here](/src/utils/create-vm-id-generator.ts#L16)
86+
:::
6887

6988
#### Example
7089

71-
72-
```ts
90+
_Using `crypto.randomUUID()` to generate view model ids_
91+
```ts{3}
7392
import { viewModelsConfig } from "mobx-view-model";
7493
7594
viewModelsConfig.generateId = () => crypto.randomUUID();
@@ -80,10 +99,16 @@ Factory function for creating [`ViewModel`](/api/view-models/interface) instance
8099

81100
Can be helpful if you want to add some constructor arguments for your own [`ViewModel`](/api/view-models/interface) implementation
82101

102+
103+
::: tip This property has default implementation [here](/src/config/global-config.ts#L25)
104+
:::
105+
83106
#### Example
84107

85-
```ts
108+
_Passing `RootStore` as first constructor parameter_
109+
```ts{2,6}
86110
import { viewModelsConfig } from "mobx-view-model";
111+
import { rootStore } from "@/shared/store";
87112
88113
viewModelsConfig.factory = (config) => {
89114
const { VM } = config;
@@ -150,7 +175,7 @@ viewModelsConfig.processViewComponent = (Component) => {
150175
}
151176
}
152177
```
153-
::: tip It works only for [`withViewModel` HOCs](/react/api/with-view-model)
178+
::: warning It works only for [`withViewModel` HOCs](/react/api/with-view-model)
154179
:::
155180

156181
## `wrapViewsInObserver`
@@ -165,7 +190,7 @@ import { viewModelsConfig } from "mobx-view-model";
165190
viewModelsConfig.wrapViewsInObserver = true;
166191
```
167192

168-
::: tip It works only for [`withViewModel` HOCs](/react/api/with-view-model)
193+
::: warning It works only for [`withViewModel` HOCs](/react/api/with-view-model)
169194
:::
170195

171196
## `observable`
@@ -180,7 +205,8 @@ This is removes `makeObservable(this, annotations)`/`makeObservable(this)` calls
180205
This is change style of marking `MobX` annotations from "decorators style" to "non decorators style".
181206
Very helpful if you want to write code with "non decorators style".
182207

183-
**default value is `true`**
208+
::: tip This property has default value - `true`
209+
:::
184210

185211
Example:
186212
```ts

src/config/global-config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { createGlobalConfig } from 'yummies/complex';
22

33
import { ViewModelsConfig } from './types.js';
4+
import { mergeVMConfigs } from './utils/merge-vm-configs.js';
45

56
/**
67
* Global configuration options for view models
@@ -21,4 +22,11 @@ export const viewModelsConfig = createGlobalConfig<ViewModelsConfig>({
2122
useDecorators: true,
2223
},
2324
},
25+
factory: (config) => {
26+
const VM = config.VM;
27+
return new VM({
28+
...config,
29+
vmConfig: mergeVMConfigs(config.config ?? config.vmConfig),
30+
});
31+
},
2432
});

src/config/types.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ export interface ViewModelObservableConfig {
2828
) => void;
2929
}
3030

31+
export type GenerateViewModelIdFn = (ctx: AnyObject) => string;
32+
33+
export type CreateViewModelFactoryFn<
34+
TViewModel extends AnyViewModel = AnyViewModel,
35+
> = (config: ViewModelCreateConfig<TViewModel>) => TViewModel;
36+
3137
/**
3238
* Configuration options for view models.
3339
* [**Documentation**](https://js2me.github.io/mobx-view-model/api/view-models/view-models-config)
@@ -46,9 +52,9 @@ export interface ViewModelsConfig {
4652
/** [**Documentation**](https://js2me.github.io/mobx-view-model/api/view-models/view-models-config#payloadcomputed) */
4753
payloadComputed?: 'struct' | boolean | ((a: any, b: any) => boolean);
4854
/** [**Documentation**](https://js2me.github.io/mobx-view-model/api/view-models/view-models-config#generateid) */
49-
generateId?: (ctx: AnyObject) => string;
55+
generateId?: GenerateViewModelIdFn;
5056
/** [**Documentation**](https://js2me.github.io/mobx-view-model/api/view-models/view-models-config#factory) */
51-
factory?: (config: ViewModelCreateConfig<AnyViewModel>) => AnyViewModel;
57+
factory: CreateViewModelFactoryFn<AnyViewModel>;
5258
/** [**Documentation**](https://js2me.github.io/mobx-view-model/api/view-models/view-models-config#fallbackcomponent) */
5359
fallbackComponent?: ComponentType;
5460
/** [**Documentation**](https://js2me.github.io/mobx-view-model/api/view-models/view-models-config#onmount) */
@@ -75,10 +81,11 @@ export interface ViewModelsConfig {
7581
*/
7682
export type ViewModelsRawConfig = Omit<
7783
ViewModelsConfig,
78-
'startViewTransitions' | 'observable'
84+
'startViewTransitions' | 'observable' | 'factory'
7985
> & {
8086
startViewTransitions?:
8187
| DeepPartial<ViewModelsConfig['startViewTransitions']>
8288
| boolean;
8389
observable?: DeepPartial<ViewModelsConfig['observable']>;
90+
factory?: ViewModelsConfig['factory'];
8491
};

src/hooks/use-create-view-model.ts

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,19 @@
11
/* eslint-disable react-hooks/rules-of-hooks */
22
import { useContext, useLayoutEffect, useRef, useState } from 'react';
3-
import {
4-
AnyObject,
5-
Class,
6-
AllPropertiesOptional,
7-
Maybe,
8-
} from 'yummies/utils/types';
3+
import { Class, AllPropertiesOptional, Maybe } from 'yummies/utils/types';
94

105
import { viewModelsConfig } from '../config/global-config.js';
11-
import { mergeVMConfigs } from '../config/index.js';
6+
import {
7+
CreateViewModelFactoryFn,
8+
GenerateViewModelIdFn,
9+
} from '../config/index.js';
1210
import { ActiveViewModelContext } from '../contexts/active-view-context.js';
1311
import { ViewModelsContext } from '../contexts/view-models-context.js';
1412
import { useIsomorphicLayoutEffect } from '../lib/hooks/use-isomorphic-layout-effect.js';
1513
import { generateVMId } from '../utils/create-vm-id-generator.js';
16-
import { ViewModelSimple } from '../view-model/view-model.js';
14+
import { ViewModelSimple } from '../view-model/view-model-simple.js';
1715
import { ViewModelCreateConfig } from '../view-model/view-model.store.types.js';
18-
import {
19-
AnyViewModel,
20-
ViewModelParams,
21-
} from '../view-model/view-model.types.js';
16+
import { AnyViewModel } from '../view-model/view-model.types.js';
2217

2318
export interface UseCreateViewModelConfig<TViewModel extends AnyViewModel>
2419
extends Pick<
@@ -33,12 +28,12 @@ export interface UseCreateViewModelConfig<TViewModel extends AnyViewModel>
3328
/**
3429
* Function to generate an identifier for the view model
3530
*/
36-
generateId?: (ctx: AnyObject) => string;
31+
generateId?: GenerateViewModelIdFn;
3732

3833
/**
3934
* Function to create an instance of the VM class
4035
*/
41-
factory?: (config: ViewModelCreateConfig<TViewModel>) => TViewModel;
36+
factory?: CreateViewModelFactoryFn<TViewModel>;
4237
}
4338

4439
const useCreateViewModelSimple = (
@@ -55,8 +50,9 @@ const useCreateViewModelSimple = (
5550

5651
const instance = new VM();
5752
viewModels?.markToBeAttached(instance);
58-
if (viewModels) {
59-
instance.linkStore?.(viewModels);
53+
54+
if (viewModels && instance.linkStore) {
55+
instance.linkStore(viewModels);
6056
}
6157
return instance;
6258
});
@@ -182,13 +178,7 @@ export function useCreateViewModel(VM: Class<any>, ...args: any[]) {
182178
const instance: AnyViewModel =
183179
config?.factory?.(configCreate) ??
184180
viewModels?.createViewModel<any>(configCreate) ??
185-
viewModelsConfig.factory?.(configCreate) ??
186-
new VM({
187-
...configCreate,
188-
vmConfig: mergeVMConfigs(
189-
configCreate.config ?? configCreate.vmConfig,
190-
),
191-
} satisfies ViewModelParams<any>);
181+
viewModelsConfig.factory(configCreate);
192182

193183
instanceRef.current = instance;
194184

0 commit comments

Comments
 (0)