@internetarchive/ia-item-navigator 0.0.0-a9 → 0.0.2-a2

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 (54) hide show
  1. package/README.md +29 -19
  2. package/demo/app-root.ts +37 -31
  3. package/demo/index.html +1 -0
  4. package/dist/demo/app-root.d.ts +11 -15
  5. package/dist/demo/app-root.js +26 -26
  6. package/dist/demo/app-root.js.map +1 -1
  7. package/dist/src/interfaces/custom-theater-interface.d.ts +20 -0
  8. package/dist/src/interfaces/custom-theater-interface.js +2 -0
  9. package/dist/src/interfaces/custom-theater-interface.js.map +1 -0
  10. package/dist/src/interfaces/event-interfaces.d.ts +11 -11
  11. package/dist/src/interfaces/event-interfaces.js.map +1 -1
  12. package/dist/src/interfaces/menu-interfaces.d.ts +6 -7
  13. package/dist/src/interfaces/menu-interfaces.js.map +1 -1
  14. package/dist/src/interfaces/nav-controller-interface.d.ts +11 -6
  15. package/dist/src/interfaces/nav-controller-interface.js.map +1 -1
  16. package/dist/src/item-inspector/item-inspector.d.ts +0 -47
  17. package/dist/src/item-inspector/item-inspector.js +253 -271
  18. package/dist/src/item-inspector/item-inspector.js.map +1 -1
  19. package/dist/src/item-navigator.d.ts +41 -28
  20. package/dist/src/item-navigator.js +96 -113
  21. package/dist/src/item-navigator.js.map +1 -1
  22. package/dist/src/no-theater-available.d.ts +9 -0
  23. package/dist/src/no-theater-available.js +79 -0
  24. package/dist/src/no-theater-available.js.map +1 -0
  25. package/dist/test/book-nav-stub.d.ts +22 -0
  26. package/dist/test/book-nav-stub.js +49 -0
  27. package/dist/test/book-nav-stub.js.map +1 -0
  28. package/dist/test/ia-item-navigator.test.d.ts +1 -0
  29. package/dist/test/ia-item-navigator.test.js +279 -131
  30. package/dist/test/ia-item-navigator.test.js.map +1 -1
  31. package/dist/test/ia-stub.d.ts +22 -0
  32. package/dist/test/ia-stub.js +34 -3
  33. package/dist/test/ia-stub.js.map +1 -1
  34. package/dist/test/no-theater-available.test.d.ts +1 -0
  35. package/dist/test/no-theater-available.test.js +27 -0
  36. package/dist/test/no-theater-available.test.js.map +1 -0
  37. package/package.json +4 -3
  38. package/src/interfaces/custom-theater-interface.ts +28 -0
  39. package/src/interfaces/event-interfaces.ts +15 -11
  40. package/src/interfaces/menu-interfaces.ts +9 -10
  41. package/src/item-navigator.ts +133 -144
  42. package/src/no-theater-available.ts +85 -0
  43. package/test/book-nav-stub.ts +47 -0
  44. package/test/ia-item-navigator.test.ts +365 -156
  45. package/test/ia-stub.ts +78 -2
  46. package/test/no-theater-available.test.ts +32 -0
  47. package/demo/demo-book-manifest.json +0 -1163
  48. package/src/interfaces/nav-controller-interface.ts +0 -18
  49. package/src/item-inspector/files-by-type/files-by-type-provider.ts +0 -43
  50. package/src/item-inspector/files-by-type/ia-files-by-type.ts +0 -100
  51. package/src/item-inspector/item-inspector.ts +0 -296
  52. package/src/item-inspector/share-provider.ts +0 -51
  53. package/src/item-inspector/visual-mod-provider.ts +0 -65
  54. package/src/item-navigator-js.js +0 -372
@@ -1,18 +0,0 @@
1
- import { LitElement } from 'lit-element';
2
- import { MetadataResponse } from '@internetarchive/search-service';
3
- import { IntMenuShortcut } from './menu-interfaces';
4
-
5
- export interface IntNavController extends LitElement {
6
- baseHost: string;
7
- itemMD: MetadataResponse;
8
- menuProviders: object;
9
- menuShortcuts: IntMenuShortcut[];
10
- sideMenuOpen: boolean;
11
-
12
- emitLoadingStatusUpdate: (loaded: boolean) => void;
13
-
14
- addMenuShortcut: (menuId: string) => void;
15
- removeMenuShortcut: (menuId: string) => void;
16
- sortMenuShortcuts: () => void;
17
- emitMenuShortcutsUpdated: () => void;
18
- }
@@ -1,43 +0,0 @@
1
- import { html, TemplateResult } from 'lit-element';
2
-
3
- import './ia-files-by-type';
4
- import '@internetarchive/icon-share/icon-share';
5
- import {
6
- IntMenuProvider,
7
- IntProviderArgs,
8
- } from '../../interfaces/menu-interfaces';
9
-
10
- export class FilesByTypeProvider implements IntMenuProvider {
11
- item: any = null;
12
-
13
- baseHost: string = 'https://archive.org';
14
-
15
- icon: TemplateResult = html`<p
16
- style="color: #fff; font-size: var(--iconHeight);"
17
- >
18
- F
19
- </p>`;
20
-
21
- id: string = 'filesByType';
22
-
23
- label: string = 'Files by type';
24
-
25
- component: TemplateResult | null = null;
26
-
27
- subPrefix: string = '';
28
-
29
- constructor(shareArgs: IntProviderArgs) {
30
- const { item, baseHost, subPrefix = '' } = shareArgs;
31
- const { title = '' } = item.metadata;
32
-
33
- this.item = item;
34
- this.baseHost = baseHost;
35
- this.subPrefix = subPrefix;
36
-
37
- this.component = html`<ia-files-by-type
38
- .item=${this.item}
39
- .description="${title}"
40
- .baseHost="${this.baseHost}"
41
- ></ia-files-by-type>`;
42
- }
43
- }
@@ -1,100 +0,0 @@
1
- import { MetadataResponse, File } from '@internetarchive/search-service';
2
- import { html, customElement, LitElement, property } from 'lit-element';
3
-
4
- interface CollapsedFileInt extends File {
5
- [menuId: string]: any;
6
- derivatives: [];
7
- }
8
-
9
- @customElement('ia-files-by-type')
10
- export default class IaFilesByType extends LitElement {
11
- @property({ type: Object }) item: MetadataResponse = {} as MetadataResponse;
12
-
13
- @property({ type: Array }) archivalArtifacts: File[] = [];
14
-
15
- @property({ type: Array }) collapsedFiles: CollapsedFileInt[] = [];
16
-
17
- firstUpdated() {
18
- this.collapseFiles();
19
- }
20
-
21
- render() {
22
- return html`
23
- <div>
24
- <p>there are ${this.collapsedFiles.length} original files</p>
25
-
26
- <p>there are ${this.archivalArtifacts.length} archival artifacts</p>
27
-
28
- <p></p>
29
- </div>
30
- `;
31
- }
32
-
33
- sortByViewer() {
34
- // const images = [];
35
- // const books = [];
36
- // const radio = [];
37
- // const audio = [];
38
- // const video = [];
39
- // const albums = [];
40
- // const software = [];
41
- // this.collapsedFiles.forEach((fi) => {
42
- // // if image
43
- // // sort by various viewers
44
- // })
45
-
46
- return true;
47
- }
48
-
49
- collapseFiles() {
50
- const { files = [] } = this?.item as MetadataResponse;
51
-
52
- const archivalArtifacts: File[] = [];
53
- const origDir: any = {};
54
-
55
- files.forEach(fi => {
56
- const { format, source, name, original = '' } = fi as File;
57
- if (
58
- format.toLowerCase() === 'metadata' ||
59
- format.toLowerCase() === 'item tile'
60
- ) {
61
- archivalArtifacts.push(fi);
62
- return;
63
- }
64
-
65
- let origEntry: any = {};
66
- if (source === 'original') {
67
- origEntry = origDir[name];
68
- if (!origEntry) {
69
- // add new
70
- origDir[name] = { ...fi, derivatives: [] } as CollapsedFileInt;
71
- origEntry = origDir[name];
72
- } else {
73
- // update
74
- const merged = { ...origEntry, ...fi };
75
- origDir[name] = merged;
76
- }
77
- return;
78
- }
79
-
80
- if (source === 'derivative') {
81
- const keyToFile = original || '';
82
- origEntry = origDir[keyToFile];
83
- if (!origEntry && original) {
84
- // add new
85
- const fileFrame = { derivatives: [] } as CollapsedFileInt;
86
- origEntry = fileFrame;
87
- origEntry?.derivatives.push(fi);
88
- origDir[keyToFile] = origEntry;
89
- origEntry = origDir[keyToFile];
90
- }
91
- origEntry?.derivatives.push(fi);
92
- }
93
- });
94
-
95
- this.archivalArtifacts = archivalArtifacts;
96
- this.collapsedFiles = Object.keys(origDir).map(
97
- (fileName: string) => origDir[fileName]
98
- );
99
- }
100
- }
@@ -1,296 +0,0 @@
1
- /* eslint-disable no-console */
2
- /* eslint-disable import/no-duplicates */
3
- import {
4
- css,
5
- html,
6
- LitElement,
7
- customElement,
8
- property,
9
- state,
10
- } from 'lit-element';
11
- import { MetadataResponse } from '@internetarchive/search-service';
12
-
13
- import {
14
- ModalManagerInterface,
15
- ModalConfig,
16
- } from '@internetarchive/modal-manager';
17
- import { SharedResizeObserverInterface } from '@internetarchive/shared-resize-observer';
18
- import { IntNavController } from '../interfaces/nav-controller-interface';
19
- import {
20
- IntMenuProvider,
21
- IntMenuShortcut,
22
- } from '../interfaces/menu-interfaces';
23
- import { IntManageFullscreenEvent } from '../interfaces/event-interfaces';
24
-
25
- import { ShareProvider } from './share-provider';
26
- import { FilesByTypeProvider } from './files-by-type/files-by-type-provider';
27
- import { VisualModsProvider } from './visual-mod-provider';
28
-
29
- // eslint-disable-next-line no-shadow
30
- enum ItemInspectorEvents {
31
- menuUpdated = 'menuUpdated',
32
- updateSideMenu = 'updateSideMenu',
33
- PostInit = 'PostInit',
34
- ViewportInFullScreen = 'ViewportInFullScreen',
35
- }
36
-
37
- interface menuProvidersInt {
38
- [menuId: string]: IntMenuProvider;
39
- }
40
-
41
- @customElement('ia-item-inspector')
42
- export class IaItemInspector extends LitElement implements IntNavController {
43
- @property({ type: Object }) itemMD: MetadataResponse = {
44
- metadata: {},
45
- } as MetadataResponse;
46
-
47
- @property({ type: String }) baseHost = 'https://archive.org';
48
-
49
- @property({ type: Object }) menuProviders: menuProvidersInt = {};
50
-
51
- @property({ type: Array }) menuShortcuts: IntMenuShortcut[] = [];
52
-
53
- @property({ type: Boolean }) sideMenuOpen = false;
54
-
55
- @property({ type: Boolean }) fullscreenState = false;
56
-
57
- @property({ attribute: false }) modal!: ModalManagerInterface;
58
-
59
- @property({ attribute: false }) sharedRO!: SharedResizeObserverInterface;
60
-
61
- @state() fileCount: number = 0;
62
-
63
- @state() loaded: boolean = false;
64
-
65
- @state() private shortcutOrder = ['visualMods'];
66
-
67
- firstUpdated() {
68
- this.loaded = true;
69
- console.log('modal', this.modal);
70
- }
71
-
72
- updated(changed: any) {
73
- if (changed.has('loaded')) {
74
- setTimeout(() => this.emitLoadingStatusUpdate(this.loaded), 1000);
75
- }
76
-
77
- if (changed.has('itemMD') && this.itemMD) {
78
- this.parseItemInfo();
79
- this.setMenu();
80
- }
81
-
82
- if (changed.has('menuProviders') || changed.has('menuShortcuts')) {
83
- this.updateMenuContents();
84
- }
85
- }
86
-
87
- modalClosedCallback() {
88
- console.log('item-inspector, modal closed');
89
- }
90
-
91
- openModal() {
92
- const config = new ModalConfig();
93
- const customModalContent = html`
94
- Can contain any markup, including web components. Event listeners also
95
- work. Try clicking on the picture.
96
- <div style="text-align: center">
97
- <a href="https://fillmurray.com" style="display: block">Fill Murray</a>
98
- <img src="100x100.jpg" alt="foo" />
99
- </div>
100
- `;
101
-
102
- this.modal.showModal({
103
- config,
104
- customModalContent,
105
- userClosedModalCallback: this.modalClosedCallback,
106
- });
107
- }
108
-
109
- render() {
110
- const { identifier = '' } = this.itemMD?.metadata;
111
- return html`
112
- <section>
113
- <div>
114
- <h2>${identifier}</h2>
115
- </div>
116
- <img src=${this.imageUrl} alt=${`${identifier} thumbnail`} />
117
- <button @click=${() => this.openModal()}>open modal</button>
118
- <p style="font-size: 20px;">
119
- Bacon ipsum dolor amet flank chicken leberkas sausage, meatball pork
120
- belly jowl. Chislic bacon salami frankfurter shankle drumstick
121
- andouille ball tip alcatra. Fatback beef ribs chicken, jerky ground
122
- round hamburger pork chop biltong. Shoulder short loin rump jerky
123
- kielbasa pork porchetta fatback ribeye pork belly sirloin chislic
124
- turducken corned beef tri-tip. Chuck pancetta meatball tail, spare
125
- ribs ham hock capicola pig. Ham hock hamburger chicken tri-tip venison
126
- swine burgdoggen boudin meatloaf pastrami chuck. Tri-tip spare ribs
127
- drumstick, tail rump hamburger burgdoggen swine t-bone tongue
128
- andouille chislic alcatra. Pork loin jowl frankfurter, doner meatball
129
- short loin ham hock filet mignon hamburger rump turkey bresaola
130
- shoulder sirloin flank. Ribeye sausage pig t-bone bacon frankfurter
131
- cupim capicola fatback pastrami ball tip pork belly. Picanha pancetta
132
- andouille flank shankle venison tri-tip tail, kevin turkey turducken
133
- chicken. Bacon picanha swine frankfurter, prosciutto chislic doner
134
- alcatra pork loin corned beef jowl biltong meatball chuck. Bacon
135
- burgdoggen pig fatback cupim t-bone. Cow pork loin bresaola brisket
136
- shoulder filet mignon chicken. Sirloin bresaola porchetta beef
137
- capicola meatloaf brisket shankle jerky turkey pork tri-tip swine
138
- kevin salami. Meatball t-bone doner venison. Pig tri-tip chuck, shank
139
- chicken pork chop landjaeger spare ribs jerky swine ham hock buffalo
140
- sirloin. Leberkas pancetta tenderloin, meatloaf buffalo rump pastrami
141
- chuck. Jerky cupim porchetta, tenderloin chuck andouille venison pork
142
- salami. Chuck strip steak cupim, turducken ham hock kielbasa shoulder
143
- porchetta chislic short loin tri-tip biltong cow corned beef.
144
- </p>
145
- </section>
146
- `;
147
- }
148
-
149
- addMenuShortcut(menuId: keyof menuProvidersInt) {
150
- if (this.menuShortcuts.find(m => m.id === menuId)) {
151
- return;
152
- }
153
-
154
- const shortcut = this.menuProviders[menuId];
155
- this.menuShortcuts.push(shortcut);
156
- this.sortMenuShortcuts();
157
- this.emitMenuShortcutsUpdated();
158
- }
159
-
160
- /**
161
- * Removes a provider object from the menuShortcuts array and emits a
162
- * menuShortcutsUpdated event.
163
- */
164
- removeMenuShortcut(menuId: string) {
165
- this.menuShortcuts = this.menuShortcuts.filter(m => m.id !== menuId);
166
- this.emitMenuShortcutsUpdated();
167
- }
168
-
169
- /**
170
- * Sorts the menuShortcuts property by comparing each provider's id to
171
- * the id in each iteration over the shortcutOrder array.
172
- */
173
- sortMenuShortcuts() {
174
- this.menuShortcuts = this.shortcutOrder.reduce(
175
- (shortcuts: IntMenuShortcut[], id) => {
176
- const menu = this.menuShortcuts.find(m => m.id === id);
177
-
178
- // eslint-disable-next-line no-param-reassign
179
- if (menu) {
180
- const newShortcuts = [...shortcuts, menu];
181
- // eslint-disable-next-line no-param-reassign
182
- shortcuts = newShortcuts;
183
- }
184
- return shortcuts;
185
- },
186
- []
187
- );
188
- }
189
-
190
- emitMenuShortcutsUpdated() {
191
- const event = new CustomEvent('menuShortcutsUpdated', {
192
- detail: this.menuShortcuts,
193
- });
194
- this.dispatchEvent(event);
195
- }
196
-
197
- setMenu() {
198
- const menuProviders = {
199
- share: new ShareProvider({
200
- item: this.itemMD,
201
- baseHost: this.baseHost,
202
- subPrefix: '',
203
- }),
204
- filesByType: new FilesByTypeProvider({
205
- item: this.itemMD,
206
- baseHost: this.baseHost,
207
- subPrefix: '',
208
- }),
209
- visualMods: new VisualModsProvider({
210
- updated: (modType: string) => {
211
- if (modType === 'toggleFullscreen') {
212
- this.updateFullscreenState();
213
- }
214
- },
215
- item: this.itemMD,
216
- baseHost: this.baseHost,
217
- subPrefix: '',
218
- // maybe DOM root for class configs?
219
- }),
220
- };
221
-
222
- this.menuProviders = menuProviders;
223
- this.addMenuShortcut('visualMods');
224
- }
225
-
226
- updateFullscreenState() {
227
- const isFullScreen = !this.fullscreenState;
228
- this.fullscreenState = isFullScreen;
229
-
230
- const event = new CustomEvent('ViewportInFullScreen', {
231
- detail: { isFullScreen },
232
- } as IntManageFullscreenEvent);
233
- this.dispatchEvent(event);
234
- }
235
-
236
- updateMenuContents() {
237
- const { share, filesByType, visualMods } = this.menuProviders;
238
- const availableMenus = [filesByType, share, visualMods].filter(
239
- menu => !!menu
240
- );
241
-
242
- const event = new CustomEvent(ItemInspectorEvents.menuUpdated, {
243
- detail: availableMenus,
244
- });
245
-
246
- this.dispatchEvent(event);
247
- }
248
-
249
- emitLoadingStatusUpdate(loaded: boolean) {
250
- const event = new CustomEvent('loadingStateUpdated', {
251
- detail: { loaded },
252
- });
253
- this.dispatchEvent(event);
254
- }
255
-
256
- parseItemInfo() {
257
- this.fileCount = this.itemMD?.files?.length || 0;
258
- }
259
-
260
- get imageUrl() {
261
- const { metadata = {} } = this.itemMD;
262
- const url = `${this.baseHost}/download/${metadata?.identifier}/__ia_thumb.jpg`;
263
- return url;
264
- }
265
-
266
- static get styles() {
267
- const main = css`
268
- :host {
269
- display: block;
270
- width: 100%;
271
- margin: 0 auto;
272
- position: relative;
273
- overflow: auto;
274
- background-color: black;
275
- color: var(--primaryTextColor, #fff);
276
- }
277
-
278
- :host,
279
- section {
280
- min-height: inherit;
281
- height: inherit;
282
- }
283
-
284
- section {
285
- margin: auto;
286
- width: 100%;
287
- text-align: center;
288
- }
289
-
290
- img {
291
- border: 1px solid var(--primaryTextColor, #fff);
292
- }
293
- `;
294
- return [main];
295
- }
296
- }
@@ -1,51 +0,0 @@
1
- import { html, TemplateResult } from 'lit-element';
2
-
3
- import '@internetarchive/ia-sharing-options';
4
- import '@internetarchive/icon-share/icon-share';
5
- import {
6
- IntMenuProvider,
7
- IntProviderArgs,
8
- } from '../interfaces/menu-interfaces';
9
-
10
- export class ShareProvider implements IntMenuProvider {
11
- item: any = null;
12
-
13
- baseHost: string = 'https://archive.org';
14
-
15
- icon: TemplateResult = html`<ia-icon-share
16
- style="width: var(--iconWidth); height: var(--iconHeight);"
17
- ></ia-icon-share>`;
18
-
19
- id: string = 'share';
20
-
21
- label: string = 'Share this item';
22
-
23
- component: TemplateResult | null = null;
24
-
25
- subPrefix: string = '';
26
-
27
- encodedSubPrefix: string = '';
28
-
29
- constructor(shareArgs: IntProviderArgs) {
30
- const { item, baseHost, subPrefix = '' } = shareArgs;
31
- const { identifier = '', creator = '', title = '' } = item.metadata || {};
32
- const encodedSubPrefix = encodeURIComponent(subPrefix);
33
- const urlIdentifier =
34
- subPrefix && subPrefix !== identifier
35
- ? `${identifier}/${encodedSubPrefix}`
36
- : identifier;
37
-
38
- this.item = item;
39
- this.baseHost = baseHost;
40
- this.subPrefix = subPrefix;
41
- this.encodedSubPrefix = encodedSubPrefix;
42
-
43
- this.component = html`<ia-sharing-options
44
- identifier=${urlIdentifier}
45
- type="item"
46
- creator="${creator}"
47
- description="${title}"
48
- baseHost="${this.baseHost}"
49
- ></ia-sharing-options>`;
50
- }
51
- }
@@ -1,65 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-unused-vars */
2
- /* eslint-disable max-classes-per-file */
3
-
4
- import { html, TemplateResult, customElement, LitElement } from 'lit-element';
5
-
6
- import '@internetarchive/ia-sharing-options';
7
- import '@internetarchive/icon-visual-adjustment/icon-visual-adjustment';
8
- import {
9
- IntMenuProvider,
10
- IntProviderArgs,
11
- } from '../interfaces/menu-interfaces';
12
-
13
- @customElement('ia-visual-mods')
14
- class VisualMods extends LitElement {
15
- toggleFullscreen() {
16
- this.dispatchEvent(new Event('fullscreenToggle'));
17
- }
18
-
19
- render() {
20
- return html`<section>
21
- <button @click=${this.toggleFullscreen}>Toggle Fullscreen</button>
22
- </section>`;
23
- }
24
- }
25
-
26
- export class VisualModsProvider implements IntMenuProvider {
27
- item: any = null;
28
-
29
- baseHost: string = 'https://archive.org';
30
-
31
- icon: TemplateResult = html`<ia-icon-visual-adjustment
32
- style="width: var(--iconWidth); height: var(--iconHeight);"
33
- ></ia-icon-visual-adjustment>`;
34
-
35
- id: string = 'visualMods';
36
-
37
- label: string = 'Visual Modifications';
38
-
39
- component: TemplateResult | null = null;
40
-
41
- subPrefix: string = '';
42
-
43
- encodedSubPrefix: string = '';
44
-
45
- updated: any = () => {};
46
-
47
- constructor(providerArgs: IntProviderArgs) {
48
- const { item, baseHost, subPrefix = '', updated } = providerArgs;
49
-
50
- this.updated = updated;
51
-
52
- this.component = html`<ia-visual-mods
53
- @fullscreenToggle=${() => this?.updated('toggleFullscreen')}
54
- @openModa=${this.openModal}
55
- ></ia-visual-mods>`;
56
- }
57
-
58
- openModal() {}
59
-
60
- closeModal() {}
61
-
62
- toggleFullscreen() {
63
- this.updated('toggleFullscreen');
64
- }
65
- }