Skip to content

Commit cd0fe95

Browse files
ascorbicbertybotbertybot2benmccann
authored
feat: stable release (#748)
Co-authored-by: Bert B <44912991+bertybot@users.noreply.github.com> Co-authored-by: Bert Bengtson <RBengtson@ashleyfurniture.com> Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
1 parent b9ceb03 commit cd0fe95

File tree

120 files changed

+6076
-2895
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+6076
-2895
lines changed

.changeset/orange-books-know.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
"@unpic/svelte": major
3+
"@unpic/react": major
4+
"@unpic/core": major
5+
"@unpic/angular": major
6+
"@unpic/astro": major
7+
"@unpic/lit": major
8+
"@unpic/preact": major
9+
"@unpic/qwik": major
10+
"@unpic/solid": major
11+
"@unpic/vue": major
12+
"@unpic/webc": major
13+
---
14+
15+
Welcome to version 1.0.0 of Unpic! 🎉
16+
17+
This is a major update, with changes to the API of all frameworks. This will not
18+
affect you if you are just using the components with default options, but if you
19+
are passing custom transformers or specifying the CDN then you will need to
20+
update your code.
21+
22+
## Breaking changes
23+
24+
* The `cdnOptions` property has been removed. Use the new [`options` property](#provider-options)
25+
instead.
26+
* The `transformer` property has been removed from the default `Image` component. Import [the base component](#base-component) and specify the transformer there instead. The type signature for the transformer has also changed. See the `unpic` library documentation for more information.
27+
* The `cdn` property has been removed. Either use the new [`fallback` property](#fallback-providers) or import [the base component](#base-component) and pass a single provider to it.
28+
29+
30+
## Changes
31+
32+
Most of the changes are because of a new approach to handling individual image
33+
CDNs and providers in the base Unpic library. This is designed to make Unpic
34+
more flexible, efficient and modular. It also introduces support for
35+
type-safe custom operations and options for each provider.
36+
37+
### Provider operations
38+
39+
*Supported frameworks: All except `webc` and `lit`.*
40+
41+
The new `operations` property allows you to specify custom operations for each
42+
provider. Many image CDNs support dozens of custom operations. Previously these
43+
were hard to use with Unpic. The new `operations` property gives type-safe
44+
support for all supported features of each provider. This works even if you have
45+
images from multiple providers in the same component, as you can specify options
46+
for each provider separately.
47+
48+
```tsx
49+
<Image
50+
src="https://example.com/image.jpg"
51+
operations={{ imgix: { flip: "h" }, bunny: { flop: true } }}
52+
/>
53+
```
54+
55+
The operations are all type-safe, with JSDoc comments and TypeScript definitions
56+
for all supported operations. This means you can get autocompletion and type
57+
checking for all operations.
58+
59+
### Provider options
60+
61+
*Supported frameworks: All except `webc` and `lit`.*
62+
63+
The new `options` property allows you to specify custom options for each
64+
provider. This is similar to the current `cdnOptions` property, but with
65+
type-safe support for all options of each provider. This allows you to specify
66+
options such as account IDs and domains for each provider.
67+
68+
### Fallback providers
69+
70+
*Supported frameworks: All. The `astro` and `nextjs` frameworks default to
71+
the framework's image provider as fallback.*
72+
73+
The new `fallback` property allows you to specify a fallback provider for each
74+
image. This allows you to use auto-detection for image CDNs as now, but also
75+
specify a fallback provider for local images and images from unknown providers.
76+
This is useful if you have a mix of images from different sources, and want to
77+
ensure that all images are handled correctly. For example, you may have a
78+
Contentful blog hosted on Netlify, with images that are mostly hosted on
79+
Contentful (a supported CDN), but also some images from third-parties or your
80+
own server. You can specify Netlify as the fallback provider so that it uses the
81+
Netlify Image CDN for all images that are not from Contentful or another
82+
supported provider. This will be all handled automatically.
83+
84+
## Base component
85+
86+
*Supported frameworks: All except `webc`, `lit` and `angular`.*
87+
88+
Previously, the `Image` and `Source` components always loaded support for every
89+
provider, even if you specified a single provider or custom transformer. This is
90+
fine if you are using auto-detection, but many people wanted to use the
91+
components in a more custom or modular way. The new base components allow you to
92+
use the Unpic component without any of the automatic detection and transform
93+
logic. You can provide your own transformer, or use a single, tree-shakable
94+
provider import. This is useful if you are using a single provider, or if you
95+
are building a custom component based on Unpic.
96+
97+
```tsx
98+
// Import from the `/base` subpath
99+
import { Image } from "@unpic/react/base";
100+
// Import the transformer for the provider you are using
101+
import { transform } from "unpic/providers/imgix";
102+
103+
export const Hero = () => (
104+
<Image
105+
src="https://images.unsplash.com/photo-1734108039189-f6c123288381"
106+
transformer={transform}
107+
operations={{ sepia: 50 }}
108+
/>
109+
);
110+
```
111+
112+
The `operations` and `options` properties are still type-safe and inferred from
113+
the transformer, and you don't need to specify the provider name in the
114+
`operations` object.
115+

.changeset/shiny-worms-vanish.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@unpic/svelte": major
3+
---
4+
5+
Update to use Svelte 5 Runes syntax

.github/workflows/e2e.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
strategy:
1111
fail-fast: false
1212
matrix:
13-
site: [astro, preact, qwik, react, solid, webc]
13+
site: [astro, preact, qwik, react, solid, vue, webc]
1414
steps:
1515
- run: echo Running tests in ${{ matrix.site }}
1616
- name: Checkout
@@ -37,6 +37,7 @@ jobs:
3737
run: npx playwright test
3838
env:
3939
SITE: ${{ matrix.site }}
40+
NETLIFY: 1
4041
- name: Upload test report
4142
if: always()
4243
uses: actions/upload-artifact@v4

docs/package.json

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
},
1414
"dependencies": {
1515
"@algolia/client-search": "^5.14.0",
16-
"@astrojs/mdx": "^3.1.9",
17-
"@astrojs/preact": "^3.5.3",
18-
"@astrojs/react": "^3.6.2",
19-
"@astrojs/rss": "^4.0.9",
16+
"@astrojs/markdown-remark": "^6.0.2",
17+
"@astrojs/mdx": "^4.0.6",
18+
"@astrojs/preact": "^4.0.2",
19+
"@astrojs/react": "^4.1.5",
20+
"@astrojs/rss": "^4.0.11",
2021
"@astrojs/sitemap": "^3.2.1",
2122
"@docsearch/css": "^3.8.0",
2223
"@docsearch/react": "^3.8.0",
@@ -33,15 +34,17 @@
3334
"@unpic/astro": "workspace:^",
3435
"@unpic/placeholder": "^0.1.2",
3536
"@unpic/react": "workspace:^",
36-
"astro": "^4.16.12",
37+
"astro": "^5.1.7",
3738
"astro-icon": "^1.1.2",
3839
"blurhash": "^2.0.5",
3940
"pako": "^2.1.0",
4041
"preact": "^10.24.3",
4142
"prism-react-renderer": "^2.4.0",
4243
"react": "^18.3.1",
4344
"react-dom": "^18.3.1",
44-
"react-live": "^4.1.7"
45+
"react-live": "^4.1.7",
46+
"typescript": "^5.7.3",
47+
"unpic": "^4.0.0"
4548
},
4649
"devDependencies": {
4750
"@types/pako": "^2.0.3",
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Traffic advice for this domain
2+
# Version: 1.0
3+
# Last Updated: 2025-01-18
4+
5+
# No restrictions. All paths are permitted.

docs/public/make-scrollable-code-focusable.js

Lines changed: 0 additions & 3 deletions
This file was deleted.

docs/src/api.md

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,59 @@ visible if the image has transparency.
4242

4343
### `aspectRatio`
4444

45-
Instead of specifying both `width` and `height`, you can specify can
45+
Instead of specifying both `width` and `height`, you can specify an
4646
`aspectRatio`.
4747

48-
### `cdn`
48+
### `fallback`
4949

50-
By default the CDN is auto-detected from the `src` URL. If you want to override
51-
this, you can specify a CDN object. See the
52-
[unpic](https://github.com/ascorbic/unpic) for supported values.
50+
By default the CDN is auto-detected from the `src` URL, and if it can't be
51+
detected then it will use the source URL without transformation. You can specify
52+
a fallback provider here instead, and all images will use this provider if the
53+
CDN can't be detected. This is useful if you are using a platform that provides
54+
its own image CDN, or if you are using a provider that can transform remote
55+
images.
56+
57+
See the [the list of providers](/providers) for supported values.
58+
59+
### `operations`
60+
61+
This allows you to pass type-safe, provider-specific operations that will be
62+
performed on any images that use that provider. You can pass options for
63+
multiple providers if the images could come from different sources, and it will
64+
automatically apply the correct operations to each image, according to the
65+
detected provider.
66+
67+
In this example, we want the image to be flipped horizontally. The `imgix` and
68+
`bunny` providers both support this operation but with different names, so we
69+
can pass both options and they will be applied to the image as required.
70+
71+
```js
72+
{ imgix: { flip: "h" }, bunny: { flop: true } }}
73+
```
74+
75+
The supported operations are specific to each provider, and are type-checked and
76+
should provide autocompletion in your editor. See the
77+
[the provider docs](/providers) for the list of providers and their supported
78+
operations.
79+
80+
### `options`
81+
82+
This allows you to pass provider-specific options that will be used for any
83+
images that use that provider. These options are used to configure the provider,
84+
including account IDs, domains and other settings. You can pass options for
85+
multiple providers if the images could come from different sources, and it will
86+
automatically apply the correct options to each image, according to the detected
87+
provider. These do not need to be provided if all images have options set in the
88+
URLs themselves.
89+
90+
```js
91+
{ cloudinary: { cloudName: "demo" }, ipx: { baseUrl: "/_images" } }}
92+
```
93+
94+
The supported configuration options are specific to each provider, and are
95+
type-checked and should provide autocompletion in your editor. See the
96+
[the provider docs](/providers) for the list of providers and their supported
97+
options.
5398

5499
### `breakpoints`
55100

@@ -58,6 +103,10 @@ layout and image size. You can override this by specifying an array of
58103
breakpoints. The breakpoints are specified as an array of numbers, representing
59104
the width of the image in pixels.
60105

106+
```js
107+
[320, 640, 960, 1280];
108+
```
109+
61110
### Other props
62111

63112
Any prop supported by `<img>` tags can be passed in, except `srcset` which is
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/** @jsxImportSource react */
2+
import React from "react";
3+
import { LiveProvider, LiveEditor, LiveError, LivePreview } from "react-live";
4+
import { themes } from "prism-react-renderer";
5+
6+
interface CodeEditorProps {
7+
code: string;
8+
scope?: Record<string, unknown>;
9+
}
10+
11+
export const CodeEditor: React.FC<CodeEditorProps> = ({
12+
code,
13+
scope,
14+
}): JSX.Element => {
15+
return (
16+
<div style={{ marginTop: "1em" }}>
17+
<LiveProvider
18+
code={code}
19+
scope={{ ...scope }}
20+
theme={themes.dracula}
21+
noInline
22+
>
23+
<label
24+
style={{
25+
position: "absolute",
26+
transform: "translateX(8px)",
27+
background: "#98C379",
28+
color: "black",
29+
zIndex: 100,
30+
padding: "0 1em",
31+
fontSize: "80%",
32+
}}
33+
>
34+
Edit me!
35+
</label>
36+
<LiveEditor />
37+
<LiveError />
38+
<div
39+
style={{
40+
resize: "horizontal",
41+
overflow: "auto",
42+
maxWidth: "100%",
43+
border: "1px gray solid",
44+
marginTop: "1em",
45+
}}
46+
>
47+
<label
48+
style={{
49+
position: "absolute",
50+
transform: "translateX(8px)",
51+
background: "#98C379",
52+
color: "black",
53+
zIndex: 100,
54+
padding: "0 1em",
55+
fontSize: "80%",
56+
}}
57+
>
58+
Preview
59+
</label>
60+
<LivePreview
61+
style={{
62+
display: "grid",
63+
placeItems: "center",
64+
gap: "1em",
65+
overflow: "initial",
66+
paddingBottom: "0.5em",
67+
background: "white",
68+
}}
69+
/>
70+
</div>
71+
</LiveProvider>
72+
</div>
73+
);
74+
};

docs/src/components/HeadCommon.astro

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ import "../styles/index.css";
2626
href="https://fonts.googleapis.com/css2?family=Fira+Code&family=Fira+Sans:wght@400;600&display=swap"
2727
rel="stylesheet"
2828
/>
29-
<!-- Scrollable a11y code helper -->
30-
<script src="/make-scrollable-code-focusable.js" is:inline></script>
31-
3229
<!-- This is intentionally inlined to avoid FOUC -->
3330
<script is:inline>
3431
const root = document.documentElement;

docs/src/components/LeftSidebar/LeftSidebar.astro

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
---
2+
import { SupportedProviders } from "unpic";
23
import { SIDEBAR } from "../../consts";
34
import { Icon } from "astro-icon/components";
45
@@ -10,7 +11,21 @@ const { currentPage } = Astro.props;
1011
const currentPageMatch = currentPage.endsWith("/")
1112
? currentPage.slice(1, -1)
1213
: currentPage.slice(1);
13-
const sidebar = SIDEBAR;
14+
const sidebar = {
15+
...SIDEBAR,
16+
"Image providers": [
17+
{
18+
link: "providers",
19+
text: "Overview",
20+
},
21+
...Object.entries(SupportedProviders)
22+
.map(([link, text]) => ({
23+
link: `providers/${link}`,
24+
text,
25+
}))
26+
.sort((a, b) => a.text.localeCompare(b.text)),
27+
],
28+
};
1429
---
1530

1631
<nav aria-labelledby="grid-left">

0 commit comments

Comments
 (0)