@internetarchive/elements 0.2.14-webdev-8969.0 → 0.3.0
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.
- package/README.md +20 -0
- package/dist/src/elements/ia-item-navigator/ia-item-navigator.d.ts +97 -0
- package/dist/src/elements/ia-item-navigator/ia-item-navigator.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/ia-item-navigator.js +588 -0
- package/dist/src/elements/ia-item-navigator/ia-item-navigator.js.map +1 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-menu-button.d.ts +39 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-menu-button.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-menu-button.js +249 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-menu-button.js.map +1 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-menu-slider.d.ts +55 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-menu-slider.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-menu-slider.js +394 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-menu-slider.js.map +1 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-no-theater-available.d.ts +20 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-no-theater-available.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-no-theater-available.js +102 -0
- package/dist/src/elements/ia-item-navigator/ia-itemnav-no-theater-available.js.map +1 -0
- package/dist/src/elements/ia-item-navigator/icons/collapse-sidebar.svg +7 -0
- package/dist/src/elements/ia-item-navigator/icons/ellipses.svg +7 -0
- package/dist/src/elements/ia-item-navigator/icons.d.ts +13 -0
- package/dist/src/elements/ia-item-navigator/icons.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/icons.js +16 -0
- package/dist/src/elements/ia-item-navigator/icons.js.map +1 -0
- package/dist/src/elements/ia-item-navigator/interfaces/event-interfaces.d.ts +41 -0
- package/dist/src/elements/ia-item-navigator/interfaces/event-interfaces.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/interfaces/event-interfaces.js +2 -0
- package/dist/src/elements/ia-item-navigator/interfaces/event-interfaces.js.map +1 -0
- package/dist/src/elements/ia-item-navigator/interfaces/menu-interfaces.d.ts +23 -0
- package/dist/src/elements/ia-item-navigator/interfaces/menu-interfaces.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/interfaces/menu-interfaces.js +2 -0
- package/dist/src/elements/ia-item-navigator/interfaces/menu-interfaces.js.map +1 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-share-panel.d.ts +47 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-share-panel.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-share-panel.js +352 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-share-panel.js.map +1 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-sort-files-button.d.ts +22 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-sort-files-button.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-sort-files-button.js +137 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-sort-files-button.js.map +1 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-viewable-files-panel.d.ts +40 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-viewable-files-panel.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-viewable-files-panel.js +217 -0
- package/dist/src/elements/ia-item-navigator/menus/ia-itemnav-viewable-files-panel.js.map +1 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/email.svg +6 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/facebook.svg +6 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/link.svg +6 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/list.svg +3 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/pinterest.svg +6 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/share.svg +6 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/sort-asc.svg +22 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/sort-desc.svg +21 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/sort-neutral.svg +13 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/tumblr.svg +6 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/twitter.svg +6 -0
- package/dist/src/elements/ia-item-navigator/menus/icons/viewable-files.svg +6 -0
- package/dist/src/elements/ia-item-navigator/menus/models.d.ts +17 -0
- package/dist/src/elements/ia-item-navigator/menus/models.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/menus/models.js +2 -0
- package/dist/src/elements/ia-item-navigator/menus/models.js.map +1 -0
- package/dist/src/elements/ia-item-navigator/menus/share-icons.d.ts +16 -0
- package/dist/src/elements/ia-item-navigator/menus/share-icons.d.ts.map +1 -0
- package/dist/src/elements/ia-item-navigator/menus/share-icons.js +23 -0
- package/dist/src/elements/ia-item-navigator/menus/share-icons.js.map +1 -0
- package/dist/src/elements/ia-playback-controls/ia-playback-controls.d.ts +12 -3
- package/dist/src/elements/ia-playback-controls/ia-playback-controls.d.ts.map +1 -1
- package/dist/src/elements/ia-playback-controls/ia-playback-controls.js +26 -9
- package/dist/src/elements/ia-playback-controls/ia-playback-controls.js.map +1 -1
- package/dist/src/elements/ia-status-indicator/ia-status-indicator.d.ts +51 -5
- package/dist/src/elements/ia-status-indicator/ia-status-indicator.d.ts.map +1 -1
- package/dist/src/elements/ia-status-indicator/ia-status-indicator.js +156 -16
- package/dist/src/elements/ia-status-indicator/ia-status-indicator.js.map +1 -1
- package/dist/src/elements/ia-status-indicator/icons/audio.svg +5 -0
- package/dist/src/elements/ia-status-indicator/icons/collection.svg +5 -0
- package/dist/src/elements/ia-status-indicator/icons/etree.svg +5 -0
- package/dist/src/elements/ia-status-indicator/icons/images.svg +6 -0
- package/dist/src/elements/ia-status-indicator/icons/search.svg +10 -0
- package/dist/src/elements/ia-status-indicator/icons/software.svg +6 -0
- package/dist/src/elements/ia-status-indicator/icons/texts.svg +6 -0
- package/dist/src/elements/ia-status-indicator/icons/tv.svg +5 -0
- package/dist/src/elements/ia-status-indicator/icons/video.svg +6 -0
- package/dist/src/elements/ia-status-indicator/icons/web.svg +6 -0
- package/dist/src/elements/ia-transcript-view/ia-transcript-view.d.ts +6 -0
- package/dist/src/elements/ia-transcript-view/ia-transcript-view.d.ts.map +1 -1
- package/dist/src/elements/ia-transcript-view/ia-transcript-view.js +20 -1
- package/dist/src/elements/ia-transcript-view/ia-transcript-view.js.map +1 -1
- package/dist/src/elements/index.d.ts +4 -0
- package/dist/src/elements/index.d.ts.map +1 -1
- package/dist/src/elements/index.js +4 -0
- package/dist/src/elements/index.js.map +1 -1
- package/dist/src/util/masked-icon.d.ts +24 -0
- package/dist/src/util/masked-icon.d.ts.map +1 -0
- package/dist/src/util/masked-icon.js +30 -0
- package/dist/src/util/masked-icon.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { css, html, LitElement, nothing, } from 'lit';
|
|
3
|
+
import { customElement, property, query } from 'lit/decorators.js';
|
|
4
|
+
import themeStyles from '../../themes/theme-styles.js';
|
|
5
|
+
import { collapseSidebarIcon } from './icons.js';
|
|
6
|
+
import './ia-itemnav-menu-button.js';
|
|
7
|
+
const sliderEvents = {
|
|
8
|
+
closeDrawer: 'menuSliderClosed',
|
|
9
|
+
closePanel: 'menuPanelClosed',
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* The sliding drawer that lists the navigator's menu providers and renders the
|
|
13
|
+
* body of whichever provider is currently selected.
|
|
14
|
+
*/
|
|
15
|
+
let IAItemNavMenuSlider = class IAItemNavMenuSlider extends LitElement {
|
|
16
|
+
constructor() {
|
|
17
|
+
super(...arguments);
|
|
18
|
+
this.menus = [];
|
|
19
|
+
/**
|
|
20
|
+
* Which panel is open. The navigator owns this — the slider only reports
|
|
21
|
+
* what the user did and renders whatever comes back, so there is one copy
|
|
22
|
+
* of the state rather than two that have to agree.
|
|
23
|
+
*/
|
|
24
|
+
this.selectedMenu = '';
|
|
25
|
+
this.selectedMenuAction = nothing;
|
|
26
|
+
/** Focus should follow what the user did, not the first render. */
|
|
27
|
+
this.isFirstRender = true;
|
|
28
|
+
}
|
|
29
|
+
updated(changed) {
|
|
30
|
+
const actionButton = this.selectedMenuDetails?.actionButton || nothing;
|
|
31
|
+
if (actionButton !== this.selectedMenuAction) {
|
|
32
|
+
this.selectedMenuAction = actionButton;
|
|
33
|
+
}
|
|
34
|
+
if (!this.isFirstRender && changed.has('selectedMenu')) {
|
|
35
|
+
this.moveFocusForSelection(changed.get('selectedMenu'));
|
|
36
|
+
}
|
|
37
|
+
this.isFirstRender = false;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Opening a panel moves focus into it, so it is announced by name; closing
|
|
41
|
+
* hands focus back to the button that opened it.
|
|
42
|
+
*/
|
|
43
|
+
moveFocusForSelection(previousMenu) {
|
|
44
|
+
if (this.selectedMenu) {
|
|
45
|
+
this.panel?.focus();
|
|
46
|
+
}
|
|
47
|
+
else if (previousMenu) {
|
|
48
|
+
this.menuButtonFor(previousMenu)?.focus();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
menuButtonFor(menuId) {
|
|
52
|
+
const buttons = this.menuList?.querySelectorAll('ia-itemnav-menu-button') ?? [];
|
|
53
|
+
return [...buttons].find((button) => button.buttonId === menuId);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Moves focus into the drawer — the open panel if there is one, otherwise
|
|
57
|
+
* the first thing worth acting on. Exposed so the navigator doesn't have to
|
|
58
|
+
* reach through this component's shadow DOM to place focus.
|
|
59
|
+
*/
|
|
60
|
+
focusDrawer() {
|
|
61
|
+
if (this.selectedMenu) {
|
|
62
|
+
this.panel?.focus();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const firstMenuButton = this.menuList?.querySelector('ia-itemnav-menu-button');
|
|
66
|
+
(firstMenuButton ?? this.drawerCloseButton)?.focus();
|
|
67
|
+
}
|
|
68
|
+
/** Asks the navigator to close the whole drawer. */
|
|
69
|
+
closeMenu() {
|
|
70
|
+
this.dispatchEvent(new CustomEvent(sliderEvents.closeDrawer, {
|
|
71
|
+
detail: this.selectedMenuDetails,
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
/** Asks the navigator to close just the open panel. */
|
|
75
|
+
closePanel() {
|
|
76
|
+
this.dispatchEvent(new CustomEvent(sliderEvents.closePanel, {
|
|
77
|
+
detail: { id: this.selectedMenu },
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
/** Escape closes the panel first, then the drawer. */
|
|
81
|
+
handleKeyDown(event) {
|
|
82
|
+
if (event.key !== 'Escape')
|
|
83
|
+
return;
|
|
84
|
+
event.preventDefault();
|
|
85
|
+
if (this.selectedMenu) {
|
|
86
|
+
this.closePanel();
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
this.closeMenu();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
get selectedMenuDetails() {
|
|
93
|
+
return this.menus.find((menu) => menu.id === this.selectedMenu);
|
|
94
|
+
}
|
|
95
|
+
/* render */
|
|
96
|
+
get selectedMenuClass() {
|
|
97
|
+
return this.selectedMenu ? 'open' : '';
|
|
98
|
+
}
|
|
99
|
+
get menuItems() {
|
|
100
|
+
return this.menus.map((menu) => html `
|
|
101
|
+
<li>
|
|
102
|
+
<ia-itemnav-menu-button
|
|
103
|
+
.icon=${menu.icon}
|
|
104
|
+
.label=${menu.label}
|
|
105
|
+
.menuDetails=${menu.menuDetails || ''}
|
|
106
|
+
.buttonId=${menu.id}
|
|
107
|
+
.selected=${menu.id === this.selectedMenu}
|
|
108
|
+
.followable=${menu.followable || false}
|
|
109
|
+
.href=${menu.href || ''}
|
|
110
|
+
></ia-itemnav-menu-button>
|
|
111
|
+
</li>
|
|
112
|
+
`);
|
|
113
|
+
}
|
|
114
|
+
get renderMenuHeader() {
|
|
115
|
+
const { label = '', menuDetails = '' } = this.selectedMenuDetails || {};
|
|
116
|
+
// `selectedMenuAction` defaults to Lit's `nothing` sentinel, which is
|
|
117
|
+
// truthy — so compare against it explicitly, otherwise the header would
|
|
118
|
+
// always get the secondary-action treatment (and an empty action span).
|
|
119
|
+
const hasAction = this.selectedMenuAction !== nothing;
|
|
120
|
+
const headerClass = hasAction ? 'with-secondary-action' : '';
|
|
121
|
+
const actionBlock = hasAction
|
|
122
|
+
? html `<span class="custom-action">${this.selectedMenuAction}</span>`
|
|
123
|
+
: nothing;
|
|
124
|
+
const closeLabel = label ? `Close ${label}` : 'Close this panel';
|
|
125
|
+
return html `
|
|
126
|
+
<header class=${headerClass}>
|
|
127
|
+
<div class="details">
|
|
128
|
+
<h3 id="panel-title">${label}</h3>
|
|
129
|
+
<span class="extra-details">${menuDetails}</span>
|
|
130
|
+
</div>
|
|
131
|
+
${actionBlock}
|
|
132
|
+
<button
|
|
133
|
+
class="close"
|
|
134
|
+
aria-label=${closeLabel}
|
|
135
|
+
title=${closeLabel}
|
|
136
|
+
@click=${this.closePanel}
|
|
137
|
+
>
|
|
138
|
+
${collapseSidebarIcon}
|
|
139
|
+
</button>
|
|
140
|
+
</header>
|
|
141
|
+
`;
|
|
142
|
+
}
|
|
143
|
+
get closeButton() {
|
|
144
|
+
return html `
|
|
145
|
+
<button
|
|
146
|
+
class="close"
|
|
147
|
+
aria-label="Close navigation"
|
|
148
|
+
title="Close navigation"
|
|
149
|
+
@click=${this.closeMenu}
|
|
150
|
+
>
|
|
151
|
+
${collapseSidebarIcon}
|
|
152
|
+
</button>
|
|
153
|
+
`;
|
|
154
|
+
}
|
|
155
|
+
/** @inheritdoc */
|
|
156
|
+
render() {
|
|
157
|
+
const panelOpen = !!this.selectedMenu;
|
|
158
|
+
return html `
|
|
159
|
+
<div class="main" @keydown=${this.handleKeyDown}>
|
|
160
|
+
<div class="menu">
|
|
161
|
+
${this.closeButton}
|
|
162
|
+
<ul class="menu-list" role="list">
|
|
163
|
+
${this.menuItems}
|
|
164
|
+
</ul>
|
|
165
|
+
<!-- Closed panels are inert so the tab order and the accessibility
|
|
166
|
+
tree agree with what is on screen; the slide is a consequence
|
|
167
|
+
of the class, not something to wait on. -->
|
|
168
|
+
<div
|
|
169
|
+
class="content ${this.selectedMenuClass}"
|
|
170
|
+
role="region"
|
|
171
|
+
aria-labelledby="panel-title"
|
|
172
|
+
tabindex="-1"
|
|
173
|
+
?inert=${!panelOpen}
|
|
174
|
+
>
|
|
175
|
+
${this.renderMenuHeader}
|
|
176
|
+
<section>
|
|
177
|
+
<div class="selected-menu">
|
|
178
|
+
${this.selectedMenuDetails?.component || nothing}
|
|
179
|
+
</div>
|
|
180
|
+
</section>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
`;
|
|
185
|
+
}
|
|
186
|
+
static get styles() {
|
|
187
|
+
const menuButtonWidth = css `42px`;
|
|
188
|
+
const sliderWidth = css `var(--item-navigator-menu-width--)`;
|
|
189
|
+
const transitionTiming = css `var(--item-navigator-animation-timing--)`;
|
|
190
|
+
return [
|
|
191
|
+
themeStyles,
|
|
192
|
+
css `
|
|
193
|
+
:host {
|
|
194
|
+
--item-navigator-menu-width--: var(
|
|
195
|
+
--item-navigator-menu-width,
|
|
196
|
+
320px
|
|
197
|
+
);
|
|
198
|
+
--item-navigator-animation-timing--: var(
|
|
199
|
+
--item-navigator-animation-timing,
|
|
200
|
+
200ms
|
|
201
|
+
);
|
|
202
|
+
--item-navigator-text-color--: var(
|
|
203
|
+
--item-navigator-text-color,
|
|
204
|
+
var(--true-white)
|
|
205
|
+
);
|
|
206
|
+
--item-navigator-menu-slider-bg--: var(
|
|
207
|
+
--item-navigator-menu-slider-bg,
|
|
208
|
+
#212121
|
|
209
|
+
);
|
|
210
|
+
--item-navigator-active-button-bg--: var(
|
|
211
|
+
--item-navigator-active-button-bg,
|
|
212
|
+
var(--mid-gray)
|
|
213
|
+
);
|
|
214
|
+
--item-navigator-border-color--: var(
|
|
215
|
+
--item-navigator-border-color,
|
|
216
|
+
#4b4b4b
|
|
217
|
+
);
|
|
218
|
+
/* Every glyph is square, so one knob sizes both axes. */
|
|
219
|
+
--item-navigator-header-icon-size--: var(
|
|
220
|
+
--item-navigator-header-icon-size,
|
|
221
|
+
2em
|
|
222
|
+
);
|
|
223
|
+
--item-navigator-icon-color--: var(
|
|
224
|
+
--item-navigator-icon-color,
|
|
225
|
+
var(--item-navigator-text-color--)
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
/* 10px base (petabox scale); internal sizing is em against it. */
|
|
229
|
+
--item-navigator-base-font-size--: var(
|
|
230
|
+
--item-navigator-base-font-size,
|
|
231
|
+
10px
|
|
232
|
+
);
|
|
233
|
+
font-size: var(--item-navigator-base-font-size--);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.main {
|
|
237
|
+
overflow: hidden;
|
|
238
|
+
width: 100%;
|
|
239
|
+
height: 100%;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/* The drawer's own slide is owned by the navigator's #menu; this just
|
|
243
|
+
fills it. */
|
|
244
|
+
.menu {
|
|
245
|
+
position: absolute;
|
|
246
|
+
top: 0;
|
|
247
|
+
left: 0;
|
|
248
|
+
bottom: 0;
|
|
249
|
+
width: ${sliderWidth};
|
|
250
|
+
padding: 0.5em 0.5em 0 0;
|
|
251
|
+
box-sizing: border-box;
|
|
252
|
+
font-size: 1.4em;
|
|
253
|
+
color: var(--item-navigator-text-color--);
|
|
254
|
+
background: var(--item-navigator-menu-slider-bg--);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
button {
|
|
258
|
+
cursor: pointer;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
header {
|
|
262
|
+
margin: 0 0 0.5em 0;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
header * {
|
|
266
|
+
margin: 0;
|
|
267
|
+
display: inline-block;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
header button {
|
|
271
|
+
cursor: pointer;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
header.with-secondary-action .details {
|
|
275
|
+
width: 80%;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
header .details {
|
|
279
|
+
font-weight: bold;
|
|
280
|
+
width: 88%;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
header .custom-action > *,
|
|
284
|
+
button.close {
|
|
285
|
+
padding: 0;
|
|
286
|
+
background-color: transparent;
|
|
287
|
+
border: 0;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
header .custom-action,
|
|
291
|
+
button.close {
|
|
292
|
+
position: absolute;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
button.close {
|
|
296
|
+
/* Reset to the base so the header icon (em) doesn't compound
|
|
297
|
+
against .menu's enlarged font-size. */
|
|
298
|
+
font-size: var(--item-navigator-base-font-size--);
|
|
299
|
+
min-width: 38px;
|
|
300
|
+
min-height: 38px;
|
|
301
|
+
display: flex;
|
|
302
|
+
justify-content: center;
|
|
303
|
+
align-items: center;
|
|
304
|
+
right: 0;
|
|
305
|
+
top: 0;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
button.close .ia-icon {
|
|
309
|
+
width: var(--item-navigator-header-icon-size--);
|
|
310
|
+
height: var(--item-navigator-header-icon-size--);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* Our glyphs are masked spans: the mask supplies the shape, this
|
|
314
|
+
supplies the paint. */
|
|
315
|
+
span.ia-icon {
|
|
316
|
+
background-color: var(--item-navigator-icon-color--);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/* Host-supplied icons may still be inline svg, so keep theming those
|
|
320
|
+
the original way. */
|
|
321
|
+
.ia-icon .fill-color {
|
|
322
|
+
fill: var(--item-navigator-icon-color--);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.content {
|
|
326
|
+
position: absolute;
|
|
327
|
+
top: 0;
|
|
328
|
+
right: 0;
|
|
329
|
+
bottom: 0;
|
|
330
|
+
left: ${menuButtonWidth};
|
|
331
|
+
z-index: 1;
|
|
332
|
+
transform: translateX(calc(${sliderWidth} * -1));
|
|
333
|
+
transition: var(
|
|
334
|
+
--item-navigator-panel-transition--,
|
|
335
|
+
transform ${transitionTiming} ease-out
|
|
336
|
+
);
|
|
337
|
+
background: var(--item-navigator-active-button-bg--);
|
|
338
|
+
border-right: 0.2em solid;
|
|
339
|
+
border-color: var(--item-navigator-border-color--);
|
|
340
|
+
padding: 0.5em 0 0 0.5em;
|
|
341
|
+
display: flex;
|
|
342
|
+
flex-direction: column;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.content.open {
|
|
346
|
+
transform: translateX(0);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
.content:focus {
|
|
350
|
+
outline: none;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.menu-list {
|
|
354
|
+
padding: 0;
|
|
355
|
+
margin: 0;
|
|
356
|
+
list-style: none;
|
|
357
|
+
background: var(--item-navigator-menu-slider-bg--);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.menu-list li {
|
|
361
|
+
margin-bottom: 0.2em;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.content > section {
|
|
365
|
+
overflow: auto;
|
|
366
|
+
overscroll-behavior: contain;
|
|
367
|
+
}
|
|
368
|
+
`,
|
|
369
|
+
];
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
__decorate([
|
|
373
|
+
property({ type: Array })
|
|
374
|
+
], IAItemNavMenuSlider.prototype, "menus", void 0);
|
|
375
|
+
__decorate([
|
|
376
|
+
property({ type: String })
|
|
377
|
+
], IAItemNavMenuSlider.prototype, "selectedMenu", void 0);
|
|
378
|
+
__decorate([
|
|
379
|
+
property({ type: Object })
|
|
380
|
+
], IAItemNavMenuSlider.prototype, "selectedMenuAction", void 0);
|
|
381
|
+
__decorate([
|
|
382
|
+
query('.content')
|
|
383
|
+
], IAItemNavMenuSlider.prototype, "panel", void 0);
|
|
384
|
+
__decorate([
|
|
385
|
+
query('.menu-list')
|
|
386
|
+
], IAItemNavMenuSlider.prototype, "menuList", void 0);
|
|
387
|
+
__decorate([
|
|
388
|
+
query('.menu > button.close')
|
|
389
|
+
], IAItemNavMenuSlider.prototype, "drawerCloseButton", void 0);
|
|
390
|
+
IAItemNavMenuSlider = __decorate([
|
|
391
|
+
customElement('ia-itemnav-menu-slider')
|
|
392
|
+
], IAItemNavMenuSlider);
|
|
393
|
+
export { IAItemNavMenuSlider };
|
|
394
|
+
//# sourceMappingURL=ia-itemnav-menu-slider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ia-itemnav-menu-slider.js","sourceRoot":"","sources":["../../../../src/elements/ia-item-navigator/ia-itemnav-menu-slider.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n css,\n html,\n LitElement,\n nothing,\n type PropertyValues,\n TemplateResult,\n type CSSResultGroup,\n} from 'lit';\nimport { customElement, property, query } from 'lit/decorators.js';\nimport themeStyles from '@src/themes/theme-styles';\nimport { collapseSidebarIcon } from './icons';\nimport './ia-itemnav-menu-button';\nimport type { IAItemNavMenuButton } from './ia-itemnav-menu-button';\nimport { MenuProviderInterface } from './interfaces/menu-interfaces';\n\nconst sliderEvents = {\n closeDrawer: 'menuSliderClosed',\n closePanel: 'menuPanelClosed',\n};\n\n/**\n * The sliding drawer that lists the navigator's menu providers and renders the\n * body of whichever provider is currently selected.\n */\n@customElement('ia-itemnav-menu-slider')\nexport class IAItemNavMenuSlider extends LitElement {\n @property({ type: Array }) menus: MenuProviderInterface[] = [];\n\n /**\n * Which panel is open. The navigator owns this — the slider only reports\n * what the user did and renders whatever comes back, so there is one copy\n * of the state rather than two that have to agree.\n */\n @property({ type: String }) selectedMenu = '';\n\n @property({ type: Object }) selectedMenuAction:\n | TemplateResult\n | typeof nothing = nothing;\n\n @query('.content') private panel?: HTMLElement;\n\n @query('.menu-list') private menuList?: HTMLUListElement;\n\n @query('.menu > button.close') private drawerCloseButton?: HTMLElement;\n\n /** Focus should follow what the user did, not the first render. */\n private isFirstRender = true;\n\n protected updated(changed: PropertyValues): void {\n const actionButton = this.selectedMenuDetails?.actionButton || nothing;\n if (actionButton !== this.selectedMenuAction) {\n this.selectedMenuAction = actionButton;\n }\n\n if (!this.isFirstRender && changed.has('selectedMenu')) {\n this.moveFocusForSelection(changed.get('selectedMenu') as string);\n }\n this.isFirstRender = false;\n }\n\n /**\n * Opening a panel moves focus into it, so it is announced by name; closing\n * hands focus back to the button that opened it.\n */\n private moveFocusForSelection(previousMenu: string): void {\n if (this.selectedMenu) {\n this.panel?.focus();\n } else if (previousMenu) {\n this.menuButtonFor(previousMenu)?.focus();\n }\n }\n\n private menuButtonFor(menuId: string): IAItemNavMenuButton | undefined {\n const buttons =\n this.menuList?.querySelectorAll<IAItemNavMenuButton>(\n 'ia-itemnav-menu-button',\n ) ?? [];\n return [...buttons].find((button) => button.buttonId === menuId);\n }\n\n /**\n * Moves focus into the drawer — the open panel if there is one, otherwise\n * the first thing worth acting on. Exposed so the navigator doesn't have to\n * reach through this component's shadow DOM to place focus.\n */\n focusDrawer(): void {\n if (this.selectedMenu) {\n this.panel?.focus();\n return;\n }\n const firstMenuButton = this.menuList?.querySelector<HTMLElement>(\n 'ia-itemnav-menu-button',\n );\n (firstMenuButton ?? this.drawerCloseButton)?.focus();\n }\n\n /** Asks the navigator to close the whole drawer. */\n closeMenu(): void {\n this.dispatchEvent(\n new CustomEvent(sliderEvents.closeDrawer, {\n detail: this.selectedMenuDetails,\n }),\n );\n }\n\n /** Asks the navigator to close just the open panel. */\n closePanel(): void {\n this.dispatchEvent(\n new CustomEvent(sliderEvents.closePanel, {\n detail: { id: this.selectedMenu },\n }),\n );\n }\n\n /** Escape closes the panel first, then the drawer. */\n handleKeyDown(event: KeyboardEvent): void {\n if (event.key !== 'Escape') return;\n event.preventDefault();\n if (this.selectedMenu) {\n this.closePanel();\n } else {\n this.closeMenu();\n }\n }\n\n get selectedMenuDetails(): MenuProviderInterface | undefined {\n return this.menus.find((menu) => menu.id === this.selectedMenu);\n }\n\n /* render */\n\n get selectedMenuClass(): string {\n return this.selectedMenu ? 'open' : '';\n }\n\n get menuItems(): TemplateResult[] {\n return this.menus.map(\n (menu) => html`\n <li>\n <ia-itemnav-menu-button\n .icon=${menu.icon}\n .label=${menu.label}\n .menuDetails=${menu.menuDetails || ''}\n .buttonId=${menu.id}\n .selected=${menu.id === this.selectedMenu}\n .followable=${menu.followable || false}\n .href=${menu.href || ''}\n ></ia-itemnav-menu-button>\n </li>\n `,\n );\n }\n\n get renderMenuHeader(): TemplateResult {\n const { label = '', menuDetails = '' } = this.selectedMenuDetails || {};\n // `selectedMenuAction` defaults to Lit's `nothing` sentinel, which is\n // truthy — so compare against it explicitly, otherwise the header would\n // always get the secondary-action treatment (and an empty action span).\n const hasAction = this.selectedMenuAction !== nothing;\n const headerClass = hasAction ? 'with-secondary-action' : '';\n const actionBlock = hasAction\n ? html`<span class=\"custom-action\">${this.selectedMenuAction}</span>`\n : nothing;\n const closeLabel = label ? `Close ${label}` : 'Close this panel';\n return html`\n <header class=${headerClass}>\n <div class=\"details\">\n <h3 id=\"panel-title\">${label}</h3>\n <span class=\"extra-details\">${menuDetails}</span>\n </div>\n ${actionBlock}\n <button\n class=\"close\"\n aria-label=${closeLabel}\n title=${closeLabel}\n @click=${this.closePanel}\n >\n ${collapseSidebarIcon}\n </button>\n </header>\n `;\n }\n\n get closeButton(): TemplateResult {\n return html`\n <button\n class=\"close\"\n aria-label=\"Close navigation\"\n title=\"Close navigation\"\n @click=${this.closeMenu}\n >\n ${collapseSidebarIcon}\n </button>\n `;\n }\n\n /** @inheritdoc */\n render(): TemplateResult {\n const panelOpen = !!this.selectedMenu;\n return html`\n <div class=\"main\" @keydown=${this.handleKeyDown}>\n <div class=\"menu\">\n ${this.closeButton}\n <ul class=\"menu-list\" role=\"list\">\n ${this.menuItems}\n </ul>\n <!-- Closed panels are inert so the tab order and the accessibility\n tree agree with what is on screen; the slide is a consequence\n of the class, not something to wait on. -->\n <div\n class=\"content ${this.selectedMenuClass}\"\n role=\"region\"\n aria-labelledby=\"panel-title\"\n tabindex=\"-1\"\n ?inert=${!panelOpen}\n >\n ${this.renderMenuHeader}\n <section>\n <div class=\"selected-menu\">\n ${this.selectedMenuDetails?.component || nothing}\n </div>\n </section>\n </div>\n </div>\n </div>\n `;\n }\n\n static get styles(): CSSResultGroup {\n const menuButtonWidth = css`42px`;\n const sliderWidth = css`var(--item-navigator-menu-width--)`;\n const transitionTiming = css`var(--item-navigator-animation-timing--)`;\n\n return [\n themeStyles,\n css`\n :host {\n --item-navigator-menu-width--: var(\n --item-navigator-menu-width,\n 320px\n );\n --item-navigator-animation-timing--: var(\n --item-navigator-animation-timing,\n 200ms\n );\n --item-navigator-text-color--: var(\n --item-navigator-text-color,\n var(--true-white)\n );\n --item-navigator-menu-slider-bg--: var(\n --item-navigator-menu-slider-bg,\n #212121\n );\n --item-navigator-active-button-bg--: var(\n --item-navigator-active-button-bg,\n var(--mid-gray)\n );\n --item-navigator-border-color--: var(\n --item-navigator-border-color,\n #4b4b4b\n );\n /* Every glyph is square, so one knob sizes both axes. */\n --item-navigator-header-icon-size--: var(\n --item-navigator-header-icon-size,\n 2em\n );\n --item-navigator-icon-color--: var(\n --item-navigator-icon-color,\n var(--item-navigator-text-color--)\n );\n\n /* 10px base (petabox scale); internal sizing is em against it. */\n --item-navigator-base-font-size--: var(\n --item-navigator-base-font-size,\n 10px\n );\n font-size: var(--item-navigator-base-font-size--);\n }\n\n .main {\n overflow: hidden;\n width: 100%;\n height: 100%;\n }\n\n /* The drawer's own slide is owned by the navigator's #menu; this just\n fills it. */\n .menu {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: ${sliderWidth};\n padding: 0.5em 0.5em 0 0;\n box-sizing: border-box;\n font-size: 1.4em;\n color: var(--item-navigator-text-color--);\n background: var(--item-navigator-menu-slider-bg--);\n }\n\n button {\n cursor: pointer;\n }\n\n header {\n margin: 0 0 0.5em 0;\n }\n\n header * {\n margin: 0;\n display: inline-block;\n }\n\n header button {\n cursor: pointer;\n }\n\n header.with-secondary-action .details {\n width: 80%;\n }\n\n header .details {\n font-weight: bold;\n width: 88%;\n }\n\n header .custom-action > *,\n button.close {\n padding: 0;\n background-color: transparent;\n border: 0;\n }\n\n header .custom-action,\n button.close {\n position: absolute;\n }\n\n button.close {\n /* Reset to the base so the header icon (em) doesn't compound\n against .menu's enlarged font-size. */\n font-size: var(--item-navigator-base-font-size--);\n min-width: 38px;\n min-height: 38px;\n display: flex;\n justify-content: center;\n align-items: center;\n right: 0;\n top: 0;\n }\n\n button.close .ia-icon {\n width: var(--item-navigator-header-icon-size--);\n height: var(--item-navigator-header-icon-size--);\n }\n\n /* Our glyphs are masked spans: the mask supplies the shape, this\n supplies the paint. */\n span.ia-icon {\n background-color: var(--item-navigator-icon-color--);\n }\n\n /* Host-supplied icons may still be inline svg, so keep theming those\n the original way. */\n .ia-icon .fill-color {\n fill: var(--item-navigator-icon-color--);\n }\n\n .content {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: ${menuButtonWidth};\n z-index: 1;\n transform: translateX(calc(${sliderWidth} * -1));\n transition: var(\n --item-navigator-panel-transition--,\n transform ${transitionTiming} ease-out\n );\n background: var(--item-navigator-active-button-bg--);\n border-right: 0.2em solid;\n border-color: var(--item-navigator-border-color--);\n padding: 0.5em 0 0 0.5em;\n display: flex;\n flex-direction: column;\n }\n\n .content.open {\n transform: translateX(0);\n }\n\n .content:focus {\n outline: none;\n }\n\n .menu-list {\n padding: 0;\n margin: 0;\n list-style: none;\n background: var(--item-navigator-menu-slider-bg--);\n }\n\n .menu-list li {\n margin-bottom: 0.2em;\n }\n\n .content > section {\n overflow: auto;\n overscroll-behavior: contain;\n }\n `,\n ];\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ia-itemnav-menu-slider': IAItemNavMenuSlider;\n }\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { LitElement, TemplateResult, PropertyValues, type CSSResultGroup } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* Placeholder shown in place of the theater when `viewAvailable` is false,
|
|
4
|
+
* i.e. the item has no files that can be experienced in the browser. Emits
|
|
5
|
+
* `loadingStateUpdated` so the navigator hides its loading spinner.
|
|
6
|
+
*/
|
|
7
|
+
export declare class IAItemNavNoTheaterAvailable extends LitElement {
|
|
8
|
+
identifier?: string;
|
|
9
|
+
emitLoaded(): void;
|
|
10
|
+
updated(changed: PropertyValues): void;
|
|
11
|
+
get downloadUrl(): string;
|
|
12
|
+
render(): TemplateResult;
|
|
13
|
+
static get styles(): CSSResultGroup;
|
|
14
|
+
}
|
|
15
|
+
declare global {
|
|
16
|
+
interface HTMLElementTagNameMap {
|
|
17
|
+
'ia-itemnav-no-theater-available': IAItemNavNoTheaterAvailable;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=ia-itemnav-no-theater-available.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ia-itemnav-no-theater-available.d.ts","sourceRoot":"","sources":["../../../../src/elements/ia-item-navigator/ia-itemnav-no-theater-available.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EAEV,cAAc,EACd,cAAc,EAEd,KAAK,cAAc,EACpB,MAAM,KAAK,CAAC;AAIb;;;;GAIG;AACH,qBACa,2BAA4B,SAAQ,UAAU;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAM;IAErD,UAAU,IAAI,IAAI;IAQlB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAMtC,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,MAAM,IAAI,cAAc;IAexB,MAAM,KAAK,MAAM,IAAI,cAAc,CAmDlC;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,iCAAiC,EAAE,2BAA2B,CAAC;KAChE;CACF"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { LitElement, html, css, } from 'lit';
|
|
3
|
+
import { customElement, property } from 'lit/decorators.js';
|
|
4
|
+
import themeStyles from '../../themes/theme-styles.js';
|
|
5
|
+
/**
|
|
6
|
+
* Placeholder shown in place of the theater when `viewAvailable` is false,
|
|
7
|
+
* i.e. the item has no files that can be experienced in the browser. Emits
|
|
8
|
+
* `loadingStateUpdated` so the navigator hides its loading spinner.
|
|
9
|
+
*/
|
|
10
|
+
let IAItemNavNoTheaterAvailable = class IAItemNavNoTheaterAvailable extends LitElement {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.identifier = '';
|
|
14
|
+
}
|
|
15
|
+
emitLoaded() {
|
|
16
|
+
this.dispatchEvent(new CustomEvent('loadingStateUpdated', {
|
|
17
|
+
detail: { loaded: true },
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
updated(changed) {
|
|
21
|
+
if (changed.has('identifier')) {
|
|
22
|
+
this.emitLoaded();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
get downloadUrl() {
|
|
26
|
+
return `/download/${this.identifier}`;
|
|
27
|
+
}
|
|
28
|
+
render() {
|
|
29
|
+
return html `
|
|
30
|
+
<section>
|
|
31
|
+
<h2>THERE IS NO PREVIEW AVAILABLE FOR THIS ITEM</h2>
|
|
32
|
+
<p>
|
|
33
|
+
This item does not appear to have any files that can be experienced on
|
|
34
|
+
Archive.org. <br />
|
|
35
|
+
Please download files in this item to interact with them on your
|
|
36
|
+
computer.
|
|
37
|
+
</p>
|
|
38
|
+
<a href=${this.downloadUrl}>Show all files</a>
|
|
39
|
+
</section>
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
static get styles() {
|
|
43
|
+
return [
|
|
44
|
+
themeStyles,
|
|
45
|
+
css `
|
|
46
|
+
:host {
|
|
47
|
+
--item-navigator-text-color--: var(
|
|
48
|
+
--item-navigator-text-color,
|
|
49
|
+
var(--true-white)
|
|
50
|
+
);
|
|
51
|
+
color: var(--item-navigator-text-color--);
|
|
52
|
+
text-align: center;
|
|
53
|
+
/* 10px base (petabox scale); internal sizing is em against it. */
|
|
54
|
+
--item-navigator-base-font-size--: var(
|
|
55
|
+
--item-navigator-base-font-size,
|
|
56
|
+
10px
|
|
57
|
+
);
|
|
58
|
+
font-size: var(--item-navigator-base-font-size--);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
section {
|
|
62
|
+
width: 100%;
|
|
63
|
+
margin: 5%;
|
|
64
|
+
padding: 0 5%;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
p {
|
|
68
|
+
font-size: 1.4em;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
a {
|
|
72
|
+
color: var(--item-navigator-text-color--);
|
|
73
|
+
background-color: var(--navy-blue);
|
|
74
|
+
min-height: 35px;
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
line-height: normal;
|
|
77
|
+
border-radius: 0.4em;
|
|
78
|
+
text-align: center;
|
|
79
|
+
vertical-align: middle;
|
|
80
|
+
font-size: 1.4em;
|
|
81
|
+
font-family: var(--base-font-family);
|
|
82
|
+
display: inline-block;
|
|
83
|
+
padding: 0.85em 1.2em;
|
|
84
|
+
border: 1px solid var(--lightest-gray);
|
|
85
|
+
white-space: nowrap;
|
|
86
|
+
appearance: auto;
|
|
87
|
+
box-sizing: border-box;
|
|
88
|
+
user-select: none;
|
|
89
|
+
text-decoration: none;
|
|
90
|
+
}
|
|
91
|
+
`,
|
|
92
|
+
];
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
__decorate([
|
|
96
|
+
property({ type: String })
|
|
97
|
+
], IAItemNavNoTheaterAvailable.prototype, "identifier", void 0);
|
|
98
|
+
IAItemNavNoTheaterAvailable = __decorate([
|
|
99
|
+
customElement('ia-itemnav-no-theater-available')
|
|
100
|
+
], IAItemNavNoTheaterAvailable);
|
|
101
|
+
export { IAItemNavNoTheaterAvailable };
|
|
102
|
+
//# sourceMappingURL=ia-itemnav-no-theater-available.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ia-itemnav-no-theater-available.js","sourceRoot":"","sources":["../../../../src/elements/ia-item-navigator/ia-itemnav-no-theater-available.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,UAAU,EACV,IAAI,EAGJ,GAAG,GAEJ,MAAM,KAAK,CAAC;AACb,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,WAAW,MAAM,0BAA0B,CAAC;AAEnD;;;;GAIG;AAEI,IAAM,2BAA2B,GAAjC,MAAM,2BAA4B,SAAQ,UAAU;IAApD;;QACuB,eAAU,GAAY,EAAE,CAAC;IAuFvD,CAAC;IArFC,UAAU;QACR,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAsB,qBAAqB,EAAE;YAC1D,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;SACzB,CAAC,CACH,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,OAAuB;QAC7B,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9B,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED,IAAI,WAAW;QACb,OAAO,aAAa,IAAI,CAAC,UAAU,EAAE,CAAC;IACxC,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAA;;;;;;;;;kBASG,IAAI,CAAC,WAAW;;KAE7B,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,MAAM;QACf,OAAO;YACL,WAAW;YACX,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8CF;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AAvF6B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;+DAA0B;AAD1C,2BAA2B;IADvC,aAAa,CAAC,iCAAiC,CAAC;GACpC,2BAA2B,CAwFvC","sourcesContent":["import {\n LitElement,\n html,\n TemplateResult,\n PropertyValues,\n css,\n type CSSResultGroup,\n} from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport themeStyles from '@src/themes/theme-styles';\n\n/**\n * Placeholder shown in place of the theater when `viewAvailable` is false,\n * i.e. the item has no files that can be experienced in the browser. Emits\n * `loadingStateUpdated` so the navigator hides its loading spinner.\n */\n@customElement('ia-itemnav-no-theater-available')\nexport class IAItemNavNoTheaterAvailable extends LitElement {\n @property({ type: String }) identifier?: string = '';\n\n emitLoaded(): void {\n this.dispatchEvent(\n new CustomEvent<{ loaded: boolean }>('loadingStateUpdated', {\n detail: { loaded: true },\n }),\n );\n }\n\n updated(changed: PropertyValues): void {\n if (changed.has('identifier')) {\n this.emitLoaded();\n }\n }\n\n get downloadUrl(): string {\n return `/download/${this.identifier}`;\n }\n\n render(): TemplateResult {\n return html`\n <section>\n <h2>THERE IS NO PREVIEW AVAILABLE FOR THIS ITEM</h2>\n <p>\n This item does not appear to have any files that can be experienced on\n Archive.org. <br />\n Please download files in this item to interact with them on your\n computer.\n </p>\n <a href=${this.downloadUrl}>Show all files</a>\n </section>\n `;\n }\n\n static get styles(): CSSResultGroup {\n return [\n themeStyles,\n css`\n :host {\n --item-navigator-text-color--: var(\n --item-navigator-text-color,\n var(--true-white)\n );\n color: var(--item-navigator-text-color--);\n text-align: center;\n /* 10px base (petabox scale); internal sizing is em against it. */\n --item-navigator-base-font-size--: var(\n --item-navigator-base-font-size,\n 10px\n );\n font-size: var(--item-navigator-base-font-size--);\n }\n\n section {\n width: 100%;\n margin: 5%;\n padding: 0 5%;\n }\n\n p {\n font-size: 1.4em;\n }\n\n a {\n color: var(--item-navigator-text-color--);\n background-color: var(--navy-blue);\n min-height: 35px;\n cursor: pointer;\n line-height: normal;\n border-radius: 0.4em;\n text-align: center;\n vertical-align: middle;\n font-size: 1.4em;\n font-family: var(--base-font-family);\n display: inline-block;\n padding: 0.85em 1.2em;\n border: 1px solid var(--lightest-gray);\n white-space: nowrap;\n appearance: auto;\n box-sizing: border-box;\n user-select: none;\n text-decoration: none;\n }\n `,\n ];\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ia-itemnav-no-theater-available': IAItemNavNoTheaterAvailable;\n }\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path
|
|
3
|
+
fill="#000"
|
|
4
|
+
fill-rule="evenodd"
|
|
5
|
+
d="m9 0c4.9705627 0 9 4.02943725 9 9 0 4.9705627-4.0294373 9-9 9-4.97056275 0-9-4.0294373-9-9 0-4.97056275 4.02943725-9 9-9zm1.6976167 5.28352881c-.365258-.3556459-.9328083-.37581056-1.32099801-.06558269l-.09308988.0844372-3 3.08108108-.08194436.09533317c-.27484337.36339327-.26799482.87009349.01656959 1.22592581l.084491.09308363 3 2.91891889.09533796.0818904c.3633964.2746544.8699472.2677153 1.2256839-.0167901l.093059-.0844712.0818904-.095338c.2746544-.3633964.2677153-.8699472-.0167901-1.2256839l-.0844712-.093059-2.283355-2.2222741 2.3024712-2.36338332.0819252-.09530804c.2997677-.39632298.2644782-.96313393-.1007797-1.31877983z"
|
|
6
|
+
/>
|
|
7
|
+
</svg>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<svg viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path
|
|
3
|
+
fill="#000"
|
|
4
|
+
fill-rule="evenodd"
|
|
5
|
+
d="m10.5 17.5c1.3807119 0 2.5 1.1192881 2.5 2.5s-1.1192881 2.5-2.5 2.5c-1.38071187 0-2.5-1.1192881-2.5-2.5s1.11928813-2.5 2.5-2.5zm9.5 0c1.3807119 0 2.5 1.1192881 2.5 2.5s-1.1192881 2.5-2.5 2.5-2.5-1.1192881-2.5-2.5 1.1192881-2.5 2.5-2.5zm9.5 0c1.3807119 0 2.5 1.1192881 2.5 2.5s-1.1192881 2.5-2.5 2.5-2.5-1.1192881-2.5-2.5 1.1192881-2.5 2.5-2.5z"
|
|
6
|
+
/>
|
|
7
|
+
</svg>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Icons taken from the `@internetarchive/icon-ellipses` and
|
|
3
|
+
* `@internetarchive/icon-collapse-sidebar` packages (v1.4.1). They ship as
|
|
4
|
+
* standalone `.svg` files — rather than icon package dependencies or inline
|
|
5
|
+
* templates — so their path data stays out of the JS bundle. Each is rendered
|
|
6
|
+
* as a CSS-masked span (see `maskedIcon`) so host components can still recolor
|
|
7
|
+
* it via their own custom properties.
|
|
8
|
+
*/
|
|
9
|
+
/** Three-dot "more options" glyph used by the menu toggle button. */
|
|
10
|
+
export declare const ellipsesIcon: import("lit").TemplateResult;
|
|
11
|
+
/** Circular "collapse sidebar" glyph used by the menu/panel close buttons. */
|
|
12
|
+
export declare const collapseSidebarIcon: import("lit").TemplateResult;
|
|
13
|
+
//# sourceMappingURL=icons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../../src/elements/ia-item-navigator/icons.ts"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AAEH,qEAAqE;AACrE,eAAO,MAAM,YAAY,8BAA0B,CAAC;AAEpD,8EAA8E;AAC9E,eAAO,MAAM,mBAAmB,8BAAiC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { maskedIcon } from '../../util/masked-icon.js';
|
|
2
|
+
import ellipsesUrl from './icons/ellipses.svg';
|
|
3
|
+
import collapseSidebarUrl from './icons/collapse-sidebar.svg';
|
|
4
|
+
/**
|
|
5
|
+
* Icons taken from the `@internetarchive/icon-ellipses` and
|
|
6
|
+
* `@internetarchive/icon-collapse-sidebar` packages (v1.4.1). They ship as
|
|
7
|
+
* standalone `.svg` files — rather than icon package dependencies or inline
|
|
8
|
+
* templates — so their path data stays out of the JS bundle. Each is rendered
|
|
9
|
+
* as a CSS-masked span (see `maskedIcon`) so host components can still recolor
|
|
10
|
+
* it via their own custom properties.
|
|
11
|
+
*/
|
|
12
|
+
/** Three-dot "more options" glyph used by the menu toggle button. */
|
|
13
|
+
export const ellipsesIcon = maskedIcon(ellipsesUrl);
|
|
14
|
+
/** Circular "collapse sidebar" glyph used by the menu/panel close buttons. */
|
|
15
|
+
export const collapseSidebarIcon = maskedIcon(collapseSidebarUrl);
|
|
16
|
+
//# sourceMappingURL=icons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.js","sourceRoot":"","sources":["../../../../src/elements/ia-item-navigator/icons.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,OAAO,WAAW,MAAM,sBAAsB,CAAC;AAC/C,OAAO,kBAAkB,MAAM,8BAA8B,CAAC;AAE9D;;;;;;;GAOG;AAEH,qEAAqE;AACrE,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;AAEpD,8EAA8E;AAC9E,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAC","sourcesContent":["import { maskedIcon } from '@src/util/masked-icon';\n\nimport ellipsesUrl from './icons/ellipses.svg';\nimport collapseSidebarUrl from './icons/collapse-sidebar.svg';\n\n/**\n * Icons taken from the `@internetarchive/icon-ellipses` and\n * `@internetarchive/icon-collapse-sidebar` packages (v1.4.1). They ship as\n * standalone `.svg` files — rather than icon package dependencies or inline\n * templates — so their path data stays out of the JS bundle. Each is rendered\n * as a CSS-masked span (see `maskedIcon`) so host components can still recolor\n * it via their own custom properties.\n */\n\n/** Three-dot \"more options\" glyph used by the menu toggle button. */\nexport const ellipsesIcon = maskedIcon(ellipsesUrl);\n\n/** Circular \"collapse sidebar\" glyph used by the menu/panel close buttons. */\nexport const collapseSidebarIcon = maskedIcon(collapseSidebarUrl);\n"]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { MenuProviderInterface, MenuShortcutInterface, MenuId } from './menu-interfaces.js';
|
|
2
|
+
/** Toggles Menu && Sets open panel */
|
|
3
|
+
export interface ToggleSideMenuOpenEvent extends CustomEvent {
|
|
4
|
+
type: 'updateSideMenu';
|
|
5
|
+
detail: {
|
|
6
|
+
menuId: MenuId | undefined | '';
|
|
7
|
+
action: 'open' | 'toggle' | '';
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/** Sets open panel */
|
|
11
|
+
export interface ToggleSidePanelOpenEvent extends CustomEvent {
|
|
12
|
+
type: 'menuTypeSelected';
|
|
13
|
+
detail: {
|
|
14
|
+
id: MenuId | '';
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Sets menu order that is displayed */
|
|
18
|
+
export interface SetSideMenuContentsEvent extends CustomEvent {
|
|
19
|
+
type: 'menuUpdated';
|
|
20
|
+
detail: MenuProviderInterface[];
|
|
21
|
+
}
|
|
22
|
+
/** Sets menu shortcuts that is displayed */
|
|
23
|
+
export interface SetSideMenuShortcutsEvent extends CustomEvent {
|
|
24
|
+
type: 'menuUpdated';
|
|
25
|
+
detail: MenuShortcutInterface[];
|
|
26
|
+
}
|
|
27
|
+
/** Toggles fullscreen mode */
|
|
28
|
+
export interface ManageFullscreenEvent extends CustomEvent {
|
|
29
|
+
type: 'ViewportInFullScreen';
|
|
30
|
+
detail: {
|
|
31
|
+
isFullScreen: boolean;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Toggles loading view */
|
|
35
|
+
export interface LoadingStateUpdatedEvent extends CustomEvent {
|
|
36
|
+
type: 'loadingStateUpdated';
|
|
37
|
+
detail: {
|
|
38
|
+
loaded: boolean;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=event-interfaces.d.ts.map
|