@brightspace-ui/labs 2.10.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/lang/cy.js +2 -2
- package/src/lang/da.js +4 -4
- package/src/lang/fr-on.js +1 -1
- package/src/lang/fr.js +2 -2
- package/src/lang/hi.js +1 -1
- package/src/lang/ja.js +1 -1
- package/src/lang/ko.js +3 -3
- package/src/lang/pt.js +1 -1
- package/src/lang/tr.js +1 -1
- package/src/lang/zh-cn.js +4 -4
- package/src/utilities/reactive-store/README.md +88 -42
- package/src/utilities/reactive-store/context-controllers.js +32 -43
- package/src/utilities/reactive-store/store-consumer.js +15 -60
- package/src/utilities/reactive-store/store-reactor.js +52 -0
package/package.json
CHANGED
package/src/lang/cy.js
CHANGED
|
@@ -50,6 +50,6 @@ export default {
|
|
|
50
50
|
"components:wizard:aria.steplabel": "Cam {currentStep} o {totalSteps}",
|
|
51
51
|
"components:wizard:stepper.defaults.next": "Nesaf",
|
|
52
52
|
"components:wizard:stepper.defaults.restart": "Ailddechrau",
|
|
53
|
-
"components:wizard:restart.button.tooltip": "
|
|
54
|
-
"components:wizard:next.button.tooltip": "
|
|
53
|
+
"components:wizard:restart.button.tooltip": "Yn ôl i'r cam cyntaf",
|
|
54
|
+
"components:wizard:next.button.tooltip": "Parhau i'r cam nesaf"
|
|
55
55
|
};
|
package/src/lang/da.js
CHANGED
|
@@ -47,9 +47,9 @@ export default {
|
|
|
47
47
|
"components:pagination:nextPage": "Næste side",
|
|
48
48
|
"components:pagination:previousPage": "Forrige side",
|
|
49
49
|
"components:pagination:resultsPerPage": "Resultater pr. side",
|
|
50
|
-
"components:wizard:aria.steplabel": "
|
|
50
|
+
"components:wizard:aria.steplabel": "Trin {currentStep} af {totalSteps}",
|
|
51
51
|
"components:wizard:stepper.defaults.next": "Next",
|
|
52
|
-
"components:wizard:stepper.defaults.restart": "
|
|
53
|
-
"components:wizard:restart.button.tooltip": "
|
|
54
|
-
"components:wizard:next.button.tooltip": "
|
|
52
|
+
"components:wizard:stepper.defaults.restart": "Genstart",
|
|
53
|
+
"components:wizard:restart.button.tooltip": "Tilbage til første trin",
|
|
54
|
+
"components:wizard:next.button.tooltip": "Fortsæt til næste trin"
|
|
55
55
|
};
|
package/src/lang/fr-on.js
CHANGED
|
@@ -47,7 +47,7 @@ export default {
|
|
|
47
47
|
"components:pagination:nextPage": "Page suivante",
|
|
48
48
|
"components:pagination:previousPage": "Page précédente",
|
|
49
49
|
"components:pagination:resultsPerPage": "Résultats par page",
|
|
50
|
-
"components:wizard:aria.steplabel": "Étape
|
|
50
|
+
"components:wizard:aria.steplabel": "Étape {currentStep} de {totalSteps}",
|
|
51
51
|
"components:wizard:stepper.defaults.next": "Page suivante",
|
|
52
52
|
"components:wizard:stepper.defaults.restart": "Redémarrer",
|
|
53
53
|
"components:wizard:restart.button.tooltip": "Retour à la première étape",
|
package/src/lang/fr.js
CHANGED
|
@@ -18,7 +18,7 @@ export default {
|
|
|
18
18
|
"components:checkboxDrawer:checkboxCollapsed": "Case à cocher réduite", // Read by screen readers when focusing the collapsed (unchecked) checkbox, with the inner content hidden
|
|
19
19
|
"components:checkboxDrawer:checkboxExpanded": "Case à cocher agrandie", // Read by screen readers when focusing the expanded (checked) checkbox, with the inner content shown
|
|
20
20
|
"components:navigation:back": "Retour",
|
|
21
|
-
"components:navigation:next": "
|
|
21
|
+
"components:navigation:next": "Suivant",
|
|
22
22
|
"components:navigation:previous": "Précédent",
|
|
23
23
|
"components:navigation:skipNav": "passer au contenu principal",
|
|
24
24
|
"components:optInFlyout:cancel": "Annuler",
|
|
@@ -47,7 +47,7 @@ export default {
|
|
|
47
47
|
"components:pagination:nextPage": "Page suivante",
|
|
48
48
|
"components:pagination:previousPage": "Page précédente",
|
|
49
49
|
"components:pagination:resultsPerPage": "Résultats par page",
|
|
50
|
-
"components:wizard:aria.steplabel": "Étape
|
|
50
|
+
"components:wizard:aria.steplabel": "Étape {currentStep} de {totalSteps}",
|
|
51
51
|
"components:wizard:stepper.defaults.next": "Suivant",
|
|
52
52
|
"components:wizard:stepper.defaults.restart": "Redémarrer",
|
|
53
53
|
"components:wizard:restart.button.tooltip": "Retour à la première étape",
|
package/src/lang/hi.js
CHANGED
|
@@ -49,7 +49,7 @@ export default {
|
|
|
49
49
|
"components:pagination:resultsPerPage": "प्रति पेज के परिणाम",
|
|
50
50
|
"components:wizard:aria.steplabel": "{totalSteps} में से {currentStep} चरण",
|
|
51
51
|
"components:wizard:stepper.defaults.next": "अगला",
|
|
52
|
-
"components:wizard:stepper.defaults.restart": "
|
|
52
|
+
"components:wizard:stepper.defaults.restart": "पुनरारंभ करें",
|
|
53
53
|
"components:wizard:restart.button.tooltip": "पहले चरण पर वापस जाएँ",
|
|
54
54
|
"components:wizard:next.button.tooltip": "अगले चरण पर आगे बढ़ें"
|
|
55
55
|
};
|
package/src/lang/ja.js
CHANGED
|
@@ -47,7 +47,7 @@ export default {
|
|
|
47
47
|
"components:pagination:nextPage": "次のページ",
|
|
48
48
|
"components:pagination:previousPage": "前のページ",
|
|
49
49
|
"components:pagination:resultsPerPage": "ページごとの結果",
|
|
50
|
-
"components:wizard:aria.steplabel": "
|
|
50
|
+
"components:wizard:aria.steplabel": "手順 {currentStep}/{totalSteps}",
|
|
51
51
|
"components:wizard:stepper.defaults.next": "次へ",
|
|
52
52
|
"components:wizard:stepper.defaults.restart": "再開",
|
|
53
53
|
"components:wizard:restart.button.tooltip": "最初の手順に戻る",
|
package/src/lang/ko.js
CHANGED
|
@@ -47,9 +47,9 @@ export default {
|
|
|
47
47
|
"components:pagination:nextPage": "다음 페이지",
|
|
48
48
|
"components:pagination:previousPage": "이전 페이지",
|
|
49
49
|
"components:pagination:resultsPerPage": "페이지당 결과 수",
|
|
50
|
-
"components:wizard:aria.steplabel": "{currentStep}/{totalSteps}
|
|
50
|
+
"components:wizard:aria.steplabel": "{currentStep}/{totalSteps}단계",
|
|
51
51
|
"components:wizard:stepper.defaults.next": "다음",
|
|
52
52
|
"components:wizard:stepper.defaults.restart": "다시 시작",
|
|
53
|
-
"components:wizard:restart.button.tooltip": "첫 번째 단계로
|
|
54
|
-
"components:wizard:next.button.tooltip": "다음 단계로
|
|
53
|
+
"components:wizard:restart.button.tooltip": "첫 번째 단계로 돌아가기",
|
|
54
|
+
"components:wizard:next.button.tooltip": "다음 단계로 진행"
|
|
55
55
|
};
|
package/src/lang/pt.js
CHANGED
|
@@ -18,7 +18,7 @@ export default {
|
|
|
18
18
|
"components:checkboxDrawer:checkboxCollapsed": "Caixa de seleção recolhida", // Read by screen readers when focusing the collapsed (unchecked) checkbox, with the inner content hidden
|
|
19
19
|
"components:checkboxDrawer:checkboxExpanded": "Caixa de seleção expandida", // Read by screen readers when focusing the expanded (checked) checkbox, with the inner content shown
|
|
20
20
|
"components:navigation:back": "Voltar",
|
|
21
|
-
"components:navigation:next": "
|
|
21
|
+
"components:navigation:next": "Avançar",
|
|
22
22
|
"components:navigation:previous": "Anterior",
|
|
23
23
|
"components:navigation:skipNav": "passar para conteúdo principal",
|
|
24
24
|
"components:optInFlyout:cancel": "Cancelar",
|
package/src/lang/tr.js
CHANGED
|
@@ -18,7 +18,7 @@ export default {
|
|
|
18
18
|
"components:checkboxDrawer:checkboxCollapsed": "Onay kutusu daraltıldı", // Read by screen readers when focusing the collapsed (unchecked) checkbox, with the inner content hidden
|
|
19
19
|
"components:checkboxDrawer:checkboxExpanded": "Onay kutusu genişletildi", // Read by screen readers when focusing the expanded (checked) checkbox, with the inner content shown
|
|
20
20
|
"components:navigation:back": "Geri",
|
|
21
|
-
"components:navigation:next": "
|
|
21
|
+
"components:navigation:next": "İleri",
|
|
22
22
|
"components:navigation:previous": "Önceki",
|
|
23
23
|
"components:navigation:skipNav": "ana içeriğe atla",
|
|
24
24
|
"components:optInFlyout:cancel": "İptal et",
|
package/src/lang/zh-cn.js
CHANGED
|
@@ -47,9 +47,9 @@ export default {
|
|
|
47
47
|
"components:pagination:nextPage": "下一页",
|
|
48
48
|
"components:pagination:previousPage": "上一页",
|
|
49
49
|
"components:pagination:resultsPerPage": "每页结果数",
|
|
50
|
-
"components:wizard:aria.steplabel": "
|
|
50
|
+
"components:wizard:aria.steplabel": "全部 {currentStep} 步中的 {totalSteps} 步",
|
|
51
51
|
"components:wizard:stepper.defaults.next": "Next",
|
|
52
|
-
"components:wizard:stepper.defaults.restart": "
|
|
53
|
-
"components:wizard:restart.button.tooltip": "
|
|
54
|
-
"components:wizard:next.button.tooltip": "
|
|
52
|
+
"components:wizard:stepper.defaults.restart": "重新开始",
|
|
53
|
+
"components:wizard:restart.button.tooltip": "返回第一步",
|
|
54
|
+
"components:wizard:next.button.tooltip": "继续下一步"
|
|
55
55
|
};
|
|
@@ -19,14 +19,22 @@ import ReactiveStore from '@brightspace-ui/labs/utilites/reactive-store.js';
|
|
|
19
19
|
class MyStore extends ReactiveStore {
|
|
20
20
|
static get properties() {
|
|
21
21
|
return {
|
|
22
|
-
|
|
22
|
+
count: { type: Number },
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
constructor() {
|
|
27
27
|
super();
|
|
28
28
|
|
|
29
|
-
this.
|
|
29
|
+
this.count = 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
increment() {
|
|
33
|
+
this.count++;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
decrement() {
|
|
37
|
+
this.count--;
|
|
30
38
|
}
|
|
31
39
|
}
|
|
32
40
|
|
|
@@ -56,15 +64,27 @@ class MyComponent extends LitElement {
|
|
|
56
64
|
render() {
|
|
57
65
|
// The consumer will have all the same properties defined in your store.
|
|
58
66
|
return html`
|
|
59
|
-
<div>
|
|
60
|
-
<button @click=${this.
|
|
67
|
+
<div>Count: ${this.myStoreConsumer.count}</div>
|
|
68
|
+
<button @click=${this._increment}>Increment</button>
|
|
69
|
+
<button @click=${this._decrement}>Decrement</button>
|
|
70
|
+
<button @click=${this._reset}>Reset</button>
|
|
61
71
|
`;
|
|
62
72
|
}
|
|
63
73
|
|
|
64
|
-
|
|
74
|
+
_reset() {
|
|
65
75
|
// Updating the values from the consumer will update the store, which will then
|
|
66
76
|
// notify all consumers of the changes and trigger component updates.
|
|
67
|
-
this.myStoreConsumer.
|
|
77
|
+
this.myStoreConsumer.count = 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
_increment() {
|
|
81
|
+
// You can access any method or property defined in the store, not just reactive properties.
|
|
82
|
+
this.myStoreConsumer.increment();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
_decrement() {
|
|
86
|
+
// You can access any method or property defined in the store, not just reactive properties.
|
|
87
|
+
this.myStoreConsumer.decrement();
|
|
68
88
|
}
|
|
69
89
|
}
|
|
70
90
|
|
|
@@ -86,14 +106,22 @@ import ReactiveStore from '@brightspace-ui/labs/utilites/reactive-store.js';
|
|
|
86
106
|
class MyStore extends ReactiveStore {
|
|
87
107
|
static get properties() {
|
|
88
108
|
return {
|
|
89
|
-
|
|
109
|
+
count: { type: Number },
|
|
90
110
|
};
|
|
91
111
|
}
|
|
92
112
|
|
|
93
113
|
constructor() {
|
|
94
114
|
super();
|
|
95
115
|
|
|
96
|
-
this.
|
|
116
|
+
this.count = 0;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
increment() {
|
|
120
|
+
this.count++;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
decrement() {
|
|
124
|
+
this.count--;
|
|
97
125
|
}
|
|
98
126
|
}
|
|
99
127
|
|
|
@@ -127,16 +155,28 @@ class MyComponent extends LitElement {
|
|
|
127
155
|
// The provider will have all the same properties defined in your store, so you can
|
|
128
156
|
// access your store data from the provider if you wish.
|
|
129
157
|
return html`
|
|
130
|
-
<div>
|
|
131
|
-
<button @click=${this.
|
|
158
|
+
<div>Count: ${this.myStoreProvider.count}</div>
|
|
159
|
+
<button @click=${this._increment}>Increment</button>
|
|
160
|
+
<button @click=${this._decrement}>Decrement</button>
|
|
161
|
+
<button @click=${this._reset}>Reset</button>
|
|
132
162
|
<my-descendant-component></my-descendant-component>
|
|
133
163
|
`;
|
|
134
164
|
}
|
|
135
165
|
|
|
136
|
-
|
|
166
|
+
_reset() {
|
|
137
167
|
// Updating the values from the provider will update the store, which will then
|
|
138
168
|
// notify all consumers of the changes and trigger component updates.
|
|
139
|
-
this.myStoreProvider.
|
|
169
|
+
this.myStoreProvider.count = 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
_increment() {
|
|
173
|
+
// You can access any method or property defined in the store, not just reactive properties.
|
|
174
|
+
this.myStoreProvider.increment();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
_decrement() {
|
|
178
|
+
// You can access any method or property defined in the store, not just reactive properties.
|
|
179
|
+
this.myStoreProvider.decrement();
|
|
140
180
|
}
|
|
141
181
|
}
|
|
142
182
|
|
|
@@ -162,16 +202,28 @@ class MyDescendantComponent extends LitElement {
|
|
|
162
202
|
render() {
|
|
163
203
|
// The consumer will have all the same properties defined in your store.
|
|
164
204
|
return html`
|
|
165
|
-
<div>
|
|
166
|
-
<button @click=${this.
|
|
205
|
+
<div>Count: ${this.myStoreConsumer.count}</div>
|
|
206
|
+
<button @click=${this._increment}>Increment</button>
|
|
207
|
+
<button @click=${this._decrement}>Decrement</button>
|
|
208
|
+
<button @click=${this._reset}>Reset</button>
|
|
167
209
|
`;
|
|
168
210
|
}
|
|
169
211
|
|
|
170
|
-
|
|
212
|
+
_reset() {
|
|
171
213
|
// Updating the values from the consumer will update the store, which will then
|
|
172
214
|
// notify all consumers of the changes and trigger component updates for all consumers and
|
|
173
215
|
// the provider as well.
|
|
174
|
-
this.myStoreConsumer.
|
|
216
|
+
this.myStoreConsumer.count = 0;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
_increment() {
|
|
220
|
+
// You can access any method or property defined in the store, not just reactive properties.
|
|
221
|
+
this.myStoreConsumer.increment();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
_decrement() {
|
|
225
|
+
// You can access any method or property defined in the store, not just reactive properties.
|
|
226
|
+
this.myStoreConsumer.decrement();
|
|
175
227
|
}
|
|
176
228
|
}
|
|
177
229
|
|
|
@@ -193,14 +245,14 @@ import ReactiveStore from '@brightspace-ui/labs/utilites/reactive-store.js';
|
|
|
193
245
|
class MyStore extends ReactiveStore {
|
|
194
246
|
static get properties() {
|
|
195
247
|
return {
|
|
196
|
-
|
|
248
|
+
count: { type: Number },
|
|
197
249
|
};
|
|
198
250
|
}
|
|
199
251
|
|
|
200
252
|
constructor() {
|
|
201
253
|
super();
|
|
202
254
|
|
|
203
|
-
this.
|
|
255
|
+
this.count = 0;
|
|
204
256
|
}
|
|
205
257
|
}
|
|
206
258
|
|
|
@@ -220,7 +272,7 @@ function handlePropertyChange({ property, value, prevValue }) {
|
|
|
220
272
|
myStore.subscribe(handlePropertyChange);
|
|
221
273
|
|
|
222
274
|
// When a store property is changed, any subscribed callback functions will be invoked synchronously
|
|
223
|
-
myStore.
|
|
275
|
+
myStore.count += 1; // console: The "count" property changed from 0 to 1
|
|
224
276
|
|
|
225
277
|
// Unsubscribe your callback function when you no longer want to receive store updates
|
|
226
278
|
myStore.unsubscribe(handlePropertyChange);
|
|
@@ -324,17 +376,19 @@ If the callback function passed in does not match a currently subscribed functio
|
|
|
324
376
|
|
|
325
377
|
This is the class that is returned by the `createConsumer()` instance method on an instance of the store.
|
|
326
378
|
|
|
327
|
-
This class is a [Lit Reactive Controller](https://lit.dev/docs/composition/controllers/) that when instantiated
|
|
379
|
+
This class is a [Lit Reactive Controller](https://lit.dev/docs/composition/controllers/) that when instantiated acts as a proxy for the originating store itself.
|
|
328
380
|
|
|
329
|
-
Any Consumer class instances will have access to all the same properties that the originating store does and will automatically trigger the update cycle on the host component whenever a property of the store changes.
|
|
381
|
+
Any Consumer class instances will have access to all the same properties and methods that the originating store does and will automatically trigger the update cycle on the host component whenever a reactive property of the store changes.
|
|
330
382
|
|
|
331
383
|
### Instance Properties
|
|
332
384
|
|
|
333
|
-
####
|
|
385
|
+
#### Proxied Properties and Methods
|
|
334
386
|
|
|
335
|
-
|
|
387
|
+
Since the Consumer acts as a proxy for the originating store, all properties and methods from the original store will also be accessible from the Consumer. The Consumer's properties will be directly connected to the corresponding properties on the originating store instance, so they can be used as if interacting with the store directly.
|
|
336
388
|
|
|
337
|
-
|
|
389
|
+
The proxied properties and methods includes methods on the `ReactiveStore` base class like `forceUpdate`, `subscribe`, `unsubscribe`, etc. However, any properties/methods that conflict with the properties/methods defined by the Consumer class itself (`changedProperties`, `hostDisconnected`, etc.) will be ignored.
|
|
390
|
+
|
|
391
|
+
Since updating a reactive property on the Consumer is the same as setting it on the store, updating a reactive property will notify all consumers of changes and, in turn, all consumers will then trigger the update cycle for their respective host components.
|
|
338
392
|
|
|
339
393
|
#### `changedProperties`
|
|
340
394
|
|
|
@@ -356,10 +410,6 @@ The constructor for the Consumer class accepts the following parameters:
|
|
|
356
410
|
|---|---|---|---|
|
|
357
411
|
| `host` | LitElement | The host Lit element that the Consumer is to be connected to. | True |
|
|
358
412
|
|
|
359
|
-
#### `forceUpdate()`
|
|
360
|
-
|
|
361
|
-
This method can be used to call the originating store's own `forceUpdate()` method, which will trigger an update for all consumer host components. See the store's `forceUpdate()` definition for additional details.
|
|
362
|
-
|
|
363
413
|
## The context `Provider` class
|
|
364
414
|
|
|
365
415
|
The context `Provider` class is one of the two [Lit Reactive Controllers](https://lit.dev/docs/composition/controllers/) returned by the `createContextControllers()` static method. The context `Consumer` class is the other controller returned and both of these act as a pair. Both of these controllers also have ther functionality tied to the specific store class you used to generate them.
|
|
@@ -370,11 +420,13 @@ This class is based on (and internally uses) the `ContextProvider` class from Li
|
|
|
370
420
|
|
|
371
421
|
### Instance Properties
|
|
372
422
|
|
|
373
|
-
####
|
|
423
|
+
#### Proxied Properties and Methods
|
|
424
|
+
|
|
425
|
+
The context `Provider` acts as a proxy for the originating store, which means that all properties and methods from the original store will also be accessible from the `Provider`. The `Provider`'s properties will be directly connected to the corresponding properties on the originating store instance, so they can be used as if interacting with the store directly.
|
|
374
426
|
|
|
375
|
-
|
|
427
|
+
The proxied properties and methods includes methods on the `ReactiveStore` base class like `forceUpdate`, `subscribe`, `unsubscribe`, etc. However, any properties/methods that conflict with the properties/methods defined by the `Provider` class itself (`changedProperties`, `hostDisconnected`, etc.) will be ignored.
|
|
376
428
|
|
|
377
|
-
|
|
429
|
+
Since updating a reactive property on the `Provider` is the same as setting it on the store, updating a reactive property will notify the `Provider` and all descendant `Consumer` instances of changes and, in turn, the `Provider` and `Consumer` instances will then trigger the update cycle for their respective host components.
|
|
378
430
|
|
|
379
431
|
#### `changedProperties`
|
|
380
432
|
|
|
@@ -397,10 +449,6 @@ The constructor for the context `Provider` class accepts the following parameter
|
|
|
397
449
|
| `host` | LitElement instance | The host Lit element that the `Provider` is to be connected to. | True | |
|
|
398
450
|
| `store` | ReactiveStore instance | The instance of your store that you wish to provide to descendant context `Consumer` classes. Note that if no store instance is passed to this parameter, an instance of your store will be instantiated to be used. | True | `new StoreClass()` |
|
|
399
451
|
|
|
400
|
-
#### `forceUpdate()`
|
|
401
|
-
|
|
402
|
-
This method can be used to call the provided store's own `forceUpdate()` method, which will trigger an update for the `Provider`'s host component as well as all context `Consumer` host components. See the store's `forceUpdate()` definition for additional details.
|
|
403
|
-
|
|
404
452
|
## The context `Consumer` class
|
|
405
453
|
|
|
406
454
|
The context `Consumer` class is one of the two [Lit Reactive Controllers](https://lit.dev/docs/composition/controllers/) returned by the `createContextControllers()` static method. The context `Provider` class is the other controller returned and both of these act as a pair. Both of these controllers also have ther functionality tied to the specific store class you used to generate them.
|
|
@@ -413,11 +461,13 @@ This class is based on (and internally uses) the `ContextConsumer` class from Li
|
|
|
413
461
|
|
|
414
462
|
### Instance Properties
|
|
415
463
|
|
|
416
|
-
####
|
|
464
|
+
#### Proxied Properties and Methods
|
|
417
465
|
|
|
418
|
-
|
|
466
|
+
The context `Consumer` acts as a proxy for the originating store (which it receives from the `Provider` ancestor), which means that all properties and methods from the original store will also be accessible from the `Consumer`. The `Consumer`'s properties will be directly connected to the corresponding properties on the originating store instance, so they can be used as if interacting with the store directly.
|
|
419
467
|
|
|
420
|
-
|
|
468
|
+
The proxied properties and methods includes methods on the `ReactiveStore` base class like `forceUpdate`, `subscribe`, `unsubscribe`, etc. However, any properties/methods that conflict with the properties/methods defined by the `Consumer` class itself (`changedProperties`, `hostDisconnected`, etc.) will be ignored.
|
|
469
|
+
|
|
470
|
+
Since updating a reactive property on the `Consumer` is the same as setting it on the store, updating a reactive property will notify the `Provider` and all descendant `Consumer` instances of changes and, in turn, the `Provider` and `Consumer` instances will then trigger the update cycle for their respective host components.
|
|
421
471
|
|
|
422
472
|
#### `changedProperties`
|
|
423
473
|
|
|
@@ -438,7 +488,3 @@ The constructor for the context `Consumer` class accepts the following parameter
|
|
|
438
488
|
| Parameter Name | Type | Description | Required |
|
|
439
489
|
|---|---|---|---|
|
|
440
490
|
| `host` | LitElement instance | The host Lit element that the `Consumer` is to be connected to. | True |
|
|
441
|
-
|
|
442
|
-
#### `forceUpdate()`
|
|
443
|
-
|
|
444
|
-
This method can be used to call the provided store's own `forceUpdate()` method, which will trigger an update for the `Provider`'s host component as well as all context `Consumer` host components. See the store's `forceUpdate()` definition for additional details.
|
|
@@ -3,70 +3,59 @@ import {
|
|
|
3
3
|
ContextConsumer as LitContextConsumer,
|
|
4
4
|
ContextProvider as LitContextProvider
|
|
5
5
|
} from '@lit/context';
|
|
6
|
-
import
|
|
6
|
+
import StoreReactor from './store-reactor.js';
|
|
7
7
|
|
|
8
8
|
export class ContextProvider {
|
|
9
9
|
constructor(host, StoreClass, store = new StoreClass()) {
|
|
10
10
|
const { properties } = StoreClass;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const storeReactor = new StoreReactor(host, store, properties);
|
|
12
|
+
new LitContextProvider(host, {
|
|
13
13
|
context: createContext(StoreClass),
|
|
14
14
|
initialValue: store,
|
|
15
15
|
});
|
|
16
|
-
this._defineProperties(properties);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
get changedProperties() {
|
|
20
|
-
return this._storeConsumer.changedProperties;
|
|
21
|
-
}
|
|
22
16
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return
|
|
32
|
-
},
|
|
33
|
-
set(value) {
|
|
34
|
-
this._storeConsumer[property] = value;
|
|
17
|
+
return new Proxy(store, {
|
|
18
|
+
get(target, prop) {
|
|
19
|
+
if (prop in storeReactor) return storeReactor[prop];
|
|
20
|
+
return Reflect.get(target, prop);
|
|
21
|
+
},
|
|
22
|
+
set(target, prop, value) {
|
|
23
|
+
if (prop in storeReactor) {
|
|
24
|
+
storeReactor[prop] = value;
|
|
25
|
+
return true;
|
|
35
26
|
}
|
|
36
|
-
|
|
27
|
+
return Reflect.set(target, prop, value);
|
|
28
|
+
}
|
|
37
29
|
});
|
|
38
30
|
}
|
|
39
31
|
}
|
|
40
32
|
export class ContextConsumer {
|
|
41
33
|
constructor(host, StoreClass) {
|
|
42
34
|
const { properties } = StoreClass;
|
|
43
|
-
|
|
35
|
+
const target = {
|
|
36
|
+
store: {},
|
|
37
|
+
storeReactor: {},
|
|
38
|
+
};
|
|
39
|
+
new LitContextConsumer(host, {
|
|
44
40
|
context: createContext(StoreClass),
|
|
45
41
|
callback: (store) => {
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
target.store = store;
|
|
43
|
+
target.storeReactor = new StoreReactor(host, store, properties);
|
|
48
44
|
},
|
|
49
45
|
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
get changedProperties() {
|
|
53
|
-
return this._storeConsumer?.changedProperties;
|
|
54
|
-
}
|
|
55
46
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return
|
|
65
|
-
},
|
|
66
|
-
set(value) {
|
|
67
|
-
this._storeConsumer[property] = value;
|
|
47
|
+
return new Proxy(target, {
|
|
48
|
+
get({ store, storeReactor }, prop) {
|
|
49
|
+
if (prop in storeReactor) return storeReactor[prop];
|
|
50
|
+
return Reflect.get(store, prop);
|
|
51
|
+
},
|
|
52
|
+
set({ store, storeReactor }, prop, value) {
|
|
53
|
+
if (prop in storeReactor) {
|
|
54
|
+
storeReactor[prop] = value;
|
|
55
|
+
return true;
|
|
68
56
|
}
|
|
69
|
-
|
|
57
|
+
return Reflect.set(store, prop, value);
|
|
58
|
+
}
|
|
70
59
|
});
|
|
71
60
|
}
|
|
72
61
|
}
|
|
@@ -1,66 +1,21 @@
|
|
|
1
|
+
import StoreReactor from './store-reactor.js';
|
|
2
|
+
|
|
1
3
|
export default class StoreConsumer {
|
|
2
4
|
constructor(host, store, properties = store.constructor.properties) {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
forceUpdate() {
|
|
17
|
-
this._store.forceUpdate();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
hostDisconnected() {
|
|
21
|
-
this._store.unsubscribe(this._onPropertyChange);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
_defineProperties(properties) {
|
|
25
|
-
Object.keys(properties).forEach((property) => {
|
|
26
|
-
Object.defineProperty(this, property, {
|
|
27
|
-
get() {
|
|
28
|
-
return this._store[property];
|
|
29
|
-
},
|
|
30
|
-
set(value) {
|
|
31
|
-
this._store[property] = value;
|
|
5
|
+
const storeReactor = new StoreReactor(host, store, properties);
|
|
6
|
+
|
|
7
|
+
return new Proxy(store, {
|
|
8
|
+
get(target, prop) {
|
|
9
|
+
if (prop in storeReactor) return storeReactor[prop];
|
|
10
|
+
return Reflect.get(target, prop);
|
|
11
|
+
},
|
|
12
|
+
set(target, prop, value) {
|
|
13
|
+
if (prop in storeReactor) {
|
|
14
|
+
storeReactor[prop] = value;
|
|
15
|
+
return true;
|
|
32
16
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
_initializeChangedProperties(properties) {
|
|
38
|
-
let shouldUpdate = false;
|
|
39
|
-
Object.keys(properties).forEach((property) => {
|
|
40
|
-
if (this._store[property] === undefined) return;
|
|
41
|
-
|
|
42
|
-
this.changedProperties.set(property, undefined);
|
|
43
|
-
shouldUpdate = true;
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
if (!shouldUpdate) return;
|
|
47
|
-
|
|
48
|
-
this._host.requestUpdate();
|
|
49
|
-
this._host.updateComplete.then(() => {
|
|
50
|
-
this.changedProperties.clear();
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
_onPropertyChange({
|
|
55
|
-
property,
|
|
56
|
-
prevValue,
|
|
57
|
-
forceUpdate = false,
|
|
58
|
-
}) {
|
|
59
|
-
if (!forceUpdate && !this.changedProperties.has(property)) this.changedProperties.set(property, prevValue);
|
|
60
|
-
|
|
61
|
-
this._host.requestUpdate();
|
|
62
|
-
this._host.updateComplete.then(() => {
|
|
63
|
-
this.changedProperties.clear();
|
|
17
|
+
return Reflect.set(target, prop, value);
|
|
18
|
+
}
|
|
64
19
|
});
|
|
65
20
|
}
|
|
66
21
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export default class StoreReactor {
|
|
2
|
+
changedProperties;
|
|
3
|
+
|
|
4
|
+
constructor(host, store, properties = store.constructor.properties) {
|
|
5
|
+
this.#host = host;
|
|
6
|
+
this.#host.addController(this);
|
|
7
|
+
this.#store = store;
|
|
8
|
+
|
|
9
|
+
this.changedProperties = new Map();
|
|
10
|
+
|
|
11
|
+
this.#store.subscribe(this.#onPropertyChange);
|
|
12
|
+
|
|
13
|
+
this.#initializeChangedProperties(properties);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
hostDisconnected() {
|
|
17
|
+
this.#store.unsubscribe(this.#onPropertyChange);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#host;
|
|
21
|
+
#store;
|
|
22
|
+
|
|
23
|
+
#onPropertyChange = ({
|
|
24
|
+
property,
|
|
25
|
+
prevValue,
|
|
26
|
+
forceUpdate = false,
|
|
27
|
+
}) => {
|
|
28
|
+
if (!forceUpdate && !this.changedProperties.has(property)) this.changedProperties.set(property, prevValue);
|
|
29
|
+
|
|
30
|
+
this.#host.requestUpdate();
|
|
31
|
+
this.#host.updateComplete.then(() => {
|
|
32
|
+
this.changedProperties.clear();
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
#initializeChangedProperties(properties) {
|
|
37
|
+
let shouldUpdate = false;
|
|
38
|
+
Object.keys(properties).forEach((property) => {
|
|
39
|
+
if (this.#store[property] === undefined) return;
|
|
40
|
+
|
|
41
|
+
this.changedProperties.set(property, undefined);
|
|
42
|
+
shouldUpdate = true;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
if (!shouldUpdate) return;
|
|
46
|
+
|
|
47
|
+
this.#host.requestUpdate();
|
|
48
|
+
this.#host.updateComplete.then(() => {
|
|
49
|
+
this.changedProperties.clear();
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|