@pixelfiddler/react 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +218 -0
- package/dist/index.cjs +60 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +56 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/package.json +78 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PixelFiddler
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# @pixelfiddler/react
|
|
2
|
+
|
|
3
|
+
React components for [PixelFiddler](https://pixel-fiddler.com) image transformations with automatic responsive image support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @pixelfiddler/react
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @pixelfiddler/react
|
|
11
|
+
# or
|
|
12
|
+
yarn add @pixelfiddler/react
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Note:** This package requires `react` >= 18.0.0 as a peer dependency.
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { PixelFiddleImage } from '@pixelfiddler/react';
|
|
21
|
+
|
|
22
|
+
function App() {
|
|
23
|
+
return (
|
|
24
|
+
<PixelFiddleImage
|
|
25
|
+
src="https://example.com/photo.jpg"
|
|
26
|
+
alt="A beautiful photo"
|
|
27
|
+
width={800}
|
|
28
|
+
transformations={{ format: 'WEBP', quality: 80 }}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Components
|
|
35
|
+
|
|
36
|
+
### `PixelFiddleImage`
|
|
37
|
+
|
|
38
|
+
A drop-in replacement for the `<img>` element that automatically generates optimized `srcSet` for responsive images.
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import { PixelFiddleImage } from '@pixelfiddler/react';
|
|
42
|
+
|
|
43
|
+
// Fixed-width image with DPR support (x descriptors)
|
|
44
|
+
<PixelFiddleImage
|
|
45
|
+
src="https://example.com/photo.jpg"
|
|
46
|
+
alt="Profile photo"
|
|
47
|
+
width={400}
|
|
48
|
+
/>
|
|
49
|
+
// Generates: srcset="...?w=640 1x, ...?w=828 2x"
|
|
50
|
+
|
|
51
|
+
// Fluid/responsive image (w descriptors)
|
|
52
|
+
<PixelFiddleImage
|
|
53
|
+
src="https://example.com/photo.jpg"
|
|
54
|
+
alt="Hero image"
|
|
55
|
+
sizes="(max-width: 768px) 100vw, 50vw"
|
|
56
|
+
/>
|
|
57
|
+
// Generates: srcset="...?w=320 320w, ...?w=640 640w, ..."
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### Props
|
|
61
|
+
|
|
62
|
+
| Prop | Type | Default | Description |
|
|
63
|
+
|------|------|---------|-------------|
|
|
64
|
+
| `src` | `string` | **required** | Base URL of the image |
|
|
65
|
+
| `alt` | `string` | - | Alt text (required for accessibility) |
|
|
66
|
+
| `width` | `number \| string` | - | Display width in CSS pixels. Generates DPR descriptors (`1x`, `2x`) |
|
|
67
|
+
| `sizes` | `string` | - | Sizes attribute for responsive images. Generates width descriptors (`w`) |
|
|
68
|
+
| `transformations` | `TransformationOptions` | - | Image transformation options |
|
|
69
|
+
| `responsive` | `boolean` | `true` | Enable automatic srcSet generation |
|
|
70
|
+
| `deviceBreakpoints` | `number[]` | `[320, 375, 640, 768, 1024, 1280, 1536, 1920]` | Breakpoints for viewport-based sizing |
|
|
71
|
+
| `imageBreakpoints` | `number[]` | `[16, 32, 48, 64, 96, 128, 256, 384]` | Breakpoints for smaller images |
|
|
72
|
+
| `config` | `UrlBuilderConfig` | - | Override provider config for this image |
|
|
73
|
+
|
|
74
|
+
All standard `<img>` attributes (`className`, `loading`, `decoding`, etc.) are also supported.
|
|
75
|
+
|
|
76
|
+
### `PixelFiddlerProvider`
|
|
77
|
+
|
|
78
|
+
A context provider for sharing configuration across all `PixelFiddleImage` components.
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { PixelFiddlerProvider, PixelFiddleImage } from '@pixelfiddler/react';
|
|
82
|
+
|
|
83
|
+
function App() {
|
|
84
|
+
return (
|
|
85
|
+
<PixelFiddlerProvider config={{ baseUrl: 'https://cdn.example.com' }}>
|
|
86
|
+
<PixelFiddleImage src="/photos/hero.jpg" alt="Hero" sizes="100vw" />
|
|
87
|
+
<PixelFiddleImage src="/photos/thumb.jpg" alt="Thumbnail" width={200} />
|
|
88
|
+
</PixelFiddlerProvider>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### Props
|
|
94
|
+
|
|
95
|
+
| Prop | Type | Description |
|
|
96
|
+
|------|------|-------------|
|
|
97
|
+
| `config` | `PixelFiddlerConfig` | Configuration object with `baseUrl` and optional `signatureKey` |
|
|
98
|
+
| `children` | `ReactNode` | Child components |
|
|
99
|
+
|
|
100
|
+
## Usage Examples
|
|
101
|
+
|
|
102
|
+
### Basic Transformations
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<PixelFiddleImage
|
|
106
|
+
src="https://example.com/photo.jpg"
|
|
107
|
+
alt="Transformed image"
|
|
108
|
+
responsive={false}
|
|
109
|
+
transformations={{
|
|
110
|
+
width: 800,
|
|
111
|
+
height: 600,
|
|
112
|
+
format: 'WEBP',
|
|
113
|
+
quality: 85,
|
|
114
|
+
}}
|
|
115
|
+
/>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Responsive Image with Fixed Display Width
|
|
119
|
+
|
|
120
|
+
When you know the exact display size, use `width` to generate DPR variants:
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
<PixelFiddleImage
|
|
124
|
+
src="https://example.com/avatar.jpg"
|
|
125
|
+
alt="User avatar"
|
|
126
|
+
width={150}
|
|
127
|
+
transformations={{ format: 'WEBP' }}
|
|
128
|
+
/>
|
|
129
|
+
// Output:
|
|
130
|
+
// src="...?w=384&f=WEBP"
|
|
131
|
+
// srcset="...?w=384&f=WEBP 1x, ...?w=640&f=WEBP 2x"
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Responsive Image with Fluid Layout
|
|
135
|
+
|
|
136
|
+
For images that scale with the viewport, use `sizes`:
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
<PixelFiddleImage
|
|
140
|
+
src="https://example.com/hero.jpg"
|
|
141
|
+
alt="Hero banner"
|
|
142
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 800px"
|
|
143
|
+
transformations={{ format: 'WEBP', quality: 80 }}
|
|
144
|
+
/>
|
|
145
|
+
// Generates srcset with width descriptors (320w, 640w, 768w, etc.)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Custom Breakpoints
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
<PixelFiddleImage
|
|
152
|
+
src="https://example.com/photo.jpg"
|
|
153
|
+
alt="Custom breakpoints"
|
|
154
|
+
sizes="100vw"
|
|
155
|
+
deviceBreakpoints={[480, 768, 1024, 1440, 1920]}
|
|
156
|
+
imageBreakpoints={[]}
|
|
157
|
+
/>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Disable Responsive Behavior
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
<PixelFiddleImage
|
|
164
|
+
src="https://example.com/photo.jpg"
|
|
165
|
+
alt="Non-responsive"
|
|
166
|
+
responsive={false}
|
|
167
|
+
transformations={{ width: 400, format: 'WEBP' }}
|
|
168
|
+
/>
|
|
169
|
+
// Output: just src, no srcset
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### With Standard Image Attributes
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
<PixelFiddleImage
|
|
176
|
+
src="https://example.com/photo.jpg"
|
|
177
|
+
alt="Lazy loaded image"
|
|
178
|
+
width={600}
|
|
179
|
+
className="rounded-lg shadow-md"
|
|
180
|
+
loading="lazy"
|
|
181
|
+
decoding="async"
|
|
182
|
+
/>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Responsive Strategy
|
|
186
|
+
|
|
187
|
+
The component automatically chooses the appropriate srcSet strategy:
|
|
188
|
+
|
|
189
|
+
| Input | Strategy | Descriptor | Use Case |
|
|
190
|
+
|-------|----------|------------|----------|
|
|
191
|
+
| `width` only | Fixed-size | `x` (1x, 2x) | Known display size, needs high-DPI support |
|
|
192
|
+
| `sizes` only | Fluid | `w` (640w, 1200w) | Image size varies with viewport |
|
|
193
|
+
| Neither | Fluid | `w` | Full-width responsive image (defaults to `sizes="100vw"`) |
|
|
194
|
+
|
|
195
|
+
## TypeScript
|
|
196
|
+
|
|
197
|
+
Full TypeScript support with exported types:
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
import type {
|
|
201
|
+
PixelFiddlerImageProps,
|
|
202
|
+
PixelFiddlerProviderProps,
|
|
203
|
+
} from '@pixelfiddler/react';
|
|
204
|
+
|
|
205
|
+
import type {
|
|
206
|
+
TransformationOptions,
|
|
207
|
+
UrlBuilderConfig,
|
|
208
|
+
PixelFiddlerConfig,
|
|
209
|
+
} from '@pixelfiddler/core';
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Related
|
|
213
|
+
|
|
214
|
+
- [@pixelfiddler/core](https://www.npmjs.com/package/@pixelfiddler/core) - Core utilities for building transformation URLs
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var core = require('@pixelfiddler/core');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
// src/components/pixel-fiddler-image.tsx
|
|
8
|
+
var PixelFiddlerContext = react.createContext(null);
|
|
9
|
+
function PixelFiddlerProvider({ children, config }) {
|
|
10
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PixelFiddlerContext.Provider, { value: { config }, children });
|
|
11
|
+
}
|
|
12
|
+
function PixelFiddlerImage({
|
|
13
|
+
src,
|
|
14
|
+
sizes,
|
|
15
|
+
width,
|
|
16
|
+
transformations,
|
|
17
|
+
baseUrl,
|
|
18
|
+
deviceBreakpoints,
|
|
19
|
+
imageBreakpoints,
|
|
20
|
+
responsive = true,
|
|
21
|
+
...imgProps
|
|
22
|
+
}) {
|
|
23
|
+
const context = react.useContext(PixelFiddlerContext);
|
|
24
|
+
const imageAttrs = react.useMemo(() => {
|
|
25
|
+
const finalBaseUrl = baseUrl || context?.config.baseUrl;
|
|
26
|
+
const hasWidthTransformation = transformations?.width;
|
|
27
|
+
if (responsive && !hasWidthTransformation) {
|
|
28
|
+
if (width && sizes) {
|
|
29
|
+
console.warn(
|
|
30
|
+
"[PixelFiddlerImage] Both `width` and `sizes` were provided. `sizes` will be ignored and a fixed-width DPR srcSet will be generated."
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return core.createResponsiveAttributes(src, finalBaseUrl, {
|
|
34
|
+
width: width && +width,
|
|
35
|
+
sizes,
|
|
36
|
+
deviceBreakpoints,
|
|
37
|
+
imageBreakpoints,
|
|
38
|
+
transformations
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
src: core.buildTransformationUrl({ src, baseUrl, transformations })
|
|
43
|
+
};
|
|
44
|
+
}, [src, sizes, transformations, deviceBreakpoints, imageBreakpoints, width, baseUrl, context?.config.baseUrl, responsive]);
|
|
45
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
46
|
+
"img",
|
|
47
|
+
{
|
|
48
|
+
src: imageAttrs.src || src,
|
|
49
|
+
srcSet: imageAttrs.srcSet,
|
|
50
|
+
sizes: imageAttrs.sizes,
|
|
51
|
+
width: imageAttrs.width || width,
|
|
52
|
+
...imgProps
|
|
53
|
+
}
|
|
54
|
+
) });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
exports.PixelFiddlerImage = PixelFiddlerImage;
|
|
58
|
+
exports.PixelFiddlerProvider = PixelFiddlerProvider;
|
|
59
|
+
//# sourceMappingURL=index.cjs.map
|
|
60
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider/pixel-fiddler-context.tsx","../src/components/pixel-fiddler-image.tsx"],"names":["createContext","jsx","useContext","useMemo","createResponsiveAttributes","buildTransformationUrl","Fragment"],"mappings":";;;;;;;AAOO,IAAM,mBAAA,GAAsBA,oBAA+C,IAAI,CAAA;AAO/E,SAAS,oBAAA,CAAqB,EAAE,QAAA,EAAU,MAAA,EAAO,EAA8B;AACpF,EAAA,uBACEC,cAAA,CAAC,oBAAoB,QAAA,EAApB,EAA6B,OAAO,EAAC,MAAA,IACnC,QAAA,EACH,CAAA;AAEJ;ACyBO,SAAS,iBAAA,CAAkB;AAAA,EACI,GAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,eAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA;AAAA,EACA,gBAAA;AAAA,EACA,UAAA,GAAa,IAAA;AAAA,EACb,GAAG;AACP,CAAA,EAA2B;AAEzD,EAAA,MAAM,OAAA,GAAUC,iBAAW,mBAAmB,CAAA;AAG9C,EAAA,MAAM,UAAA,GAAaC,cAAQ,MAAM;AAC7B,IAAA,MAAM,YAAA,GAAe,OAAA,IAAW,OAAA,EAAS,MAAA,CAAO,OAAA;AAEhD,IAAA,MAAM,yBAAyB,eAAA,EAAiB,KAAA;AAEhD,IAAA,IAAI,UAAA,IAAc,CAAC,sBAAA,EAAwB;AACvC,MAAA,IAAI,SAAS,KAAA,EAAO;AAChB,QAAA,OAAA,CAAQ,IAAA;AAAA,UACJ;AAAA,SAEJ;AAAA,MACJ;AAEA,MAAA,OAAOC,+BAAA,CAA2B,KAAK,YAAA,EAAc;AAAA,QACjD,KAAA,EAAO,SAAS,CAAC,KAAA;AAAA,QACjB,KAAA;AAAA,QACA,iBAAA;AAAA,QACA,gBAAA;AAAA,QACA;AAAA,OACH,CAAA;AAAA,IACL;AACA,IAAA,OAAO;AAAA,MACH,KAAKC,2BAAA,CAAuB,EAAC,GAAA,EAAK,OAAA,EAAS,iBAAgB;AAAA,KAC/D;AAAA,EAEJ,CAAA,EAAG,CAAC,GAAA,EAAK,KAAA,EAAO,eAAA,EAAiB,iBAAA,EAAmB,gBAAA,EAAkB,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,MAAA,CAAO,OAAA,EAAS,UAAU,CAAC,CAAA;AAE1H,EAAA,uBACIJ,cAAAA,CAAAK,mBAAA,EAAA,EACI,QAAA,kBAAAL,cAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACG,GAAA,EAAK,WAAW,GAAA,IAAO,GAAA;AAAA,MACvB,QAAQ,UAAA,CAAW,MAAA;AAAA,MACnB,OAAO,UAAA,CAAW,KAAA;AAAA,MAClB,KAAA,EAAO,WAAW,KAAA,IAAS,KAAA;AAAA,MAC1B,GAAG;AAAA;AAAA,GACR,EACJ,CAAA;AAER","file":"index.cjs","sourcesContent":["import { createContext, type ReactNode } from 'react';\nimport type { PixelFiddlerConfig } from '@pixelfiddler/core';\n\nexport interface PixelFiddlerContextValue {\n config: PixelFiddlerConfig;\n}\n\nexport const PixelFiddlerContext = createContext<PixelFiddlerContextValue | null>(null);\n\nexport interface PixelFiddlerProviderProps {\n children: ReactNode;\n config: PixelFiddlerConfig;\n}\n\nexport function PixelFiddlerProvider({ children, config }: PixelFiddlerProviderProps) {\n return (\n <PixelFiddlerContext.Provider value={{config}}>\n {children}\n </PixelFiddlerContext.Provider>\n );\n}\n","import { ImgHTMLAttributes, useContext, useMemo } from 'react';\r\nimport { buildTransformationUrl, createResponsiveAttributes, TransformationOptions, } from '@pixelfiddler/core';\r\nimport { PixelFiddlerContext } from '../provider/pixel-fiddler-context';\r\n\r\nexport interface PixelFiddlerImageProps\r\n extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'width' | 'sizes'> {\r\n /** Src to your image - can be both relative or absolute.\r\n * If it's relative, it will be attached to baseUrl from config\r\n * If it's absolute, it will be left as is\r\n * */\r\n src: string\r\n /** This should be your baseURL endpoint for the source from PixelFiddle Dashboard. You can skip this property if\r\n * you either pass it in PixelFiddlerProvider or pass an absolute path to src property.\r\n *\r\n * */\r\n baseUrl?: string\r\n /**\r\n * The sizes attribute for responsive images (e.g., \"100vw\", \"(max-width: 768px) 100vw, 50vw\").\r\n * Required if no fixed width was provided, and you want the image to be responsive\r\n */\r\n sizes?: string;\r\n /**\r\n * Decides whether srcSet should be built automatically for responsive images. In case `width` is passed, this will result in srcSet with `x` (dpr) descriptor.\r\n *\r\n *\r\n * If you want responsiveness based on layout, then you must pass `sizes` property for this to function properly e.g `(max-width: 768px) 100vw, 50vw\")`\r\n * which will generate srcSet based on vw\r\n *\r\n *\r\n * Ignored if `transformation.width` is set.\r\n * @default true\r\n */\r\n responsive?: boolean\r\n /**\r\n * Display width in CSS pixels.\r\n */\r\n width?: number | `${number}`;\r\n /** Transformation options to apply */\r\n transformations?: TransformationOptions;\r\n /** Custom device breakpoints for responsive srcset */\r\n deviceBreakpoints?: number[];\r\n /** Custom image breakpoints for smaller images */\r\n imageBreakpoints?: number[];\r\n}\r\n\r\nexport function PixelFiddlerImage({\r\n src,\r\n sizes,\r\n width,\r\n transformations,\r\n baseUrl,\r\n deviceBreakpoints,\r\n imageBreakpoints,\r\n responsive = true,\r\n ...imgProps\r\n }: PixelFiddlerImageProps) {\r\n\r\n const context = useContext(PixelFiddlerContext);\r\n\r\n\r\n const imageAttrs = useMemo(() => {\r\n const finalBaseUrl = baseUrl || context?.config.baseUrl\r\n\r\n const hasWidthTransformation = transformations?.width\r\n\r\n if (responsive && !hasWidthTransformation) {\r\n if (width && sizes) {\r\n console.warn(\r\n '[PixelFiddlerImage] Both `width` and `sizes` were provided. ' +\r\n '`sizes` will be ignored and a fixed-width DPR srcSet will be generated.'\r\n );\r\n }\r\n\r\n return createResponsiveAttributes(src, finalBaseUrl, {\r\n width: width && +width,\r\n sizes,\r\n deviceBreakpoints,\r\n imageBreakpoints,\r\n transformations\r\n });\r\n }\r\n return {\r\n src: buildTransformationUrl({src, baseUrl, transformations}),\r\n };\r\n\r\n }, [src, sizes, transformations, deviceBreakpoints, imageBreakpoints, width, baseUrl, context?.config.baseUrl, responsive]);\r\n\r\n return (\r\n <>\r\n <img\r\n src={imageAttrs.src || src}\r\n srcSet={imageAttrs.srcSet}\r\n sizes={imageAttrs.sizes}\r\n width={imageAttrs.width || width}\r\n {...imgProps}\r\n />\r\n </>\r\n );\r\n}\r\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ImgHTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
import { TransformationOptions, PixelFiddlerConfig } from '@pixelfiddler/core';
|
|
4
|
+
export { BorderOptions, CropOptions, EffectOptions, FormatOptions, PixelFiddlerConfig, ResizeOptions, TextOptions, TransformationOptions, WatermarkOptions } from '@pixelfiddler/core';
|
|
5
|
+
|
|
6
|
+
interface PixelFiddlerImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'width' | 'sizes'> {
|
|
7
|
+
/** Src to your image - can be both relative or absolute.
|
|
8
|
+
* If it's relative, it will be attached to baseUrl from config
|
|
9
|
+
* If it's absolute, it will be left as is
|
|
10
|
+
* */
|
|
11
|
+
src: string;
|
|
12
|
+
/** This should be your baseURL endpoint for the source from PixelFiddle Dashboard. You can skip this property if
|
|
13
|
+
* you either pass it in PixelFiddlerProvider or pass an absolute path to src property.
|
|
14
|
+
*
|
|
15
|
+
* */
|
|
16
|
+
baseUrl?: string;
|
|
17
|
+
/**
|
|
18
|
+
* The sizes attribute for responsive images (e.g., "100vw", "(max-width: 768px) 100vw, 50vw").
|
|
19
|
+
* Required if no fixed width was provided, and you want the image to be responsive
|
|
20
|
+
*/
|
|
21
|
+
sizes?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Decides whether srcSet should be built automatically for responsive images. In case `width` is passed, this will result in srcSet with `x` (dpr) descriptor.
|
|
24
|
+
*
|
|
25
|
+
*
|
|
26
|
+
* If you want responsiveness based on layout, then you must pass `sizes` property for this to function properly e.g `(max-width: 768px) 100vw, 50vw")`
|
|
27
|
+
* which will generate srcSet based on vw
|
|
28
|
+
*
|
|
29
|
+
*
|
|
30
|
+
* Ignored if `transformation.width` is set.
|
|
31
|
+
* @default true
|
|
32
|
+
*/
|
|
33
|
+
responsive?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Display width in CSS pixels.
|
|
36
|
+
*/
|
|
37
|
+
width?: number | `${number}`;
|
|
38
|
+
/** Transformation options to apply */
|
|
39
|
+
transformations?: TransformationOptions;
|
|
40
|
+
/** Custom device breakpoints for responsive srcset */
|
|
41
|
+
deviceBreakpoints?: number[];
|
|
42
|
+
/** Custom image breakpoints for smaller images */
|
|
43
|
+
imageBreakpoints?: number[];
|
|
44
|
+
}
|
|
45
|
+
declare function PixelFiddlerImage({ src, sizes, width, transformations, baseUrl, deviceBreakpoints, imageBreakpoints, responsive, ...imgProps }: PixelFiddlerImageProps): react_jsx_runtime.JSX.Element;
|
|
46
|
+
|
|
47
|
+
interface PixelFiddlerContextValue {
|
|
48
|
+
config: PixelFiddlerConfig;
|
|
49
|
+
}
|
|
50
|
+
interface PixelFiddlerProviderProps {
|
|
51
|
+
children: ReactNode;
|
|
52
|
+
config: PixelFiddlerConfig;
|
|
53
|
+
}
|
|
54
|
+
declare function PixelFiddlerProvider({ children, config }: PixelFiddlerProviderProps): react_jsx_runtime.JSX.Element;
|
|
55
|
+
|
|
56
|
+
export { type PixelFiddlerContextValue, PixelFiddlerImage, type PixelFiddlerImageProps, PixelFiddlerProvider };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ImgHTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
import { TransformationOptions, PixelFiddlerConfig } from '@pixelfiddler/core';
|
|
4
|
+
export { BorderOptions, CropOptions, EffectOptions, FormatOptions, PixelFiddlerConfig, ResizeOptions, TextOptions, TransformationOptions, WatermarkOptions } from '@pixelfiddler/core';
|
|
5
|
+
|
|
6
|
+
interface PixelFiddlerImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'width' | 'sizes'> {
|
|
7
|
+
/** Src to your image - can be both relative or absolute.
|
|
8
|
+
* If it's relative, it will be attached to baseUrl from config
|
|
9
|
+
* If it's absolute, it will be left as is
|
|
10
|
+
* */
|
|
11
|
+
src: string;
|
|
12
|
+
/** This should be your baseURL endpoint for the source from PixelFiddle Dashboard. You can skip this property if
|
|
13
|
+
* you either pass it in PixelFiddlerProvider or pass an absolute path to src property.
|
|
14
|
+
*
|
|
15
|
+
* */
|
|
16
|
+
baseUrl?: string;
|
|
17
|
+
/**
|
|
18
|
+
* The sizes attribute for responsive images (e.g., "100vw", "(max-width: 768px) 100vw, 50vw").
|
|
19
|
+
* Required if no fixed width was provided, and you want the image to be responsive
|
|
20
|
+
*/
|
|
21
|
+
sizes?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Decides whether srcSet should be built automatically for responsive images. In case `width` is passed, this will result in srcSet with `x` (dpr) descriptor.
|
|
24
|
+
*
|
|
25
|
+
*
|
|
26
|
+
* If you want responsiveness based on layout, then you must pass `sizes` property for this to function properly e.g `(max-width: 768px) 100vw, 50vw")`
|
|
27
|
+
* which will generate srcSet based on vw
|
|
28
|
+
*
|
|
29
|
+
*
|
|
30
|
+
* Ignored if `transformation.width` is set.
|
|
31
|
+
* @default true
|
|
32
|
+
*/
|
|
33
|
+
responsive?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Display width in CSS pixels.
|
|
36
|
+
*/
|
|
37
|
+
width?: number | `${number}`;
|
|
38
|
+
/** Transformation options to apply */
|
|
39
|
+
transformations?: TransformationOptions;
|
|
40
|
+
/** Custom device breakpoints for responsive srcset */
|
|
41
|
+
deviceBreakpoints?: number[];
|
|
42
|
+
/** Custom image breakpoints for smaller images */
|
|
43
|
+
imageBreakpoints?: number[];
|
|
44
|
+
}
|
|
45
|
+
declare function PixelFiddlerImage({ src, sizes, width, transformations, baseUrl, deviceBreakpoints, imageBreakpoints, responsive, ...imgProps }: PixelFiddlerImageProps): react_jsx_runtime.JSX.Element;
|
|
46
|
+
|
|
47
|
+
interface PixelFiddlerContextValue {
|
|
48
|
+
config: PixelFiddlerConfig;
|
|
49
|
+
}
|
|
50
|
+
interface PixelFiddlerProviderProps {
|
|
51
|
+
children: ReactNode;
|
|
52
|
+
config: PixelFiddlerConfig;
|
|
53
|
+
}
|
|
54
|
+
declare function PixelFiddlerProvider({ children, config }: PixelFiddlerProviderProps): react_jsx_runtime.JSX.Element;
|
|
55
|
+
|
|
56
|
+
export { type PixelFiddlerContextValue, PixelFiddlerImage, type PixelFiddlerImageProps, PixelFiddlerProvider };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { createContext, useContext, useMemo } from 'react';
|
|
2
|
+
import { createResponsiveAttributes, buildTransformationUrl } from '@pixelfiddler/core';
|
|
3
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/components/pixel-fiddler-image.tsx
|
|
6
|
+
var PixelFiddlerContext = createContext(null);
|
|
7
|
+
function PixelFiddlerProvider({ children, config }) {
|
|
8
|
+
return /* @__PURE__ */ jsx(PixelFiddlerContext.Provider, { value: { config }, children });
|
|
9
|
+
}
|
|
10
|
+
function PixelFiddlerImage({
|
|
11
|
+
src,
|
|
12
|
+
sizes,
|
|
13
|
+
width,
|
|
14
|
+
transformations,
|
|
15
|
+
baseUrl,
|
|
16
|
+
deviceBreakpoints,
|
|
17
|
+
imageBreakpoints,
|
|
18
|
+
responsive = true,
|
|
19
|
+
...imgProps
|
|
20
|
+
}) {
|
|
21
|
+
const context = useContext(PixelFiddlerContext);
|
|
22
|
+
const imageAttrs = useMemo(() => {
|
|
23
|
+
const finalBaseUrl = baseUrl || context?.config.baseUrl;
|
|
24
|
+
const hasWidthTransformation = transformations?.width;
|
|
25
|
+
if (responsive && !hasWidthTransformation) {
|
|
26
|
+
if (width && sizes) {
|
|
27
|
+
console.warn(
|
|
28
|
+
"[PixelFiddlerImage] Both `width` and `sizes` were provided. `sizes` will be ignored and a fixed-width DPR srcSet will be generated."
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return createResponsiveAttributes(src, finalBaseUrl, {
|
|
32
|
+
width: width && +width,
|
|
33
|
+
sizes,
|
|
34
|
+
deviceBreakpoints,
|
|
35
|
+
imageBreakpoints,
|
|
36
|
+
transformations
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
src: buildTransformationUrl({ src, baseUrl, transformations })
|
|
41
|
+
};
|
|
42
|
+
}, [src, sizes, transformations, deviceBreakpoints, imageBreakpoints, width, baseUrl, context?.config.baseUrl, responsive]);
|
|
43
|
+
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
|
|
44
|
+
"img",
|
|
45
|
+
{
|
|
46
|
+
src: imageAttrs.src || src,
|
|
47
|
+
srcSet: imageAttrs.srcSet,
|
|
48
|
+
sizes: imageAttrs.sizes,
|
|
49
|
+
width: imageAttrs.width || width,
|
|
50
|
+
...imgProps
|
|
51
|
+
}
|
|
52
|
+
) });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { PixelFiddlerImage, PixelFiddlerProvider };
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
57
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider/pixel-fiddler-context.tsx","../src/components/pixel-fiddler-image.tsx"],"names":["jsx"],"mappings":";;;;;AAOO,IAAM,mBAAA,GAAsB,cAA+C,IAAI,CAAA;AAO/E,SAAS,oBAAA,CAAqB,EAAE,QAAA,EAAU,MAAA,EAAO,EAA8B;AACpF,EAAA,uBACE,GAAA,CAAC,oBAAoB,QAAA,EAApB,EAA6B,OAAO,EAAC,MAAA,IACnC,QAAA,EACH,CAAA;AAEJ;ACyBO,SAAS,iBAAA,CAAkB;AAAA,EACI,GAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,eAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA;AAAA,EACA,gBAAA;AAAA,EACA,UAAA,GAAa,IAAA;AAAA,EACb,GAAG;AACP,CAAA,EAA2B;AAEzD,EAAA,MAAM,OAAA,GAAU,WAAW,mBAAmB,CAAA;AAG9C,EAAA,MAAM,UAAA,GAAa,QAAQ,MAAM;AAC7B,IAAA,MAAM,YAAA,GAAe,OAAA,IAAW,OAAA,EAAS,MAAA,CAAO,OAAA;AAEhD,IAAA,MAAM,yBAAyB,eAAA,EAAiB,KAAA;AAEhD,IAAA,IAAI,UAAA,IAAc,CAAC,sBAAA,EAAwB;AACvC,MAAA,IAAI,SAAS,KAAA,EAAO;AAChB,QAAA,OAAA,CAAQ,IAAA;AAAA,UACJ;AAAA,SAEJ;AAAA,MACJ;AAEA,MAAA,OAAO,0BAAA,CAA2B,KAAK,YAAA,EAAc;AAAA,QACjD,KAAA,EAAO,SAAS,CAAC,KAAA;AAAA,QACjB,KAAA;AAAA,QACA,iBAAA;AAAA,QACA,gBAAA;AAAA,QACA;AAAA,OACH,CAAA;AAAA,IACL;AACA,IAAA,OAAO;AAAA,MACH,KAAK,sBAAA,CAAuB,EAAC,GAAA,EAAK,OAAA,EAAS,iBAAgB;AAAA,KAC/D;AAAA,EAEJ,CAAA,EAAG,CAAC,GAAA,EAAK,KAAA,EAAO,eAAA,EAAiB,iBAAA,EAAmB,gBAAA,EAAkB,KAAA,EAAO,OAAA,EAAS,OAAA,EAAS,MAAA,CAAO,OAAA,EAAS,UAAU,CAAC,CAAA;AAE1H,EAAA,uBACIA,GAAAA,CAAA,QAAA,EAAA,EACI,QAAA,kBAAAA,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACG,GAAA,EAAK,WAAW,GAAA,IAAO,GAAA;AAAA,MACvB,QAAQ,UAAA,CAAW,MAAA;AAAA,MACnB,OAAO,UAAA,CAAW,KAAA;AAAA,MAClB,KAAA,EAAO,WAAW,KAAA,IAAS,KAAA;AAAA,MAC1B,GAAG;AAAA;AAAA,GACR,EACJ,CAAA;AAER","file":"index.js","sourcesContent":["import { createContext, type ReactNode } from 'react';\nimport type { PixelFiddlerConfig } from '@pixelfiddler/core';\n\nexport interface PixelFiddlerContextValue {\n config: PixelFiddlerConfig;\n}\n\nexport const PixelFiddlerContext = createContext<PixelFiddlerContextValue | null>(null);\n\nexport interface PixelFiddlerProviderProps {\n children: ReactNode;\n config: PixelFiddlerConfig;\n}\n\nexport function PixelFiddlerProvider({ children, config }: PixelFiddlerProviderProps) {\n return (\n <PixelFiddlerContext.Provider value={{config}}>\n {children}\n </PixelFiddlerContext.Provider>\n );\n}\n","import { ImgHTMLAttributes, useContext, useMemo } from 'react';\r\nimport { buildTransformationUrl, createResponsiveAttributes, TransformationOptions, } from '@pixelfiddler/core';\r\nimport { PixelFiddlerContext } from '../provider/pixel-fiddler-context';\r\n\r\nexport interface PixelFiddlerImageProps\r\n extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'src' | 'width' | 'sizes'> {\r\n /** Src to your image - can be both relative or absolute.\r\n * If it's relative, it will be attached to baseUrl from config\r\n * If it's absolute, it will be left as is\r\n * */\r\n src: string\r\n /** This should be your baseURL endpoint for the source from PixelFiddle Dashboard. You can skip this property if\r\n * you either pass it in PixelFiddlerProvider or pass an absolute path to src property.\r\n *\r\n * */\r\n baseUrl?: string\r\n /**\r\n * The sizes attribute for responsive images (e.g., \"100vw\", \"(max-width: 768px) 100vw, 50vw\").\r\n * Required if no fixed width was provided, and you want the image to be responsive\r\n */\r\n sizes?: string;\r\n /**\r\n * Decides whether srcSet should be built automatically for responsive images. In case `width` is passed, this will result in srcSet with `x` (dpr) descriptor.\r\n *\r\n *\r\n * If you want responsiveness based on layout, then you must pass `sizes` property for this to function properly e.g `(max-width: 768px) 100vw, 50vw\")`\r\n * which will generate srcSet based on vw\r\n *\r\n *\r\n * Ignored if `transformation.width` is set.\r\n * @default true\r\n */\r\n responsive?: boolean\r\n /**\r\n * Display width in CSS pixels.\r\n */\r\n width?: number | `${number}`;\r\n /** Transformation options to apply */\r\n transformations?: TransformationOptions;\r\n /** Custom device breakpoints for responsive srcset */\r\n deviceBreakpoints?: number[];\r\n /** Custom image breakpoints for smaller images */\r\n imageBreakpoints?: number[];\r\n}\r\n\r\nexport function PixelFiddlerImage({\r\n src,\r\n sizes,\r\n width,\r\n transformations,\r\n baseUrl,\r\n deviceBreakpoints,\r\n imageBreakpoints,\r\n responsive = true,\r\n ...imgProps\r\n }: PixelFiddlerImageProps) {\r\n\r\n const context = useContext(PixelFiddlerContext);\r\n\r\n\r\n const imageAttrs = useMemo(() => {\r\n const finalBaseUrl = baseUrl || context?.config.baseUrl\r\n\r\n const hasWidthTransformation = transformations?.width\r\n\r\n if (responsive && !hasWidthTransformation) {\r\n if (width && sizes) {\r\n console.warn(\r\n '[PixelFiddlerImage] Both `width` and `sizes` were provided. ' +\r\n '`sizes` will be ignored and a fixed-width DPR srcSet will be generated.'\r\n );\r\n }\r\n\r\n return createResponsiveAttributes(src, finalBaseUrl, {\r\n width: width && +width,\r\n sizes,\r\n deviceBreakpoints,\r\n imageBreakpoints,\r\n transformations\r\n });\r\n }\r\n return {\r\n src: buildTransformationUrl({src, baseUrl, transformations}),\r\n };\r\n\r\n }, [src, sizes, transformations, deviceBreakpoints, imageBreakpoints, width, baseUrl, context?.config.baseUrl, responsive]);\r\n\r\n return (\r\n <>\r\n <img\r\n src={imageAttrs.src || src}\r\n srcSet={imageAttrs.srcSet}\r\n sizes={imageAttrs.sizes}\r\n width={imageAttrs.width || width}\r\n {...imgProps}\r\n />\r\n </>\r\n );\r\n}\r\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pixelfiddler/react",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "React components for PixelFiddler image transformation SDK",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@pixelfiddler/core": "1.0.0"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"react": ">=18.0.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@testing-library/react": "^16.3.2",
|
|
32
|
+
"@types/react": "^18.2.0",
|
|
33
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
34
|
+
"jsdom": "^27.4.0",
|
|
35
|
+
"react": "^18.3.1",
|
|
36
|
+
"react-dom": "18",
|
|
37
|
+
"tsup": "^8.0.1",
|
|
38
|
+
"typescript": "^5.3.3",
|
|
39
|
+
"vitest": "^4.0.18"
|
|
40
|
+
},
|
|
41
|
+
"keywords": [
|
|
42
|
+
"pixelfiddler",
|
|
43
|
+
"react",
|
|
44
|
+
"image",
|
|
45
|
+
"transformation",
|
|
46
|
+
"cdn",
|
|
47
|
+
"optimization",
|
|
48
|
+
"component"
|
|
49
|
+
],
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"author": "PixelFiddler",
|
|
52
|
+
"homepage": "https://pixel-fiddler.com",
|
|
53
|
+
"bugs": {
|
|
54
|
+
"url": "https://github.com/pixel-fiddler/js-sdk/issues"
|
|
55
|
+
},
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "git+https://github.com/pixel-fiddler/js-sdk.git",
|
|
59
|
+
"directory": "packages/react"
|
|
60
|
+
},
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public"
|
|
63
|
+
},
|
|
64
|
+
"engines": {
|
|
65
|
+
"node": ">=18"
|
|
66
|
+
},
|
|
67
|
+
"sideEffects": false,
|
|
68
|
+
"scripts": {
|
|
69
|
+
"build": "tsup",
|
|
70
|
+
"dev": "tsup --watch",
|
|
71
|
+
"test": "vitest run",
|
|
72
|
+
"test:watch": "vitest",
|
|
73
|
+
"test:coverage": "vitest run --coverage",
|
|
74
|
+
"typecheck": "tsc --noEmit",
|
|
75
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
76
|
+
"clean": "rm -rf dist coverage"
|
|
77
|
+
}
|
|
78
|
+
}
|