@brightspace-ui/labs 2.45.0 → 2.46.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 CHANGED
@@ -114,5 +114,5 @@
114
114
  "resize-observer-polyfill": "^1",
115
115
  "webvtt-parser": "^2"
116
116
  },
117
- "version": "2.45.0"
117
+ "version": "2.46.0"
118
118
  }
@@ -168,8 +168,10 @@ class MediaPlayer extends LocalizeLabsElement(RtlMixin(LitElement)) {
168
168
  }
169
169
 
170
170
  #d2l-labs-media-player-video-poster {
171
+ background-color: #000000;
171
172
  cursor: pointer;
172
- height: auto;
173
+ height: 100%;
174
+ object-fit: contain;
173
175
  position: absolute;
174
176
  width: 100%;
175
177
  z-index: 1;
@@ -2,7 +2,7 @@
2
2
 
3
3
  A simple data store that will automatically notify subscribers when any of its properties changes.
4
4
 
5
- It's designed to work as a state store for Lit based apps and mimics Lit's component class API.
5
+ It's designed to work as a state store for Lit based apps and mimics Lit's component class API, but it can just as easily support many non-Lit contexts.
6
6
 
7
7
  ## Usage Examples
8
8
 
@@ -400,15 +400,26 @@ This map serves a similar function to the `changedProperties` map that [Lit prov
400
400
 
401
401
  Note that `changedProperties` is unique for each instance of the Consumer class and is explicitly tied to the hosting component's update cycle.
402
402
 
403
+ #### `dependentProperties`
404
+
405
+ A Set containing all the property names of the properties that the Consumer instance is watching for changes. This Set can be modified in order to specify which property changes from the store actually trigger a re-render. The host component will only re-render if one or more of the properties named in this Set change.
406
+
407
+ By default, this Set will initialize with all properties from the store. However, if the Consumer's `detectDependentProperties` option is set to true, this Set will initialize with no properties.
408
+
409
+ Additionally, the initial properties in this Set can be overriden by using the Consumer's `dependentProperties` option.
410
+
403
411
  ### Instance Methods
404
412
 
405
- #### `constructor(host)`
413
+ #### `constructor(host, options = {})`
406
414
 
407
415
  The constructor for the Consumer class accepts the following parameters:
408
416
 
409
- | Parameter Name | Type | Description | Required |
410
- |---|---|---|---|
411
- | `host` | LitElement | The host Lit element that the Consumer is to be connected to. | True |
417
+ | Parameter Name | Type | Description | Required | Default Value |
418
+ |---|---|---|---|---|
419
+ | `host` | LitElement | The host Lit element that the Consumer is to be connected to. | True | |
420
+ | `options` | Object | An object containing various initialization options. | False | `{}` |
421
+ | `options.dependentProperties` | Array | An array of strings where each string is the name of a property from the store. Each property listed here will be used to initialize the Consumer instance's `dependentProperties` Set. | False | If the `detectDependentProperties` option is set to false, this array will defult with all properties from the store. Otherwise, this array will default to an empty array. |
422
+ | `options.detectDependentProperties` | Boolean | If this options is set to true, store properties will be automatically added to the `dependentProperties` Set whenever they're accessed through their corresponding getter or setter on the Consumer instance. | False | `false` |
412
423
 
413
424
  ## The context `Provider` class
414
425
 
@@ -438,16 +449,27 @@ This map serves a similar function to the `changedProperties` map that [Lit prov
438
449
 
439
450
  Note that `changedProperties` is unique for each instance of the `Provider` class and is explicitly tied to the hosting component's update cycle.
440
451
 
452
+ #### `dependentProperties`
453
+
454
+ A Set containing all the property names of the properties that the context `Provider` instance is watching for changes. This Set can be modified in order to specify which property changes from the store actually trigger a re-render. The host component will only re-render if one or more of the properties named in this Set change.
455
+
456
+ By default, this Set will initialize with all properties from the store. However, if the context `Provider`'s `detectDependentProperties` option is set to true, this Set will initialize with no properties.
457
+
458
+ Additionally, the initial properties in this Set can be overriden by using the context `Provider`'s `dependentProperties` option.
459
+
441
460
  ### Instance Methods
442
461
 
443
- #### `constructor(host, store = new StoreClass())`
462
+ #### `constructor(host, options = {})`
444
463
 
445
464
  The constructor for the context `Provider` class accepts the following parameters:
446
465
 
447
466
  | Parameter Name | Type | Description | Required | Default Value |
448
467
  |---|---|---|---|---|
449
468
  | `host` | LitElement instance | The host Lit element that the `Provider` is to be connected to. | True | |
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()` |
469
+ | `options` | Object | An object containing various initialization options. | False | `{}` |
470
+ | `options.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. | False | `new StoreClass()` |
471
+ | `options.dependentProperties` | Array | An array of strings where each string is the name of a property from the store. Each property listed here will be used to initialize the context `Provider` instance's `dependentProperties` Set. | False | If the `detectDependentProperties` option is set to false, this array will defult with all properties from the store. Otherwise, this array will default to an empty array. |
472
+ | `options.detectDependentProperties` | Boolean | If this options is set to true, store properties will be automatically added to the `dependentProperties` Set whenever they're accessed through their corresponding getter or setter on the context `Provider` instance. | False | `false` |
451
473
 
452
474
  ## The context `Consumer` class
453
475
 
@@ -479,12 +501,23 @@ This map serves a similar function to the `changedProperties` map that [Lit prov
479
501
 
480
502
  Note that `changedProperties` is unique for each instance of the context `Consumer` class and is explicitly tied to the hosting component's update cycle.
481
503
 
504
+ #### `dependentProperties`
505
+
506
+ A Set containing all the property names of the properties that the context `Consumer` instance is watching for changes. This Set can be modified in order to specify which property changes from the store actually trigger a re-render. The host component will only re-render if one or more of the properties named in this Set change.
507
+
508
+ By default, this Set will initialize with all properties from the store. However, if the context `Consumer`'s `detectDependentProperties` option is set to true, this Set will initialize with no properties.
509
+
510
+ Additionally, the initial properties in this Set can be overriden by using the context `Consumer`'s `dependentProperties` option.
511
+
482
512
  ### Instance Methods
483
513
 
484
514
  #### `constructor(host)`
485
515
 
486
516
  The constructor for the context `Consumer` class accepts the following parameters:
487
517
 
488
- | Parameter Name | Type | Description | Required |
489
- |---|---|---|---|
490
- | `host` | LitElement instance | The host Lit element that the `Consumer` is to be connected to. | True |
518
+ | Parameter Name | Type | Description | Required | Default value |
519
+ |---|---|---|---|---|
520
+ | `host` | LitElement instance | The host Lit element that the `Consumer` is to be connected to. | True | |
521
+ | `options` | Object | An object containing various initialization options. | False | `{}` |
522
+ | `options.dependentProperties` | Array | An array of strings where each string is the name of a property from the store. Each property listed here will be used to initialize the context `Consumer` instance's `dependentProperties` Set. | False | If the `detectDependentProperties` option is set to false, this array will defult with all properties from the store. Otherwise, this array will default to an empty array. |
523
+ | `options.detectDependentProperties` | Boolean | If this options is set to true, store properties will be automatically added to the `dependentProperties` Set whenever they're accessed through their corresponding getter or setter on the context `Consumer` instance. | False | `false` |
@@ -7,9 +7,19 @@ import { combinedPropertiesSymbol } from './constants.js';
7
7
  import StoreReactor from './store-reactor.js';
8
8
 
9
9
  export class ContextProvider {
10
- constructor(host, StoreClass, store = new StoreClass()) {
10
+ constructor(host, StoreClass, options = {}) {
11
+ const {
12
+ detectDependentProperties = false,
13
+ dependentProperties = detectDependentProperties ? [] : undefined,
14
+ store = new StoreClass(),
15
+ ...restOptions
16
+ } = options;
17
+
11
18
  const properties = StoreClass[combinedPropertiesSymbol];
12
- const storeReactor = new StoreReactor(host, store, properties);
19
+ const storeReactor = new StoreReactor(host, store, {
20
+ dependentProperties,
21
+ ...restOptions,
22
+ });
13
23
  new LitContextProvider(host, {
14
24
  context: createContext(StoreClass),
15
25
  initialValue: store,
@@ -18,6 +28,10 @@ export class ContextProvider {
18
28
  return new Proxy(store, {
19
29
  get(target, prop) {
20
30
  if (prop in storeReactor) return storeReactor[prop];
31
+
32
+ if (detectDependentProperties && prop in properties)
33
+ storeReactor.dependentProperties.add(prop);
34
+
21
35
  return Reflect.get(target, prop);
22
36
  },
23
37
  set(target, prop, value) {
@@ -25,13 +39,23 @@ export class ContextProvider {
25
39
  storeReactor[prop] = value;
26
40
  return true;
27
41
  }
42
+
43
+ if (detectDependentProperties && prop in properties)
44
+ storeReactor.dependentProperties.add(prop);
45
+
28
46
  return Reflect.set(target, prop, value);
29
47
  }
30
48
  });
31
49
  }
32
50
  }
33
51
  export class ContextConsumer {
34
- constructor(host, StoreClass) {
52
+ constructor(host, StoreClass, options = {}) {
53
+ const {
54
+ detectDependentProperties = false,
55
+ dependentProperties = detectDependentProperties ? [] : undefined,
56
+ ...restOptions
57
+ } = options;
58
+
35
59
  const properties = StoreClass[combinedPropertiesSymbol];
36
60
  const target = {
37
61
  store: {},
@@ -41,13 +65,20 @@ export class ContextConsumer {
41
65
  context: createContext(StoreClass),
42
66
  callback: (store) => {
43
67
  target.store = store;
44
- target.storeReactor = new StoreReactor(host, store, properties);
68
+ target.storeReactor = new StoreReactor(host, store, {
69
+ dependentProperties,
70
+ ...restOptions,
71
+ });
45
72
  },
46
73
  });
47
74
 
48
75
  return new Proxy(target, {
49
76
  get({ store, storeReactor }, prop) {
50
77
  if (prop in storeReactor) return storeReactor[prop];
78
+
79
+ if (detectDependentProperties && prop in properties)
80
+ storeReactor.dependentProperties.add(prop);
81
+
51
82
  return Reflect.get(store, prop);
52
83
  },
53
84
  set({ store, storeReactor }, prop, value) {
@@ -55,6 +86,10 @@ export class ContextConsumer {
55
86
  storeReactor[prop] = value;
56
87
  return true;
57
88
  }
89
+
90
+ if (detectDependentProperties && prop in properties)
91
+ storeReactor.dependentProperties.add(prop);
92
+
58
93
  return Reflect.set(store, prop, value);
59
94
  }
60
95
  });
@@ -64,13 +99,13 @@ export class ContextConsumer {
64
99
  export function createContextControllers(StoreClass) {
65
100
  return {
66
101
  Provider: class extends ContextProvider {
67
- constructor(host, store = new StoreClass()) {
68
- super(host, StoreClass, store);
102
+ constructor(host, options) {
103
+ super(host, StoreClass, options);
69
104
  }
70
105
  },
71
106
  Consumer: class extends ContextConsumer {
72
- constructor(host) {
73
- super(host, StoreClass);
107
+ constructor(host, options) {
108
+ super(host, StoreClass, options);
74
109
  }
75
110
  },
76
111
  };
@@ -24,8 +24,8 @@ export default class ReactiveStore {
24
24
  createConsumer() {
25
25
  const store = this;
26
26
  return class extends StoreConsumer {
27
- constructor(host) {
28
- super(host, store);
27
+ constructor(host, options) {
28
+ super(host, store, options);
29
29
  }
30
30
  };
31
31
  }
@@ -2,12 +2,26 @@ import { combinedPropertiesSymbol } from './constants.js';
2
2
  import StoreReactor from './store-reactor.js';
3
3
 
4
4
  export default class StoreConsumer {
5
- constructor(host, store, properties = store.constructor[combinedPropertiesSymbol]) {
6
- const storeReactor = new StoreReactor(host, store, properties);
5
+ constructor(host, store, options = {}) {
6
+ const {
7
+ detectDependentProperties = false,
8
+ dependentProperties = detectDependentProperties ? [] : undefined,
9
+ ...restOptions
10
+ } = options;
11
+
12
+ const properties = store.constructor[combinedPropertiesSymbol];
13
+ const storeReactor = new StoreReactor(host, store, {
14
+ dependentProperties,
15
+ ...restOptions,
16
+ });
7
17
 
8
18
  return new Proxy(store, {
9
19
  get(target, prop) {
10
20
  if (prop in storeReactor) return storeReactor[prop];
21
+
22
+ if (detectDependentProperties && prop in properties)
23
+ storeReactor.dependentProperties.add(prop);
24
+
11
25
  return Reflect.get(target, prop);
12
26
  },
13
27
  set(target, prop, value) {
@@ -15,6 +29,10 @@ export default class StoreConsumer {
15
29
  storeReactor[prop] = value;
16
30
  return true;
17
31
  }
32
+
33
+ if (detectDependentProperties && prop in properties)
34
+ storeReactor.dependentProperties.add(prop);
35
+
18
36
  return Reflect.set(target, prop, value);
19
37
  }
20
38
  });
@@ -3,11 +3,18 @@ import { combinedPropertiesSymbol } from './constants.js';
3
3
  export default class StoreReactor {
4
4
  changedProperties;
5
5
 
6
- constructor(host, store, properties = store.constructor[combinedPropertiesSymbol]) {
6
+ constructor(host, store, options = {}) {
7
7
  this.#host = host;
8
8
  this.#host.addController(this);
9
9
  this.#store = store;
10
10
 
11
+ const properties = store.constructor[combinedPropertiesSymbol];
12
+
13
+ const {
14
+ dependentProperties = Object.keys(properties),
15
+ } = options;
16
+
17
+ this.dependentProperties = new Set(dependentProperties);
11
18
  this.changedProperties = new Map();
12
19
 
13
20
  this.#store.subscribe(this.#onPropertyChange);
@@ -27,12 +34,13 @@ export default class StoreReactor {
27
34
  prevValue,
28
35
  forceUpdate = false,
29
36
  }) => {
30
- if (!forceUpdate && !this.changedProperties.has(property)) this.changedProperties.set(property, prevValue);
37
+ if (forceUpdate) return this.#requestUpdate();
31
38
 
32
- this.#host.requestUpdate();
33
- this.#host.updateComplete.then(() => {
34
- this.changedProperties.clear();
35
- });
39
+ // If the property has changed multiple times within the same update cycle, we want to
40
+ // preserve the value from before the first change.
41
+ if (!this.changedProperties.has(property)) this.changedProperties.set(property, prevValue);
42
+
43
+ if (this.dependentProperties.has(property)) this.#requestUpdate();
36
44
  };
37
45
 
38
46
  #initializeChangedProperties(properties) {
@@ -41,11 +49,16 @@ export default class StoreReactor {
41
49
  if (this.#store[property] === undefined) return;
42
50
 
43
51
  this.changedProperties.set(property, undefined);
44
- shouldUpdate = true;
52
+
53
+ if (this.dependentProperties.has(property)) {
54
+ shouldUpdate = true;
55
+ }
45
56
  });
46
57
 
47
- if (!shouldUpdate) return;
58
+ if (shouldUpdate) this.#requestUpdate();
59
+ }
48
60
 
61
+ #requestUpdate() {
49
62
  this.#host.requestUpdate();
50
63
  this.#host.updateComplete.then(() => {
51
64
  this.changedProperties.clear();