@internetarchive/ia-item-navigator 0.0.4-3 → 0.0.5-2
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/README.md +1 -12
- package/demo/app-root.ts +180 -23
- package/demo/index.html +4 -0
- package/dist/demo/app-root.d.ts +16 -4
- package/dist/demo/app-root.js +163 -30
- package/dist/demo/app-root.js.map +1 -1
- package/dist/src/item-navigator.d.ts +1 -5
- package/dist/src/item-navigator.js +37 -34
- package/dist/src/item-navigator.js.map +1 -1
- package/dist/src/no-theater-available.js +2 -1
- package/dist/src/no-theater-available.js.map +1 -1
- package/dist/test/ia-item-navigator.test.d.ts +0 -1
- package/dist/test/ia-item-navigator.test.js +17 -7
- package/dist/test/ia-item-navigator.test.js.map +1 -1
- package/package.json +1 -1
- package/src/item-navigator.ts +35 -34
- package/src/no-theater-available.ts +2 -1
- package/test/ia-item-navigator.test.ts +19 -8
- package/test/book-nav-stub.ts +0 -47
package/src/item-navigator.ts
CHANGED
@@ -37,9 +37,6 @@ import {
|
|
37
37
|
} from './interfaces/menu-interfaces';
|
38
38
|
import './no-theater-available';
|
39
39
|
|
40
|
-
export enum ItemType {
|
41
|
-
OPEN = 'open',
|
42
|
-
}
|
43
40
|
@customElement('ia-item-navigator')
|
44
41
|
export class ItemNavigator
|
45
42
|
extends LitElement
|
@@ -55,7 +52,7 @@ export class ItemNavigator
|
|
55
52
|
})
|
56
53
|
item?: MetadataResponse;
|
57
54
|
|
58
|
-
@property({ type:
|
55
|
+
@property({ type: Boolean }) viewAvailable: Boolean = true;
|
59
56
|
|
60
57
|
@property({ type: String }) baseHost = 'archive.org';
|
61
58
|
|
@@ -92,9 +89,9 @@ export class ItemNavigator
|
|
92
89
|
|
93
90
|
@query('#frame') private frame!: HTMLDivElement;
|
94
91
|
|
95
|
-
@query('slot[name="
|
92
|
+
@query('slot[name="header"]') private headerSlot!: HTMLSlotElement;
|
96
93
|
|
97
|
-
@query('slot[name="
|
94
|
+
@query('slot[name="main"]') private mainSlot!: HTMLSlotElement;
|
98
95
|
|
99
96
|
disconnectedCallback() {
|
100
97
|
this.removeResizeObserver();
|
@@ -151,13 +148,6 @@ export class ItemNavigator
|
|
151
148
|
return this.viewportInFullscreen ? 'Internet Archive' : '';
|
152
149
|
}
|
153
150
|
|
154
|
-
get readerHeightStyle(): string {
|
155
|
-
const calcFSHeight = `calc(100vh - ${
|
156
|
-
this.headerSlot?.offsetHeight || 0
|
157
|
-
}px)`;
|
158
|
-
return this.viewportInFullscreen ? `height: ${calcFSHeight}` : '';
|
159
|
-
}
|
160
|
-
|
161
151
|
get loadingArea() {
|
162
152
|
return html`
|
163
153
|
<div class="loading-area">
|
@@ -181,19 +171,18 @@ export class ItemNavigator
|
|
181
171
|
|
182
172
|
render(): TemplateResult {
|
183
173
|
const displayReaderClass = this.loaded ? '' : 'hidden';
|
174
|
+
const headerHeight =
|
175
|
+
(this.headerSlot?.assignedNodes()[0] as HTMLElement)?.offsetHeight || 0;
|
184
176
|
return html`
|
185
|
-
<div id="frame" class=${
|
177
|
+
<div id="frame" class=${this.menuClass}>
|
186
178
|
<slot
|
187
|
-
name="
|
179
|
+
name="header"
|
180
|
+
style=${`height: ${headerHeight}px`}
|
188
181
|
@slotchange=${(e: Event) => this.slotChange(e, 'header')}
|
189
182
|
></slot>
|
190
183
|
<div class="menu-and-reader">
|
191
184
|
${this.shouldRenderMenu ? this.renderSideMenu : nothing}
|
192
|
-
<div
|
193
|
-
id="reader"
|
194
|
-
class=${displayReaderClass}
|
195
|
-
style=${this.readerHeightStyle}
|
196
|
-
>
|
185
|
+
<div id="reader" class=${displayReaderClass}>
|
197
186
|
${this.renderViewport}
|
198
187
|
</div>
|
199
188
|
${!this.loaded ? this.loadingArea : nothing}
|
@@ -210,19 +199,15 @@ export class ItemNavigator
|
|
210
199
|
}
|
211
200
|
|
212
201
|
get renderViewport(): TemplateResult | typeof nothing {
|
213
|
-
if (!this.
|
214
|
-
return nothing;
|
215
|
-
}
|
216
|
-
if (this.itemType !== ItemType.OPEN) {
|
202
|
+
if (!this.viewAvailable) {
|
217
203
|
return this.noTheaterView;
|
218
204
|
}
|
219
205
|
|
220
206
|
const slotVisibility = !this.loaded ? 'opacity: 0;' : 'opacity: 1;';
|
221
207
|
return html`
|
222
|
-
<div slot="
|
208
|
+
<div slot="main" style=${slotVisibility}>
|
223
209
|
<slot
|
224
|
-
name="
|
225
|
-
style=${this.readerHeightStyle}
|
210
|
+
name="main"
|
226
211
|
@slotchange=${(e: Event) => this.slotChange(e, 'main')}
|
227
212
|
></slot>
|
228
213
|
</div>
|
@@ -353,7 +338,9 @@ export class ItemNavigator
|
|
353
338
|
|
354
339
|
/** Misc Render */
|
355
340
|
get menuClass(): string {
|
356
|
-
const
|
341
|
+
const hasMenuOrShortcuts =
|
342
|
+
this.menuContents?.length || this.menuShortcuts?.length;
|
343
|
+
const drawerState = this.menuOpened && hasMenuOrShortcuts ? 'open' : '';
|
357
344
|
const fullscreenState = this.viewportInFullscreen ? 'fullscreen' : '';
|
358
345
|
return `${drawerState} ${fullscreenState} ${this.openMenuState}`;
|
359
346
|
}
|
@@ -369,8 +356,6 @@ export class ItemNavigator
|
|
369
356
|
:host,
|
370
357
|
#frame,
|
371
358
|
.menu-and-reader {
|
372
|
-
min-height: inherit;
|
373
|
-
height: inherit;
|
374
359
|
position: relative;
|
375
360
|
overflow: hidden;
|
376
361
|
display: block;
|
@@ -378,7 +363,6 @@ export class ItemNavigator
|
|
378
363
|
|
379
364
|
:host,
|
380
365
|
#frame,
|
381
|
-
.menu-and-reader,
|
382
366
|
.loading-area,
|
383
367
|
.loading-view {
|
384
368
|
min-height: inherit;
|
@@ -388,6 +372,7 @@ export class ItemNavigator
|
|
388
372
|
slot {
|
389
373
|
display: block;
|
390
374
|
overflow: hidden;
|
375
|
+
width: 100%;
|
391
376
|
}
|
392
377
|
|
393
378
|
slot * {
|
@@ -398,6 +383,8 @@ export class ItemNavigator
|
|
398
383
|
#frame {
|
399
384
|
background-color: ${theaterBg};
|
400
385
|
color-scheme: dark;
|
386
|
+
display: flex;
|
387
|
+
flex-direction: column;
|
401
388
|
}
|
402
389
|
|
403
390
|
#frame.fullscreen {
|
@@ -410,18 +397,23 @@ export class ItemNavigator
|
|
410
397
|
}
|
411
398
|
|
412
399
|
.loading-view {
|
400
|
+
height: 100%;
|
413
401
|
display: flex;
|
414
402
|
align-items: center;
|
415
403
|
justify-content: center;
|
416
404
|
}
|
417
405
|
|
406
|
+
.loading-area {
|
407
|
+
width: 100%;
|
408
|
+
}
|
409
|
+
|
418
410
|
ia-itemnav-loader {
|
419
411
|
display: block;
|
420
412
|
width: 100%;
|
421
413
|
}
|
422
414
|
|
423
415
|
.hidden {
|
424
|
-
display: none;
|
416
|
+
display: none !important;
|
425
417
|
}
|
426
418
|
|
427
419
|
button {
|
@@ -437,6 +429,8 @@ export class ItemNavigator
|
|
437
429
|
|
438
430
|
.menu-and-reader {
|
439
431
|
position: relative;
|
432
|
+
display: flex;
|
433
|
+
flex: 1;
|
440
434
|
}
|
441
435
|
|
442
436
|
nav button {
|
@@ -499,6 +493,13 @@ export class ItemNavigator
|
|
499
493
|
z-index: 1;
|
500
494
|
transform: translateX(0);
|
501
495
|
width: 100%;
|
496
|
+
display: flex;
|
497
|
+
}
|
498
|
+
|
499
|
+
#reader > * {
|
500
|
+
width: 100%;
|
501
|
+
display: flex;
|
502
|
+
flex: 1;
|
502
503
|
}
|
503
504
|
|
504
505
|
.open.overlay #reader {
|
@@ -512,8 +513,8 @@ export class ItemNavigator
|
|
512
513
|
}
|
513
514
|
|
514
515
|
.open.shift #reader {
|
515
|
-
width: calc(100% -
|
516
|
-
|
516
|
+
width: calc(100% - ${subnavWidth});
|
517
|
+
margin-left: ${subnavWidth};
|
517
518
|
transition: ${transitionEffect};
|
518
519
|
}
|
519
520
|
`;
|
@@ -7,7 +7,6 @@ import { ModalManager } from '@internetarchive/modal-manager';
|
|
7
7
|
import { ItemNavigator } from '../src/item-navigator';
|
8
8
|
import '../src/item-navigator';
|
9
9
|
|
10
|
-
import '../test/book-nav-stub';
|
11
10
|
import { ItemStub, menuProvider, shortcut } from '../test/ia-stub';
|
12
11
|
import {
|
13
12
|
ManageFullscreenEvent,
|
@@ -23,12 +22,25 @@ afterEach(() => {
|
|
23
22
|
|
24
23
|
describe('ItemNavigator', () => {
|
25
24
|
describe('Theaters', () => {
|
26
|
-
it('shows <ia-no-theater-available>
|
25
|
+
it('shows <ia-no-theater-available> if told', async () => {
|
27
26
|
const el = await fixture<ItemNavigator>(
|
28
27
|
html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
|
29
28
|
);
|
29
|
+
el.viewAvailable = false;
|
30
|
+
await el.updateComplete;
|
31
|
+
expect(el.viewAvailable).to.be.false;
|
30
32
|
expect(el.shadowRoot?.querySelector('ia-no-theater-available')).to.exist;
|
31
33
|
});
|
34
|
+
it('opens main slot by default', async () => {
|
35
|
+
const el = await fixture<ItemNavigator>(
|
36
|
+
html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
|
37
|
+
);
|
38
|
+
|
39
|
+
expect(el.viewAvailable).to.be.true;
|
40
|
+
expect(el.shadowRoot?.querySelector('ia-no-theater-available')).to.be
|
41
|
+
.null;
|
42
|
+
expect(el.shadowRoot?.querySelector('slot[name="main"]')).to.exist;
|
43
|
+
});
|
32
44
|
});
|
33
45
|
describe('`el.loaded`', () => {
|
34
46
|
it('toggles the spinning loader', async () => {
|
@@ -52,14 +64,16 @@ describe('ItemNavigator', () => {
|
|
52
64
|
html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
|
53
65
|
);
|
54
66
|
|
67
|
+
el.loaded = true;
|
68
|
+
await el.updateComplete;
|
55
69
|
const mainTheaterSection = el.shadowRoot?.querySelector('#reader');
|
56
70
|
expect(mainTheaterSection?.classList.contains('hide')).to.be.false;
|
57
71
|
expect(el.loaded).to.be.true;
|
58
72
|
// `loaded` property is reflected as DOM attribute
|
59
73
|
expect(el.hasAttribute('loaded')).to.equal(true);
|
60
|
-
expect(el.shadowRoot?.querySelector('
|
74
|
+
expect(el.shadowRoot?.querySelector('slot[name="main"]')).to.exist;
|
61
75
|
});
|
62
|
-
it('listens to `@loadingStateUpdated` to update `loaded`', async () => {
|
76
|
+
it('listens to `@loadingStateUpdated` to update `loaded` for <no-theater-available>', async () => {
|
63
77
|
const el = await fixture<ItemNavigator>(
|
64
78
|
html`<ia-item-navigator></ia-item-navigator>`
|
65
79
|
);
|
@@ -68,15 +82,12 @@ describe('ItemNavigator', () => {
|
|
68
82
|
const spy = Sinon.spy();
|
69
83
|
el.loadingStateUpdated = spy;
|
70
84
|
el.loaded = null;
|
85
|
+
el.viewAvailable = false;
|
71
86
|
await el.updateComplete;
|
72
87
|
// check base properties
|
73
88
|
expect(el.loaded).to.equal(null);
|
74
89
|
expect(el.item).to.be.undefined;
|
75
90
|
|
76
|
-
// hydrate item
|
77
|
-
el.item = new ItemStub();
|
78
|
-
await el.updateComplete;
|
79
|
-
|
80
91
|
// spy fires
|
81
92
|
expect(spy.called).to.equal(true);
|
82
93
|
expect(spy.callCount).to.equal(1);
|
package/test/book-nav-stub.ts
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
import { ModalManager } from '@internetarchive/modal-manager';
|
2
|
-
import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
|
3
|
-
import { html, customElement, LitElement, property } from 'lit-element';
|
4
|
-
import { MetadataResponse } from '@internetarchive/search-service';
|
5
|
-
import {
|
6
|
-
MenuProviderInterface,
|
7
|
-
MenuShortcutInterface,
|
8
|
-
} from '../src/interfaces/menu-interfaces';
|
9
|
-
import { CustomTheaterInterface } from '../src/interfaces/custom-theater-interface';
|
10
|
-
@customElement('book-navigator')
|
11
|
-
export class BookNavigator
|
12
|
-
extends LitElement
|
13
|
-
implements CustomTheaterInterface {
|
14
|
-
@property({ attribute: false }) modal?: ModalManager;
|
15
|
-
|
16
|
-
@property({ type: Object }) itemMD?: MetadataResponse;
|
17
|
-
|
18
|
-
@property({ type: String }) baseHost?: string;
|
19
|
-
|
20
|
-
@property({ type: Boolean, reflect: true }) signedIn?: boolean | null = null;
|
21
|
-
|
22
|
-
@property({ type: Boolean }) sideMenuOpen!: boolean;
|
23
|
-
|
24
|
-
@property({ attribute: false }) sharedObserver?: SharedResizeObserver;
|
25
|
-
|
26
|
-
@property({ type: Array }) menuProviders?: MenuProviderInterface[];
|
27
|
-
|
28
|
-
@property({ type: Array }) menuShortcuts?: MenuShortcutInterface[];
|
29
|
-
|
30
|
-
emitLoadingStatusUpdate() {}
|
31
|
-
|
32
|
-
addMenuShortcut(menuId: string) {
|
33
|
-
return menuId;
|
34
|
-
}
|
35
|
-
|
36
|
-
removeMenuShortcut(menuId: string) {
|
37
|
-
return menuId;
|
38
|
-
}
|
39
|
-
|
40
|
-
sortMenuShortcuts() {}
|
41
|
-
|
42
|
-
emitMenuShortcutsUpdated() {}
|
43
|
-
|
44
|
-
render() {
|
45
|
-
return html` <p>foo</p> `;
|
46
|
-
}
|
47
|
-
}
|