@phosart/common 0.4.55 → 0.4.57
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/dist/Image.svelte +6 -2
- package/dist/Image.svelte.d.ts +1 -0
- package/dist/Image.svelte.d.ts.map +1 -1
- package/dist/ModalGallery/ImageSection.svelte +126 -30
- package/dist/ModalGallery/ImageSection.svelte.d.ts.map +1 -1
- package/dist/ModalGallery/ImageView.svelte +2 -3
- package/dist/ModalGallery/ImageView.svelte.d.ts +2 -1
- package/dist/ModalGallery/ImageView.svelte.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/lib/Image.svelte +6 -2
- package/src/lib/ModalGallery/ImageSection.svelte +126 -30
- package/src/lib/ModalGallery/ImageView.svelte +2 -3
package/dist/Image.svelte
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
loading?: boolean;
|
|
16
16
|
transformSrc?: (src: string) => string;
|
|
17
17
|
nsfw?: boolean;
|
|
18
|
+
lqipFit?: 'cover' | 'contain';
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
let {
|
|
@@ -26,7 +27,8 @@
|
|
|
26
27
|
controls = false,
|
|
27
28
|
nolqip = false,
|
|
28
29
|
loading = $bindable(true),
|
|
29
|
-
transformSrc: userTransformSrc
|
|
30
|
+
transformSrc: userTransformSrc,
|
|
31
|
+
lqipFit = 'contain'
|
|
30
32
|
}: Props = $props();
|
|
31
33
|
|
|
32
34
|
const config = useLibraryConfig();
|
|
@@ -43,7 +45,9 @@
|
|
|
43
45
|
let src = $derived(highRes ? onlyHighRes(picture) : no4K(picture));
|
|
44
46
|
|
|
45
47
|
let background = $derived(
|
|
46
|
-
!nolqip && src.lqip && showBackground
|
|
48
|
+
!nolqip && src.lqip && showBackground
|
|
49
|
+
? `url(${src.lqip.src}) no-repeat center/${lqipFit}`
|
|
50
|
+
: 'none'
|
|
47
51
|
);
|
|
48
52
|
|
|
49
53
|
$effect(() => {
|
package/dist/Image.svelte.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Image.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Image.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,KAAK,IAAI,UAAU,EAAQ,MAAM,eAAe,CAAC;AAO3E,UAAU,KAAK;IACd,OAAO,EAAE,UAAU,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Image.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Image.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,KAAK,IAAI,UAAU,EAAQ,MAAM,eAAe,CAAC;AAO3E,UAAU,KAAK;IACd,OAAO,EAAE,UAAU,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC9B;AA4HF,QAAA,MAAM,KAAK,kDAAwC,CAAC;AACpD,KAAK,KAAK,GAAG,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;AACtC,eAAe,KAAK,CAAC"}
|
|
@@ -27,19 +27,23 @@
|
|
|
27
27
|
parseInt(getComputedStyle(document.documentElement).getPropertyValue('--info-height') ?? '100')
|
|
28
28
|
);
|
|
29
29
|
|
|
30
|
+
let altWidth: number = $state(0);
|
|
30
31
|
let containerWidth: number = $state(0);
|
|
31
32
|
let containerHeight: number = $state(0);
|
|
32
33
|
let containerHeightLessInfo = $derived(Math.max(0, containerHeight - infoHeight));
|
|
34
|
+
let containerWidthLessAlt = $derived(containerWidth - altWidth);
|
|
33
35
|
let isComic = $derived(piece.alts_display === 'comic_panels');
|
|
34
36
|
let bounded: HTMLDivElement | null = $state(null);
|
|
37
|
+
let selectedAlt: number | null = $state(null);
|
|
35
38
|
|
|
36
39
|
function scale(image: Picture) {
|
|
37
40
|
const scaleByHeight =
|
|
38
41
|
!isComic &&
|
|
39
|
-
|
|
42
|
+
containerWidthLessAlt / containerHeightLessInfo >
|
|
43
|
+
image.full.fallback.w / image.full.fallback.h;
|
|
40
44
|
const scalingFactor: number = scaleByHeight
|
|
41
45
|
? containerHeightLessInfo / image.full.fallback.h
|
|
42
|
-
:
|
|
46
|
+
: containerWidthLessAlt / image.full.fallback.w;
|
|
43
47
|
|
|
44
48
|
return scalingFactor;
|
|
45
49
|
}
|
|
@@ -148,35 +152,101 @@
|
|
|
148
152
|
bind:this={bounded}
|
|
149
153
|
>
|
|
150
154
|
<div class="flex flex-col">
|
|
151
|
-
<div
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
e
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
e
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
155
|
+
<div class="flex">
|
|
156
|
+
<div
|
|
157
|
+
class="bounded-div"
|
|
158
|
+
onkeypress={(e) => {
|
|
159
|
+
e.stopPropagation();
|
|
160
|
+
scrollDown();
|
|
161
|
+
}}
|
|
162
|
+
onclick={(e) => {
|
|
163
|
+
e.stopPropagation();
|
|
164
|
+
}}
|
|
165
|
+
role="button"
|
|
166
|
+
tabindex={-1}
|
|
167
|
+
style="
|
|
168
|
+
z-index: 2; width: {w}px; height: {h}px;{isComic
|
|
169
|
+
? ' border-radius: 12px 12px 0 0;'
|
|
170
|
+
: piece.alts && piece.alts.length > 0
|
|
171
|
+
? ' border-radius: 12px 0 0 12px;'
|
|
172
|
+
: ''}"
|
|
173
|
+
>
|
|
174
|
+
<ImageView bind:selectedAlt {piece} {nameInHeader}>
|
|
175
|
+
{#snippet display(image, onloaded)}
|
|
176
|
+
<div class="image-container">
|
|
177
|
+
<Image
|
|
178
|
+
video={image.video?.full}
|
|
179
|
+
controls
|
|
180
|
+
picture={image.image.full}
|
|
181
|
+
alt={image.alt}
|
|
182
|
+
nsfw={image.nsfw}
|
|
183
|
+
{onloaded}
|
|
184
|
+
/>
|
|
185
|
+
</div>
|
|
186
|
+
{/snippet}
|
|
187
|
+
</ImageView>
|
|
188
|
+
</div>
|
|
189
|
+
{#if piece.alts && piece.alts.length > 0}
|
|
190
|
+
<div
|
|
191
|
+
bind:clientWidth={altWidth}
|
|
192
|
+
style="background-color: transparent; width:75px; position: relative"
|
|
193
|
+
>
|
|
194
|
+
{#each piece.alts as alt, i ('alt-' + JSON.stringify(alt))}
|
|
195
|
+
{@const isOriginal = i === selectedAlt}
|
|
196
|
+
{@const selPiece = isOriginal ? piece : alt}
|
|
197
|
+
{@const top = (i * h) / piece.alts.length}
|
|
198
|
+
{@const WRatio = 75 / selPiece.image.full.fallback.w}
|
|
199
|
+
{@const myH = selPiece.image.full.fallback.h * WRatio}
|
|
200
|
+
|
|
201
|
+
<div>
|
|
202
|
+
<button
|
|
203
|
+
onclick={(e) => {
|
|
204
|
+
e.stopPropagation();
|
|
205
|
+
selectedAlt = isOriginal ? null : i;
|
|
206
|
+
}}
|
|
207
|
+
tabindex={-1}
|
|
208
|
+
class="altcarry"
|
|
209
|
+
style="top: {top}px; width:75px; height: {h /
|
|
210
|
+
piece.alts.length}px; overflow:hidden; position: absolute; z-index: 1;"
|
|
211
|
+
>
|
|
212
|
+
<div
|
|
213
|
+
style="width: 75px; height: {Math.max(
|
|
214
|
+
myH,
|
|
215
|
+
h / piece.alts.length
|
|
216
|
+
)}px; min-height: {myH}px; position:absolute; top:0;right:0;"
|
|
217
|
+
>
|
|
218
|
+
<div class="image-container objr" style="top: 0; object-fit: cover">
|
|
219
|
+
<Image
|
|
220
|
+
video={selPiece.video?.full}
|
|
221
|
+
controls
|
|
222
|
+
picture={selPiece.image.full}
|
|
223
|
+
alt={selPiece.alt}
|
|
224
|
+
loading={false}
|
|
225
|
+
nolqip
|
|
226
|
+
/>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
</button>
|
|
230
|
+
<div
|
|
231
|
+
class="alt-tooltip"
|
|
232
|
+
style="z-index: 3; height: 2rem; text-overflow: elipsis; top: calc({top}px + 1rem); color: white; padding: 0.5rem; position: absolute; left: -9rem; width: 8rem; display: flex; justify-content: end; align-items: center;"
|
|
233
|
+
>
|
|
234
|
+
<div
|
|
235
|
+
style="background-color: #0009; border-radius: 0.25rem; padding: 0 0.25rem"
|
|
236
|
+
>
|
|
237
|
+
{#if isOriginal}
|
|
238
|
+
Back to Original Piece
|
|
239
|
+
{:else}
|
|
240
|
+
Alt: {alt.name}
|
|
241
|
+
{/if}
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
{/each}
|
|
246
|
+
</div>
|
|
247
|
+
{/if}
|
|
178
248
|
</div>
|
|
179
|
-
{#if isComic && piece.alts}
|
|
249
|
+
{#if isComic && piece.alts && piece.alts.length > 0}
|
|
180
250
|
{#each piece.alts as alt, i (JSON.stringify(alt))}
|
|
181
251
|
<div
|
|
182
252
|
class="bounded-div"
|
|
@@ -287,4 +357,30 @@
|
|
|
287
357
|
left: 0;
|
|
288
358
|
right: 0;
|
|
289
359
|
}
|
|
360
|
+
|
|
361
|
+
.objr :global(img) {
|
|
362
|
+
object-position: right center;
|
|
363
|
+
object-fit: cover;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.altcarry {
|
|
367
|
+
right: 1rem;
|
|
368
|
+
transition:
|
|
369
|
+
right 0.2s ease-in-out,
|
|
370
|
+
clip-path 0.2s ease-in-out;
|
|
371
|
+
clip-path: inset(0 0 0 16px);
|
|
372
|
+
}
|
|
373
|
+
.altcarry:hover {
|
|
374
|
+
right: 0rem;
|
|
375
|
+
clip-path: inset(0 0 0 0);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.altcarry:hover ~ .alt-tooltip {
|
|
379
|
+
opacity: 1;
|
|
380
|
+
}
|
|
381
|
+
.alt-tooltip {
|
|
382
|
+
opacity: 0;
|
|
383
|
+
user-select: none;
|
|
384
|
+
transition: opacity 0.2s ease-in-out;
|
|
385
|
+
}
|
|
290
386
|
</style>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageSection.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/ModalGallery/ImageSection.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,+CAA+C,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAW,MAAM,gBAAgB,CAAC;AAMvD,UAAU,KAAK;IACd,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,IAAI,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"ImageSection.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/ModalGallery/ImageSection.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,+CAA+C,CAAC;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAW,MAAM,gBAAgB,CAAC;AAMvD,UAAU,KAAK;IACd,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,IAAI,CAAC;CACnB;AAsNF,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -14,17 +14,16 @@
|
|
|
14
14
|
display: Snippet<
|
|
15
15
|
[image: ArtPiece | NonNullable<ArtPiece['alts']>[number], onloaded: () => void]
|
|
16
16
|
>;
|
|
17
|
+
selectedAlt?: number | null;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
let { piece, nameInHeader, display }: Props = $props();
|
|
20
|
+
let { piece, nameInHeader, display, selectedAlt = $bindable(null) }: Props = $props();
|
|
20
21
|
|
|
21
22
|
let config = useLibraryConfig();
|
|
22
23
|
|
|
23
24
|
let loading = $state(true);
|
|
24
25
|
let showingDescription = $state(false);
|
|
25
26
|
|
|
26
|
-
let selectedAlt: number | null = $state(null);
|
|
27
|
-
|
|
28
27
|
let image = $derived(typeof selectedAlt === 'number' ? piece.alts![selectedAlt] : piece);
|
|
29
28
|
|
|
30
29
|
run(() => {
|
|
@@ -7,8 +7,9 @@ interface Props {
|
|
|
7
7
|
image: ArtPiece | NonNullable<ArtPiece['alts']>[number],
|
|
8
8
|
onloaded: () => void
|
|
9
9
|
]>;
|
|
10
|
+
selectedAlt?: number | null;
|
|
10
11
|
}
|
|
11
|
-
declare const ImageView: import("svelte").Component<Props, {}, "">;
|
|
12
|
+
declare const ImageView: import("svelte").Component<Props, {}, "selectedAlt">;
|
|
12
13
|
type ImageView = ReturnType<typeof ImageView>;
|
|
13
14
|
export default ImageView;
|
|
14
15
|
//# sourceMappingURL=ImageView.svelte.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ImageView.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/ModalGallery/ImageView.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGrC,UAAU,KAAK;IACd,KAAK,EAAE,QAAQ,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CACf;QAAC,KAAK,EAAE,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAAE,QAAQ,EAAE,MAAM,IAAI;KAAC,CAC/E,CAAC;
|
|
1
|
+
{"version":3,"file":"ImageView.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/ModalGallery/ImageView.svelte.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGrC,UAAU,KAAK;IACd,KAAK,EAAE,QAAQ,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CACf;QAAC,KAAK,EAAE,QAAQ,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;QAAE,QAAQ,EAAE,MAAM,IAAI;KAAC,CAC/E,CAAC;IACF,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AA2CF,QAAA,MAAM,SAAS,sDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|
package/package.json
CHANGED
package/src/lib/Image.svelte
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
loading?: boolean;
|
|
16
16
|
transformSrc?: (src: string) => string;
|
|
17
17
|
nsfw?: boolean;
|
|
18
|
+
lqipFit?: 'cover' | 'contain';
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
let {
|
|
@@ -26,7 +27,8 @@
|
|
|
26
27
|
controls = false,
|
|
27
28
|
nolqip = false,
|
|
28
29
|
loading = $bindable(true),
|
|
29
|
-
transformSrc: userTransformSrc
|
|
30
|
+
transformSrc: userTransformSrc,
|
|
31
|
+
lqipFit = 'contain'
|
|
30
32
|
}: Props = $props();
|
|
31
33
|
|
|
32
34
|
const config = useLibraryConfig();
|
|
@@ -43,7 +45,9 @@
|
|
|
43
45
|
let src = $derived(highRes ? onlyHighRes(picture) : no4K(picture));
|
|
44
46
|
|
|
45
47
|
let background = $derived(
|
|
46
|
-
!nolqip && src.lqip && showBackground
|
|
48
|
+
!nolqip && src.lqip && showBackground
|
|
49
|
+
? `url(${src.lqip.src}) no-repeat center/${lqipFit}`
|
|
50
|
+
: 'none'
|
|
47
51
|
);
|
|
48
52
|
|
|
49
53
|
$effect(() => {
|
|
@@ -27,19 +27,23 @@
|
|
|
27
27
|
parseInt(getComputedStyle(document.documentElement).getPropertyValue('--info-height') ?? '100')
|
|
28
28
|
);
|
|
29
29
|
|
|
30
|
+
let altWidth: number = $state(0);
|
|
30
31
|
let containerWidth: number = $state(0);
|
|
31
32
|
let containerHeight: number = $state(0);
|
|
32
33
|
let containerHeightLessInfo = $derived(Math.max(0, containerHeight - infoHeight));
|
|
34
|
+
let containerWidthLessAlt = $derived(containerWidth - altWidth);
|
|
33
35
|
let isComic = $derived(piece.alts_display === 'comic_panels');
|
|
34
36
|
let bounded: HTMLDivElement | null = $state(null);
|
|
37
|
+
let selectedAlt: number | null = $state(null);
|
|
35
38
|
|
|
36
39
|
function scale(image: Picture) {
|
|
37
40
|
const scaleByHeight =
|
|
38
41
|
!isComic &&
|
|
39
|
-
|
|
42
|
+
containerWidthLessAlt / containerHeightLessInfo >
|
|
43
|
+
image.full.fallback.w / image.full.fallback.h;
|
|
40
44
|
const scalingFactor: number = scaleByHeight
|
|
41
45
|
? containerHeightLessInfo / image.full.fallback.h
|
|
42
|
-
:
|
|
46
|
+
: containerWidthLessAlt / image.full.fallback.w;
|
|
43
47
|
|
|
44
48
|
return scalingFactor;
|
|
45
49
|
}
|
|
@@ -148,35 +152,101 @@
|
|
|
148
152
|
bind:this={bounded}
|
|
149
153
|
>
|
|
150
154
|
<div class="flex flex-col">
|
|
151
|
-
<div
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
e
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
e
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
155
|
+
<div class="flex">
|
|
156
|
+
<div
|
|
157
|
+
class="bounded-div"
|
|
158
|
+
onkeypress={(e) => {
|
|
159
|
+
e.stopPropagation();
|
|
160
|
+
scrollDown();
|
|
161
|
+
}}
|
|
162
|
+
onclick={(e) => {
|
|
163
|
+
e.stopPropagation();
|
|
164
|
+
}}
|
|
165
|
+
role="button"
|
|
166
|
+
tabindex={-1}
|
|
167
|
+
style="
|
|
168
|
+
z-index: 2; width: {w}px; height: {h}px;{isComic
|
|
169
|
+
? ' border-radius: 12px 12px 0 0;'
|
|
170
|
+
: piece.alts && piece.alts.length > 0
|
|
171
|
+
? ' border-radius: 12px 0 0 12px;'
|
|
172
|
+
: ''}"
|
|
173
|
+
>
|
|
174
|
+
<ImageView bind:selectedAlt {piece} {nameInHeader}>
|
|
175
|
+
{#snippet display(image, onloaded)}
|
|
176
|
+
<div class="image-container">
|
|
177
|
+
<Image
|
|
178
|
+
video={image.video?.full}
|
|
179
|
+
controls
|
|
180
|
+
picture={image.image.full}
|
|
181
|
+
alt={image.alt}
|
|
182
|
+
nsfw={image.nsfw}
|
|
183
|
+
{onloaded}
|
|
184
|
+
/>
|
|
185
|
+
</div>
|
|
186
|
+
{/snippet}
|
|
187
|
+
</ImageView>
|
|
188
|
+
</div>
|
|
189
|
+
{#if piece.alts && piece.alts.length > 0}
|
|
190
|
+
<div
|
|
191
|
+
bind:clientWidth={altWidth}
|
|
192
|
+
style="background-color: transparent; width:75px; position: relative"
|
|
193
|
+
>
|
|
194
|
+
{#each piece.alts as alt, i ('alt-' + JSON.stringify(alt))}
|
|
195
|
+
{@const isOriginal = i === selectedAlt}
|
|
196
|
+
{@const selPiece = isOriginal ? piece : alt}
|
|
197
|
+
{@const top = (i * h) / piece.alts.length}
|
|
198
|
+
{@const WRatio = 75 / selPiece.image.full.fallback.w}
|
|
199
|
+
{@const myH = selPiece.image.full.fallback.h * WRatio}
|
|
200
|
+
|
|
201
|
+
<div>
|
|
202
|
+
<button
|
|
203
|
+
onclick={(e) => {
|
|
204
|
+
e.stopPropagation();
|
|
205
|
+
selectedAlt = isOriginal ? null : i;
|
|
206
|
+
}}
|
|
207
|
+
tabindex={-1}
|
|
208
|
+
class="altcarry"
|
|
209
|
+
style="top: {top}px; width:75px; height: {h /
|
|
210
|
+
piece.alts.length}px; overflow:hidden; position: absolute; z-index: 1;"
|
|
211
|
+
>
|
|
212
|
+
<div
|
|
213
|
+
style="width: 75px; height: {Math.max(
|
|
214
|
+
myH,
|
|
215
|
+
h / piece.alts.length
|
|
216
|
+
)}px; min-height: {myH}px; position:absolute; top:0;right:0;"
|
|
217
|
+
>
|
|
218
|
+
<div class="image-container objr" style="top: 0; object-fit: cover">
|
|
219
|
+
<Image
|
|
220
|
+
video={selPiece.video?.full}
|
|
221
|
+
controls
|
|
222
|
+
picture={selPiece.image.full}
|
|
223
|
+
alt={selPiece.alt}
|
|
224
|
+
loading={false}
|
|
225
|
+
nolqip
|
|
226
|
+
/>
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
</button>
|
|
230
|
+
<div
|
|
231
|
+
class="alt-tooltip"
|
|
232
|
+
style="z-index: 3; height: 2rem; text-overflow: elipsis; top: calc({top}px + 1rem); color: white; padding: 0.5rem; position: absolute; left: -9rem; width: 8rem; display: flex; justify-content: end; align-items: center;"
|
|
233
|
+
>
|
|
234
|
+
<div
|
|
235
|
+
style="background-color: #0009; border-radius: 0.25rem; padding: 0 0.25rem"
|
|
236
|
+
>
|
|
237
|
+
{#if isOriginal}
|
|
238
|
+
Back to Original Piece
|
|
239
|
+
{:else}
|
|
240
|
+
Alt: {alt.name}
|
|
241
|
+
{/if}
|
|
242
|
+
</div>
|
|
243
|
+
</div>
|
|
244
|
+
</div>
|
|
245
|
+
{/each}
|
|
246
|
+
</div>
|
|
247
|
+
{/if}
|
|
178
248
|
</div>
|
|
179
|
-
{#if isComic && piece.alts}
|
|
249
|
+
{#if isComic && piece.alts && piece.alts.length > 0}
|
|
180
250
|
{#each piece.alts as alt, i (JSON.stringify(alt))}
|
|
181
251
|
<div
|
|
182
252
|
class="bounded-div"
|
|
@@ -287,4 +357,30 @@
|
|
|
287
357
|
left: 0;
|
|
288
358
|
right: 0;
|
|
289
359
|
}
|
|
360
|
+
|
|
361
|
+
.objr :global(img) {
|
|
362
|
+
object-position: right center;
|
|
363
|
+
object-fit: cover;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.altcarry {
|
|
367
|
+
right: 1rem;
|
|
368
|
+
transition:
|
|
369
|
+
right 0.2s ease-in-out,
|
|
370
|
+
clip-path 0.2s ease-in-out;
|
|
371
|
+
clip-path: inset(0 0 0 16px);
|
|
372
|
+
}
|
|
373
|
+
.altcarry:hover {
|
|
374
|
+
right: 0rem;
|
|
375
|
+
clip-path: inset(0 0 0 0);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.altcarry:hover ~ .alt-tooltip {
|
|
379
|
+
opacity: 1;
|
|
380
|
+
}
|
|
381
|
+
.alt-tooltip {
|
|
382
|
+
opacity: 0;
|
|
383
|
+
user-select: none;
|
|
384
|
+
transition: opacity 0.2s ease-in-out;
|
|
385
|
+
}
|
|
290
386
|
</style>
|
|
@@ -14,17 +14,16 @@
|
|
|
14
14
|
display: Snippet<
|
|
15
15
|
[image: ArtPiece | NonNullable<ArtPiece['alts']>[number], onloaded: () => void]
|
|
16
16
|
>;
|
|
17
|
+
selectedAlt?: number | null;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
let { piece, nameInHeader, display }: Props = $props();
|
|
20
|
+
let { piece, nameInHeader, display, selectedAlt = $bindable(null) }: Props = $props();
|
|
20
21
|
|
|
21
22
|
let config = useLibraryConfig();
|
|
22
23
|
|
|
23
24
|
let loading = $state(true);
|
|
24
25
|
let showingDescription = $state(false);
|
|
25
26
|
|
|
26
|
-
let selectedAlt: number | null = $state(null);
|
|
27
|
-
|
|
28
27
|
let image = $derived(typeof selectedAlt === 'number' ? piece.alts![selectedAlt] : piece);
|
|
29
28
|
|
|
30
29
|
run(() => {
|