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

Sign up to get free protection for your applications and to get access to all the features.
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
- }