@internetarchive/ia-item-navigator 0.0.4-3 → 0.0.5-2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
}
|