@flightdev/image 0.0.2
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/LICENSE +21 -0
- package/README.md +219 -0
- package/dist/adapters/cloudinary.d.ts +46 -0
- package/dist/adapters/cloudinary.js +160 -0
- package/dist/adapters/cloudinary.js.map +1 -0
- package/dist/adapters/imgix.d.ts +39 -0
- package/dist/adapters/imgix.js +152 -0
- package/dist/adapters/imgix.js.map +1 -0
- package/dist/adapters/sharp.d.ts +37 -0
- package/dist/adapters/sharp.js +165 -0
- package/dist/adapters/sharp.js.map +1 -0
- package/dist/adapters/squoosh.d.ts +36 -0
- package/dist/adapters/squoosh.js +141 -0
- package/dist/adapters/squoosh.js.map +1 -0
- package/dist/components/react.d.ts +66 -0
- package/dist/components/react.js +129 -0
- package/dist/components/react.js.map +1 -0
- package/dist/components/solid.d.ts +44 -0
- package/dist/components/solid.js +101 -0
- package/dist/components/solid.js.map +1 -0
- package/dist/components/svelte.d.ts +70 -0
- package/dist/components/svelte.js +89 -0
- package/dist/components/svelte.js.map +1 -0
- package/dist/components/vue.d.ts +133 -0
- package/dist/components/vue.js +109 -0
- package/dist/components/vue.js.map +1 -0
- package/dist/index.d.ts +210 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/package.json +97 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
// src/components/react.tsx
|
|
5
|
+
function buildOptimizedUrl(src, options, baseUrl = "") {
|
|
6
|
+
const params = new URLSearchParams();
|
|
7
|
+
if (options.width) params.set("w", options.width.toString());
|
|
8
|
+
if (options.height) params.set("h", options.height.toString());
|
|
9
|
+
if (options.format && options.format !== "auto") params.set("f", options.format);
|
|
10
|
+
if (options.quality) params.set("q", options.quality.toString());
|
|
11
|
+
if (options.fit) params.set("fit", options.fit);
|
|
12
|
+
const queryString = params.toString();
|
|
13
|
+
const normalizedSrc = src.startsWith("/") ? src : `/${src}`;
|
|
14
|
+
return `${baseUrl}/_flight/image${normalizedSrc}${queryString ? "?" + queryString : ""}`;
|
|
15
|
+
}
|
|
16
|
+
var Image = React.forwardRef(function Image2({
|
|
17
|
+
src,
|
|
18
|
+
alt,
|
|
19
|
+
width,
|
|
20
|
+
height,
|
|
21
|
+
format = "auto",
|
|
22
|
+
quality = 80,
|
|
23
|
+
fit = "cover",
|
|
24
|
+
priority = false,
|
|
25
|
+
placeholder = "empty",
|
|
26
|
+
blurDataUrl,
|
|
27
|
+
sizes,
|
|
28
|
+
baseUrl = "",
|
|
29
|
+
loading,
|
|
30
|
+
onLoad,
|
|
31
|
+
onError,
|
|
32
|
+
style,
|
|
33
|
+
className,
|
|
34
|
+
...rest
|
|
35
|
+
}, ref) {
|
|
36
|
+
const [isLoaded, setIsLoaded] = React.useState(false);
|
|
37
|
+
const [error, setError] = React.useState(false);
|
|
38
|
+
const optimizedSrc = buildOptimizedUrl(src, { width, height, format, quality, fit }, baseUrl);
|
|
39
|
+
const srcSet = React.useMemo(() => {
|
|
40
|
+
if (!width) return void 0;
|
|
41
|
+
const widths = [width, width * 1.5, width * 2].map(Math.round);
|
|
42
|
+
return widths.map((w) => `${buildOptimizedUrl(src, { width: w, height: height ? Math.round(height * w / width) : void 0, format, quality, fit }, baseUrl)} ${w}w`).join(", ");
|
|
43
|
+
}, [src, width, height, format, quality, fit, baseUrl]);
|
|
44
|
+
const defaultSizes = width ? `(max-width: ${width}px) 100vw, ${width}px` : void 0;
|
|
45
|
+
const handleLoad = React.useCallback((e) => {
|
|
46
|
+
setIsLoaded(true);
|
|
47
|
+
onLoad?.(e);
|
|
48
|
+
}, [onLoad]);
|
|
49
|
+
const handleError = React.useCallback((e) => {
|
|
50
|
+
setError(true);
|
|
51
|
+
onError?.(e);
|
|
52
|
+
}, [onError]);
|
|
53
|
+
const placeholderStyle = placeholder === "blur" && blurDataUrl && !isLoaded ? {
|
|
54
|
+
backgroundImage: `url(${blurDataUrl})`,
|
|
55
|
+
backgroundSize: "cover",
|
|
56
|
+
backgroundPosition: "center",
|
|
57
|
+
filter: "blur(20px)",
|
|
58
|
+
transform: "scale(1.1)"
|
|
59
|
+
} : void 0;
|
|
60
|
+
const containerStyle = {
|
|
61
|
+
position: "relative",
|
|
62
|
+
overflow: "hidden",
|
|
63
|
+
width: width ? `${width}px` : void 0,
|
|
64
|
+
height: height ? `${height}px` : void 0,
|
|
65
|
+
...style
|
|
66
|
+
};
|
|
67
|
+
const imageStyle = {
|
|
68
|
+
width: "100%",
|
|
69
|
+
height: "100%",
|
|
70
|
+
objectFit: fit,
|
|
71
|
+
opacity: isLoaded ? 1 : 0,
|
|
72
|
+
transition: "opacity 0.3s ease-in-out"
|
|
73
|
+
};
|
|
74
|
+
return /* @__PURE__ */ jsxs(
|
|
75
|
+
"div",
|
|
76
|
+
{
|
|
77
|
+
style: containerStyle,
|
|
78
|
+
className,
|
|
79
|
+
children: [
|
|
80
|
+
placeholder === "blur" && blurDataUrl && !isLoaded && /* @__PURE__ */ jsx(
|
|
81
|
+
"div",
|
|
82
|
+
{
|
|
83
|
+
style: {
|
|
84
|
+
position: "absolute",
|
|
85
|
+
inset: 0,
|
|
86
|
+
...placeholderStyle
|
|
87
|
+
},
|
|
88
|
+
"aria-hidden": "true"
|
|
89
|
+
}
|
|
90
|
+
),
|
|
91
|
+
/* @__PURE__ */ jsx(
|
|
92
|
+
"img",
|
|
93
|
+
{
|
|
94
|
+
ref,
|
|
95
|
+
src: optimizedSrc,
|
|
96
|
+
srcSet,
|
|
97
|
+
sizes: sizes ?? defaultSizes,
|
|
98
|
+
alt,
|
|
99
|
+
width,
|
|
100
|
+
height,
|
|
101
|
+
loading: priority ? "eager" : loading ?? "lazy",
|
|
102
|
+
decoding: priority ? "sync" : "async",
|
|
103
|
+
fetchPriority: priority ? "high" : void 0,
|
|
104
|
+
onLoad: handleLoad,
|
|
105
|
+
onError: handleError,
|
|
106
|
+
style: imageStyle,
|
|
107
|
+
...rest
|
|
108
|
+
}
|
|
109
|
+
),
|
|
110
|
+
priority && typeof document !== "undefined" && /* @__PURE__ */ jsx(
|
|
111
|
+
"link",
|
|
112
|
+
{
|
|
113
|
+
rel: "preload",
|
|
114
|
+
as: "image",
|
|
115
|
+
href: optimizedSrc,
|
|
116
|
+
imageSrcSet: srcSet,
|
|
117
|
+
imageSizes: sizes ?? defaultSizes
|
|
118
|
+
}
|
|
119
|
+
)
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
Image.displayName = "FlightImage";
|
|
125
|
+
var react_default = Image;
|
|
126
|
+
|
|
127
|
+
export { Image, react_default as default };
|
|
128
|
+
//# sourceMappingURL=react.js.map
|
|
129
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/react.tsx"],"names":["Image"],"mappings":"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","file":"react.js","sourcesContent":["/**\r\n * React Image Component for @flightdev/image\r\n * \r\n * @example\r\n * ```tsx\r\n * import { Image } from '@flightdev/image/react';\r\n * \r\n * <Image\r\n * src=\"/hero.jpg\"\r\n * alt=\"Hero\"\r\n * width={800}\r\n * height={600}\r\n * priority\r\n * placeholder=\"blur\"\r\n * />\r\n * ```\r\n */\r\n\r\nimport * as React from 'react';\r\nimport type { ImageOptimizeOptions, ImageFormat, ImageFit } from '../index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport interface ImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {\r\n /** Image source URL or path */\r\n src: string;\r\n /** Alt text (required for accessibility) */\r\n alt: string;\r\n /** Target width */\r\n width?: number;\r\n /** Target height */\r\n height?: number;\r\n /** Output format */\r\n format?: ImageFormat;\r\n /** Quality (1-100) */\r\n quality?: number;\r\n /** Fit mode */\r\n fit?: ImageFit;\r\n /** Priority loading (preload) */\r\n priority?: boolean;\r\n /** Placeholder type */\r\n placeholder?: 'blur' | 'empty' | 'none';\r\n /** Custom blur data URL */\r\n blurDataUrl?: string;\r\n /** Sizes attribute for responsive images */\r\n sizes?: string;\r\n /** Image service base URL */\r\n baseUrl?: string;\r\n /** Loading behavior */\r\n loading?: 'lazy' | 'eager';\r\n /** Callback when image loads */\r\n onLoad?: React.ReactEventHandler<HTMLImageElement>;\r\n /** Callback on error */\r\n onError?: React.ReactEventHandler<HTMLImageElement>;\r\n}\r\n\r\n// ============================================================================\r\n// URL Builder\r\n// ============================================================================\r\n\r\nfunction buildOptimizedUrl(\r\n src: string,\r\n options: ImageOptimizeOptions,\r\n baseUrl: string = ''\r\n): string {\r\n const params = new URLSearchParams();\r\n\r\n if (options.width) params.set('w', options.width.toString());\r\n if (options.height) params.set('h', options.height.toString());\r\n if (options.format && options.format !== 'auto') params.set('f', options.format);\r\n if (options.quality) params.set('q', options.quality.toString());\r\n if (options.fit) params.set('fit', options.fit);\r\n\r\n const queryString = params.toString();\r\n const normalizedSrc = src.startsWith('/') ? src : `/${src}`;\r\n return `${baseUrl}/_flight/image${normalizedSrc}${queryString ? '?' + queryString : ''}`;\r\n}\r\n\r\n// ============================================================================\r\n// Image Component\r\n// ============================================================================\r\n\r\n/**\r\n * Optimized Image component for React\r\n * \r\n * Automatically handles:\r\n * - Lazy loading with IntersectionObserver\r\n * - Blur placeholder during load\r\n * - Responsive srcset generation\r\n * - Format optimization\r\n */\r\nexport const Image = React.forwardRef<HTMLImageElement, ImageProps>(function Image(\r\n {\r\n src,\r\n alt,\r\n width,\r\n height,\r\n format = 'auto',\r\n quality = 80,\r\n fit = 'cover',\r\n priority = false,\r\n placeholder = 'empty',\r\n blurDataUrl,\r\n sizes,\r\n baseUrl = '',\r\n loading,\r\n onLoad,\r\n onError,\r\n style,\r\n className,\r\n ...rest\r\n },\r\n ref\r\n) {\r\n const [isLoaded, setIsLoaded] = React.useState(false);\r\n const [error, setError] = React.useState(false);\r\n\r\n // Build optimized URL\r\n const optimizedSrc = buildOptimizedUrl(src, { width, height, format, quality, fit }, baseUrl);\r\n\r\n // Generate srcset for responsive images\r\n const srcSet = React.useMemo(() => {\r\n if (!width) return undefined;\r\n\r\n const widths = [width, width * 1.5, width * 2].map(Math.round);\r\n return widths\r\n .map(w => `${buildOptimizedUrl(src, { width: w, height: height ? Math.round(height * w / width) : undefined, format, quality, fit }, baseUrl)} ${w}w`)\r\n .join(', ');\r\n }, [src, width, height, format, quality, fit, baseUrl]);\r\n\r\n // Default sizes if not provided\r\n const defaultSizes = width ? `(max-width: ${width}px) 100vw, ${width}px` : undefined;\r\n\r\n // Handle load\r\n const handleLoad = React.useCallback((e: React.SyntheticEvent<HTMLImageElement>) => {\r\n setIsLoaded(true);\r\n onLoad?.(e);\r\n }, [onLoad]);\r\n\r\n // Handle error\r\n const handleError = React.useCallback((e: React.SyntheticEvent<HTMLImageElement>) => {\r\n setError(true);\r\n onError?.(e);\r\n }, [onError]);\r\n\r\n // Placeholder styles\r\n const placeholderStyle: React.CSSProperties | undefined =\r\n placeholder === 'blur' && blurDataUrl && !isLoaded\r\n ? {\r\n backgroundImage: `url(${blurDataUrl})`,\r\n backgroundSize: 'cover',\r\n backgroundPosition: 'center',\r\n filter: 'blur(20px)',\r\n transform: 'scale(1.1)',\r\n }\r\n : undefined;\r\n\r\n // Container styles for placeholder\r\n const containerStyle: React.CSSProperties = {\r\n position: 'relative',\r\n overflow: 'hidden',\r\n width: width ? `${width}px` : undefined,\r\n height: height ? `${height}px` : undefined,\r\n ...style,\r\n };\r\n\r\n // Image styles\r\n const imageStyle: React.CSSProperties = {\r\n width: '100%',\r\n height: '100%',\r\n objectFit: fit as React.CSSProperties['objectFit'],\r\n opacity: isLoaded ? 1 : 0,\r\n transition: 'opacity 0.3s ease-in-out',\r\n };\r\n\r\n return (\r\n <div\r\n style={containerStyle}\r\n className={className}\r\n >\r\n {/* Blur placeholder background */}\r\n {placeholder === 'blur' && blurDataUrl && !isLoaded && (\r\n <div\r\n style={{\r\n position: 'absolute',\r\n inset: 0,\r\n ...placeholderStyle,\r\n }}\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n\r\n {/* Actual image */}\r\n <img\r\n ref={ref}\r\n src={optimizedSrc}\r\n srcSet={srcSet}\r\n sizes={sizes ?? defaultSizes}\r\n alt={alt}\r\n width={width}\r\n height={height}\r\n loading={priority ? 'eager' : loading ?? 'lazy'}\r\n decoding={priority ? 'sync' : 'async'}\r\n fetchPriority={priority ? 'high' : undefined}\r\n onLoad={handleLoad}\r\n onError={handleError}\r\n style={imageStyle}\r\n {...rest}\r\n />\r\n\r\n {/* Preload link for priority images */}\r\n {priority && typeof document !== 'undefined' && (\r\n <link\r\n rel=\"preload\"\r\n as=\"image\"\r\n href={optimizedSrc}\r\n imageSrcSet={srcSet}\r\n imageSizes={sizes ?? defaultSizes}\r\n />\r\n )}\r\n </div>\r\n );\r\n});\r\n\r\nImage.displayName = 'FlightImage';\r\n\r\nexport default Image;\r\n"]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Component, JSX } from 'solid-js';
|
|
2
|
+
import { ImageFormat, ImageFit } from '../index.js';
|
|
3
|
+
import 'node:buffer';
|
|
4
|
+
|
|
5
|
+
/** @jsxImportSource solid-js */
|
|
6
|
+
/**
|
|
7
|
+
* Solid Image Component for @flightdev/image
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```tsx
|
|
11
|
+
* import { Image } from '@flightdev/image/solid';
|
|
12
|
+
*
|
|
13
|
+
* <Image
|
|
14
|
+
* src="/hero.jpg"
|
|
15
|
+
* alt="Hero"
|
|
16
|
+
* width={800}
|
|
17
|
+
* height={600}
|
|
18
|
+
* priority
|
|
19
|
+
* placeholder="blur"
|
|
20
|
+
* />
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
interface ImageProps {
|
|
25
|
+
src: string;
|
|
26
|
+
alt: string;
|
|
27
|
+
width?: number;
|
|
28
|
+
height?: number;
|
|
29
|
+
format?: ImageFormat;
|
|
30
|
+
quality?: number;
|
|
31
|
+
fit?: ImageFit;
|
|
32
|
+
priority?: boolean;
|
|
33
|
+
placeholder?: 'blur' | 'empty' | 'none';
|
|
34
|
+
blurDataUrl?: string;
|
|
35
|
+
sizes?: string;
|
|
36
|
+
baseUrl?: string;
|
|
37
|
+
class?: string;
|
|
38
|
+
style?: JSX.CSSProperties;
|
|
39
|
+
onLoad?: () => void;
|
|
40
|
+
onError?: () => void;
|
|
41
|
+
}
|
|
42
|
+
declare const Image: Component<ImageProps>;
|
|
43
|
+
|
|
44
|
+
export { Image, type ImageProps, Image as default };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { createSignal, createMemo, Show } from 'solid-js';
|
|
2
|
+
import { jsxs, jsx } from 'solid-js/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
// src/components/solid.tsx
|
|
5
|
+
function buildOptimizedUrl(src, options, baseUrl = "") {
|
|
6
|
+
const params = new URLSearchParams();
|
|
7
|
+
if (options.width) params.set("w", options.width.toString());
|
|
8
|
+
if (options.height) params.set("h", options.height.toString());
|
|
9
|
+
if (options.format && options.format !== "auto") params.set("f", options.format);
|
|
10
|
+
if (options.quality) params.set("q", options.quality.toString());
|
|
11
|
+
if (options.fit) params.set("fit", options.fit);
|
|
12
|
+
const queryString = params.toString();
|
|
13
|
+
const normalizedSrc = src.startsWith("/") ? src : `/${src}`;
|
|
14
|
+
return `${baseUrl}/_flight/image${normalizedSrc}${queryString ? "?" + queryString : ""}`;
|
|
15
|
+
}
|
|
16
|
+
var Image = (props) => {
|
|
17
|
+
const [isLoaded, setIsLoaded] = createSignal(false);
|
|
18
|
+
const [error, setError] = createSignal(false);
|
|
19
|
+
const format = () => props.format ?? "auto";
|
|
20
|
+
const quality = () => props.quality ?? 80;
|
|
21
|
+
const fit = () => props.fit ?? "cover";
|
|
22
|
+
const priority = () => props.priority ?? false;
|
|
23
|
+
const placeholder = () => props.placeholder ?? "empty";
|
|
24
|
+
const baseUrl = () => props.baseUrl ?? "";
|
|
25
|
+
const optimizedSrc = createMemo(
|
|
26
|
+
() => buildOptimizedUrl(props.src, {
|
|
27
|
+
width: props.width,
|
|
28
|
+
height: props.height,
|
|
29
|
+
format: format(),
|
|
30
|
+
quality: quality(),
|
|
31
|
+
fit: fit()
|
|
32
|
+
}, baseUrl())
|
|
33
|
+
);
|
|
34
|
+
const srcSet = createMemo(() => {
|
|
35
|
+
if (!props.width) return void 0;
|
|
36
|
+
const widths = [props.width, Math.round(props.width * 1.5), props.width * 2];
|
|
37
|
+
return widths.map((w) => {
|
|
38
|
+
const h = props.height ? Math.round(props.height * w / props.width) : void 0;
|
|
39
|
+
return `${buildOptimizedUrl(props.src, { width: w, height: h, format: format(), quality: quality(), fit: fit() }, baseUrl())} ${w}w`;
|
|
40
|
+
}).join(", ");
|
|
41
|
+
});
|
|
42
|
+
const defaultSizes = createMemo(
|
|
43
|
+
() => props.width ? `(max-width: ${props.width}px) 100vw, ${props.width}px` : void 0
|
|
44
|
+
);
|
|
45
|
+
const handleLoad = () => {
|
|
46
|
+
setIsLoaded(true);
|
|
47
|
+
props.onLoad?.();
|
|
48
|
+
};
|
|
49
|
+
const handleError = () => {
|
|
50
|
+
setError(true);
|
|
51
|
+
props.onError?.();
|
|
52
|
+
};
|
|
53
|
+
const containerStyle = () => ({
|
|
54
|
+
position: "relative",
|
|
55
|
+
overflow: "hidden",
|
|
56
|
+
width: props.width ? `${props.width}px` : void 0,
|
|
57
|
+
height: props.height ? `${props.height}px` : void 0,
|
|
58
|
+
...props.style
|
|
59
|
+
});
|
|
60
|
+
const imageStyle = () => ({
|
|
61
|
+
width: "100%",
|
|
62
|
+
height: "100%",
|
|
63
|
+
"object-fit": fit(),
|
|
64
|
+
opacity: isLoaded() ? 1 : 0,
|
|
65
|
+
transition: "opacity 0.3s ease-in-out"
|
|
66
|
+
});
|
|
67
|
+
const blurStyle = () => ({
|
|
68
|
+
position: "absolute",
|
|
69
|
+
inset: "0",
|
|
70
|
+
"background-image": props.blurDataUrl ? `url(${props.blurDataUrl})` : void 0,
|
|
71
|
+
"background-size": "cover",
|
|
72
|
+
"background-position": "center",
|
|
73
|
+
filter: "blur(20px)",
|
|
74
|
+
transform: "scale(1.1)"
|
|
75
|
+
});
|
|
76
|
+
return /* @__PURE__ */ jsxs("div", { style: containerStyle(), class: props.class, children: [
|
|
77
|
+
/* @__PURE__ */ jsx(Show, { when: placeholder() === "blur" && props.blurDataUrl && !isLoaded(), children: /* @__PURE__ */ jsx("div", { style: blurStyle(), "aria-hidden": "true" }) }),
|
|
78
|
+
/* @__PURE__ */ jsx(
|
|
79
|
+
"img",
|
|
80
|
+
{
|
|
81
|
+
src: optimizedSrc(),
|
|
82
|
+
srcset: srcSet(),
|
|
83
|
+
sizes: props.sizes ?? defaultSizes(),
|
|
84
|
+
alt: props.alt,
|
|
85
|
+
width: props.width,
|
|
86
|
+
height: props.height,
|
|
87
|
+
loading: priority() ? "eager" : "lazy",
|
|
88
|
+
decoding: priority() ? "sync" : "async",
|
|
89
|
+
fetchpriority: priority() ? "high" : void 0,
|
|
90
|
+
onLoad: handleLoad,
|
|
91
|
+
onError: handleError,
|
|
92
|
+
style: imageStyle()
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
] });
|
|
96
|
+
};
|
|
97
|
+
var solid_default = Image;
|
|
98
|
+
|
|
99
|
+
export { Image, solid_default as default };
|
|
100
|
+
//# sourceMappingURL=solid.js.map
|
|
101
|
+
//# sourceMappingURL=solid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/solid.tsx"],"names":[],"mappings":"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","file":"solid.js","sourcesContent":["/** @jsxImportSource solid-js */\r\n/**\r\n * Solid Image Component for @flightdev/image\r\n * \r\n * @example\r\n * ```tsx\r\n * import { Image } from '@flightdev/image/solid';\r\n * \r\n * <Image\r\n * src=\"/hero.jpg\"\r\n * alt=\"Hero\"\r\n * width={800}\r\n * height={600}\r\n * priority\r\n * placeholder=\"blur\"\r\n * />\r\n * ```\r\n */\r\n\r\nimport { createSignal, createMemo, Show, type JSX, type Component } from 'solid-js';\r\nimport type { ImageFormat, ImageFit } from '../index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport interface ImageProps {\r\n src: string;\r\n alt: string;\r\n width?: number;\r\n height?: number;\r\n format?: ImageFormat;\r\n quality?: number;\r\n fit?: ImageFit;\r\n priority?: boolean;\r\n placeholder?: 'blur' | 'empty' | 'none';\r\n blurDataUrl?: string;\r\n sizes?: string;\r\n baseUrl?: string;\r\n class?: string;\r\n style?: JSX.CSSProperties;\r\n onLoad?: () => void;\r\n onError?: () => void;\r\n}\r\n\r\n// ============================================================================\r\n// URL Builder\r\n// ============================================================================\r\n\r\nfunction buildOptimizedUrl(\r\n src: string,\r\n options: { width?: number; height?: number; format?: ImageFormat; quality?: number; fit?: ImageFit },\r\n baseUrl: string = ''\r\n): string {\r\n const params = new URLSearchParams();\r\n\r\n if (options.width) params.set('w', options.width.toString());\r\n if (options.height) params.set('h', options.height.toString());\r\n if (options.format && options.format !== 'auto') params.set('f', options.format);\r\n if (options.quality) params.set('q', options.quality.toString());\r\n if (options.fit) params.set('fit', options.fit);\r\n\r\n const queryString = params.toString();\r\n const normalizedSrc = src.startsWith('/') ? src : `/${src}`;\r\n return `${baseUrl}/_flight/image${normalizedSrc}${queryString ? '?' + queryString : ''}`;\r\n}\r\n\r\n// ============================================================================\r\n// Solid Component\r\n// ============================================================================\r\n\r\nexport const Image: Component<ImageProps> = (props) => {\r\n const [isLoaded, setIsLoaded] = createSignal(false);\r\n const [error, setError] = createSignal(false);\r\n\r\n const format = () => props.format ?? 'auto';\r\n const quality = () => props.quality ?? 80;\r\n const fit = () => props.fit ?? 'cover';\r\n const priority = () => props.priority ?? false;\r\n const placeholder = () => props.placeholder ?? 'empty';\r\n const baseUrl = () => props.baseUrl ?? '';\r\n\r\n const optimizedSrc = createMemo(() =>\r\n buildOptimizedUrl(props.src, {\r\n width: props.width,\r\n height: props.height,\r\n format: format(),\r\n quality: quality(),\r\n fit: fit(),\r\n }, baseUrl())\r\n );\r\n\r\n const srcSet = createMemo(() => {\r\n if (!props.width) return undefined;\r\n\r\n const widths = [props.width, Math.round(props.width * 1.5), props.width * 2];\r\n return widths\r\n .map(w => {\r\n const h = props.height ? Math.round(props.height * w / props.width!) : undefined;\r\n return `${buildOptimizedUrl(props.src, { width: w, height: h, format: format(), quality: quality(), fit: fit() }, baseUrl())} ${w}w`;\r\n })\r\n .join(', ');\r\n });\r\n\r\n const defaultSizes = createMemo(() =>\r\n props.width ? `(max-width: ${props.width}px) 100vw, ${props.width}px` : undefined\r\n );\r\n\r\n const handleLoad = () => {\r\n setIsLoaded(true);\r\n props.onLoad?.();\r\n };\r\n\r\n const handleError = () => {\r\n setError(true);\r\n props.onError?.();\r\n };\r\n\r\n const containerStyle = (): JSX.CSSProperties => ({\r\n position: 'relative',\r\n overflow: 'hidden',\r\n width: props.width ? `${props.width}px` : undefined,\r\n height: props.height ? `${props.height}px` : undefined,\r\n ...props.style,\r\n });\r\n\r\n const imageStyle = (): JSX.CSSProperties => ({\r\n width: '100%',\r\n height: '100%',\r\n 'object-fit': fit() as 'cover' | 'contain' | 'fill' | 'none' | 'scale-down',\r\n opacity: isLoaded() ? 1 : 0,\r\n transition: 'opacity 0.3s ease-in-out',\r\n });\r\n\r\n const blurStyle = (): JSX.CSSProperties => ({\r\n position: 'absolute',\r\n inset: '0',\r\n 'background-image': props.blurDataUrl ? `url(${props.blurDataUrl})` : undefined,\r\n 'background-size': 'cover',\r\n 'background-position': 'center',\r\n filter: 'blur(20px)',\r\n transform: 'scale(1.1)',\r\n });\r\n\r\n return (\r\n <div style={containerStyle()} class={props.class}>\r\n {/* Blur placeholder */}\r\n <Show when={placeholder() === 'blur' && props.blurDataUrl && !isLoaded()}>\r\n <div style={blurStyle()} aria-hidden=\"true\" />\r\n </Show>\r\n\r\n {/* Image */}\r\n <img\r\n src={optimizedSrc()}\r\n srcset={srcSet()}\r\n sizes={props.sizes ?? defaultSizes()}\r\n alt={props.alt}\r\n width={props.width}\r\n height={props.height}\r\n loading={priority() ? 'eager' : 'lazy'}\r\n decoding={priority() ? 'sync' : 'async'}\r\n // @ts-ignore - fetchpriority is valid but not in types\r\n fetchpriority={priority() ? 'high' : undefined}\r\n onLoad={handleLoad}\r\n onError={handleError}\r\n style={imageStyle()}\r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default Image;\r\n"]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ImageFormat, ImageFit } from '../index.js';
|
|
2
|
+
import 'node:buffer';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Svelte Image Component for @flightdev/image
|
|
6
|
+
*
|
|
7
|
+
* This file exports utilities and types for a Svelte Image component.
|
|
8
|
+
* The actual Svelte component should be in a .svelte file.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <script>
|
|
13
|
+
* import { createImageProps } from '@flightdev/image/svelte';
|
|
14
|
+
*
|
|
15
|
+
* export let src;
|
|
16
|
+
* export let alt;
|
|
17
|
+
* export let width = undefined;
|
|
18
|
+
* export let height = undefined;
|
|
19
|
+
*
|
|
20
|
+
* $: imageProps = createImageProps({ src, alt, width, height });
|
|
21
|
+
* </script>
|
|
22
|
+
*
|
|
23
|
+
* <img {...imageProps} loading="lazy" />
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
interface SvelteImageOptions {
|
|
28
|
+
src: string;
|
|
29
|
+
alt: string;
|
|
30
|
+
width?: number;
|
|
31
|
+
height?: number;
|
|
32
|
+
format?: ImageFormat;
|
|
33
|
+
quality?: number;
|
|
34
|
+
fit?: ImageFit;
|
|
35
|
+
priority?: boolean;
|
|
36
|
+
baseUrl?: string;
|
|
37
|
+
}
|
|
38
|
+
interface SvelteImageProps {
|
|
39
|
+
src: string;
|
|
40
|
+
srcset?: string;
|
|
41
|
+
sizes?: string;
|
|
42
|
+
alt: string;
|
|
43
|
+
width?: number;
|
|
44
|
+
height?: number;
|
|
45
|
+
loading: 'lazy' | 'eager';
|
|
46
|
+
decoding: 'sync' | 'async';
|
|
47
|
+
fetchpriority?: 'high' | 'low' | 'auto';
|
|
48
|
+
style?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Create props object for a Svelte img element
|
|
52
|
+
*/
|
|
53
|
+
declare function createImageProps(options: SvelteImageOptions): SvelteImageProps;
|
|
54
|
+
/**
|
|
55
|
+
* Create blur placeholder style string
|
|
56
|
+
*/
|
|
57
|
+
declare function createBlurPlaceholderStyle(blurDataUrl: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Svelte action for lazy loading images with blur placeholder
|
|
60
|
+
*/
|
|
61
|
+
declare function lazyImage(node: HTMLImageElement, blurDataUrl?: string): {
|
|
62
|
+
destroy(): void;
|
|
63
|
+
};
|
|
64
|
+
declare const _default: {
|
|
65
|
+
createImageProps: typeof createImageProps;
|
|
66
|
+
createBlurPlaceholderStyle: typeof createBlurPlaceholderStyle;
|
|
67
|
+
lazyImage: typeof lazyImage;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export { type SvelteImageOptions, type SvelteImageProps, createBlurPlaceholderStyle, createImageProps, _default as default, lazyImage };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// src/components/svelte.ts
|
|
2
|
+
function buildOptimizedUrl(src, options, baseUrl = "") {
|
|
3
|
+
const params = new URLSearchParams();
|
|
4
|
+
if (options.width) params.set("w", options.width.toString());
|
|
5
|
+
if (options.height) params.set("h", options.height.toString());
|
|
6
|
+
if (options.format && options.format !== "auto") params.set("f", options.format);
|
|
7
|
+
if (options.quality) params.set("q", options.quality.toString());
|
|
8
|
+
if (options.fit) params.set("fit", options.fit);
|
|
9
|
+
const queryString = params.toString();
|
|
10
|
+
const normalizedSrc = src.startsWith("/") ? src : `/${src}`;
|
|
11
|
+
return `${baseUrl}/_flight/image${normalizedSrc}${queryString ? "?" + queryString : ""}`;
|
|
12
|
+
}
|
|
13
|
+
function createImageProps(options) {
|
|
14
|
+
const {
|
|
15
|
+
src,
|
|
16
|
+
alt,
|
|
17
|
+
width,
|
|
18
|
+
height,
|
|
19
|
+
format = "auto",
|
|
20
|
+
quality = 80,
|
|
21
|
+
fit = "cover",
|
|
22
|
+
priority = false,
|
|
23
|
+
baseUrl = ""
|
|
24
|
+
} = options;
|
|
25
|
+
const optimizedSrc = buildOptimizedUrl(src, { width, height, format, quality, fit }, baseUrl);
|
|
26
|
+
let srcset;
|
|
27
|
+
if (width) {
|
|
28
|
+
const widths = [width, Math.round(width * 1.5), width * 2];
|
|
29
|
+
srcset = widths.map((w) => {
|
|
30
|
+
const h = height ? Math.round(height * w / width) : void 0;
|
|
31
|
+
return `${buildOptimizedUrl(src, { width: w, height: h, format, quality, fit }, baseUrl)} ${w}w`;
|
|
32
|
+
}).join(", ");
|
|
33
|
+
}
|
|
34
|
+
const sizes = width ? `(max-width: ${width}px) 100vw, ${width}px` : void 0;
|
|
35
|
+
return {
|
|
36
|
+
src: optimizedSrc,
|
|
37
|
+
srcset,
|
|
38
|
+
sizes,
|
|
39
|
+
alt,
|
|
40
|
+
width,
|
|
41
|
+
height,
|
|
42
|
+
loading: priority ? "eager" : "lazy",
|
|
43
|
+
decoding: priority ? "sync" : "async",
|
|
44
|
+
fetchpriority: priority ? "high" : void 0,
|
|
45
|
+
style: `object-fit: ${fit}`
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function createBlurPlaceholderStyle(blurDataUrl) {
|
|
49
|
+
return `
|
|
50
|
+
background-image: url(${blurDataUrl});
|
|
51
|
+
background-size: cover;
|
|
52
|
+
background-position: center;
|
|
53
|
+
filter: blur(20px);
|
|
54
|
+
transform: scale(1.1);
|
|
55
|
+
`.trim();
|
|
56
|
+
}
|
|
57
|
+
function lazyImage(node, blurDataUrl) {
|
|
58
|
+
if (blurDataUrl) {
|
|
59
|
+
const wrapper = node.parentElement;
|
|
60
|
+
if (wrapper) {
|
|
61
|
+
wrapper.style.position = "relative";
|
|
62
|
+
wrapper.style.overflow = "hidden";
|
|
63
|
+
const placeholder = document.createElement("div");
|
|
64
|
+
placeholder.style.cssText = `
|
|
65
|
+
position: absolute;
|
|
66
|
+
inset: 0;
|
|
67
|
+
${createBlurPlaceholderStyle(blurDataUrl)}
|
|
68
|
+
transition: opacity 0.3s ease-in-out;
|
|
69
|
+
`;
|
|
70
|
+
wrapper.insertBefore(placeholder, node);
|
|
71
|
+
node.style.opacity = "0";
|
|
72
|
+
node.style.transition = "opacity 0.3s ease-in-out";
|
|
73
|
+
node.addEventListener("load", () => {
|
|
74
|
+
node.style.opacity = "1";
|
|
75
|
+
placeholder.style.opacity = "0";
|
|
76
|
+
setTimeout(() => placeholder.remove(), 300);
|
|
77
|
+
}, { once: true });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
destroy() {
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
var svelte_default = { createImageProps, createBlurPlaceholderStyle, lazyImage };
|
|
86
|
+
|
|
87
|
+
export { createBlurPlaceholderStyle, createImageProps, svelte_default as default, lazyImage };
|
|
88
|
+
//# sourceMappingURL=svelte.js.map
|
|
89
|
+
//# sourceMappingURL=svelte.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/svelte.ts"],"names":[],"mappings":"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","file":"svelte.js","sourcesContent":["/**\r\n * Svelte Image Component for @flightdev/image\r\n * \r\n * This file exports utilities and types for a Svelte Image component.\r\n * The actual Svelte component should be in a .svelte file.\r\n * \r\n * @example\r\n * ```svelte\r\n * <script>\r\n * import { createImageProps } from '@flightdev/image/svelte';\r\n * \r\n * export let src;\r\n * export let alt;\r\n * export let width = undefined;\r\n * export let height = undefined;\r\n * \r\n * $: imageProps = createImageProps({ src, alt, width, height });\r\n * </script>\r\n * \r\n * <img {...imageProps} loading=\"lazy\" />\r\n * ```\r\n */\r\n\r\nimport type { ImageFormat, ImageFit } from '../index.js';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport interface SvelteImageOptions {\r\n src: string;\r\n alt: string;\r\n width?: number;\r\n height?: number;\r\n format?: ImageFormat;\r\n quality?: number;\r\n fit?: ImageFit;\r\n priority?: boolean;\r\n baseUrl?: string;\r\n}\r\n\r\nexport interface SvelteImageProps {\r\n src: string;\r\n srcset?: string;\r\n sizes?: string;\r\n alt: string;\r\n width?: number;\r\n height?: number;\r\n loading: 'lazy' | 'eager';\r\n decoding: 'sync' | 'async';\r\n fetchpriority?: 'high' | 'low' | 'auto';\r\n style?: string;\r\n}\r\n\r\n// ============================================================================\r\n// URL Builder\r\n// ============================================================================\r\n\r\nfunction buildOptimizedUrl(\r\n src: string,\r\n options: { width?: number; height?: number; format?: ImageFormat; quality?: number; fit?: ImageFit },\r\n baseUrl: string = ''\r\n): string {\r\n const params = new URLSearchParams();\r\n\r\n if (options.width) params.set('w', options.width.toString());\r\n if (options.height) params.set('h', options.height.toString());\r\n if (options.format && options.format !== 'auto') params.set('f', options.format);\r\n if (options.quality) params.set('q', options.quality.toString());\r\n if (options.fit) params.set('fit', options.fit);\r\n\r\n const queryString = params.toString();\r\n const normalizedSrc = src.startsWith('/') ? src : `/${src}`;\r\n return `${baseUrl}/_flight/image${normalizedSrc}${queryString ? '?' + queryString : ''}`;\r\n}\r\n\r\n// ============================================================================\r\n// Svelte Utilities\r\n// ============================================================================\r\n\r\n/**\r\n * Create props object for a Svelte img element\r\n */\r\nexport function createImageProps(options: SvelteImageOptions): SvelteImageProps {\r\n const {\r\n src,\r\n alt,\r\n width,\r\n height,\r\n format = 'auto',\r\n quality = 80,\r\n fit = 'cover',\r\n priority = false,\r\n baseUrl = '',\r\n } = options;\r\n\r\n const optimizedSrc = buildOptimizedUrl(src, { width, height, format, quality, fit }, baseUrl);\r\n\r\n let srcset: string | undefined;\r\n if (width) {\r\n const widths = [width, Math.round(width * 1.5), width * 2];\r\n srcset = widths\r\n .map(w => {\r\n const h = height ? Math.round(height * w / width) : undefined;\r\n return `${buildOptimizedUrl(src, { width: w, height: h, format, quality, fit }, baseUrl)} ${w}w`;\r\n })\r\n .join(', ');\r\n }\r\n\r\n const sizes = width ? `(max-width: ${width}px) 100vw, ${width}px` : undefined;\r\n\r\n return {\r\n src: optimizedSrc,\r\n srcset,\r\n sizes,\r\n alt,\r\n width,\r\n height,\r\n loading: priority ? 'eager' : 'lazy',\r\n decoding: priority ? 'sync' : 'async',\r\n fetchpriority: priority ? 'high' : undefined,\r\n style: `object-fit: ${fit}`,\r\n };\r\n}\r\n\r\n/**\r\n * Create blur placeholder style string\r\n */\r\nexport function createBlurPlaceholderStyle(blurDataUrl: string): string {\r\n return `\r\n background-image: url(${blurDataUrl});\r\n background-size: cover;\r\n background-position: center;\r\n filter: blur(20px);\r\n transform: scale(1.1);\r\n `.trim();\r\n}\r\n\r\n/**\r\n * Svelte action for lazy loading images with blur placeholder\r\n */\r\nexport function lazyImage(node: HTMLImageElement, blurDataUrl?: string) {\r\n if (blurDataUrl) {\r\n // Set blur background initially\r\n const wrapper = node.parentElement;\r\n if (wrapper) {\r\n wrapper.style.position = 'relative';\r\n wrapper.style.overflow = 'hidden';\r\n\r\n const placeholder = document.createElement('div');\r\n placeholder.style.cssText = `\r\n position: absolute;\r\n inset: 0;\r\n ${createBlurPlaceholderStyle(blurDataUrl)}\r\n transition: opacity 0.3s ease-in-out;\r\n `;\r\n wrapper.insertBefore(placeholder, node);\r\n\r\n node.style.opacity = '0';\r\n node.style.transition = 'opacity 0.3s ease-in-out';\r\n\r\n node.addEventListener('load', () => {\r\n node.style.opacity = '1';\r\n placeholder.style.opacity = '0';\r\n setTimeout(() => placeholder.remove(), 300);\r\n }, { once: true });\r\n }\r\n }\r\n\r\n return {\r\n destroy() {\r\n // Cleanup if needed\r\n },\r\n };\r\n}\r\n\r\nexport default { createImageProps, createBlurPlaceholderStyle, lazyImage };\r\n"]}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import * as vue from 'vue';
|
|
2
|
+
import { PropType } from 'vue';
|
|
3
|
+
import { ImageFormat, ImageFit } from '../index.js';
|
|
4
|
+
import 'node:buffer';
|
|
5
|
+
|
|
6
|
+
interface FlightImageProps {
|
|
7
|
+
src: string;
|
|
8
|
+
alt: string;
|
|
9
|
+
width?: number;
|
|
10
|
+
height?: number;
|
|
11
|
+
format?: ImageFormat;
|
|
12
|
+
quality?: number;
|
|
13
|
+
fit?: ImageFit;
|
|
14
|
+
priority?: boolean;
|
|
15
|
+
placeholder?: 'blur' | 'empty' | 'none';
|
|
16
|
+
blurDataUrl?: string;
|
|
17
|
+
sizes?: string;
|
|
18
|
+
baseUrl?: string;
|
|
19
|
+
}
|
|
20
|
+
declare const FlightImage: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
21
|
+
src: {
|
|
22
|
+
type: StringConstructor;
|
|
23
|
+
required: true;
|
|
24
|
+
};
|
|
25
|
+
alt: {
|
|
26
|
+
type: StringConstructor;
|
|
27
|
+
required: true;
|
|
28
|
+
};
|
|
29
|
+
width: {
|
|
30
|
+
type: NumberConstructor;
|
|
31
|
+
default: undefined;
|
|
32
|
+
};
|
|
33
|
+
height: {
|
|
34
|
+
type: NumberConstructor;
|
|
35
|
+
default: undefined;
|
|
36
|
+
};
|
|
37
|
+
format: {
|
|
38
|
+
type: PropType<ImageFormat>;
|
|
39
|
+
default: string;
|
|
40
|
+
};
|
|
41
|
+
quality: {
|
|
42
|
+
type: NumberConstructor;
|
|
43
|
+
default: number;
|
|
44
|
+
};
|
|
45
|
+
fit: {
|
|
46
|
+
type: PropType<ImageFit>;
|
|
47
|
+
default: string;
|
|
48
|
+
};
|
|
49
|
+
priority: {
|
|
50
|
+
type: BooleanConstructor;
|
|
51
|
+
default: boolean;
|
|
52
|
+
};
|
|
53
|
+
placeholder: {
|
|
54
|
+
type: PropType<"blur" | "empty" | "none">;
|
|
55
|
+
default: string;
|
|
56
|
+
};
|
|
57
|
+
blurDataUrl: {
|
|
58
|
+
type: StringConstructor;
|
|
59
|
+
default: undefined;
|
|
60
|
+
};
|
|
61
|
+
sizes: {
|
|
62
|
+
type: StringConstructor;
|
|
63
|
+
default: undefined;
|
|
64
|
+
};
|
|
65
|
+
baseUrl: {
|
|
66
|
+
type: StringConstructor;
|
|
67
|
+
default: string;
|
|
68
|
+
};
|
|
69
|
+
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
70
|
+
[key: string]: any;
|
|
71
|
+
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
72
|
+
src: {
|
|
73
|
+
type: StringConstructor;
|
|
74
|
+
required: true;
|
|
75
|
+
};
|
|
76
|
+
alt: {
|
|
77
|
+
type: StringConstructor;
|
|
78
|
+
required: true;
|
|
79
|
+
};
|
|
80
|
+
width: {
|
|
81
|
+
type: NumberConstructor;
|
|
82
|
+
default: undefined;
|
|
83
|
+
};
|
|
84
|
+
height: {
|
|
85
|
+
type: NumberConstructor;
|
|
86
|
+
default: undefined;
|
|
87
|
+
};
|
|
88
|
+
format: {
|
|
89
|
+
type: PropType<ImageFormat>;
|
|
90
|
+
default: string;
|
|
91
|
+
};
|
|
92
|
+
quality: {
|
|
93
|
+
type: NumberConstructor;
|
|
94
|
+
default: number;
|
|
95
|
+
};
|
|
96
|
+
fit: {
|
|
97
|
+
type: PropType<ImageFit>;
|
|
98
|
+
default: string;
|
|
99
|
+
};
|
|
100
|
+
priority: {
|
|
101
|
+
type: BooleanConstructor;
|
|
102
|
+
default: boolean;
|
|
103
|
+
};
|
|
104
|
+
placeholder: {
|
|
105
|
+
type: PropType<"blur" | "empty" | "none">;
|
|
106
|
+
default: string;
|
|
107
|
+
};
|
|
108
|
+
blurDataUrl: {
|
|
109
|
+
type: StringConstructor;
|
|
110
|
+
default: undefined;
|
|
111
|
+
};
|
|
112
|
+
sizes: {
|
|
113
|
+
type: StringConstructor;
|
|
114
|
+
default: undefined;
|
|
115
|
+
};
|
|
116
|
+
baseUrl: {
|
|
117
|
+
type: StringConstructor;
|
|
118
|
+
default: string;
|
|
119
|
+
};
|
|
120
|
+
}>> & Readonly<{}>, {
|
|
121
|
+
fit: ImageFit;
|
|
122
|
+
width: number;
|
|
123
|
+
height: number;
|
|
124
|
+
format: ImageFormat;
|
|
125
|
+
quality: number;
|
|
126
|
+
priority: boolean;
|
|
127
|
+
placeholder: "blur" | "empty" | "none";
|
|
128
|
+
blurDataUrl: string;
|
|
129
|
+
sizes: string;
|
|
130
|
+
baseUrl: string;
|
|
131
|
+
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
132
|
+
|
|
133
|
+
export { FlightImage, type FlightImageProps, FlightImage as default };
|