zone5 1.1.0 → 1.2.1
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/components/Zone5.svelte +25 -104
- package/dist/components/Zone5Img.svelte +30 -9
- package/dist/components/Zone5Provider.svelte +74 -25
- package/dist/components/Zone5Single.svelte +22 -0
- package/dist/components/Zone5Single.svelte.d.ts +9 -0
- package/dist/components/Zone5Wall.svelte +25 -0
- package/dist/components/Zone5Wall.svelte.d.ts +8 -0
- package/dist/components/Zone5Waterfall.svelte +76 -0
- package/dist/components/Zone5Waterfall.svelte.d.ts +11 -0
- package/dist/config.d.ts +3 -3
- package/dist/module.d.ts +1 -8
- package/dist/processor/config.d.ts +1 -1
- package/dist/processor/config.js +1 -1
- package/dist/processor/variants.js +5 -1
- package/package.json +6 -1
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { onMount } from 'svelte';
|
|
2
|
+
import { onMount, untrack } from 'svelte';
|
|
3
3
|
|
|
4
|
-
import Img from './Zone5Img.svelte';
|
|
5
4
|
import { useImageRegistry } from './Zone5Provider.svelte';
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from './constants';
|
|
5
|
+
import Zone5Single from './Zone5Single.svelte';
|
|
6
|
+
import Zone5Wall from './Zone5Wall.svelte';
|
|
7
|
+
import Zone5Waterfall from './Zone5Waterfall.svelte';
|
|
8
|
+
import { DEFAULT_COLUMN_BREAKPOINTS } from './constants';
|
|
11
9
|
import type { ImageData } from './types';
|
|
12
10
|
|
|
13
11
|
interface Props {
|
|
@@ -29,9 +27,15 @@
|
|
|
29
27
|
|
|
30
28
|
// Register images with the global image registry
|
|
31
29
|
$effect(() => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
// Track images to re-run when they change
|
|
31
|
+
const imagesToRegister = images;
|
|
32
|
+
|
|
33
|
+
// Use untrack to prevent the store update from creating a circular dependency
|
|
34
|
+
untrack(() => {
|
|
35
|
+
if (imageStore) {
|
|
36
|
+
imageStore.register(componentId, imagesToRegister);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
35
39
|
});
|
|
36
40
|
|
|
37
41
|
// Cleanup on component unmount
|
|
@@ -51,103 +55,20 @@
|
|
|
51
55
|
imageStore.setCurrent(componentId, index);
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
|
-
|
|
55
|
-
// WATERFALL MODE CALCULATIONS
|
|
56
|
-
let containerWidth = $state(0);
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Calculate number of columns based on container width and breakpoints
|
|
60
|
-
*/
|
|
61
|
-
let nColumns = $derived.by(() => {
|
|
62
|
-
if (mode !== 'waterfall') return 1;
|
|
63
|
-
|
|
64
|
-
let columns = 1;
|
|
65
|
-
const sortedBreakpoints = Object.entries(columnBreakpoints).sort(
|
|
66
|
-
([a], [b]) => Number(a) - Number(b),
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
for (const [breakpoint, cols] of sortedBreakpoints) {
|
|
70
|
-
if (containerWidth >= Number(breakpoint)) {
|
|
71
|
-
columns = cols;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return columns;
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Distribute images across columns in round-robin fashion
|
|
80
|
-
*/
|
|
81
|
-
let colPhotos = $derived.by(() => {
|
|
82
|
-
if (mode !== 'waterfall') return [];
|
|
83
|
-
|
|
84
|
-
const cols: { image: ImageData; idx: number }[][] = Array.from({ length: nColumns }, () => []);
|
|
85
|
-
images.forEach((image, idx) => {
|
|
86
|
-
cols[idx % nColumns].push({ image, idx });
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
return cols;
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Calculate filler heights to equalize column heights in waterfall mode
|
|
94
|
-
*/
|
|
95
|
-
let colFillers = $derived.by(() => {
|
|
96
|
-
if (mode !== 'waterfall') return [];
|
|
97
|
-
|
|
98
|
-
const totalHeights = colPhotos.map((col) =>
|
|
99
|
-
col.reduce((sum, img) => sum + 1 / img.image.properties.aspectRatio, 0),
|
|
100
|
-
);
|
|
101
|
-
const maxHeight = Math.max(...totalHeights);
|
|
102
|
-
|
|
103
|
-
return totalHeights.map((height) => maxHeight - height);
|
|
104
|
-
});
|
|
105
58
|
</script>
|
|
106
59
|
|
|
107
60
|
{#if mode === 'wall' && images.length === 1}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
onclick={imageStore ? () => handleImageClick(0) : undefined}
|
|
114
|
-
/>
|
|
115
|
-
{#if image.properties.title && !nocaption}
|
|
116
|
-
<figcaption class="mt-2 text-sm text-gray-600">
|
|
117
|
-
{image.properties.title}
|
|
118
|
-
</figcaption>
|
|
119
|
-
{/if}
|
|
120
|
-
</figure>
|
|
61
|
+
<Zone5Single
|
|
62
|
+
image={images[0]}
|
|
63
|
+
{nocaption}
|
|
64
|
+
onclick={imageStore ? () => handleImageClick(0) : undefined}
|
|
65
|
+
/>
|
|
121
66
|
{:else if mode === 'wall'}
|
|
122
|
-
<
|
|
123
|
-
{#each images as image, idx (idx)}
|
|
124
|
-
<div class="grow {WALL_IMAGE_HEIGHT_CLASS} flex" role="listitem">
|
|
125
|
-
<Img
|
|
126
|
-
{image}
|
|
127
|
-
cover
|
|
128
|
-
class="grow"
|
|
129
|
-
onclick={imageStore ? () => handleImageClick(idx) : undefined}
|
|
130
|
-
/>
|
|
131
|
-
</div>
|
|
132
|
-
{/each}
|
|
133
|
-
</div>
|
|
67
|
+
<Zone5Wall {images} onImageClick={imageStore ? handleImageClick : undefined} />
|
|
134
68
|
{:else if mode === 'waterfall'}
|
|
135
|
-
<
|
|
136
|
-
{
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<Img {image} onclick={imageStore ? () => handleImageClick(idx) : undefined} />
|
|
141
|
-
</div>
|
|
142
|
-
{/each}
|
|
143
|
-
{#if colFillers[columnId] > 0}
|
|
144
|
-
<div
|
|
145
|
-
class="bg-slate-200 rounded"
|
|
146
|
-
style:height={colFillers[columnId] * 100 + '%'}
|
|
147
|
-
aria-hidden="true"
|
|
148
|
-
></div>
|
|
149
|
-
{/if}
|
|
150
|
-
</div>
|
|
151
|
-
{/each}
|
|
152
|
-
</div>
|
|
69
|
+
<Zone5Waterfall
|
|
70
|
+
{columnBreakpoints}
|
|
71
|
+
{images}
|
|
72
|
+
onImageClick={imageStore ? handleImageClick : undefined}
|
|
73
|
+
/>
|
|
153
74
|
{/if}
|
|
@@ -25,16 +25,37 @@
|
|
|
25
25
|
return breakpoints.join(', ');
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
let img: HTMLImageElement;
|
|
29
28
|
let loaded = $state(false);
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
img.removeEventListener('load', handleLoad);
|
|
29
|
+
|
|
30
|
+
// Action to handle image load state - runs when element is mounted
|
|
31
|
+
const useImageLoad: Action<HTMLImageElement> = (node) => {
|
|
32
|
+
const handleLoad = () => {
|
|
33
|
+
loaded = true;
|
|
36
34
|
};
|
|
37
|
-
|
|
35
|
+
|
|
36
|
+
// Check if already loaded (e.g., from cache)
|
|
37
|
+
if (node.complete && node.naturalWidth > 0) {
|
|
38
|
+
loaded = true;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Not loaded yet - add listener first, then recheck to avoid race condition
|
|
43
|
+
loaded = false;
|
|
44
|
+
node.addEventListener('load', handleLoad);
|
|
45
|
+
|
|
46
|
+
// Recheck complete after adding listener in case image loaded during setup
|
|
47
|
+
if (node.complete && node.naturalWidth > 0) {
|
|
48
|
+
loaded = true;
|
|
49
|
+
node.removeEventListener('load', handleLoad);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
destroy: () => {
|
|
55
|
+
node.removeEventListener('load', handleLoad);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
};
|
|
38
59
|
|
|
39
60
|
const useOnclick: Action<HTMLDivElement, (() => void) | undefined> = (node, handler) => {
|
|
40
61
|
const setHandler = (handler?: () => void | undefined) => {
|
|
@@ -91,7 +112,7 @@
|
|
|
91
112
|
'opacity-100': loaded,
|
|
92
113
|
},
|
|
93
114
|
]}
|
|
94
|
-
|
|
115
|
+
use:useImageLoad
|
|
95
116
|
/>
|
|
96
117
|
</picture>
|
|
97
118
|
</div>
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
2
|
import { getContext, setContext } from 'svelte';
|
|
3
3
|
|
|
4
|
-
const key =
|
|
4
|
+
const key = 'Zone5 provider';
|
|
5
5
|
export const useImageRegistry = () => getContext<Registry>(key);
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<script lang="ts">
|
|
9
9
|
import type { Snippet } from 'svelte';
|
|
10
|
-
import {
|
|
10
|
+
import { untrack } from 'svelte';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { browser } from '$app/environment';
|
|
13
|
+
import { beforeNavigate, goto } from '$app/navigation';
|
|
14
|
+
import { page } from '$app/state';
|
|
13
15
|
|
|
14
16
|
import { type Registry, registry } from '../stores';
|
|
15
17
|
import Zone5Lightbox from './Zone5Lightbox.svelte';
|
|
@@ -18,39 +20,86 @@
|
|
|
18
20
|
|
|
19
21
|
setContext<Registry>(key, registry);
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const getZ5FromUrl = () => (browser ? page.url.searchParams.get('z5') : null);
|
|
24
|
+
const setZ5InUrl = (value: string | null) => {
|
|
25
|
+
if (!browser) return;
|
|
26
|
+
const url = new URL(page.url);
|
|
27
|
+
if (value) {
|
|
28
|
+
url.searchParams.set('z5', value);
|
|
29
|
+
} else {
|
|
30
|
+
url.searchParams.delete('z5');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// eslint-disable-next-line svelte/no-navigation-without-resolve -- staying on same page, just updating query params
|
|
34
|
+
goto(`${url.pathname}${url.search}`, { replaceState: true, noScroll: true, keepFocus: true });
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
let optimisticForce = $state(getZ5FromUrl() !== null);
|
|
38
|
+
|
|
39
|
+
let isUpdatingFromUrl = false;
|
|
40
|
+
let isUpdatingUrl = false;
|
|
41
|
+
let initialSyncComplete = false;
|
|
26
42
|
|
|
27
|
-
// clear registry when navigating away
|
|
28
43
|
beforeNavigate((navigation) => {
|
|
29
|
-
if (navigation.from?.route.id
|
|
44
|
+
if (navigation.from?.route.id === navigation.to?.route.id) return;
|
|
30
45
|
registry.clear();
|
|
31
46
|
});
|
|
32
47
|
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
48
|
+
// registry → URL
|
|
49
|
+
$effect(() => {
|
|
50
|
+
const current = $registry.current;
|
|
51
|
+
const images = $registry.images;
|
|
52
|
+
|
|
53
|
+
if (isUpdatingFromUrl) return;
|
|
54
|
+
|
|
55
|
+
const currentZ5 = untrack(() => getZ5FromUrl());
|
|
56
|
+
const newZ5 = current?.id ?? null;
|
|
57
|
+
|
|
58
|
+
if (currentZ5 !== newZ5) {
|
|
59
|
+
// Don't clear the URL z5 param during initial load (waiting for all images to register)
|
|
60
|
+
if (newZ5 === null && currentZ5 !== null && !initialSyncComplete) {
|
|
61
|
+
const urlImageExists = images.some((img) => img.id === currentZ5);
|
|
62
|
+
if (urlImageExists) {
|
|
63
|
+
// Don't clear URL yet, let URL→registry sync handle it
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
41
66
|
}
|
|
67
|
+
|
|
68
|
+
isUpdatingUrl = true;
|
|
69
|
+
setZ5InUrl(newZ5);
|
|
70
|
+
queueMicrotask(() => {
|
|
71
|
+
isUpdatingUrl = false;
|
|
72
|
+
});
|
|
42
73
|
}
|
|
43
74
|
});
|
|
44
75
|
|
|
45
|
-
//
|
|
46
|
-
$effect(
|
|
47
|
-
const z5 =
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
76
|
+
// URL → registry
|
|
77
|
+
$effect(() => {
|
|
78
|
+
const z5 = getZ5FromUrl();
|
|
79
|
+
const images = $registry.images;
|
|
80
|
+
|
|
81
|
+
if (isUpdatingUrl || images.length === 0) return;
|
|
82
|
+
|
|
83
|
+
if (z5) {
|
|
84
|
+
isUpdatingFromUrl = true;
|
|
85
|
+
const found = registry.findCurrent(z5);
|
|
86
|
+
if (found) {
|
|
51
87
|
optimisticForce = false;
|
|
52
|
-
$params.z5 = null;
|
|
53
88
|
}
|
|
89
|
+
initialSyncComplete = true;
|
|
90
|
+
queueMicrotask(() => {
|
|
91
|
+
isUpdatingFromUrl = false;
|
|
92
|
+
});
|
|
93
|
+
} else {
|
|
94
|
+
const currentId = untrack(() => $registry.current?.id);
|
|
95
|
+
if (currentId) {
|
|
96
|
+
isUpdatingFromUrl = true;
|
|
97
|
+
registry.clearCurrent();
|
|
98
|
+
queueMicrotask(() => {
|
|
99
|
+
isUpdatingFromUrl = false;
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
initialSyncComplete = true;
|
|
54
103
|
}
|
|
55
104
|
});
|
|
56
105
|
</script>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Img from './Zone5Img.svelte';
|
|
3
|
+
import { SINGLE_IMAGE_HEIGHT_CLASS } from './constants';
|
|
4
|
+
import type { ImageData } from './types';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
image: ImageData;
|
|
8
|
+
nocaption?: boolean;
|
|
9
|
+
onclick?: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { image, nocaption = false, onclick }: Props = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<figure class="flex justify-center" aria-label={image.properties.title || 'Image'}>
|
|
16
|
+
<Img {image} class={SINGLE_IMAGE_HEIGHT_CLASS} {onclick} />
|
|
17
|
+
{#if image.properties.title && !nocaption}
|
|
18
|
+
<figcaption class="mt-2 text-sm text-gray-600">
|
|
19
|
+
{image.properties.title}
|
|
20
|
+
</figcaption>
|
|
21
|
+
{/if}
|
|
22
|
+
</figure>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ImageData } from './types';
|
|
2
|
+
interface Props {
|
|
3
|
+
image: ImageData;
|
|
4
|
+
nocaption?: boolean;
|
|
5
|
+
onclick?: () => void;
|
|
6
|
+
}
|
|
7
|
+
declare const Zone5Single: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type Zone5Single = ReturnType<typeof Zone5Single>;
|
|
9
|
+
export default Zone5Single;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Img from './Zone5Img.svelte';
|
|
3
|
+
import { WALL_IMAGE_HEIGHT_CLASS } from './constants';
|
|
4
|
+
import type { ImageData } from './types';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
images: ImageData[];
|
|
8
|
+
onImageClick?: (index: number) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let { images, onImageClick }: Props = $props();
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<div class="flex gap-2 flex-col md:flex-row md:flex-wrap zone5-wall" role="list">
|
|
15
|
+
{#each images as image, idx (idx)}
|
|
16
|
+
<div class="grow {WALL_IMAGE_HEIGHT_CLASS} flex" role="listitem">
|
|
17
|
+
<Img
|
|
18
|
+
{image}
|
|
19
|
+
cover
|
|
20
|
+
class="grow"
|
|
21
|
+
onclick={onImageClick ? () => onImageClick(idx) : undefined}
|
|
22
|
+
/>
|
|
23
|
+
</div>
|
|
24
|
+
{/each}
|
|
25
|
+
</div>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ImageData } from './types';
|
|
2
|
+
interface Props {
|
|
3
|
+
images: ImageData[];
|
|
4
|
+
onImageClick?: (index: number) => void;
|
|
5
|
+
}
|
|
6
|
+
declare const Zone5Wall: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type Zone5Wall = ReturnType<typeof Zone5Wall>;
|
|
8
|
+
export default Zone5Wall;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import Img from './Zone5Img.svelte';
|
|
3
|
+
import { DEFAULT_COLUMN_BREAKPOINTS } from './constants';
|
|
4
|
+
import type { ImageData } from './types';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
columnBreakpoints?: { [key: number]: number };
|
|
8
|
+
images: ImageData[];
|
|
9
|
+
onImageClick?: (index: number) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { columnBreakpoints = DEFAULT_COLUMN_BREAKPOINTS, images, onImageClick }: Props = $props();
|
|
13
|
+
|
|
14
|
+
let containerWidth = $state(0);
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Calculate number of columns based on container width and breakpoints
|
|
18
|
+
*/
|
|
19
|
+
let nColumns = $derived.by(() => {
|
|
20
|
+
let columns = 1;
|
|
21
|
+
const sortedBreakpoints = Object.entries(columnBreakpoints).sort(
|
|
22
|
+
([a], [b]) => Number(a) - Number(b),
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
for (const [breakpoint, cols] of sortedBreakpoints) {
|
|
26
|
+
if (containerWidth >= Number(breakpoint)) {
|
|
27
|
+
columns = cols;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return columns;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Distribute images across columns in round-robin fashion
|
|
36
|
+
*/
|
|
37
|
+
let colPhotos = $derived.by(() => {
|
|
38
|
+
const cols: { image: ImageData; idx: number }[][] = Array.from({ length: nColumns }, () => []);
|
|
39
|
+
images.forEach((image, idx) => {
|
|
40
|
+
cols[idx % nColumns].push({ image, idx });
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return cols;
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Calculate filler heights to equalize column heights in waterfall mode
|
|
48
|
+
*/
|
|
49
|
+
let colFillers = $derived.by(() => {
|
|
50
|
+
const totalHeights = colPhotos.map((col) =>
|
|
51
|
+
col.reduce((sum, img) => sum + 1 / img.image.properties.aspectRatio, 0),
|
|
52
|
+
);
|
|
53
|
+
const maxHeight = Math.max(...totalHeights);
|
|
54
|
+
|
|
55
|
+
return totalHeights.map((height) => maxHeight - height);
|
|
56
|
+
});
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<div class="flex gap-2" bind:clientWidth={containerWidth} role="list">
|
|
60
|
+
{#each Array.from({ length: nColumns }, (_, i) => i) as columnId (columnId)}
|
|
61
|
+
<div class="flex flex-col gap-2" role="listitem">
|
|
62
|
+
{#each colPhotos[columnId] as { image, idx } (idx)}
|
|
63
|
+
<div>
|
|
64
|
+
<Img {image} onclick={onImageClick ? () => onImageClick(idx) : undefined} />
|
|
65
|
+
</div>
|
|
66
|
+
{/each}
|
|
67
|
+
{#if colFillers[columnId] > 0}
|
|
68
|
+
<div
|
|
69
|
+
class="bg-slate-200 rounded"
|
|
70
|
+
style:height={colFillers[columnId] * 100 + '%'}
|
|
71
|
+
aria-hidden="true"
|
|
72
|
+
></div>
|
|
73
|
+
{/if}
|
|
74
|
+
</div>
|
|
75
|
+
{/each}
|
|
76
|
+
</div>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ImageData } from './types';
|
|
2
|
+
interface Props {
|
|
3
|
+
columnBreakpoints?: {
|
|
4
|
+
[key: number]: number;
|
|
5
|
+
};
|
|
6
|
+
images: ImageData[];
|
|
7
|
+
onImageClick?: (index: number) => void;
|
|
8
|
+
}
|
|
9
|
+
declare const Zone5Waterfall: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type Zone5Waterfall = ReturnType<typeof Zone5Waterfall>;
|
|
11
|
+
export default Zone5Waterfall;
|
package/dist/config.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
15
15
|
resize_kernel: z.ZodDefault<z.ZodEnum<{
|
|
16
16
|
[x: string]: any;
|
|
17
17
|
}>>;
|
|
18
|
-
resize_gamma: z.
|
|
18
|
+
resize_gamma: z.ZodOptional<z.ZodNumber>;
|
|
19
19
|
variants: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
|
|
20
20
|
}, z.core.$strip>>>;
|
|
21
21
|
}, z.core.$strip>;
|
|
@@ -29,8 +29,8 @@ export declare const load: (configDir?: string | undefined) => Promise<{
|
|
|
29
29
|
};
|
|
30
30
|
processor: {
|
|
31
31
|
resize_kernel: any;
|
|
32
|
-
resize_gamma: number;
|
|
33
32
|
variants: number[];
|
|
33
|
+
resize_gamma?: number | undefined;
|
|
34
34
|
};
|
|
35
35
|
} | {
|
|
36
36
|
src: string;
|
|
@@ -41,8 +41,8 @@ export declare const load: (configDir?: string | undefined) => Promise<{
|
|
|
41
41
|
};
|
|
42
42
|
processor: {
|
|
43
43
|
resize_kernel: any;
|
|
44
|
-
resize_gamma: number;
|
|
45
44
|
variants: number[];
|
|
45
|
+
resize_gamma?: number | undefined;
|
|
46
46
|
};
|
|
47
47
|
}>;
|
|
48
48
|
export declare const toToml: (config: ConfigType & {
|
package/dist/module.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Augment mdast types
|
|
1
|
+
// Augment mdast types for remark plugin
|
|
2
2
|
import type { SvelteComponent } from 'svast';
|
|
3
3
|
|
|
4
4
|
declare module 'mdast' {
|
|
@@ -10,10 +10,3 @@ declare module 'mdast' {
|
|
|
10
10
|
svelteComponent: SvelteComponent;
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
declare module '*?z5' {
|
|
15
|
-
import type { ItemFeature } from './processor';
|
|
16
|
-
|
|
17
|
-
const data: ItemFeature;
|
|
18
|
-
export default data;
|
|
19
|
-
}
|
|
@@ -3,7 +3,7 @@ export declare const ProcessorConfigSchema: z.ZodPrefault<z.ZodObject<{
|
|
|
3
3
|
resize_kernel: z.ZodDefault<z.ZodEnum<{
|
|
4
4
|
[x: string]: any;
|
|
5
5
|
}>>;
|
|
6
|
-
resize_gamma: z.
|
|
6
|
+
resize_gamma: z.ZodOptional<z.ZodNumber>;
|
|
7
7
|
variants: z.ZodDefault<z.ZodArray<z.ZodNumber>>;
|
|
8
8
|
}, z.core.$strip>>;
|
|
9
9
|
export type ProcessorConfig = z.infer<typeof ProcessorConfigSchema>;
|
package/dist/processor/config.js
CHANGED
|
@@ -4,7 +4,7 @@ import z from 'zod';
|
|
|
4
4
|
export const ProcessorConfigSchema = z
|
|
5
5
|
.object({
|
|
6
6
|
resize_kernel: z.enum(Object.values(sharp.kernel)).default(sharp.kernel.mks2021),
|
|
7
|
-
resize_gamma: z.number().min(1.0).max(3.0).
|
|
7
|
+
resize_gamma: z.number().min(1.0).max(3.0).optional(),
|
|
8
8
|
variants: z.array(z.number().int().min(1)).default([640, 768, 1280, 1920, 2560]),
|
|
9
9
|
})
|
|
10
10
|
.prefault({});
|
|
@@ -43,7 +43,11 @@ export async function generateImageVariants(options) {
|
|
|
43
43
|
// Check if variant already exists and should be overwritten
|
|
44
44
|
const variantExists = await fileExists(variantPath);
|
|
45
45
|
if (!variantExists || forceOverwrite) {
|
|
46
|
-
let img = sharp(sourceFile)
|
|
46
|
+
let img = sharp(sourceFile);
|
|
47
|
+
if (processor.resize_gamma) {
|
|
48
|
+
img = img.gamma(processor.resize_gamma);
|
|
49
|
+
}
|
|
50
|
+
img = img.resize(width, null, {
|
|
47
51
|
fit: 'inside',
|
|
48
52
|
kernel: processor.resize_kernel,
|
|
49
53
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zone5",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"repository": {
|
|
5
5
|
"url": "https://github.com/cwygoda/zone5"
|
|
6
6
|
},
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
"build:cli": "vite build --config vite.cli.config.ts",
|
|
14
14
|
"build:watch": "vite build --watch",
|
|
15
15
|
"build": "svelte-kit sync && svelte-package && pnpm build:cli && publint",
|
|
16
|
+
"build:site": "vite build",
|
|
17
|
+
"build:all": "pnpm build && pnpm build:site",
|
|
16
18
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
17
19
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
18
20
|
"dev": "vite dev",
|
|
@@ -29,6 +31,7 @@
|
|
|
29
31
|
"dagger:test:all": "dagger -m ./dagger call test-all --source=.",
|
|
30
32
|
"dagger:check": "dagger -m ./dagger call check --source=.",
|
|
31
33
|
"dagger:lint": "dagger -m ./dagger call lint --source=.",
|
|
34
|
+
"dagger:build:site": "dagger -m ./dagger call build-site --source=.",
|
|
32
35
|
"dagger:ci": "dagger -m ./dagger call ci --source=.",
|
|
33
36
|
"prepare": "husky"
|
|
34
37
|
},
|
|
@@ -85,6 +88,7 @@
|
|
|
85
88
|
"@dagger.io/dagger": "^0.19.6",
|
|
86
89
|
"@lucide/svelte": "0.553.0",
|
|
87
90
|
"@playwright/test": "^1.56.1",
|
|
91
|
+
"@sveltejs/adapter-static": "^3.0.10",
|
|
88
92
|
"@sveltejs/kit": "^2.48.4",
|
|
89
93
|
"@sveltejs/package": "^2.3.7",
|
|
90
94
|
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
|
@@ -126,6 +130,7 @@
|
|
|
126
130
|
"fast-average-color-node": "^3.1.0",
|
|
127
131
|
"fs-extra": "^11.2.0",
|
|
128
132
|
"globals": "^16.5.0",
|
|
133
|
+
"mdast-util-to-string": "^4.0.0",
|
|
129
134
|
"mime": "^4.1.0",
|
|
130
135
|
"ora": "^9.0.0",
|
|
131
136
|
"picocolors": "^1.1.1",
|