@internetarchive/ia-item-navigator 0.0.4-4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: String }) itemType?: ItemType;
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="theater-header"]') private headerSlot!: HTMLSlotElement;
92
+ @query('slot[name="header"]') private headerSlot!: HTMLSlotElement;
96
93
 
97
- @query('slot[name="theater-main"]') private mainSlot!: HTMLSlotElement;
94
+ @query('slot[name="main"]') private mainSlot!: HTMLSlotElement;
98
95
 
99
96
  disconnectedCallback() {
100
97
  this.removeResizeObserver();
@@ -151,12 +148,6 @@ export class ItemNavigator
151
148
  return this.viewportInFullscreen ? 'Internet Archive' : '';
152
149
  }
153
150
 
154
- get readerHeightStyle(): string {
155
- const calcFSHeight = `calc(100% - ${this.headerSlot?.offsetHeight || 0}px)`;
156
-
157
- return this.headerSlot?.offsetHeight > 0 ? `height: ${calcFSHeight}` : '';
158
- }
159
-
160
151
  get loadingArea() {
161
152
  return html`
162
153
  <div class="loading-area">
@@ -180,13 +171,16 @@ export class ItemNavigator
180
171
 
181
172
  render(): TemplateResult {
182
173
  const displayReaderClass = this.loaded ? '' : 'hidden';
174
+ const headerHeight =
175
+ (this.headerSlot?.assignedNodes()[0] as HTMLElement)?.offsetHeight || 0;
183
176
  return html`
184
177
  <div id="frame" class=${this.menuClass}>
185
178
  <slot
186
- name="theater-header"
179
+ name="header"
180
+ style=${`height: ${headerHeight}px`}
187
181
  @slotchange=${(e: Event) => this.slotChange(e, 'header')}
188
182
  ></slot>
189
- <div class="menu-and-reader" style=${this.readerHeightStyle}>
183
+ <div class="menu-and-reader">
190
184
  ${this.shouldRenderMenu ? this.renderSideMenu : nothing}
191
185
  <div id="reader" class=${displayReaderClass}>
192
186
  ${this.renderViewport}
@@ -205,19 +199,15 @@ export class ItemNavigator
205
199
  }
206
200
 
207
201
  get renderViewport(): TemplateResult | typeof nothing {
208
- if (!this.item) {
209
- return nothing;
210
- }
211
- if (this.itemType !== ItemType.OPEN) {
202
+ if (!this.viewAvailable) {
212
203
  return this.noTheaterView;
213
204
  }
214
205
 
215
206
  const slotVisibility = !this.loaded ? 'opacity: 0;' : 'opacity: 1;';
216
207
  return html`
217
- <div slot="theater-main" style=${slotVisibility}>
208
+ <div slot="main" style=${slotVisibility}>
218
209
  <slot
219
- name="theater-main"
220
- style=${this.readerHeightStyle}
210
+ name="main"
221
211
  @slotchange=${(e: Event) => this.slotChange(e, 'main')}
222
212
  ></slot>
223
213
  </div>
@@ -348,7 +338,9 @@ export class ItemNavigator
348
338
 
349
339
  /** Misc Render */
350
340
  get menuClass(): string {
351
- const drawerState = this.menuOpened ? 'open' : '';
341
+ const hasMenuOrShortcuts =
342
+ this.menuContents?.length || this.menuShortcuts?.length;
343
+ const drawerState = this.menuOpened && hasMenuOrShortcuts ? 'open' : '';
352
344
  const fullscreenState = this.viewportInFullscreen ? 'fullscreen' : '';
353
345
  return `${drawerState} ${fullscreenState} ${this.openMenuState}`;
354
346
  }
@@ -364,8 +356,6 @@ export class ItemNavigator
364
356
  :host,
365
357
  #frame,
366
358
  .menu-and-reader {
367
- min-height: inherit;
368
- height: inherit;
369
359
  position: relative;
370
360
  overflow: hidden;
371
361
  display: block;
@@ -373,7 +363,6 @@ export class ItemNavigator
373
363
 
374
364
  :host,
375
365
  #frame,
376
- .menu-and-reader,
377
366
  .loading-area,
378
367
  .loading-view {
379
368
  min-height: inherit;
@@ -382,7 +371,6 @@ export class ItemNavigator
382
371
 
383
372
  slot {
384
373
  display: block;
385
- overflow: hidden;
386
374
  width: 100%;
387
375
  }
388
376
 
@@ -394,6 +382,8 @@ export class ItemNavigator
394
382
  #frame {
395
383
  background-color: ${theaterBg};
396
384
  color-scheme: dark;
385
+ display: flex;
386
+ flex-direction: column;
397
387
  }
398
388
 
399
389
  #frame.fullscreen {
@@ -406,18 +396,23 @@ export class ItemNavigator
406
396
  }
407
397
 
408
398
  .loading-view {
399
+ height: 100%;
409
400
  display: flex;
410
401
  align-items: center;
411
402
  justify-content: center;
412
403
  }
413
404
 
405
+ .loading-area {
406
+ width: 100%;
407
+ }
408
+
414
409
  ia-itemnav-loader {
415
410
  display: block;
416
411
  width: 100%;
417
412
  }
418
413
 
419
414
  .hidden {
420
- display: none;
415
+ display: none !important;
421
416
  }
422
417
 
423
418
  button {
@@ -433,6 +428,8 @@ export class ItemNavigator
433
428
 
434
429
  .menu-and-reader {
435
430
  position: relative;
431
+ display: flex;
432
+ flex: 1;
436
433
  }
437
434
 
438
435
  nav button {
@@ -495,13 +492,13 @@ export class ItemNavigator
495
492
  z-index: 1;
496
493
  transform: translateX(0);
497
494
  width: 100%;
498
- height: 100%;
495
+ display: flex;
499
496
  }
500
497
 
501
498
  #reader > * {
502
499
  width: 100%;
503
500
  display: flex;
504
- height: 100%;
501
+ flex: 1;
505
502
  }
506
503
 
507
504
  .open.overlay #reader {
@@ -515,8 +512,8 @@ export class ItemNavigator
515
512
  }
516
513
 
517
514
  .open.shift #reader {
518
- width: calc(100% - var(--menuWidth));
519
- float: right;
515
+ width: calc(100% - ${subnavWidth});
516
+ margin-left: ${subnavWidth};
520
517
  transition: ${transitionEffect};
521
518
  }
522
519
  `;
@@ -4,7 +4,7 @@ import Sinon from 'sinon';
4
4
 
5
5
  import { SharedResizeObserver } from '@internetarchive/shared-resize-observer';
6
6
  import { ModalManager } from '@internetarchive/modal-manager';
7
- import { ItemNavigator, ItemType } from '../src/item-navigator';
7
+ import { ItemNavigator } from '../src/item-navigator';
8
8
  import '../src/item-navigator';
9
9
 
10
10
  import { ItemStub, menuProvider, shortcut } from '../test/ia-stub';
@@ -22,25 +22,24 @@ afterEach(() => {
22
22
 
23
23
  describe('ItemNavigator', () => {
24
24
  describe('Theaters', () => {
25
- it('shows <ia-no-theater-available> by default', async () => {
25
+ it('shows <ia-no-theater-available> if told', async () => {
26
26
  const el = await fixture<ItemNavigator>(
27
27
  html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
28
28
  );
29
+ el.viewAvailable = false;
30
+ await el.updateComplete;
31
+ expect(el.viewAvailable).to.be.false;
29
32
  expect(el.shadowRoot?.querySelector('ia-no-theater-available')).to.exist;
30
- expect(el.itemType).to.not.equal(ItemType.OPEN);
31
33
  });
32
- it('opens main slot when itemType = open', async () => {
34
+ it('opens main slot by default', async () => {
33
35
  const el = await fixture<ItemNavigator>(
34
36
  html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
35
37
  );
36
- el.itemType = ItemType.OPEN;
37
- await el.updateComplete;
38
38
 
39
- expect(el.itemType).to.equal(ItemType.OPEN);
39
+ expect(el.viewAvailable).to.be.true;
40
40
  expect(el.shadowRoot?.querySelector('ia-no-theater-available')).to.be
41
41
  .null;
42
- expect(el.shadowRoot?.querySelector('slot[name="theater-main"]')).to
43
- .exist;
42
+ expect(el.shadowRoot?.querySelector('slot[name="main"]')).to.exist;
44
43
  });
45
44
  });
46
45
  describe('`el.loaded`', () => {
@@ -65,14 +64,16 @@ describe('ItemNavigator', () => {
65
64
  html`<ia-item-navigator .item=${new ItemStub()}></ia-item-navigator>`
66
65
  );
67
66
 
67
+ el.loaded = true;
68
+ await el.updateComplete;
68
69
  const mainTheaterSection = el.shadowRoot?.querySelector('#reader');
69
70
  expect(mainTheaterSection?.classList.contains('hide')).to.be.false;
70
71
  expect(el.loaded).to.be.true;
71
72
  // `loaded` property is reflected as DOM attribute
72
73
  expect(el.hasAttribute('loaded')).to.equal(true);
73
- expect(el.shadowRoot?.querySelector('ia-no-theater-available')).to.exist;
74
+ expect(el.shadowRoot?.querySelector('slot[name="main"]')).to.exist;
74
75
  });
75
- it('listens to `@loadingStateUpdated` to update `loaded`', async () => {
76
+ it('listens to `@loadingStateUpdated` to update `loaded` for <no-theater-available>', async () => {
76
77
  const el = await fixture<ItemNavigator>(
77
78
  html`<ia-item-navigator></ia-item-navigator>`
78
79
  );
@@ -81,15 +82,12 @@ describe('ItemNavigator', () => {
81
82
  const spy = Sinon.spy();
82
83
  el.loadingStateUpdated = spy;
83
84
  el.loaded = null;
85
+ el.viewAvailable = false;
84
86
  await el.updateComplete;
85
87
  // check base properties
86
88
  expect(el.loaded).to.equal(null);
87
89
  expect(el.item).to.be.undefined;
88
90
 
89
- // hydrate item
90
- el.item = new ItemStub();
91
- await el.updateComplete;
92
-
93
91
  // spy fires
94
92
  expect(spy.called).to.equal(true);
95
93
  expect(spy.callCount).to.equal(1);