@internetarchive/elements 0.2.13-webdev-9022.1 → 0.2.13

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 (29) hide show
  1. package/dist/src/elements/index.d.ts +0 -1
  2. package/dist/src/elements/index.d.ts.map +1 -1
  3. package/dist/src/elements/index.js +0 -1
  4. package/dist/src/elements/index.js.map +1 -1
  5. package/package.json +1 -1
  6. package/dist/src/elements/ia-image-viewer/ia-image-viewer.d.ts +0 -147
  7. package/dist/src/elements/ia-image-viewer/ia-image-viewer.d.ts.map +0 -1
  8. package/dist/src/elements/ia-image-viewer/ia-image-viewer.js +0 -532
  9. package/dist/src/elements/ia-image-viewer/ia-image-viewer.js.map +0 -1
  10. package/dist/src/elements/ia-image-viewer/ia-imgview-controls.d.ts +0 -22
  11. package/dist/src/elements/ia-image-viewer/ia-imgview-controls.d.ts.map +0 -1
  12. package/dist/src/elements/ia-image-viewer/ia-imgview-controls.js +0 -157
  13. package/dist/src/elements/ia-image-viewer/ia-imgview-controls.js.map +0 -1
  14. package/dist/src/elements/ia-image-viewer/ia-imgview-slide.d.ts +0 -44
  15. package/dist/src/elements/ia-image-viewer/ia-imgview-slide.d.ts.map +0 -1
  16. package/dist/src/elements/ia-image-viewer/ia-imgview-slide.js +0 -225
  17. package/dist/src/elements/ia-image-viewer/ia-imgview-slide.js.map +0 -1
  18. package/dist/src/elements/ia-image-viewer/image-viewer-gestures.d.ts +0 -79
  19. package/dist/src/elements/ia-image-viewer/image-viewer-gestures.d.ts.map +0 -1
  20. package/dist/src/elements/ia-image-viewer/image-viewer-gestures.js +0 -254
  21. package/dist/src/elements/ia-image-viewer/image-viewer-gestures.js.map +0 -1
  22. package/dist/src/elements/ia-image-viewer/models.d.ts +0 -20
  23. package/dist/src/elements/ia-image-viewer/models.d.ts.map +0 -1
  24. package/dist/src/elements/ia-image-viewer/models.js +0 -2
  25. package/dist/src/elements/ia-image-viewer/models.js.map +0 -1
  26. package/dist/src/util/prefers-reduced-motion.d.ts +0 -10
  27. package/dist/src/util/prefers-reduced-motion.d.ts.map +0 -1
  28. package/dist/src/util/prefers-reduced-motion.js +0 -12
  29. package/dist/src/util/prefers-reduced-motion.js.map +0 -1
@@ -1,157 +0,0 @@
1
- import { __decorate } from "tslib";
2
- import { css, html, LitElement, } from 'lit';
3
- import { customElement, property } from 'lit/decorators.js';
4
- import { msg } from '@lit/localize';
5
- import themeStyles from '../../themes/theme-styles.js';
6
- /**
7
- * The image viewer's previous / next buttons and the "n / total" counter.
8
- *
9
- * Past the wide breakpoint the buttons position themselves over the image
10
- * area, which lives in the viewer's shadow root. That works because an
11
- * absolutely positioned element finds its containing block through the flat
12
- * tree, so the viewer's frame is still the reference as long as this element's
13
- * own host box stays unpositioned. The breakpoint queries the `image-viewer`
14
- * container by name, so it tracks the viewer's width rather than whichever
15
- * container a consumer happens to have further up the tree.
16
- */
17
- let IAImageViewerControls = class IAImageViewerControls extends LitElement {
18
- constructor() {
19
- super(...arguments);
20
- /** Zero-based index of the image being shown, for the counter. */
21
- this.currentIndex = 0;
22
- this.totalImages = 0;
23
- }
24
- render() {
25
- return html `
26
- <button
27
- class="nav-btn prev"
28
- aria-label=${msg('Previous image')}
29
- @click=${this.onPrevious}
30
- >
31
- &#8249;
32
- </button>
33
- <div class="counter">${this.currentIndex + 1} / ${this.totalImages}</div>
34
- <button
35
- class="nav-btn next"
36
- aria-label=${msg('Next image')}
37
- @click=${this.onNext}
38
- >
39
- &#8250;
40
- </button>
41
- `;
42
- }
43
- onPrevious() {
44
- this.dispatchEvent(new CustomEvent('showPrevious'));
45
- }
46
- onNext() {
47
- this.dispatchEvent(new CustomEvent('showNext'));
48
- }
49
- static get styles() {
50
- return [
51
- themeStyles,
52
- css `
53
- :host {
54
- --imgview-controls-text-color--: var(
55
- --image-viewer-text-color,
56
- var(--true-white)
57
- );
58
- --imgview-controls-btn-width--: var(
59
- --image-viewer-nav-button-width,
60
- 40px
61
- );
62
- --imgview-controls-btn-width-wide--: var(
63
- --image-viewer-nav-button-width-wide,
64
- 60px
65
- );
66
- --imgview-controls-focus-color--: var(
67
- --image-viewer-focus-outline-color,
68
- rgba(255, 255, 255, 0.8)
69
- );
70
-
71
- display: flex;
72
- align-items: center;
73
- justify-content: space-between;
74
- width: 100%;
75
- margin-top: 0.8rem;
76
- }
77
-
78
- .nav-btn {
79
- width: var(--imgview-controls-btn-width--);
80
- background: transparent;
81
- color: var(--imgview-controls-text-color--);
82
- border: none;
83
- cursor: pointer;
84
- font-size: 30px;
85
- display: flex;
86
- align-items: center;
87
- justify-content: center;
88
- opacity: 0.5;
89
- text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
90
- transition: opacity 0.15s;
91
- }
92
-
93
- .nav-btn:hover {
94
- opacity: 1;
95
- }
96
-
97
- .nav-btn:focus-visible {
98
- outline: 2px solid var(--imgview-controls-focus-color--);
99
- outline-offset: -2px;
100
- }
101
-
102
- .counter {
103
- color: var(--imgview-controls-text-color--);
104
- font-size: 14px;
105
- font-weight: 200;
106
- letter-spacing: 0.05em;
107
- }
108
-
109
- @media (prefers-reduced-motion: reduce) {
110
- .nav-btn {
111
- transition: none;
112
- }
113
- }
114
-
115
- @container image-viewer (min-width: 890px) {
116
- :host {
117
- position: static;
118
- width: auto;
119
- margin-top: 0;
120
- }
121
-
122
- .nav-btn {
123
- position: absolute;
124
- top: 0;
125
- bottom: 0;
126
- width: var(--imgview-controls-btn-width-wide--);
127
- font-size: 60px;
128
- z-index: 1;
129
- }
130
-
131
- .prev {
132
- left: 0;
133
- }
134
-
135
- .next {
136
- right: 0;
137
- }
138
-
139
- .counter {
140
- margin-top: 0.8rem;
141
- }
142
- }
143
- `,
144
- ];
145
- }
146
- };
147
- __decorate([
148
- property({ type: Number })
149
- ], IAImageViewerControls.prototype, "currentIndex", void 0);
150
- __decorate([
151
- property({ type: Number })
152
- ], IAImageViewerControls.prototype, "totalImages", void 0);
153
- IAImageViewerControls = __decorate([
154
- customElement('ia-imgview-controls')
155
- ], IAImageViewerControls);
156
- export { IAImageViewerControls };
157
- //# sourceMappingURL=ia-imgview-controls.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ia-imgview-controls.js","sourceRoot":"","sources":["../../../../src/elements/ia-image-viewer/ia-imgview-controls.ts"],"names":[],"mappings":";AAAA,OAAO,EACL,GAAG,EAEH,IAAI,EACJ,UAAU,GAEX,MAAM,KAAK,CAAC;AACb,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAEpC,OAAO,WAAW,MAAM,0BAA0B,CAAC;AAEnD;;;;;;;;;;GAUG;AAEI,IAAM,qBAAqB,GAA3B,MAAM,qBAAsB,SAAQ,UAAU;IAA9C;;QACL,kEAAkE;QACtC,iBAAY,GAAG,CAAC,CAAC;QAEjB,gBAAW,GAAG,CAAC,CAAC;IA+H9C,CAAC;IA7HC,MAAM;QACJ,OAAO,IAAI,CAAA;;;qBAGM,GAAG,CAAC,gBAAgB,CAAC;iBACzB,IAAI,CAAC,UAAU;;;;6BAIH,IAAI,CAAC,YAAY,GAAG,CAAC,MAAM,IAAI,CAAC,WAAW;;;qBAGnD,GAAG,CAAC,YAAY,CAAC;iBACrB,IAAI,CAAC,MAAM;;;;KAIvB,CAAC;IACJ,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC;IACtD,CAAC;IAEO,MAAM;QACZ,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,KAAK,MAAM;QACf,OAAO;YACL,WAAW;YACX,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2FF;SACF,CAAC;IACJ,CAAC;CACF,CAAA;AAjI6B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;2DAAkB;AAEjB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;0DAAiB;AAJjC,qBAAqB;IADjC,aAAa,CAAC,qBAAqB,CAAC;GACxB,qBAAqB,CAmIjC","sourcesContent":["import {\n css,\n type CSSResultGroup,\n html,\n LitElement,\n type TemplateResult,\n} from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { msg } from '@lit/localize';\n\nimport themeStyles from '@src/themes/theme-styles';\n\n/**\n * The image viewer's previous / next buttons and the \"n / total\" counter.\n *\n * Past the wide breakpoint the buttons position themselves over the image\n * area, which lives in the viewer's shadow root. That works because an\n * absolutely positioned element finds its containing block through the flat\n * tree, so the viewer's frame is still the reference as long as this element's\n * own host box stays unpositioned. The breakpoint queries the `image-viewer`\n * container by name, so it tracks the viewer's width rather than whichever\n * container a consumer happens to have further up the tree.\n */\n@customElement('ia-imgview-controls')\nexport class IAImageViewerControls extends LitElement {\n /** Zero-based index of the image being shown, for the counter. */\n @property({ type: Number }) currentIndex = 0;\n\n @property({ type: Number }) totalImages = 0;\n\n render(): TemplateResult {\n return html`\n <button\n class=\"nav-btn prev\"\n aria-label=${msg('Previous image')}\n @click=${this.onPrevious}\n >\n &#8249;\n </button>\n <div class=\"counter\">${this.currentIndex + 1} / ${this.totalImages}</div>\n <button\n class=\"nav-btn next\"\n aria-label=${msg('Next image')}\n @click=${this.onNext}\n >\n &#8250;\n </button>\n `;\n }\n\n private onPrevious(): void {\n this.dispatchEvent(new CustomEvent('showPrevious'));\n }\n\n private onNext(): void {\n this.dispatchEvent(new CustomEvent('showNext'));\n }\n\n static get styles(): CSSResultGroup {\n return [\n themeStyles,\n css`\n :host {\n --imgview-controls-text-color--: var(\n --image-viewer-text-color,\n var(--true-white)\n );\n --imgview-controls-btn-width--: var(\n --image-viewer-nav-button-width,\n 40px\n );\n --imgview-controls-btn-width-wide--: var(\n --image-viewer-nav-button-width-wide,\n 60px\n );\n --imgview-controls-focus-color--: var(\n --image-viewer-focus-outline-color,\n rgba(255, 255, 255, 0.8)\n );\n\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n margin-top: 0.8rem;\n }\n\n .nav-btn {\n width: var(--imgview-controls-btn-width--);\n background: transparent;\n color: var(--imgview-controls-text-color--);\n border: none;\n cursor: pointer;\n font-size: 30px;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 0.5;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n transition: opacity 0.15s;\n }\n\n .nav-btn:hover {\n opacity: 1;\n }\n\n .nav-btn:focus-visible {\n outline: 2px solid var(--imgview-controls-focus-color--);\n outline-offset: -2px;\n }\n\n .counter {\n color: var(--imgview-controls-text-color--);\n font-size: 14px;\n font-weight: 200;\n letter-spacing: 0.05em;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .nav-btn {\n transition: none;\n }\n }\n\n @container image-viewer (min-width: 890px) {\n :host {\n position: static;\n width: auto;\n margin-top: 0;\n }\n\n .nav-btn {\n position: absolute;\n top: 0;\n bottom: 0;\n width: var(--imgview-controls-btn-width-wide--);\n font-size: 60px;\n z-index: 1;\n }\n\n .prev {\n left: 0;\n }\n\n .next {\n right: 0;\n }\n\n .counter {\n margin-top: 0.8rem;\n }\n }\n `,\n ];\n }\n}\n"]}
@@ -1,44 +0,0 @@
1
- import { type CSSResultGroup, LitElement, nothing, type PropertyValues, type TemplateResult } from 'lit';
2
- import type { ImageViewerImage } from './models.js';
3
- /**
4
- * A single image in the viewer's track.
5
- *
6
- * Owns everything about one image: its load state, its failure message, and
7
- * the link that opens the full-size file. The viewer creates these both from
8
- * its template and by hand during a drag, so the element works with no
9
- * per-instance setup beyond its properties.
10
- */
11
- export declare class IAImageViewerSlide extends LitElement {
12
- image?: ImageViewerImage;
13
- private imageElement?;
14
- private loaded;
15
- private failed;
16
- protected willUpdate(changed: PropertyValues): void;
17
- protected updated(): void;
18
- render(): TemplateResult | typeof nothing;
19
- /**
20
- * Lets the viewer veto opening the image, which it does when the click is
21
- * the tail end of a swipe. A host can veto it too, to show the image its own
22
- * way instead of in a new tab.
23
- */
24
- private onClick;
25
- private markLoaded;
26
- private markFailed;
27
- /**
28
- * Tells the viewer what happened to this image, so it can pass failures on
29
- * to the host. Bubbles because the viewer listens on the track, which is
30
- * also where the slides it creates by hand during a drag end up.
31
- */
32
- private report;
33
- /**
34
- * Catches an image that finished before its listeners could fire, because
35
- * the browser had already resolved the request (from the cache or a
36
- * preload) by the time the element rendered.
37
- *
38
- * `complete` is true for a failed image as well as a loaded one, so the two
39
- * are told apart by `naturalWidth`, which stays 0 when the load failed.
40
- */
41
- private checkAlreadyResolved;
42
- static get styles(): CSSResultGroup;
43
- }
44
- //# sourceMappingURL=ia-imgview-slide.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ia-imgview-slide.d.ts","sourceRoot":"","sources":["../../../../src/elements/ia-image-viewer/ia-imgview-slide.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,cAAc,EAEnB,UAAU,EACV,OAAO,EACP,KAAK,cAAc,EACnB,KAAK,cAAc,EACpB,MAAM,KAAK,CAAC;AAMb,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD;;;;;;;GAOG;AACH,qBACa,kBAAmB,SAAQ,UAAU;IACpB,KAAK,CAAC,EAAE,gBAAgB,CAAC;IAE/B,OAAO,CAAC,YAAY,CAAC,CAAmB;IAErD,OAAO,CAAC,MAAM,CAAS;IAEvB,OAAO,CAAC,MAAM,CAAS;IAEhC,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAOnD,SAAS,CAAC,OAAO,IAAI,IAAI;IAIzB,MAAM,IAAI,cAAc,GAAG,OAAO,OAAO;IAiCzC;;;;OAIG;IACH,OAAO,CAAC,OAAO;IAYf,OAAO,CAAC,UAAU,CAIhB;IAEF,OAAO,CAAC,UAAU,CAIhB;IAEF;;;;OAIG;IACH,OAAO,CAAC,MAAM;IAOd;;;;;;;OAOG;IACH,OAAO,CAAC,oBAAoB;IAO5B,MAAM,KAAK,MAAM,IAAI,cAAc,CA6FlC;CACF"}
@@ -1,225 +0,0 @@
1
- import { __decorate } from "tslib";
2
- import { css, html, LitElement, nothing, } from 'lit';
3
- import { customElement, property, query, state } from 'lit/decorators.js';
4
- import { classMap } from 'lit/directives/class-map.js';
5
- import { msg } from '@lit/localize';
6
- import themeStyles from '../../themes/theme-styles.js';
7
- /**
8
- * A single image in the viewer's track.
9
- *
10
- * Owns everything about one image: its load state, its failure message, and
11
- * the link that opens the full-size file. The viewer creates these both from
12
- * its template and by hand during a drag, so the element works with no
13
- * per-instance setup beyond its properties.
14
- */
15
- let IAImageViewerSlide = class IAImageViewerSlide extends LitElement {
16
- constructor() {
17
- super(...arguments);
18
- this.loaded = false;
19
- this.failed = false;
20
- this.markLoaded = () => {
21
- this.loaded = true;
22
- this.failed = false;
23
- this.report('imageLoaded');
24
- };
25
- this.markFailed = () => {
26
- this.loaded = false;
27
- this.failed = true;
28
- this.report('imageFailed');
29
- };
30
- }
31
- willUpdate(changed) {
32
- if (changed.has('image')) {
33
- this.loaded = false;
34
- this.failed = false;
35
- }
36
- }
37
- updated() {
38
- this.checkAlreadyResolved();
39
- }
40
- render() {
41
- if (!this.image)
42
- return nothing;
43
- const imageClasses = { 'main-image': true, loaded: this.loaded };
44
- const linkClasses = { 'image-link': true, failed: this.failed };
45
- return html `
46
- <a
47
- class=${classMap(linkClasses)}
48
- href=${this.image.url}
49
- target="_blank"
50
- rel="noopener noreferrer"
51
- @click=${this.onClick}
52
- >
53
- <img
54
- class=${classMap(imageClasses)}
55
- src=${this.image.url}
56
- alt=${this.image.title ?? this.image.name}
57
- data-image-name=${this.image.name}
58
- draggable="false"
59
- @load=${this.markLoaded}
60
- @error=${this.markFailed}
61
- />
62
- <div class="loading-spinner"></div>
63
- ${this.failed
64
- ? html `<p class="image-failed">
65
- ${msg('This image could not be loaded.')}
66
- </p>`
67
- : nothing}
68
- </a>
69
- `;
70
- }
71
- /**
72
- * Lets the viewer veto opening the image, which it does when the click is
73
- * the tail end of a swipe. A host can veto it too, to show the image its own
74
- * way instead of in a new tab.
75
- */
76
- onClick(e) {
77
- if (!this.image)
78
- return;
79
- const allowed = this.dispatchEvent(new CustomEvent('imageActivated', {
80
- detail: { image: this.image },
81
- bubbles: true,
82
- cancelable: true,
83
- }));
84
- if (!allowed)
85
- e.preventDefault();
86
- }
87
- /**
88
- * Tells the viewer what happened to this image, so it can pass failures on
89
- * to the host. Bubbles because the viewer listens on the track, which is
90
- * also where the slides it creates by hand during a drag end up.
91
- */
92
- report(name) {
93
- if (!this.image)
94
- return;
95
- this.dispatchEvent(new CustomEvent(name, { detail: { image: this.image }, bubbles: true }));
96
- }
97
- /**
98
- * Catches an image that finished before its listeners could fire, because
99
- * the browser had already resolved the request (from the cache or a
100
- * preload) by the time the element rendered.
101
- *
102
- * `complete` is true for a failed image as well as a loaded one, so the two
103
- * are told apart by `naturalWidth`, which stays 0 when the load failed.
104
- */
105
- checkAlreadyResolved() {
106
- const img = this.imageElement;
107
- if (!img || this.loaded || this.failed || !img.complete)
108
- return;
109
- if (img.naturalWidth > 0)
110
- this.markLoaded();
111
- else
112
- this.markFailed();
113
- }
114
- static get styles() {
115
- return [
116
- themeStyles,
117
- css `
118
- :host {
119
- --imgview-slide-spinner-color--: var(
120
- --image-viewer-spinner-color,
121
- rgba(255, 255, 255, 0.5)
122
- );
123
- --imgview-slide-spinner-track-color--: var(
124
- --image-viewer-spinner-track-color,
125
- rgba(255, 255, 255, 0.15)
126
- );
127
- --imgview-slide-text-color--: var(
128
- --image-viewer-text-color,
129
- var(--true-white)
130
- );
131
- --imgview-slide-fade-duration--: var(
132
- --image-viewer-fade-duration,
133
- 0.2s
134
- );
135
-
136
- flex: 0 0 100%;
137
- height: 100%;
138
- display: flex;
139
- align-items: center;
140
- justify-content: center;
141
- position: relative;
142
- }
143
-
144
- .image-link {
145
- display: flex;
146
- align-items: center;
147
- justify-content: center;
148
- height: 100%;
149
- cursor: pointer;
150
- }
151
-
152
- .main-image {
153
- display: block;
154
- max-height: 100%;
155
- max-width: 100%;
156
- object-fit: contain;
157
- opacity: 0;
158
- transition: opacity var(--imgview-slide-fade-duration--) ease;
159
- user-select: none;
160
- }
161
-
162
- .main-image.loaded {
163
- opacity: 1;
164
- }
165
-
166
- .main-image.loaded + .loading-spinner,
167
- .image-link.failed .loading-spinner {
168
- display: none;
169
- }
170
-
171
- .loading-spinner {
172
- position: absolute;
173
- width: 24px;
174
- height: 24px;
175
- border: 2px solid var(--imgview-slide-spinner-track-color--);
176
- border-top-color: var(--imgview-slide-spinner-color--);
177
- border-radius: 50%;
178
- animation: spin 0.8s linear infinite;
179
- }
180
-
181
- @keyframes spin {
182
- to {
183
- transform: rotate(360deg);
184
- }
185
- }
186
-
187
- .image-failed {
188
- position: absolute;
189
- margin: 0;
190
- padding: 0 1.6rem;
191
- color: var(--imgview-slide-text-color--);
192
- font-size: 1.4rem;
193
- text-align: center;
194
- }
195
-
196
- @media (prefers-reduced-motion: reduce) {
197
- .loading-spinner {
198
- animation: none;
199
- }
200
-
201
- .main-image {
202
- transition: none;
203
- }
204
- }
205
- `,
206
- ];
207
- }
208
- };
209
- __decorate([
210
- property({ type: Object })
211
- ], IAImageViewerSlide.prototype, "image", void 0);
212
- __decorate([
213
- query('.main-image')
214
- ], IAImageViewerSlide.prototype, "imageElement", void 0);
215
- __decorate([
216
- state()
217
- ], IAImageViewerSlide.prototype, "loaded", void 0);
218
- __decorate([
219
- state()
220
- ], IAImageViewerSlide.prototype, "failed", void 0);
221
- IAImageViewerSlide = __decorate([
222
- customElement('ia-imgview-slide')
223
- ], IAImageViewerSlide);
224
- export { IAImageViewerSlide };
225
- //# sourceMappingURL=ia-imgview-slide.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ia-imgview-slide.js","sourceRoot":"","sources":["../../../../src/elements/ia-image-viewer/ia-imgview-slide.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n css,\n type CSSResultGroup,\n html,\n LitElement,\n nothing,\n type PropertyValues,\n type TemplateResult,\n} from 'lit';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { msg } from '@lit/localize';\n\nimport themeStyles from '@src/themes/theme-styles';\nimport type { ImageViewerImage } from './models';\n\n/**\n * A single image in the viewer's track.\n *\n * Owns everything about one image: its load state, its failure message, and\n * the link that opens the full-size file. The viewer creates these both from\n * its template and by hand during a drag, so the element works with no\n * per-instance setup beyond its properties.\n */\n@customElement('ia-imgview-slide')\nexport class IAImageViewerSlide extends LitElement {\n @property({ type: Object }) image?: ImageViewerImage;\n\n @query('.main-image') private imageElement?: HTMLImageElement;\n\n @state() private loaded = false;\n\n @state() private failed = false;\n\n protected willUpdate(changed: PropertyValues): void {\n if (changed.has('image')) {\n this.loaded = false;\n this.failed = false;\n }\n }\n\n protected updated(): void {\n this.checkAlreadyResolved();\n }\n\n render(): TemplateResult | typeof nothing {\n if (!this.image) return nothing;\n\n const imageClasses = { 'main-image': true, loaded: this.loaded };\n const linkClasses = { 'image-link': true, failed: this.failed };\n\n return html`\n <a\n class=${classMap(linkClasses)}\n href=${this.image.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n @click=${this.onClick}\n >\n <img\n class=${classMap(imageClasses)}\n src=${this.image.url}\n alt=${this.image.title ?? this.image.name}\n data-image-name=${this.image.name}\n draggable=\"false\"\n @load=${this.markLoaded}\n @error=${this.markFailed}\n />\n <div class=\"loading-spinner\"></div>\n ${this.failed\n ? html`<p class=\"image-failed\">\n ${msg('This image could not be loaded.')}\n </p>`\n : nothing}\n </a>\n `;\n }\n\n /**\n * Lets the viewer veto opening the image, which it does when the click is\n * the tail end of a swipe. A host can veto it too, to show the image its own\n * way instead of in a new tab.\n */\n private onClick(e: MouseEvent): void {\n if (!this.image) return;\n const allowed = this.dispatchEvent(\n new CustomEvent('imageActivated', {\n detail: { image: this.image },\n bubbles: true,\n cancelable: true,\n }),\n );\n if (!allowed) e.preventDefault();\n }\n\n private markLoaded = (): void => {\n this.loaded = true;\n this.failed = false;\n this.report('imageLoaded');\n };\n\n private markFailed = (): void => {\n this.loaded = false;\n this.failed = true;\n this.report('imageFailed');\n };\n\n /**\n * Tells the viewer what happened to this image, so it can pass failures on\n * to the host. Bubbles because the viewer listens on the track, which is\n * also where the slides it creates by hand during a drag end up.\n */\n private report(name: 'imageLoaded' | 'imageFailed'): void {\n if (!this.image) return;\n this.dispatchEvent(\n new CustomEvent(name, { detail: { image: this.image }, bubbles: true }),\n );\n }\n\n /**\n * Catches an image that finished before its listeners could fire, because\n * the browser had already resolved the request (from the cache or a\n * preload) by the time the element rendered.\n *\n * `complete` is true for a failed image as well as a loaded one, so the two\n * are told apart by `naturalWidth`, which stays 0 when the load failed.\n */\n private checkAlreadyResolved(): void {\n const img = this.imageElement;\n if (!img || this.loaded || this.failed || !img.complete) return;\n if (img.naturalWidth > 0) this.markLoaded();\n else this.markFailed();\n }\n\n static get styles(): CSSResultGroup {\n return [\n themeStyles,\n css`\n :host {\n --imgview-slide-spinner-color--: var(\n --image-viewer-spinner-color,\n rgba(255, 255, 255, 0.5)\n );\n --imgview-slide-spinner-track-color--: var(\n --image-viewer-spinner-track-color,\n rgba(255, 255, 255, 0.15)\n );\n --imgview-slide-text-color--: var(\n --image-viewer-text-color,\n var(--true-white)\n );\n --imgview-slide-fade-duration--: var(\n --image-viewer-fade-duration,\n 0.2s\n );\n\n flex: 0 0 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n position: relative;\n }\n\n .image-link {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n cursor: pointer;\n }\n\n .main-image {\n display: block;\n max-height: 100%;\n max-width: 100%;\n object-fit: contain;\n opacity: 0;\n transition: opacity var(--imgview-slide-fade-duration--) ease;\n user-select: none;\n }\n\n .main-image.loaded {\n opacity: 1;\n }\n\n .main-image.loaded + .loading-spinner,\n .image-link.failed .loading-spinner {\n display: none;\n }\n\n .loading-spinner {\n position: absolute;\n width: 24px;\n height: 24px;\n border: 2px solid var(--imgview-slide-spinner-track-color--);\n border-top-color: var(--imgview-slide-spinner-color--);\n border-radius: 50%;\n animation: spin 0.8s linear infinite;\n }\n\n @keyframes spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n .image-failed {\n position: absolute;\n margin: 0;\n padding: 0 1.6rem;\n color: var(--imgview-slide-text-color--);\n font-size: 1.4rem;\n text-align: center;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .loading-spinner {\n animation: none;\n }\n\n .main-image {\n transition: none;\n }\n }\n `,\n ];\n }\n}\n"]}
@@ -1,79 +0,0 @@
1
- import type { ReactiveController, ReactiveControllerHost } from 'lit';
2
- import type { SlideDirection } from './models.js';
3
- /** What the gesture controller needs from the viewer it drives. */
4
- export type ImageViewerGestureHost = ReactiveControllerHost & {
5
- readonly imageCount: number;
6
- readonly currentIndex: number;
7
- /** The element gestures are tracked against, once it has rendered. */
8
- readonly imageArea?: HTMLElement;
9
- /** The element a drag translates. */
10
- readonly slideTrack?: HTMLElement;
11
- /** Commits an in-flight slide animation so a new one starts from rest. */
12
- settleIfAnimating(): void;
13
- showNext(): void;
14
- showPrevious(): void;
15
- preloadAroundIndex(index: number): void;
16
- /** Adds the neighbouring slides a drag reveals on either side. */
17
- insertDragSlides(): void;
18
- removeDragSlides(): void;
19
- /** Advances to the neighbouring image a completed drag landed on. */
20
- commitDrag(direction: SlideDirection): void;
21
- };
22
- /**
23
- * Touch, wheel and keyboard navigation for the image viewer.
24
- *
25
- * A drag is driven imperatively: it translates the track directly and asks the
26
- * viewer to insert neighbouring slides by hand, because a re-render mid-gesture
27
- * would replace the element the touch started on and the browser would fire
28
- * touchcancel.
29
- */
30
- export declare class ImageViewerGestures implements ReactiveController {
31
- /** Whether a drag is in progress. The viewer reads this while rendering. */
32
- dragging: boolean;
33
- private host;
34
- /**
35
- * The element the touch and wheel listeners are currently on, so they can
36
- * follow the image area when it's replaced. A boolean wouldn't: the area is
37
- * removed whenever the image list empties, and a later refill renders a
38
- * different element.
39
- */
40
- private listeningTo;
41
- private touchStartX;
42
- private touchStartY;
43
- private touchStartTime;
44
- /** Whether the current gesture has locked in as a horizontal swipe */
45
- private swiping;
46
- /** Set when a swipe completes, so the tap it ends on doesn't open the image */
47
- private swipeHandled;
48
- private dragOffsetX;
49
- private wheelDeltaX;
50
- private wheelAnimating;
51
- private wheelAnimationEndTime;
52
- constructor(host: ImageViewerGestureHost);
53
- hostConnected(): void;
54
- hostUpdated(): void;
55
- hostDisconnected(): void;
56
- /**
57
- * Whether a swipe just ended on this tap, meaning the click that follows it
58
- * should be ignored rather than treated as opening the image.
59
- */
60
- consumeSwipeTap(): boolean;
61
- /** Lets wheel navigation resume once a slide animation has finished. */
62
- animationSettled(): void;
63
- /**
64
- * Points the gesture listeners at the current image area, moving them off
65
- * the previous one. The area isn't rendered until there are images to show,
66
- * and it's torn down and rebuilt whenever the list empties and refills, so
67
- * this runs on every update and re-attaches whenever the element changes.
68
- */
69
- private attachListeners;
70
- private detachListeners;
71
- private onTouchStart;
72
- private onTouchMove;
73
- private onTouchEnd;
74
- /** Applies the drag offset to the track during touch gestures. */
75
- private applyDragTransform;
76
- private onWheel;
77
- private onKeydown;
78
- }
79
- //# sourceMappingURL=image-viewer-gestures.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"image-viewer-gestures.d.ts","sourceRoot":"","sources":["../../../../src/elements/ia-image-viewer/image-viewer-gestures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,KAAK,CAAC;AAGtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,mEAAmE;AACnE,MAAM,MAAM,sBAAsB,GAAG,sBAAsB,GAAG;IAC5D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAE5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B,sEAAsE;IACtE,QAAQ,CAAC,SAAS,CAAC,EAAE,WAAW,CAAC;IAEjC,qCAAqC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC;IAElC,0EAA0E;IAC1E,iBAAiB,IAAI,IAAI,CAAC;IAE1B,QAAQ,IAAI,IAAI,CAAC;IAEjB,YAAY,IAAI,IAAI,CAAC;IAErB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAExC,kEAAkE;IAClE,gBAAgB,IAAI,IAAI,CAAC;IAEzB,gBAAgB,IAAI,IAAI,CAAC;IAEzB,qEAAqE;IACrE,UAAU,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAAC;CAC7C,CAAC;AA0BF;;;;;;;GAOG;AACH,qBAAa,mBAAoB,YAAW,kBAAkB;IAC5D,4EAA4E;IAC5E,QAAQ,UAAS;IAEjB,OAAO,CAAC,IAAI,CAAyB;IAErC;;;;;OAKG;IACH,OAAO,CAAC,WAAW,CAA4B;IAE/C,OAAO,CAAC,WAAW,CAAuB;IAE1C,OAAO,CAAC,WAAW,CAAuB;IAE1C,OAAO,CAAC,cAAc,CAAK;IAE3B,sEAAsE;IACtE,OAAO,CAAC,OAAO,CAAS;IAExB,+EAA+E;IAC/E,OAAO,CAAC,YAAY,CAAS;IAE7B,OAAO,CAAC,WAAW,CAAK;IAExB,OAAO,CAAC,WAAW,CAAK;IAExB,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,qBAAqB,CAAK;gBAEtB,IAAI,EAAE,sBAAsB;IAKxC,aAAa,IAAI,IAAI;IAOrB,WAAW,IAAI,IAAI;IAInB,gBAAgB,IAAI,IAAI;IAKxB;;;OAGG;IACH,eAAe,IAAI,OAAO;IAM1B,wEAAwE;IACxE,gBAAgB,IAAI,IAAI;IAMxB;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,YAAY,CASlB;IAEF,OAAO,CAAC,WAAW,CAmBjB;IAEF,OAAO,CAAC,UAAU,CAmFhB;IAEF,kEAAkE;IAClE,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,OAAO,CAyBb;IAEF,OAAO,CAAC,SAAS,CAOf;CACH"}