@smoothcdn/loader 1.0.1 → 1.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.
@@ -0,0 +1,42 @@
1
+ export type CdnLoadingMode = {
2
+ isCritical?: boolean;
3
+ };
4
+ export type ImageVariantSource = {
5
+ width: number;
6
+ url: string;
7
+ };
8
+ export type ImageSnippetAttributes = {
9
+ src: string;
10
+ srcSet?: string;
11
+ sizes?: string;
12
+ loading?: "lazy";
13
+ decoding: "async" | "sync";
14
+ fetchPriority?: "high";
15
+ width?: number | string;
16
+ height?: number | string;
17
+ };
18
+ export type MediaSnippetAttributes = {
19
+ preload: "auto" | "none";
20
+ };
21
+ export type ScriptSnippetAttributes = {
22
+ async?: true;
23
+ defer?: true;
24
+ preload?: true;
25
+ };
26
+ export type StyleSnippetAttributes = {
27
+ preload?: true;
28
+ };
29
+ export declare function getImageSnippetAttributes({ src, variants, alt, isCritical, width, height, }: {
30
+ src: string;
31
+ variants?: ImageVariantSource[];
32
+ alt: string;
33
+ isCritical?: boolean;
34
+ width?: number | string;
35
+ height?: number | string;
36
+ }): ImageSnippetAttributes & {
37
+ alt: string;
38
+ };
39
+ export declare function getMediaSnippetAttributes({ isCritical }?: CdnLoadingMode): MediaSnippetAttributes;
40
+ export declare function getScriptSnippetAttributes({ isCritical }?: CdnLoadingMode): ScriptSnippetAttributes;
41
+ export declare function getStyleSnippetAttributes({ isCritical }?: CdnLoadingMode): StyleSnippetAttributes;
42
+ //# sourceMappingURL=html-snippets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-snippets.d.ts","sourceRoot":"","sources":["../../src/core/html-snippets.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACjC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IAClC,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,KAAK,CAAC,EAAE,IAAI,CAAC;IACb,OAAO,CAAC,EAAE,IAAI,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACjC,OAAO,CAAC,EAAE,IAAI,CAAC;CAClB,CAAC;AAEF,wBAAgB,yBAAyB,CACrC,EACI,GAAG,EACH,QAAa,EACb,GAAG,EACH,UAAkB,EAClB,KAAK,EACL,MAAM,GACT,EAAE;IACC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B,GACF,sBAAsB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAgB1C;AAED,wBAAgB,yBAAyB,CAAC,EAAC,UAAkB,EAAC,GAAE,cAAmB,GAAG,sBAAsB,CAI3G;AAED,wBAAgB,0BAA0B,CAAC,EAAC,UAAkB,EAAC,GAAE,cAAmB,GAAG,uBAAuB,CAI7G;AAED,wBAAgB,yBAAyB,CAAC,EAAC,UAAkB,EAAC,GAAE,cAAmB,GAAG,sBAAsB,CAE3G"}
@@ -0,0 +1,55 @@
1
+ export function getImageSnippetAttributes({ src, variants = [], alt, isCritical = false, width, height, }) {
2
+ const srcSet = getImageSrcSet(variants);
3
+ const sizes = getImageSizes(width, srcSet);
4
+ const fallbackSrc = variants.length ? variants[variants.length - 1]?.url || src : src;
5
+ return {
6
+ src: fallbackSrc,
7
+ alt,
8
+ ...(srcSet ? { srcSet } : {}),
9
+ ...(sizes ? { sizes } : {}),
10
+ ...(isCritical
11
+ ? { fetchPriority: "high", decoding: "sync" }
12
+ : { loading: "lazy", decoding: "async" }),
13
+ ...(width ? { width } : {}),
14
+ ...(height ? { height } : {}),
15
+ };
16
+ }
17
+ export function getMediaSnippetAttributes({ isCritical = false } = {}) {
18
+ return {
19
+ preload: isCritical ? "auto" : "none",
20
+ };
21
+ }
22
+ export function getScriptSnippetAttributes({ isCritical = false } = {}) {
23
+ return isCritical
24
+ ? { preload: true, defer: true }
25
+ : { defer: true };
26
+ }
27
+ export function getStyleSnippetAttributes({ isCritical = false } = {}) {
28
+ return isCritical ? { preload: true } : {};
29
+ }
30
+ const getImageSrcSet = (variants) => {
31
+ if (!variants.length) {
32
+ return "";
33
+ }
34
+ const uniqueVariants = new Map();
35
+ for (const variant of variants) {
36
+ if (!variant.url || !Number.isFinite(variant.width) || variant.width <= 0) {
37
+ continue;
38
+ }
39
+ uniqueVariants.set(variant.width, variant.url);
40
+ }
41
+ return Array.from(uniqueVariants.entries())
42
+ .sort((a, b) => a[0] - b[0])
43
+ .map(([width, url]) => `${url} ${width}w`)
44
+ .join(", ");
45
+ };
46
+ const getImageSizes = (width, srcSet) => {
47
+ if (!srcSet) {
48
+ return "";
49
+ }
50
+ const numericWidth = Number(width);
51
+ if (Number.isFinite(numericWidth) && numericWidth > 0) {
52
+ return `(max-width: ${numericWidth}px) 100vw, ${numericWidth}px`;
53
+ }
54
+ return "100vw";
55
+ };
@@ -1,5 +1,7 @@
1
1
  export { createLoader } from "./createLoader.js";
2
2
  export { getConfig, initConfig, normalizeConfig } from "./config.js";
3
+ export { getImageSnippetAttributes, getMediaSnippetAttributes, getScriptSnippetAttributes, getStyleSnippetAttributes, } from "./html-snippets.js";
3
4
  export { buildUrl, normalizePath, resolveDefaultVariantSlug } from "./utils.js";
5
+ export type * from "./html-snippets.js";
4
6
  export type * from "./types.js";
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAC,SAAS,EAAE,UAAU,EAAE,eAAe,EAAC,MAAM,aAAa,CAAC;AACnE,OAAO,EAAC,QAAQ,EAAE,aAAa,EAAE,yBAAyB,EAAC,MAAM,YAAY,CAAC;AAC9E,mBAAmB,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAC,SAAS,EAAE,UAAU,EAAE,eAAe,EAAC,MAAM,aAAa,CAAC;AACnE,OAAO,EACH,yBAAyB,EACzB,yBAAyB,EACzB,0BAA0B,EAC1B,yBAAyB,GAC5B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,QAAQ,EAAE,aAAa,EAAE,yBAAyB,EAAC,MAAM,YAAY,CAAC;AAC9E,mBAAmB,oBAAoB,CAAC;AACxC,mBAAmB,YAAY,CAAC"}
@@ -1,3 +1,4 @@
1
1
  export { createLoader } from "./createLoader.js";
2
2
  export { getConfig, initConfig, normalizeConfig } from "./config.js";
3
+ export { getImageSnippetAttributes, getMediaSnippetAttributes, getScriptSnippetAttributes, getStyleSnippetAttributes, } from "./html-snippets.js";
3
4
  export { buildUrl, normalizePath, resolveDefaultVariantSlug } from "./utils.js";
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  export { createLoader } from "./core/createLoader.js";
2
2
  export { initConfig, normalizeConfig } from "./core/config.js";
3
+ export { getImageSnippetAttributes, getMediaSnippetAttributes, getScriptSnippetAttributes, getStyleSnippetAttributes, } from "./core/html-snippets.js";
3
4
  export { buildUrl } from "./core/utils.js";
5
+ export type * from "./core/html-snippets.js";
4
6
  export type * from "./core/types.js";
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,mBAAmB,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EACH,yBAAyB,EACzB,yBAAyB,EACzB,0BAA0B,EAC1B,yBAAyB,GAC5B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,mBAAmB,yBAAyB,CAAC;AAC7C,mBAAmB,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { createLoader } from "./core/createLoader.js";
2
2
  export { initConfig, normalizeConfig } from "./core/config.js";
3
+ export { getImageSnippetAttributes, getMediaSnippetAttributes, getScriptSnippetAttributes, getStyleSnippetAttributes, } from "./core/html-snippets.js";
3
4
  export { buildUrl } from "./core/utils.js";
@@ -1,8 +1,3 @@
1
- import { ImageProps } from "next/image";
2
- import type { LoaderAssetMap, LoaderDefaultAssetMap, LoaderImagePath, LoaderVariantSlug } from "../core/types.js";
3
- export type CDNImageProps<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap> = {
4
- assetPath: LoaderImagePath<TAssets>;
5
- variantSlug?: LoaderVariantSlug<TAssets>;
6
- } & Omit<ImageProps, "src">;
7
- export declare function CDNImage<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>({ assetPath, variantSlug, ...props }: CDNImageProps<TAssets>): import("react/jsx-runtime").JSX.Element;
1
+ export { CDNImage } from "../react/CDNImage.js";
2
+ export type { CDNImageProps } from "../react/CDNImage.js";
8
3
  //# sourceMappingURL=CDNImage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CDNImage.d.ts","sourceRoot":"","sources":["../../src/next/CDNImage.tsx"],"names":[],"mappings":"AACA,OAAc,EAAC,UAAU,EAAC,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEhH,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,IAAI;IACrG,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;CAC5C,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;AAE5B,wBAAgB,QAAQ,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAChG,EACI,SAAS,EACT,WAAW,EACX,GAAG,KAAK,EACX,EAAE,aAAa,CAAC,OAAO,CAAC,2CAE5B"}
1
+ {"version":3,"file":"CDNImage.d.ts","sourceRoot":"","sources":["../../src/next/CDNImage.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAC9C,YAAY,EAAC,aAAa,EAAC,MAAM,sBAAsB,CAAC"}
@@ -1,6 +1 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import Image from "next/image";
3
- import { buildUrl } from "../core/utils.js";
4
- export function CDNImage({ assetPath, variantSlug, ...props }) {
5
- return _jsx(Image, { src: buildUrl(assetPath, variantSlug), ...props });
6
- }
1
+ export { CDNImage } from "../react/CDNImage.js";
@@ -1,7 +1,7 @@
1
1
  import type { LoaderAssetMap, LoaderDefaultAssetMap, LoaderScriptPath, LoaderVariantSlug } from "../core/types.js";
2
- export declare function Script<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>({ assetPath, variantSlug, strategy }: {
2
+ export declare function Script<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>({ assetPath, variantSlug, isCritical, }: {
3
3
  assetPath: LoaderScriptPath<TAssets>;
4
4
  variantSlug?: LoaderVariantSlug<TAssets>;
5
- strategy?: "afterInteractive" | "lazyOnload";
5
+ isCritical?: boolean;
6
6
  }): import("react/jsx-runtime").JSX.Element;
7
7
  //# sourceMappingURL=Script.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Script.d.ts","sourceRoot":"","sources":["../../src/next/Script.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEjH,wBAAgB,MAAM,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAC9F,EACI,SAAS,EACT,WAAW,EACX,QAA6B,EAChC,EAAE;IACC,SAAS,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,kBAAkB,GAAG,YAAY,CAAC;CAChD,2CAOJ"}
1
+ {"version":3,"file":"Script.d.ts","sourceRoot":"","sources":["../../src/next/Script.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEjH,wBAAgB,MAAM,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAC9F,EACI,SAAS,EACT,WAAW,EACX,UAAkB,GACrB,EAAE;IACC,SAAS,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,2CAaJ"}
@@ -1,7 +1,10 @@
1
1
  "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import NextScript from "next/script";
4
+ import { getScriptSnippetAttributes } from "../core/html-snippets.js";
4
5
  import { buildUrl } from "../core/utils.js";
5
- export function Script({ assetPath, variantSlug, strategy = "afterInteractive" }) {
6
- return (_jsx(NextScript, { src: buildUrl(assetPath, variantSlug), strategy: strategy }));
6
+ export function Script({ assetPath, variantSlug, isCritical = false, }) {
7
+ const src = buildUrl(assetPath, variantSlug);
8
+ const snippetAttributes = getScriptSnippetAttributes({ isCritical });
9
+ return (_jsxs(_Fragment, { children: [snippetAttributes.preload ? _jsx("link", { rel: "preload", as: "script", href: src }) : null, _jsx(NextScript, { src: src, strategy: isCritical ? "beforeInteractive" : "afterInteractive" })] }));
7
10
  }
@@ -1,6 +1,7 @@
1
1
  import type { LoaderAssetMap, LoaderDefaultAssetMap, LoaderStylePath, LoaderVariantSlug } from "../core/types.js";
2
- export declare function Style<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>({ assetPath, variantSlug, }: {
2
+ export declare function Style<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>({ assetPath, variantSlug, isCritical, }: {
3
3
  assetPath: LoaderStylePath<TAssets>;
4
4
  variantSlug?: LoaderVariantSlug<TAssets>;
5
+ isCritical?: boolean;
5
6
  }): import("react/jsx-runtime").JSX.Element;
6
7
  //# sourceMappingURL=Style.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Style.d.ts","sourceRoot":"","sources":["../../src/next/Style.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEhH,wBAAgB,KAAK,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAC7F,EACI,SAAS,EACT,WAAW,GACd,EAAE;IACC,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;CAC5C,2CAMJ"}
1
+ {"version":3,"file":"Style.d.ts","sourceRoot":"","sources":["../../src/next/Style.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEhH,wBAAgB,KAAK,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAC7F,EACI,SAAS,EACT,WAAW,EACX,UAAkB,GACrB,EAAE;IACC,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,2CAUJ"}
@@ -1,7 +1,10 @@
1
1
  "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import Head from "next/head";
4
+ import { getStyleSnippetAttributes } from "../core/html-snippets.js";
4
5
  import { buildUrl } from "../core/utils.js";
5
- export function Style({ assetPath, variantSlug, }) {
6
- return (_jsx(Head, { children: _jsx("link", { rel: "stylesheet", href: buildUrl(assetPath, variantSlug) }) }));
6
+ export function Style({ assetPath, variantSlug, isCritical = false, }) {
7
+ const href = buildUrl(assetPath, variantSlug);
8
+ const snippetAttributes = getStyleSnippetAttributes({ isCritical });
9
+ return (_jsxs(Head, { children: [snippetAttributes.preload ? _jsx("link", { rel: "preload", as: "style", href: href }) : null, _jsx("link", { rel: "stylesheet", href: href })] }));
7
10
  }
@@ -1,4 +1,4 @@
1
- export { CDNImage } from "../react/CDNImage.js";
1
+ export { CDNImage } from "./CDNImage.js";
2
2
  export { CDNAudio } from "../react/CDNAudio.js";
3
3
  export { CDNVideo } from "../react/CDNVideo.js";
4
4
  export { Script } from "./Script.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EACH,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,QAAQ,GACX,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EACH,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,QAAQ,GACX,MAAM,UAAU,CAAC"}
@@ -1,4 +1,4 @@
1
- export { CDNImage } from "../react/CDNImage.js";
1
+ export { CDNImage } from "./CDNImage.js";
2
2
  export { CDNAudio } from "../react/CDNAudio.js";
3
3
  export { CDNVideo } from "../react/CDNVideo.js";
4
4
  export { Script } from "./Script.js";
@@ -8,7 +8,10 @@ export interface CDNMediaSource<TAssetPath extends string, TVariant extends stri
8
8
  export type CDNAudioProps<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap> = {
9
9
  assetPath: LoaderAudioPath<TAssets>;
10
10
  variantSlug?: LoaderVariantSlug<TAssets>;
11
+ isCritical?: boolean;
12
+ controls?: boolean;
13
+ loop?: boolean;
11
14
  sources?: Array<CDNMediaSource<LoaderAudioPath<TAssets>, LoaderVariantSlug<TAssets>>>;
12
- } & Omit<React.AudioHTMLAttributes<HTMLAudioElement>, "src">;
13
- export declare function CDNAudio<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>({ assetPath, variantSlug, sources, children, ...props }: CDNAudioProps<TAssets>): import("react/jsx-runtime").JSX.Element;
15
+ } & Omit<React.AudioHTMLAttributes<HTMLAudioElement>, "controls" | "loop" | "preload" | "src">;
16
+ export declare function CDNAudio<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>({ assetPath, variantSlug, isCritical, sources, children, ...props }: CDNAudioProps<TAssets>): import("react/jsx-runtime").JSX.Element;
14
17
  //# sourceMappingURL=CDNAudio.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CDNAudio.d.ts","sourceRoot":"","sources":["../../src/react/CDNAudio.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEhH,MAAM,WAAW,cAAc,CAAC,UAAU,SAAS,MAAM,EAAE,QAAQ,SAAS,MAAM;IAC9E,SAAS,EAAE,UAAU,CAAC;IACtB,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,IAAI;IACrG,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,OAAO,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;CACzF,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,KAAK,CAAC,CAAC;AAE7D,wBAAgB,QAAQ,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAChG,EACI,SAAS,EACT,WAAW,EACX,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACX,EAAE,aAAa,CAAC,OAAO,CAAC,2CAa5B"}
1
+ {"version":3,"file":"CDNAudio.d.ts","sourceRoot":"","sources":["../../src/react/CDNAudio.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEhH,MAAM,WAAW,cAAc,CAAC,UAAU,SAAS,MAAM,EAAE,QAAQ,SAAS,MAAM;IAC9E,SAAS,EAAE,UAAU,CAAC;IACtB,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,IAAI;IACrG,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;CACzF,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC;AAE/F,wBAAgB,QAAQ,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAChG,EACI,SAAS,EACT,WAAW,EACX,UAAkB,EAClB,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACX,EAAE,aAAa,CAAC,OAAO,CAAC,2CAiB5B"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { getMediaSnippetAttributes } from "../core/html-snippets.js";
2
3
  import { buildUrl } from "../core/utils.js";
3
- export function CDNAudio({ assetPath, variantSlug, sources, children, ...props }) {
4
- return (_jsxs("audio", { src: sources?.length ? undefined : buildUrl(assetPath, variantSlug), ...props, children: [sources?.map((source) => (_jsx("source", { src: buildUrl(source.assetPath, source.variantSlug), type: source.type }, `${source.assetPath}:${source.variantSlug || ""}:${source.type || ""}`))), children] }));
4
+ export function CDNAudio({ assetPath, variantSlug, isCritical = false, sources, children, ...props }) {
5
+ return (_jsxs("audio", { src: sources?.length ? undefined : buildUrl(assetPath, variantSlug), ...getMediaSnippetAttributes({ isCritical }), ...props, children: [sources?.map((source) => (_jsx("source", { src: buildUrl(source.assetPath, source.variantSlug), type: source.type }, `${source.assetPath}:${source.variantSlug || ""}:${source.type || ""}`))), children] }));
5
6
  }
@@ -4,8 +4,9 @@ export type CDNImageProps<TAssets extends Partial<LoaderAssetMap> | undefined =
4
4
  assetPath: LoaderImagePath<TAssets>;
5
5
  variantSlug?: LoaderVariantSlug<TAssets>;
6
6
  alt: string;
7
- responsive?: boolean;
8
- variants?: number[];
9
- } & Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src" | "srcSet">;
10
- export declare function CDNImage<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>({ assetPath, variantSlug, alt, responsive, variants, sizes, ...props }: CDNImageProps<TAssets>): import("react/jsx-runtime").JSX.Element;
7
+ isCritical?: boolean;
8
+ width?: number | string;
9
+ height?: number | string;
10
+ } & Omit<React.ImgHTMLAttributes<HTMLImageElement>, "alt" | "decoding" | "fetchPriority" | "height" | "loading" | "sizes" | "src" | "srcSet" | "width">;
11
+ export declare function CDNImage<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>({ assetPath, variantSlug, alt, isCritical, width, height, ...props }: CDNImageProps<TAssets>): import("react/jsx-runtime").JSX.Element;
11
12
  //# sourceMappingURL=CDNImage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CDNImage.d.ts","sourceRoot":"","sources":["../../src/react/CDNImage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAIhH,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,IAAI;IACrG,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,CAAC;AAEtE,wBAAgB,QAAQ,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAChG,EACI,SAAS,EACT,WAAW,EACX,GAAQ,EACR,UAAkB,EAClB,QAAQ,EACR,KAAK,EACL,GAAG,KAAK,EACX,EAAE,aAAa,CAAC,OAAO,CAAC,2CAsB5B"}
1
+ {"version":3,"file":"CDNImage.d.ts","sourceRoot":"","sources":["../../src/react/CDNImage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEhH,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,IAAI;IACrG,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B,GAAG,IAAI,CACJ,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EACzC,KAAK,GAAG,UAAU,GAAG,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CACrG,CAAC;AAEF,wBAAgB,QAAQ,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAChG,EACI,SAAS,EACT,WAAW,EACX,GAAQ,EACR,UAAkB,EAClB,KAAK,EACL,MAAM,EACN,GAAG,KAAK,EACX,EAAE,aAAa,CAAC,OAAO,CAAC,2CAuB5B"}
@@ -1,23 +1,28 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { tryGetConfig } from "../core/config.js";
3
+ import { getImageSnippetAttributes } from "../core/html-snippets.js";
3
4
  import { buildUrl } from "../core/utils.js";
4
- const defaultSizes = "(min-width: 1280px) 556px, (min-width: 1024px) calc((100vw - 232px) / 2), (min-width: 768px) calc(100vw - 128px), calc(100vw - 32px)";
5
- export function CDNImage({ assetPath, variantSlug, alt = '', responsive = false, variants, sizes, ...props }) {
5
+ export function CDNImage({ assetPath, variantSlug, alt = '', isCritical = false, width, height, ...props }) {
6
6
  const src = buildUrl(assetPath, variantSlug);
7
- if (!responsive) {
8
- return _jsx("img", { alt: alt, src: src, sizes: sizes, ...props });
9
- }
10
- const width = typeof props.width === "number" ? props.width : undefined;
11
- const availableVariants = resolveImageVariants(variants).filter((variantWidth) => width ? variantWidth <= width : true);
12
- const fallbackWidth = availableVariants[availableVariants.length - 1];
13
- return (_jsx("img", { alt: alt, src: fallbackWidth ? getVariantSrc(src, fallbackWidth) : src, srcSet: availableVariants.map((variantWidth) => `${getVariantSrc(src, variantWidth)} ${variantWidth}w`).join(", "), sizes: sizes || defaultSizes, ...props }));
7
+ const availableVariants = resolveImageVariants().filter((variantWidth) => typeof width === "number" ? variantWidth <= width : true);
8
+ const snippetAttributes = getImageSnippetAttributes({
9
+ src,
10
+ alt,
11
+ isCritical,
12
+ width,
13
+ height,
14
+ variants: availableVariants.map((variantWidth) => ({
15
+ width: variantWidth,
16
+ url: getVariantSrc(src, variantWidth),
17
+ })),
18
+ });
19
+ return (_jsx("img", { ...snippetAttributes, ...props }));
14
20
  }
15
- const resolveImageVariants = (variants) => {
16
- if (variants && variants.length > 0) {
17
- return variants;
18
- }
21
+ const resolveImageVariants = () => {
19
22
  const configVariants = Object.values(tryGetConfig()?.imageVariants || {});
20
- return configVariants.length > 0 ? configVariants : [320, 480, 640, 768, 960, 1200];
23
+ return configVariants
24
+ .filter((variantWidth) => Number.isFinite(variantWidth) && variantWidth > 0)
25
+ .sort((a, b) => a - b);
21
26
  };
22
27
  const getVariantSrc = (src, width) => {
23
28
  const extensionIndex = src.lastIndexOf(".");
@@ -6,7 +6,10 @@ export type CDNVideoProps<TAssets extends Partial<LoaderAssetMap> | undefined =
6
6
  variantSlug?: LoaderVariantSlug<TAssets>;
7
7
  posterAssetPath?: LoaderImagePath<TAssets>;
8
8
  posterVariantSlug?: LoaderVariantSlug<TAssets>;
9
+ isCritical?: boolean;
10
+ controls?: boolean;
11
+ loop?: boolean;
9
12
  sources?: Array<CDNMediaSource<LoaderVideoPath<TAssets>, LoaderVariantSlug<TAssets>>>;
10
- } & Omit<React.VideoHTMLAttributes<HTMLVideoElement>, "src" | "poster">;
11
- export declare function CDNVideo<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>({ assetPath, variantSlug, posterAssetPath, posterVariantSlug, sources, children, ...props }: CDNVideoProps<TAssets>): import("react/jsx-runtime").JSX.Element;
13
+ } & Omit<React.VideoHTMLAttributes<HTMLVideoElement>, "controls" | "loop" | "poster" | "preload" | "src">;
14
+ export declare function CDNVideo<TAssets extends Partial<LoaderAssetMap> | undefined = LoaderDefaultAssetMap>({ assetPath, variantSlug, posterAssetPath, posterVariantSlug, isCritical, sources, children, ...props }: CDNVideoProps<TAssets>): import("react/jsx-runtime").JSX.Element;
12
15
  //# sourceMappingURL=CDNVideo.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CDNVideo.d.ts","sourceRoot":"","sources":["../../src/react/CDNVideo.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAC,MAAM,kBAAkB,CAAC;AACjI,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,IAAI;IACrG,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,eAAe,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC3C,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;CACzF,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC,CAAC;AAExE,wBAAgB,QAAQ,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAChG,EACI,SAAS,EACT,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACX,EAAE,aAAa,CAAC,OAAO,CAAC,2CAiB5B"}
1
+ {"version":3,"file":"CDNVideo.d.ts","sourceRoot":"","sources":["../../src/react/CDNVideo.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAC,MAAM,kBAAkB,CAAC;AACjI,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,IAAI;IACrG,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,eAAe,CAAC,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IAC3C,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;CACzF,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,KAAK,CAAC,CAAC;AAE1G,wBAAgB,QAAQ,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,EAChG,EACI,SAAS,EACT,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,UAAkB,EAClB,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACX,EAAE,aAAa,CAAC,OAAO,CAAC,2CAkB5B"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { getMediaSnippetAttributes } from "../core/html-snippets.js";
2
3
  import { buildUrl } from "../core/utils.js";
3
- export function CDNVideo({ assetPath, variantSlug, posterAssetPath, posterVariantSlug, sources, children, ...props }) {
4
- return (_jsxs("video", { src: sources?.length ? undefined : buildUrl(assetPath, variantSlug), poster: posterAssetPath ? buildUrl(posterAssetPath, posterVariantSlug) : undefined, ...props, children: [sources?.map((source) => (_jsx("source", { src: buildUrl(source.assetPath, source.variantSlug), type: source.type }, `${source.assetPath}:${source.variantSlug || ""}:${source.type || ""}`))), children] }));
4
+ export function CDNVideo({ assetPath, variantSlug, posterAssetPath, posterVariantSlug, isCritical = false, sources, children, ...props }) {
5
+ return (_jsxs("video", { src: sources?.length ? undefined : buildUrl(assetPath, variantSlug), poster: posterAssetPath ? buildUrl(posterAssetPath, posterVariantSlug) : undefined, ...getMediaSnippetAttributes({ isCritical }), ...props, children: [sources?.map((source) => (_jsx("source", { src: buildUrl(source.assetPath, source.variantSlug), type: source.type }, `${source.assetPath}:${source.variantSlug || ""}:${source.type || ""}`))), children] }));
5
6
  }
@@ -4,7 +4,10 @@ export type CDNImageProps<TAssets extends Partial<LoaderAssetMap> | undefined =
4
4
  assetPath: LoaderImagePath<TAssets>;
5
5
  variantSlug?: LoaderVariantSlug<TAssets>;
6
6
  alt?: string;
7
- } & Omit<ImgHTMLAttributes, "src">;
7
+ isCritical?: boolean;
8
+ width?: number | string;
9
+ height?: number | string;
10
+ } & Omit<ImgHTMLAttributes, "alt" | "decoding" | "fetchpriority" | "height" | "loading" | "sizes" | "src" | "srcset" | "width">;
8
11
  export declare const CDNImage: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
9
12
  assetPath: {
10
13
  type: PropType<string>;
@@ -18,6 +21,18 @@ export declare const CDNImage: import("vue").DefineComponent<import("vue").Extra
18
21
  type: StringConstructor;
19
22
  default: string;
20
23
  };
24
+ isCritical: {
25
+ type: BooleanConstructor;
26
+ default: boolean;
27
+ };
28
+ width: {
29
+ type: PropType<number | string | undefined>;
30
+ required: false;
31
+ };
32
+ height: {
33
+ type: PropType<number | string | undefined>;
34
+ required: false;
35
+ };
21
36
  }>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
22
37
  [key: string]: any;
23
38
  }>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
@@ -33,7 +48,20 @@ export declare const CDNImage: import("vue").DefineComponent<import("vue").Extra
33
48
  type: StringConstructor;
34
49
  default: string;
35
50
  };
51
+ isCritical: {
52
+ type: BooleanConstructor;
53
+ default: boolean;
54
+ };
55
+ width: {
56
+ type: PropType<number | string | undefined>;
57
+ required: false;
58
+ };
59
+ height: {
60
+ type: PropType<number | string | undefined>;
61
+ required: false;
62
+ };
36
63
  }>> & Readonly<{}>, {
37
64
  alt: string;
65
+ isCritical: boolean;
38
66
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
39
67
  //# sourceMappingURL=CDNImage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CDNImage.d.ts","sourceRoot":"","sources":["../../src/vue/CDNImage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAC,MAAM,KAAK,CAAC;AAE9E,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEhH,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,IAAI;IACrG,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;AAEnC,eAAO,MAAM,QAAQ;;cAIO,QAAQ,CAAC,MAAM,CAAC;;;;cAIhB,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC;;;;;;;;;;;cAJ5B,QAAQ,CAAC,MAAM,CAAC;;;;cAIhB,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC;;;;;;;;;4EAetD,CAAC"}
1
+ {"version":3,"file":"CDNImage.d.ts","sourceRoot":"","sources":["../../src/vue/CDNImage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,iBAAiB,EAAE,KAAK,QAAQ,EAAC,MAAM,KAAK,CAAC;AAI9E,OAAO,KAAK,EAAC,cAAc,EAAE,qBAAqB,EAAE,eAAe,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEhH,MAAM,MAAM,aAAa,CAAC,OAAO,SAAS,OAAO,CAAC,cAAc,CAAC,GAAG,SAAS,GAAG,qBAAqB,IAAI;IACrG,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B,GAAG,IAAI,CAAC,iBAAiB,EAAE,KAAK,GAAG,UAAU,GAAG,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC,CAAC;AAEhI,eAAO,MAAM,QAAQ;;cAIO,QAAQ,CAAC,MAAM,CAAC;;;;cAIhB,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC;;;;;;;;;;;;cAYlB,QAAQ,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;;;;cAIrC,QAAQ,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;;;;;;;cApB/C,QAAQ,CAAC,MAAM,CAAC;;;;cAIhB,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC;;;;;;;;;;;;cAYlB,QAAQ,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;;;;cAIrC,QAAQ,CAAC,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;;;;;;4EA4BzE,CAAC"}
@@ -1,4 +1,6 @@
1
1
  import { defineComponent, h } from "vue";
2
+ import { tryGetConfig } from "../core/config.js";
3
+ import { getImageSnippetAttributes } from "../core/html-snippets.js";
2
4
  import { buildUrl } from "../core/utils.js";
3
5
  export const CDNImage = defineComponent({
4
6
  name: "SmoothCDNImage",
@@ -14,13 +16,52 @@ export const CDNImage = defineComponent({
14
16
  alt: {
15
17
  type: String,
16
18
  default: ""
19
+ },
20
+ isCritical: {
21
+ type: Boolean,
22
+ default: false
23
+ },
24
+ width: {
25
+ type: [Number, String],
26
+ required: false
27
+ },
28
+ height: {
29
+ type: [Number, String],
30
+ required: false
17
31
  }
18
32
  },
19
33
  setup(props, { attrs }) {
20
- return () => h("img", {
21
- ...attrs,
22
- alt: props.alt,
23
- src: buildUrl(props.assetPath, props.variantSlug)
24
- });
34
+ return () => {
35
+ const src = buildUrl(props.assetPath, props.variantSlug);
36
+ const availableVariants = resolveImageVariants().filter((variantWidth) => typeof props.width === "number" ? variantWidth <= props.width : true);
37
+ const snippetAttributes = getImageSnippetAttributes({
38
+ src,
39
+ alt: props.alt,
40
+ isCritical: props.isCritical,
41
+ width: props.width,
42
+ height: props.height,
43
+ variants: availableVariants.map((variantWidth) => ({
44
+ width: variantWidth,
45
+ url: getVariantSrc(src, variantWidth),
46
+ })),
47
+ });
48
+ return h("img", {
49
+ ...snippetAttributes,
50
+ ...attrs,
51
+ });
52
+ };
25
53
  }
26
54
  });
55
+ const resolveImageVariants = () => {
56
+ const configVariants = Object.values(tryGetConfig()?.imageVariants || {});
57
+ return configVariants
58
+ .filter((variantWidth) => Number.isFinite(variantWidth) && variantWidth > 0)
59
+ .sort((a, b) => a - b);
60
+ };
61
+ const getVariantSrc = (src, width) => {
62
+ const extensionIndex = src.lastIndexOf(".");
63
+ if (extensionIndex === -1) {
64
+ return src;
65
+ }
66
+ return `${src.slice(0, extensionIndex)}_${width}${src.slice(extensionIndex)}`;
67
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smoothcdn/loader",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Smooth CDN framework-aware asset loader",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
package/readme.md CHANGED
@@ -12,6 +12,8 @@ It includes:
12
12
  - Astro, SvelteKit and Remix entrypoints,
13
13
  - TypeScript asset typing generated from `.scdn.json`.
14
14
 
15
+ Image, media, script and style components share the same loading semantics as Smooth CDN HTML snippets. Use `isCritical` for assets needed above the fold; the loader then applies the correct loading attributes. Image responsiveness is driven only by `imageVariants` in `.scdn.json`.
16
+
15
17
  ## Installation
16
18
 
17
19
  ```bash
@@ -158,18 +160,18 @@ export function DataBlock() {
158
160
  ## Next.js
159
161
 
160
162
  ```tsx
161
- import { Script, Style } from "@smoothcdn/loader/next";
162
- import { CDNAudio, CDNImage, CDNVideo } from "@smoothcdn/loader/react";
163
+ import { CDNAudio, CDNImage, CDNVideo, Script, Style } from "@smoothcdn/loader/next";
163
164
 
164
165
  export default function Page() {
165
166
  return (
166
167
  <>
167
- <Style assetPath="/public/app.css" />
168
- <Script assetPath="/public/app.js" />
168
+ <Style assetPath="/public/app.css" isCritical />
169
+ <Script assetPath="/public/app.js" isCritical />
169
170
 
170
171
  <CDNImage
171
172
  assetPath="/public/logo.svg"
172
173
  alt="Smooth CDN"
174
+ isCritical
173
175
  width={80}
174
176
  height={80}
175
177
  />
@@ -182,6 +184,7 @@ export default function Page() {
182
184
  <CDNVideo
183
185
  assetPath="/public/demo.mp4"
184
186
  posterAssetPath="/public/demo-poster.jpg"
187
+ isCritical
185
188
  controls
186
189
  width={1280}
187
190
  height={720}
@@ -329,7 +332,9 @@ const loader = createLoader();
329
332
  loader.image("/public/logo.png", "640");
330
333
  ```
331
334
 
332
- For responsive images, use the package component with `responsive`. It builds `srcSet` from `imageVariants` in `.scdn.json` unless you pass `variants` explicitly.
335
+ When `.scdn.json` contains `imageVariants`, image components automatically build `srcSet` from those configured widths. When `imageVariants` is not configured, the same component renders a single CDN `src`.
336
+
337
+ `isCritical` controls loading behavior. Critical images get `fetchpriority="high"` and synchronous decoding. Non-critical images get `loading="lazy"` and async decoding.
333
338
 
334
339
  ```tsx
335
340
  import { CDNImage } from "@smoothcdn/loader/react";
@@ -337,12 +342,11 @@ import { CDNImage } from "@smoothcdn/loader/react";
337
342
  export function HeroImage() {
338
343
  return (
339
344
  <CDNImage
340
- responsive
341
345
  assetPath="/public/hero.png"
342
346
  alt="Hero"
347
+ isCritical
343
348
  width={1536}
344
349
  height={1024}
345
- sizes="(min-width: 1024px) 50vw, 100vw"
346
350
  />
347
351
  );
348
352
  }