mobx-mantle 0.3.5 → 0.3.7
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/README.md +19 -54
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MobX Mantle
|
|
2
2
|
|
|
3
|
-
A lightweight library for building React components with a class-based API and MobX reactivity built in. Get full access to the React ecosystem, with better access to vanilla JS libraries, and simpler overall DX for both.
|
|
3
|
+
A lightweight library for building React components with a familiar class-based API and MobX reactivity built in. Get full access to the React ecosystem, with better access to vanilla JS libraries, and simpler overall DX for both.
|
|
4
4
|
|
|
5
5
|
## Why
|
|
6
6
|
|
|
@@ -79,8 +79,8 @@ toggle(id: number) { // automatically bound to this
|
|
|
79
79
|
|
|
80
80
|
**React to changes explicitly:**
|
|
81
81
|
```tsx
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
onCreate() {
|
|
83
|
+
this.watch(
|
|
84
84
|
() => this.props.filter,
|
|
85
85
|
(filter) => this.applyFilter(filter)
|
|
86
86
|
);
|
|
@@ -94,7 +94,7 @@ onMount() {
|
|
|
94
94
|
| `onCreate()` | Instance created, props available |
|
|
95
95
|
| `onLayoutMount()` | DOM ready, before paint. Return a cleanup function (optional). |
|
|
96
96
|
| `onMount()` | Component mounted, after paint. Return a cleanup function (optional). |
|
|
97
|
-
| `
|
|
97
|
+
| `onUpdate()` | After every render (via `useEffect`). |
|
|
98
98
|
| `onUnmount()` | Component unmounting. Called after cleanups (optional). |
|
|
99
99
|
| `render()` | On mount and updates. Return JSX. |
|
|
100
100
|
|
|
@@ -159,6 +159,8 @@ onCreate() {
|
|
|
159
159
|
}
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
+
`this.watch` wraps MobX's `reaction` with automatic lifecycle disposal. For advanced MobX patterns (`autorun`, `when`, custom schedulers), use `reaction` directly and return a dispose function from `onMount`.
|
|
163
|
+
|
|
162
164
|
### Props Reactivity
|
|
163
165
|
|
|
164
166
|
`this.props` is reactive: your component re-renders when accessed props change.
|
|
@@ -187,10 +189,10 @@ onMount() {
|
|
|
187
189
|
}
|
|
188
190
|
```
|
|
189
191
|
|
|
190
|
-
**Option 3: `
|
|
192
|
+
**Option 3: `onUpdate`** — imperative hook after each render (requires manual dirty-checking):
|
|
191
193
|
|
|
192
194
|
```tsx
|
|
193
|
-
|
|
195
|
+
onUpdate() {
|
|
194
196
|
if (this.props.filter !== this.lastFilter) {
|
|
195
197
|
this.lastFilter = this.props.filter;
|
|
196
198
|
this.applyFilter(this.props.filter);
|
|
@@ -370,42 +372,6 @@ function Parent() {
|
|
|
370
372
|
}
|
|
371
373
|
```
|
|
372
374
|
|
|
373
|
-
## Reactions
|
|
374
|
-
|
|
375
|
-
```tsx
|
|
376
|
-
class SearchView extends View<Props> {
|
|
377
|
-
query = '';
|
|
378
|
-
results: string[] = [];
|
|
379
|
-
|
|
380
|
-
onMount() {
|
|
381
|
-
const dispose = reaction(
|
|
382
|
-
() => this.query,
|
|
383
|
-
async (query) => {
|
|
384
|
-
if (query.length > 2) {
|
|
385
|
-
this.results = await searchApi(query);
|
|
386
|
-
}
|
|
387
|
-
},
|
|
388
|
-
{ delay: 300 }
|
|
389
|
-
);
|
|
390
|
-
|
|
391
|
-
return dispose;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
setQuery(e: React.ChangeEvent<HTMLInputElement>) {
|
|
395
|
-
this.query = e.target.value;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
render() {
|
|
399
|
-
return (
|
|
400
|
-
<div>
|
|
401
|
-
<input value={this.query} onChange={this.setQuery} />
|
|
402
|
-
<ul>{this.results.map(r => <li key={r}>{r}</li>)}</ul>
|
|
403
|
-
</div>
|
|
404
|
-
);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
```
|
|
408
|
-
|
|
409
375
|
## React Hooks
|
|
410
376
|
|
|
411
377
|
Hooks work inside `render()`:
|
|
@@ -439,20 +405,19 @@ class ChartView extends View<{ data: number[] }> {
|
|
|
439
405
|
containerRef = this.ref<HTMLDivElement>();
|
|
440
406
|
chart: Chart | null = null;
|
|
441
407
|
|
|
408
|
+
onCreate() {
|
|
409
|
+
this.watch(
|
|
410
|
+
() => this.props.data,
|
|
411
|
+
(data) => this.chart?.update(data)
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
|
|
442
415
|
onMount() {
|
|
443
416
|
this.chart = new Chart(this.containerRef.current!, {
|
|
444
417
|
data: this.props.data,
|
|
445
418
|
});
|
|
446
419
|
|
|
447
|
-
|
|
448
|
-
() => this.props.data,
|
|
449
|
-
(data) => this.chart?.update(data)
|
|
450
|
-
);
|
|
451
|
-
|
|
452
|
-
return () => {
|
|
453
|
-
dispose();
|
|
454
|
-
this.chart?.destroy();
|
|
455
|
-
};
|
|
420
|
+
return () => this.chart?.destroy();
|
|
456
421
|
}
|
|
457
422
|
|
|
458
423
|
render() {
|
|
@@ -485,7 +450,7 @@ Split effects, multiple refs, dependency tracking: all unnecessary with Mantle.
|
|
|
485
450
|
|
|
486
451
|
## Error Handling
|
|
487
452
|
|
|
488
|
-
Render errors propagate to React error boundaries as usual. Lifecycle errors (`onLayoutMount`, `onMount`, `
|
|
453
|
+
Render errors propagate to React error boundaries as usual. Lifecycle errors (`onLayoutMount`, `onMount`, `onUpdate`, `onUnmount`, `watch`) in both Views and Behaviors are caught and routed through a configurable handler.
|
|
489
454
|
|
|
490
455
|
By default, errors are logged to `console.error`. Configure a global handler to integrate with your error reporting:
|
|
491
456
|
|
|
@@ -494,7 +459,7 @@ import { configure } from 'mobx-mantle';
|
|
|
494
459
|
|
|
495
460
|
configure({
|
|
496
461
|
onError: (error, context) => {
|
|
497
|
-
// context.phase: 'onLayoutMount' | 'onMount' | '
|
|
462
|
+
// context.phase: 'onLayoutMount' | 'onMount' | 'onUpdate' | 'onUnmount' | 'watch'
|
|
498
463
|
// context.name: class name of the View or Behavior
|
|
499
464
|
// context.isBehavior: true if the error came from a Behavior
|
|
500
465
|
Sentry.captureException(error, {
|
|
@@ -694,7 +659,7 @@ Base class for view components. `ViewModel` is an alias for `View`. Use it when
|
|
|
694
659
|
| `onCreate()` | Called when instance created |
|
|
695
660
|
| `onLayoutMount()` | Called before paint, return cleanup (optional) |
|
|
696
661
|
| `onMount()` | Called after paint, return cleanup (optional) |
|
|
697
|
-
| `
|
|
662
|
+
| `onUpdate()` | Called after every render |
|
|
698
663
|
| `onUnmount()` | Called on unmount, after cleanups (optional) |
|
|
699
664
|
| `render()` | Return JSX (optional if using template) |
|
|
700
665
|
| `ref<T>()` | Create a ref for DOM elements |
|
package/dist/index.cjs
CHANGED
|
@@ -388,7 +388,7 @@ var BASE_EXCLUDES = /* @__PURE__ */ new Set([
|
|
|
388
388
|
"onCreate",
|
|
389
389
|
"onLayoutMount",
|
|
390
390
|
"onMount",
|
|
391
|
-
"
|
|
391
|
+
"onUpdate",
|
|
392
392
|
"onUnmount",
|
|
393
393
|
"render",
|
|
394
394
|
"ref",
|
|
@@ -556,9 +556,9 @@ function createView(ViewClass, templateOrOptions) {
|
|
|
556
556
|
}, [vm]);
|
|
557
557
|
(0, import_react.useEffect)(() => {
|
|
558
558
|
try {
|
|
559
|
-
vm.
|
|
559
|
+
vm.onUpdate?.();
|
|
560
560
|
} catch (e) {
|
|
561
|
-
reportError(e, { phase: "
|
|
561
|
+
reportError(e, { phase: "onUpdate", name: ViewClass.name, isBehavior: false });
|
|
562
562
|
}
|
|
563
563
|
});
|
|
564
564
|
if (!template && !vm.render) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/mantle.tsx","../src/behavior.ts","../src/config.ts","../src/decorators.ts"],"sourcesContent":["export {\n // Core classes\n View,\n ViewModel,\n Behavior,\n \n // Wrappers\n createView,\n createBehavior,\n \n // Decorators (for explicit annotation mode)\n observable,\n action,\n computed,\n \n // Config\n configure,\n} from './mantle';\n\nexport type { MantleConfig, MantleErrorContext, WatchOptions } from './mantle';\n","import { useRef, useEffect, useLayoutEffect, forwardRef as reactForwardRef, memo, type Ref, type JSX } from 'react';\r\nimport { makeObservable, observable, computed, action, runInAction, reaction, AnnotationsMap, type IObservableValue } from 'mobx';\r\nimport { useObserver } from 'mobx-react-lite';\r\nimport {\r\n type BehaviorEntry,\r\n isBehavior,\r\n layoutMountBehavior,\r\n mountBehavior,\r\n unmountBehavior,\r\n} from './behavior';\r\nimport { globalConfig, reportError, type WatchOptions } from './config';\r\nimport { getAnnotations } from './decorators';\r\n\r\n// Re-export config utilities\r\nexport { configure, type MantleConfig, type MantleErrorContext, type WatchOptions } from './config';\r\n\r\n// Re-export decorators for single-import convenience\r\nexport { observable, action, computed } from './decorators';\r\n\r\n/** Tracks refs created by View.ref() — no footprint on the object itself */\r\nconst viewRefs = new WeakSet();\r\n\r\n/** Shallow-compare two objects by own enumerable keys */\r\nfunction shallowEqual(a: any, b: any): boolean {\r\n if (a === b) return true;\r\n if (!a || !b) return false;\r\n const keysA = Object.keys(a);\r\n const keysB = Object.keys(b);\r\n if (keysA.length !== keysB.length) return false;\r\n for (const key of keysA) {\r\n if (a[key] !== b[key]) return false;\r\n }\r\n return true;\r\n}\r\n\r\nexport class View<P = {}> {\r\n /** @internal */\r\n _propsBox!: IObservableValue<P>;\r\n\r\n get props(): P {\r\n return this._propsBox.get();\r\n }\r\n\r\n /** @internal — called by createView to silently update props during render */\r\n _syncProps(value: P) {\r\n // Directly set the internal value without triggering MobX notifications.\r\n // React renders the component tree synchronously — if we used runInAction\r\n // here, endBatch() would flush reactions and try to update other observer\r\n // components while React is still rendering, causing:\r\n // \"Cannot update component A while rendering component B\"\r\n //\r\n // The value is updated so this._propsBox.get() returns the correct value\r\n // during render. Reactions are notified separately in useLayoutEffect.\r\n (this._propsBox as any).value_ = value;\r\n }\r\n\r\n forwardRef?: Ref<any>;\r\n\r\n /** @internal */\r\n _behaviors: BehaviorEntry[] = [];\r\n\r\n /** @internal */\r\n _watchDisposers: (() => void)[] = [];\r\n\r\n onCreate?(props: P): void;\r\n onLayoutMount?(): void | (() => void);\r\n onMount?(): void | (() => void);\r\n onUpdated?(): void;\r\n onUnmount?(): void;\r\n\r\n ref<T extends HTMLElement = HTMLElement>(): { current: T | null } {\r\n const r = { current: null } as { current: T | null };\r\n viewRefs.add(r);\r\n return r;\r\n }\r\n\r\n /**\r\n * Watch a reactive expression and run a callback when it changes.\r\n * Automatically disposed on unmount.\r\n * \r\n * @param expr - Reactive expression (getter) to watch\r\n * @param callback - Called when the expression result changes\r\n * @param options - Optional configuration (delay, fireImmediately)\r\n * @returns Dispose function for early teardown\r\n * \r\n * @example\r\n * ```tsx\r\n * onCreate() {\r\n * this.watch(\r\n * () => this.query,\r\n * async (query) => {\r\n * if (query.length > 2) {\r\n * this.results = await searchApi(query);\r\n * }\r\n * },\r\n * { delay: 300 }\r\n * );\r\n * }\r\n * ```\r\n */\r\n watch<T>(\r\n expr: () => T,\r\n callback: (value: T, prevValue: T | undefined) => void,\r\n options?: WatchOptions\r\n ): () => void {\r\n const dispose = reaction(\r\n expr,\r\n (value, prevValue) => {\r\n try {\r\n callback(value, prevValue);\r\n } catch (e) {\r\n reportError(e, { phase: 'watch', name: this.constructor.name, isBehavior: false });\r\n }\r\n },\r\n {\r\n delay: options?.delay,\r\n fireImmediately: options?.fireImmediately,\r\n }\r\n );\r\n\r\n this._watchDisposers.push(dispose);\r\n\r\n // Return a dispose function that also removes from the array\r\n return () => {\r\n dispose();\r\n const idx = this._watchDisposers.indexOf(dispose);\r\n if (idx !== -1) this._watchDisposers.splice(idx, 1);\r\n };\r\n }\r\n\r\n /** @internal */\r\n _disposeWatchers(): void {\r\n for (const dispose of this._watchDisposers) {\r\n dispose();\r\n }\r\n this._watchDisposers.length = 0;\r\n }\r\n\r\n /** @internal - Scan own properties for behavior instances and register them */\r\n _collectBehaviors(): void {\r\n for (const key of Object.keys(this)) {\r\n if (key.startsWith('_')) continue;\r\n const value = (this as any)[key];\r\n if (isBehavior(value)) {\r\n this._behaviors.push({ instance: value });\r\n }\r\n }\r\n }\r\n\r\n /** @internal */\r\n _layoutMountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n layoutMountBehavior(behavior);\r\n }\r\n }\r\n\r\n /** @internal */\r\n _mountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n mountBehavior(behavior);\r\n }\r\n }\r\n\r\n /** @internal */\r\n _unmountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n unmountBehavior(behavior);\r\n }\r\n }\r\n\r\n render?(): JSX.Element | null;\r\n}\r\n\r\n/** Alias for View - use when separating ViewModel from template */\r\nexport { View as ViewModel };\r\n\r\n// Re-export from behavior module\r\nexport { createBehavior, Behavior } from './behavior';\r\n\r\n// Base class members that should not be made observable\r\nconst BASE_EXCLUDES = new Set([\r\n 'props',\r\n '_propsBox',\r\n 'forwardRef', \r\n 'onCreate',\r\n 'onLayoutMount',\r\n 'onMount', \r\n 'onUpdated',\r\n 'onUnmount',\r\n 'render', \r\n 'ref',\r\n 'watch',\r\n 'constructor',\r\n '_behaviors',\r\n '_collectBehaviors',\r\n '_layoutMountBehaviors',\r\n '_mountBehaviors',\r\n '_unmountBehaviors',\r\n '_syncProps',\r\n '_watchDisposers',\r\n '_disposeWatchers',\r\n]);\r\n\r\n/**\r\n * Detects if a value is a ref created by View.ref()\r\n * These should use observable.ref to preserve object identity for React\r\n */\r\nfunction isViewRef(value: unknown): boolean {\r\n return value !== null && typeof value === 'object' && viewRefs.has(value as object);\r\n}\r\n\r\n/**\r\n * Creates observable annotations for a View subclass instance.\r\n * This is needed because makeAutoObservable doesn't work with inheritance.\r\n */\r\nfunction makeViewObservable<T extends View>(instance: T, autoBind: boolean) {\r\n const annotations: AnnotationsMap<T, never> = {} as AnnotationsMap<T, never>;\r\n\r\n // Collect own properties (instance state) → observable\r\n // Also check prototype for class field declarations (handles uninitialized fields)\r\n const ownKeys = new Set([\r\n ...Object.keys(instance),\r\n ...Object.keys(Object.getPrototypeOf(instance)),\r\n ]);\r\n\r\n for (const key of ownKeys) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n\r\n const value = (instance as any)[key];\r\n\r\n // Skip functions (these are handled in the prototype walk)\r\n if (typeof value === 'function') continue;\r\n\r\n // Skip behavior instances (they're already observable)\r\n if (isBehavior(value)) {\r\n (annotations as any)[key] = observable.ref;\r\n continue;\r\n }\r\n\r\n // Use observable.ref for View.ref() objects to preserve identity\r\n if (isViewRef(value)) {\r\n (annotations as any)[key] = observable.ref;\r\n } else {\r\n (annotations as any)[key] = observable;\r\n }\r\n }\r\n\r\n // Walk prototype chain up to (but not including) View\r\n let proto = Object.getPrototypeOf(instance);\r\n while (proto && proto !== View.prototype) {\r\n const descriptors = Object.getOwnPropertyDescriptors(proto);\r\n\r\n for (const [key, descriptor] of Object.entries(descriptors)) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n\r\n if (descriptor.get) {\r\n // Getter → computed\r\n (annotations as any)[key] = computed;\r\n } else if (typeof descriptor.value === 'function') {\r\n // Method → action (optionally bound)\r\n (annotations as any)[key] = autoBind ? action.bound : action;\r\n }\r\n }\r\n\r\n proto = Object.getPrototypeOf(proto);\r\n }\r\n\r\n makeObservable(instance, annotations);\r\n}\r\n\r\ntype PropsOf<V> = V extends View<infer P> ? P : object;\r\n\r\nexport function createView<V extends View<any>>(\r\n ViewClass: new () => V,\r\n templateOrOptions?: ((vm: V) => JSX.Element) | { autoObservable?: boolean }\r\n) {\r\n type P = PropsOf<V>;\r\n\r\n const template = typeof templateOrOptions === 'function' ? templateOrOptions : undefined;\r\n const options = typeof templateOrOptions === 'object' ? templateOrOptions : {};\r\n const { autoObservable = globalConfig.autoObservable } = options;\r\n\r\n const Component = reactForwardRef<unknown, P>((props, ref) => {\r\n const vmRef = useRef<V | null>(null);\r\n const classRef = useRef(ViewClass);\r\n const prevPropsRef = useRef<P | null>(null);\r\n const propsNotifyingRef = useRef(false);\r\n\r\n // HMR: class identity changes when the module re-executes, but useRef\r\n // values survive (React Fast Refresh preserves hooks). On detection,\r\n // we simply discard the old instance and create fresh — clean slate.\r\n // In production this check is always false (class identity is stable).\r\n if (vmRef.current && classRef.current !== ViewClass) {\r\n classRef.current = ViewClass;\r\n vmRef.current = null;\r\n }\r\n\r\n if (!vmRef.current) {\r\n const instance = new ViewClass();\r\n\r\n // Props is always reactive via observable.box (works with all decorator modes)\r\n instance._propsBox = observable.box(props, { deep: false });\r\n instance.forwardRef = ref;\r\n\r\n // Collect behavior instances from properties (must happen before makeObservable)\r\n instance._collectBehaviors();\r\n\r\n // Check for Mantle decorator annotations first\r\n const decoratorAnnotations = getAnnotations(instance);\r\n \r\n if (decoratorAnnotations) {\r\n // Mantle decorators: use collected annotations\r\n // Auto-bind all methods for stable `this` references\r\n const annotations = { ...decoratorAnnotations };\r\n \r\n // Walk prototype chain to auto-bind methods not explicitly decorated\r\n let proto = Object.getPrototypeOf(instance);\r\n while (proto && proto !== View.prototype) {\r\n const descriptors = Object.getOwnPropertyDescriptors(proto);\r\n for (const [key, descriptor] of Object.entries(descriptors)) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n if (typeof descriptor.value === 'function') {\r\n annotations[key] = action.bound;\r\n }\r\n }\r\n proto = Object.getPrototypeOf(proto);\r\n }\r\n \r\n makeObservable(instance, annotations as AnnotationsMap<V, never>);\r\n } else if (autoObservable) {\r\n makeViewObservable(instance, true);\r\n } else {\r\n // For legacy decorator users: applies decorator metadata\r\n makeObservable(instance);\r\n }\r\n\r\n // Proxy forwards property access to instance.props, so reads are tracked\r\n // by MobX when used in reactions/computeds (same behavior as this.props)\r\n const reactiveProps = new Proxy({} as P, {\r\n get: (_, key) => (instance.props as any)[key],\r\n has: (_, key) => key in (instance.props as any),\r\n ownKeys: () => Reflect.ownKeys(instance.props as object),\r\n getOwnPropertyDescriptor: (_, key) =>\r\n Reflect.getOwnPropertyDescriptor(instance.props as object, key),\r\n });\r\n instance.onCreate?.(reactiveProps);\r\n vmRef.current = instance;\r\n prevPropsRef.current = props as P;\r\n }\r\n\r\n const vm = vmRef.current;\r\n\r\n // Dev warning: detect when a prop-triggered reaction causes a re-render.\r\n // This means a reaction is being used for derived state — a computed getter\r\n // would avoid the double render.\r\n if (process.env.NODE_ENV !== 'production' && propsNotifyingRef.current) {\r\n console.warn(\r\n `[mobx-mantle] ${ViewClass.name}: A reaction to a prop change modified ` +\r\n `observable state, which caused an extra re-render. Consider using a ` +\r\n `computed getter instead.`\r\n );\r\n propsNotifyingRef.current = false;\r\n }\r\n\r\n // Silently update _propsBox.value_ so this.props returns the correct value\r\n // during render, without triggering MobX reactions (which would cause\r\n // \"Cannot update component A while rendering component B\").\r\n vm._syncProps(props as P);\r\n vm.forwardRef = ref;\r\n\r\n // After render completes, properly notify MobX observers of prop changes.\r\n // This enables reaction(() => this.props.x, ...) in lifecycle methods.\r\n // useLayoutEffect runs after React finishes the render pass, so it's safe\r\n // to flush reactions here.\r\n useLayoutEffect(() => {\r\n if (!shallowEqual(prevPropsRef.current, props)) {\r\n prevPropsRef.current = props as P;\r\n propsNotifyingRef.current = true;\r\n runInAction(() => {\r\n vm._propsBox.set(props);\r\n });\r\n // If a reaction triggered a synchronous re-render, the warning\r\n // already fired above. Clear the flag for the normal case.\r\n propsNotifyingRef.current = false;\r\n }\r\n });\r\n\r\n // [vm] dep ensures effects re-run when instance changes (HMR).\r\n // On normal renders vm is stable, so effects run once — same as [].\r\n useLayoutEffect(() => {\r\n vm._layoutMountBehaviors();\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const result = vm.onLayoutMount?.();\r\n if (process.env.NODE_ENV !== 'production' && result instanceof Promise) {\r\n console.error(\r\n `[mobx-mantle] ${ViewClass.name}.onLayoutMount() returned a Promise. ` +\r\n `Lifecycle methods must be synchronous. Use a sync onLayoutMount that ` +\r\n `calls an async method instead.`\r\n );\r\n }\r\n cleanup = result as (() => void) | undefined;\r\n } catch (e) {\r\n reportError(e, { phase: 'onLayoutMount', name: ViewClass.name, isBehavior: false });\r\n }\r\n return () => {\r\n cleanup?.();\r\n };\r\n }, [vm]);\r\n\r\n useEffect(() => {\r\n vm._mountBehaviors();\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const result = vm.onMount?.();\r\n if (process.env.NODE_ENV !== 'production' && result instanceof Promise) {\r\n console.error(\r\n `[mobx-mantle] ${ViewClass.name}.onMount() returned a Promise. ` +\r\n `Lifecycle methods must be synchronous. Use a sync onMount that ` +\r\n `calls an async method instead.`\r\n );\r\n }\r\n cleanup = result as (() => void) | undefined;\r\n } catch (e) {\r\n reportError(e, { phase: 'onMount', name: ViewClass.name, isBehavior: false });\r\n }\r\n return () => {\r\n cleanup?.();\r\n try {\r\n vm.onUnmount?.();\r\n } catch (e) {\r\n reportError(e, { phase: 'onUnmount', name: ViewClass.name, isBehavior: false });\r\n }\r\n vm._disposeWatchers();\r\n vm._unmountBehaviors();\r\n };\r\n }, [vm]);\r\n\r\n // Called after every render (via useEffect)\r\n useEffect(() => {\r\n try {\r\n vm.onUpdated?.();\r\n } catch (e) {\r\n reportError(e, { phase: 'onUpdated', name: ViewClass.name, isBehavior: false });\r\n }\r\n });\r\n\r\n if (!template && !vm.render) {\r\n throw new Error(\r\n `[mobx-mantle] ${ViewClass.name}: Missing render() method. Either define render() in your View class or pass a template function to createView().`\r\n );\r\n }\r\n\r\n // Only the render call is tracked by MobX (useObserver).\r\n return useObserver(() => {\r\n return template ? template(vm) : vm.render!();\r\n });\r\n });\r\n\r\n // Wrap in React.memo to match observer()'s behavior — skip re-renders\r\n // when parent re-renders but props haven't changed (shallow comparison).\r\n return memo(Component) as typeof Component;\r\n}\r\n\r\n","import { makeObservable, observable, computed, action, reaction, type AnnotationsMap } from 'mobx';\nimport { globalConfig, reportError, type WatchOptions } from './config';\n\n/** Symbol marker to identify behavior instances */\nexport const BEHAVIOR_MARKER = Symbol('behavior');\n\n// Behavior base class members that should not be made observable\nconst BEHAVIOR_EXCLUDES = new Set([\n 'onCreate',\n 'onLayoutMount',\n 'onMount',\n 'onUnmount',\n 'watch',\n 'constructor',\n '_watchDisposers',\n '_disposeWatchers',\n]);\n\n/**\n * Detects if a value looks like a React ref ({ current: ... })\n * These should use observable.ref to preserve object identity\n */\nfunction isRefLike(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false;\n if (Array.isArray(value)) return false;\n return 'current' in value && Object.keys(value).length === 1;\n}\n\n/**\n * Base class for behaviors. Provides lifecycle method signatures for IDE autocomplete.\n * Extend this class and wrap with createBehavior() to create a factory.\n * \n * @example\n * ```tsx\n * class WindowSizeBehavior extends Behavior {\n * width = window.innerWidth;\n * onCreate(breakpoint = 768) { ... }\n * onMount() { ... }\n * }\n * export const withWindowSize = createBehavior(WindowSizeBehavior);\n * ```\n */\nexport class Behavior {\n /** @internal */\n _watchDisposers: (() => void)[] = [];\n\n onCreate?(...args: any[]): void;\n onLayoutMount?(): void | (() => void);\n onMount?(): void | (() => void);\n onUnmount?(): void;\n\n /**\n * Watch a reactive expression and run a callback when it changes.\n * Automatically disposed on unmount.\n * \n * @param expr - Reactive expression (getter) to watch\n * @param callback - Called when the expression result changes\n * @param options - Optional configuration (delay, fireImmediately)\n * @returns Dispose function for early teardown\n * \n * @example\n * ```tsx\n * onCreate(url: string) {\n * this.url = url;\n * this.watch(() => this.url, () => this.fetchData());\n * }\n * ```\n */\n watch<T>(\n expr: () => T,\n callback: (value: T, prevValue: T | undefined) => void,\n options?: WatchOptions\n ): () => void {\n const dispose = reaction(\n expr,\n (value, prevValue) => {\n try {\n callback(value, prevValue);\n } catch (e) {\n reportError(e, { phase: 'watch', name: this.constructor.name, isBehavior: true });\n }\n },\n {\n delay: options?.delay,\n fireImmediately: options?.fireImmediately,\n }\n );\n\n this._watchDisposers.push(dispose);\n\n // Return a dispose function that also removes from the array\n return () => {\n dispose();\n const idx = this._watchDisposers.indexOf(dispose);\n if (idx !== -1) this._watchDisposers.splice(idx, 1);\n };\n }\n\n /** @internal */\n _disposeWatchers(): void {\n for (const dispose of this._watchDisposers) {\n dispose();\n }\n this._watchDisposers.length = 0;\n }\n}\n\n/**\n * Makes a behavior instance observable, handling inheritance properly.\n * Works with classes that extend Behavior or plain classes.\n */\nfunction makeBehaviorObservable<T extends object>(instance: T): void {\n const annotations: AnnotationsMap<T, never> = {} as AnnotationsMap<T, never>;\n\n // Collect own properties → observable\n const ownKeys = new Set([\n ...Object.keys(instance),\n ...Object.keys(Object.getPrototypeOf(instance)),\n ]);\n\n for (const key of ownKeys) {\n if (BEHAVIOR_EXCLUDES.has(key)) continue;\n if (key in annotations) continue;\n\n const value = (instance as any)[key];\n if (typeof value === 'function') continue;\n\n // Use observable.ref for ref-like objects to preserve identity\n if (isRefLike(value)) {\n (annotations as any)[key] = observable.ref;\n } else {\n (annotations as any)[key] = observable;\n }\n }\n\n // Walk prototype chain up to (but not including) Behavior or Object\n let proto = Object.getPrototypeOf(instance);\n while (proto && proto !== Behavior.prototype && proto !== Object.prototype) {\n const descriptors = Object.getOwnPropertyDescriptors(proto);\n\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (BEHAVIOR_EXCLUDES.has(key)) continue;\n if (key in annotations) continue;\n\n if (descriptor.get) {\n (annotations as any)[key] = computed;\n } else if (typeof descriptor.value === 'function') {\n (annotations as any)[key] = action.bound;\n }\n }\n\n proto = Object.getPrototypeOf(proto);\n }\n\n makeObservable(instance, annotations);\n}\n\n/** @internal */\nexport interface BehaviorEntry {\n instance: any;\n cleanup?: () => void;\n layoutCleanup?: () => void;\n}\n\n/**\n * Extracts parameter types from onCreate method\n */\ntype OnCreateParams<T> = T extends { onCreate(...args: infer A): any } ? A : [];\n\n/**\n * Extracts constructor parameter types\n */\ntype ConstructorParams<T> = T extends new (...args: infer A) => any ? A : [];\n\n/**\n * Determines the args for createBehavior:\n * - If constructor has args, use those\n * - Otherwise, if onCreate has args, use those\n */\ntype BehaviorArgs<T extends new (...args: any[]) => any> = \n ConstructorParams<T> extends [] \n ? OnCreateParams<InstanceType<T>> \n : ConstructorParams<T>;\n\n/**\n * Creates a behavior factory with automatic observable wrapping and lifecycle management.\n * \n * Returns a factory function (not a class) — use without `new`:\n * \n * @example Defining a behavior\n * ```tsx\n * class DragTrait extends Behavior {\n * ref!: RefObject<HTMLElement>;\n * \n * onCreate(ref: RefObject<HTMLElement>) {\n * this.ref = ref;\n * }\n * \n * onMount() {\n * this.ref.current?.addEventListener('pointerdown', this.onPointerDown);\n * return () => this.ref.current?.removeEventListener('pointerdown', this.onPointerDown);\n * }\n * }\n * \n * export const withDrag = createBehavior(DragTrait);\n * ```\n * \n * @example Using in a View\n * ```tsx\n * class Editor extends View<Props> {\n * canvas = this.ref<HTMLCanvasElement>();\n * \n * // No `new` keyword — factory function\n * drag = withDrag(this.canvas);\n * autosave = withAutosave('/api/save', 5000);\n * }\n * export default createView(Editor);\n * ```\n * \n * The `with` prefix convention signals that the view manages this behavior's lifecycle.\n */\n/**\n * Type that supports both `new` and direct call syntax\n */\ntype BehaviorFactory<Args extends any[], Instance> = {\n new (...args: Args): Instance;\n (...args: Args): Instance;\n};\n\nexport function createBehavior<T extends new (...args: any[]) => any>(\n Def: T,\n options?: { autoObservable?: boolean }\n): BehaviorFactory<BehaviorArgs<T>, InstanceType<T>> {\n // Internal class that wraps the user's behavior definition\n const BehaviorClass = class extends (Def as any) {\n static [BEHAVIOR_MARKER] = true;\n\n constructor(...args: any[]) {\n super(...args);\n \n // Call onCreate with args (if it exists)\n if (typeof this.onCreate === 'function') {\n this.onCreate(...args);\n }\n \n // Make the instance observable (respects global config and per-behavior options)\n const autoObservable = options?.autoObservable ?? globalConfig.autoObservable;\n if (autoObservable) {\n makeBehaviorObservable(this);\n } else {\n // For decorator users: applies decorator metadata\n makeObservable(this);\n }\n }\n };\n\n // Preserve the original class name for debugging\n Object.defineProperty(BehaviorClass, 'name', { value: Def.name });\n\n // Use Proxy to make the class callable without `new`\n // This allows both: withWindowSize(768) and new withWindowSize(768)\n return new Proxy(BehaviorClass, {\n apply(_target, _thisArg, args) {\n return new BehaviorClass(...args);\n },\n }) as unknown as BehaviorFactory<BehaviorArgs<T>, InstanceType<T>>;\n}\n\n\n/**\n * Checks if a value is a behavior instance created by createBehavior()\n */\nexport function isBehavior(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false;\n return (value.constructor as any)?.[BEHAVIOR_MARKER] === true;\n}\n\n/** @internal */\nexport function layoutMountBehavior(behavior: BehaviorEntry): void {\n const inst = behavior.instance;\n\n if ('onLayoutMount' in inst && typeof inst.onLayoutMount === 'function') {\n try {\n behavior.layoutCleanup = inst.onLayoutMount() ?? undefined;\n } catch (e) {\n reportError(e, { phase: 'onLayoutMount', name: inst.constructor.name, isBehavior: true });\n }\n }\n}\n\n/** @internal */\nexport function mountBehavior(behavior: BehaviorEntry): void {\n const inst = behavior.instance;\n\n if ('onMount' in inst && typeof inst.onMount === 'function') {\n try {\n behavior.cleanup = inst.onMount() ?? undefined;\n } catch (e) {\n reportError(e, { phase: 'onMount', name: inst.constructor.name, isBehavior: true });\n }\n }\n}\n\n/** @internal */\nexport function unmountBehavior(behavior: BehaviorEntry): void {\n // Call layout cleanup if exists\n behavior.layoutCleanup?.();\n\n // Call cleanup if exists\n behavior.cleanup?.();\n\n // Call onUnmount if exists\n const inst = behavior.instance;\n if ('onUnmount' in inst && typeof inst.onUnmount === 'function') {\n try {\n inst.onUnmount();\n } catch (e) {\n reportError(e, { phase: 'onUnmount', name: inst.constructor.name, isBehavior: true });\n }\n }\n\n // Dispose all watchers\n if (typeof inst._disposeWatchers === 'function') {\n inst._disposeWatchers();\n }\n}\n","/** Options for the watch method */\r\nexport interface WatchOptions {\r\n /** Debounce the callback by N milliseconds */\r\n delay?: number;\r\n /** Run callback immediately with current value */\r\n fireImmediately?: boolean;\r\n}\r\n\r\n/**\r\n * Error context passed to the onError handler\r\n */\r\nexport interface MantleErrorContext {\r\n /** The lifecycle phase where the error occurred */\r\n phase: 'onLayoutMount' | 'onMount' | 'onUpdated' | 'onUnmount' | 'watch';\r\n /** The View or Behavior class name */\r\n name: string;\r\n /** Whether the error came from a Behavior (true) or a View (false) */\r\n isBehavior: boolean;\r\n}\r\n\r\n/**\r\n * Global configuration options for mobx-mantle\r\n */\r\nexport interface MantleConfig {\r\n /** Whether to automatically make View/Behavior instances observable (default: true) */\r\n autoObservable?: boolean;\r\n /** Global error handler for lifecycle errors. Defaults to console.error. */\r\n onError?: (error: unknown, context: MantleErrorContext) => void;\r\n}\r\n\r\nexport const globalConfig: MantleConfig = {\r\n autoObservable: true,\r\n};\r\n\r\n/** @internal Report a lifecycle error through the configured handler or console.error */\r\nexport function reportError(error: unknown, context: MantleErrorContext): void {\r\n if (globalConfig.onError) {\r\n globalConfig.onError(error, context);\r\n } else {\r\n console.error(\r\n `[mobx-mantle] Error in ${context.isBehavior ? 'behavior' : 'view'} ${context.name}.${context.phase}():`,\r\n error,\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Configure global defaults for mobx-mantle.\r\n * Settings can still be overridden per-view in createView options.\r\n */\r\nexport function configure(config: MantleConfig): void {\r\n Object.assign(globalConfig, config);\r\n}\r\n","import * as mobx from 'mobx';\r\n\r\n/**\r\n * Symbol key for storing decorator annotations in class metadata.\r\n * These annotations are read by createView() after construction.\r\n */\r\nexport const ANNOTATIONS = Symbol('mantle:annotations');\r\n\r\n/**\r\n * Decorator context type for TC39 decorators\r\n */\r\ninterface DecoratorContext {\r\n kind: 'field' | 'method' | 'getter' | 'setter' | 'accessor' | 'class';\r\n name: string | symbol;\r\n metadata: Record<symbol, unknown>;\r\n}\r\n\r\n/**\r\n * Helper to set annotation metadata\r\n */\r\nfunction setAnnotation(context: DecoratorContext, annotation: any): void {\r\n context.metadata[ANNOTATIONS] ??= {};\r\n (context.metadata[ANNOTATIONS] as Record<string | symbol, any>)[context.name] = annotation;\r\n}\r\n\r\n/**\r\n * Marks a field as observable. No `accessor` keyword needed.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function observable(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable);\r\n}\r\n\r\n/**\r\n * Observable variants for different observation modes\r\n */\r\nobservable.ref = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.ref);\r\n};\r\n\r\nobservable.shallow = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.shallow);\r\n};\r\n\r\nobservable.struct = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.struct);\r\n};\r\n\r\nobservable.deep = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.deep);\r\n};\r\n\r\n/**\r\n * Marks a method as an action. Auto-bound by default.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * \r\n * @action increment() {\r\n * this.count++;\r\n * }\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function action(_value: Function, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.action.bound);\r\n}\r\n\r\n/**\r\n * Marks a getter as computed.\r\n * Note: Getters are automatically computed in autoObservable mode,\r\n * but this decorator is useful for explicit annotation.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * \r\n * @computed get doubled() {\r\n * return this.count * 2;\r\n * }\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function computed(_value: Function, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.computed);\r\n}\r\n\r\n/**\r\n * Retrieves the annotations stored in class metadata.\r\n * Used by createView() to apply MobX observability.\r\n */\r\nexport function getAnnotations(instance: object): Record<string, any> | undefined {\r\n const metadata = (instance.constructor as any)[Symbol.metadata];\r\n return metadata?.[ANNOTATIONS] as Record<string, any> | undefined;\r\n}\r\n"],"mappings":"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","names":["action","computed","observable","import_mobx","observable","action","computed","reactForwardRef"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/mantle.tsx","../src/behavior.ts","../src/config.ts","../src/decorators.ts"],"sourcesContent":["export {\n // Core classes\n View,\n ViewModel,\n Behavior,\n \n // Wrappers\n createView,\n createBehavior,\n \n // Decorators (for explicit annotation mode)\n observable,\n action,\n computed,\n \n // Config\n configure,\n} from './mantle';\n\nexport type { MantleConfig, MantleErrorContext, WatchOptions } from './mantle';\n","import { useRef, useEffect, useLayoutEffect, forwardRef as reactForwardRef, memo, type Ref, type JSX } from 'react';\r\nimport { makeObservable, observable, computed, action, runInAction, reaction, AnnotationsMap, type IObservableValue } from 'mobx';\r\nimport { useObserver } from 'mobx-react-lite';\r\nimport {\r\n type BehaviorEntry,\r\n isBehavior,\r\n layoutMountBehavior,\r\n mountBehavior,\r\n unmountBehavior,\r\n} from './behavior';\r\nimport { globalConfig, reportError, type WatchOptions } from './config';\r\nimport { getAnnotations } from './decorators';\r\n\r\n// Re-export config utilities\r\nexport { configure, type MantleConfig, type MantleErrorContext, type WatchOptions } from './config';\r\n\r\n// Re-export decorators for single-import convenience\r\nexport { observable, action, computed } from './decorators';\r\n\r\n/** Tracks refs created by View.ref() — no footprint on the object itself */\r\nconst viewRefs = new WeakSet();\r\n\r\n/** Shallow-compare two objects by own enumerable keys */\r\nfunction shallowEqual(a: any, b: any): boolean {\r\n if (a === b) return true;\r\n if (!a || !b) return false;\r\n const keysA = Object.keys(a);\r\n const keysB = Object.keys(b);\r\n if (keysA.length !== keysB.length) return false;\r\n for (const key of keysA) {\r\n if (a[key] !== b[key]) return false;\r\n }\r\n return true;\r\n}\r\n\r\nexport class View<P = {}> {\r\n /** @internal */\r\n _propsBox!: IObservableValue<P>;\r\n\r\n get props(): P {\r\n return this._propsBox.get();\r\n }\r\n\r\n /** @internal — called by createView to silently update props during render */\r\n _syncProps(value: P) {\r\n // Directly set the internal value without triggering MobX notifications.\r\n // React renders the component tree synchronously — if we used runInAction\r\n // here, endBatch() would flush reactions and try to update other observer\r\n // components while React is still rendering, causing:\r\n // \"Cannot update component A while rendering component B\"\r\n //\r\n // The value is updated so this._propsBox.get() returns the correct value\r\n // during render. Reactions are notified separately in useLayoutEffect.\r\n (this._propsBox as any).value_ = value;\r\n }\r\n\r\n forwardRef?: Ref<any>;\r\n\r\n /** @internal */\r\n _behaviors: BehaviorEntry[] = [];\r\n\r\n /** @internal */\r\n _watchDisposers: (() => void)[] = [];\r\n\r\n onCreate?(props: P): void;\r\n onLayoutMount?(): void | (() => void);\r\n onMount?(): void | (() => void);\r\n onUpdate?(): void;\r\n onUnmount?(): void;\r\n\r\n ref<T extends HTMLElement = HTMLElement>(): { current: T | null } {\r\n const r = { current: null } as { current: T | null };\r\n viewRefs.add(r);\r\n return r;\r\n }\r\n\r\n /**\r\n * Watch a reactive expression and run a callback when it changes.\r\n * Automatically disposed on unmount.\r\n * \r\n * @param expr - Reactive expression (getter) to watch\r\n * @param callback - Called when the expression result changes\r\n * @param options - Optional configuration (delay, fireImmediately)\r\n * @returns Dispose function for early teardown\r\n * \r\n * @example\r\n * ```tsx\r\n * onCreate() {\r\n * this.watch(\r\n * () => this.query,\r\n * async (query) => {\r\n * if (query.length > 2) {\r\n * this.results = await searchApi(query);\r\n * }\r\n * },\r\n * { delay: 300 }\r\n * );\r\n * }\r\n * ```\r\n */\r\n watch<T>(\r\n expr: () => T,\r\n callback: (value: T, prevValue: T | undefined) => void,\r\n options?: WatchOptions\r\n ): () => void {\r\n const dispose = reaction(\r\n expr,\r\n (value, prevValue) => {\r\n try {\r\n callback(value, prevValue);\r\n } catch (e) {\r\n reportError(e, { phase: 'watch', name: this.constructor.name, isBehavior: false });\r\n }\r\n },\r\n {\r\n delay: options?.delay,\r\n fireImmediately: options?.fireImmediately,\r\n }\r\n );\r\n\r\n this._watchDisposers.push(dispose);\r\n\r\n // Return a dispose function that also removes from the array\r\n return () => {\r\n dispose();\r\n const idx = this._watchDisposers.indexOf(dispose);\r\n if (idx !== -1) this._watchDisposers.splice(idx, 1);\r\n };\r\n }\r\n\r\n /** @internal */\r\n _disposeWatchers(): void {\r\n for (const dispose of this._watchDisposers) {\r\n dispose();\r\n }\r\n this._watchDisposers.length = 0;\r\n }\r\n\r\n /** @internal - Scan own properties for behavior instances and register them */\r\n _collectBehaviors(): void {\r\n for (const key of Object.keys(this)) {\r\n if (key.startsWith('_')) continue;\r\n const value = (this as any)[key];\r\n if (isBehavior(value)) {\r\n this._behaviors.push({ instance: value });\r\n }\r\n }\r\n }\r\n\r\n /** @internal */\r\n _layoutMountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n layoutMountBehavior(behavior);\r\n }\r\n }\r\n\r\n /** @internal */\r\n _mountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n mountBehavior(behavior);\r\n }\r\n }\r\n\r\n /** @internal */\r\n _unmountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n unmountBehavior(behavior);\r\n }\r\n }\r\n\r\n render?(): JSX.Element | null;\r\n}\r\n\r\n/** Alias for View - use when separating ViewModel from template */\r\nexport { View as ViewModel };\r\n\r\n// Re-export from behavior module\r\nexport { createBehavior, Behavior } from './behavior';\r\n\r\n// Base class members that should not be made observable\r\nconst BASE_EXCLUDES = new Set([\r\n 'props',\r\n '_propsBox',\r\n 'forwardRef', \r\n 'onCreate',\r\n 'onLayoutMount',\r\n 'onMount', \r\n 'onUpdate',\r\n 'onUnmount',\r\n 'render', \r\n 'ref',\r\n 'watch',\r\n 'constructor',\r\n '_behaviors',\r\n '_collectBehaviors',\r\n '_layoutMountBehaviors',\r\n '_mountBehaviors',\r\n '_unmountBehaviors',\r\n '_syncProps',\r\n '_watchDisposers',\r\n '_disposeWatchers',\r\n]);\r\n\r\n/**\r\n * Detects if a value is a ref created by View.ref()\r\n * These should use observable.ref to preserve object identity for React\r\n */\r\nfunction isViewRef(value: unknown): boolean {\r\n return value !== null && typeof value === 'object' && viewRefs.has(value as object);\r\n}\r\n\r\n/**\r\n * Creates observable annotations for a View subclass instance.\r\n * This is needed because makeAutoObservable doesn't work with inheritance.\r\n */\r\nfunction makeViewObservable<T extends View>(instance: T, autoBind: boolean) {\r\n const annotations: AnnotationsMap<T, never> = {} as AnnotationsMap<T, never>;\r\n\r\n // Collect own properties (instance state) → observable\r\n // Also check prototype for class field declarations (handles uninitialized fields)\r\n const ownKeys = new Set([\r\n ...Object.keys(instance),\r\n ...Object.keys(Object.getPrototypeOf(instance)),\r\n ]);\r\n\r\n for (const key of ownKeys) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n\r\n const value = (instance as any)[key];\r\n\r\n // Skip functions (these are handled in the prototype walk)\r\n if (typeof value === 'function') continue;\r\n\r\n // Skip behavior instances (they're already observable)\r\n if (isBehavior(value)) {\r\n (annotations as any)[key] = observable.ref;\r\n continue;\r\n }\r\n\r\n // Use observable.ref for View.ref() objects to preserve identity\r\n if (isViewRef(value)) {\r\n (annotations as any)[key] = observable.ref;\r\n } else {\r\n (annotations as any)[key] = observable;\r\n }\r\n }\r\n\r\n // Walk prototype chain up to (but not including) View\r\n let proto = Object.getPrototypeOf(instance);\r\n while (proto && proto !== View.prototype) {\r\n const descriptors = Object.getOwnPropertyDescriptors(proto);\r\n\r\n for (const [key, descriptor] of Object.entries(descriptors)) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n\r\n if (descriptor.get) {\r\n // Getter → computed\r\n (annotations as any)[key] = computed;\r\n } else if (typeof descriptor.value === 'function') {\r\n // Method → action (optionally bound)\r\n (annotations as any)[key] = autoBind ? action.bound : action;\r\n }\r\n }\r\n\r\n proto = Object.getPrototypeOf(proto);\r\n }\r\n\r\n makeObservable(instance, annotations);\r\n}\r\n\r\ntype PropsOf<V> = V extends View<infer P> ? P : object;\r\n\r\nexport function createView<V extends View<any>>(\r\n ViewClass: new () => V,\r\n templateOrOptions?: ((vm: V) => JSX.Element) | { autoObservable?: boolean }\r\n) {\r\n type P = PropsOf<V>;\r\n\r\n const template = typeof templateOrOptions === 'function' ? templateOrOptions : undefined;\r\n const options = typeof templateOrOptions === 'object' ? templateOrOptions : {};\r\n const { autoObservable = globalConfig.autoObservable } = options;\r\n\r\n const Component = reactForwardRef<unknown, P>((props, ref) => {\r\n const vmRef = useRef<V | null>(null);\r\n const classRef = useRef(ViewClass);\r\n const prevPropsRef = useRef<P | null>(null);\r\n const propsNotifyingRef = useRef(false);\r\n\r\n // HMR: class identity changes when the module re-executes, but useRef\r\n // values survive (React Fast Refresh preserves hooks). On detection,\r\n // we simply discard the old instance and create fresh — clean slate.\r\n // In production this check is always false (class identity is stable).\r\n if (vmRef.current && classRef.current !== ViewClass) {\r\n classRef.current = ViewClass;\r\n vmRef.current = null;\r\n }\r\n\r\n if (!vmRef.current) {\r\n const instance = new ViewClass();\r\n\r\n // Props is always reactive via observable.box (works with all decorator modes)\r\n instance._propsBox = observable.box(props, { deep: false });\r\n instance.forwardRef = ref;\r\n\r\n // Collect behavior instances from properties (must happen before makeObservable)\r\n instance._collectBehaviors();\r\n\r\n // Check for Mantle decorator annotations first\r\n const decoratorAnnotations = getAnnotations(instance);\r\n \r\n if (decoratorAnnotations) {\r\n // Mantle decorators: use collected annotations\r\n // Auto-bind all methods for stable `this` references\r\n const annotations = { ...decoratorAnnotations };\r\n \r\n // Walk prototype chain to auto-bind methods not explicitly decorated\r\n let proto = Object.getPrototypeOf(instance);\r\n while (proto && proto !== View.prototype) {\r\n const descriptors = Object.getOwnPropertyDescriptors(proto);\r\n for (const [key, descriptor] of Object.entries(descriptors)) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n if (typeof descriptor.value === 'function') {\r\n annotations[key] = action.bound;\r\n }\r\n }\r\n proto = Object.getPrototypeOf(proto);\r\n }\r\n \r\n makeObservable(instance, annotations as AnnotationsMap<V, never>);\r\n } else if (autoObservable) {\r\n makeViewObservable(instance, true);\r\n } else {\r\n // For legacy decorator users: applies decorator metadata\r\n makeObservable(instance);\r\n }\r\n\r\n // Proxy forwards property access to instance.props, so reads are tracked\r\n // by MobX when used in reactions/computeds (same behavior as this.props)\r\n const reactiveProps = new Proxy({} as P, {\r\n get: (_, key) => (instance.props as any)[key],\r\n has: (_, key) => key in (instance.props as any),\r\n ownKeys: () => Reflect.ownKeys(instance.props as object),\r\n getOwnPropertyDescriptor: (_, key) =>\r\n Reflect.getOwnPropertyDescriptor(instance.props as object, key),\r\n });\r\n instance.onCreate?.(reactiveProps);\r\n vmRef.current = instance;\r\n prevPropsRef.current = props as P;\r\n }\r\n\r\n const vm = vmRef.current;\r\n\r\n // Dev warning: detect when a prop-triggered reaction causes a re-render.\r\n // This means a reaction is being used for derived state — a computed getter\r\n // would avoid the double render.\r\n if (process.env.NODE_ENV !== 'production' && propsNotifyingRef.current) {\r\n console.warn(\r\n `[mobx-mantle] ${ViewClass.name}: A reaction to a prop change modified ` +\r\n `observable state, which caused an extra re-render. Consider using a ` +\r\n `computed getter instead.`\r\n );\r\n propsNotifyingRef.current = false;\r\n }\r\n\r\n // Silently update _propsBox.value_ so this.props returns the correct value\r\n // during render, without triggering MobX reactions (which would cause\r\n // \"Cannot update component A while rendering component B\").\r\n vm._syncProps(props as P);\r\n vm.forwardRef = ref;\r\n\r\n // After render completes, properly notify MobX observers of prop changes.\r\n // This enables reaction(() => this.props.x, ...) in lifecycle methods.\r\n // useLayoutEffect runs after React finishes the render pass, so it's safe\r\n // to flush reactions here.\r\n useLayoutEffect(() => {\r\n if (!shallowEqual(prevPropsRef.current, props)) {\r\n prevPropsRef.current = props as P;\r\n propsNotifyingRef.current = true;\r\n runInAction(() => {\r\n vm._propsBox.set(props);\r\n });\r\n // If a reaction triggered a synchronous re-render, the warning\r\n // already fired above. Clear the flag for the normal case.\r\n propsNotifyingRef.current = false;\r\n }\r\n });\r\n\r\n // [vm] dep ensures effects re-run when instance changes (HMR).\r\n // On normal renders vm is stable, so effects run once — same as [].\r\n useLayoutEffect(() => {\r\n vm._layoutMountBehaviors();\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const result = vm.onLayoutMount?.();\r\n if (process.env.NODE_ENV !== 'production' && result instanceof Promise) {\r\n console.error(\r\n `[mobx-mantle] ${ViewClass.name}.onLayoutMount() returned a Promise. ` +\r\n `Lifecycle methods must be synchronous. Use a sync onLayoutMount that ` +\r\n `calls an async method instead.`\r\n );\r\n }\r\n cleanup = result as (() => void) | undefined;\r\n } catch (e) {\r\n reportError(e, { phase: 'onLayoutMount', name: ViewClass.name, isBehavior: false });\r\n }\r\n return () => {\r\n cleanup?.();\r\n };\r\n }, [vm]);\r\n\r\n useEffect(() => {\r\n vm._mountBehaviors();\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const result = vm.onMount?.();\r\n if (process.env.NODE_ENV !== 'production' && result instanceof Promise) {\r\n console.error(\r\n `[mobx-mantle] ${ViewClass.name}.onMount() returned a Promise. ` +\r\n `Lifecycle methods must be synchronous. Use a sync onMount that ` +\r\n `calls an async method instead.`\r\n );\r\n }\r\n cleanup = result as (() => void) | undefined;\r\n } catch (e) {\r\n reportError(e, { phase: 'onMount', name: ViewClass.name, isBehavior: false });\r\n }\r\n return () => {\r\n cleanup?.();\r\n try {\r\n vm.onUnmount?.();\r\n } catch (e) {\r\n reportError(e, { phase: 'onUnmount', name: ViewClass.name, isBehavior: false });\r\n }\r\n vm._disposeWatchers();\r\n vm._unmountBehaviors();\r\n };\r\n }, [vm]);\r\n\r\n // Called after every render (via useEffect)\r\n useEffect(() => {\r\n try {\r\n vm.onUpdate?.();\r\n } catch (e) {\r\n reportError(e, { phase: 'onUpdate', name: ViewClass.name, isBehavior: false });\r\n }\r\n });\r\n\r\n if (!template && !vm.render) {\r\n throw new Error(\r\n `[mobx-mantle] ${ViewClass.name}: Missing render() method. Either define render() in your View class or pass a template function to createView().`\r\n );\r\n }\r\n\r\n // Only the render call is tracked by MobX (useObserver).\r\n return useObserver(() => {\r\n return template ? template(vm) : vm.render!();\r\n });\r\n });\r\n\r\n // Wrap in React.memo to match observer()'s behavior — skip re-renders\r\n // when parent re-renders but props haven't changed (shallow comparison).\r\n return memo(Component) as typeof Component;\r\n}\r\n\r\n","import { makeObservable, observable, computed, action, reaction, type AnnotationsMap } from 'mobx';\nimport { globalConfig, reportError, type WatchOptions } from './config';\n\n/** Symbol marker to identify behavior instances */\nexport const BEHAVIOR_MARKER = Symbol('behavior');\n\n// Behavior base class members that should not be made observable\nconst BEHAVIOR_EXCLUDES = new Set([\n 'onCreate',\n 'onLayoutMount',\n 'onMount',\n 'onUnmount',\n 'watch',\n 'constructor',\n '_watchDisposers',\n '_disposeWatchers',\n]);\n\n/**\n * Detects if a value looks like a React ref ({ current: ... })\n * These should use observable.ref to preserve object identity\n */\nfunction isRefLike(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false;\n if (Array.isArray(value)) return false;\n return 'current' in value && Object.keys(value).length === 1;\n}\n\n/**\n * Base class for behaviors. Provides lifecycle method signatures for IDE autocomplete.\n * Extend this class and wrap with createBehavior() to create a factory.\n * \n * @example\n * ```tsx\n * class WindowSizeBehavior extends Behavior {\n * width = window.innerWidth;\n * onCreate(breakpoint = 768) { ... }\n * onMount() { ... }\n * }\n * export const withWindowSize = createBehavior(WindowSizeBehavior);\n * ```\n */\nexport class Behavior {\n /** @internal */\n _watchDisposers: (() => void)[] = [];\n\n onCreate?(...args: any[]): void;\n onLayoutMount?(): void | (() => void);\n onMount?(): void | (() => void);\n onUnmount?(): void;\n\n /**\n * Watch a reactive expression and run a callback when it changes.\n * Automatically disposed on unmount.\n * \n * @param expr - Reactive expression (getter) to watch\n * @param callback - Called when the expression result changes\n * @param options - Optional configuration (delay, fireImmediately)\n * @returns Dispose function for early teardown\n * \n * @example\n * ```tsx\n * onCreate(url: string) {\n * this.url = url;\n * this.watch(() => this.url, () => this.fetchData());\n * }\n * ```\n */\n watch<T>(\n expr: () => T,\n callback: (value: T, prevValue: T | undefined) => void,\n options?: WatchOptions\n ): () => void {\n const dispose = reaction(\n expr,\n (value, prevValue) => {\n try {\n callback(value, prevValue);\n } catch (e) {\n reportError(e, { phase: 'watch', name: this.constructor.name, isBehavior: true });\n }\n },\n {\n delay: options?.delay,\n fireImmediately: options?.fireImmediately,\n }\n );\n\n this._watchDisposers.push(dispose);\n\n // Return a dispose function that also removes from the array\n return () => {\n dispose();\n const idx = this._watchDisposers.indexOf(dispose);\n if (idx !== -1) this._watchDisposers.splice(idx, 1);\n };\n }\n\n /** @internal */\n _disposeWatchers(): void {\n for (const dispose of this._watchDisposers) {\n dispose();\n }\n this._watchDisposers.length = 0;\n }\n}\n\n/**\n * Makes a behavior instance observable, handling inheritance properly.\n * Works with classes that extend Behavior or plain classes.\n */\nfunction makeBehaviorObservable<T extends object>(instance: T): void {\n const annotations: AnnotationsMap<T, never> = {} as AnnotationsMap<T, never>;\n\n // Collect own properties → observable\n const ownKeys = new Set([\n ...Object.keys(instance),\n ...Object.keys(Object.getPrototypeOf(instance)),\n ]);\n\n for (const key of ownKeys) {\n if (BEHAVIOR_EXCLUDES.has(key)) continue;\n if (key in annotations) continue;\n\n const value = (instance as any)[key];\n if (typeof value === 'function') continue;\n\n // Use observable.ref for ref-like objects to preserve identity\n if (isRefLike(value)) {\n (annotations as any)[key] = observable.ref;\n } else {\n (annotations as any)[key] = observable;\n }\n }\n\n // Walk prototype chain up to (but not including) Behavior or Object\n let proto = Object.getPrototypeOf(instance);\n while (proto && proto !== Behavior.prototype && proto !== Object.prototype) {\n const descriptors = Object.getOwnPropertyDescriptors(proto);\n\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (BEHAVIOR_EXCLUDES.has(key)) continue;\n if (key in annotations) continue;\n\n if (descriptor.get) {\n (annotations as any)[key] = computed;\n } else if (typeof descriptor.value === 'function') {\n (annotations as any)[key] = action.bound;\n }\n }\n\n proto = Object.getPrototypeOf(proto);\n }\n\n makeObservable(instance, annotations);\n}\n\n/** @internal */\nexport interface BehaviorEntry {\n instance: any;\n cleanup?: () => void;\n layoutCleanup?: () => void;\n}\n\n/**\n * Extracts parameter types from onCreate method\n */\ntype OnCreateParams<T> = T extends { onCreate(...args: infer A): any } ? A : [];\n\n/**\n * Extracts constructor parameter types\n */\ntype ConstructorParams<T> = T extends new (...args: infer A) => any ? A : [];\n\n/**\n * Determines the args for createBehavior:\n * - If constructor has args, use those\n * - Otherwise, if onCreate has args, use those\n */\ntype BehaviorArgs<T extends new (...args: any[]) => any> = \n ConstructorParams<T> extends [] \n ? OnCreateParams<InstanceType<T>> \n : ConstructorParams<T>;\n\n/**\n * Creates a behavior factory with automatic observable wrapping and lifecycle management.\n * \n * Returns a factory function (not a class) — use without `new`:\n * \n * @example Defining a behavior\n * ```tsx\n * class DragTrait extends Behavior {\n * ref!: RefObject<HTMLElement>;\n * \n * onCreate(ref: RefObject<HTMLElement>) {\n * this.ref = ref;\n * }\n * \n * onMount() {\n * this.ref.current?.addEventListener('pointerdown', this.onPointerDown);\n * return () => this.ref.current?.removeEventListener('pointerdown', this.onPointerDown);\n * }\n * }\n * \n * export const withDrag = createBehavior(DragTrait);\n * ```\n * \n * @example Using in a View\n * ```tsx\n * class Editor extends View<Props> {\n * canvas = this.ref<HTMLCanvasElement>();\n * \n * // No `new` keyword — factory function\n * drag = withDrag(this.canvas);\n * autosave = withAutosave('/api/save', 5000);\n * }\n * export default createView(Editor);\n * ```\n * \n * The `with` prefix convention signals that the view manages this behavior's lifecycle.\n */\n/**\n * Type that supports both `new` and direct call syntax\n */\ntype BehaviorFactory<Args extends any[], Instance> = {\n new (...args: Args): Instance;\n (...args: Args): Instance;\n};\n\nexport function createBehavior<T extends new (...args: any[]) => any>(\n Def: T,\n options?: { autoObservable?: boolean }\n): BehaviorFactory<BehaviorArgs<T>, InstanceType<T>> {\n // Internal class that wraps the user's behavior definition\n const BehaviorClass = class extends (Def as any) {\n static [BEHAVIOR_MARKER] = true;\n\n constructor(...args: any[]) {\n super(...args);\n \n // Call onCreate with args (if it exists)\n if (typeof this.onCreate === 'function') {\n this.onCreate(...args);\n }\n \n // Make the instance observable (respects global config and per-behavior options)\n const autoObservable = options?.autoObservable ?? globalConfig.autoObservable;\n if (autoObservable) {\n makeBehaviorObservable(this);\n } else {\n // For decorator users: applies decorator metadata\n makeObservable(this);\n }\n }\n };\n\n // Preserve the original class name for debugging\n Object.defineProperty(BehaviorClass, 'name', { value: Def.name });\n\n // Use Proxy to make the class callable without `new`\n // This allows both: withWindowSize(768) and new withWindowSize(768)\n return new Proxy(BehaviorClass, {\n apply(_target, _thisArg, args) {\n return new BehaviorClass(...args);\n },\n }) as unknown as BehaviorFactory<BehaviorArgs<T>, InstanceType<T>>;\n}\n\n\n/**\n * Checks if a value is a behavior instance created by createBehavior()\n */\nexport function isBehavior(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false;\n return (value.constructor as any)?.[BEHAVIOR_MARKER] === true;\n}\n\n/** @internal */\nexport function layoutMountBehavior(behavior: BehaviorEntry): void {\n const inst = behavior.instance;\n\n if ('onLayoutMount' in inst && typeof inst.onLayoutMount === 'function') {\n try {\n behavior.layoutCleanup = inst.onLayoutMount() ?? undefined;\n } catch (e) {\n reportError(e, { phase: 'onLayoutMount', name: inst.constructor.name, isBehavior: true });\n }\n }\n}\n\n/** @internal */\nexport function mountBehavior(behavior: BehaviorEntry): void {\n const inst = behavior.instance;\n\n if ('onMount' in inst && typeof inst.onMount === 'function') {\n try {\n behavior.cleanup = inst.onMount() ?? undefined;\n } catch (e) {\n reportError(e, { phase: 'onMount', name: inst.constructor.name, isBehavior: true });\n }\n }\n}\n\n/** @internal */\nexport function unmountBehavior(behavior: BehaviorEntry): void {\n // Call layout cleanup if exists\n behavior.layoutCleanup?.();\n\n // Call cleanup if exists\n behavior.cleanup?.();\n\n // Call onUnmount if exists\n const inst = behavior.instance;\n if ('onUnmount' in inst && typeof inst.onUnmount === 'function') {\n try {\n inst.onUnmount();\n } catch (e) {\n reportError(e, { phase: 'onUnmount', name: inst.constructor.name, isBehavior: true });\n }\n }\n\n // Dispose all watchers\n if (typeof inst._disposeWatchers === 'function') {\n inst._disposeWatchers();\n }\n}\n","/** Options for the watch method */\r\nexport interface WatchOptions {\r\n /** Debounce the callback by N milliseconds */\r\n delay?: number;\r\n /** Run callback immediately with current value */\r\n fireImmediately?: boolean;\r\n}\r\n\r\n/**\r\n * Error context passed to the onError handler\r\n */\r\nexport interface MantleErrorContext {\r\n /** The lifecycle phase where the error occurred */\r\n phase: 'onLayoutMount' | 'onMount' | 'onUpdate' | 'onUnmount' | 'watch';\r\n /** The View or Behavior class name */\r\n name: string;\r\n /** Whether the error came from a Behavior (true) or a View (false) */\r\n isBehavior: boolean;\r\n}\r\n\r\n/**\r\n * Global configuration options for mobx-mantle\r\n */\r\nexport interface MantleConfig {\r\n /** Whether to automatically make View/Behavior instances observable (default: true) */\r\n autoObservable?: boolean;\r\n /** Global error handler for lifecycle errors. Defaults to console.error. */\r\n onError?: (error: unknown, context: MantleErrorContext) => void;\r\n}\r\n\r\nexport const globalConfig: MantleConfig = {\r\n autoObservable: true,\r\n};\r\n\r\n/** @internal Report a lifecycle error through the configured handler or console.error */\r\nexport function reportError(error: unknown, context: MantleErrorContext): void {\r\n if (globalConfig.onError) {\r\n globalConfig.onError(error, context);\r\n } else {\r\n console.error(\r\n `[mobx-mantle] Error in ${context.isBehavior ? 'behavior' : 'view'} ${context.name}.${context.phase}():`,\r\n error,\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Configure global defaults for mobx-mantle.\r\n * Settings can still be overridden per-view in createView options.\r\n */\r\nexport function configure(config: MantleConfig): void {\r\n Object.assign(globalConfig, config);\r\n}\r\n","import * as mobx from 'mobx';\r\n\r\n/**\r\n * Symbol key for storing decorator annotations in class metadata.\r\n * These annotations are read by createView() after construction.\r\n */\r\nexport const ANNOTATIONS = Symbol('mantle:annotations');\r\n\r\n/**\r\n * Decorator context type for TC39 decorators\r\n */\r\ninterface DecoratorContext {\r\n kind: 'field' | 'method' | 'getter' | 'setter' | 'accessor' | 'class';\r\n name: string | symbol;\r\n metadata: Record<symbol, unknown>;\r\n}\r\n\r\n/**\r\n * Helper to set annotation metadata\r\n */\r\nfunction setAnnotation(context: DecoratorContext, annotation: any): void {\r\n context.metadata[ANNOTATIONS] ??= {};\r\n (context.metadata[ANNOTATIONS] as Record<string | symbol, any>)[context.name] = annotation;\r\n}\r\n\r\n/**\r\n * Marks a field as observable. No `accessor` keyword needed.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function observable(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable);\r\n}\r\n\r\n/**\r\n * Observable variants for different observation modes\r\n */\r\nobservable.ref = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.ref);\r\n};\r\n\r\nobservable.shallow = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.shallow);\r\n};\r\n\r\nobservable.struct = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.struct);\r\n};\r\n\r\nobservable.deep = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.deep);\r\n};\r\n\r\n/**\r\n * Marks a method as an action. Auto-bound by default.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * \r\n * @action increment() {\r\n * this.count++;\r\n * }\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function action(_value: Function, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.action.bound);\r\n}\r\n\r\n/**\r\n * Marks a getter as computed.\r\n * Note: Getters are automatically computed in autoObservable mode,\r\n * but this decorator is useful for explicit annotation.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * \r\n * @computed get doubled() {\r\n * return this.count * 2;\r\n * }\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function computed(_value: Function, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.computed);\r\n}\r\n\r\n/**\r\n * Retrieves the annotations stored in class metadata.\r\n * Used by createView() to apply MobX observability.\r\n */\r\nexport function getAnnotations(instance: object): Record<string, any> | undefined {\r\n const metadata = (instance.constructor as any)[Symbol.metadata];\r\n return metadata?.[ANNOTATIONS] as Record<string, any> | undefined;\r\n}\r\n"],"mappings":"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","names":["action","computed","observable","import_mobx","observable","action","computed","reactForwardRef"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -14,7 +14,7 @@ interface WatchOptions {
|
|
|
14
14
|
*/
|
|
15
15
|
interface MantleErrorContext {
|
|
16
16
|
/** The lifecycle phase where the error occurred */
|
|
17
|
-
phase: 'onLayoutMount' | 'onMount' | '
|
|
17
|
+
phase: 'onLayoutMount' | 'onMount' | 'onUpdate' | 'onUnmount' | 'watch';
|
|
18
18
|
/** The View or Behavior class name */
|
|
19
19
|
name: string;
|
|
20
20
|
/** Whether the error came from a Behavior (true) or a View (false) */
|
|
@@ -222,7 +222,7 @@ declare class View<P = {}> {
|
|
|
222
222
|
onCreate?(props: P): void;
|
|
223
223
|
onLayoutMount?(): void | (() => void);
|
|
224
224
|
onMount?(): void | (() => void);
|
|
225
|
-
|
|
225
|
+
onUpdate?(): void;
|
|
226
226
|
onUnmount?(): void;
|
|
227
227
|
ref<T extends HTMLElement = HTMLElement>(): {
|
|
228
228
|
current: T | null;
|
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ interface WatchOptions {
|
|
|
14
14
|
*/
|
|
15
15
|
interface MantleErrorContext {
|
|
16
16
|
/** The lifecycle phase where the error occurred */
|
|
17
|
-
phase: 'onLayoutMount' | 'onMount' | '
|
|
17
|
+
phase: 'onLayoutMount' | 'onMount' | 'onUpdate' | 'onUnmount' | 'watch';
|
|
18
18
|
/** The View or Behavior class name */
|
|
19
19
|
name: string;
|
|
20
20
|
/** Whether the error came from a Behavior (true) or a View (false) */
|
|
@@ -222,7 +222,7 @@ declare class View<P = {}> {
|
|
|
222
222
|
onCreate?(props: P): void;
|
|
223
223
|
onLayoutMount?(): void | (() => void);
|
|
224
224
|
onMount?(): void | (() => void);
|
|
225
|
-
|
|
225
|
+
onUpdate?(): void;
|
|
226
226
|
onUnmount?(): void;
|
|
227
227
|
ref<T extends HTMLElement = HTMLElement>(): {
|
|
228
228
|
current: T | null;
|
package/dist/index.js
CHANGED
|
@@ -344,7 +344,7 @@ var BASE_EXCLUDES = /* @__PURE__ */ new Set([
|
|
|
344
344
|
"onCreate",
|
|
345
345
|
"onLayoutMount",
|
|
346
346
|
"onMount",
|
|
347
|
-
"
|
|
347
|
+
"onUpdate",
|
|
348
348
|
"onUnmount",
|
|
349
349
|
"render",
|
|
350
350
|
"ref",
|
|
@@ -512,9 +512,9 @@ function createView(ViewClass, templateOrOptions) {
|
|
|
512
512
|
}, [vm]);
|
|
513
513
|
useEffect(() => {
|
|
514
514
|
try {
|
|
515
|
-
vm.
|
|
515
|
+
vm.onUpdate?.();
|
|
516
516
|
} catch (e) {
|
|
517
|
-
reportError(e, { phase: "
|
|
517
|
+
reportError(e, { phase: "onUpdate", name: ViewClass.name, isBehavior: false });
|
|
518
518
|
}
|
|
519
519
|
});
|
|
520
520
|
if (!template && !vm.render) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mantle.tsx","../src/behavior.ts","../src/config.ts","../src/decorators.ts"],"sourcesContent":["import { useRef, useEffect, useLayoutEffect, forwardRef as reactForwardRef, memo, type Ref, type JSX } from 'react';\r\nimport { makeObservable, observable, computed, action, runInAction, reaction, AnnotationsMap, type IObservableValue } from 'mobx';\r\nimport { useObserver } from 'mobx-react-lite';\r\nimport {\r\n type BehaviorEntry,\r\n isBehavior,\r\n layoutMountBehavior,\r\n mountBehavior,\r\n unmountBehavior,\r\n} from './behavior';\r\nimport { globalConfig, reportError, type WatchOptions } from './config';\r\nimport { getAnnotations } from './decorators';\r\n\r\n// Re-export config utilities\r\nexport { configure, type MantleConfig, type MantleErrorContext, type WatchOptions } from './config';\r\n\r\n// Re-export decorators for single-import convenience\r\nexport { observable, action, computed } from './decorators';\r\n\r\n/** Tracks refs created by View.ref() — no footprint on the object itself */\r\nconst viewRefs = new WeakSet();\r\n\r\n/** Shallow-compare two objects by own enumerable keys */\r\nfunction shallowEqual(a: any, b: any): boolean {\r\n if (a === b) return true;\r\n if (!a || !b) return false;\r\n const keysA = Object.keys(a);\r\n const keysB = Object.keys(b);\r\n if (keysA.length !== keysB.length) return false;\r\n for (const key of keysA) {\r\n if (a[key] !== b[key]) return false;\r\n }\r\n return true;\r\n}\r\n\r\nexport class View<P = {}> {\r\n /** @internal */\r\n _propsBox!: IObservableValue<P>;\r\n\r\n get props(): P {\r\n return this._propsBox.get();\r\n }\r\n\r\n /** @internal — called by createView to silently update props during render */\r\n _syncProps(value: P) {\r\n // Directly set the internal value without triggering MobX notifications.\r\n // React renders the component tree synchronously — if we used runInAction\r\n // here, endBatch() would flush reactions and try to update other observer\r\n // components while React is still rendering, causing:\r\n // \"Cannot update component A while rendering component B\"\r\n //\r\n // The value is updated so this._propsBox.get() returns the correct value\r\n // during render. Reactions are notified separately in useLayoutEffect.\r\n (this._propsBox as any).value_ = value;\r\n }\r\n\r\n forwardRef?: Ref<any>;\r\n\r\n /** @internal */\r\n _behaviors: BehaviorEntry[] = [];\r\n\r\n /** @internal */\r\n _watchDisposers: (() => void)[] = [];\r\n\r\n onCreate?(props: P): void;\r\n onLayoutMount?(): void | (() => void);\r\n onMount?(): void | (() => void);\r\n onUpdated?(): void;\r\n onUnmount?(): void;\r\n\r\n ref<T extends HTMLElement = HTMLElement>(): { current: T | null } {\r\n const r = { current: null } as { current: T | null };\r\n viewRefs.add(r);\r\n return r;\r\n }\r\n\r\n /**\r\n * Watch a reactive expression and run a callback when it changes.\r\n * Automatically disposed on unmount.\r\n * \r\n * @param expr - Reactive expression (getter) to watch\r\n * @param callback - Called when the expression result changes\r\n * @param options - Optional configuration (delay, fireImmediately)\r\n * @returns Dispose function for early teardown\r\n * \r\n * @example\r\n * ```tsx\r\n * onCreate() {\r\n * this.watch(\r\n * () => this.query,\r\n * async (query) => {\r\n * if (query.length > 2) {\r\n * this.results = await searchApi(query);\r\n * }\r\n * },\r\n * { delay: 300 }\r\n * );\r\n * }\r\n * ```\r\n */\r\n watch<T>(\r\n expr: () => T,\r\n callback: (value: T, prevValue: T | undefined) => void,\r\n options?: WatchOptions\r\n ): () => void {\r\n const dispose = reaction(\r\n expr,\r\n (value, prevValue) => {\r\n try {\r\n callback(value, prevValue);\r\n } catch (e) {\r\n reportError(e, { phase: 'watch', name: this.constructor.name, isBehavior: false });\r\n }\r\n },\r\n {\r\n delay: options?.delay,\r\n fireImmediately: options?.fireImmediately,\r\n }\r\n );\r\n\r\n this._watchDisposers.push(dispose);\r\n\r\n // Return a dispose function that also removes from the array\r\n return () => {\r\n dispose();\r\n const idx = this._watchDisposers.indexOf(dispose);\r\n if (idx !== -1) this._watchDisposers.splice(idx, 1);\r\n };\r\n }\r\n\r\n /** @internal */\r\n _disposeWatchers(): void {\r\n for (const dispose of this._watchDisposers) {\r\n dispose();\r\n }\r\n this._watchDisposers.length = 0;\r\n }\r\n\r\n /** @internal - Scan own properties for behavior instances and register them */\r\n _collectBehaviors(): void {\r\n for (const key of Object.keys(this)) {\r\n if (key.startsWith('_')) continue;\r\n const value = (this as any)[key];\r\n if (isBehavior(value)) {\r\n this._behaviors.push({ instance: value });\r\n }\r\n }\r\n }\r\n\r\n /** @internal */\r\n _layoutMountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n layoutMountBehavior(behavior);\r\n }\r\n }\r\n\r\n /** @internal */\r\n _mountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n mountBehavior(behavior);\r\n }\r\n }\r\n\r\n /** @internal */\r\n _unmountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n unmountBehavior(behavior);\r\n }\r\n }\r\n\r\n render?(): JSX.Element | null;\r\n}\r\n\r\n/** Alias for View - use when separating ViewModel from template */\r\nexport { View as ViewModel };\r\n\r\n// Re-export from behavior module\r\nexport { createBehavior, Behavior } from './behavior';\r\n\r\n// Base class members that should not be made observable\r\nconst BASE_EXCLUDES = new Set([\r\n 'props',\r\n '_propsBox',\r\n 'forwardRef', \r\n 'onCreate',\r\n 'onLayoutMount',\r\n 'onMount', \r\n 'onUpdated',\r\n 'onUnmount',\r\n 'render', \r\n 'ref',\r\n 'watch',\r\n 'constructor',\r\n '_behaviors',\r\n '_collectBehaviors',\r\n '_layoutMountBehaviors',\r\n '_mountBehaviors',\r\n '_unmountBehaviors',\r\n '_syncProps',\r\n '_watchDisposers',\r\n '_disposeWatchers',\r\n]);\r\n\r\n/**\r\n * Detects if a value is a ref created by View.ref()\r\n * These should use observable.ref to preserve object identity for React\r\n */\r\nfunction isViewRef(value: unknown): boolean {\r\n return value !== null && typeof value === 'object' && viewRefs.has(value as object);\r\n}\r\n\r\n/**\r\n * Creates observable annotations for a View subclass instance.\r\n * This is needed because makeAutoObservable doesn't work with inheritance.\r\n */\r\nfunction makeViewObservable<T extends View>(instance: T, autoBind: boolean) {\r\n const annotations: AnnotationsMap<T, never> = {} as AnnotationsMap<T, never>;\r\n\r\n // Collect own properties (instance state) → observable\r\n // Also check prototype for class field declarations (handles uninitialized fields)\r\n const ownKeys = new Set([\r\n ...Object.keys(instance),\r\n ...Object.keys(Object.getPrototypeOf(instance)),\r\n ]);\r\n\r\n for (const key of ownKeys) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n\r\n const value = (instance as any)[key];\r\n\r\n // Skip functions (these are handled in the prototype walk)\r\n if (typeof value === 'function') continue;\r\n\r\n // Skip behavior instances (they're already observable)\r\n if (isBehavior(value)) {\r\n (annotations as any)[key] = observable.ref;\r\n continue;\r\n }\r\n\r\n // Use observable.ref for View.ref() objects to preserve identity\r\n if (isViewRef(value)) {\r\n (annotations as any)[key] = observable.ref;\r\n } else {\r\n (annotations as any)[key] = observable;\r\n }\r\n }\r\n\r\n // Walk prototype chain up to (but not including) View\r\n let proto = Object.getPrototypeOf(instance);\r\n while (proto && proto !== View.prototype) {\r\n const descriptors = Object.getOwnPropertyDescriptors(proto);\r\n\r\n for (const [key, descriptor] of Object.entries(descriptors)) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n\r\n if (descriptor.get) {\r\n // Getter → computed\r\n (annotations as any)[key] = computed;\r\n } else if (typeof descriptor.value === 'function') {\r\n // Method → action (optionally bound)\r\n (annotations as any)[key] = autoBind ? action.bound : action;\r\n }\r\n }\r\n\r\n proto = Object.getPrototypeOf(proto);\r\n }\r\n\r\n makeObservable(instance, annotations);\r\n}\r\n\r\ntype PropsOf<V> = V extends View<infer P> ? P : object;\r\n\r\nexport function createView<V extends View<any>>(\r\n ViewClass: new () => V,\r\n templateOrOptions?: ((vm: V) => JSX.Element) | { autoObservable?: boolean }\r\n) {\r\n type P = PropsOf<V>;\r\n\r\n const template = typeof templateOrOptions === 'function' ? templateOrOptions : undefined;\r\n const options = typeof templateOrOptions === 'object' ? templateOrOptions : {};\r\n const { autoObservable = globalConfig.autoObservable } = options;\r\n\r\n const Component = reactForwardRef<unknown, P>((props, ref) => {\r\n const vmRef = useRef<V | null>(null);\r\n const classRef = useRef(ViewClass);\r\n const prevPropsRef = useRef<P | null>(null);\r\n const propsNotifyingRef = useRef(false);\r\n\r\n // HMR: class identity changes when the module re-executes, but useRef\r\n // values survive (React Fast Refresh preserves hooks). On detection,\r\n // we simply discard the old instance and create fresh — clean slate.\r\n // In production this check is always false (class identity is stable).\r\n if (vmRef.current && classRef.current !== ViewClass) {\r\n classRef.current = ViewClass;\r\n vmRef.current = null;\r\n }\r\n\r\n if (!vmRef.current) {\r\n const instance = new ViewClass();\r\n\r\n // Props is always reactive via observable.box (works with all decorator modes)\r\n instance._propsBox = observable.box(props, { deep: false });\r\n instance.forwardRef = ref;\r\n\r\n // Collect behavior instances from properties (must happen before makeObservable)\r\n instance._collectBehaviors();\r\n\r\n // Check for Mantle decorator annotations first\r\n const decoratorAnnotations = getAnnotations(instance);\r\n \r\n if (decoratorAnnotations) {\r\n // Mantle decorators: use collected annotations\r\n // Auto-bind all methods for stable `this` references\r\n const annotations = { ...decoratorAnnotations };\r\n \r\n // Walk prototype chain to auto-bind methods not explicitly decorated\r\n let proto = Object.getPrototypeOf(instance);\r\n while (proto && proto !== View.prototype) {\r\n const descriptors = Object.getOwnPropertyDescriptors(proto);\r\n for (const [key, descriptor] of Object.entries(descriptors)) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n if (typeof descriptor.value === 'function') {\r\n annotations[key] = action.bound;\r\n }\r\n }\r\n proto = Object.getPrototypeOf(proto);\r\n }\r\n \r\n makeObservable(instance, annotations as AnnotationsMap<V, never>);\r\n } else if (autoObservable) {\r\n makeViewObservable(instance, true);\r\n } else {\r\n // For legacy decorator users: applies decorator metadata\r\n makeObservable(instance);\r\n }\r\n\r\n // Proxy forwards property access to instance.props, so reads are tracked\r\n // by MobX when used in reactions/computeds (same behavior as this.props)\r\n const reactiveProps = new Proxy({} as P, {\r\n get: (_, key) => (instance.props as any)[key],\r\n has: (_, key) => key in (instance.props as any),\r\n ownKeys: () => Reflect.ownKeys(instance.props as object),\r\n getOwnPropertyDescriptor: (_, key) =>\r\n Reflect.getOwnPropertyDescriptor(instance.props as object, key),\r\n });\r\n instance.onCreate?.(reactiveProps);\r\n vmRef.current = instance;\r\n prevPropsRef.current = props as P;\r\n }\r\n\r\n const vm = vmRef.current;\r\n\r\n // Dev warning: detect when a prop-triggered reaction causes a re-render.\r\n // This means a reaction is being used for derived state — a computed getter\r\n // would avoid the double render.\r\n if (process.env.NODE_ENV !== 'production' && propsNotifyingRef.current) {\r\n console.warn(\r\n `[mobx-mantle] ${ViewClass.name}: A reaction to a prop change modified ` +\r\n `observable state, which caused an extra re-render. Consider using a ` +\r\n `computed getter instead.`\r\n );\r\n propsNotifyingRef.current = false;\r\n }\r\n\r\n // Silently update _propsBox.value_ so this.props returns the correct value\r\n // during render, without triggering MobX reactions (which would cause\r\n // \"Cannot update component A while rendering component B\").\r\n vm._syncProps(props as P);\r\n vm.forwardRef = ref;\r\n\r\n // After render completes, properly notify MobX observers of prop changes.\r\n // This enables reaction(() => this.props.x, ...) in lifecycle methods.\r\n // useLayoutEffect runs after React finishes the render pass, so it's safe\r\n // to flush reactions here.\r\n useLayoutEffect(() => {\r\n if (!shallowEqual(prevPropsRef.current, props)) {\r\n prevPropsRef.current = props as P;\r\n propsNotifyingRef.current = true;\r\n runInAction(() => {\r\n vm._propsBox.set(props);\r\n });\r\n // If a reaction triggered a synchronous re-render, the warning\r\n // already fired above. Clear the flag for the normal case.\r\n propsNotifyingRef.current = false;\r\n }\r\n });\r\n\r\n // [vm] dep ensures effects re-run when instance changes (HMR).\r\n // On normal renders vm is stable, so effects run once — same as [].\r\n useLayoutEffect(() => {\r\n vm._layoutMountBehaviors();\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const result = vm.onLayoutMount?.();\r\n if (process.env.NODE_ENV !== 'production' && result instanceof Promise) {\r\n console.error(\r\n `[mobx-mantle] ${ViewClass.name}.onLayoutMount() returned a Promise. ` +\r\n `Lifecycle methods must be synchronous. Use a sync onLayoutMount that ` +\r\n `calls an async method instead.`\r\n );\r\n }\r\n cleanup = result as (() => void) | undefined;\r\n } catch (e) {\r\n reportError(e, { phase: 'onLayoutMount', name: ViewClass.name, isBehavior: false });\r\n }\r\n return () => {\r\n cleanup?.();\r\n };\r\n }, [vm]);\r\n\r\n useEffect(() => {\r\n vm._mountBehaviors();\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const result = vm.onMount?.();\r\n if (process.env.NODE_ENV !== 'production' && result instanceof Promise) {\r\n console.error(\r\n `[mobx-mantle] ${ViewClass.name}.onMount() returned a Promise. ` +\r\n `Lifecycle methods must be synchronous. Use a sync onMount that ` +\r\n `calls an async method instead.`\r\n );\r\n }\r\n cleanup = result as (() => void) | undefined;\r\n } catch (e) {\r\n reportError(e, { phase: 'onMount', name: ViewClass.name, isBehavior: false });\r\n }\r\n return () => {\r\n cleanup?.();\r\n try {\r\n vm.onUnmount?.();\r\n } catch (e) {\r\n reportError(e, { phase: 'onUnmount', name: ViewClass.name, isBehavior: false });\r\n }\r\n vm._disposeWatchers();\r\n vm._unmountBehaviors();\r\n };\r\n }, [vm]);\r\n\r\n // Called after every render (via useEffect)\r\n useEffect(() => {\r\n try {\r\n vm.onUpdated?.();\r\n } catch (e) {\r\n reportError(e, { phase: 'onUpdated', name: ViewClass.name, isBehavior: false });\r\n }\r\n });\r\n\r\n if (!template && !vm.render) {\r\n throw new Error(\r\n `[mobx-mantle] ${ViewClass.name}: Missing render() method. Either define render() in your View class or pass a template function to createView().`\r\n );\r\n }\r\n\r\n // Only the render call is tracked by MobX (useObserver).\r\n return useObserver(() => {\r\n return template ? template(vm) : vm.render!();\r\n });\r\n });\r\n\r\n // Wrap in React.memo to match observer()'s behavior — skip re-renders\r\n // when parent re-renders but props haven't changed (shallow comparison).\r\n return memo(Component) as typeof Component;\r\n}\r\n\r\n","import { makeObservable, observable, computed, action, reaction, type AnnotationsMap } from 'mobx';\nimport { globalConfig, reportError, type WatchOptions } from './config';\n\n/** Symbol marker to identify behavior instances */\nexport const BEHAVIOR_MARKER = Symbol('behavior');\n\n// Behavior base class members that should not be made observable\nconst BEHAVIOR_EXCLUDES = new Set([\n 'onCreate',\n 'onLayoutMount',\n 'onMount',\n 'onUnmount',\n 'watch',\n 'constructor',\n '_watchDisposers',\n '_disposeWatchers',\n]);\n\n/**\n * Detects if a value looks like a React ref ({ current: ... })\n * These should use observable.ref to preserve object identity\n */\nfunction isRefLike(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false;\n if (Array.isArray(value)) return false;\n return 'current' in value && Object.keys(value).length === 1;\n}\n\n/**\n * Base class for behaviors. Provides lifecycle method signatures for IDE autocomplete.\n * Extend this class and wrap with createBehavior() to create a factory.\n * \n * @example\n * ```tsx\n * class WindowSizeBehavior extends Behavior {\n * width = window.innerWidth;\n * onCreate(breakpoint = 768) { ... }\n * onMount() { ... }\n * }\n * export const withWindowSize = createBehavior(WindowSizeBehavior);\n * ```\n */\nexport class Behavior {\n /** @internal */\n _watchDisposers: (() => void)[] = [];\n\n onCreate?(...args: any[]): void;\n onLayoutMount?(): void | (() => void);\n onMount?(): void | (() => void);\n onUnmount?(): void;\n\n /**\n * Watch a reactive expression and run a callback when it changes.\n * Automatically disposed on unmount.\n * \n * @param expr - Reactive expression (getter) to watch\n * @param callback - Called when the expression result changes\n * @param options - Optional configuration (delay, fireImmediately)\n * @returns Dispose function for early teardown\n * \n * @example\n * ```tsx\n * onCreate(url: string) {\n * this.url = url;\n * this.watch(() => this.url, () => this.fetchData());\n * }\n * ```\n */\n watch<T>(\n expr: () => T,\n callback: (value: T, prevValue: T | undefined) => void,\n options?: WatchOptions\n ): () => void {\n const dispose = reaction(\n expr,\n (value, prevValue) => {\n try {\n callback(value, prevValue);\n } catch (e) {\n reportError(e, { phase: 'watch', name: this.constructor.name, isBehavior: true });\n }\n },\n {\n delay: options?.delay,\n fireImmediately: options?.fireImmediately,\n }\n );\n\n this._watchDisposers.push(dispose);\n\n // Return a dispose function that also removes from the array\n return () => {\n dispose();\n const idx = this._watchDisposers.indexOf(dispose);\n if (idx !== -1) this._watchDisposers.splice(idx, 1);\n };\n }\n\n /** @internal */\n _disposeWatchers(): void {\n for (const dispose of this._watchDisposers) {\n dispose();\n }\n this._watchDisposers.length = 0;\n }\n}\n\n/**\n * Makes a behavior instance observable, handling inheritance properly.\n * Works with classes that extend Behavior or plain classes.\n */\nfunction makeBehaviorObservable<T extends object>(instance: T): void {\n const annotations: AnnotationsMap<T, never> = {} as AnnotationsMap<T, never>;\n\n // Collect own properties → observable\n const ownKeys = new Set([\n ...Object.keys(instance),\n ...Object.keys(Object.getPrototypeOf(instance)),\n ]);\n\n for (const key of ownKeys) {\n if (BEHAVIOR_EXCLUDES.has(key)) continue;\n if (key in annotations) continue;\n\n const value = (instance as any)[key];\n if (typeof value === 'function') continue;\n\n // Use observable.ref for ref-like objects to preserve identity\n if (isRefLike(value)) {\n (annotations as any)[key] = observable.ref;\n } else {\n (annotations as any)[key] = observable;\n }\n }\n\n // Walk prototype chain up to (but not including) Behavior or Object\n let proto = Object.getPrototypeOf(instance);\n while (proto && proto !== Behavior.prototype && proto !== Object.prototype) {\n const descriptors = Object.getOwnPropertyDescriptors(proto);\n\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (BEHAVIOR_EXCLUDES.has(key)) continue;\n if (key in annotations) continue;\n\n if (descriptor.get) {\n (annotations as any)[key] = computed;\n } else if (typeof descriptor.value === 'function') {\n (annotations as any)[key] = action.bound;\n }\n }\n\n proto = Object.getPrototypeOf(proto);\n }\n\n makeObservable(instance, annotations);\n}\n\n/** @internal */\nexport interface BehaviorEntry {\n instance: any;\n cleanup?: () => void;\n layoutCleanup?: () => void;\n}\n\n/**\n * Extracts parameter types from onCreate method\n */\ntype OnCreateParams<T> = T extends { onCreate(...args: infer A): any } ? A : [];\n\n/**\n * Extracts constructor parameter types\n */\ntype ConstructorParams<T> = T extends new (...args: infer A) => any ? A : [];\n\n/**\n * Determines the args for createBehavior:\n * - If constructor has args, use those\n * - Otherwise, if onCreate has args, use those\n */\ntype BehaviorArgs<T extends new (...args: any[]) => any> = \n ConstructorParams<T> extends [] \n ? OnCreateParams<InstanceType<T>> \n : ConstructorParams<T>;\n\n/**\n * Creates a behavior factory with automatic observable wrapping and lifecycle management.\n * \n * Returns a factory function (not a class) — use without `new`:\n * \n * @example Defining a behavior\n * ```tsx\n * class DragTrait extends Behavior {\n * ref!: RefObject<HTMLElement>;\n * \n * onCreate(ref: RefObject<HTMLElement>) {\n * this.ref = ref;\n * }\n * \n * onMount() {\n * this.ref.current?.addEventListener('pointerdown', this.onPointerDown);\n * return () => this.ref.current?.removeEventListener('pointerdown', this.onPointerDown);\n * }\n * }\n * \n * export const withDrag = createBehavior(DragTrait);\n * ```\n * \n * @example Using in a View\n * ```tsx\n * class Editor extends View<Props> {\n * canvas = this.ref<HTMLCanvasElement>();\n * \n * // No `new` keyword — factory function\n * drag = withDrag(this.canvas);\n * autosave = withAutosave('/api/save', 5000);\n * }\n * export default createView(Editor);\n * ```\n * \n * The `with` prefix convention signals that the view manages this behavior's lifecycle.\n */\n/**\n * Type that supports both `new` and direct call syntax\n */\ntype BehaviorFactory<Args extends any[], Instance> = {\n new (...args: Args): Instance;\n (...args: Args): Instance;\n};\n\nexport function createBehavior<T extends new (...args: any[]) => any>(\n Def: T,\n options?: { autoObservable?: boolean }\n): BehaviorFactory<BehaviorArgs<T>, InstanceType<T>> {\n // Internal class that wraps the user's behavior definition\n const BehaviorClass = class extends (Def as any) {\n static [BEHAVIOR_MARKER] = true;\n\n constructor(...args: any[]) {\n super(...args);\n \n // Call onCreate with args (if it exists)\n if (typeof this.onCreate === 'function') {\n this.onCreate(...args);\n }\n \n // Make the instance observable (respects global config and per-behavior options)\n const autoObservable = options?.autoObservable ?? globalConfig.autoObservable;\n if (autoObservable) {\n makeBehaviorObservable(this);\n } else {\n // For decorator users: applies decorator metadata\n makeObservable(this);\n }\n }\n };\n\n // Preserve the original class name for debugging\n Object.defineProperty(BehaviorClass, 'name', { value: Def.name });\n\n // Use Proxy to make the class callable without `new`\n // This allows both: withWindowSize(768) and new withWindowSize(768)\n return new Proxy(BehaviorClass, {\n apply(_target, _thisArg, args) {\n return new BehaviorClass(...args);\n },\n }) as unknown as BehaviorFactory<BehaviorArgs<T>, InstanceType<T>>;\n}\n\n\n/**\n * Checks if a value is a behavior instance created by createBehavior()\n */\nexport function isBehavior(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false;\n return (value.constructor as any)?.[BEHAVIOR_MARKER] === true;\n}\n\n/** @internal */\nexport function layoutMountBehavior(behavior: BehaviorEntry): void {\n const inst = behavior.instance;\n\n if ('onLayoutMount' in inst && typeof inst.onLayoutMount === 'function') {\n try {\n behavior.layoutCleanup = inst.onLayoutMount() ?? undefined;\n } catch (e) {\n reportError(e, { phase: 'onLayoutMount', name: inst.constructor.name, isBehavior: true });\n }\n }\n}\n\n/** @internal */\nexport function mountBehavior(behavior: BehaviorEntry): void {\n const inst = behavior.instance;\n\n if ('onMount' in inst && typeof inst.onMount === 'function') {\n try {\n behavior.cleanup = inst.onMount() ?? undefined;\n } catch (e) {\n reportError(e, { phase: 'onMount', name: inst.constructor.name, isBehavior: true });\n }\n }\n}\n\n/** @internal */\nexport function unmountBehavior(behavior: BehaviorEntry): void {\n // Call layout cleanup if exists\n behavior.layoutCleanup?.();\n\n // Call cleanup if exists\n behavior.cleanup?.();\n\n // Call onUnmount if exists\n const inst = behavior.instance;\n if ('onUnmount' in inst && typeof inst.onUnmount === 'function') {\n try {\n inst.onUnmount();\n } catch (e) {\n reportError(e, { phase: 'onUnmount', name: inst.constructor.name, isBehavior: true });\n }\n }\n\n // Dispose all watchers\n if (typeof inst._disposeWatchers === 'function') {\n inst._disposeWatchers();\n }\n}\n","/** Options for the watch method */\r\nexport interface WatchOptions {\r\n /** Debounce the callback by N milliseconds */\r\n delay?: number;\r\n /** Run callback immediately with current value */\r\n fireImmediately?: boolean;\r\n}\r\n\r\n/**\r\n * Error context passed to the onError handler\r\n */\r\nexport interface MantleErrorContext {\r\n /** The lifecycle phase where the error occurred */\r\n phase: 'onLayoutMount' | 'onMount' | 'onUpdated' | 'onUnmount' | 'watch';\r\n /** The View or Behavior class name */\r\n name: string;\r\n /** Whether the error came from a Behavior (true) or a View (false) */\r\n isBehavior: boolean;\r\n}\r\n\r\n/**\r\n * Global configuration options for mobx-mantle\r\n */\r\nexport interface MantleConfig {\r\n /** Whether to automatically make View/Behavior instances observable (default: true) */\r\n autoObservable?: boolean;\r\n /** Global error handler for lifecycle errors. Defaults to console.error. */\r\n onError?: (error: unknown, context: MantleErrorContext) => void;\r\n}\r\n\r\nexport const globalConfig: MantleConfig = {\r\n autoObservable: true,\r\n};\r\n\r\n/** @internal Report a lifecycle error through the configured handler or console.error */\r\nexport function reportError(error: unknown, context: MantleErrorContext): void {\r\n if (globalConfig.onError) {\r\n globalConfig.onError(error, context);\r\n } else {\r\n console.error(\r\n `[mobx-mantle] Error in ${context.isBehavior ? 'behavior' : 'view'} ${context.name}.${context.phase}():`,\r\n error,\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Configure global defaults for mobx-mantle.\r\n * Settings can still be overridden per-view in createView options.\r\n */\r\nexport function configure(config: MantleConfig): void {\r\n Object.assign(globalConfig, config);\r\n}\r\n","import * as mobx from 'mobx';\r\n\r\n/**\r\n * Symbol key for storing decorator annotations in class metadata.\r\n * These annotations are read by createView() after construction.\r\n */\r\nexport const ANNOTATIONS = Symbol('mantle:annotations');\r\n\r\n/**\r\n * Decorator context type for TC39 decorators\r\n */\r\ninterface DecoratorContext {\r\n kind: 'field' | 'method' | 'getter' | 'setter' | 'accessor' | 'class';\r\n name: string | symbol;\r\n metadata: Record<symbol, unknown>;\r\n}\r\n\r\n/**\r\n * Helper to set annotation metadata\r\n */\r\nfunction setAnnotation(context: DecoratorContext, annotation: any): void {\r\n context.metadata[ANNOTATIONS] ??= {};\r\n (context.metadata[ANNOTATIONS] as Record<string | symbol, any>)[context.name] = annotation;\r\n}\r\n\r\n/**\r\n * Marks a field as observable. No `accessor` keyword needed.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function observable(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable);\r\n}\r\n\r\n/**\r\n * Observable variants for different observation modes\r\n */\r\nobservable.ref = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.ref);\r\n};\r\n\r\nobservable.shallow = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.shallow);\r\n};\r\n\r\nobservable.struct = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.struct);\r\n};\r\n\r\nobservable.deep = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.deep);\r\n};\r\n\r\n/**\r\n * Marks a method as an action. Auto-bound by default.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * \r\n * @action increment() {\r\n * this.count++;\r\n * }\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function action(_value: Function, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.action.bound);\r\n}\r\n\r\n/**\r\n * Marks a getter as computed.\r\n * Note: Getters are automatically computed in autoObservable mode,\r\n * but this decorator is useful for explicit annotation.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * \r\n * @computed get doubled() {\r\n * return this.count * 2;\r\n * }\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function computed(_value: Function, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.computed);\r\n}\r\n\r\n/**\r\n * Retrieves the annotations stored in class metadata.\r\n * Used by createView() to apply MobX observability.\r\n */\r\nexport function getAnnotations(instance: object): Record<string, any> | undefined {\r\n const metadata = (instance.constructor as any)[Symbol.metadata];\r\n return metadata?.[ANNOTATIONS] as Record<string, any> | undefined;\r\n}\r\n"],"mappings":"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","names":["makeObservable","observable","computed","action","reaction","observable","action","computed","reaction","observable","computed","action","makeObservable"]}
|
|
1
|
+
{"version":3,"sources":["../src/mantle.tsx","../src/behavior.ts","../src/config.ts","../src/decorators.ts"],"sourcesContent":["import { useRef, useEffect, useLayoutEffect, forwardRef as reactForwardRef, memo, type Ref, type JSX } from 'react';\r\nimport { makeObservable, observable, computed, action, runInAction, reaction, AnnotationsMap, type IObservableValue } from 'mobx';\r\nimport { useObserver } from 'mobx-react-lite';\r\nimport {\r\n type BehaviorEntry,\r\n isBehavior,\r\n layoutMountBehavior,\r\n mountBehavior,\r\n unmountBehavior,\r\n} from './behavior';\r\nimport { globalConfig, reportError, type WatchOptions } from './config';\r\nimport { getAnnotations } from './decorators';\r\n\r\n// Re-export config utilities\r\nexport { configure, type MantleConfig, type MantleErrorContext, type WatchOptions } from './config';\r\n\r\n// Re-export decorators for single-import convenience\r\nexport { observable, action, computed } from './decorators';\r\n\r\n/** Tracks refs created by View.ref() — no footprint on the object itself */\r\nconst viewRefs = new WeakSet();\r\n\r\n/** Shallow-compare two objects by own enumerable keys */\r\nfunction shallowEqual(a: any, b: any): boolean {\r\n if (a === b) return true;\r\n if (!a || !b) return false;\r\n const keysA = Object.keys(a);\r\n const keysB = Object.keys(b);\r\n if (keysA.length !== keysB.length) return false;\r\n for (const key of keysA) {\r\n if (a[key] !== b[key]) return false;\r\n }\r\n return true;\r\n}\r\n\r\nexport class View<P = {}> {\r\n /** @internal */\r\n _propsBox!: IObservableValue<P>;\r\n\r\n get props(): P {\r\n return this._propsBox.get();\r\n }\r\n\r\n /** @internal — called by createView to silently update props during render */\r\n _syncProps(value: P) {\r\n // Directly set the internal value without triggering MobX notifications.\r\n // React renders the component tree synchronously — if we used runInAction\r\n // here, endBatch() would flush reactions and try to update other observer\r\n // components while React is still rendering, causing:\r\n // \"Cannot update component A while rendering component B\"\r\n //\r\n // The value is updated so this._propsBox.get() returns the correct value\r\n // during render. Reactions are notified separately in useLayoutEffect.\r\n (this._propsBox as any).value_ = value;\r\n }\r\n\r\n forwardRef?: Ref<any>;\r\n\r\n /** @internal */\r\n _behaviors: BehaviorEntry[] = [];\r\n\r\n /** @internal */\r\n _watchDisposers: (() => void)[] = [];\r\n\r\n onCreate?(props: P): void;\r\n onLayoutMount?(): void | (() => void);\r\n onMount?(): void | (() => void);\r\n onUpdate?(): void;\r\n onUnmount?(): void;\r\n\r\n ref<T extends HTMLElement = HTMLElement>(): { current: T | null } {\r\n const r = { current: null } as { current: T | null };\r\n viewRefs.add(r);\r\n return r;\r\n }\r\n\r\n /**\r\n * Watch a reactive expression and run a callback when it changes.\r\n * Automatically disposed on unmount.\r\n * \r\n * @param expr - Reactive expression (getter) to watch\r\n * @param callback - Called when the expression result changes\r\n * @param options - Optional configuration (delay, fireImmediately)\r\n * @returns Dispose function for early teardown\r\n * \r\n * @example\r\n * ```tsx\r\n * onCreate() {\r\n * this.watch(\r\n * () => this.query,\r\n * async (query) => {\r\n * if (query.length > 2) {\r\n * this.results = await searchApi(query);\r\n * }\r\n * },\r\n * { delay: 300 }\r\n * );\r\n * }\r\n * ```\r\n */\r\n watch<T>(\r\n expr: () => T,\r\n callback: (value: T, prevValue: T | undefined) => void,\r\n options?: WatchOptions\r\n ): () => void {\r\n const dispose = reaction(\r\n expr,\r\n (value, prevValue) => {\r\n try {\r\n callback(value, prevValue);\r\n } catch (e) {\r\n reportError(e, { phase: 'watch', name: this.constructor.name, isBehavior: false });\r\n }\r\n },\r\n {\r\n delay: options?.delay,\r\n fireImmediately: options?.fireImmediately,\r\n }\r\n );\r\n\r\n this._watchDisposers.push(dispose);\r\n\r\n // Return a dispose function that also removes from the array\r\n return () => {\r\n dispose();\r\n const idx = this._watchDisposers.indexOf(dispose);\r\n if (idx !== -1) this._watchDisposers.splice(idx, 1);\r\n };\r\n }\r\n\r\n /** @internal */\r\n _disposeWatchers(): void {\r\n for (const dispose of this._watchDisposers) {\r\n dispose();\r\n }\r\n this._watchDisposers.length = 0;\r\n }\r\n\r\n /** @internal - Scan own properties for behavior instances and register them */\r\n _collectBehaviors(): void {\r\n for (const key of Object.keys(this)) {\r\n if (key.startsWith('_')) continue;\r\n const value = (this as any)[key];\r\n if (isBehavior(value)) {\r\n this._behaviors.push({ instance: value });\r\n }\r\n }\r\n }\r\n\r\n /** @internal */\r\n _layoutMountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n layoutMountBehavior(behavior);\r\n }\r\n }\r\n\r\n /** @internal */\r\n _mountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n mountBehavior(behavior);\r\n }\r\n }\r\n\r\n /** @internal */\r\n _unmountBehaviors(): void {\r\n for (const behavior of this._behaviors) {\r\n unmountBehavior(behavior);\r\n }\r\n }\r\n\r\n render?(): JSX.Element | null;\r\n}\r\n\r\n/** Alias for View - use when separating ViewModel from template */\r\nexport { View as ViewModel };\r\n\r\n// Re-export from behavior module\r\nexport { createBehavior, Behavior } from './behavior';\r\n\r\n// Base class members that should not be made observable\r\nconst BASE_EXCLUDES = new Set([\r\n 'props',\r\n '_propsBox',\r\n 'forwardRef', \r\n 'onCreate',\r\n 'onLayoutMount',\r\n 'onMount', \r\n 'onUpdate',\r\n 'onUnmount',\r\n 'render', \r\n 'ref',\r\n 'watch',\r\n 'constructor',\r\n '_behaviors',\r\n '_collectBehaviors',\r\n '_layoutMountBehaviors',\r\n '_mountBehaviors',\r\n '_unmountBehaviors',\r\n '_syncProps',\r\n '_watchDisposers',\r\n '_disposeWatchers',\r\n]);\r\n\r\n/**\r\n * Detects if a value is a ref created by View.ref()\r\n * These should use observable.ref to preserve object identity for React\r\n */\r\nfunction isViewRef(value: unknown): boolean {\r\n return value !== null && typeof value === 'object' && viewRefs.has(value as object);\r\n}\r\n\r\n/**\r\n * Creates observable annotations for a View subclass instance.\r\n * This is needed because makeAutoObservable doesn't work with inheritance.\r\n */\r\nfunction makeViewObservable<T extends View>(instance: T, autoBind: boolean) {\r\n const annotations: AnnotationsMap<T, never> = {} as AnnotationsMap<T, never>;\r\n\r\n // Collect own properties (instance state) → observable\r\n // Also check prototype for class field declarations (handles uninitialized fields)\r\n const ownKeys = new Set([\r\n ...Object.keys(instance),\r\n ...Object.keys(Object.getPrototypeOf(instance)),\r\n ]);\r\n\r\n for (const key of ownKeys) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n\r\n const value = (instance as any)[key];\r\n\r\n // Skip functions (these are handled in the prototype walk)\r\n if (typeof value === 'function') continue;\r\n\r\n // Skip behavior instances (they're already observable)\r\n if (isBehavior(value)) {\r\n (annotations as any)[key] = observable.ref;\r\n continue;\r\n }\r\n\r\n // Use observable.ref for View.ref() objects to preserve identity\r\n if (isViewRef(value)) {\r\n (annotations as any)[key] = observable.ref;\r\n } else {\r\n (annotations as any)[key] = observable;\r\n }\r\n }\r\n\r\n // Walk prototype chain up to (but not including) View\r\n let proto = Object.getPrototypeOf(instance);\r\n while (proto && proto !== View.prototype) {\r\n const descriptors = Object.getOwnPropertyDescriptors(proto);\r\n\r\n for (const [key, descriptor] of Object.entries(descriptors)) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n\r\n if (descriptor.get) {\r\n // Getter → computed\r\n (annotations as any)[key] = computed;\r\n } else if (typeof descriptor.value === 'function') {\r\n // Method → action (optionally bound)\r\n (annotations as any)[key] = autoBind ? action.bound : action;\r\n }\r\n }\r\n\r\n proto = Object.getPrototypeOf(proto);\r\n }\r\n\r\n makeObservable(instance, annotations);\r\n}\r\n\r\ntype PropsOf<V> = V extends View<infer P> ? P : object;\r\n\r\nexport function createView<V extends View<any>>(\r\n ViewClass: new () => V,\r\n templateOrOptions?: ((vm: V) => JSX.Element) | { autoObservable?: boolean }\r\n) {\r\n type P = PropsOf<V>;\r\n\r\n const template = typeof templateOrOptions === 'function' ? templateOrOptions : undefined;\r\n const options = typeof templateOrOptions === 'object' ? templateOrOptions : {};\r\n const { autoObservable = globalConfig.autoObservable } = options;\r\n\r\n const Component = reactForwardRef<unknown, P>((props, ref) => {\r\n const vmRef = useRef<V | null>(null);\r\n const classRef = useRef(ViewClass);\r\n const prevPropsRef = useRef<P | null>(null);\r\n const propsNotifyingRef = useRef(false);\r\n\r\n // HMR: class identity changes when the module re-executes, but useRef\r\n // values survive (React Fast Refresh preserves hooks). On detection,\r\n // we simply discard the old instance and create fresh — clean slate.\r\n // In production this check is always false (class identity is stable).\r\n if (vmRef.current && classRef.current !== ViewClass) {\r\n classRef.current = ViewClass;\r\n vmRef.current = null;\r\n }\r\n\r\n if (!vmRef.current) {\r\n const instance = new ViewClass();\r\n\r\n // Props is always reactive via observable.box (works with all decorator modes)\r\n instance._propsBox = observable.box(props, { deep: false });\r\n instance.forwardRef = ref;\r\n\r\n // Collect behavior instances from properties (must happen before makeObservable)\r\n instance._collectBehaviors();\r\n\r\n // Check for Mantle decorator annotations first\r\n const decoratorAnnotations = getAnnotations(instance);\r\n \r\n if (decoratorAnnotations) {\r\n // Mantle decorators: use collected annotations\r\n // Auto-bind all methods for stable `this` references\r\n const annotations = { ...decoratorAnnotations };\r\n \r\n // Walk prototype chain to auto-bind methods not explicitly decorated\r\n let proto = Object.getPrototypeOf(instance);\r\n while (proto && proto !== View.prototype) {\r\n const descriptors = Object.getOwnPropertyDescriptors(proto);\r\n for (const [key, descriptor] of Object.entries(descriptors)) {\r\n if (BASE_EXCLUDES.has(key)) continue;\r\n if (key in annotations) continue;\r\n if (typeof descriptor.value === 'function') {\r\n annotations[key] = action.bound;\r\n }\r\n }\r\n proto = Object.getPrototypeOf(proto);\r\n }\r\n \r\n makeObservable(instance, annotations as AnnotationsMap<V, never>);\r\n } else if (autoObservable) {\r\n makeViewObservable(instance, true);\r\n } else {\r\n // For legacy decorator users: applies decorator metadata\r\n makeObservable(instance);\r\n }\r\n\r\n // Proxy forwards property access to instance.props, so reads are tracked\r\n // by MobX when used in reactions/computeds (same behavior as this.props)\r\n const reactiveProps = new Proxy({} as P, {\r\n get: (_, key) => (instance.props as any)[key],\r\n has: (_, key) => key in (instance.props as any),\r\n ownKeys: () => Reflect.ownKeys(instance.props as object),\r\n getOwnPropertyDescriptor: (_, key) =>\r\n Reflect.getOwnPropertyDescriptor(instance.props as object, key),\r\n });\r\n instance.onCreate?.(reactiveProps);\r\n vmRef.current = instance;\r\n prevPropsRef.current = props as P;\r\n }\r\n\r\n const vm = vmRef.current;\r\n\r\n // Dev warning: detect when a prop-triggered reaction causes a re-render.\r\n // This means a reaction is being used for derived state — a computed getter\r\n // would avoid the double render.\r\n if (process.env.NODE_ENV !== 'production' && propsNotifyingRef.current) {\r\n console.warn(\r\n `[mobx-mantle] ${ViewClass.name}: A reaction to a prop change modified ` +\r\n `observable state, which caused an extra re-render. Consider using a ` +\r\n `computed getter instead.`\r\n );\r\n propsNotifyingRef.current = false;\r\n }\r\n\r\n // Silently update _propsBox.value_ so this.props returns the correct value\r\n // during render, without triggering MobX reactions (which would cause\r\n // \"Cannot update component A while rendering component B\").\r\n vm._syncProps(props as P);\r\n vm.forwardRef = ref;\r\n\r\n // After render completes, properly notify MobX observers of prop changes.\r\n // This enables reaction(() => this.props.x, ...) in lifecycle methods.\r\n // useLayoutEffect runs after React finishes the render pass, so it's safe\r\n // to flush reactions here.\r\n useLayoutEffect(() => {\r\n if (!shallowEqual(prevPropsRef.current, props)) {\r\n prevPropsRef.current = props as P;\r\n propsNotifyingRef.current = true;\r\n runInAction(() => {\r\n vm._propsBox.set(props);\r\n });\r\n // If a reaction triggered a synchronous re-render, the warning\r\n // already fired above. Clear the flag for the normal case.\r\n propsNotifyingRef.current = false;\r\n }\r\n });\r\n\r\n // [vm] dep ensures effects re-run when instance changes (HMR).\r\n // On normal renders vm is stable, so effects run once — same as [].\r\n useLayoutEffect(() => {\r\n vm._layoutMountBehaviors();\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const result = vm.onLayoutMount?.();\r\n if (process.env.NODE_ENV !== 'production' && result instanceof Promise) {\r\n console.error(\r\n `[mobx-mantle] ${ViewClass.name}.onLayoutMount() returned a Promise. ` +\r\n `Lifecycle methods must be synchronous. Use a sync onLayoutMount that ` +\r\n `calls an async method instead.`\r\n );\r\n }\r\n cleanup = result as (() => void) | undefined;\r\n } catch (e) {\r\n reportError(e, { phase: 'onLayoutMount', name: ViewClass.name, isBehavior: false });\r\n }\r\n return () => {\r\n cleanup?.();\r\n };\r\n }, [vm]);\r\n\r\n useEffect(() => {\r\n vm._mountBehaviors();\r\n let cleanup: (() => void) | undefined;\r\n try {\r\n const result = vm.onMount?.();\r\n if (process.env.NODE_ENV !== 'production' && result instanceof Promise) {\r\n console.error(\r\n `[mobx-mantle] ${ViewClass.name}.onMount() returned a Promise. ` +\r\n `Lifecycle methods must be synchronous. Use a sync onMount that ` +\r\n `calls an async method instead.`\r\n );\r\n }\r\n cleanup = result as (() => void) | undefined;\r\n } catch (e) {\r\n reportError(e, { phase: 'onMount', name: ViewClass.name, isBehavior: false });\r\n }\r\n return () => {\r\n cleanup?.();\r\n try {\r\n vm.onUnmount?.();\r\n } catch (e) {\r\n reportError(e, { phase: 'onUnmount', name: ViewClass.name, isBehavior: false });\r\n }\r\n vm._disposeWatchers();\r\n vm._unmountBehaviors();\r\n };\r\n }, [vm]);\r\n\r\n // Called after every render (via useEffect)\r\n useEffect(() => {\r\n try {\r\n vm.onUpdate?.();\r\n } catch (e) {\r\n reportError(e, { phase: 'onUpdate', name: ViewClass.name, isBehavior: false });\r\n }\r\n });\r\n\r\n if (!template && !vm.render) {\r\n throw new Error(\r\n `[mobx-mantle] ${ViewClass.name}: Missing render() method. Either define render() in your View class or pass a template function to createView().`\r\n );\r\n }\r\n\r\n // Only the render call is tracked by MobX (useObserver).\r\n return useObserver(() => {\r\n return template ? template(vm) : vm.render!();\r\n });\r\n });\r\n\r\n // Wrap in React.memo to match observer()'s behavior — skip re-renders\r\n // when parent re-renders but props haven't changed (shallow comparison).\r\n return memo(Component) as typeof Component;\r\n}\r\n\r\n","import { makeObservable, observable, computed, action, reaction, type AnnotationsMap } from 'mobx';\nimport { globalConfig, reportError, type WatchOptions } from './config';\n\n/** Symbol marker to identify behavior instances */\nexport const BEHAVIOR_MARKER = Symbol('behavior');\n\n// Behavior base class members that should not be made observable\nconst BEHAVIOR_EXCLUDES = new Set([\n 'onCreate',\n 'onLayoutMount',\n 'onMount',\n 'onUnmount',\n 'watch',\n 'constructor',\n '_watchDisposers',\n '_disposeWatchers',\n]);\n\n/**\n * Detects if a value looks like a React ref ({ current: ... })\n * These should use observable.ref to preserve object identity\n */\nfunction isRefLike(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false;\n if (Array.isArray(value)) return false;\n return 'current' in value && Object.keys(value).length === 1;\n}\n\n/**\n * Base class for behaviors. Provides lifecycle method signatures for IDE autocomplete.\n * Extend this class and wrap with createBehavior() to create a factory.\n * \n * @example\n * ```tsx\n * class WindowSizeBehavior extends Behavior {\n * width = window.innerWidth;\n * onCreate(breakpoint = 768) { ... }\n * onMount() { ... }\n * }\n * export const withWindowSize = createBehavior(WindowSizeBehavior);\n * ```\n */\nexport class Behavior {\n /** @internal */\n _watchDisposers: (() => void)[] = [];\n\n onCreate?(...args: any[]): void;\n onLayoutMount?(): void | (() => void);\n onMount?(): void | (() => void);\n onUnmount?(): void;\n\n /**\n * Watch a reactive expression and run a callback when it changes.\n * Automatically disposed on unmount.\n * \n * @param expr - Reactive expression (getter) to watch\n * @param callback - Called when the expression result changes\n * @param options - Optional configuration (delay, fireImmediately)\n * @returns Dispose function for early teardown\n * \n * @example\n * ```tsx\n * onCreate(url: string) {\n * this.url = url;\n * this.watch(() => this.url, () => this.fetchData());\n * }\n * ```\n */\n watch<T>(\n expr: () => T,\n callback: (value: T, prevValue: T | undefined) => void,\n options?: WatchOptions\n ): () => void {\n const dispose = reaction(\n expr,\n (value, prevValue) => {\n try {\n callback(value, prevValue);\n } catch (e) {\n reportError(e, { phase: 'watch', name: this.constructor.name, isBehavior: true });\n }\n },\n {\n delay: options?.delay,\n fireImmediately: options?.fireImmediately,\n }\n );\n\n this._watchDisposers.push(dispose);\n\n // Return a dispose function that also removes from the array\n return () => {\n dispose();\n const idx = this._watchDisposers.indexOf(dispose);\n if (idx !== -1) this._watchDisposers.splice(idx, 1);\n };\n }\n\n /** @internal */\n _disposeWatchers(): void {\n for (const dispose of this._watchDisposers) {\n dispose();\n }\n this._watchDisposers.length = 0;\n }\n}\n\n/**\n * Makes a behavior instance observable, handling inheritance properly.\n * Works with classes that extend Behavior or plain classes.\n */\nfunction makeBehaviorObservable<T extends object>(instance: T): void {\n const annotations: AnnotationsMap<T, never> = {} as AnnotationsMap<T, never>;\n\n // Collect own properties → observable\n const ownKeys = new Set([\n ...Object.keys(instance),\n ...Object.keys(Object.getPrototypeOf(instance)),\n ]);\n\n for (const key of ownKeys) {\n if (BEHAVIOR_EXCLUDES.has(key)) continue;\n if (key in annotations) continue;\n\n const value = (instance as any)[key];\n if (typeof value === 'function') continue;\n\n // Use observable.ref for ref-like objects to preserve identity\n if (isRefLike(value)) {\n (annotations as any)[key] = observable.ref;\n } else {\n (annotations as any)[key] = observable;\n }\n }\n\n // Walk prototype chain up to (but not including) Behavior or Object\n let proto = Object.getPrototypeOf(instance);\n while (proto && proto !== Behavior.prototype && proto !== Object.prototype) {\n const descriptors = Object.getOwnPropertyDescriptors(proto);\n\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (BEHAVIOR_EXCLUDES.has(key)) continue;\n if (key in annotations) continue;\n\n if (descriptor.get) {\n (annotations as any)[key] = computed;\n } else if (typeof descriptor.value === 'function') {\n (annotations as any)[key] = action.bound;\n }\n }\n\n proto = Object.getPrototypeOf(proto);\n }\n\n makeObservable(instance, annotations);\n}\n\n/** @internal */\nexport interface BehaviorEntry {\n instance: any;\n cleanup?: () => void;\n layoutCleanup?: () => void;\n}\n\n/**\n * Extracts parameter types from onCreate method\n */\ntype OnCreateParams<T> = T extends { onCreate(...args: infer A): any } ? A : [];\n\n/**\n * Extracts constructor parameter types\n */\ntype ConstructorParams<T> = T extends new (...args: infer A) => any ? A : [];\n\n/**\n * Determines the args for createBehavior:\n * - If constructor has args, use those\n * - Otherwise, if onCreate has args, use those\n */\ntype BehaviorArgs<T extends new (...args: any[]) => any> = \n ConstructorParams<T> extends [] \n ? OnCreateParams<InstanceType<T>> \n : ConstructorParams<T>;\n\n/**\n * Creates a behavior factory with automatic observable wrapping and lifecycle management.\n * \n * Returns a factory function (not a class) — use without `new`:\n * \n * @example Defining a behavior\n * ```tsx\n * class DragTrait extends Behavior {\n * ref!: RefObject<HTMLElement>;\n * \n * onCreate(ref: RefObject<HTMLElement>) {\n * this.ref = ref;\n * }\n * \n * onMount() {\n * this.ref.current?.addEventListener('pointerdown', this.onPointerDown);\n * return () => this.ref.current?.removeEventListener('pointerdown', this.onPointerDown);\n * }\n * }\n * \n * export const withDrag = createBehavior(DragTrait);\n * ```\n * \n * @example Using in a View\n * ```tsx\n * class Editor extends View<Props> {\n * canvas = this.ref<HTMLCanvasElement>();\n * \n * // No `new` keyword — factory function\n * drag = withDrag(this.canvas);\n * autosave = withAutosave('/api/save', 5000);\n * }\n * export default createView(Editor);\n * ```\n * \n * The `with` prefix convention signals that the view manages this behavior's lifecycle.\n */\n/**\n * Type that supports both `new` and direct call syntax\n */\ntype BehaviorFactory<Args extends any[], Instance> = {\n new (...args: Args): Instance;\n (...args: Args): Instance;\n};\n\nexport function createBehavior<T extends new (...args: any[]) => any>(\n Def: T,\n options?: { autoObservable?: boolean }\n): BehaviorFactory<BehaviorArgs<T>, InstanceType<T>> {\n // Internal class that wraps the user's behavior definition\n const BehaviorClass = class extends (Def as any) {\n static [BEHAVIOR_MARKER] = true;\n\n constructor(...args: any[]) {\n super(...args);\n \n // Call onCreate with args (if it exists)\n if (typeof this.onCreate === 'function') {\n this.onCreate(...args);\n }\n \n // Make the instance observable (respects global config and per-behavior options)\n const autoObservable = options?.autoObservable ?? globalConfig.autoObservable;\n if (autoObservable) {\n makeBehaviorObservable(this);\n } else {\n // For decorator users: applies decorator metadata\n makeObservable(this);\n }\n }\n };\n\n // Preserve the original class name for debugging\n Object.defineProperty(BehaviorClass, 'name', { value: Def.name });\n\n // Use Proxy to make the class callable without `new`\n // This allows both: withWindowSize(768) and new withWindowSize(768)\n return new Proxy(BehaviorClass, {\n apply(_target, _thisArg, args) {\n return new BehaviorClass(...args);\n },\n }) as unknown as BehaviorFactory<BehaviorArgs<T>, InstanceType<T>>;\n}\n\n\n/**\n * Checks if a value is a behavior instance created by createBehavior()\n */\nexport function isBehavior(value: unknown): boolean {\n if (value === null || typeof value !== 'object') return false;\n return (value.constructor as any)?.[BEHAVIOR_MARKER] === true;\n}\n\n/** @internal */\nexport function layoutMountBehavior(behavior: BehaviorEntry): void {\n const inst = behavior.instance;\n\n if ('onLayoutMount' in inst && typeof inst.onLayoutMount === 'function') {\n try {\n behavior.layoutCleanup = inst.onLayoutMount() ?? undefined;\n } catch (e) {\n reportError(e, { phase: 'onLayoutMount', name: inst.constructor.name, isBehavior: true });\n }\n }\n}\n\n/** @internal */\nexport function mountBehavior(behavior: BehaviorEntry): void {\n const inst = behavior.instance;\n\n if ('onMount' in inst && typeof inst.onMount === 'function') {\n try {\n behavior.cleanup = inst.onMount() ?? undefined;\n } catch (e) {\n reportError(e, { phase: 'onMount', name: inst.constructor.name, isBehavior: true });\n }\n }\n}\n\n/** @internal */\nexport function unmountBehavior(behavior: BehaviorEntry): void {\n // Call layout cleanup if exists\n behavior.layoutCleanup?.();\n\n // Call cleanup if exists\n behavior.cleanup?.();\n\n // Call onUnmount if exists\n const inst = behavior.instance;\n if ('onUnmount' in inst && typeof inst.onUnmount === 'function') {\n try {\n inst.onUnmount();\n } catch (e) {\n reportError(e, { phase: 'onUnmount', name: inst.constructor.name, isBehavior: true });\n }\n }\n\n // Dispose all watchers\n if (typeof inst._disposeWatchers === 'function') {\n inst._disposeWatchers();\n }\n}\n","/** Options for the watch method */\r\nexport interface WatchOptions {\r\n /** Debounce the callback by N milliseconds */\r\n delay?: number;\r\n /** Run callback immediately with current value */\r\n fireImmediately?: boolean;\r\n}\r\n\r\n/**\r\n * Error context passed to the onError handler\r\n */\r\nexport interface MantleErrorContext {\r\n /** The lifecycle phase where the error occurred */\r\n phase: 'onLayoutMount' | 'onMount' | 'onUpdate' | 'onUnmount' | 'watch';\r\n /** The View or Behavior class name */\r\n name: string;\r\n /** Whether the error came from a Behavior (true) or a View (false) */\r\n isBehavior: boolean;\r\n}\r\n\r\n/**\r\n * Global configuration options for mobx-mantle\r\n */\r\nexport interface MantleConfig {\r\n /** Whether to automatically make View/Behavior instances observable (default: true) */\r\n autoObservable?: boolean;\r\n /** Global error handler for lifecycle errors. Defaults to console.error. */\r\n onError?: (error: unknown, context: MantleErrorContext) => void;\r\n}\r\n\r\nexport const globalConfig: MantleConfig = {\r\n autoObservable: true,\r\n};\r\n\r\n/** @internal Report a lifecycle error through the configured handler or console.error */\r\nexport function reportError(error: unknown, context: MantleErrorContext): void {\r\n if (globalConfig.onError) {\r\n globalConfig.onError(error, context);\r\n } else {\r\n console.error(\r\n `[mobx-mantle] Error in ${context.isBehavior ? 'behavior' : 'view'} ${context.name}.${context.phase}():`,\r\n error,\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * Configure global defaults for mobx-mantle.\r\n * Settings can still be overridden per-view in createView options.\r\n */\r\nexport function configure(config: MantleConfig): void {\r\n Object.assign(globalConfig, config);\r\n}\r\n","import * as mobx from 'mobx';\r\n\r\n/**\r\n * Symbol key for storing decorator annotations in class metadata.\r\n * These annotations are read by createView() after construction.\r\n */\r\nexport const ANNOTATIONS = Symbol('mantle:annotations');\r\n\r\n/**\r\n * Decorator context type for TC39 decorators\r\n */\r\ninterface DecoratorContext {\r\n kind: 'field' | 'method' | 'getter' | 'setter' | 'accessor' | 'class';\r\n name: string | symbol;\r\n metadata: Record<symbol, unknown>;\r\n}\r\n\r\n/**\r\n * Helper to set annotation metadata\r\n */\r\nfunction setAnnotation(context: DecoratorContext, annotation: any): void {\r\n context.metadata[ANNOTATIONS] ??= {};\r\n (context.metadata[ANNOTATIONS] as Record<string | symbol, any>)[context.name] = annotation;\r\n}\r\n\r\n/**\r\n * Marks a field as observable. No `accessor` keyword needed.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function observable(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable);\r\n}\r\n\r\n/**\r\n * Observable variants for different observation modes\r\n */\r\nobservable.ref = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.ref);\r\n};\r\n\r\nobservable.shallow = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.shallow);\r\n};\r\n\r\nobservable.struct = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.struct);\r\n};\r\n\r\nobservable.deep = function(_value: undefined, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.observable.deep);\r\n};\r\n\r\n/**\r\n * Marks a method as an action. Auto-bound by default.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * \r\n * @action increment() {\r\n * this.count++;\r\n * }\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function action(_value: Function, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.action.bound);\r\n}\r\n\r\n/**\r\n * Marks a getter as computed.\r\n * Note: Getters are automatically computed in autoObservable mode,\r\n * but this decorator is useful for explicit annotation.\r\n * \r\n * @example\r\n * ```tsx\r\n * class Counter extends View {\r\n * @observable count = 0;\r\n * \r\n * @computed get doubled() {\r\n * return this.count * 2;\r\n * }\r\n * }\r\n * export default createView(Counter);\r\n * ```\r\n */\r\nexport function computed(_value: Function, context: DecoratorContext): void {\r\n setAnnotation(context, mobx.computed);\r\n}\r\n\r\n/**\r\n * Retrieves the annotations stored in class metadata.\r\n * Used by createView() to apply MobX observability.\r\n */\r\nexport function getAnnotations(instance: object): Record<string, any> | undefined {\r\n const metadata = (instance.constructor as any)[Symbol.metadata];\r\n return metadata?.[ANNOTATIONS] as Record<string, any> | undefined;\r\n}\r\n"],"mappings":"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","names":["makeObservable","observable","computed","action","reaction","observable","action","computed","reaction","observable","computed","action","makeObservable"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mobx-mantle",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "A
|
|
3
|
+
"version": "0.3.7",
|
|
4
|
+
"description": "A lightweight library for building React components with a familiar class-based API and MobX reactivity built in.",
|
|
5
5
|
"author": "Craig Albert <me@craigalbert.com>",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|