@internetarchive/collection-browser 4.7.1-alpha-webdev9189.0 → 4.8.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 (87) hide show
  1. package/dist/src/app-root.js +0 -2
  2. package/dist/src/app-root.js.map +1 -1
  3. package/dist/src/assets/img/icons/check.d.ts +2 -0
  4. package/dist/src/assets/img/icons/check.js +5 -0
  5. package/dist/src/assets/img/icons/check.js.map +1 -0
  6. package/dist/src/collection-browser.js +2 -24
  7. package/dist/src/collection-browser.js.map +1 -1
  8. package/dist/src/collection-facets/facet-row-template.d.ts +38 -0
  9. package/dist/src/collection-facets/facet-row-template.js +200 -0
  10. package/dist/src/collection-facets/facet-row-template.js.map +1 -0
  11. package/dist/src/collection-facets/facet-row.js +11 -186
  12. package/dist/src/collection-facets/facet-row.js.map +1 -1
  13. package/dist/src/collection-facets/models.d.ts +7 -2
  14. package/dist/src/collection-facets/models.js +7 -2
  15. package/dist/src/collection-facets/models.js.map +1 -1
  16. package/dist/src/collection-facets/more-facets-content.d.ts +87 -21
  17. package/dist/src/collection-facets/more-facets-content.js +477 -200
  18. package/dist/src/collection-facets/more-facets-content.js.map +1 -1
  19. package/dist/src/collection-facets/more-facets-scroller.d.ts +85 -0
  20. package/dist/src/collection-facets/more-facets-scroller.js +428 -0
  21. package/dist/src/collection-facets/more-facets-scroller.js.map +1 -0
  22. package/dist/src/collection-facets/page-window.d.ts +73 -0
  23. package/dist/src/collection-facets/page-window.js +202 -0
  24. package/dist/src/collection-facets/page-window.js.map +1 -0
  25. package/dist/src/collection-facets/toggle-switch.js +1 -0
  26. package/dist/src/collection-facets/toggle-switch.js.map +1 -1
  27. package/dist/src/models.d.ts +4 -0
  28. package/dist/src/models.js +16 -0
  29. package/dist/src/models.js.map +1 -1
  30. package/dist/src/sort-filter-bar/sort-filter-bar.js +0 -1
  31. package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
  32. package/dist/src/utils/log.d.ts +1 -4
  33. package/dist/src/utils/normalize-filter-text.d.ts +28 -0
  34. package/dist/src/utils/normalize-filter-text.js +35 -0
  35. package/dist/src/utils/normalize-filter-text.js.map +1 -0
  36. package/dist/test/collection-browser.test.js +0 -34
  37. package/dist/test/collection-browser.test.js.map +1 -1
  38. package/dist/test/collection-facets/more-facets-content.test.js +367 -17
  39. package/dist/test/collection-facets/more-facets-content.test.js.map +1 -1
  40. package/dist/test/collection-facets/more-facets-scroller.test.d.ts +1 -0
  41. package/dist/test/collection-facets/more-facets-scroller.test.js +288 -0
  42. package/dist/test/collection-facets/more-facets-scroller.test.js.map +1 -0
  43. package/dist/test/collection-facets/page-window.test.d.ts +1 -0
  44. package/dist/test/collection-facets/page-window.test.js +175 -0
  45. package/dist/test/collection-facets/page-window.test.js.map +1 -0
  46. package/dist/test/mocks/mock-search-responses.d.ts +6 -0
  47. package/dist/test/mocks/mock-search-responses.js +52 -0
  48. package/dist/test/mocks/mock-search-responses.js.map +1 -1
  49. package/dist/test/mocks/mock-search-service.js +2 -1
  50. package/dist/test/mocks/mock-search-service.js.map +1 -1
  51. package/dist/test/sort-filter-bar/sort-filter-bar.test.js +0 -22
  52. package/dist/test/sort-filter-bar/sort-filter-bar.test.js.map +1 -1
  53. package/dist/test/utils/normalize-filter-text.test.d.ts +1 -0
  54. package/dist/test/utils/normalize-filter-text.test.js +69 -0
  55. package/dist/test/utils/normalize-filter-text.test.js.map +1 -0
  56. package/docs/design/column-virtualization.md +214 -0
  57. package/package.json +3 -1
  58. package/src/app-root.ts +0 -2
  59. package/src/assets/img/icons/check.ts +5 -0
  60. package/src/collection-browser.ts +4 -26
  61. package/src/collection-facets/facet-row-template.ts +242 -0
  62. package/src/collection-facets/facet-row.ts +15 -202
  63. package/src/collection-facets/models.ts +8 -2
  64. package/src/collection-facets/more-facets-content.ts +528 -221
  65. package/src/collection-facets/more-facets-scroller.ts +485 -0
  66. package/src/collection-facets/page-window.ts +247 -0
  67. package/src/collection-facets/toggle-switch.ts +1 -0
  68. package/src/models.ts +17 -0
  69. package/src/sort-filter-bar/sort-filter-bar.ts +0 -1
  70. package/src/utils/normalize-filter-text.ts +54 -0
  71. package/test/collection-browser.test.ts +0 -55
  72. package/test/collection-facets/more-facets-content.test.ts +509 -24
  73. package/test/collection-facets/more-facets-scroller.test.ts +401 -0
  74. package/test/collection-facets/page-window.test.ts +208 -0
  75. package/test/mocks/mock-search-responses.ts +56 -0
  76. package/test/mocks/mock-search-service.ts +2 -0
  77. package/test/sort-filter-bar/sort-filter-bar.test.ts +0 -29
  78. package/test/utils/normalize-filter-text.test.ts +87 -0
  79. package/web-test-runner.config.mjs +7 -2
  80. package/dist/src/collection-facets/more-facets-pagination.d.ts +0 -36
  81. package/dist/src/collection-facets/more-facets-pagination.js +0 -260
  82. package/dist/src/collection-facets/more-facets-pagination.js.map +0 -1
  83. package/dist/test/collection-facets/more-facets-pagination.test.d.ts +0 -1
  84. package/dist/test/collection-facets/more-facets-pagination.test.js +0 -126
  85. package/dist/test/collection-facets/more-facets-pagination.test.js.map +0 -1
  86. package/src/collection-facets/more-facets-pagination.ts +0 -294
  87. package/test/collection-facets/more-facets-pagination.test.ts +0 -201
@@ -1,294 +0,0 @@
1
- import {
2
- css,
3
- CSSResultGroup,
4
- html,
5
- LitElement,
6
- nothing,
7
- TemplateResult,
8
- } from 'lit';
9
- import { customElement, property, state } from 'lit/decorators.js';
10
- import arrowLeftIcon from '../assets/img/icons/arrow-left';
11
- import arrowRightIcon from '../assets/img/icons/arrow-right';
12
- import { srOnlyStyle } from '../styles/sr-only';
13
-
14
- @customElement('more-facets-pagination')
15
- export class MoreFacetsPagination extends LitElement {
16
- /**
17
- * Total number of pages
18
- */
19
- @property({ type: Number }) size!: number;
20
-
21
- /**
22
- * Number of pages can be moved in back/forward
23
- */
24
- @property({ type: Number }) step = 2;
25
-
26
- @property({ type: Number }) currentPage: number = 1;
27
-
28
- @state() pages?: number[] = [];
29
-
30
- firstUpdated() {
31
- this.observePageCount();
32
- }
33
-
34
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
- override updated(changed: Map<string, any>) {
36
- if (changed.has('size')) {
37
- this.observePageCount();
38
- }
39
- if (changed.has('currentPage')) {
40
- this.observePageCount();
41
- this.emitPageClick();
42
- }
43
- }
44
-
45
- /** creates `this.pages` array that notes which pages to draw
46
- * - `0` is elipses marker
47
- * - rule: selected page is centered between -2/+2 pages
48
- * - outlier: first page selected, show _1_ 2 3 ... N
49
- * - outlier: second page selected, show 1 _2_ 3 4 ... N
50
- * - outlier: last page selected, show 1 ... N-2 N-1 _N_
51
- * - outlier: if page count = 7, & selected is either [2, 3, 4, 5, 6], show all pages
52
- */
53
- observePageCount() {
54
- this.pages = []; /* `0` is elipses marker */
55
-
56
- const paginatorMaxPagesToShow = 7;
57
- const atMinThreshold = this.size <= paginatorMaxPagesToShow;
58
-
59
- /** Display outliers */
60
- if (this.size <= 5) {
61
- // display all pages
62
- this.pages = [...Array(this.size).keys()].map(i => i + 1);
63
- return;
64
- }
65
-
66
- if (this.size === paginatorMaxPagesToShow) {
67
- // edge: 7 pages
68
- if (this.currentPage === 2) {
69
- this.pages = [1, 2, 3, 4, 0, this.size];
70
- return;
71
- }
72
-
73
- if (this.currentPage === this.size - 1) {
74
- this.pages = [1, 0, 4, 5, this.size - 1, this.size];
75
- return;
76
- }
77
- }
78
-
79
- if (this.currentPage === 1) {
80
- // first page
81
- this.pages = [1, 2, 3, 0, this.size];
82
- return;
83
- }
84
-
85
- if (this.currentPage === this.size) {
86
- // last page
87
- this.pages = [1, 0, this.size - 2, this.size - 1, this.size];
88
- return;
89
- }
90
-
91
- if (this.currentPage === this.size - 1) {
92
- // second last page
93
- this.pages = [
94
- 1,
95
- 0,
96
- this.size - 3,
97
- this.size - 2,
98
- this.size - 1,
99
- this.size,
100
- ];
101
- return;
102
- }
103
-
104
- if (
105
- atMinThreshold &&
106
- this.currentPage > 1 &&
107
- this.currentPage < paginatorMaxPagesToShow
108
- ) {
109
- this.pages = [...Array(this.size).keys()].map(i => i + 1);
110
- return;
111
- }
112
-
113
- /* The rest here calculates the range to display in "page window" */
114
- let startPage = this.currentPage - this.step;
115
- let endPage = this.currentPage + this.step;
116
-
117
- if (startPage <= 0) {
118
- endPage += -startPage + 1;
119
- startPage = 1;
120
- }
121
-
122
- if (endPage >= this.size) {
123
- startPage = Math.max(startPage - (endPage - this.size), 1);
124
- endPage = this.size;
125
- }
126
-
127
- if (startPage === 2) {
128
- endPage -= 1;
129
- }
130
-
131
- if (endPage === this.size - 1) {
132
- startPage += 1;
133
- }
134
-
135
- // create first page node
136
- this.createFirstNode(startPage);
137
-
138
- // create middle pages node
139
- this.createMiddelNode(startPage, endPage);
140
-
141
- // create last page node
142
- this.createLastNode(endPage);
143
- }
144
-
145
- private createFirstNode(startPage: number) {
146
- if (startPage > 1) {
147
- this.pages?.push(1);
148
- }
149
- if (startPage > 2) {
150
- this.pages?.push(0); // let's asssume 0 is for ellipsis template
151
- }
152
- }
153
-
154
- private createMiddelNode(startPage: number, endPage: number) {
155
- for (let page = startPage; page <= endPage; page += 1) {
156
- this.pages?.push(page);
157
- }
158
- }
159
-
160
- private createLastNode(endPage: number) {
161
- if (endPage < this.size - 1) {
162
- this.pages?.push(0); // let's asssume 0 is for ellipsis template
163
- }
164
- if (endPage < this.size) {
165
- this.pages?.push(this.size);
166
- }
167
- }
168
-
169
- private get getEllipsisTemplate() {
170
- return html`<i class="ellipses">...</i>`;
171
- }
172
-
173
- emitPageClick() {
174
- this.dispatchEvent(
175
- new CustomEvent('pageNumberClicked', {
176
- detail: { page: this.currentPage },
177
- bubbles: true,
178
- composed: true,
179
- }),
180
- );
181
- }
182
-
183
- private onRewind() {
184
- this.currentPage -= 1;
185
- if (this.currentPage < 1) {
186
- this.currentPage = 1;
187
- }
188
- }
189
-
190
- private onForward() {
191
- this.currentPage += 1;
192
- if (this.currentPage > this.size) {
193
- this.currentPage = this.size;
194
- }
195
- }
196
-
197
- private onChange(page: number) {
198
- this.currentPage = page;
199
- }
200
-
201
- private getPageTemplate(page: number) {
202
- return html`
203
- <button
204
- @click=${() => this.onChange(page)}
205
- class=${this.currentPage === page ? 'current' : ''}
206
- data-page=${page}
207
- >
208
- ${page}
209
- </button>
210
- `;
211
- }
212
-
213
- private get getPagesTemplate(): TemplateResult | typeof nothing {
214
- if (!this.pages || !this.pages.length) {
215
- return nothing;
216
- }
217
-
218
- return html`
219
- ${this.pages?.map(
220
- page =>
221
- html`${page !== 0
222
- ? this.getPageTemplate(page)
223
- : this.getEllipsisTemplate}`,
224
- )}
225
- `;
226
- }
227
-
228
- render() {
229
- return html`
230
- <div class="facets-pagination">
231
- <button class="arrow-icon rewind" @click=${this.onRewind}>
232
- <span class="sr-only">Rewind pagination:</span>
233
- ${arrowLeftIcon}
234
- </button>
235
- <div class="page-numbers">${this.getPagesTemplate}</div>
236
- <button class="arrow-icon forward" @click=${this.onForward}>
237
- <span class="sr-only">Forward pagination:</span>
238
- ${arrowRightIcon}
239
- </button>
240
- </div>
241
- `;
242
- }
243
-
244
- static get styles(): CSSResultGroup {
245
- return [
246
- srOnlyStyle,
247
- css`
248
- .facets-pagination {
249
- user-select: none;
250
- margin-top: 10px;
251
- background-color: #eee;
252
- text-align: center;
253
- }
254
- .facets-pagination button {
255
- border: none;
256
- background: none;
257
- }
258
- .facets-pagination .arrow-icon {
259
- width: 2.5rem;
260
- vertical-align: middle;
261
- }
262
- .facets-pagination .arrow-icon svg {
263
- height: 14px;
264
- fill: #2c2c2c;
265
- }
266
- .facets-pagination button,
267
- .facets-pagination i {
268
- background: none;
269
- border: 0;
270
- cursor: pointer;
271
- border-radius: 4px;
272
- margin: 10px 5px;
273
- padding: 5px;
274
- font-size: 1.4rem;
275
- color: inherit;
276
- vertical-align: baseline;
277
- display: inline-block;
278
- min-width: 2.5rem;
279
- }
280
- .facets-pagination i {
281
- cursor: auto;
282
- display: inline;
283
- }
284
- .facets-pagination button.current {
285
- background: #2c2c2c;
286
- color: white;
287
- }
288
- .page-numbers {
289
- display: inline-block;
290
- }
291
- `,
292
- ];
293
- }
294
- }
@@ -1,201 +0,0 @@
1
- import { expect, fixture, oneEvent } from '@open-wc/testing';
2
- import { html } from 'lit';
3
- import sinon from 'sinon';
4
- import '../../src/collection-facets/more-facets-pagination';
5
- import type { MoreFacetsPagination } from '../../src/collection-facets/more-facets-pagination';
6
-
7
- afterEach(() => {
8
- sinon.restore();
9
- });
10
-
11
- describe('More facets pagination', () => {
12
- describe('5 pages or less', () => {
13
- it('shows all pages', async () => {
14
- const el = await fixture<MoreFacetsPagination>(
15
- html`<more-facets-pagination .size=${5}></more-facets-pagination>`,
16
- );
17
-
18
- await el.updateComplete;
19
-
20
- const pageButtons = el.shadowRoot?.querySelectorAll(
21
- 'button[data-page]',
22
- ) as NodeList;
23
- expect(pageButtons.length).to.greaterThan(0);
24
-
25
- pageButtons.forEach((button, index) => {
26
- expect(button.textContent).to.contain(index + 1);
27
- });
28
- });
29
- });
30
-
31
- it('should render pagination template', async () => {
32
- const el = await fixture<MoreFacetsPagination>(
33
- html`<more-facets-pagination .size=${10}></more-facets-pagination>`,
34
- );
35
-
36
- await el.updateComplete;
37
-
38
- expect(el.shadowRoot?.querySelector('.facets-pagination')).to.exist;
39
- expect(el.shadowRoot?.querySelector('.arrow-icon')).to.exist;
40
- });
41
-
42
- it('should render page numbers', async () => {
43
- const el = await fixture<MoreFacetsPagination>(
44
- html`<more-facets-pagination .size=${3}></more-facets-pagination>`,
45
- );
46
-
47
- await el.updateComplete;
48
-
49
- const pageNumberElement = el.shadowRoot?.querySelector('.page-numbers');
50
- expect(pageNumberElement).to.exist;
51
- expect(pageNumberElement?.querySelectorAll('button').length).to.equal(3);
52
- });
53
-
54
- it('check current page and total pages', async () => {
55
- const el = await fixture<MoreFacetsPagination>(
56
- html`<more-facets-pagination
57
- .size=${4}
58
- .currentPage=${2}
59
- ></more-facets-pagination>`,
60
- );
61
-
62
- await el.updateComplete;
63
-
64
- const pageNumberElement = el.shadowRoot?.querySelector('.page-numbers');
65
- expect(pageNumberElement).to.exist;
66
- expect(
67
- pageNumberElement
68
- ?.querySelectorAll('button')[1]
69
- .classList.contains('current'),
70
- ).to.be.true;
71
- expect(el.pages?.length).to.equal(4);
72
- });
73
-
74
- it('get page numbers based of size and currentPage', async () => {
75
- const el = await fixture<MoreFacetsPagination>(
76
- html`<more-facets-pagination
77
- .size=${4}
78
- .currentPage=${2}
79
- ></more-facets-pagination>`,
80
- );
81
-
82
- await el.updateComplete;
83
-
84
- expect(el.pages?.length).to.equal(4);
85
- });
86
-
87
- describe('Selecting a page', () => {
88
- it('fires event', async () => {
89
- const el = await fixture<MoreFacetsPagination>(
90
- html`<more-facets-pagination></more-facets-pagination>`,
91
- );
92
-
93
- await el.updateComplete;
94
-
95
- setTimeout(() =>
96
- el.dispatchEvent(
97
- new CustomEvent('pageNumberClicked', { detail: { page: 15 } }),
98
- ),
99
- );
100
- const { detail } = await oneEvent(el, 'pageNumberClicked');
101
- expect(detail?.page).to.equal(15);
102
- });
103
- it('sets off side effects with `onChange`', async () => {
104
- const el = await fixture<MoreFacetsPagination>(
105
- html`<more-facets-pagination
106
- .size=${'10'}
107
- .currentPage=${2}
108
- ></more-facets-pagination>`,
109
- );
110
-
111
- expect(el.currentPage).to.equal(2); // confirm current page
112
-
113
- const fake1 = sinon.fake();
114
- const fake2 = sinon.fake();
115
- el.observePageCount = fake1;
116
- el.emitPageClick = fake2;
117
-
118
- // select first page button
119
- const pageButton = el.shadowRoot?.querySelector(
120
- '.page-numbers > button',
121
- ) as HTMLButtonElement;
122
- // confirm button isn't selected
123
- expect(pageButton.classList.contains('current')).to.be.false;
124
- pageButton.click();
125
-
126
- await el.updateComplete;
127
-
128
- expect(fake1.callCount).to.equal(1);
129
- expect(fake2.callCount).to.equal(1);
130
- expect(el.currentPage).to.equal(1); // brings us back to currentPage
131
- // confirm button is selected
132
- expect(pageButton.classList.contains('current')).to.be.true;
133
- });
134
- });
135
-
136
- describe('Using Arrows', () => {
137
- it('going backwards', async () => {
138
- const el = await fixture<MoreFacetsPagination>(
139
- html`<more-facets-pagination
140
- .size=${'10'}
141
- .currentPage=${2}
142
- ></more-facets-pagination>`,
143
- );
144
-
145
- expect(el.currentPage).to.equal(2); // confirm current page
146
-
147
- const fake1 = sinon.fake();
148
- const fake2 = sinon.fake();
149
- el.observePageCount = fake1;
150
- el.emitPageClick = fake2;
151
-
152
- // select first page button
153
- const rewindButton = el.shadowRoot?.querySelector(
154
- '.facets-pagination > button.rewind',
155
- ) as HTMLButtonElement;
156
- rewindButton.click();
157
-
158
- await el.updateComplete;
159
-
160
- expect(fake1.callCount).to.equal(1);
161
- expect(fake2.callCount).to.equal(1);
162
- expect(el.currentPage).to.equal(1); // brings us back 1 page
163
- // confirm button is selected
164
- expect(
165
- (
166
- el.shadowRoot?.querySelector(
167
- '.page-numbers > button[data-page="1"]',
168
- ) as HTMLButtonElement
169
- ).classList.contains('current'),
170
- ).to.be.true;
171
- });
172
-
173
- it('going forwards', async () => {
174
- const el = await fixture<MoreFacetsPagination>(
175
- html`<more-facets-pagination
176
- .size=${'10'}
177
- .currentPage=${5}
178
- ></more-facets-pagination>`,
179
- );
180
-
181
- expect(el.currentPage).to.equal(5); // confirm current page
182
-
183
- const fake1 = sinon.fake();
184
- const fake2 = sinon.fake();
185
- el.observePageCount = fake1;
186
- el.emitPageClick = fake2;
187
-
188
- // select first page button
189
- const forwardButton = el.shadowRoot?.querySelector(
190
- '.facets-pagination > button.forward',
191
- ) as HTMLButtonElement;
192
- forwardButton.click();
193
-
194
- await el.updateComplete;
195
-
196
- expect(fake1.callCount).to.equal(1);
197
- expect(fake2.callCount).to.equal(1);
198
- expect(el.currentPage).to.equal(6); // brings us forward 1 page
199
- });
200
- });
201
- });