@vscode/observables-react 0.1.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +349 -0
  3. package/dist/IPropertyTransformer.d.ts +37 -0
  4. package/dist/IPropertyTransformer.d.ts.map +1 -0
  5. package/dist/IPropertyTransformer.js +64 -0
  6. package/dist/IPropertyTransformer.js.map +1 -0
  7. package/dist/ManualChangesHandler.d.ts +14 -0
  8. package/dist/ManualChangesHandler.d.ts.map +1 -0
  9. package/dist/ManualChangesHandler.js +45 -0
  10. package/dist/ManualChangesHandler.js.map +1 -0
  11. package/dist/ProvideViewModel.d.ts +41 -0
  12. package/dist/ProvideViewModel.d.ts.map +1 -0
  13. package/dist/ProvideViewModel.js +41 -0
  14. package/dist/ProvideViewModel.js.map +1 -0
  15. package/dist/Value.d.ts +16 -0
  16. package/dist/Value.d.ts.map +1 -0
  17. package/dist/Value.js +26 -0
  18. package/dist/Value.js.map +1 -0
  19. package/dist/di.d.ts +31 -0
  20. package/dist/di.d.ts.map +1 -0
  21. package/dist/di.js +86 -0
  22. package/dist/di.js.map +1 -0
  23. package/dist/index.d.ts +12 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +20 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/index.min.js +6 -0
  28. package/dist/index.min.js.map +1 -0
  29. package/dist/internal.d.ts +2 -0
  30. package/dist/internal.d.ts.map +1 -0
  31. package/dist/internal.js +6 -0
  32. package/dist/internal.js.map +1 -0
  33. package/dist/obsView.d.ts +14 -0
  34. package/dist/obsView.d.ts.map +1 -0
  35. package/dist/obsView.js +109 -0
  36. package/dist/obsView.js.map +1 -0
  37. package/dist/router/Navigator.d.ts +18 -0
  38. package/dist/router/Navigator.d.ts.map +1 -0
  39. package/dist/router/Navigator.js +35 -0
  40. package/dist/router/Navigator.js.map +1 -0
  41. package/dist/router/Path.d.ts +23 -0
  42. package/dist/router/Path.d.ts.map +1 -0
  43. package/dist/router/Path.js +63 -0
  44. package/dist/router/Path.js.map +1 -0
  45. package/dist/router/PathPattern.d.ts +15 -0
  46. package/dist/router/PathPattern.d.ts.map +1 -0
  47. package/dist/router/PathPattern.js +88 -0
  48. package/dist/router/PathPattern.js.map +1 -0
  49. package/dist/router/Route.d.ts +35 -0
  50. package/dist/router/Route.d.ts.map +1 -0
  51. package/dist/router/Route.js +63 -0
  52. package/dist/router/Route.js.map +1 -0
  53. package/dist/router/Router.d.ts +16 -0
  54. package/dist/router/Router.d.ts.map +1 -0
  55. package/dist/router/Router.js +37 -0
  56. package/dist/router/Router.js.map +1 -0
  57. package/dist/router/index.d.ts +10 -0
  58. package/dist/router/index.d.ts.map +1 -0
  59. package/dist/utils.d.ts +8 -0
  60. package/dist/utils.d.ts.map +1 -0
  61. package/dist/utils.js +14 -0
  62. package/dist/utils.js.map +1 -0
  63. package/dist/view.d.ts +9 -0
  64. package/dist/view.d.ts.map +1 -0
  65. package/dist/view.js +27 -0
  66. package/dist/view.js.map +1 -0
  67. package/dist/viewModel.d.ts +33 -0
  68. package/dist/viewModel.d.ts.map +1 -0
  69. package/dist/viewModel.js +36 -0
  70. package/dist/viewModel.js.map +1 -0
  71. package/dist/viewWithModel.d.ts +30 -0
  72. package/dist/viewWithModel.d.ts.map +1 -0
  73. package/dist/viewWithModel.js +50 -0
  74. package/dist/viewWithModel.js.map +1 -0
  75. package/package.json +72 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Microsoft Corporation.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,349 @@
1
+ # @vscode/observables-react
2
+
3
+ React bindings for `@vscode/observables`. Provides patterns for building reactive React components with observable state.
4
+
5
+ > **Note:** React Strict Mode is not supported.
6
+
7
+ <!-- @codeblock-config
8
+ outDir: readme-codeblock-examples/out
9
+ -->
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @vscode/observables @vscode/observables-react
15
+ ```
16
+
17
+ ## Core Patterns
18
+
19
+ ### viewWithModel - The ViewModel Pattern
20
+
21
+ The recommended way to build components with observable state:
22
+
23
+ <!-- @codeblock
24
+ file: counter.tsx
25
+ postfix: |
26
+ export { Counter, CounterModel };
27
+ additionalFiles:
28
+ - suffix: .playwright-spec.tsx
29
+ content: |
30
+ import { test, expect } from '@playwright/experimental-ct-react';
31
+ import { Counter } from './counter';
32
+
33
+ test('counter increments and shows doubled value', async ({ mount }) => {
34
+ const component = await mount(<Counter initialCount={5} label="Score" />);
35
+ await expect(component).toContainText('Score: 5');
36
+ await expect(component).toContainText('Doubled: 10');
37
+ await component.getByRole('button', { name: '+' }).click();
38
+ await expect(component).toContainText('Score: 6');
39
+ await expect(component).toContainText('Doubled: 12');
40
+ });
41
+ -->
42
+ ```tsx
43
+ import { observableValue, derived, IReader } from '@vscode/observables';
44
+ import { ViewModel, viewWithModel, prop } from '@vscode/observables-react';
45
+
46
+ class CounterModel extends ViewModel({ initialCount: prop.const<number>() }) {
47
+ public readonly count = observableValue(this, this.props.initialCount);
48
+ public readonly doubled = derived(this, reader => this.count.read(reader) * 2);
49
+
50
+ increment = () => this.count.set(this.count.get() + 1, undefined);
51
+
52
+ override dispose(): void {
53
+ // cleanup
54
+ super.dispose();
55
+ }
56
+ }
57
+
58
+ const Counter = viewWithModel(CounterModel, { label: prop<string>() }, (reader, model, props) => (
59
+ <div>
60
+ <span>{props.label.read(reader)}: {model.count.read(reader)}</span>
61
+ <span>Doubled: {model.doubled.read(reader)}</span>
62
+ <button onClick={model.increment}>+</button>
63
+ </div>
64
+ )
65
+ );
66
+
67
+ // Usage - both ViewModel props (initialCount) and view props (label) are merged
68
+ const example = <Counter initialCount={10} label="Score" />;
69
+ ```
70
+
71
+ ### view - Observable Props
72
+
73
+ Create components with typed observable props:
74
+
75
+ <!-- @codeblock display.tsx -->
76
+ ```tsx
77
+ import { view, prop } from '@vscode/observables-react';
78
+
79
+ const Display = view(
80
+ {
81
+ label: prop<string>(),
82
+ count: prop<number>(),
83
+ },
84
+ (reader, props) => (
85
+ <div>
86
+ <span>{props.label.read(reader)}</span>
87
+ <span>{props.count.read(reader)}</span>
88
+ </div>
89
+ )
90
+ );
91
+
92
+ // Usage
93
+ const example = <Display label="Total" count={42} />;
94
+ ```
95
+
96
+ ### ObsView - Inline Observable Rendering
97
+
98
+ For embedding observable values in existing components:
99
+
100
+ <!-- @codeblock obsview.tsx -->
101
+ ```tsx
102
+ import { observableValue } from '@vscode/observables';
103
+ import { ObsView } from '@vscode/observables-react';
104
+
105
+ const count = observableValue('count', 0);
106
+
107
+ function App() {
108
+ return (
109
+ <div>
110
+ <ObsView>{reader => <span>{count.read(reader)}</span>}</ObsView>
111
+ <button onClick={() => count.set(count.get() + 1, undefined)}>+</button>
112
+ </div>
113
+ );
114
+ }
115
+ ```
116
+
117
+ ### val - Observable to JSX Helper
118
+
119
+ Render an observable value inline:
120
+
121
+ <!-- @codeblock val.tsx -->
122
+ ```tsx
123
+ import { observableValue } from '@vscode/observables';
124
+ import { val } from '@vscode/observables-react';
125
+
126
+ const message = observableValue('msg', 'Hello');
127
+
128
+ function App() {
129
+ return <div>{val(message)}</div>;
130
+ }
131
+ ```
132
+
133
+ ## Property Transformers
134
+
135
+ Property transformers control how props are passed to `view`, `viewWithModel`, and `ViewModel`. They define both the input type (what React receives) and the output type (what your render function or ViewModel sees).
136
+
137
+ ### For `view` and `viewWithModel` props
138
+
139
+ <!-- @codeblock property-transformers.tsx -->
140
+ ```tsx
141
+ import { view, prop } from '@vscode/observables-react';
142
+
143
+ const MyComponent = view(
144
+ {
145
+ // prop<T>() - input: T, output: IObservable<T>
146
+ // No re-render when value changes, read via observable
147
+ name: prop<string>(),
148
+
149
+ // prop.const<T>() - input: T, output: T
150
+ // Re-renders when value changes, available directly
151
+ label: prop.const<string>(),
152
+
153
+ // prop.obs<T>() - input: T | IObservable<T>, output: IObservable<T>
154
+ // Accepts either, normalizes to observable (slightly more expensive)
155
+ value: prop.obs<number>(),
156
+ },
157
+ (reader, props) => (
158
+ <div>
159
+ <span>{props.name.read(reader)}</span>
160
+ <span>{props.label}</span>
161
+ <span>{props.value.read(reader)}</span>
162
+ </div>
163
+ )
164
+ );
165
+ ```
166
+
167
+ ### For `ViewModel` constructor props
168
+
169
+ The same transformers work in `ViewModel()`, making them available via `this.props`:
170
+
171
+ - `prop.const<T>()` - When the value changes, the **ViewModel is disposed and recreated**. Use for identity/key-like props. Has a slight performance advantage when the value is not expected to change (no observable wrapper).
172
+ - `prop<T>()` - Changes update the observable without recreating the ViewModel. Use for values that change during the ViewModel's lifetime.
173
+
174
+ <!-- @codeblock
175
+ file: viewmodel-props.tsx
176
+ prefix: |
177
+ import { observableValue, IObservable } from '@vscode/observables';
178
+ import { ViewModel, prop } from '@vscode/observables-react';
179
+ -->
180
+ ```tsx
181
+ class MyModel extends ViewModel({
182
+ initialValue: prop.const<number>(), // if this changes, MyModel is recreated
183
+ config: prop<string>(), // changes update this.props.config observable
184
+ }) {
185
+ readonly value = observableValue(this, this.props.initialValue);
186
+ }
187
+ ```
188
+
189
+ ### `inject` - DI transformer for ViewModels
190
+
191
+ `inject(key)` is a special transformer that resolves a service from the DI container:
192
+
193
+ <!-- @codeblock
194
+ file: inject-snippet.tsx
195
+ prefix: |
196
+ import { observableValue } from '@vscode/observables';
197
+ import { ViewModel, inject, createServiceKey } from '@vscode/observables-react';
198
+ class AppModel {
199
+ userName = observableValue(this, '');
200
+ login = (_userName: string) => {};
201
+ }
202
+ -->
203
+ ```tsx
204
+ const $AppModel = createServiceKey(AppModel);
205
+
206
+ class LoginViewModel extends ViewModel({
207
+ appModel: inject($AppModel), // resolved from DIContainer, available as this.props.appModel
208
+ }) {
209
+ public readonly userName = observableValue(this, '');
210
+ login = () => this.props.appModel.login(this.userName.get());
211
+ }
212
+ ```
213
+
214
+ - Input: optional (can be passed explicitly for testing)
215
+ - Output: the service instance
216
+ - Requires a `DIProvider` ancestor in the component tree
217
+
218
+ ## Dependency Injection
219
+
220
+ Built-in DI support for ViewModels:
221
+
222
+ <!-- @codeblock di.tsx -->
223
+ ```tsx
224
+ import { observableValue } from '@vscode/observables';
225
+ import {
226
+ createServiceKey, DIContainer, DIProvider, inject,
227
+ ViewModel, viewWithModel
228
+ } from '@vscode/observables-react';
229
+
230
+ // The AppModel, for simple apps the central piece for the business logic
231
+ class AppModel {
232
+ public readonly currentUser = observableValue<string | undefined>(this, undefined);
233
+ login = (userName: string) => this.currentUser.set(userName, undefined);
234
+ dispose() {} // Required for DisposableStore
235
+ }
236
+
237
+ const $AppModel = createServiceKey(AppModel);
238
+
239
+ // RootViewModel - sets up DI and provides services.
240
+ class RootViewModel extends ViewModel() {
241
+ private readonly _appModel = this._store.add(new AppModel());
242
+ public readonly container = new DIContainer()
243
+ .register($AppModel, this._appModel);
244
+ }
245
+
246
+ // use `inject` to get the instance. It's private to the view model.
247
+ // The view model acts as an isolating bridge between the app model and the view.
248
+ class LoginViewModel extends ViewModel({ appModel: inject($AppModel) }) {
249
+ public readonly userName = observableValue(this, '');
250
+ login = () => this.props.appModel.login(this.userName.get());
251
+ }
252
+
253
+ // Root component provides DI context
254
+ const Root = viewWithModel(RootViewModel, (_reader, model) => (
255
+ <DIProvider container={model.container}>
256
+ <LoginPage />
257
+ </DIProvider>
258
+ ));
259
+
260
+ const LoginPage = viewWithModel(LoginViewModel, (reader, model) => (
261
+ <div>
262
+ <input
263
+ value={model.userName.read(reader)}
264
+ onChange={e => model.userName.set(e.target.value, undefined)}
265
+ />
266
+ <button onClick={model.login}>Login</button>
267
+ </div>
268
+ ));
269
+ ```
270
+
271
+ ## Testing with Mock ViewModels
272
+
273
+ Override ViewModel instances for testing:
274
+
275
+ <!-- @codeblock
276
+ file: testing.tsx
277
+ prefix: |
278
+ import { observableValue, derived } from '@vscode/observables';
279
+ import { ViewModel, viewWithModel, prop, ProvideMockViewModels, mockViewModel } from '@vscode/observables-react';
280
+
281
+ class CounterModel extends ViewModel({ initialCount: prop.const<number>() }) {
282
+ public readonly count = observableValue(this, this.props.initialCount);
283
+ increment = () => this.count.set(this.count.get() + 1, undefined);
284
+ }
285
+ const Counter = viewWithModel(CounterModel, (reader, model) => (
286
+ <div><span>{model.count.read(reader)}</span></div>
287
+ ));
288
+ -->
289
+ ```tsx
290
+ const mockModel = new CounterModel({ initialCount: 0 });
291
+ mockModel.count.set(42, undefined);
292
+
293
+ const example = (
294
+ <ProvideMockViewModels mocks={[mockViewModel(CounterModel, mockModel)]}>
295
+ <Counter initialCount={0} />
296
+ </ProvideMockViewModels>
297
+ );
298
+ ```
299
+
300
+ ## Router (Experimental)
301
+
302
+ Type-safe routing utilities:
303
+
304
+ <!-- @codeblock router.tsx -->
305
+ ```tsx
306
+ import { Route, Router } from '@vscode/observables-react';
307
+
308
+ const homeRoute = Route.create('/');
309
+ const userRoute = Route.create('/users/:id', { id: 'string' });
310
+
311
+ const router = Router.create<string>()
312
+ .with(homeRoute, () => 'home')
313
+ .with(userRoute, (args) => `user-${args.id}`);
314
+ ```
315
+
316
+ ## API Reference
317
+
318
+ ### Components & Views
319
+
320
+ - `viewWithModel(ModelClass, props, render)` - Create component with ViewModel
321
+ - `view(props, render)` - Create component with observable props
322
+ - `ObsView` - Inline observable rendering component
323
+ - `Value` - Render observable as component
324
+ - `val(observable)` - Render observable inline
325
+
326
+ ### ViewModel
327
+
328
+ - `ViewModel(props)` - Base class factory for ViewModels
329
+ - `BaseViewModel` - Base class with disposable store
330
+ - `ProvideMockViewModels` - Override multiple ViewModels for testing
331
+ - `mockViewModel(Class, instance)` - Create mock binding for ProvideMockViewModels
332
+ - `ProvideViewModel` - Override single ViewModel for testing (low-level)
333
+
334
+ ### Property Transformers
335
+
336
+ - `prop<T>()` - Transform to `IObservable<T>`
337
+ - `prop.const<T>()` - Pass through as `T`
338
+ - `prop.obs<T>()` - Normalize to `IObservable<T>`
339
+
340
+ ### Dependency Injection
341
+
342
+ - `createServiceKey<T>(name)` or `createServiceKey(Class)` - Create typed service identifier
343
+ - `DIContainer` - Service container
344
+ - `DIProvider` - React context provider
345
+ - `inject(key)` - Property transformer for injection
346
+
347
+ ## License
348
+
349
+ MIT
@@ -0,0 +1,37 @@
1
+ import { IObservable, IReader } from "@vscode/observables";
2
+ import { Context } from "react";
3
+ export type Readable<T> = (reader: IReader) => T;
4
+ export interface IReadableObj<T> {
5
+ /**
6
+ * The reader of the component.
7
+ */
8
+ read(reader: IReader): T;
9
+ }
10
+ export interface IPropertyTransformerFactory<TIn, TOut> {
11
+ /** If set, this context's value is passed to create() */
12
+ readonly _requiredContext?: Context<unknown>;
13
+ /** @param contextValue - value of _requiredContext if declared, otherwise undefined */
14
+ create(readable: Readable<TIn>, contextValue: unknown): IReadableObj<TOut>;
15
+ }
16
+ /**
17
+ * Takes a value of type `T` and makes it available as `IObservable<T>`.
18
+ * When it changes, the component will not re-render.
19
+ */
20
+ export declare function prop<T>(): IPropertyTransformerFactory<T, IObservable<T>>;
21
+ export declare namespace prop {
22
+ var _a: typeof propConst;
23
+ export var obs: typeof propObs;
24
+ export { _a as const };
25
+ }
26
+ /**
27
+ * Takes a value of type `T` and makes it available as `T`.
28
+ * When it changes, the component will re-render.
29
+ */
30
+ declare function propConst<T>(): IPropertyTransformerFactory<T, T>;
31
+ /**
32
+ * Takes a value of type `T` or `IObservable<T>` and makes it available as `IObservable<T>`.
33
+ * When it changes, the component will not re-render.
34
+ */
35
+ declare function propObs<T>(): IPropertyTransformerFactory<T | IObservable<T>, IObservable<T>>;
36
+ export {};
37
+ //# sourceMappingURL=IPropertyTransformer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IPropertyTransformer.d.ts","sourceRoot":"","sources":["../src/IPropertyTransformer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,WAAW,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEhC,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,KAAK,CAAC,CAAC;AAEjD,MAAM,WAAW,YAAY,CAAC,CAAC;IAC3B;;MAEE;IACF,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,2BAA2B,CAAC,GAAG,EAAE,IAAI;IAClD,yDAAyD;IACzD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,uFAAuF;IACvF,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,YAAY,EAAE,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;CAC9E;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,CAAC,KAAK,2BAA2B,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAExE;yBAFe,IAAI;;;;;AAIpB;;;GAGG;AACH,iBAAS,SAAS,CAAC,CAAC,KAAK,2BAA2B,CAAC,CAAC,EAAE,CAAC,CAAC,CAEzD;AAED;;;GAGG;AACH,iBAAS,OAAO,CAAC,CAAC,KAAK,2BAA2B,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAErF"}
@@ -0,0 +1,64 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { derived } from '@vscode/observables';
6
+
7
+ /**
8
+ * Takes a value of type `T` and makes it available as `IObservable<T>`.
9
+ * When it changes, the component will not re-render.
10
+ */
11
+ function prop() {
12
+ return PropertyTransformerFactory.instance;
13
+ }
14
+ /**
15
+ * Takes a value of type `T` and makes it available as `T`.
16
+ * When it changes, the component will re-render.
17
+ */
18
+ function propConst() {
19
+ return PropertyConstTransformerFactory.instance;
20
+ }
21
+ /**
22
+ * Takes a value of type `T` or `IObservable<T>` and makes it available as `IObservable<T>`.
23
+ * When it changes, the component will not re-render.
24
+ */
25
+ function propObs() {
26
+ return PropertyObsTransformerFactory.instance;
27
+ }
28
+ prop.const = propConst;
29
+ prop.obs = propObs;
30
+ class PropertyTransformerFactory {
31
+ create(readableProp) {
32
+ const d = derived(reader => readableProp(reader));
33
+ return { read: (_reader) => d };
34
+ }
35
+ }
36
+ PropertyTransformerFactory.instance = new PropertyTransformerFactory();
37
+ class PropertyConstTransformerFactory {
38
+ create(readableProp) {
39
+ const d = derived(reader => readableProp(reader));
40
+ return { read: (reader) => d.read(reader) };
41
+ }
42
+ }
43
+ PropertyConstTransformerFactory.instance = new PropertyConstTransformerFactory();
44
+ class PropertyObsTransformerFactory {
45
+ create(readableProp) {
46
+ const d = derived(reader => {
47
+ const v = readableProp(reader);
48
+ if (isObservable(v)) {
49
+ return v.read(reader);
50
+ }
51
+ else {
52
+ return v;
53
+ }
54
+ });
55
+ return { read: (_reader) => d };
56
+ }
57
+ }
58
+ PropertyObsTransformerFactory.instance = new PropertyObsTransformerFactory();
59
+ function isObservable(obs) {
60
+ return typeof obs === "object" && obs !== null && "read" in obs;
61
+ }
62
+
63
+ export { prop };
64
+ //# sourceMappingURL=IPropertyTransformer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IPropertyTransformer.js","sources":["../src/IPropertyTransformer.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAmBA;;;AAGG;SACa,IAAI,GAAA;IAChB,OAAO,0BAA0B,CAAC,QAAQ,CAAC;AAC/C,CAAC;AAED;;;AAGG;AACH,SAAS,SAAS,GAAA;IACd,OAAO,+BAA+B,CAAC,QAAQ,CAAC;AACpD,CAAC;AAED;;;AAGG;AACH,SAAS,OAAO,GAAA;IACZ,OAAO,6BAA6B,CAAC,QAAQ,CAAC;AAClD,CAAC;AAED,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;AACvB,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC;AAEnB,MAAM,0BAA0B,CAAA;AAG5B,IAAA,MAAM,CAAC,YAAyB,EAAA;AAC5B,QAAA,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;QAClD,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;KACnC;;AALsB,0BAAA,CAAA,QAAQ,GAAG,IAAI,0BAA0B,EAAO,CAAC;AAQ5E,MAAM,+BAA+B,CAAA;AAGjC,IAAA,MAAM,CAAC,YAAyB,EAAA;AAC5B,QAAA,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;AAClD,QAAA,OAAO,EAAE,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;KAC/C;;AALsB,+BAAA,CAAA,QAAQ,GAAG,IAAI,+BAA+B,EAAO,CAAC;AAQjF,MAAM,6BAA6B,CAAA;AAG/B,IAAA,MAAM,CAAC,YAA0C,EAAA;AAC7C,QAAA,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,IAAG;AACvB,YAAA,MAAM,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAC/B,YAAA,IAAI,YAAY,CAAC,CAAC,CAAC,EAAE;AACjB,gBAAA,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;aACzB;iBAAM;AACH,gBAAA,OAAO,CAAC,CAAC;aACZ;AACL,SAAC,CAAC,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;KACnC;;AAZsB,6BAAA,CAAA,QAAQ,GAAG,IAAI,6BAA6B,EAAO,CAAC;AAe/E,SAAS,YAAY,CAAC,GAAQ,EAAA;AAC1B,IAAA,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,IAAI,GAAG,CAAC;AACpE;;;;"}
@@ -0,0 +1,14 @@
1
+ import { IObservable, IObservableWithChange, IObserver, IDisposable } from "@vscode/observables";
2
+ export declare class ManualChangesHandler<TData> implements IObserver {
3
+ readonly _run: (changes: TData[]) => void;
4
+ private _changes;
5
+ private readonly _map;
6
+ constructor(_run: (changes: TData[]) => void);
7
+ addDependency(observable: IObservable<any>, data: TData): IDisposable;
8
+ private _updateCounter;
9
+ beginUpdate<T>(observable: IObservableWithChange<T, unknown>): void;
10
+ endUpdate<T>(_observable: IObservableWithChange<T, unknown>): void;
11
+ handlePossibleChange<T>(observable: IObservableWithChange<T, unknown>): void;
12
+ handleChange<T, TChange>(_observable: IObservableWithChange<T, TChange>, _change: TChange): void;
13
+ }
14
+ //# sourceMappingURL=ManualChangesHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ManualChangesHandler.d.ts","sourceRoot":"","sources":["../src/ManualChangesHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,qBAAqB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEjG,qBAAa,oBAAoB,CAAC,KAAK,CAAE,YAAW,SAAS;aAK3C,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI;IAJjD,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsC;gBAG1C,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,IAAI;IAGjD,aAAa,CAAC,UAAU,EAAE,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,GAAG,WAAW;IAUrE,OAAO,CAAC,cAAc,CAAK;IAE3B,WAAW,CAAC,CAAC,EAAE,UAAU,EAAE,qBAAqB,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,IAAI;IAKnE,SAAS,CAAC,CAAC,EAAE,WAAW,EAAE,qBAAqB,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,IAAI;IAWlE,oBAAoB,CAAC,CAAC,EAAE,UAAU,EAAE,qBAAqB,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,IAAI;IAI5E,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,qBAAqB,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;CAGhG"}
@@ -0,0 +1,45 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ class ManualChangesHandler {
6
+ constructor(_run) {
7
+ this._run = _run;
8
+ this._changes = [];
9
+ this._map = new Map();
10
+ this._updateCounter = 0;
11
+ }
12
+ addDependency(observable, data) {
13
+ this._map.set(observable, data);
14
+ observable.addObserver(this);
15
+ return {
16
+ dispose: () => {
17
+ this._map.delete(observable);
18
+ observable.removeObserver(this);
19
+ }
20
+ };
21
+ }
22
+ beginUpdate(observable) {
23
+ this._updateCounter++;
24
+ this._changes.push(this._map.get(observable));
25
+ }
26
+ endUpdate(_observable) {
27
+ this._updateCounter--;
28
+ if (this._updateCounter === 0) {
29
+ if (this._changes.length > 0) {
30
+ const c = this._changes;
31
+ this._changes = [];
32
+ this._run(c);
33
+ }
34
+ }
35
+ }
36
+ handlePossibleChange(observable) {
37
+ this._changes.push(this._map.get(observable));
38
+ }
39
+ handleChange(_observable, _change) {
40
+ //this._changes.push(this._map.get(observable)!);
41
+ }
42
+ }
43
+
44
+ export { ManualChangesHandler };
45
+ //# sourceMappingURL=ManualChangesHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ManualChangesHandler.js","sources":["../src/ManualChangesHandler.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;MAEa,oBAAoB,CAAA;AAIhC,IAAA,WAAA,CACiB,IAAgC,EAAA;QAAhC,IAAI,CAAA,IAAA,GAAJ,IAAI,CAA4B;QAJzC,IAAQ,CAAA,QAAA,GAAY,EAAE,CAAC;AACd,QAAA,IAAA,CAAA,IAAI,GAAG,IAAI,GAAG,EAA2B,CAAC;QAgBnD,IAAc,CAAA,cAAA,GAAG,CAAC,CAAC;KAZtB;IAEL,aAAa,CAAC,UAA4B,EAAE,IAAW,EAAA;QACtD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AAChC,QAAA,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC7B,OAAO;YACN,OAAO,EAAE,MAAK;AACb,gBAAA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAC7B,gBAAA,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;aAChC;SACD,CAAC;KACF;AAGD,IAAA,WAAW,CAAI,UAA6C,EAAA;QAC3D,IAAI,CAAC,cAAc,EAAE,CAAC;AACtB,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAE,CAAC,CAAC;KAC/C;AAED,IAAA,SAAS,CAAI,WAA8C,EAAA;QAC1D,IAAI,CAAC,cAAc,EAAE,CAAC;AACtB,QAAA,IAAI,IAAI,CAAC,cAAc,KAAK,CAAC,EAAE;YAC9B,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;AAC7B,gBAAA,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;AACxB,gBAAA,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;AACnB,gBAAA,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aACb;SACD;KACD;AAED,IAAA,oBAAoB,CAAI,UAA6C,EAAA;AACpE,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAE,CAAC,CAAC;KAC/C;IAED,YAAY,CAAa,WAA8C,EAAE,OAAgB,EAAA;;KAExF;AACD;;;;"}
@@ -0,0 +1,41 @@
1
+ import { Context, ReactNode } from "react";
2
+ import { ViewModelContextSymbol } from "./viewModel";
3
+ /**
4
+ * Provider component to override a ViewModel instance.
5
+ * Useful for testing - allows injecting a mock ViewModel.
6
+ */
7
+ export declare function ProvideViewModel<T>({ viewModel: ViewModelClass, value, children }: {
8
+ viewModel: {
9
+ [ViewModelContextSymbol]?: Context<T | undefined>;
10
+ };
11
+ value: T;
12
+ children: ReactNode;
13
+ }): ReactNode;
14
+ /**
15
+ * Represents a mock binding of a ViewModel class to an instance.
16
+ */
17
+ export interface ViewModelMock {
18
+ readonly _provide: (children: ReactNode) => ReactNode;
19
+ }
20
+ /**
21
+ * Creates a mock binding for use with ProvideMockViewModels.
22
+ */
23
+ export declare function mockViewModel<T>(viewModelClass: {
24
+ [ViewModelContextSymbol]?: Context<T | undefined>;
25
+ }, instance: T): ViewModelMock;
26
+ /**
27
+ * Provider component to override multiple ViewModel instances at once.
28
+ * Useful for testing - allows injecting multiple mock ViewModels.
29
+ *
30
+ * @example
31
+ * ```tsx
32
+ * <ProvideMockViewModels mocks={[mockViewModel(AppPageViewModel, fakeViewModel)]}>
33
+ * <AppPage theme="light" />
34
+ * </ProvideMockViewModels>
35
+ * ```
36
+ */
37
+ export declare function ProvideMockViewModels({ mocks, children }: {
38
+ mocks: ViewModelMock[];
39
+ children: ReactNode;
40
+ }): ReactNode;
41
+ //# sourceMappingURL=ProvideViewModel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProvideViewModel.d.ts","sourceRoot":"","sources":["../src/ProvideViewModel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAA+B,MAAM,aAAa,CAAC;AAElF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,EAChC,SAAS,EAAE,cAAc,EACzB,KAAK,EACL,QAAQ,EACX,EAAE;IACC,SAAS,EAAE;QAAE,CAAC,sBAAsB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;KAAE,CAAC;IACjE,KAAK,EAAE,CAAC,CAAC;IACT,QAAQ,EAAE,SAAS,CAAC;CACvB,GAAG,SAAS,CAGZ;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,KAAK,SAAS,CAAC;CACzD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC3B,cAAc,EAAE;IAAE,CAAC,sBAAsB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;CAAE,EACrE,QAAQ,EAAE,CAAC,GACZ,aAAa,CAKf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,EAClC,KAAK,EACL,QAAQ,EACX,EAAE;IACC,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,QAAQ,EAAE,SAAS,CAAC;CACvB,GAAG,SAAS,CAKZ"}
@@ -0,0 +1,41 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { jsx } from 'react/jsx-runtime';
6
+ import { getOrCreateViewModelContext } from './viewModel.js';
7
+
8
+ /**
9
+ * Provider component to override a ViewModel instance.
10
+ * Useful for testing - allows injecting a mock ViewModel.
11
+ */
12
+ function ProvideViewModel({ viewModel: ViewModelClass, value, children }) {
13
+ const ContextType = getOrCreateViewModelContext(ViewModelClass);
14
+ return jsx(ContextType.Provider, { value: value, children: children });
15
+ }
16
+ /**
17
+ * Creates a mock binding for use with ProvideMockViewModels.
18
+ */
19
+ function mockViewModel(viewModelClass, instance) {
20
+ const ContextType = getOrCreateViewModelContext(viewModelClass);
21
+ return {
22
+ _provide: children => jsx(ContextType.Provider, { value: instance, children: children }),
23
+ };
24
+ }
25
+ /**
26
+ * Provider component to override multiple ViewModel instances at once.
27
+ * Useful for testing - allows injecting multiple mock ViewModels.
28
+ *
29
+ * @example
30
+ * ```tsx
31
+ * <ProvideMockViewModels mocks={[mockViewModel(AppPageViewModel, fakeViewModel)]}>
32
+ * <AppPage theme="light" />
33
+ * </ProvideMockViewModels>
34
+ * ```
35
+ */
36
+ function ProvideMockViewModels({ mocks, children }) {
37
+ return mocks.reduceRight((acc, mock) => mock._provide(acc), children);
38
+ }
39
+
40
+ export { ProvideMockViewModels, ProvideViewModel, mockViewModel };
41
+ //# sourceMappingURL=ProvideViewModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProvideViewModel.js","sources":["../src/ProvideViewModel.tsx"],"sourcesContent":[null],"names":["_jsx"],"mappings":";;;;;;;AAGA;;;AAGG;AACG,SAAU,gBAAgB,CAAI,EAChC,SAAS,EAAE,cAAc,EACzB,KAAK,EACL,QAAQ,EAKX,EAAA;AACG,IAAA,MAAM,WAAW,GAAG,2BAA2B,CAAI,cAAc,CAAC,CAAC;IACnE,OAAOA,GAAA,CAAC,WAAW,CAAC,QAAQ,EAAA,EAAC,KAAK,EAAE,KAAK,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAwB,CAAC;AACjF,CAAC;AASD;;AAEG;AACa,SAAA,aAAa,CACzB,cAAqE,EACrE,QAAW,EAAA;AAEX,IAAA,MAAM,WAAW,GAAG,2BAA2B,CAAI,cAAc,CAAC,CAAC;IACnE,OAAO;AACH,QAAA,QAAQ,EAAE,QAAQ,IAAIA,GAAC,CAAA,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,QAAQ,EAAA,QAAA,EAAG,QAAQ,EAAwB,CAAA;KACjG,CAAC;AACN,CAAC;AAED;;;;;;;;;;AAUG;SACa,qBAAqB,CAAC,EAClC,KAAK,EACL,QAAQ,EAIX,EAAA;IACG,OAAO,KAAK,CAAC,WAAW,CACpB,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EACjC,QAAQ,CACX,CAAC;AACN;;;;"}
@@ -0,0 +1,16 @@
1
+ import { IObservable } from "@vscode/observables";
2
+ import { ReactNode } from "react";
3
+ /**
4
+ * A component that renders an observable ReactNode value.
5
+ * Re-renders when the observable changes.
6
+ * Usage: <Value value={myObservable} />
7
+ */
8
+ export declare const Value: import("react").ComponentType<import("./viewModel").PropsIn<{
9
+ value: import("./IPropertyTransformer").IPropertyTransformerFactory<ReactNode | IObservable<ReactNode>, IObservable<ReactNode>>;
10
+ }>>;
11
+ /**
12
+ * Helper function to render an observable as inline JSX.
13
+ * Usage: {val(myObservable)}
14
+ */
15
+ export declare function val(v: IObservable<ReactNode>): ReactNode;
16
+ //# sourceMappingURL=Value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Value.d.ts","sourceRoot":"","sources":["../src/Value.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlC;;;;GAIG;AACH,eAAO,MAAM,KAAK;;GAEhB,CAAC;AAEH;;;GAGG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,GAAG,SAAS,CAExD"}