@page-speed/img 0.4.5 → 0.4.7
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 +1 -1
- package/README.md +163 -36
- package/dist/browser/page-speed-img.umd.cjs +1 -1
- package/dist/browser/page-speed-img.umd.js +1 -1
- package/dist/browser/page-speed-img.umd.js.map +1 -1
- package/dist/core/Img.cjs +54 -53
- package/dist/core/Img.d.ts +4 -0
- package/dist/core/Img.js +54 -53
- package/dist/core/OptixFlowConfig.cjs +30 -0
- package/dist/core/OptixFlowConfig.d.ts +37 -0
- package/dist/core/OptixFlowConfig.js +30 -0
- package/dist/core/index.cjs +2 -1
- package/dist/core/index.d.ts +4 -1
- package/dist/core/index.js +2 -1
- package/dist/core/useImgDebugLog.cjs +46 -0
- package/dist/core/useImgDebugLog.d.ts +20 -0
- package/dist/core/useImgDebugLog.js +46 -0
- package/dist/index.cjs +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/package.json +5 -4
- package/dist/browser/opensite-img.umd.cjs +0 -2
- package/dist/browser/opensite-img.umd.js +0 -2
- package/dist/browser/opensite-img.umd.js.map +0 -1
- package/dist/types.cjs +0 -1
- package/dist/types.d.ts +0 -6
- package/dist/types.js +0 -1
- package/dist/utils/api.cjs +0 -94
- package/dist/utils/api.d.ts +0 -11
- package/dist/utils/api.js +0 -94
- package/dist/utils/cache.cjs +0 -12
- package/dist/utils/cache.d.ts +0 -3
- package/dist/utils/cache.js +0 -12
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
BSD 3-Clause License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2026, OpenSite AI. All rights reserved.
|
|
4
4
|
|
|
5
5
|
Redistribution and use in source and binary forms, with or without
|
|
6
6
|
modification, are permitted provided that the following conditions are met:
|
package/README.md
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
|
-

|
|
2
|
-
|
|
3
|
-
---
|
|
4
|
-
|
|
5
1
|
# ⚡ @page-speed/img
|
|
6
|
-
|
|
7
|
-
**Performance-optimized React Image component**
|
|
8
2
|
|
|
9
|
-
Drop-in Image implementation of [web.dev](https://web.dev) best practices with zero configuration. Also a great alternative to [next/image](https://nextjs.org/docs/api-reference/next/image) for non-Next.js projects that still need the automated image optimization tools that the Next `Image` component provides.
|
|
3
|
+
## Performance-optimized React Image component - Drop-in Image implementation of [web.dev](https://web.dev) best practices with zero configuration. Also a great alternative to [next/image](https://nextjs.org/docs/api-reference/next/image) for non-Next.js projects that still need the automated image optimization tools that the Next `Image` component provides. Utilized throughout the [OpenSite Semantic UI Platform](https://opensite.ai).
|
|
4
|
+
|
|
5
|
+

|
|
10
6
|
|
|
11
7
|
[](https://www.npmjs.com/package/@page-speed/hooks)
|
|
12
8
|
[](https://www.npmjs.com/package/@page-speed/hooks)
|
|
13
9
|
[](./LICENSE)
|
|
14
10
|
[](./tsconfig.json)
|
|
15
|
-
[](#tree-shaking)
|
|
16
11
|
|
|
17
|
-
[Documentation](#documentation) · [Quick Start](#quick-start) · [
|
|
12
|
+
[Documentation](#documentation) · [Quick Start](#quick-start) · [Global Defaults](#setting-global-defaults) · [Examples](#examples) · [Contributing](./CONTRIBUTING.md)
|
|
18
13
|
|
|
19
14
|
---
|
|
20
15
|
|
|
21
16
|
## Documentation
|
|
22
17
|
|
|
23
|
-
`@page-speed/img` is a React-first, OptixFlow-enabled image component that ships Lighthouse-friendly markup by default. It uses `useOptimizedImage` from `@page-speed/hooks` to compute pixel-perfect `src`, DPR-aware `srcset`, and `sizes` on the client. Tree shaking keeps the bundle lean—only the media hook is pulled in.
|
|
18
|
+
`@page-speed/img` is a React-first, OptixFlow-enabled image component that ships Lighthouse-friendly markup by default. It uses `useOptimizedImage` from `@page-speed/hooks` to compute pixel-perfect `src`, DPR-aware `srcset`, and `sizes` on the client. Tree shaking keeps the bundle lean — only the media hook is pulled in.
|
|
24
19
|
|
|
25
20
|
### Installation
|
|
26
21
|
|
|
@@ -30,13 +25,103 @@ pnpm add @page-speed/img
|
|
|
30
25
|
|
|
31
26
|
Peer deps: `react` and `react-dom` (17+). For OptixFlow optimization, supply an API key.
|
|
32
27
|
|
|
28
|
+
---
|
|
29
|
+
|
|
33
30
|
### Usage (React / Next.js)
|
|
34
31
|
|
|
32
|
+
```tsx
|
|
33
|
+
import { Img } from "@page-speed/img";
|
|
34
|
+
|
|
35
|
+
export function HeroImage() {
|
|
36
|
+
return (
|
|
37
|
+
<Img
|
|
38
|
+
src="https://images.example.com/hero.jpg"
|
|
39
|
+
alt="Hero"
|
|
40
|
+
width={1280}
|
|
41
|
+
height={720}
|
|
42
|
+
eager
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
What you get automatically:
|
|
49
|
+
|
|
50
|
+
- Pixel-perfect primary `src` sized to the rendered element (Lighthouse "Properly size images" pass).
|
|
51
|
+
- DPR-aware `srcset` (1x/2x) for AVIF, WebP, and JPEG.
|
|
52
|
+
- Lazy loading via IntersectionObserver; set `eager` for above-the-fold images.
|
|
53
|
+
- Optional OptixFlow compression and format selection with a single prop.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
### Setting Global Defaults
|
|
58
|
+
|
|
59
|
+
When all or most images in your app share the same OptixFlow configuration, you can set it once globally instead of repeating `optixFlowConfig` on every `<Img />`.
|
|
60
|
+
|
|
61
|
+
#### ✅ Recommended: `<OptixFlowConfig />` component (SSR-safe)
|
|
62
|
+
|
|
63
|
+
The `OptixFlowConfig` component is the preferred approach for React and Next.js apps. It applies the default config inside a `useEffect`, which means it **never runs during server-side rendering** — making it safe to place in any server component tree without wrapping in a `"use client"` boundary at the call site.
|
|
64
|
+
|
|
65
|
+
**As a wrapper around your app:**
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
// app/layout.tsx (Next.js App Router) or src/App.tsx
|
|
69
|
+
import { OptixFlowConfig } from "@page-speed/img";
|
|
70
|
+
|
|
71
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
72
|
+
return (
|
|
73
|
+
<html lang="en">
|
|
74
|
+
<body>
|
|
75
|
+
<OptixFlowConfig config={{ apiKey: process.env.NEXT_PUBLIC_OPTIX_API_KEY!, compressionLevel: 80 }}>
|
|
76
|
+
{children}
|
|
77
|
+
</OptixFlowConfig>
|
|
78
|
+
</body>
|
|
79
|
+
</html>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Standalone (no children required):**
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
// Place anywhere in the tree; renders null, no visual output
|
|
88
|
+
import { OptixFlowConfig } from "@page-speed/img";
|
|
89
|
+
|
|
90
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
91
|
+
return (
|
|
92
|
+
<>
|
|
93
|
+
<OptixFlowConfig config={{ apiKey: process.env.NEXT_PUBLIC_OPTIX_API_KEY! }} />
|
|
94
|
+
{children}
|
|
95
|
+
</>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Individual `<Img />` components can always override the default with their own `optixFlowConfig` prop:
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
<Img
|
|
104
|
+
src="https://images.example.com/hero.jpg"
|
|
105
|
+
alt="Hero"
|
|
106
|
+
width={1280}
|
|
107
|
+
height={720}
|
|
108
|
+
// Overrides the global default for this image only
|
|
109
|
+
optixFlowConfig={{ renderedFileType: "jpeg", objectFit: "cover" }}
|
|
110
|
+
/>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Alternative: `setDefaultOptixFlowConfig()` function
|
|
114
|
+
|
|
115
|
+
For purely client-side apps, scripts, or imperative initialization (e.g. outside of React's render tree), the `setDefaultOptixFlowConfig` function is available. Call it once at app startup before any `<Img />` components mount.
|
|
116
|
+
|
|
35
117
|
```tsx
|
|
36
118
|
import { Img, setDefaultOptixFlowConfig } from "@page-speed/img";
|
|
37
119
|
|
|
38
|
-
//
|
|
39
|
-
setDefaultOptixFlowConfig({
|
|
120
|
+
// Call once, e.g. in main.tsx / index.tsx before rendering
|
|
121
|
+
setDefaultOptixFlowConfig({
|
|
122
|
+
apiKey: process.env.VITE_OPTIX_API_KEY!,
|
|
123
|
+
compressionLevel: 80,
|
|
124
|
+
});
|
|
40
125
|
|
|
41
126
|
export function HeroImage() {
|
|
42
127
|
return (
|
|
@@ -45,33 +130,22 @@ export function HeroImage() {
|
|
|
45
130
|
alt="Hero"
|
|
46
131
|
width={1280}
|
|
47
132
|
height={720}
|
|
48
|
-
// Per-image override (optional)
|
|
49
|
-
optixFlowConfig={{ renderedFileType: "jpeg", objectFit: "cover" }}
|
|
50
133
|
/>
|
|
51
134
|
);
|
|
52
135
|
}
|
|
53
136
|
```
|
|
54
137
|
|
|
55
|
-
|
|
56
|
-
- Pixel-perfect primary `src` sized to the rendered element (Lighthouse “Properly size images” pass).
|
|
57
|
-
- DPR-aware `srcset` (1x/2x) for AVIF/WebP/JPEG.
|
|
58
|
-
- Lazy loading with IntersectionObserver; set `eager` for above-the-fold.
|
|
59
|
-
- Optional OptixFlow compression/format selection with a single prop.
|
|
138
|
+
> **Note:** `setDefaultOptixFlowConfig` is not SSR-safe on its own. In server-rendered environments (Next.js, Remix, etc.) prefer the `<OptixFlowConfig />` component, which handles the client/server boundary automatically.
|
|
60
139
|
|
|
61
|
-
|
|
140
|
+
To clear or reset the global default at any point:
|
|
62
141
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
- `loading`, `decoding`: Defaults `lazy` / `async`. Set `eager` to force above-the-fold fetch.
|
|
67
|
-
- `sizes`: Override the auto-generated `sizes` from `useOptimizedImage`.
|
|
68
|
-
- `intersectionMargin`, `intersectionThreshold`: Tweak lazy-load observer.
|
|
69
|
-
- `optixFlowConfig`: `{ apiKey: string; compressionLevel?: number; renderedFileType?: 'avif' | 'webp' | 'jpeg' | 'png'; objectFit?: 'cover' | 'contain' | 'fill'; }`.
|
|
142
|
+
```ts
|
|
143
|
+
setDefaultOptixFlowConfig(null);
|
|
144
|
+
```
|
|
70
145
|
|
|
71
|
-
|
|
146
|
+
#### Browser global (UMD / inline script)
|
|
72
147
|
|
|
73
|
-
|
|
74
|
-
- Browser global (UMD/inline):
|
|
148
|
+
For vanilla HTML pages or CMS integrations using the UMD build, set the global before the component renders:
|
|
75
149
|
|
|
76
150
|
```html
|
|
77
151
|
<script>
|
|
@@ -87,12 +161,52 @@ What you get:
|
|
|
87
161
|
|
|
88
162
|
`window.OpensiteImgDefaults` and `window.PAGE_SPEED_IMG_DEFAULTS` are also honored for backward compatibility.
|
|
89
163
|
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### `<Img />` Props
|
|
167
|
+
|
|
168
|
+
| Prop | Type | Default | Description |
|
|
169
|
+
|---|---|---|---|
|
|
170
|
+
| `src` | `string` | — | **(Required)** Image URL. |
|
|
171
|
+
| `alt` | `string` | — | Alt text (passed through to `<img>`). |
|
|
172
|
+
| `width` | `number \| string` | — | Hint for sizing and CLS prevention. |
|
|
173
|
+
| `height` | `number \| string` | — | Hint for sizing and CLS prevention. |
|
|
174
|
+
| `eager` | `boolean` | `false` | Force eager loading (above-the-fold). Equivalent to `loading="eager"`. |
|
|
175
|
+
| `loading` | `"lazy" \| "eager"` | `"lazy"` | Native loading attribute. `eager` prop takes precedence. |
|
|
176
|
+
| `decoding` | `"async" \| "sync" \| "auto"` | `"async"` | Native decoding attribute. |
|
|
177
|
+
| `fetchPriority` | `"high" \| "low" \| "auto"` | `"high"` when eager | Native fetch priority. |
|
|
178
|
+
| `sizes` | `string` | auto-computed | Override the `sizes` attribute generated by `useOptimizedImage`. |
|
|
179
|
+
| `intersectionMargin` | `string` | `"200px"` | Root margin for the lazy-load IntersectionObserver. |
|
|
180
|
+
| `intersectionThreshold` | `number` | `0.1` | Threshold for the lazy-load IntersectionObserver. |
|
|
181
|
+
| `optixFlowConfig` | `OptixFlowConfig` | global default | Per-image OptixFlow config. Overrides any global default. |
|
|
182
|
+
| `useDebugMode` | `boolean` | `false` | Log image request details to the console. |
|
|
183
|
+
|
|
184
|
+
**`optixFlowConfig` shape:**
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
{
|
|
188
|
+
apiKey: string;
|
|
189
|
+
compressionLevel?: number; // 1–100
|
|
190
|
+
renderedFileType?: "avif" | "webp" | "jpeg" | "png";
|
|
191
|
+
objectFit?: "cover" | "contain" | "fill";
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### `<OptixFlowConfig />` Props
|
|
196
|
+
|
|
197
|
+
| Prop | Type | Description |
|
|
198
|
+
|---|---|---|
|
|
199
|
+
| `config` | `OptixFlowConfig` | The OptixFlow configuration to apply as the global default. |
|
|
200
|
+
| `children` | `React.ReactNode` | Optional. When provided, children are rendered; otherwise the component renders `null`. |
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
90
204
|
### UMD usage
|
|
91
205
|
|
|
92
206
|
```html
|
|
93
207
|
<script src="https://unpkg.com/react@18/umd/react.production.min.js" crossorigin></script>
|
|
94
208
|
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js" crossorigin></script>
|
|
95
|
-
<script src="https://cdn.jsdelivr.net/npm/@page-speed/img@0.
|
|
209
|
+
<script src="https://cdn.jsdelivr.net/npm/@page-speed/img@0.4.7/dist/browser/page-speed-img.umd.js" crossorigin></script>
|
|
96
210
|
|
|
97
211
|
<div id="app"></div>
|
|
98
212
|
<script>
|
|
@@ -109,14 +223,21 @@ What you get:
|
|
|
109
223
|
</script>
|
|
110
224
|
```
|
|
111
225
|
|
|
226
|
+
---
|
|
227
|
+
|
|
112
228
|
### SSR considerations
|
|
113
229
|
|
|
114
|
-
-
|
|
115
|
-
-
|
|
230
|
+
- `<Img />` is marked `"use client"`. In Next.js App Router, place it inside a Client Component or a shared layout where the `"use client"` boundary is already established.
|
|
231
|
+
- `<OptixFlowConfig />` is also marked `"use client"` and applies its config exclusively via `useEffect`, so it is safe to import and render from a Server Component tree — the config call never executes on the server.
|
|
232
|
+
- Guards exist for `window` and `IntersectionObserver` throughout the library, so modules can be imported safely in SSR environments without crashing.
|
|
233
|
+
|
|
234
|
+
---
|
|
116
235
|
|
|
117
236
|
### Tree shaking
|
|
118
237
|
|
|
119
|
-
`@page-speed/img` only imports `useOptimizedImage` from `@page-speed/hooks`, keeping bundles small. Both ESM and CJS builds are emitted; UMD
|
|
238
|
+
`@page-speed/img` only imports `useOptimizedImage` from `@page-speed/hooks`, keeping bundles small. Both ESM and CJS builds are emitted; the UMD build externalizes React and ReactDOM.
|
|
239
|
+
|
|
240
|
+
---
|
|
120
241
|
|
|
121
242
|
### Testing
|
|
122
243
|
|
|
@@ -124,12 +245,18 @@ What you get:
|
|
|
124
245
|
pnpm test
|
|
125
246
|
```
|
|
126
247
|
|
|
248
|
+
---
|
|
249
|
+
|
|
127
250
|
### Roadmap
|
|
128
251
|
|
|
129
|
-
- Add
|
|
252
|
+
- Add Storybook examples for common layouts (hero, gallery, card).
|
|
130
253
|
|
|
131
254
|
---
|
|
132
255
|
|
|
133
256
|
## Contributing
|
|
134
257
|
|
|
135
|
-
PRs welcome. Please run `pnpm test` before submitting.
|
|
258
|
+
PRs welcome. Please run `pnpm test` before submitting. See [CONTRIBUTING.md](./CONTRIBUTING.md) for details.
|
|
259
|
+
|
|
260
|
+
## License
|
|
261
|
+
|
|
262
|
+
BSD 3-Clause
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).PageSpeedImg={},e.React)}(this,function(e,t){"use strict";
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).PageSpeedImg={},e.React)}(this,function(e,t){"use strict";function i(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const i in e)if("default"!==i){const n=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,n.get?n:{enumerable:!0,get:()=>e[i]})}return t.default=e,Object.freeze(t)}const n=i(t);var r=[1,2],o="undefined"!=typeof window?t.useLayoutEffect:t.useEffect;const s="dt:media-selected",u=()=>{};let l=0,c=!1;function d(e){e&&e.querySelectorAll("source").forEach(e=>{const t=e.getAttribute("srcset");t&&(e.setAttribute("data-srcset",t),e.removeAttribute("srcset"),requestAnimationFrame(()=>{e.setAttribute("srcset",t)}))})}const a="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";let f;const g=e=>e??f??(()=>{var e,t,i;if("undefined"==typeof globalThis)return;const n=globalThis;return(null==(e=n.PageSpeedImgDefaults)?void 0:e.optixFlowConfig)||(null==(t=n.OpensiteImgDefaults)?void 0:t.optixFlowConfig)||(null==(i=n.PAGE_SPEED_IMG_DEFAULTS)?void 0:i.optixFlowConfig)})(),h=e=>{f=e??void 0},p=e=>{if(""!==e&&null!=e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"==typeof e){const t=Number(e);if(Number.isFinite(t))return t}}},w=({sizes:e,loading:i,decoding:n,alt:f,title:h,src:w,eager:m,width:v,height:b,fetchPriority:y,intersectionMargin:E,intersectionThreshold:M,optixFlowConfig:A,useDebugMode:S,forwardedRef:I,...j})=>{const L=t.useRef(null),F=t.useRef(null);var P;P=F,t.useEffect(()=>{const e=P.current;e&&(e instanceof HTMLPictureElement?d(e):e.parentElement instanceof HTMLPictureElement&&d(e.parentElement))},[P]),t.useEffect(()=>{if("undefined"!=typeof window)return c||(window.addEventListener(s,u),c=!0),l+=1,()=>{l-=1,l<=0&&c&&(window.removeEventListener(s,u),c=!1)}},[]);const x=t.useMemo(()=>"string"==typeof w?w.trim():"",[w]),O=t.useMemo(()=>p(v),[v]),z=t.useMemo(()=>p(b),[b]),V=t.useMemo(()=>g(A),[A]),T=t.useMemo(()=>m??"eager"===i,[m,i]),C=t.useMemo(()=>({src:x,eager:T,width:O,height:z,rootMargin:E??"200px",threshold:M??.1,optixFlowConfig:V}),[x,T,O,z,E,M,V]),{ref:R,src:D,srcset:N,sizes:q,loading:_,isInView:k,size:H}=function(e){const{src:i,eager:n=!1,threshold:s=.1,rootMargin:u="50px",width:l,height:c,optixFlowConfig:d}=e,a=t.useMemo(()=>null==d?void 0:d.apiKey,[null==d?void 0:d.apiKey]),f=t.useMemo(()=>!!a,[a]),[g,h]=t.useState({isLoaded:!1,isInView:!1}),[p,w]=t.useState({width:0,height:0}),m=t.useRef(null),v=t.useRef(null),b=t.useMemo(()=>({width:l??p.width,height:c??p.height}),[l,c,p.width,p.height]);o(()=>{if(!m.current)return;if(void 0!==l&&void 0!==c)return;const e=()=>{const e=m.current;if(!e)return;const t=l??(Math.round(e.clientWidth)||e.naturalWidth||0),i=c??(Math.round(e.clientHeight)||e.naturalHeight||0);(t>0||i>0)&&w(e=>e.width!==t||e.height!==i?{width:t,height:i}:e)};m.current.clientWidth>0&&e();const t=m.current;t.addEventListener("load",e);let i=null;return"undefined"!=typeof ResizeObserver&&(i=new ResizeObserver(()=>{e()}),i.observe(t)),()=>{t.removeEventListener("load",e),null==i||i.disconnect()}},[l,c]);const y=t.useCallback((e,t,n)=>{if(!f)return i;if(!e||!t)return i;const r=new URLSearchParams;return r.set("url",i),r.set("fit",String((null==d?void 0:d.objectFit)??"cover")),r.set("w",String(e)),r.set("h",String(t)),r.set("q",String((null==d?void 0:d.compressionLevel)??75)),r.set("f",n),r.set("apiKey",a),`https://octane.cdn.ing/api/v1/images/transform?${r.toString()}`},[f,i,null==d?void 0:d.compressionLevel,a,null==d?void 0:d.objectFit]),E=t.useCallback((e,t,i)=>f&&0!==e&&0!==t?r.map(n=>{const r=Math.round(e*n),o=Math.round(t*n);return`${y(r,o,i)} ${n}x`}).join(", "):"",[f,y]),M=t.useMemo(()=>{const e=b.width>0&&b.height>0;if(!f||!e)return i;const t=(null==d?void 0:d.renderedFileType)??"jpeg";return y(b.width,b.height,t)},[f,i,b.width,b.height,null==d?void 0:d.renderedFileType,null==d?void 0:d.compressionLevel,null==d?void 0:d.objectFit,y]),A=t.useMemo(()=>({avif:E(b.width,b.height,"avif"),webp:E(b.width,b.height,"webp"),jpeg:E(b.width,b.height,"jpeg")}),[b.width,b.height,E]),S=t.useMemo(()=>0===b.width?"":`${b.width}px`,[b.width]);return t.useEffect(()=>{if("undefined"!=typeof window&&m.current){if(!n)return v.current=new IntersectionObserver(([e])=>{var t;e.isIntersecting&&(h(e=>({...e,isInView:!0})),null==(t=v.current)||t.disconnect())},{threshold:s,rootMargin:u}),v.current.observe(m.current),()=>{var e;null==(e=v.current)||e.disconnect()};h({isLoaded:!1,isInView:!0})}},[n,s,u]),t.useEffect(()=>{if(!m.current)return;const e=()=>{h(e=>({...e,isLoaded:!0}))},t=m.current;if(!t.complete)return t.addEventListener("load",e),()=>t.removeEventListener("load",e);e()},[g.isInView]),{ref:t.useCallback(e=>{m.current=e},[]),src:g.isInView||n?M:i,srcset:g.isInView||n?A:{avif:"",webp:"",jpeg:""},sizes:g.isInView||n?S:"",isLoaded:g.isLoaded,isInView:g.isInView,loading:n?"eager":"lazy",size:b}}(C),$=((e,i,n)=>t.useCallback(t=>{e(t),n.current=t,"function"==typeof i?i(t):i&&"object"==typeof i&&(i.current=t)},[e,i,n]))(R,I,L),B=t.useMemo(()=>e??(q||void 0),[e,q]),G=t.useMemo(()=>i??_??"lazy",[i,_]),K=t.useMemo(()=>n??"async",[n]),U=t.useMemo(()=>y??(T?"high":void 0),[y,T]),W=t.useMemo(()=>Boolean(N.avif||N.webp||N.jpeg),[N.avif,N.webp,N.jpeg]),Q=t.useMemo(()=>D||x||a,[D,x]),J=t.useMemo(()=>!W||N.avif||N.webp?"":N.jpeg,[W,N.avif,N.webp,N.jpeg]),X=t.useMemo(()=>O??(H.width||void 0),[O,null==H?void 0:H.width]),Y=t.useMemo(()=>z??(H.height||void 0),[z,null==H?void 0:H.height]);return function({enabled:e,eagerLoad:i,isInView:n,imgSrc:r,transparentPixel:o,srcset:s,sizesAttr:u}){const l=t.useRef(null);t.useEffect(()=>{if(!e)return;if("undefined"==typeof window)return;if(!i&&!n)return;if(!r||r===o)return;const t=[r,s.avif,s.webp,s.jpeg,u??""].join("|");l.current!==t&&(l.current=t,"undefined"!=typeof console&&console.info&&console.info("[PageSpeedImg] image request",{src:r,srcset:s,sizes:u}))},[e,i,r,n,u,s.avif,s.webp,s.jpeg,o])}({enabled:S??!1,eagerLoad:T,isInView:k,imgSrc:Q,transparentPixel:a,srcset:N,sizesAttr:B}),W?t.createElement("picture",{ref:F},N.avif?t.createElement("source",{type:"image/avif",srcSet:N.avif,sizes:B}):null,N.webp?t.createElement("source",{type:"image/webp",srcSet:N.webp,sizes:B}):null,t.createElement("img",{ref:$,src:Q,srcSet:J||void 0,sizes:J?B:void 0,loading:G,decoding:K,fetchPriority:U,alt:f,title:h,width:X,height:Y,...j})):t.createElement("img",{ref:$,src:Q,loading:G,decoding:K,fetchPriority:U,alt:f,title:h,width:X,height:Y,...j})},m=t.forwardRef(function(e,i){return"string"==typeof e.src&&e.src.trim().length>0?t.createElement(w,{...e,forwardedRef:i}):("undefined"!=typeof console&&console.warn&&console.warn("<Img /> requires src. No src provided, rendering null."),null)}),v=t.memo(m);v.displayName="PageSpeedImg";const b="undefined"!=typeof globalThis?globalThis:void 0;if(b)if(b.process){const e=b.process.env??(b.process.env={});void 0===e.NODE_ENV&&(e.NODE_ENV="production")}else b.process={env:{NODE_ENV:"production"}};e.Img=v,e.OptixFlowConfig=function({config:e,children:t}){return n.useEffect(()=>{h(e??null)},[e]),t?n.createElement(n.Fragment,null,t):null},e.setDefaultOptixFlowConfig=h,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
|
|
2
2
|
//# sourceMappingURL=page-speed-img.umd.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).PageSpeedImg={},e.React)}(this,function(e,t){"use strict";
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("react")):"function"==typeof define&&define.amd?define(["exports","react"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).PageSpeedImg={},e.React)}(this,function(e,t){"use strict";function i(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e)for(const i in e)if("default"!==i){const n=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,n.get?n:{enumerable:!0,get:()=>e[i]})}return t.default=e,Object.freeze(t)}const n=i(t);var r=[1,2],o="undefined"!=typeof window?t.useLayoutEffect:t.useEffect;const s="dt:media-selected",u=()=>{};let l=0,c=!1;function d(e){e&&e.querySelectorAll("source").forEach(e=>{const t=e.getAttribute("srcset");t&&(e.setAttribute("data-srcset",t),e.removeAttribute("srcset"),requestAnimationFrame(()=>{e.setAttribute("srcset",t)}))})}const a="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";let f;const g=e=>e??f??(()=>{var e,t,i;if("undefined"==typeof globalThis)return;const n=globalThis;return(null==(e=n.PageSpeedImgDefaults)?void 0:e.optixFlowConfig)||(null==(t=n.OpensiteImgDefaults)?void 0:t.optixFlowConfig)||(null==(i=n.PAGE_SPEED_IMG_DEFAULTS)?void 0:i.optixFlowConfig)})(),h=e=>{f=e??void 0},p=e=>{if(""!==e&&null!=e){if("number"==typeof e&&Number.isFinite(e))return e;if("string"==typeof e){const t=Number(e);if(Number.isFinite(t))return t}}},w=({sizes:e,loading:i,decoding:n,alt:f,title:h,src:w,eager:m,width:v,height:b,fetchPriority:y,intersectionMargin:E,intersectionThreshold:M,optixFlowConfig:A,useDebugMode:S,forwardedRef:I,...j})=>{const L=t.useRef(null),F=t.useRef(null);var P;P=F,t.useEffect(()=>{const e=P.current;e&&(e instanceof HTMLPictureElement?d(e):e.parentElement instanceof HTMLPictureElement&&d(e.parentElement))},[P]),t.useEffect(()=>{if("undefined"!=typeof window)return c||(window.addEventListener(s,u),c=!0),l+=1,()=>{l-=1,l<=0&&c&&(window.removeEventListener(s,u),c=!1)}},[]);const x=t.useMemo(()=>"string"==typeof w?w.trim():"",[w]),O=t.useMemo(()=>p(v),[v]),z=t.useMemo(()=>p(b),[b]),V=t.useMemo(()=>g(A),[A]),T=t.useMemo(()=>m??"eager"===i,[m,i]),C=t.useMemo(()=>({src:x,eager:T,width:O,height:z,rootMargin:E??"200px",threshold:M??.1,optixFlowConfig:V}),[x,T,O,z,E,M,V]),{ref:R,src:D,srcset:N,sizes:q,loading:_,isInView:k,size:H}=function(e){const{src:i,eager:n=!1,threshold:s=.1,rootMargin:u="50px",width:l,height:c,optixFlowConfig:d}=e,a=t.useMemo(()=>null==d?void 0:d.apiKey,[null==d?void 0:d.apiKey]),f=t.useMemo(()=>!!a,[a]),[g,h]=t.useState({isLoaded:!1,isInView:!1}),[p,w]=t.useState({width:0,height:0}),m=t.useRef(null),v=t.useRef(null),b=t.useMemo(()=>({width:l??p.width,height:c??p.height}),[l,c,p.width,p.height]);o(()=>{if(!m.current)return;if(void 0!==l&&void 0!==c)return;const e=()=>{const e=m.current;if(!e)return;const t=l??(Math.round(e.clientWidth)||e.naturalWidth||0),i=c??(Math.round(e.clientHeight)||e.naturalHeight||0);(t>0||i>0)&&w(e=>e.width!==t||e.height!==i?{width:t,height:i}:e)};m.current.clientWidth>0&&e();const t=m.current;t.addEventListener("load",e);let i=null;return"undefined"!=typeof ResizeObserver&&(i=new ResizeObserver(()=>{e()}),i.observe(t)),()=>{t.removeEventListener("load",e),null==i||i.disconnect()}},[l,c]);const y=t.useCallback((e,t,n)=>{if(!f)return i;if(!e||!t)return i;const r=new URLSearchParams;return r.set("url",i),r.set("fit",String((null==d?void 0:d.objectFit)??"cover")),r.set("w",String(e)),r.set("h",String(t)),r.set("q",String((null==d?void 0:d.compressionLevel)??75)),r.set("f",n),r.set("apiKey",a),`https://octane.cdn.ing/api/v1/images/transform?${r.toString()}`},[f,i,null==d?void 0:d.compressionLevel,a,null==d?void 0:d.objectFit]),E=t.useCallback((e,t,i)=>f&&0!==e&&0!==t?r.map(n=>{const r=Math.round(e*n),o=Math.round(t*n);return`${y(r,o,i)} ${n}x`}).join(", "):"",[f,y]),M=t.useMemo(()=>{const e=b.width>0&&b.height>0;if(!f||!e)return i;const t=(null==d?void 0:d.renderedFileType)??"jpeg";return y(b.width,b.height,t)},[f,i,b.width,b.height,null==d?void 0:d.renderedFileType,null==d?void 0:d.compressionLevel,null==d?void 0:d.objectFit,y]),A=t.useMemo(()=>({avif:E(b.width,b.height,"avif"),webp:E(b.width,b.height,"webp"),jpeg:E(b.width,b.height,"jpeg")}),[b.width,b.height,E]),S=t.useMemo(()=>0===b.width?"":`${b.width}px`,[b.width]);return t.useEffect(()=>{if("undefined"!=typeof window&&m.current){if(!n)return v.current=new IntersectionObserver(([e])=>{var t;e.isIntersecting&&(h(e=>({...e,isInView:!0})),null==(t=v.current)||t.disconnect())},{threshold:s,rootMargin:u}),v.current.observe(m.current),()=>{var e;null==(e=v.current)||e.disconnect()};h({isLoaded:!1,isInView:!0})}},[n,s,u]),t.useEffect(()=>{if(!m.current)return;const e=()=>{h(e=>({...e,isLoaded:!0}))},t=m.current;if(!t.complete)return t.addEventListener("load",e),()=>t.removeEventListener("load",e);e()},[g.isInView]),{ref:t.useCallback(e=>{m.current=e},[]),src:g.isInView||n?M:i,srcset:g.isInView||n?A:{avif:"",webp:"",jpeg:""},sizes:g.isInView||n?S:"",isLoaded:g.isLoaded,isInView:g.isInView,loading:n?"eager":"lazy",size:b}}(C),$=((e,i,n)=>t.useCallback(t=>{e(t),n.current=t,"function"==typeof i?i(t):i&&"object"==typeof i&&(i.current=t)},[e,i,n]))(R,I,L),B=t.useMemo(()=>e??(q||void 0),[e,q]),G=t.useMemo(()=>i??_??"lazy",[i,_]),K=t.useMemo(()=>n??"async",[n]),U=t.useMemo(()=>y??(T?"high":void 0),[y,T]),W=t.useMemo(()=>Boolean(N.avif||N.webp||N.jpeg),[N.avif,N.webp,N.jpeg]),Q=t.useMemo(()=>D||x||a,[D,x]),J=t.useMemo(()=>!W||N.avif||N.webp?"":N.jpeg,[W,N.avif,N.webp,N.jpeg]),X=t.useMemo(()=>O??(H.width||void 0),[O,null==H?void 0:H.width]),Y=t.useMemo(()=>z??(H.height||void 0),[z,null==H?void 0:H.height]);return function({enabled:e,eagerLoad:i,isInView:n,imgSrc:r,transparentPixel:o,srcset:s,sizesAttr:u}){const l=t.useRef(null);t.useEffect(()=>{if(!e)return;if("undefined"==typeof window)return;if(!i&&!n)return;if(!r||r===o)return;const t=[r,s.avif,s.webp,s.jpeg,u??""].join("|");l.current!==t&&(l.current=t,"undefined"!=typeof console&&console.info&&console.info("[PageSpeedImg] image request",{src:r,srcset:s,sizes:u}))},[e,i,r,n,u,s.avif,s.webp,s.jpeg,o])}({enabled:S??!1,eagerLoad:T,isInView:k,imgSrc:Q,transparentPixel:a,srcset:N,sizesAttr:B}),W?t.createElement("picture",{ref:F},N.avif?t.createElement("source",{type:"image/avif",srcSet:N.avif,sizes:B}):null,N.webp?t.createElement("source",{type:"image/webp",srcSet:N.webp,sizes:B}):null,t.createElement("img",{ref:$,src:Q,srcSet:J||void 0,sizes:J?B:void 0,loading:G,decoding:K,fetchPriority:U,alt:f,title:h,width:X,height:Y,...j})):t.createElement("img",{ref:$,src:Q,loading:G,decoding:K,fetchPriority:U,alt:f,title:h,width:X,height:Y,...j})},m=t.forwardRef(function(e,i){return"string"==typeof e.src&&e.src.trim().length>0?t.createElement(w,{...e,forwardedRef:i}):("undefined"!=typeof console&&console.warn&&console.warn("<Img /> requires src. No src provided, rendering null."),null)}),v=t.memo(m);v.displayName="PageSpeedImg";const b="undefined"!=typeof globalThis?globalThis:void 0;if(b)if(b.process){const e=b.process.env??(b.process.env={});void 0===e.NODE_ENV&&(e.NODE_ENV="production")}else b.process={env:{NODE_ENV:"production"}};e.Img=v,e.OptixFlowConfig=function({config:e,children:t}){return n.useEffect(()=>{h(e??null)},[e]),t?n.createElement(n.Fragment,null,t):null},e.setDefaultOptixFlowConfig=h,Object.defineProperty(e,Symbol.toStringTag,{value:"Module"})});
|
|
2
2
|
//# sourceMappingURL=page-speed-img.umd.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-speed-img.umd.js","sources":["../../node_modules/.pnpm/@page-speed+hooks@0.4.5_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/@page-speed/hooks/dist/chunk-ZTHTGLZO.js","../../src/core/useMediaSelectionEffect.ts","../../src/core/useResponsiveReset.ts","../../src/core/Img.tsx","../../src/index.ts"],"sourcesContent":["import { useMemo, useState, useRef, useLayoutEffect, useEffect, useCallback } from 'react';\n\nvar BASE_URL = \"https://octane.cdn.ing/api/v1/images/transform?\";\nvar DPR_MULTIPLIERS = [1, 2];\nvar useIsomorphicLayoutEffect = typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\nfunction useOptimizedImage(options) {\n const {\n src,\n eager = false,\n threshold = 0.1,\n rootMargin = \"50px\",\n width,\n height,\n optixFlowConfig\n } = options;\n const optixFlowApiKey = useMemo(() => {\n return optixFlowConfig?.apiKey;\n }, [optixFlowConfig?.apiKey]);\n const useOptixFlow = useMemo(() => {\n return optixFlowApiKey ? true : false;\n }, [optixFlowApiKey]);\n const [state, setState] = useState({\n isLoaded: false,\n isInView: false\n });\n const [measuredSize, setMeasuredSize] = useState({\n width: 0,\n height: 0\n });\n const imgRef = useRef(null);\n const observerRef = useRef(null);\n const size = useMemo(\n () => ({\n width: width ?? measuredSize.width,\n height: height ?? measuredSize.height\n }),\n [width, height, measuredSize.width, measuredSize.height]\n );\n useIsomorphicLayoutEffect(() => {\n if (!imgRef.current) return;\n if (width !== void 0 && height !== void 0) return;\n const calculateRenderedSize = () => {\n const img2 = imgRef.current;\n if (!img2) return;\n const renderedWidth = width ?? (Math.round(img2.clientWidth) || img2.naturalWidth || 0);\n const renderedHeight = height ?? (Math.round(img2.clientHeight) || img2.naturalHeight || 0);\n if (renderedWidth > 0 || renderedHeight > 0) {\n setMeasuredSize((prev) => {\n if (prev.width !== renderedWidth || prev.height !== renderedHeight) {\n return { width: renderedWidth, height: renderedHeight };\n }\n return prev;\n });\n }\n };\n if (imgRef.current.clientWidth > 0) {\n calculateRenderedSize();\n }\n const img = imgRef.current;\n img.addEventListener(\"load\", calculateRenderedSize);\n let resizeObserver = null;\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver = new ResizeObserver(() => {\n calculateRenderedSize();\n });\n resizeObserver.observe(img);\n }\n return () => {\n img.removeEventListener(\"load\", calculateRenderedSize);\n resizeObserver?.disconnect();\n };\n }, [width, height]);\n const buildOptixFlowUrl = useCallback(\n (imgWidth, imgHeight, format) => {\n if (!useOptixFlow) return src;\n if (!imgWidth || !imgHeight) return src;\n const params = new URLSearchParams();\n params.set(\"url\", src);\n params.set(\"fit\", String(optixFlowConfig?.objectFit ?? \"cover\"));\n params.set(\"w\", String(imgWidth));\n params.set(\"h\", String(imgHeight));\n params.set(\"q\", String(optixFlowConfig?.compressionLevel ?? 75));\n params.set(\"f\", format);\n params.set(\"apiKey\", optixFlowApiKey);\n return `${BASE_URL}${params.toString()}`;\n },\n [\n useOptixFlow,\n src,\n optixFlowConfig?.compressionLevel,\n optixFlowApiKey,\n optixFlowConfig?.objectFit\n ]\n );\n const generateSrcset = useCallback(\n (baseWidth, baseHeight, format) => {\n if (!useOptixFlow || baseWidth === 0 || baseHeight === 0) return \"\";\n return DPR_MULTIPLIERS.map((dpr) => {\n const scaledWidth = Math.round(baseWidth * dpr);\n const scaledHeight = Math.round(baseHeight * dpr);\n const url = buildOptixFlowUrl(scaledWidth, scaledHeight, format);\n return `${url} ${dpr}x`;\n }).join(\", \");\n },\n [useOptixFlow, buildOptixFlowUrl]\n );\n const primarySrc = useMemo(() => {\n const hasDimensions = size.width > 0 && size.height > 0;\n if (!useOptixFlow || !hasDimensions) return src;\n const fallbackFormat = optixFlowConfig?.renderedFileType ?? \"jpeg\";\n return buildOptixFlowUrl(size.width, size.height, fallbackFormat);\n }, [\n useOptixFlow,\n src,\n size.width,\n size.height,\n optixFlowConfig?.renderedFileType,\n optixFlowConfig?.compressionLevel,\n optixFlowConfig?.objectFit,\n buildOptixFlowUrl\n ]);\n const srcset = useMemo(() => {\n return {\n avif: generateSrcset(size.width, size.height, \"avif\"),\n webp: generateSrcset(size.width, size.height, \"webp\"),\n jpeg: generateSrcset(size.width, size.height, \"jpeg\")\n };\n }, [size.width, size.height, generateSrcset]);\n const sizes = useMemo(() => {\n if (size.width === 0) return \"\";\n return `${size.width}px`;\n }, [size.width]);\n useEffect(() => {\n if (typeof window === \"undefined\" || !imgRef.current) {\n return;\n }\n if (eager) {\n setState({ isLoaded: false, isInView: true });\n return;\n }\n observerRef.current = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setState((prev) => ({ ...prev, isInView: true }));\n observerRef.current?.disconnect();\n }\n },\n { threshold, rootMargin }\n );\n observerRef.current.observe(imgRef.current);\n return () => {\n observerRef.current?.disconnect();\n };\n }, [eager, threshold, rootMargin]);\n useEffect(() => {\n if (!imgRef.current) return;\n const handleLoad = () => {\n setState((prev) => ({ ...prev, isLoaded: true }));\n };\n const img = imgRef.current;\n if (img.complete) {\n handleLoad();\n } else {\n img.addEventListener(\"load\", handleLoad);\n return () => img.removeEventListener(\"load\", handleLoad);\n }\n }, [state.isInView]);\n const ref = useCallback((node) => {\n imgRef.current = node;\n }, []);\n const emptySrcset = { avif: \"\", webp: \"\", jpeg: \"\" };\n return {\n ref,\n // Primary src uses exact rendered dimensions for Lighthouse \"Properly size images\" compliance\n src: state.isInView || eager ? primarySrc : src,\n // Srcset with format variants and DPR multipliers for <picture> element\n srcset: state.isInView || eager ? srcset : emptySrcset,\n // Sizes attribute for responsive image selection\n sizes: state.isInView || eager ? sizes : \"\",\n isLoaded: state.isLoaded,\n isInView: state.isInView,\n loading: eager ? \"eager\" : \"lazy\",\n size\n };\n}\n\nexport { useOptimizedImage };\n//# sourceMappingURL=chunk-ZTHTGLZO.js.map\n//# sourceMappingURL=chunk-ZTHTGLZO.js.map","import { useEffect } from 'react';\n\nconst MEDIA_SELECTED_EVENT = 'dt:media-selected';\nconst mediaSelectionHandler = () => {\n // no-op: the real handler is attached in the builder via addEventListener\n};\n\nlet mediaSelectionListenerCount = 0;\nlet isMediaSelectionListenerAttached = false;\n\nexport function sendMediaSelection(blockId: string, payload: unknown) {\n if (typeof window === 'undefined') return;\n window.dispatchEvent(\n new CustomEvent(MEDIA_SELECTED_EVENT, {\n detail: { blockId, payload },\n })\n );\n}\n\nexport function useMediaSelectionEffect() {\n useEffect(() => {\n if (typeof window === 'undefined') return;\n if (!isMediaSelectionListenerAttached) {\n window.addEventListener(MEDIA_SELECTED_EVENT, mediaSelectionHandler);\n isMediaSelectionListenerAttached = true;\n }\n mediaSelectionListenerCount += 1;\n\n return () => {\n mediaSelectionListenerCount -= 1;\n if (mediaSelectionListenerCount <= 0 && isMediaSelectionListenerAttached) {\n window.removeEventListener(MEDIA_SELECTED_EVENT, mediaSelectionHandler);\n isMediaSelectionListenerAttached = false;\n }\n };\n }, []);\n}\n","import { useEffect } from 'react';\n\nexport function resetResponsivePictureState(element: HTMLPictureElement | null) {\n if (!element) return;\n element.querySelectorAll('source').forEach((source) => {\n // force browser to reconsider responsive sources\n const srcset = source.getAttribute('srcset');\n if (srcset) {\n source.setAttribute('data-srcset', srcset);\n source.removeAttribute('srcset');\n requestAnimationFrame(() => {\n source.setAttribute('srcset', srcset);\n });\n }\n });\n}\n\nexport function useResponsiveReset(ref: React.RefObject<HTMLPictureElement | HTMLImageElement>) {\n useEffect(() => {\n const element = ref.current;\n if (!element) return;\n if (element instanceof HTMLPictureElement) {\n resetResponsivePictureState(element);\n } else if (element.parentElement instanceof HTMLPictureElement) {\n resetResponsivePictureState(element.parentElement);\n }\n }, [ref]);\n}\n\n","\"use client\";\n\nimport React, { forwardRef, memo, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { useOptimizedImage } from \"@page-speed/hooks/media\";\nimport type { UseOptimizedImageOptions } from \"@page-speed/hooks/media\";\nimport { useMediaSelectionEffect } from \"./useMediaSelectionEffect.js\";\nimport { useResponsiveReset } from \"./useResponsiveReset.js\";\n\ntype NativeImgProps = Omit<\n React.ImgHTMLAttributes<HTMLImageElement>,\n \"src\" | \"srcSet\" | \"sizes\"\n> & {\n src?: string;\n};\n\nexport type ImgProps = NativeImgProps & {\n /** Explicit sizes attribute (otherwise derived from useOptimizedImage) */\n sizes?: string;\n /** Force eager load (alias for loading=\"eager\") */\n eager?: boolean;\n /** Intersection observer threshold for lazy loading */\n intersectionThreshold?: number;\n /** Intersection observer root margin for lazy loading */\n intersectionMargin?: string;\n /** OptixFlow integration options */\n optixFlowConfig?: UseOptimizedImageOptions[\"optixFlowConfig\"];\n};\n\ntype ForwardedImgProps = ImgProps & {\n forwardedRef: React.Ref<HTMLImageElement | null>;\n};\n\nconst TRANSPARENT_PIXEL =\n \"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==\";\n\nlet defaultOptixFlowConfig:\n | UseOptimizedImageOptions[\"optixFlowConfig\"]\n | undefined;\n\nconst readGlobalOptixFlowConfig = ():\n | UseOptimizedImageOptions[\"optixFlowConfig\"]\n | undefined => {\n if (typeof globalThis === \"undefined\") return undefined;\n const globalAny = globalThis as any;\n return (\n globalAny.PageSpeedImgDefaults?.optixFlowConfig ||\n globalAny.OpensiteImgDefaults?.optixFlowConfig ||\n globalAny.PAGE_SPEED_IMG_DEFAULTS?.optixFlowConfig\n );\n};\n\nconst resolveOptixFlowConfig = (\n config?: UseOptimizedImageOptions[\"optixFlowConfig\"],\n): UseOptimizedImageOptions[\"optixFlowConfig\"] | undefined => {\n return config ?? defaultOptixFlowConfig ?? readGlobalOptixFlowConfig();\n};\n\nexport const setDefaultOptixFlowConfig = (\n config?: UseOptimizedImageOptions[\"optixFlowConfig\"] | null,\n) => {\n defaultOptixFlowConfig = config ?? undefined;\n};\n\nconst isUrlString = (value: unknown): value is string =>\n typeof value === \"string\" && value.trim().length > 0;\n\nconst parseDimension = (value: unknown): number | undefined => {\n if (value === \"\" || value === null || typeof value === \"undefined\")\n return undefined;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\") {\n const numeric = Number(value);\n if (Number.isFinite(numeric)) return numeric;\n }\n return undefined;\n};\n\nconst composeRefs = (\n hookRef: (node: HTMLImageElement | null) => void,\n forwardedRef: React.Ref<HTMLImageElement | null>,\n localRef: React.RefObject<HTMLImageElement>,\n) =>\n useCallback(\n (node: HTMLImageElement | null) => {\n hookRef(node);\n // eslint-disable-next-line no-param-reassign\n (localRef as any).current = node;\n if (typeof forwardedRef === \"function\") {\n forwardedRef(node);\n } else if (forwardedRef && typeof (forwardedRef as any) === \"object\") {\n (forwardedRef as any).current = node;\n }\n },\n [hookRef, forwardedRef, localRef],\n );\n\nconst ModernImg: React.FC<ForwardedImgProps> = ({\n sizes,\n loading,\n decoding,\n alt,\n title,\n src: directSrc,\n eager,\n intersectionMargin,\n intersectionThreshold,\n optixFlowConfig,\n forwardedRef,\n ...rest\n}) => {\n const imgRef = useRef<HTMLImageElement | null>(null);\n const pictureRef = useRef<HTMLPictureElement | null>(null);\n const logKeyRef = useRef<string | null>(null);\n\n useResponsiveReset(pictureRef);\n useMediaSelectionEffect();\n\n const normalizedSrc = useMemo(\n () => (typeof directSrc === \"string\" ? directSrc.trim() : \"\"),\n [directSrc],\n );\n const numericWidth = useMemo(\n () => parseDimension((rest as any).width),\n [rest],\n );\n const numericHeight = useMemo(\n () => parseDimension((rest as any).height),\n [rest],\n );\n const resolvedOptixConfig = useMemo(\n () => resolveOptixFlowConfig(optixFlowConfig),\n [optixFlowConfig],\n );\n const eagerLoad = eager ?? loading === \"eager\";\n\n const {\n ref: hookRef,\n src,\n srcset,\n sizes: computedSizes,\n loading: hookLoading,\n isInView,\n size,\n } = useOptimizedImage({\n src: normalizedSrc,\n eager: eagerLoad,\n width: numericWidth,\n height: numericHeight,\n rootMargin: intersectionMargin ?? \"200px\",\n threshold: intersectionThreshold ?? 0.1,\n optixFlowConfig: resolvedOptixConfig,\n });\n\n const mergedRef = composeRefs(hookRef, forwardedRef, imgRef);\n const { width, height, ...restProps } = rest as Record<string, unknown>;\n const sizesAttr = sizes ?? (computedSizes || undefined);\n const loadingAttr = loading ?? hookLoading ?? \"lazy\";\n const decodingAttr = decoding ?? \"async\";\n const hasSrcSet = Boolean(srcset.avif || srcset.webp || srcset.jpeg);\n const imgSrc = src || normalizedSrc || TRANSPARENT_PIXEL;\n const inlineSrcSet =\n hasSrcSet && !srcset.avif && !srcset.webp ? srcset.jpeg : \"\";\n const parsedWidth = parseDimension(width);\n const parsedHeight = parseDimension(height);\n const widthAttr = parsedWidth ?? (size.width || numericWidth || undefined);\n const heightAttr =\n parsedHeight ?? (size.height || numericHeight || undefined);\n\n // Temporary logging to detect repeated transform requests and URL churn.\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n if (!eagerLoad && !isInView) return;\n if (!imgSrc || imgSrc === TRANSPARENT_PIXEL) return;\n\n const logKey = [\n imgSrc,\n srcset.avif,\n srcset.webp,\n srcset.jpeg,\n sizesAttr ?? \"\",\n ].join(\"|\");\n\n if (logKeyRef.current === logKey) return;\n logKeyRef.current = logKey;\n\n if (typeof console !== \"undefined\" && console.info) {\n console.info(\"[PageSpeedImg] image request\", {\n src: imgSrc,\n srcset,\n sizes: sizesAttr,\n });\n }\n }, [\n eagerLoad,\n imgSrc,\n isInView,\n sizesAttr,\n srcset.avif,\n srcset.webp,\n srcset.jpeg,\n ]);\n\n if (!hasSrcSet) {\n return (\n <img\n ref={mergedRef}\n src={imgSrc}\n loading={loadingAttr}\n decoding={decodingAttr}\n alt={alt}\n title={title}\n width={widthAttr}\n height={heightAttr}\n {...restProps}\n />\n );\n }\n\n return (\n <picture ref={pictureRef}>\n {srcset.avif ? (\n <source type=\"image/avif\" srcSet={srcset.avif} sizes={sizesAttr} />\n ) : null}\n {srcset.webp ? (\n <source type=\"image/webp\" srcSet={srcset.webp} sizes={sizesAttr} />\n ) : null}\n <img\n ref={mergedRef}\n src={imgSrc}\n srcSet={inlineSrcSet || undefined}\n sizes={inlineSrcSet ? sizesAttr : undefined}\n loading={loadingAttr}\n decoding={decodingAttr}\n alt={alt}\n title={title}\n width={widthAttr}\n height={heightAttr}\n {...restProps}\n />\n </picture>\n );\n};\n\nconst ImgBase = forwardRef<HTMLImageElement, ImgProps>(\n function Img(props, ref) {\n const hasSrc = typeof props.src === \"string\" && props.src.trim().length > 0;\n if (!hasSrc) {\n if (typeof console !== \"undefined\" && console.warn) {\n console.warn(\"<Img /> requires src. No src provided, rendering null.\");\n }\n return null;\n }\n\n return <ModernImg {...props} forwardedRef={ref} />;\n },\n);\n\nexport const Img = memo(ImgBase);\nImg.displayName = \"PageSpeedImg\";\n","// Ensure process.env exists when the module is loaded directly in the browser UMD build.\ntype GlobalWithProcess = typeof globalThis & { process?: NodeJS.Process };\n\nconst globalObject =\n typeof globalThis !== 'undefined' ? (globalThis as GlobalWithProcess) : undefined;\n\nif (globalObject) {\n if (!globalObject.process) {\n globalObject.process = {\n env: { NODE_ENV: 'production' } as NodeJS.ProcessEnv,\n } as NodeJS.Process;\n } else {\n const env = globalObject.process.env ?? (globalObject.process.env = {} as NodeJS.ProcessEnv);\n if (typeof env.NODE_ENV === 'undefined') {\n env.NODE_ENV = 'production';\n }\n }\n}\n\nimport type { UseOptimizedImageOptions } from '@page-speed/hooks/media';\n\nexport * from './core/index.js';\nexport type {\n ImageFormat,\n SrcsetByFormat,\n UseOptimizedImageOptions,\n UseOptimizedImageState,\n} from '@page-speed/hooks/media';\nexport type OptixFlowConfig = UseOptimizedImageOptions['optixFlowConfig'];\n"],"names":["DPR_MULTIPLIERS","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","MEDIA_SELECTED_EVENT","mediaSelectionHandler","mediaSelectionListenerCount","isMediaSelectionListenerAttached","resetResponsivePictureState","element","querySelectorAll","forEach","source","srcset","getAttribute","setAttribute","removeAttribute","requestAnimationFrame","TRANSPARENT_PIXEL","defaultOptixFlowConfig","resolveOptixFlowConfig","config","globalThis","globalAny","_a","PageSpeedImgDefaults","optixFlowConfig","_b","OpensiteImgDefaults","_c","PAGE_SPEED_IMG_DEFAULTS","readGlobalOptixFlowConfig","parseDimension","value","Number","isFinite","numeric","ModernImg","sizes","loading","decoding","alt","title","src","directSrc","eager","intersectionMargin","intersectionThreshold","forwardedRef","rest","imgRef","useRef","pictureRef","logKeyRef","ref","current","HTMLPictureElement","parentElement","addEventListener","removeEventListener","normalizedSrc","useMemo","trim","numericWidth","width","numericHeight","height","resolvedOptixConfig","eagerLoad","hookRef","computedSizes","hookLoading","isInView","size","options","threshold","rootMargin","optixFlowApiKey","apiKey","useOptixFlow","state","setState","useState","isLoaded","measuredSize","setMeasuredSize","observerRef","calculateRenderedSize","img2","renderedWidth","Math","round","clientWidth","naturalWidth","renderedHeight","clientHeight","naturalHeight","prev","img","resizeObserver","ResizeObserver","observe","disconnect","buildOptixFlowUrl","useCallback","imgWidth","imgHeight","format","params","URLSearchParams","set","String","objectFit","compressionLevel","toString","generateSrcset","baseWidth","baseHeight","map","dpr","scaledWidth","scaledHeight","join","primarySrc","hasDimensions","fallbackFormat","renderedFileType","avif","webp","jpeg","IntersectionObserver","entry","isIntersecting","handleLoad","complete","node","useOptimizedImage","mergedRef","localRef","composeRefs","restProps","sizesAttr","loadingAttr","decodingAttr","hasSrcSet","Boolean","imgSrc","inlineSrcSet","parsedWidth","parsedHeight","widthAttr","heightAttr","logKey","console","info","createElement","React","type","srcSet","ImgBase","forwardRef","props","length","warn","Img","memo","displayName","globalObject","process","env","NODE_ENV"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"page-speed-img.umd.js","sources":["../../node_modules/.pnpm/@page-speed+hooks@0.4.5_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/@page-speed/hooks/dist/chunk-ZTHTGLZO.js","../../src/core/useMediaSelectionEffect.ts","../../src/core/useResponsiveReset.ts","../../src/core/Img.tsx","../../src/core/useImgDebugLog.ts","../../src/index.ts","../../src/core/OptixFlowConfig.tsx"],"sourcesContent":["import { useMemo, useState, useRef, useLayoutEffect, useEffect, useCallback } from 'react';\n\nvar BASE_URL = \"https://octane.cdn.ing/api/v1/images/transform?\";\nvar DPR_MULTIPLIERS = [1, 2];\nvar useIsomorphicLayoutEffect = typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\nfunction useOptimizedImage(options) {\n const {\n src,\n eager = false,\n threshold = 0.1,\n rootMargin = \"50px\",\n width,\n height,\n optixFlowConfig\n } = options;\n const optixFlowApiKey = useMemo(() => {\n return optixFlowConfig?.apiKey;\n }, [optixFlowConfig?.apiKey]);\n const useOptixFlow = useMemo(() => {\n return optixFlowApiKey ? true : false;\n }, [optixFlowApiKey]);\n const [state, setState] = useState({\n isLoaded: false,\n isInView: false\n });\n const [measuredSize, setMeasuredSize] = useState({\n width: 0,\n height: 0\n });\n const imgRef = useRef(null);\n const observerRef = useRef(null);\n const size = useMemo(\n () => ({\n width: width ?? measuredSize.width,\n height: height ?? measuredSize.height\n }),\n [width, height, measuredSize.width, measuredSize.height]\n );\n useIsomorphicLayoutEffect(() => {\n if (!imgRef.current) return;\n if (width !== void 0 && height !== void 0) return;\n const calculateRenderedSize = () => {\n const img2 = imgRef.current;\n if (!img2) return;\n const renderedWidth = width ?? (Math.round(img2.clientWidth) || img2.naturalWidth || 0);\n const renderedHeight = height ?? (Math.round(img2.clientHeight) || img2.naturalHeight || 0);\n if (renderedWidth > 0 || renderedHeight > 0) {\n setMeasuredSize((prev) => {\n if (prev.width !== renderedWidth || prev.height !== renderedHeight) {\n return { width: renderedWidth, height: renderedHeight };\n }\n return prev;\n });\n }\n };\n if (imgRef.current.clientWidth > 0) {\n calculateRenderedSize();\n }\n const img = imgRef.current;\n img.addEventListener(\"load\", calculateRenderedSize);\n let resizeObserver = null;\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver = new ResizeObserver(() => {\n calculateRenderedSize();\n });\n resizeObserver.observe(img);\n }\n return () => {\n img.removeEventListener(\"load\", calculateRenderedSize);\n resizeObserver?.disconnect();\n };\n }, [width, height]);\n const buildOptixFlowUrl = useCallback(\n (imgWidth, imgHeight, format) => {\n if (!useOptixFlow) return src;\n if (!imgWidth || !imgHeight) return src;\n const params = new URLSearchParams();\n params.set(\"url\", src);\n params.set(\"fit\", String(optixFlowConfig?.objectFit ?? \"cover\"));\n params.set(\"w\", String(imgWidth));\n params.set(\"h\", String(imgHeight));\n params.set(\"q\", String(optixFlowConfig?.compressionLevel ?? 75));\n params.set(\"f\", format);\n params.set(\"apiKey\", optixFlowApiKey);\n return `${BASE_URL}${params.toString()}`;\n },\n [\n useOptixFlow,\n src,\n optixFlowConfig?.compressionLevel,\n optixFlowApiKey,\n optixFlowConfig?.objectFit\n ]\n );\n const generateSrcset = useCallback(\n (baseWidth, baseHeight, format) => {\n if (!useOptixFlow || baseWidth === 0 || baseHeight === 0) return \"\";\n return DPR_MULTIPLIERS.map((dpr) => {\n const scaledWidth = Math.round(baseWidth * dpr);\n const scaledHeight = Math.round(baseHeight * dpr);\n const url = buildOptixFlowUrl(scaledWidth, scaledHeight, format);\n return `${url} ${dpr}x`;\n }).join(\", \");\n },\n [useOptixFlow, buildOptixFlowUrl]\n );\n const primarySrc = useMemo(() => {\n const hasDimensions = size.width > 0 && size.height > 0;\n if (!useOptixFlow || !hasDimensions) return src;\n const fallbackFormat = optixFlowConfig?.renderedFileType ?? \"jpeg\";\n return buildOptixFlowUrl(size.width, size.height, fallbackFormat);\n }, [\n useOptixFlow,\n src,\n size.width,\n size.height,\n optixFlowConfig?.renderedFileType,\n optixFlowConfig?.compressionLevel,\n optixFlowConfig?.objectFit,\n buildOptixFlowUrl\n ]);\n const srcset = useMemo(() => {\n return {\n avif: generateSrcset(size.width, size.height, \"avif\"),\n webp: generateSrcset(size.width, size.height, \"webp\"),\n jpeg: generateSrcset(size.width, size.height, \"jpeg\")\n };\n }, [size.width, size.height, generateSrcset]);\n const sizes = useMemo(() => {\n if (size.width === 0) return \"\";\n return `${size.width}px`;\n }, [size.width]);\n useEffect(() => {\n if (typeof window === \"undefined\" || !imgRef.current) {\n return;\n }\n if (eager) {\n setState({ isLoaded: false, isInView: true });\n return;\n }\n observerRef.current = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setState((prev) => ({ ...prev, isInView: true }));\n observerRef.current?.disconnect();\n }\n },\n { threshold, rootMargin }\n );\n observerRef.current.observe(imgRef.current);\n return () => {\n observerRef.current?.disconnect();\n };\n }, [eager, threshold, rootMargin]);\n useEffect(() => {\n if (!imgRef.current) return;\n const handleLoad = () => {\n setState((prev) => ({ ...prev, isLoaded: true }));\n };\n const img = imgRef.current;\n if (img.complete) {\n handleLoad();\n } else {\n img.addEventListener(\"load\", handleLoad);\n return () => img.removeEventListener(\"load\", handleLoad);\n }\n }, [state.isInView]);\n const ref = useCallback((node) => {\n imgRef.current = node;\n }, []);\n const emptySrcset = { avif: \"\", webp: \"\", jpeg: \"\" };\n return {\n ref,\n // Primary src uses exact rendered dimensions for Lighthouse \"Properly size images\" compliance\n src: state.isInView || eager ? primarySrc : src,\n // Srcset with format variants and DPR multipliers for <picture> element\n srcset: state.isInView || eager ? srcset : emptySrcset,\n // Sizes attribute for responsive image selection\n sizes: state.isInView || eager ? sizes : \"\",\n isLoaded: state.isLoaded,\n isInView: state.isInView,\n loading: eager ? \"eager\" : \"lazy\",\n size\n };\n}\n\nexport { useOptimizedImage };\n//# sourceMappingURL=chunk-ZTHTGLZO.js.map\n//# sourceMappingURL=chunk-ZTHTGLZO.js.map","import { useEffect } from 'react';\n\nconst MEDIA_SELECTED_EVENT = 'dt:media-selected';\nconst mediaSelectionHandler = () => {\n // no-op: the real handler is attached in the builder via addEventListener\n};\n\nlet mediaSelectionListenerCount = 0;\nlet isMediaSelectionListenerAttached = false;\n\nexport function sendMediaSelection(blockId: string, payload: unknown) {\n if (typeof window === 'undefined') return;\n window.dispatchEvent(\n new CustomEvent(MEDIA_SELECTED_EVENT, {\n detail: { blockId, payload },\n })\n );\n}\n\nexport function useMediaSelectionEffect() {\n useEffect(() => {\n if (typeof window === 'undefined') return;\n if (!isMediaSelectionListenerAttached) {\n window.addEventListener(MEDIA_SELECTED_EVENT, mediaSelectionHandler);\n isMediaSelectionListenerAttached = true;\n }\n mediaSelectionListenerCount += 1;\n\n return () => {\n mediaSelectionListenerCount -= 1;\n if (mediaSelectionListenerCount <= 0 && isMediaSelectionListenerAttached) {\n window.removeEventListener(MEDIA_SELECTED_EVENT, mediaSelectionHandler);\n isMediaSelectionListenerAttached = false;\n }\n };\n }, []);\n}\n","import { useEffect } from 'react';\n\nexport function resetResponsivePictureState(element: HTMLPictureElement | null) {\n if (!element) return;\n element.querySelectorAll('source').forEach((source) => {\n // force browser to reconsider responsive sources\n const srcset = source.getAttribute('srcset');\n if (srcset) {\n source.setAttribute('data-srcset', srcset);\n source.removeAttribute('srcset');\n requestAnimationFrame(() => {\n source.setAttribute('srcset', srcset);\n });\n }\n });\n}\n\nexport function useResponsiveReset(ref: React.RefObject<HTMLPictureElement | HTMLImageElement>) {\n useEffect(() => {\n const element = ref.current;\n if (!element) return;\n if (element instanceof HTMLPictureElement) {\n resetResponsivePictureState(element);\n } else if (element.parentElement instanceof HTMLPictureElement) {\n resetResponsivePictureState(element.parentElement);\n }\n }, [ref]);\n}\n\n","\"use client\";\n\nimport React, { forwardRef, memo, useCallback, useMemo, useRef } from \"react\";\nimport { useOptimizedImage } from \"@page-speed/hooks/media\";\nimport type { UseOptimizedImageOptions } from \"@page-speed/hooks/media\";\nimport { useImgDebugLog } from \"./useImgDebugLog.js\";\nimport { useMediaSelectionEffect } from \"./useMediaSelectionEffect.js\";\nimport { useResponsiveReset } from \"./useResponsiveReset.js\";\n\ntype NativeImgProps = Omit<\n React.ImgHTMLAttributes<HTMLImageElement>,\n \"src\" | \"srcSet\" | \"sizes\"\n> & {\n src?: string;\n};\n\nexport type ImgProps = NativeImgProps & {\n /** Explicit sizes attribute (otherwise derived from useOptimizedImage) */\n sizes?: string;\n /** Force eager load (alias for loading=\"eager\") */\n eager?: boolean;\n /** Intersection observer threshold for lazy loading */\n intersectionThreshold?: number;\n /** Intersection observer root margin for lazy loading */\n intersectionMargin?: string;\n /** OptixFlow integration options */\n optixFlowConfig?: UseOptimizedImageOptions[\"optixFlowConfig\"];\n /** Enable debug logging for image requests */\n useDebugMode?: boolean;\n};\n\ntype ForwardedImgProps = ImgProps & {\n forwardedRef: React.Ref<HTMLImageElement | null>;\n};\n\nconst TRANSPARENT_PIXEL =\n \"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==\";\n\nlet defaultOptixFlowConfig:\n | UseOptimizedImageOptions[\"optixFlowConfig\"]\n | undefined;\n\nconst readGlobalOptixFlowConfig = ():\n | UseOptimizedImageOptions[\"optixFlowConfig\"]\n | undefined => {\n if (typeof globalThis === \"undefined\") return undefined;\n const globalAny = globalThis as any;\n return (\n globalAny.PageSpeedImgDefaults?.optixFlowConfig ||\n globalAny.OpensiteImgDefaults?.optixFlowConfig ||\n globalAny.PAGE_SPEED_IMG_DEFAULTS?.optixFlowConfig\n );\n};\n\nconst resolveOptixFlowConfig = (\n config?: UseOptimizedImageOptions[\"optixFlowConfig\"],\n): UseOptimizedImageOptions[\"optixFlowConfig\"] | undefined => {\n return config ?? defaultOptixFlowConfig ?? readGlobalOptixFlowConfig();\n};\n\nexport const setDefaultOptixFlowConfig = (\n config?: UseOptimizedImageOptions[\"optixFlowConfig\"] | null,\n) => {\n defaultOptixFlowConfig = config ?? undefined;\n};\n\nconst parseDimension = (value: unknown): number | undefined => {\n if (value === \"\" || value === null || typeof value === \"undefined\")\n return undefined;\n if (typeof value === \"number\" && Number.isFinite(value)) return value;\n if (typeof value === \"string\") {\n const numeric = Number(value);\n if (Number.isFinite(numeric)) return numeric;\n }\n return undefined;\n};\n\nconst composeRefs = (\n hookRef: (node: HTMLImageElement | null) => void,\n forwardedRef: React.Ref<HTMLImageElement | null>,\n localRef: React.RefObject<HTMLImageElement>,\n) =>\n useCallback(\n (node: HTMLImageElement | null) => {\n hookRef(node);\n // eslint-disable-next-line no-param-reassign\n (localRef as any).current = node;\n if (typeof forwardedRef === \"function\") {\n forwardedRef(node);\n } else if (forwardedRef && typeof (forwardedRef as any) === \"object\") {\n (forwardedRef as any).current = node;\n }\n },\n [hookRef, forwardedRef, localRef],\n );\n\nconst ModernImg: React.FC<ForwardedImgProps> = ({\n sizes,\n loading,\n decoding,\n alt,\n title,\n src: directSrc,\n eager,\n width,\n height,\n fetchPriority,\n intersectionMargin,\n intersectionThreshold,\n optixFlowConfig,\n useDebugMode,\n forwardedRef,\n ...restProps\n}) => {\n const imgRef = useRef<HTMLImageElement | null>(null);\n const pictureRef = useRef<HTMLPictureElement | null>(null);\n\n useResponsiveReset(pictureRef);\n useMediaSelectionEffect();\n\n const normalizedSrc = useMemo(\n () => (typeof directSrc === \"string\" ? directSrc.trim() : \"\"),\n [directSrc],\n );\n const numericWidth = useMemo(() => parseDimension(width), [width]);\n const numericHeight = useMemo(() => parseDimension(height), [height]);\n const resolvedOptixConfig = useMemo(\n () => resolveOptixFlowConfig(optixFlowConfig),\n [optixFlowConfig],\n );\n const eagerLoad = useMemo(() => {\n return eager ?? loading === \"eager\";\n }, [eager, loading]);\n\n const hookOptions = useMemo(\n () => ({\n src: normalizedSrc,\n eager: eagerLoad,\n width: numericWidth,\n height: numericHeight,\n rootMargin: intersectionMargin ?? \"200px\",\n threshold: intersectionThreshold ?? 0.1,\n optixFlowConfig: resolvedOptixConfig,\n }),\n [\n normalizedSrc,\n eagerLoad,\n numericWidth,\n numericHeight,\n intersectionMargin,\n intersectionThreshold,\n resolvedOptixConfig,\n ],\n );\n\n const {\n ref: hookRef,\n src,\n srcset,\n sizes: computedSizes,\n loading: hookLoading,\n isInView,\n size,\n } = useOptimizedImage(hookOptions);\n\n const mergedRef = composeRefs(hookRef, forwardedRef, imgRef);\n\n const sizesAttr = useMemo(() => {\n return sizes ?? (computedSizes || undefined);\n }, [sizes, computedSizes]);\n const loadingAttr = useMemo(() => {\n return loading ?? hookLoading ?? \"lazy\";\n }, [loading, hookLoading]);\n const decodingAttr = useMemo(() => {\n return decoding ?? \"async\";\n }, [decoding]);\n const fetchPriorityAttr = useMemo(() => {\n return fetchPriority ?? (eagerLoad ? \"high\" : undefined);\n }, [fetchPriority, eagerLoad]);\n\n const hasSrcSet = useMemo(() => {\n return Boolean(srcset.avif || srcset.webp || srcset.jpeg);\n }, [srcset.avif, srcset.webp, srcset.jpeg]);\n const imgSrc = useMemo(() => {\n return src || normalizedSrc || TRANSPARENT_PIXEL;\n }, [src, normalizedSrc]);\n const inlineSrcSet = useMemo(() => {\n return hasSrcSet && !srcset.avif && !srcset.webp ? srcset.jpeg : \"\";\n }, [hasSrcSet, srcset.avif, srcset.webp, srcset.jpeg]);\n\n const widthAttr = useMemo(() => {\n return numericWidth ?? (size.width || undefined);\n }, [numericWidth, size?.width]);\n const heightAttr = useMemo(() => {\n return numericHeight ?? (size.height || undefined);\n }, [numericHeight, size?.height]);\n\n useImgDebugLog({\n enabled: useDebugMode ?? false,\n eagerLoad,\n isInView,\n imgSrc,\n transparentPixel: TRANSPARENT_PIXEL,\n srcset,\n sizesAttr,\n });\n\n if (!hasSrcSet) {\n return (\n <img\n ref={mergedRef}\n src={imgSrc}\n loading={loadingAttr}\n decoding={decodingAttr}\n fetchPriority={fetchPriorityAttr}\n alt={alt}\n title={title}\n width={widthAttr}\n height={heightAttr}\n {...restProps}\n />\n );\n }\n\n return (\n <picture ref={pictureRef}>\n {srcset.avif ? (\n <source type=\"image/avif\" srcSet={srcset.avif} sizes={sizesAttr} />\n ) : null}\n {srcset.webp ? (\n <source type=\"image/webp\" srcSet={srcset.webp} sizes={sizesAttr} />\n ) : null}\n <img\n ref={mergedRef}\n src={imgSrc}\n srcSet={inlineSrcSet || undefined}\n sizes={inlineSrcSet ? sizesAttr : undefined}\n loading={loadingAttr}\n decoding={decodingAttr}\n fetchPriority={fetchPriorityAttr}\n alt={alt}\n title={title}\n width={widthAttr}\n height={heightAttr}\n {...restProps}\n />\n </picture>\n );\n};\n\nconst ImgBase = forwardRef<HTMLImageElement, ImgProps>(\n function Img(props, ref) {\n const hasSrc = typeof props.src === \"string\" && props.src.trim().length > 0;\n if (!hasSrc) {\n if (typeof console !== \"undefined\" && console.warn) {\n console.warn(\"<Img /> requires src. No src provided, rendering null.\");\n }\n return null;\n }\n\n return <ModernImg {...props} forwardedRef={ref} />;\n },\n);\n\nexport const Img = memo(ImgBase);\nImg.displayName = \"PageSpeedImg\";\n","import { useEffect, useRef } from \"react\";\n\ninterface ImgDebugLogParams {\n enabled: boolean;\n eagerLoad: boolean;\n isInView: boolean;\n imgSrc: string;\n transparentPixel: string;\n srcset: { avif: string; webp: string; jpeg: string };\n sizesAttr: string | undefined;\n}\n\n/**\n * Logs image-request details to the console when `enabled` is true.\n * When disabled (the default), the hook short-circuits on the very first\n * line so there is no meaningful runtime cost.\n */\nexport function useImgDebugLog({\n enabled,\n eagerLoad,\n isInView,\n imgSrc,\n transparentPixel,\n srcset,\n sizesAttr,\n}: ImgDebugLogParams): void {\n const logKeyRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (!enabled) return;\n if (typeof window === \"undefined\") return;\n if (!eagerLoad && !isInView) return;\n if (!imgSrc || imgSrc === transparentPixel) return;\n\n const logKey = [\n imgSrc,\n srcset.avif,\n srcset.webp,\n srcset.jpeg,\n sizesAttr ?? \"\",\n ].join(\"|\");\n\n if (logKeyRef.current === logKey) return;\n logKeyRef.current = logKey;\n\n if (typeof console !== \"undefined\" && console.info) {\n console.info(\"[PageSpeedImg] image request\", {\n src: imgSrc,\n srcset,\n sizes: sizesAttr,\n });\n }\n }, [\n enabled,\n eagerLoad,\n imgSrc,\n isInView,\n sizesAttr,\n srcset.avif,\n srcset.webp,\n srcset.jpeg,\n transparentPixel,\n ]);\n}\n","// Ensure process.env exists when the module is loaded directly in the browser UMD build.\ntype GlobalWithProcess = typeof globalThis & { process?: NodeJS.Process };\n\nconst globalObject =\n typeof globalThis !== 'undefined' ? (globalThis as GlobalWithProcess) : undefined;\n\nif (globalObject) {\n if (!globalObject.process) {\n globalObject.process = {\n env: { NODE_ENV: 'production' } as NodeJS.ProcessEnv,\n } as NodeJS.Process;\n } else {\n const env = globalObject.process.env ?? (globalObject.process.env = {} as NodeJS.ProcessEnv);\n if (typeof env.NODE_ENV === 'undefined') {\n env.NODE_ENV = 'production';\n }\n }\n}\n\nimport type { UseOptimizedImageOptions } from '@page-speed/hooks/media';\n\nexport * from './core/index.js';\nexport type {\n ImageFormat,\n SrcsetByFormat,\n UseOptimizedImageOptions,\n UseOptimizedImageState,\n} from '@page-speed/hooks/media';\nexport type OptixFlowConfig = UseOptimizedImageOptions['optixFlowConfig'];\n// Re-export specific items for clarity and CDN usage\nexport { Img, setDefaultOptixFlowConfig, OptixFlowConfig } from './core/index.js';\nexport type { ImgProps, OptixFlowConfigProps } from './core/index.js';\n","\"use client\";\n\nimport * as React from \"react\";\nimport type { UseOptimizedImageOptions } from \"@page-speed/hooks/media\";\nimport { setDefaultOptixFlowConfig } from \"./Img.js\";\n\n/**\n * Props for the OptixFlowConfig component\n */\nexport interface OptixFlowConfigProps {\n /**\n * OptixFlow configuration to set as default for all images\n * @example { apiKey: 'your-api-key', compressionLevel: 80 }\n */\n config: UseOptimizedImageOptions[\"optixFlowConfig\"];\n /**\n * Optional children (component returns null regardless)\n */\n children?: React.ReactNode;\n}\n\n/**\n * A component that sets the default OptixFlow configuration for all Img components\n * in an SSR-safe way. This component should be rendered once at the app root level.\n *\n * The config is applied inside a useEffect, which means it only runs on the client\n * and is never executed during server-side rendering.\n *\n * @example\n * ```tsx\n * // In your app root\n * <OptixFlowConfig config={{ apiKey: 'your-api-key' }}>\n * <App />\n * </OptixFlowConfig>\n * ```\n *\n * Or without children:\n * ```tsx\n * <OptixFlowConfig config={{ apiKey: 'your-api-key' }} />\n * ```\n */\nexport function OptixFlowConfig({\n config,\n children,\n}: OptixFlowConfigProps): React.ReactElement | null {\n React.useEffect(() => {\n setDefaultOptixFlowConfig(config ?? null);\n }, [config]);\n\n return children ? <>{children}</> : null;\n}\n"],"names":["DPR_MULTIPLIERS","useIsomorphicLayoutEffect","window","useLayoutEffect","useEffect","MEDIA_SELECTED_EVENT","mediaSelectionHandler","mediaSelectionListenerCount","isMediaSelectionListenerAttached","resetResponsivePictureState","element","querySelectorAll","forEach","source","srcset","getAttribute","setAttribute","removeAttribute","requestAnimationFrame","TRANSPARENT_PIXEL","defaultOptixFlowConfig","resolveOptixFlowConfig","config","globalThis","globalAny","_a","PageSpeedImgDefaults","optixFlowConfig","_b","OpensiteImgDefaults","_c","PAGE_SPEED_IMG_DEFAULTS","readGlobalOptixFlowConfig","setDefaultOptixFlowConfig","parseDimension","value","Number","isFinite","numeric","ModernImg","sizes","loading","decoding","alt","title","src","directSrc","eager","width","height","fetchPriority","intersectionMargin","intersectionThreshold","useDebugMode","forwardedRef","restProps","imgRef","useRef","pictureRef","ref","current","HTMLPictureElement","parentElement","addEventListener","removeEventListener","normalizedSrc","useMemo","trim","numericWidth","numericHeight","resolvedOptixConfig","eagerLoad","hookOptions","rootMargin","threshold","hookRef","computedSizes","hookLoading","isInView","size","options","optixFlowApiKey","apiKey","useOptixFlow","state","setState","useState","isLoaded","measuredSize","setMeasuredSize","observerRef","calculateRenderedSize","img2","renderedWidth","Math","round","clientWidth","naturalWidth","renderedHeight","clientHeight","naturalHeight","prev","img","resizeObserver","ResizeObserver","observe","disconnect","buildOptixFlowUrl","useCallback","imgWidth","imgHeight","format","params","URLSearchParams","set","String","objectFit","compressionLevel","toString","generateSrcset","baseWidth","baseHeight","map","dpr","scaledWidth","scaledHeight","join","primarySrc","hasDimensions","fallbackFormat","renderedFileType","avif","webp","jpeg","IntersectionObserver","entry","isIntersecting","handleLoad","complete","node","useOptimizedImage","mergedRef","localRef","composeRefs","sizesAttr","loadingAttr","decodingAttr","fetchPriorityAttr","hasSrcSet","Boolean","imgSrc","inlineSrcSet","widthAttr","heightAttr","enabled","transparentPixel","logKeyRef","logKey","console","info","useImgDebugLog","createElement","React","type","srcSet","ImgBase","forwardRef","props","length","warn","Img","memo","displayName","globalObject","process","env","NODE_ENV","children","Fragment"],"mappings":"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","x_google_ignoreList":[0]}
|