@brightspace-ui/core 2.105.0 → 2.106.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.
@@ -169,7 +169,7 @@ class ListDemoNested extends LitElement {
169
169
 
170
170
  _renderList(items, nested, includeControls = false, showLoadMore = false) {
171
171
  return html`
172
- <d2l-list ?grid="${!this.disableListGrid}" drag-multiple slot="${ifDefined(nested ? 'nested' : undefined)}">
172
+ <d2l-list ?grid="${!this.disableListGrid}" drag-multiple slot="${ifDefined(nested ? 'nested' : undefined)}" item-count="${this._items.length}">
173
173
  ${ includeControls ? this._renderListControls() : nothing }
174
174
  ${repeat(items, item => item.key, item => html`
175
175
  ${this._renderListItem(item)}
@@ -268,7 +268,6 @@ class ListDemoNested extends LitElement {
268
268
  <d2l-pager-load-more slot="pager"
269
269
  @d2l-pager-load-more="${this._handlePagerLoadMore}"
270
270
  ?has-more="${this._lastItemLoadedIndex < this._items.length - 1}"
271
- item-count="${this._items.length}"
272
271
  page-size="${this._remainingItemCount < this._pageSize ? this._remainingItemCount : this._pageSize}">
273
272
  </d2l-pager-load-more>
274
273
  `;
@@ -201,7 +201,6 @@ class DemoList extends LitElement {
201
201
  <d2l-pager-load-more slot="pager"
202
202
  @d2l-pager-load-more="${this._handlePagerLoadMore}"
203
203
  ?has-more="${this._lastItemLoadedIndex < this.items.length - 1}"
204
- item-count="${this.items.length}"
205
204
  page-size="${remainingItemCount < this._pageSize ? remainingItemCount : this._pageSize}">
206
205
  </d2l-pager-load-more>
207
206
  </d2l-list>
@@ -64,8 +64,6 @@ class List extends PageableMixin(SelectionMixin(LitElement)) {
64
64
  this.dragMultiple = false;
65
65
  this.extendSeparators = false;
66
66
  this.grid = false;
67
- this._itemsShowingCount = 0;
68
- this._itemsShowingTotalCount = 0;
69
67
  this._listItemChanges = [];
70
68
  this._childHasExpandCollapseToggle = false;
71
69
 
@@ -77,7 +75,7 @@ class List extends PageableMixin(SelectionMixin(LitElement)) {
77
75
 
78
76
  connectedCallback() {
79
77
  super.connectedCallback();
80
- this.addEventListener('d2l-list-items-showing-count-change', this._handleListItemsShowingCountChange);
78
+ this.addEventListener('d2l-list-item-showing-count-change', this._handleListItemShowingCountChange);
81
79
  this.addEventListener('d2l-list-item-nested-change', (e) => this._handleListIemNestedChange(e));
82
80
  }
83
81
 
@@ -190,13 +188,8 @@ class List extends PageableMixin(SelectionMixin(LitElement)) {
190
188
  return items[index];
191
189
  }
192
190
 
193
- async _getItemsShowingCount() {
194
- if (this.slot === 'nested') return this._itemsShowingCount;
195
- else return this._getListItemsShowingTotalCount(false);
196
- }
197
-
198
- _getLastItemIndex() {
199
- return this._itemsShowingCount - 1;
191
+ _getItemShowingCount() {
192
+ return this.getItems().length;
200
193
  }
201
194
 
202
195
  _getLazyLoadItems() {
@@ -204,13 +197,6 @@ class List extends PageableMixin(SelectionMixin(LitElement)) {
204
197
  return items.length > 0 ? items[0]._getFlattenedListItems().lazyLoadListItems : new Map();
205
198
  }
206
199
 
207
- async _getListItemsShowingTotalCount(refresh) {
208
- if (refresh) {
209
- this._itemsShowingTotalCount = this.getItems().length;
210
- }
211
- return this._itemsShowingTotalCount;
212
- }
213
-
214
200
  _handleKeyDown(e) {
215
201
  if (!this.grid || this.slot === 'nested' || e.keyCode !== keyCodes.TAB) return;
216
202
  e.preventDefault();
@@ -236,33 +222,26 @@ class List extends PageableMixin(SelectionMixin(LitElement)) {
236
222
  this._listChildrenUpdatedSubscribers.updateSubscribers();
237
223
  }
238
224
 
239
- _handleListItemsShowingCountChange() {
225
+ _handleListItemShowingCountChange() {
240
226
  if (this.slot === 'nested') return;
241
227
 
242
228
  // debounce the updates for first render case
243
- if (this._updateItemsShowingTotalCountRequested) return;
244
-
245
- this._updateItemsShowingTotalCountRequested = true;
246
- setTimeout(async() => {
247
- const oldCount = this._itemsShowingTotalCount;
248
- const newCount = await this._getListItemsShowingTotalCount(true);
249
- if (oldCount !== newCount) this._updatePagerCount(newCount);
250
- this._updateItemsShowingTotalCountRequested = false;
229
+ if (this._updateItemShowingCountRequested) return;
230
+
231
+ this._updateItemShowingCountRequested = true;
232
+ setTimeout(() => {
233
+ this._updateItemShowingCount();
234
+ this._updateItemShowingCountRequested = false;
251
235
  }, 0);
252
236
  }
253
237
 
254
- async _handleSlotChange(e) {
255
- const items = this.getItems(e.target);
256
- if (this._itemsShowingCount === items.length) return;
257
- this._itemsShowingCount = items.length;
258
-
259
- this._updatePagerCount(await this._getListItemsShowingTotalCount(true));
238
+ _handleSlotChange() {
239
+ this._updateItemShowingCount();
260
240
 
261
241
  /** @ignore */
262
- this.dispatchEvent(new CustomEvent('d2l-list-items-showing-count-change', {
242
+ this.dispatchEvent(new CustomEvent('d2l-list-item-showing-count-change', {
263
243
  bubbles: true,
264
- composed: true,
265
- detail: { count: this._itemsShowingCount }
244
+ composed: true
266
245
  }));
267
246
  }
268
247
 
@@ -7,16 +7,9 @@ The paging components and mixins can be used to provide consistent paging functi
7
7
  <script type="module">
8
8
  import '@brightspace-ui/core/components/paging/pager-load-more.js';
9
9
  </script>
10
- <d2l-pager-load-more has-more page-size="3" item-count="15"></d2l-pager-load-more>
10
+ <d2l-pager-load-more has-more page-size="3"></d2l-pager-load-more>
11
11
  ```
12
12
 
13
- ## Best Practices
14
- <!-- docs: start best practices -->
15
- <!-- docs: start dos -->
16
- * Consider the performance impact of acquiring the optional total `item-count`. The `item-count` provides useful context for the user, but counting large numbers of rows can be detrimental to performance. As a very general guide, when the total number of rows that needs to be counted is < 50,000, it's not a performance concern.
17
- <!-- docs: end dos -->
18
- <!-- docs: end best practices -->
19
-
20
13
  ## Load More Paging [d2l-pager-load-more]
21
14
 
22
15
  The `d2l-pager-load-more` component can be used in conjunction with pageable components such as `d2l-list` to provide load-more paging functionality. The pager will dispatch the `d2l-pager-load-more` when clicked, and then the consumer handles the event by loading more items, updating the pager state, and signalling completion by calling `complete()` on the event detail. Focus will be automatically moved on the first new item once complete.
@@ -24,10 +17,10 @@ The `d2l-pager-load-more` component can be used in conjunction with pageable com
24
17
  See [Pageable Lists](../../components/list/#pageable-lists).
25
18
 
26
19
  ```html
27
- <d2l-list>
20
+ <d2l-list item-count="85">
28
21
  <d2l-list-item ...></d2l-list-item>
29
22
  <d2l-list-item ...></d2l-list-item>
30
- <d2l-pager-load-more slot="pager" has-more page-size="10" item-count="85"></d2l-pager-load-more>
23
+ <d2l-pager-load-more slot="pager" has-more page-size="10"></d2l-pager-load-more>
31
24
  </d2l-list>
32
25
  ```
33
26
 
@@ -44,7 +37,6 @@ pager.addEventListener('d2l-pager-load-more', e => {
44
37
  | Property | Type | Description |
45
38
  |---|---|---|
46
39
  | `has-more` | Boolean, default: `false` | Whether there are more items that can be loaded. |
47
- | `item-count` | Number | Total number of items. If not specified, neither it nor the count of items showing will be displayed. |
48
40
  | `page-size` | Number, default: 50 | The number of additional items to load. |
49
41
 
50
42
  ### Events
@@ -27,12 +27,12 @@
27
27
 
28
28
  <d2l-demo-snippet>
29
29
  <template>
30
- <d2l-test-pageable>
30
+ <d2l-test-pageable item-count="12">
31
31
  <ul>
32
32
  <li><a href="https://some-website">item 1</a></li>
33
33
  <li><a href="https://some-website">item 2</a></li>
34
34
  </ul>
35
- <d2l-pager-load-more id="pager1" slot="pager" has-more page-size="3" item-count="12"></d2l-pager-load-more>
35
+ <d2l-pager-load-more id="pager1" slot="pager" has-more page-size="3"></d2l-pager-load-more>
36
36
  </d2l-test-pageable>
37
37
  <script>
38
38
  document.querySelector('#pager1').addEventListener('d2l-pager-load-more', window.handleLoadMore);
@@ -1,35 +1,62 @@
1
+ import { CollectionMixin } from '../../mixins/collection/collection-mixin.js';
1
2
  import { html } from 'lit';
3
+ import { SubscriberRegistryController } from '../../controllers/subscriber/subscriberControllers.js';
2
4
 
3
- export const PageableMixin = superclass => class extends superclass {
5
+ export const PageableMixin = superclass => class extends CollectionMixin(superclass) {
6
+
7
+ static get properties() {
8
+ return {
9
+ _itemShowingCount: { state: true },
10
+ };
11
+ }
4
12
 
5
13
  constructor() {
6
14
  super();
7
- this._pageable = true;
15
+
16
+ this._itemShowingCount = 0;
17
+ this._pageableSubscriberRegistry = new SubscriberRegistryController(this, 'pageable', {
18
+ onSubscribe: this._updatePageableSubscriber.bind(this),
19
+ updateSubscribers: this._updatePageableSubscribers.bind(this)
20
+ });
8
21
  }
9
22
 
10
- /* must be implemented by consumer */
11
- _getItemByIndex(index) { } // eslint-disable-line no-unused-vars
23
+ firstUpdated(changedProperties) {
24
+ super.firstUpdated(changedProperties);
25
+ this._updateItemShowingCount();
26
+ }
27
+
28
+ updated(changedProperties) {
29
+ super.updated(changedProperties);
30
+
31
+ if (changedProperties.has('itemCount') || changedProperties.has('_itemShowingCount')) {
32
+ this._pageableSubscriberRegistry.updateSubscribers();
33
+ }
34
+ }
12
35
 
13
36
  /* must be implemented by consumer */
14
- async _getItemsShowingCount() { }
37
+ _getItemByIndex(index) { } // eslint-disable-line no-unused-vars
15
38
 
16
39
  /* must be implemented by consumer */
17
- _getLastItemIndex() { }
40
+ _getItemShowingCount() { }
18
41
 
19
- async _handlePagerSlotChange(e) {
20
- this._updatePagerCount(await this._getItemsShowingCount(), e.target);
42
+ _getLastItemIndex() {
43
+ return this._itemShowingCount - 1;
21
44
  }
22
45
 
23
46
  _renderPagerContainer() {
24
- return html`<slot name="pager" @slotchange="${this._handlePagerSlotChange}"></slot>`;
47
+ return html`<slot name="pager"></slot>`;
25
48
  }
26
49
 
27
- _updatePagerCount(count, slot) {
28
- if (!slot) slot = this.shadowRoot.querySelector('slot[name="pager"]');
29
- const elements = slot.assignedElements({ flatten: true });
30
- if (elements.length > 0) {
31
- elements[0].itemShowingCount = count;
32
- }
50
+ _updateItemShowingCount() {
51
+ this._itemShowingCount = this._getItemShowingCount();
52
+ }
53
+
54
+ _updatePageableSubscriber(subscriber) {
55
+ subscriber._pageableInfo = { itemShowingCount: this._itemShowingCount, itemCount: this.itemCount };
56
+ }
57
+
58
+ _updatePageableSubscribers(subscribers) {
59
+ subscribers.forEach(subscriber => this._updatePageableSubscriber(subscriber));
33
60
  }
34
61
 
35
62
  };
@@ -0,0 +1,33 @@
1
+ import { EventSubscriberController, IdSubscriberController } from '../../controllers/subscriber/subscriberControllers.js';
2
+
3
+ export const PageableSubscriberMixin = superclass => class extends superclass {
4
+
5
+ static get properties() {
6
+ return {
7
+ /**
8
+ * Id of the `PageableMixin` component this component wants to observe (if not located within that component)
9
+ * @type {string}
10
+ */
11
+ pageableFor: { type: String, reflect: true, attribute: 'pageable-for' },
12
+ _pageableInfo: { state: true }
13
+ };
14
+ }
15
+
16
+ constructor() {
17
+ super();
18
+
19
+ this._pageableInfo = { itemCount: null, itemShowingCount: 0 };
20
+ this._pageableEventSubscriber = new EventSubscriberController(this, 'pageable');
21
+ this._pageableIdSubscriber = new IdSubscriberController(this, 'pageable', { idPropertyName: 'pageableFor' });
22
+ }
23
+
24
+ async getUpdateComplete() {
25
+ await super.getUpdateComplete();
26
+ await (this.pageableFor ? this._pageableIdSubscriber._subscriptionComplete : this._pageableEventSubscriber._subscriptionComplete);
27
+ }
28
+
29
+ _getPageableRegistries() {
30
+ return this.pageableFor ? this._pageableIdSubscriber.registries : [ this._pageableEventSubscriber.registry ];
31
+ }
32
+
33
+ };
@@ -2,7 +2,6 @@ import '../colors/colors.js';
2
2
  import '../loading-spinner/loading-spinner.js';
3
3
  import { css, html, LitElement, nothing } from 'lit';
4
4
  import { buttonStyles } from '../button/button-styles.js';
5
- import { findComposedAncestor } from '../../helpers/dom.js';
6
5
  import { FocusMixin } from '../../mixins/focus/focus-mixin.js';
7
6
  import { formatNumber } from '@brightspace-ui/intl/lib/number.js';
8
7
  import { getFirstFocusableDescendant } from '../../helpers/focus.js';
@@ -10,6 +9,7 @@ import { getSeparator } from '@brightspace-ui/intl/lib/list.js';
10
9
  import { labelStyles } from '../typography/styles.js';
11
10
  import { LocalizeCoreElement } from '../../helpers/localize-core-element.js';
12
11
  import { offscreenStyles } from '../offscreen/offscreen.js';
12
+ import { PageableSubscriberMixin } from './pageable-subscriber-mixin.js';
13
13
 
14
14
  const nativeFocus = document.createElement('div').focus;
15
15
 
@@ -17,7 +17,7 @@ const nativeFocus = document.createElement('div').focus;
17
17
  * A pager component for load-more paging.
18
18
  * @fires d2l-pager-load-more - Dispatched when the user clicks the load-more button. Consumers must call the provided "complete" method once items have been loaded.
19
19
  */
20
- class LoadMore extends FocusMixin(LocalizeCoreElement(LitElement)) {
20
+ class LoadMore extends PageableSubscriberMixin(FocusMixin(LocalizeCoreElement(LitElement))) {
21
21
 
22
22
  static get properties() {
23
23
  return {
@@ -26,21 +26,11 @@ class LoadMore extends FocusMixin(LocalizeCoreElement(LitElement)) {
26
26
  * @type {boolean}
27
27
  */
28
28
  hasMore: { type: Boolean, attribute: 'has-more', reflect: true },
29
- /**
30
- * Total number of items. If not specified, neither it nor the count of items showing will be displayed.
31
- * @type {number}
32
- */
33
- itemCount: { type: Number, attribute: 'item-count', reflect: true },
34
29
  /**
35
30
  * The number of additional items to load.
36
31
  * @type {number}
37
32
  */
38
33
  pageSize: { type: Number, attribute: 'page-size', reflect: true },
39
- /**
40
- * The number of items showing. Assigned by PageableMixin.
41
- * @ignore
42
- */
43
- itemShowingCount: { attribute: false, type: Number },
44
34
  _loading: { state: true }
45
35
  };
46
36
  }
@@ -85,9 +75,8 @@ class LoadMore extends FocusMixin(LocalizeCoreElement(LitElement)) {
85
75
  constructor() {
86
76
  super();
87
77
  this.hasMore = false;
88
- this.itemCount = -1;
78
+
89
79
  /** @ignore */
90
- this.itemShowingCount = 0;
91
80
  this.pageSize = 50;
92
81
  this._loading = false;
93
82
  }
@@ -97,7 +86,9 @@ class LoadMore extends FocusMixin(LocalizeCoreElement(LitElement)) {
97
86
  }
98
87
 
99
88
  render() {
100
- if (!this.hasMore) return;
89
+ if (!this.hasMore) return nothing;
90
+ const { itemCount, itemShowingCount } = this._pageableInfo;
91
+
101
92
  return html`
102
93
  ${this._loading ? html`
103
94
  <span class="d2l-offscreen" role="alert">${this.localize('components.pager-load-more.status-loading')}</span>
@@ -107,10 +98,10 @@ class LoadMore extends FocusMixin(LocalizeCoreElement(LitElement)) {
107
98
  <d2l-loading-spinner size="24"></d2l-loading-spinner>
108
99
  ` : html`
109
100
  <span class="action">${this.localize('components.pager-load-more.action', { count: formatNumber(this.pageSize) })}</span>
110
- ${this.itemCount > -1 ? html`
101
+ ${itemCount !== null ? html`
111
102
  <span class="d2l-offscreen">${getSeparator({ nonBreaking: true })}</span>
112
103
  <span class="separator"></span>
113
- <span class="info">${this.localize('components.pager-load-more.info', { showingCount: formatNumber(this.itemShowingCount), totalCount: this.itemCount, totalCountFormatted: formatNumber(this.itemCount) })}</span>
104
+ <span class="info">${this.localize('components.pager-load-more.info', { showingCount: formatNumber(itemShowingCount), totalCount: itemCount, totalCountFormatted: formatNumber(itemCount) })}</span>
114
105
  ` : nothing}
115
106
  `}
116
107
  </button>
@@ -119,7 +110,7 @@ class LoadMore extends FocusMixin(LocalizeCoreElement(LitElement)) {
119
110
 
120
111
  async _handleClick() {
121
112
  if (this._loading) return;
122
- const pageable = findComposedAncestor(this, node => node._pageable);
113
+ const pageable = this._getPageableRegistries()[0];
123
114
  if (!pageable) return;
124
115
  const lastItemIndex = pageable._getLastItemIndex();
125
116
 
@@ -1,3 +1,4 @@
1
+ import { CollectionMixin } from '../../mixins/collection/collection-mixin.js';
1
2
  import { RtlMixin } from '../../mixins/rtl/rtl-mixin.js';
2
3
 
3
4
  const keyCodes = {
@@ -35,15 +36,10 @@ export class SelectionInfo {
35
36
 
36
37
  }
37
38
 
38
- export const SelectionMixin = superclass => class extends RtlMixin(superclass) {
39
+ export const SelectionMixin = superclass => class extends RtlMixin(CollectionMixin(superclass)) {
39
40
 
40
41
  static get properties() {
41
42
  return {
42
- /**
43
- * Total number of items. Required when selecting all pages is allowed.
44
- * @type {number}
45
- */
46
- itemCount: { type: Number, attribute: 'item-count' },
47
43
  /**
48
44
  * Whether to render with single selection behaviour. If `selection-single` is specified, the nested `d2l-selection-input` elements will render radios instead of checkboxes, and the selection component will maintain a single selected item.
49
45
  * @type {boolean}
@@ -59,7 +55,6 @@ export const SelectionMixin = superclass => class extends RtlMixin(superclass) {
59
55
 
60
56
  constructor() {
61
57
  super();
62
- this.itemCount = 0;
63
58
  this.selectionSingle = false;
64
59
  this._selectAllPages = false;
65
60
  this._selectionObservers = new Map();
@@ -9,6 +9,7 @@ class BaseController {
9
9
  this._name = name;
10
10
  this._options = options;
11
11
  this._eventName = `d2l-subscribe-${this._name}`;
12
+ this._subscriptionComplete = Promise.resolve();
12
13
  }
13
14
  }
14
15
 
@@ -111,7 +112,12 @@ export class EventSubscriberController extends BaseSubscriber {
111
112
 
112
113
  hostConnected() {
113
114
  // delay subscription otherwise import/upgrade order can cause selection mixin to miss event
114
- requestAnimationFrame(() => this._subscribe());
115
+ this._subscriptionComplete = new Promise(resolve => {
116
+ requestAnimationFrame(() => {
117
+ this._subscribe();
118
+ resolve();
119
+ });
120
+ });
115
121
  }
116
122
 
117
123
  hostDisconnected() {
@@ -8864,15 +8864,14 @@
8864
8864
  "default": "false"
8865
8865
  },
8866
8866
  {
8867
- "name": "selection-count-override",
8868
- "description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
8867
+ "name": "item-count",
8868
+ "description": "Total number of items. If not specified, features like select-all-pages will be disabled.",
8869
8869
  "type": "number"
8870
8870
  },
8871
8871
  {
8872
- "name": "item-count",
8873
- "description": "Total number of items. Required when selecting all pages is allowed.",
8874
- "type": "number",
8875
- "default": "0"
8872
+ "name": "selection-count-override",
8873
+ "description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
8874
+ "type": "number"
8876
8875
  },
8877
8876
  {
8878
8877
  "name": "selection-single",
@@ -8910,19 +8909,18 @@
8910
8909
  "type": "boolean",
8911
8910
  "default": "false"
8912
8911
  },
8912
+ {
8913
+ "name": "itemCount",
8914
+ "attribute": "item-count",
8915
+ "description": "Total number of items. If not specified, features like select-all-pages will be disabled.",
8916
+ "type": "number"
8917
+ },
8913
8918
  {
8914
8919
  "name": "selectionCountOverride",
8915
8920
  "attribute": "selection-count-override",
8916
8921
  "description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
8917
8922
  "type": "number"
8918
8923
  },
8919
- {
8920
- "name": "itemCount",
8921
- "attribute": "item-count",
8922
- "description": "Total number of items. Required when selecting all pages is allowed.",
8923
- "type": "number",
8924
- "default": "0"
8925
- },
8926
8924
  {
8927
8925
  "name": "selectionSingle",
8928
8926
  "attribute": "selection-single",
@@ -10059,6 +10057,11 @@
10059
10057
  "path": "./components/paging/pager-load-more.js",
10060
10058
  "description": "A pager component for load-more paging.",
10061
10059
  "attributes": [
10060
+ {
10061
+ "name": "page-size",
10062
+ "description": "The number of additional items to load.",
10063
+ "type": "number"
10064
+ },
10062
10065
  {
10063
10066
  "name": "has-more",
10064
10067
  "description": "Whether there are more items that can be loaded.",
@@ -10066,19 +10069,18 @@
10066
10069
  "default": "false"
10067
10070
  },
10068
10071
  {
10069
- "name": "item-count",
10070
- "description": "Total number of items. If not specified, neither it nor the count of items showing will be displayed.",
10071
- "type": "number",
10072
- "default": "-1"
10073
- },
10074
- {
10075
- "name": "page-size",
10076
- "description": "The number of additional items to load.",
10077
- "type": "number",
10078
- "default": "50"
10072
+ "name": "pageable-for",
10073
+ "description": "Id of the `PageableMixin` component this component wants to observe (if not located within that component)",
10074
+ "type": "string"
10079
10075
  }
10080
10076
  ],
10081
10077
  "properties": [
10078
+ {
10079
+ "name": "pageSize",
10080
+ "attribute": "page-size",
10081
+ "description": "The number of additional items to load.",
10082
+ "type": "number"
10083
+ },
10082
10084
  {
10083
10085
  "name": "hasMore",
10084
10086
  "attribute": "has-more",
@@ -10087,18 +10089,10 @@
10087
10089
  "default": "false"
10088
10090
  },
10089
10091
  {
10090
- "name": "itemCount",
10091
- "attribute": "item-count",
10092
- "description": "Total number of items. If not specified, neither it nor the count of items showing will be displayed.",
10093
- "type": "number",
10094
- "default": "-1"
10095
- },
10096
- {
10097
- "name": "pageSize",
10098
- "attribute": "page-size",
10099
- "description": "The number of additional items to load.",
10100
- "type": "number",
10101
- "default": "50"
10092
+ "name": "pageableFor",
10093
+ "attribute": "pageable-for",
10094
+ "description": "Id of the `PageableMixin` component this component wants to observe (if not located within that component)",
10095
+ "type": "string"
10102
10096
  },
10103
10097
  {
10104
10098
  "name": "documentLocaleSettings",
@@ -10114,7 +10108,41 @@
10114
10108
  },
10115
10109
  {
10116
10110
  "name": "d2l-test-pageable",
10117
- "path": "./components/paging/test/pageable-component.js"
10111
+ "path": "./components/paging/test/pageable-component.js",
10112
+ "attributes": [
10113
+ {
10114
+ "name": "item-count",
10115
+ "description": "Total number of items. If not specified, features like select-all-pages will be disabled.",
10116
+ "type": "number"
10117
+ }
10118
+ ],
10119
+ "properties": [
10120
+ {
10121
+ "name": "itemCount",
10122
+ "attribute": "item-count",
10123
+ "description": "Total number of items. If not specified, features like select-all-pages will be disabled.",
10124
+ "type": "number"
10125
+ }
10126
+ ]
10127
+ },
10128
+ {
10129
+ "name": "d2l-test-pageable-simple",
10130
+ "path": "./components/paging/test/pageable-component.js",
10131
+ "attributes": [
10132
+ {
10133
+ "name": "item-count",
10134
+ "description": "Total number of items. If not specified, features like select-all-pages will be disabled.",
10135
+ "type": "number"
10136
+ }
10137
+ ],
10138
+ "properties": [
10139
+ {
10140
+ "name": "itemCount",
10141
+ "attribute": "item-count",
10142
+ "description": "Total number of items. If not specified, features like select-all-pages will be disabled.",
10143
+ "type": "number"
10144
+ }
10145
+ ]
10118
10146
  },
10119
10147
  {
10120
10148
  "name": "d2l-test-scroll-wrapper",
@@ -10194,12 +10222,6 @@
10194
10222
  "description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
10195
10223
  "type": "number"
10196
10224
  },
10197
- {
10198
- "name": "item-count",
10199
- "description": "Total number of items. Required when selecting all pages is allowed.",
10200
- "type": "number",
10201
- "default": "0"
10202
- },
10203
10225
  {
10204
10226
  "name": "selection-single",
10205
10227
  "description": "Whether to render with single selection behaviour. If `selection-single` is specified, the nested `d2l-selection-input` elements will render radios instead of checkboxes, and the selection component will maintain a single selected item.",
@@ -10214,13 +10236,6 @@
10214
10236
  "description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
10215
10237
  "type": "number"
10216
10238
  },
10217
- {
10218
- "name": "itemCount",
10219
- "attribute": "item-count",
10220
- "description": "Total number of items. Required when selecting all pages is allowed.",
10221
- "type": "number",
10222
- "default": "0"
10223
- },
10224
10239
  {
10225
10240
  "name": "selectionSingle",
10226
10241
  "attribute": "selection-single",
@@ -10843,12 +10858,6 @@
10843
10858
  "description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
10844
10859
  "type": "number"
10845
10860
  },
10846
- {
10847
- "name": "item-count",
10848
- "description": "Total number of items. Required when selecting all pages is allowed.",
10849
- "type": "number",
10850
- "default": "0"
10851
- },
10852
10861
  {
10853
10862
  "name": "selection-single",
10854
10863
  "description": "Whether to render with single selection behaviour. If `selection-single` is specified, the nested `d2l-selection-input` elements will render radios instead of checkboxes, and the selection component will maintain a single selected item.",
@@ -10863,13 +10872,6 @@
10863
10872
  "description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
10864
10873
  "type": "number"
10865
10874
  },
10866
- {
10867
- "name": "itemCount",
10868
- "attribute": "item-count",
10869
- "description": "Total number of items. Required when selecting all pages is allowed.",
10870
- "type": "number",
10871
- "default": "0"
10872
- },
10873
10875
  {
10874
10876
  "name": "selectionSingle",
10875
10877
  "attribute": "selection-single",
@@ -11371,12 +11373,6 @@
11371
11373
  "description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
11372
11374
  "type": "number"
11373
11375
  },
11374
- {
11375
- "name": "item-count",
11376
- "description": "Total number of items. Required when selecting all pages is allowed.",
11377
- "type": "number",
11378
- "default": "0"
11379
- },
11380
11376
  {
11381
11377
  "name": "selection-single",
11382
11378
  "description": "Whether to render with single selection behaviour. If `selection-single` is specified, the nested `d2l-selection-input` elements will render radios instead of checkboxes, and the selection component will maintain a single selected item.",
@@ -11422,13 +11418,6 @@
11422
11418
  "description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
11423
11419
  "type": "number"
11424
11420
  },
11425
- {
11426
- "name": "itemCount",
11427
- "attribute": "item-count",
11428
- "description": "Total number of items. Required when selecting all pages is allowed.",
11429
- "type": "number",
11430
- "default": "0"
11431
- },
11432
11421
  {
11433
11422
  "name": "selectionSingle",
11434
11423
  "attribute": "selection-single",
@@ -11594,12 +11583,6 @@
11594
11583
  "description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
11595
11584
  "type": "number"
11596
11585
  },
11597
- {
11598
- "name": "item-count",
11599
- "description": "Total number of items. Required when selecting all pages is allowed.",
11600
- "type": "number",
11601
- "default": "0"
11602
- },
11603
11586
  {
11604
11587
  "name": "selection-single",
11605
11588
  "description": "Whether to render with single selection behaviour. If `selection-single` is specified, the nested `d2l-selection-input` elements will render radios instead of checkboxes, and the selection component will maintain a single selected item.",
@@ -11635,13 +11618,6 @@
11635
11618
  "description": "ADVANCED: Temporary optional parameter used to override existing count. Will be removed soon, use with caution.",
11636
11619
  "type": "number"
11637
11620
  },
11638
- {
11639
- "name": "itemCount",
11640
- "attribute": "item-count",
11641
- "description": "Total number of items. Required when selecting all pages is allowed.",
11642
- "type": "number",
11643
- "default": "0"
11644
- },
11645
11621
  {
11646
11622
  "name": "selectionSingle",
11647
11623
  "attribute": "selection-single",
@@ -0,0 +1,36 @@
1
+ # CollectionMixin
2
+
3
+ The `CollectionMixin` describes a collection of items like a list or table. It has one attribute, `item-count`, which optionally defines the total number of items in the collection. This may be greater than the number of items currently displayed, and is useful for actions like select-all and paging.
4
+
5
+ ## Best Practices
6
+ <!-- docs: start best practices -->
7
+ <!-- docs: start dos -->
8
+ * Consider the performance impact of acquiring the optional total `item-count`. The `item-count` provides useful context for the user, but counting large numbers of rows can be detrimental to performance. As a very general guide, when the total number of rows that needs to be counted is < 50,000, it's not a performance concern.
9
+ <!-- docs: end dos -->
10
+ <!-- docs: end best practices -->
11
+
12
+ ## Usage
13
+
14
+ Apply the mixin and access the `itemCount` property as needed. Note that `itemCount` has a default value of `null` to indicate that no count was specified.
15
+
16
+ ```js
17
+ import { CollectionMixin } from '@brightspace-ui/core/mixins/collection-mixin.js';
18
+
19
+ class MyComponent extends CollectionMixin(LitElement) {
20
+ render() {
21
+ const itemCountToDisplay = this.itemCount !== null ? this.itemCount : 'Unspecified';
22
+ return html`
23
+ <p>Total number of items: ${itemCountToDisplay}</p>
24
+ <slot></slot>
25
+ `;
26
+ }
27
+ }
28
+ ```
29
+
30
+ <!-- docs: start hidden content -->
31
+ ### Properties
32
+
33
+ | Property | Type | Description |
34
+ |---|---|---|
35
+ | `item-count` | Number | Total number of items. Required when selecting all pages is allowed. |
36
+ <!-- docs: end hidden content -->
@@ -0,0 +1,18 @@
1
+ export const CollectionMixin = superclass => class extends superclass {
2
+
3
+ static get properties() {
4
+ return {
5
+ /**
6
+ * Total number of items. If not specified, features like select-all-pages will be disabled.
7
+ * @type {number}
8
+ */
9
+ itemCount: { type: Number, attribute: 'item-count', reflect: true },
10
+ };
11
+ }
12
+
13
+ constructor() {
14
+ super();
15
+ this.itemCount = null;
16
+ }
17
+
18
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brightspace-ui/core",
3
- "version": "2.105.0",
3
+ "version": "2.106.0",
4
4
  "description": "A collection of accessible, free, open-source web components for building Brightspace applications",
5
5
  "type": "module",
6
6
  "repository": "https://github.com/BrightspaceUI/core.git",