@phosart/common 0.4.22
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 +58 -0
- package/dist/FullGallery.svelte +51 -0
- package/dist/FullGallery.svelte.d.ts +17 -0
- package/dist/FullGallery.svelte.d.ts.map +1 -0
- package/dist/Gallery.svelte +30 -0
- package/dist/Gallery.svelte.d.ts +14 -0
- package/dist/Gallery.svelte.d.ts.map +1 -0
- package/dist/GalleryPreview.svelte +60 -0
- package/dist/GalleryPreview.svelte.d.ts +9 -0
- package/dist/GalleryPreview.svelte.d.ts.map +1 -0
- package/dist/HighResContext.svelte +21 -0
- package/dist/HighResContext.svelte.d.ts +8 -0
- package/dist/HighResContext.svelte.d.ts.map +1 -0
- package/dist/Image.svelte +171 -0
- package/dist/Image.svelte.d.ts +14 -0
- package/dist/Image.svelte.d.ts.map +1 -0
- package/dist/Modal.svelte +87 -0
- package/dist/Modal.svelte.d.ts +9 -0
- package/dist/Modal.svelte.d.ts.map +1 -0
- package/dist/ModalGallery/Carousel.svelte +76 -0
- package/dist/ModalGallery/Carousel.svelte.d.ts +10 -0
- package/dist/ModalGallery/Carousel.svelte.d.ts.map +1 -0
- package/dist/ModalGallery/ImageSection.svelte +156 -0
- package/dist/ModalGallery/ImageSection.svelte.d.ts +11 -0
- package/dist/ModalGallery/ImageSection.svelte.d.ts.map +1 -0
- package/dist/ModalGallery/ImageView.svelte +92 -0
- package/dist/ModalGallery/ImageView.svelte.d.ts +9 -0
- package/dist/ModalGallery/ImageView.svelte.d.ts.map +1 -0
- package/dist/ModalGallery/Spinner.svelte +71 -0
- package/dist/ModalGallery/Spinner.svelte.d.ts +7 -0
- package/dist/ModalGallery/Spinner.svelte.d.ts.map +1 -0
- package/dist/ModalGallery.svelte +165 -0
- package/dist/ModalGallery.svelte.d.ts +16 -0
- package/dist/ModalGallery.svelte.d.ts.map +1 -0
- package/dist/OpengraphMeta.svelte +125 -0
- package/dist/OpengraphMeta.svelte.d.ts +15 -0
- package/dist/OpengraphMeta.svelte.d.ts.map +1 -0
- package/dist/Postcard/ArtistLink.svelte +46 -0
- package/dist/Postcard/ArtistLink.svelte.d.ts +9 -0
- package/dist/Postcard/ArtistLink.svelte.d.ts.map +1 -0
- package/dist/Postcard/Chip.svelte +100 -0
- package/dist/Postcard/Chip.svelte.d.ts +12 -0
- package/dist/Postcard/Chip.svelte.d.ts.map +1 -0
- package/dist/Postcard/Description/Character.svelte +79 -0
- package/dist/Postcard/Description/Character.svelte.d.ts +9 -0
- package/dist/Postcard/Description/Character.svelte.d.ts.map +1 -0
- package/dist/Postcard/Description.svelte +146 -0
- package/dist/Postcard/Description.svelte.d.ts +13 -0
- package/dist/Postcard/Description.svelte.d.ts.map +1 -0
- package/dist/Postcard/Headline.svelte +70 -0
- package/dist/Postcard/Headline.svelte.d.ts +10 -0
- package/dist/Postcard/Headline.svelte.d.ts.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/server/artist.d.ts +7 -0
- package/dist/server/artist.d.ts.map +1 -0
- package/dist/server/artist.js +40 -0
- package/dist/server/character.d.ts +9 -0
- package/dist/server/character.d.ts.map +1 -0
- package/dist/server/character.js +76 -0
- package/dist/server/directories.d.ts +4 -0
- package/dist/server/directories.d.ts.map +1 -0
- package/dist/server/directories.js +39 -0
- package/dist/server/fastcache.d.ts +11 -0
- package/dist/server/fastcache.d.ts.map +1 -0
- package/dist/server/fastcache.js +43 -0
- package/dist/server/filter.d.ts +6 -0
- package/dist/server/filter.d.ts.map +1 -0
- package/dist/server/filter.js +53 -0
- package/dist/server/gallery.d.ts +16 -0
- package/dist/server/gallery.d.ts.map +1 -0
- package/dist/server/gallery.js +162 -0
- package/dist/server/imageprocess.d.ts +18 -0
- package/dist/server/imageprocess.d.ts.map +1 -0
- package/dist/server/imageprocess.js +243 -0
- package/dist/server/index.d.ts +15 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +15 -0
- package/dist/server/models/Artist.d.ts +7 -0
- package/dist/server/models/Artist.d.ts.map +1 -0
- package/dist/server/models/Artist.js +15 -0
- package/dist/server/models/Character.d.ts +108 -0
- package/dist/server/models/Character.d.ts.map +1 -0
- package/dist/server/models/Character.js +21 -0
- package/dist/server/models/Gallery.d.ts +373 -0
- package/dist/server/models/Gallery.d.ts.map +1 -0
- package/dist/server/models/Gallery.js +60 -0
- package/dist/server/models/image.d.ts +64 -0
- package/dist/server/models/image.d.ts.map +1 -0
- package/dist/server/models/image.js +17 -0
- package/dist/server/pack.d.ts +3 -0
- package/dist/server/pack.d.ts.map +1 -0
- package/dist/server/pack.js +26 -0
- package/dist/server/theme/schema.d.ts +57 -0
- package/dist/server/theme/schema.d.ts.map +1 -0
- package/dist/server/theme/schema.js +217 -0
- package/dist/server/util.d.ts +24 -0
- package/dist/server/util.d.ts.map +1 -0
- package/dist/server/util.js +71 -0
- package/dist/util/art.d.ts +52 -0
- package/dist/util/art.d.ts.map +1 -0
- package/dist/util/art.js +57 -0
- package/dist/util/artistcontext.svelte.d.ts +8 -0
- package/dist/util/artistcontext.svelte.d.ts.map +1 -0
- package/dist/util/artistcontext.svelte.js +18 -0
- package/dist/util/charactercontext.svelte.d.ts +4 -0
- package/dist/util/charactercontext.svelte.d.ts.map +1 -0
- package/dist/util/charactercontext.svelte.js +11 -0
- package/dist/util/date.d.ts +2 -0
- package/dist/util/date.d.ts.map +1 -0
- package/dist/util/date.js +6 -0
- package/dist/util/index.d.ts +13 -0
- package/dist/util/index.d.ts.map +1 -0
- package/dist/util/index.js +10 -0
- package/dist/util/markdown.d.ts +2 -0
- package/dist/util/markdown.d.ts.map +1 -0
- package/dist/util/markdown.js +16 -0
- package/dist/util/phosart_config.svelte.d.ts +44 -0
- package/dist/util/phosart_config.svelte.d.ts.map +1 -0
- package/dist/util/phosart_config.svelte.js +51 -0
- package/dist/util/search.d.ts +3 -0
- package/dist/util/search.d.ts.map +1 -0
- package/dist/util/search.js +24 -0
- package/dist/util/smoothscroll.d.ts +4 -0
- package/dist/util/smoothscroll.d.ts.map +1 -0
- package/dist/util/smoothscroll.js +21 -0
- package/dist/util/tree.d.ts +19 -0
- package/dist/util/tree.d.ts.map +1 -0
- package/dist/util/tree.js +58 -0
- package/dist/util/util.d.ts +4 -0
- package/dist/util/util.d.ts.map +1 -0
- package/dist/util/util.js +22 -0
- package/package.json +102 -0
- package/src/lib/FullGallery.svelte +51 -0
- package/src/lib/Gallery.svelte +30 -0
- package/src/lib/GalleryPreview.svelte +60 -0
- package/src/lib/HighResContext.svelte +21 -0
- package/src/lib/Image.svelte +171 -0
- package/src/lib/Modal.svelte +87 -0
- package/src/lib/ModalGallery/Carousel.svelte +76 -0
- package/src/lib/ModalGallery/ImageSection.svelte +156 -0
- package/src/lib/ModalGallery/ImageView.svelte +92 -0
- package/src/lib/ModalGallery/Spinner.svelte +71 -0
- package/src/lib/ModalGallery.svelte +165 -0
- package/src/lib/OpengraphMeta.svelte +125 -0
- package/src/lib/Postcard/ArtistLink.svelte +46 -0
- package/src/lib/Postcard/Chip.svelte +100 -0
- package/src/lib/Postcard/Description/Character.svelte +79 -0
- package/src/lib/Postcard/Description.svelte +146 -0
- package/src/lib/Postcard/Headline.svelte +70 -0
- package/src/lib/index.ts +20 -0
- package/src/lib/server/artist.ts +50 -0
- package/src/lib/server/character.ts +113 -0
- package/src/lib/server/directories.ts +45 -0
- package/src/lib/server/fastcache.ts +66 -0
- package/src/lib/server/filter.ts +71 -0
- package/src/lib/server/gallery.ts +259 -0
- package/src/lib/server/imageprocess.ts +382 -0
- package/src/lib/server/index.ts +57 -0
- package/src/lib/server/models/Artist.ts +19 -0
- package/src/lib/server/models/Character.ts +24 -0
- package/src/lib/server/models/Gallery.ts +70 -0
- package/src/lib/server/models/image.ts +20 -0
- package/src/lib/server/pack.ts +31 -0
- package/src/lib/server/theme/schema.ts +286 -0
- package/src/lib/server/util.ts +102 -0
- package/src/lib/util/art.ts +136 -0
- package/src/lib/util/artistcontext.svelte.ts +25 -0
- package/src/lib/util/charactercontext.svelte.ts +15 -0
- package/src/lib/util/date.ts +7 -0
- package/src/lib/util/index.ts +29 -0
- package/src/lib/util/markdown.ts +17 -0
- package/src/lib/util/phosart_config.svelte.ts +101 -0
- package/src/lib/util/search.ts +28 -0
- package/src/lib/util/smoothscroll.ts +21 -0
- package/src/lib/util/tree.ts +75 -0
- package/src/lib/util/util.ts +37 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import '@fortawesome/fontawesome-free/css/all.min.css';
|
|
3
|
+
|
|
4
|
+
import type { ArtPiece } from '../util/art.js';
|
|
5
|
+
import ImageView from './ImageView.svelte';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
piece: ArtPiece;
|
|
9
|
+
onnext: () => void;
|
|
10
|
+
onprev: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let { piece, onnext, onprev }: Props = $props();
|
|
14
|
+
|
|
15
|
+
function doOnNext(e: Event) {
|
|
16
|
+
e.stopPropagation();
|
|
17
|
+
onnext();
|
|
18
|
+
}
|
|
19
|
+
function doOnPrev(e: Event) {
|
|
20
|
+
e.stopPropagation();
|
|
21
|
+
onprev();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let containerWidth: number = $state(0);
|
|
25
|
+
let containerHeight: number = $state(0);
|
|
26
|
+
let containerHeightLessInfo = $derived(Math.max(0, containerHeight - 50));
|
|
27
|
+
|
|
28
|
+
let scaleByHeight = $derived(
|
|
29
|
+
containerWidth / containerHeightLessInfo >
|
|
30
|
+
piece.image.full.fallback.w / piece.image.full.fallback.h
|
|
31
|
+
);
|
|
32
|
+
let scalingFactor: number = $derived(
|
|
33
|
+
scaleByHeight
|
|
34
|
+
? containerHeightLessInfo / piece.image.full.fallback.h
|
|
35
|
+
: containerWidth / piece.image.full.fallback.w
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
let w = $derived(piece.image.full.fallback.w * scalingFactor);
|
|
39
|
+
let h = $derived(piece.image.full.fallback.h * scalingFactor + 50);
|
|
40
|
+
|
|
41
|
+
let nameInHeader = $derived(w > 500);
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<div class="image-section">
|
|
45
|
+
<div class="nav-container">
|
|
46
|
+
<div
|
|
47
|
+
class="fa-solid fa-arrow-left hoverable"
|
|
48
|
+
style="font-size: 32pt;"
|
|
49
|
+
onclick={doOnPrev}
|
|
50
|
+
onkeypress={doOnPrev}
|
|
51
|
+
role="button"
|
|
52
|
+
tabindex={-1}
|
|
53
|
+
></div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div class="main-container">
|
|
57
|
+
<div class="bounding-div" bind:clientHeight={containerHeight} bind:clientWidth={containerWidth}>
|
|
58
|
+
<div
|
|
59
|
+
class="bounded-div"
|
|
60
|
+
onclick={(e) => e.stopPropagation()}
|
|
61
|
+
onkeypress={(e) => e.stopPropagation()}
|
|
62
|
+
role="button"
|
|
63
|
+
tabindex={-1}
|
|
64
|
+
style="width: {w}px; height: {h}px"
|
|
65
|
+
>
|
|
66
|
+
<ImageView {piece} {nameInHeader} />
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="nav-container">
|
|
72
|
+
<div
|
|
73
|
+
class="fa-solid fa-arrow-right hoverable"
|
|
74
|
+
style="font-size: 32pt;"
|
|
75
|
+
onclick={doOnNext}
|
|
76
|
+
onkeypress={doOnPrev}
|
|
77
|
+
role="button"
|
|
78
|
+
tabindex={-1}
|
|
79
|
+
></div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<style>
|
|
84
|
+
:global(:root) {
|
|
85
|
+
--info-height: 50px;
|
|
86
|
+
--carousel-height: 100px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@media only screen and (max-width: 800px) {
|
|
90
|
+
:global(:root) {
|
|
91
|
+
--info-height: 50px;
|
|
92
|
+
--carousel-height: 75px;
|
|
93
|
+
}
|
|
94
|
+
.nav-container.nav-container {
|
|
95
|
+
width: 0;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.image-section {
|
|
100
|
+
display: flex;
|
|
101
|
+
flex-direction: row;
|
|
102
|
+
justify-content: center;
|
|
103
|
+
align-items: center;
|
|
104
|
+
overflow: visible;
|
|
105
|
+
max-height: calc(100% - 50px - var(--carousel-height));
|
|
106
|
+
position: relative;
|
|
107
|
+
height: 100%;
|
|
108
|
+
padding: 2rem;
|
|
109
|
+
}
|
|
110
|
+
.nav-container {
|
|
111
|
+
color: white;
|
|
112
|
+
height: min-content;
|
|
113
|
+
width: 50px;
|
|
114
|
+
display: flex;
|
|
115
|
+
flex-direction: column;
|
|
116
|
+
justify-content: center;
|
|
117
|
+
align-items: center;
|
|
118
|
+
transition: width 0.2s ease-in-out;
|
|
119
|
+
overflow: hidden;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.hoverable {
|
|
123
|
+
color: gray;
|
|
124
|
+
cursor: pointer;
|
|
125
|
+
}
|
|
126
|
+
.hoverable:hover {
|
|
127
|
+
color: white;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.main-container {
|
|
131
|
+
flex-grow: 1;
|
|
132
|
+
height: 100%;
|
|
133
|
+
display: flex;
|
|
134
|
+
flex-direction: row;
|
|
135
|
+
justify-content: center;
|
|
136
|
+
align-items: center;
|
|
137
|
+
overflow: hidden;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.bounding-div {
|
|
141
|
+
flex-grow: 1;
|
|
142
|
+
height: 100%;
|
|
143
|
+
position: relative;
|
|
144
|
+
overflow: hidden;
|
|
145
|
+
display: flex;
|
|
146
|
+
justify-content: center;
|
|
147
|
+
align-items: center;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.bounded-div {
|
|
151
|
+
overflow: hidden;
|
|
152
|
+
border-radius: 12px;
|
|
153
|
+
display: flex;
|
|
154
|
+
position: relative;
|
|
155
|
+
}
|
|
156
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import '@fortawesome/fontawesome-free/css/all.min.css';
|
|
2
|
+
import type { ArtPiece } from '../util/art.ts';
|
|
3
|
+
interface Props {
|
|
4
|
+
piece: ArtPiece;
|
|
5
|
+
onnext: () => void;
|
|
6
|
+
onprev: () => void;
|
|
7
|
+
}
|
|
8
|
+
declare const ImageSection: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type ImageSection = ReturnType<typeof ImageSection>;
|
|
10
|
+
export default ImageSection;
|
|
11
|
+
//# sourceMappingURL=ImageSection.svelte.d.ts.map
|
|
@@ -0,0 +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,EAAE,MAAM,gBAAgB,CAAC;AAI9C,UAAU,KAAK;IACd,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,IAAI,CAAC;CACnB;AA6DF,QAAA,MAAM,YAAY,2CAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { run } from 'svelte/legacy';
|
|
3
|
+
|
|
4
|
+
import Image from '../Image.svelte';
|
|
5
|
+
|
|
6
|
+
import Spinner from './Spinner.svelte';
|
|
7
|
+
import Headline from '../Postcard/Headline.svelte';
|
|
8
|
+
import Description from '../Postcard/Description.svelte';
|
|
9
|
+
import type { ArtPiece } from '../util/art.js';
|
|
10
|
+
|
|
11
|
+
interface Props {
|
|
12
|
+
piece: ArtPiece;
|
|
13
|
+
nameInHeader: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let { piece, nameInHeader }: Props = $props();
|
|
17
|
+
|
|
18
|
+
let loading = $state(true);
|
|
19
|
+
let showingDescription = $state(false);
|
|
20
|
+
|
|
21
|
+
let selectedAlt: number | null = $state(null);
|
|
22
|
+
|
|
23
|
+
let image = $derived(typeof selectedAlt === 'number' ? piece.alts![selectedAlt] : piece);
|
|
24
|
+
|
|
25
|
+
run(() => {
|
|
26
|
+
if (piece) loading = true;
|
|
27
|
+
});
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<Spinner {loading} />
|
|
31
|
+
|
|
32
|
+
<div class="image-container">
|
|
33
|
+
<Image
|
|
34
|
+
video={image.video?.full}
|
|
35
|
+
controls
|
|
36
|
+
picture={image.image.full}
|
|
37
|
+
alt={image.alt}
|
|
38
|
+
onloaded={() => (loading = false)}
|
|
39
|
+
/>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<div class="headline-container">
|
|
43
|
+
<Headline {piece} bind:showingDescription showName={nameInHeader} />
|
|
44
|
+
</div>
|
|
45
|
+
<div class="description-container">
|
|
46
|
+
<Description
|
|
47
|
+
{piece}
|
|
48
|
+
bind:visible={showingDescription}
|
|
49
|
+
showName={!nameInHeader}
|
|
50
|
+
{selectedAlt}
|
|
51
|
+
onselectalt={(i) => (selectedAlt = i ?? null)}
|
|
52
|
+
/>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<style>
|
|
56
|
+
.image-container {
|
|
57
|
+
position: absolute;
|
|
58
|
+
top: var(--info-height);
|
|
59
|
+
bottom: 0;
|
|
60
|
+
left: 0;
|
|
61
|
+
right: 0;
|
|
62
|
+
}
|
|
63
|
+
.description-container {
|
|
64
|
+
position: absolute;
|
|
65
|
+
top: var(--info-height);
|
|
66
|
+
height: calc(100% - var(--info-height));
|
|
67
|
+
left: 0;
|
|
68
|
+
right: 0;
|
|
69
|
+
color: #ddd;
|
|
70
|
+
overflow-x: hidden;
|
|
71
|
+
overflow-y: auto;
|
|
72
|
+
|
|
73
|
+
& > :global(*) {
|
|
74
|
+
background-color: #000c;
|
|
75
|
+
}
|
|
76
|
+
:global(strong) {
|
|
77
|
+
color: white;
|
|
78
|
+
}
|
|
79
|
+
pointer-events: none;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.headline-container {
|
|
83
|
+
position: absolute;
|
|
84
|
+
top: 0;
|
|
85
|
+
left: 0;
|
|
86
|
+
right: 0;
|
|
87
|
+
color: white;
|
|
88
|
+
background-color: black;
|
|
89
|
+
height: var(--info-height);
|
|
90
|
+
z-index: 9;
|
|
91
|
+
}
|
|
92
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ArtPiece } from '../util/art.ts';
|
|
2
|
+
interface Props {
|
|
3
|
+
piece: ArtPiece;
|
|
4
|
+
nameInHeader: boolean;
|
|
5
|
+
}
|
|
6
|
+
declare const ImageView: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type ImageView = ReturnType<typeof ImageView>;
|
|
8
|
+
export default ImageView;
|
|
9
|
+
//# sourceMappingURL=ImageView.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImageView.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/ModalGallery/ImageView.svelte.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG9C,UAAU,KAAK;IACd,KAAK,EAAE,QAAQ,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;CACtB;AA2CF,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
loading: boolean;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
let { loading }: Props = $props();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<svg class:loading class="loading-spinner" xmlns="http://www.w3.org/2000/svg">
|
|
10
|
+
<rect
|
|
11
|
+
width="100%"
|
|
12
|
+
height="100%"
|
|
13
|
+
fill="none"
|
|
14
|
+
stroke="#278965"
|
|
15
|
+
stroke-linecap="butt"
|
|
16
|
+
rx="12px"
|
|
17
|
+
ry="12px"
|
|
18
|
+
/>
|
|
19
|
+
<rect
|
|
20
|
+
width="100%"
|
|
21
|
+
height="100%"
|
|
22
|
+
fill="none"
|
|
23
|
+
stroke="#3EB489"
|
|
24
|
+
stroke-dasharray="40, 100"
|
|
25
|
+
stroke-linecap="butt"
|
|
26
|
+
rx="12px"
|
|
27
|
+
ry="12px"
|
|
28
|
+
/>
|
|
29
|
+
</svg>
|
|
30
|
+
|
|
31
|
+
<style>
|
|
32
|
+
.loading-spinner {
|
|
33
|
+
position: absolute;
|
|
34
|
+
left: 0;
|
|
35
|
+
top: 0;
|
|
36
|
+
width: 100%;
|
|
37
|
+
height: 100%;
|
|
38
|
+
border-radius: 12px;
|
|
39
|
+
z-index: 10;
|
|
40
|
+
opacity: 0;
|
|
41
|
+
transition: opacity 0.2s;
|
|
42
|
+
pointer-events: none;
|
|
43
|
+
|
|
44
|
+
rect {
|
|
45
|
+
transition: stroke-width 0.2s;
|
|
46
|
+
stroke-width: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&.loading {
|
|
50
|
+
opacity: 1;
|
|
51
|
+
|
|
52
|
+
rect {
|
|
53
|
+
stroke-width: 4px;
|
|
54
|
+
}
|
|
55
|
+
rect:last-of-type {
|
|
56
|
+
stroke-dashoffset: 600;
|
|
57
|
+
stroke-dasharray: 200, 80;
|
|
58
|
+
animation: svgloader forwards linear infinite 0.5s;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@keyframes svgloader {
|
|
64
|
+
from {
|
|
65
|
+
stroke-dashoffset: 280;
|
|
66
|
+
}
|
|
67
|
+
to {
|
|
68
|
+
stroke-dashoffset: 0;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Spinner.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/ModalGallery/Spinner.svelte.ts"],"names":[],"mappings":"AAGC,UAAU,KAAK;IACd,OAAO,EAAE,OAAO,CAAC;CACjB;AAgBF,QAAA,MAAM,OAAO,2CAAwC,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import '@fortawesome/fontawesome-free/css/all.min.css';
|
|
3
|
+
|
|
4
|
+
const modelGalleryOpens: boolean[] = [];
|
|
5
|
+
|
|
6
|
+
export function useIsModelGalleryOpen() {
|
|
7
|
+
const idx = modelGalleryOpens.length;
|
|
8
|
+
modelGalleryOpens.push(false);
|
|
9
|
+
return {
|
|
10
|
+
set open(isOpen: boolean) {
|
|
11
|
+
modelGalleryOpens[idx] = isOpen;
|
|
12
|
+
},
|
|
13
|
+
get open() {
|
|
14
|
+
return modelGalleryOpens[idx];
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function isAnyModelGalleryOpen() {
|
|
20
|
+
return modelGalleryOpens.reduce((p, v) => p || v, false);
|
|
21
|
+
}
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<script lang="ts">
|
|
25
|
+
import type { ArtPiece } from './util/art.js';
|
|
26
|
+
import Modal from './Modal.svelte';
|
|
27
|
+
import { onMount } from 'svelte';
|
|
28
|
+
import ImageSection from './ModalGallery/ImageSection.svelte';
|
|
29
|
+
import Carousel from './ModalGallery/Carousel.svelte';
|
|
30
|
+
import HighResContext from './HighResContext.svelte';
|
|
31
|
+
|
|
32
|
+
interface Props {
|
|
33
|
+
pieces: ArtPiece[];
|
|
34
|
+
selected?: number | null;
|
|
35
|
+
hashUpdateReady?: boolean;
|
|
36
|
+
browser: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let {
|
|
40
|
+
pieces,
|
|
41
|
+
selected = $bindable(null),
|
|
42
|
+
hashUpdateReady = $bindable(false),
|
|
43
|
+
browser
|
|
44
|
+
}: Props = $props();
|
|
45
|
+
|
|
46
|
+
const isGalleryOpen = $state(useIsModelGalleryOpen());
|
|
47
|
+
|
|
48
|
+
onMount(() => {
|
|
49
|
+
const handler = (e: KeyboardEvent) => {
|
|
50
|
+
if (e.code === 'ArrowLeft' && selected !== null) {
|
|
51
|
+
selected = (selected - 1 + pieces.length) % pieces.length;
|
|
52
|
+
} else if (e.code === 'ArrowRight' && selected !== null) {
|
|
53
|
+
selected = (selected + 1) % pieces.length;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const hashchange = (hce: { oldURL?: string; newURL: string }) => {
|
|
58
|
+
const hash = new URL(hce.newURL).hash.replace(/^#/, '');
|
|
59
|
+
if (browser) {
|
|
60
|
+
console.log('H ->', hash);
|
|
61
|
+
const foundSelected = pieces.findIndex((piece) => piece.slug === hash);
|
|
62
|
+
if (!isAnyModelGalleryOpen()) {
|
|
63
|
+
if (foundSelected !== -1) {
|
|
64
|
+
selected = foundSelected;
|
|
65
|
+
}
|
|
66
|
+
} else if (isGalleryOpen.open) {
|
|
67
|
+
if (!hash || hash == '#') {
|
|
68
|
+
selected = null;
|
|
69
|
+
} else if (foundSelected !== -1) {
|
|
70
|
+
selected = foundSelected;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
hashchange({ newURL: window.location.href });
|
|
76
|
+
|
|
77
|
+
window.addEventListener('hashchange', hashchange);
|
|
78
|
+
document.body.addEventListener('keydown', handler);
|
|
79
|
+
|
|
80
|
+
hashUpdateReady = true;
|
|
81
|
+
return () => {
|
|
82
|
+
window.removeEventListener('hashchange', hashchange);
|
|
83
|
+
document.body.removeEventListener('keydown', handler);
|
|
84
|
+
};
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
function updateHash(selected: number | null) {
|
|
88
|
+
if (!browser) return;
|
|
89
|
+
|
|
90
|
+
if (isAnyModelGalleryOpen() === false && window.location.hash) {
|
|
91
|
+
window.location.hash = '##';
|
|
92
|
+
} else if (selected !== null && pieces[selected]) {
|
|
93
|
+
console.log('H <-', pieces[selected].slug);
|
|
94
|
+
window.location.hash = '#' + encodeURIComponent(pieces[selected].slug);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
$effect.pre(() => {
|
|
99
|
+
isGalleryOpen.open = selected !== null;
|
|
100
|
+
});
|
|
101
|
+
$effect.pre(() => {
|
|
102
|
+
if (hashUpdateReady) {
|
|
103
|
+
updateHash(selected);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
</script>
|
|
107
|
+
|
|
108
|
+
<Modal open={selected !== null} onclose={() => (selected = null)}>
|
|
109
|
+
<div class="gallery-container">
|
|
110
|
+
<div
|
|
111
|
+
role="button"
|
|
112
|
+
tabindex={-1}
|
|
113
|
+
class="fa-solid fa-close hoverable close-button"
|
|
114
|
+
onclick={(e) => {
|
|
115
|
+
e.stopPropagation();
|
|
116
|
+
selected = null;
|
|
117
|
+
}}
|
|
118
|
+
onkeypress={() => {
|
|
119
|
+
selected = null;
|
|
120
|
+
}}
|
|
121
|
+
></div>
|
|
122
|
+
<div style="flex-grow: 1"></div>
|
|
123
|
+
|
|
124
|
+
{#if selected !== null}
|
|
125
|
+
<HighResContext>
|
|
126
|
+
<ImageSection
|
|
127
|
+
piece={pieces[selected]}
|
|
128
|
+
onprev={() =>
|
|
129
|
+
(selected = selected !== null ? (selected - 1 + pieces.length) % pieces.length : null)}
|
|
130
|
+
onnext={() => (selected = selected !== null ? (selected + 1) % pieces.length : null)}
|
|
131
|
+
/>
|
|
132
|
+
</HighResContext>
|
|
133
|
+
{/if}
|
|
134
|
+
|
|
135
|
+
<div style="flex-grow: 1"></div>
|
|
136
|
+
|
|
137
|
+
<Carousel {pieces} {browser} bind:selected />
|
|
138
|
+
</div>
|
|
139
|
+
</Modal>
|
|
140
|
+
|
|
141
|
+
<style>
|
|
142
|
+
.gallery-container {
|
|
143
|
+
display: flex;
|
|
144
|
+
flex-direction: column;
|
|
145
|
+
width: 100%;
|
|
146
|
+
height: 100%;
|
|
147
|
+
user-select: none;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.close-button {
|
|
151
|
+
font-size: 20pt;
|
|
152
|
+
position: fixed;
|
|
153
|
+
top: 20px;
|
|
154
|
+
left: 20px;
|
|
155
|
+
z-index: 40;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.hoverable {
|
|
159
|
+
color: gray;
|
|
160
|
+
cursor: pointer;
|
|
161
|
+
}
|
|
162
|
+
.hoverable:hover {
|
|
163
|
+
color: white;
|
|
164
|
+
}
|
|
165
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import '@fortawesome/fontawesome-free/css/all.min.css';
|
|
2
|
+
export declare function useIsModelGalleryOpen(): {
|
|
3
|
+
open: boolean;
|
|
4
|
+
};
|
|
5
|
+
export declare function isAnyModelGalleryOpen(): boolean;
|
|
6
|
+
import type { ArtPiece } from './util/art.ts';
|
|
7
|
+
interface Props {
|
|
8
|
+
pieces: ArtPiece[];
|
|
9
|
+
selected?: number | null;
|
|
10
|
+
hashUpdateReady?: boolean;
|
|
11
|
+
browser: boolean;
|
|
12
|
+
}
|
|
13
|
+
declare const ModalGallery: import("svelte").Component<Props, {}, "selected" | "hashUpdateReady">;
|
|
14
|
+
type ModalGallery = ReturnType<typeof ModalGallery>;
|
|
15
|
+
export default ModalGallery;
|
|
16
|
+
//# sourceMappingURL=ModalGallery.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModalGallery.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ModalGallery.svelte.ts"],"names":[],"mappings":"AAGC,OAAO,+CAA+C,CAAC;AAIvD,wBAAgB,qBAAqB;UAIlB,OAAO;EAOzB;AAED,wBAAgB,qBAAqB,YAEpC;AAGF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAQ7C,UAAU,KAAK;IACd,MAAM,EAAE,QAAQ,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;CACjB;AA4GF,QAAA,MAAM,YAAY,uEAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import { asString } from './Postcard/ArtistLink.svelte';
|
|
3
|
+
import { normalizeArtist, type ResourceRef } from './util/art.js';
|
|
4
|
+
import { useLibraryConfig } from './util/phosart_config.svelte.js';
|
|
5
|
+
|
|
6
|
+
interface OpengraphMeta {
|
|
7
|
+
title: string | null;
|
|
8
|
+
description: string | null;
|
|
9
|
+
siteName: string | null;
|
|
10
|
+
image: string | null;
|
|
11
|
+
width: number | null;
|
|
12
|
+
height: number | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getMeta(resource: ResourceRef, siteName?: string | null): OpengraphMeta {
|
|
16
|
+
const base: OpengraphMeta = {
|
|
17
|
+
title: null,
|
|
18
|
+
description: null,
|
|
19
|
+
siteName: siteName ?? null,
|
|
20
|
+
image: null,
|
|
21
|
+
width: null,
|
|
22
|
+
height: null
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
if (!resource.type || !resource.resource) {
|
|
26
|
+
return base;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
switch (resource.type) {
|
|
30
|
+
case 'artist':
|
|
31
|
+
base.title = `@${resource.resource.info?.name ?? resource.resource.name}`;
|
|
32
|
+
break;
|
|
33
|
+
case 'character': {
|
|
34
|
+
base.title = `${resource.resource.info?.name ?? resource.resource.name}`;
|
|
35
|
+
if (resource.resource.from) {
|
|
36
|
+
base.title += ` by @${resource.resource.from}`;
|
|
37
|
+
}
|
|
38
|
+
const image =
|
|
39
|
+
resource.resource.info?.thumbnail?.full.fallback ??
|
|
40
|
+
resource.resource.info?.picture.full.fallback ??
|
|
41
|
+
null;
|
|
42
|
+
|
|
43
|
+
base.image = image?.src ?? null;
|
|
44
|
+
base.width = image?.w ?? null;
|
|
45
|
+
base.height = image?.h ?? null;
|
|
46
|
+
base.description =
|
|
47
|
+
resource.resource.info?.short_description ?? resource.resource.info?.description ?? null;
|
|
48
|
+
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
case 'piece': {
|
|
52
|
+
base.title = resource.resource.name;
|
|
53
|
+
const artists = normalizeArtist(resource.resource.artist);
|
|
54
|
+
if (artists.length > 0) {
|
|
55
|
+
base.title += ` by ${asString(artists)}`;
|
|
56
|
+
}
|
|
57
|
+
base.description = resource.resource.description || resource.resource.alt;
|
|
58
|
+
base.image = resource.resource.image.full.fallback.src;
|
|
59
|
+
base.width = resource.resource.image.full.fallback.w;
|
|
60
|
+
base.height = resource.resource.image.full.fallback.h;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case 'tag':
|
|
64
|
+
base.title = `#${resource.resource}`;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (base.siteName) {
|
|
69
|
+
base.title += ` | ${base.siteName}`;
|
|
70
|
+
}
|
|
71
|
+
return base;
|
|
72
|
+
}
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<script lang="ts">
|
|
76
|
+
type Props = ResourceRef &
|
|
77
|
+
// If unspecified, the following will be inferred from above
|
|
78
|
+
Partial<OpengraphMeta> & {
|
|
79
|
+
setPageTitle?: boolean;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const {
|
|
83
|
+
setPageTitle,
|
|
84
|
+
height: userHeight,
|
|
85
|
+
image: userImage,
|
|
86
|
+
siteName: userSiteName,
|
|
87
|
+
description: userDescription,
|
|
88
|
+
title: userTitle,
|
|
89
|
+
width: userWidth,
|
|
90
|
+
...resourceRef
|
|
91
|
+
}: Props = $props();
|
|
92
|
+
|
|
93
|
+
const config = useLibraryConfig();
|
|
94
|
+
|
|
95
|
+
const inferred = getMeta(resourceRef, config.siteName);
|
|
96
|
+
const height = $derived(userHeight ?? inferred.height);
|
|
97
|
+
const image = $derived(userImage ?? inferred.image);
|
|
98
|
+
const siteName = $derived(userSiteName ?? inferred.siteName);
|
|
99
|
+
const description = $derived(userDescription ?? inferred.description);
|
|
100
|
+
const title = $derived(userTitle ?? inferred.title);
|
|
101
|
+
const width = $derived(userWidth ?? inferred.width);
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<svelte:head>
|
|
105
|
+
{#if resourceRef.type && resourceRef.resource}
|
|
106
|
+
{#if siteName}
|
|
107
|
+
<meta property="og:site_name" content={siteName} />
|
|
108
|
+
{/if}
|
|
109
|
+
{#if title}
|
|
110
|
+
<meta property="og:title" content={title} />
|
|
111
|
+
{#if setPageTitle}
|
|
112
|
+
<title>{title}</title>
|
|
113
|
+
{/if}
|
|
114
|
+
{/if}
|
|
115
|
+
{#if description}
|
|
116
|
+
<meta property="og:description" content={description} />
|
|
117
|
+
{/if}
|
|
118
|
+
{#if image && width && height}
|
|
119
|
+
<meta property="og:image" content={image} />
|
|
120
|
+
<meta property="og:image:width" content={String(width)} />
|
|
121
|
+
<meta property="og:image:height" content={String(height)} />
|
|
122
|
+
<meta name="twitter:card" content="summary_large_image" />
|
|
123
|
+
{/if}
|
|
124
|
+
{/if}
|
|
125
|
+
</svelte:head>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ResourceRef } from './util/art.ts';
|
|
2
|
+
interface OpengraphMeta {
|
|
3
|
+
title: string | null;
|
|
4
|
+
description: string | null;
|
|
5
|
+
siteName: string | null;
|
|
6
|
+
image: string | null;
|
|
7
|
+
width: number | null;
|
|
8
|
+
height: number | null;
|
|
9
|
+
}
|
|
10
|
+
type Props = ResourceRef & Partial<OpengraphMeta> & {
|
|
11
|
+
setPageTitle?: boolean;
|
|
12
|
+
};
|
|
13
|
+
declare const OpengraphMeta: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
export default OpengraphMeta;
|
|
15
|
+
//# sourceMappingURL=OpengraphMeta.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpengraphMeta.svelte.d.ts","sourceRoot":"","sources":["../src/lib/OpengraphMeta.svelte.ts"],"names":[],"mappings":"AAIC,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAGlE,UAAU,aAAa;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AA6DD,KAAK,KAAK,GAAG,WAAW,GAEvB,OAAO,CAAC,aAAa,CAAC,GAAG;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAqDJ,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAE5D,eAAe,aAAa,CAAC"}
|