@internetarchive/ia-item-navigator 0.0.0-a8 → 0.0.2-a1

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