mui-image-alter 3.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.md ADDED
@@ -0,0 +1,17 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2022 [benmneb](https://github.com/benmneb/)
4
+
5
+ Copyright (c) 2023 [mddanish00](https://github.com/mddanish00)
6
+
7
+ Permission to use, copy, modify, and/or distribute this software for any
8
+ purpose with or without fee is hereby granted, provided that the above
9
+ copyright notice and this permission notice appear in all copies.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,355 @@
1
+ <div align="center">
2
+ <h1><span>🌅</span><br /><code>mui-image-alter</code></h1>
3
+ </div>
4
+ <p align="center">
5
+ The another Material UI image component to satisfy the Material Design guidelines for loading images.
6
+ </p>
7
+ <div align="center">
8
+
9
+ ![GitHub License](https://img.shields.io/github/license/mddanish00/mui-image-alter?style=flat-square) ![npm](https://img.shields.io/npm/v/mui-image-alter?style=flat-square) ![npm bundle size](https://img.shields.io/bundlephobia/minzip/mui-image-alter%40latest?style=flat-square) ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/mddanish00/mui-image-alter/test.yml?style=flat-square) ![Coverage from badge.yml](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/mddanish00/83c2a74197bb80b661019a2747e71daa/raw/mui-image-alter_coverage__main.json) [![Buy Me A Coffee](https://img.shields.io/badge/mddanish00-black?style=flat-square&logo=buymeacoffee&logoColor=black&label=Buy%20Me%20A%20Coffee&labelColor=%23FFDD00)](https://www.buymeacoffee.com/mddanish00)
10
+
11
+ </div>
12
+ <p align="center">
13
+ The <b>fork</b> by mddanish00. Original project <a href="https://github.com/benmneb/mui-image">here</a>.
14
+ </p>
15
+ <p align="center">
16
+ <strong><a href="https://mddanish00.github.io/mui-image-alter/">Demo Playground ↗️</a></strong> <br />
17
+ </p>
18
+
19
+ ### If you're already using [Material UI v5](https://material-ui.com), why not display your images according to the Material guidelines too?
20
+
21
+ > Illustrations and photographs may load and transition in three phases at staggered durations, rather than relying on opacity changes alone.
22
+ >
23
+ > Visualize the image fading in, like a print during the photo development process.
24
+ >
25
+ > \- [Material guidelines](https://material.io/archive/guidelines/patterns/loading-images.html#loading-images-usage)
26
+
27
+ ## About the fork
28
+
29
+ Alter from alternative.
30
+
31
+ I actually just to make a fork with small modification for my website but somehow I ended changed many things... How it became like this?
32
+
33
+ ### Why should I use this?
34
+
35
+ If you satisfied with original project, you probably not need this. This is for users with a specific need.
36
+
37
+ To put it simply, you only needed this if:
38
+
39
+ - You want to change the component root element, `img` with other component like `Image` from `next/image`.
40
+ - You want to use `styled` function from `styled-components` or `emotion` or `MUI` on `Image` component but noticed some style not working properly.[^1]
41
+
42
+ [^1]: This happen on original project because the styles set using style prop. To correct this for original project, you need to use style or wrapperStyle or iconWrapperStyle that provided to overwrite the default style.
43
+
44
+ ### Changes in this fork
45
+
46
+ - Breaking Changes
47
+ - Height and width prop forwarded to the component root element (by default, `img`) instead of using CSS to set height and width of component wrapper element. Some alternate image components like `next/image` actually need for height and width prop.
48
+ - Put all styles that set though style prop in styled for better compability with MUI's styled.
49
+ - No UMD build. Go post an issue if you want UMD to be added.
50
+ - Only named exports. Read this [article](https://esbuild.github.io/content-types/#default-interop).
51
+
52
+ - Other Changes
53
+ - Rewritten fully in Typescript with types built-in based on MUI component types.
54
+ - Add support to MUI's component prop; That's means you can subtitute component root element with `Image` from `next/image` if you want. Component supported are `img`, `img`-derived HTML element and component with `src` prop.
55
+ - Properly export esm and cjs build via package.json exports.
56
+
57
+ - Development Changes
58
+ - Use Vite instead of nwb for development and building the library for fast and better developer experience for me!
59
+ - Added unit tests for testing mui-image-alter component. Also, added new Github Action that will automatically run these tests every pull request.
60
+
61
+ ## Simple Q & A
62
+
63
+ - **Q**: Why you created this fork?
64
+ **A**: MUI's styled don't work very well with the original mui-image because some of default styling and it use style prop instead of using styled to set some of the styling. So, I want to modify a little bit... And I end up doing at lot.
65
+ Originally, I want to just post an issue for this but I am suck in comunication. 😅
66
+
67
+ - **Q**: Why you change nwb to Vite?
68
+ **A**: I just wanted to fork for my own benefit. So, I thought maybe I can write this in TypeScript... but it don't work with nwb. I am so frustrated that I cannot find how to do it and try migarating to Vite instead. (Also, looks like nwb is abandoned too...) It took a lot of work but never thought it work so well...
69
+ Maybe there is actually a way to use Typescript with nwb but I never regret switching to Vite.
70
+
71
+ Vite is so fast!!! 😍
72
+
73
+ - **Q**: Will you intergrate changes from the original project?
74
+ **A**: Yeah. As many as possible. 💪
75
+
76
+ ---
77
+
78
+ ### 1. Install
79
+
80
+ Install the `mui-image-alter` peer dependencies first. (Can skip if you already done it.)
81
+
82
+ If you haven't yet install MUI, please follow the [official guide](https://mui.com/material-ui/getting-started/installation/).
83
+
84
+ Now, you can install the `mui-image-alter`.
85
+
86
+ #### Install from npm
87
+
88
+ ```bash
89
+ npm install mui-image-alter
90
+ ```
91
+
92
+ ```bash
93
+ yarn add mui-image-alter
94
+ ```
95
+
96
+ #### Install from repository
97
+
98
+ Recommended to specify a version tag like this for installation from the repository like below for stability.
99
+
100
+ ```bash
101
+ npm install github:mddanish00/mui-image-alter#vx.x.xx
102
+ ```
103
+
104
+ ```bash
105
+ yarn add mui-image-alter@github:mddanish00/mui-image-alter#vx.x.xx
106
+ ```
107
+
108
+ Replace `x.x.xx` with actual tags from [here](https://github.com/mddanish00/mui-image-alter/tags).
109
+
110
+ ### 2. Use
111
+
112
+ ```jsx
113
+ import { Image } from 'mui-image-alter';
114
+
115
+ // then
116
+
117
+ <Image src="my-image.png" />
118
+ ```
119
+
120
+ ### 3. Profit 💰
121
+
122
+ _Note: Profits not guaranteed and Material UI v5 is a peer dependency. If you need to support legacy versions of Material UI, use [`material-ui-image`](https://github.com/TeamWertarbyte/material-ui-image) instead. See the [comparison chart](#comparison-with-similar-components) below for more._
123
+
124
+ ## Usage Examples
125
+
126
+ You can use `mui-image-alter` like a regular image.
127
+
128
+ ```jsx
129
+ <Image src="my-image.png" />
130
+ ```
131
+
132
+ Except... it will fade and animate in as the Material guidelines recommend. 🤯
133
+
134
+ Apply the `showLoading` prop to add a progress indicator to let your fans know something amazing is coming. You can use the default MUI indicator or bring your own. 😎
135
+
136
+ ```jsx
137
+ <Image src="my-image.png" showLoading />
138
+ <Image src="my-image.bmp" showLoading={<MyCustomSpinner />} />
139
+ ```
140
+
141
+ If you want the image to fail silently you can disable the `errorIcon`, or you can add your own to suit your brand.
142
+
143
+ ```jsx
144
+ <Image src="my-cats.png" errorIcon={null} />
145
+ <Image src="my-dogs.png" errorIcon={<MyErrorIcon />} />
146
+ ```
147
+
148
+ If you want to _disobey Google_ 😵 then you can customise the animation and speed via the `duration` and `easing` props to any valid CSS property. Duration is always milliseconds.
149
+
150
+ ```jsx
151
+ <Image src="my-fish.png" duration={325} />
152
+ <Image src="my-bird.jpg" easing="ease-in-out" />
153
+ ```
154
+
155
+ To add that extra bit of spice 🌶 you can do exactly what Google suggests and apply a small position `shift` to images as they appear. The direction, distance, and duration (in milliseconds) are up to you.
156
+
157
+ ```jsx
158
+ <Image src="my-lawd.png" shift="left" />
159
+ <Image src="my-gawd.jpg" shift="bottom" distance={300} />
160
+ <Image src="my-gosh.gif" shift="top" distance="2rem" shiftDuration={320} />
161
+ ```
162
+
163
+ And of course, you can style `mui-image` like you would a regular image... but with the addition of the MUI v5 `sx` prop and [all the benefits](https://mui.com/system/the-sx-prop/) it brings. 😏
164
+
165
+ ```jsx
166
+ <Image src="my-self.jpeg" style={{ borderRadius: 16 }} />
167
+ <Image src="my-wife.webp" className="custom-class" />
168
+ <Image src="my-exgf.tiff" sx={{ display: { sm: 'none', lg: 'inline' }}} />
169
+ ```
170
+
171
+ If you want to get fancy 💃 you can also add inline styles and additional `className`'s to the root wrapper `div` and loading/error icon wrapper `div`, or just target their default `className`'s. This allows for complete customisation of every aspect of the component.
172
+
173
+ ### Fork Exclusive Usage
174
+
175
+ With this fork, you can use MUI's styled normally like this. More info on MUI's [official doccumentation](https://mui.com/system/styled/).
176
+
177
+ ```ts
178
+ import { styled } from '@mui/material/styles';
179
+ import { Image } from 'mui-image-alter';
180
+
181
+ const customImage = styled(Image)({
182
+ margin: 0 auto;
183
+ max-width: 100%;
184
+ display: block;
185
+ max-height: 500px;
186
+ });
187
+ ```
188
+
189
+ You also can use composition to create custom components.
190
+
191
+ ```ts
192
+ import { Image, ImageProps } from 'mui-image-alter';
193
+
194
+ const customImage = ({ className, ...props }: MuiImageProps) => (
195
+ <Image className="some-custom-class" {...props} />
196
+ );
197
+ ```
198
+
199
+ You also can extend the props by importing props.
200
+
201
+ ```ts
202
+ import React from 'react';
203
+ import { Image, ImageProps } from 'mui-image-alter';
204
+
205
+ type CustomImageProps = ImageProps & {
206
+ customImage: string;
207
+ };
208
+
209
+ const customImage = ({ customImage, src, ...props }: CustomImageProps) => {
210
+ const imageSrc = () => {
211
+ if (customImage === 'grass') {
212
+ return 'https//www.picture.org/grass.png';
213
+ }
214
+
215
+ if (customImage === 'beach') {
216
+ return 'https//www.picture.org/beach.png';
217
+ }
218
+
219
+ return 'https//www.picture.org/none.png';
220
+ };
221
+ return <Image src={imageSrc()} {...props} />;
222
+ };
223
+ ```
224
+
225
+ You can also change the component root element like official MUI components. Only img or img-derived component are supported from time being.
226
+
227
+ ```ts
228
+ import React, { ElementType } from 'react';
229
+ import { Image, ImageProps } from 'mui-image-alter';
230
+ import NextImage from 'next/image';
231
+
232
+ type CustomImageProps = ImageProps<typeof NextImage> & {
233
+ customImage: string;
234
+ };
235
+
236
+ const customImage = ({
237
+ customImage,
238
+ src,
239
+ ...props
240
+ }: CustomImageProps) => {
241
+ const imageSrc = () => {
242
+ if (customImage === 'grass') {
243
+ return 'https//www.picture.org/grass.png';
244
+ }
245
+
246
+ if (customImage === 'beach') {
247
+ return 'https//www.picture.org/beach.png';
248
+ }
249
+
250
+ return 'https//www.picture.org/none.png';
251
+ };
252
+ return <Image src={imageSrc()} component={NextImage} {...props} />;
253
+ };
254
+ ```
255
+
256
+ Like and subscribe below for more. ⏬
257
+
258
+ ## Props
259
+
260
+ | Name | Type | Default | Description |
261
+ | -------------------- | ---------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
262
+ | alt | string | "" | Alternate text for the image, which is displayed if the image fails to load or is not available. This text is also used by screen readers to provide a textual representation of the image for users who are visually impaired. |
263
+ | bgColor | string | "inherit" | Background color of the image when it first loads. This can be used to create a smooth transition between the loading state and the fully-loaded image. |
264
+ | className | string | "" | Class name to be applied to the root element of the Image component. |
265
+ | distance | string / number | 100 | Distance (in any valid CSS length units) that the image should shift when it finishes loading. This prop is only used if the shift prop is set. Accept valid CSS [`length`](https://developer.mozilla.org/en-US/docs/Web/CSS/length#units) value. |
266
+ | duration | number | 3000 | Duration of the transition (in milliseconds) when the image finishes loading. This prop is used to set the transition-duration CSS property on the image. Accept valid CSS [`transition-duration`](https://developer.mozilla.org/en-US/docs/Web/CSS/transition-duration) in milliseconds. |
267
+ | easing | string | cubic-bezier(0.7, 0, 0.6, 1) | Easing function for the transition when the image finishes loading. This prop is used to set the transition-timing-function CSS property on the image. Accept valid CSS [`transition-timing-function`](https://developer.mozilla.org/en-US/docs/Web/CSS/transition-timing-function) value. |
268
+ | errorIcon | boolean / node | true | Whether or not to display an error icon when the image fails to load. If set to true, the default error icon will be displayed. If set to false, no error icon will be displayed. If set to a JSX element, the specified element will be displayed as the error icon. |
269
+ | fit | string | "contain" | How the image should be resized to fit within its container. Accept valid CSS [`object-fit`](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit#syntax) value. |
270
+ | iconWrapperClassName | string | "" | Class name to be applied to the `div` element that wraps the error or loading icon. This can be used to apply custom styles to the icon using CSS. |
271
+ | iconWrapperStyle | object | { } | Inline styles to be applied to the `div` element that wraps the error or loading icon. |
272
+ | position | string | "relative" | Positioning of the image within its container. Accept valid CSS [`position`](https://developer.mozilla.org/en-US/docs/Web/CSS/position) value. |
273
+ | shift | boolean / string | false | Direction in which the image should shift when it finishes loading. Possible values are "left", "right", "top", "bottom", null, or false. If set to null or false, no shift animation will be applied. |
274
+ | shiftDuration | number | duration \* 0.3 | Duration of the shift animation (in milliseconds) when the image finishes loading. This prop is only used if the shift prop is set to a valid shift direction. |
275
+ | showLoading | boolean / node | false | Whether or not to display a loading indicator while the image is loading. If set to true, the default loading indicator will be displayed. If set to false, no loading indicator will be displayed. If set to a JSX element, the specified element will be displayed as the loading indicator. |
276
+ | **_src_** \* | string | | Source of the image to be displayed. This value should be a valid URL or file path to the image. |
277
+ | style | object | | Inline styles to be applied to the root element of the Image component. |
278
+ | wrapperClassName | string | "" | Class name to be applied to the root `div` element that wraps the Image component. |
279
+ | wrapperStyle | object | | Inline styles to be applied to the root `div` element that wraps the Image component. |
280
+ | sx | object | | Allows the user to style the Image component using the theme and style props provided by the MUI library. Used in the same way as the sx prop in other MUI components. Check out [MUI official documentation](https://mui.com/system/getting-started/the-sx-prop/) of the `sx` prop. |
281
+ | component | string / node | | Allows the user to specify a custom element to use as the root element for the Image component. Used in the same way as the component prop in other MUI components. Should only be used with elements that are derived from the `img` element. |
282
+
283
+ \* required prop
284
+
285
+ Any other props (eg. `src`, `alt`, `onLoad`) are passed directly to the root image element like `img`.
286
+
287
+ All the description on this table are generated using ChatGPT and edited by me. 👍
288
+
289
+ ## Material guidelines for loading images
290
+
291
+ > #### ✅ Fade-in
292
+ >
293
+ > Visualize the image fading in, like a print during the photo development process.
294
+
295
+ > #### ✅ Opacity, exposure, and saturation recommendations
296
+ >
297
+ > Images should begin loading with low contrast levels and desaturated color. Once image opacity reaches 100%, display the image with full-color saturation.
298
+
299
+ > #### ✅ Duration
300
+ >
301
+ > A longer duration is recommended for loading images, and a shorter duration is recommended for transitions.
302
+
303
+ > #### ✅ Animation
304
+ >
305
+ > Add a small position shift to loading images.
306
+
307
+ [(Source)](https://material.io/archive/guidelines/patterns/loading-images.html#loading-images-behavior)
308
+
309
+ ## Comparison with similar components
310
+
311
+ | Feature | `mui-image` | `mui-image-alter` | `material-ui-image` |
312
+ | ----------------------------- | :------------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------: |
313
+ | Size (minzipped) | ![npm bundle size](https://img.shields.io/bundlephobia/minzip/mui-image?color=%2343a047&label=%20&style=flat-square) | ![npm bundle size](https://img.shields.io/bundlephobia/minzip/mui-image-alter?color=%23b71c1c&label=%20&style=flat-square) | ![npm bundle size](https://img.shields.io/bundlephobia/minzip/material-ui-image?color=%23b71c1c&label=%20&style=flat-square) |
314
+ | Supports MUI v5 | ✅ | ✅ | ❌ |
315
+ | Supports MUI component prop | ❌ | ✅ | ❌ |
316
+ | Built-in Typescript types | ❌ | ✅ | ❌ |
317
+ | Fade-in | ✅ | ✅ | ✅ |
318
+ | Progressive level adjustments | ✅ | ✅ | ❌ |
319
+ | Suggested duration | ✅ | ✅ | ✅ |
320
+ | Optional shift animation | ✅ | ✅ | ❌ |
321
+ | Supports legacy MUI versions | ❌ | ❌ | ✅ |
322
+
323
+ ## Like this project?
324
+
325
+ Star this project and also the original project too if it is useful for you.
326
+
327
+ Also, consider buying me a coffee!
328
+
329
+ [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/mddanish00)
330
+
331
+ ## License
332
+
333
+ Copyright (c) 2022 [benmneb](https://github.com/benmneb/)
334
+
335
+ Copyright (c) 2023 [mddanish00](https://github.com/mddanish00)
336
+
337
+ [ISC License](https://choosealicense.com/licenses/isc/)
338
+
339
+ Permission to use, copy, modify, and/or distribute this software for any
340
+ purpose with or without fee is hereby granted, provided that the above
341
+ copyright notice and this permission notice appear in all copies.
342
+
343
+ <!-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
344
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
345
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
346
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
347
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
348
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
349
+ PERFORMANCE OF THIS SOFTWARE. -->
350
+
351
+ ## Other License
352
+
353
+ The mui-image types from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) project is licensed under [MIT License](https://github.com/DefinitelyTyped/DefinitelyTyped/raw/master/LICENSE).
354
+
355
+ This component types structure based on types of components created by [Material UI](https://github.com/mui/material-ui) under [MIT License](https://github.com/mui/material-ui/blob/master/LICENSE).
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use client";"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react/jsx-runtime"),V=require("react"),m=require("@mui/material/styles"),G=require("@mui/material/SvgIcon"),J=require("@mui/material/CircularProgress"),K=require("clsx"),Q=require("use-resize-observer"),u=e=>e&&e.__esModule?e:{default:e};function U(e){if(e&&e.__esModule)return e;const i=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const a in e)if(a!=="default"){const r=Object.getOwnPropertyDescriptor(e,a);Object.defineProperty(i,a,r.get?r:{enumerable:!0,get:()=>e[a]})}}return i.default=e,Object.freeze(i)}const t=U(V),X=u(G),Y=u(J),h=u(K),Z=u(Q),p=e=>o.jsx(X.default,{...e,children:o.jsx("path",{d:"M21 5v6.59l-2.29-2.3c-.39-.39-1.03-.39-1.42 0L14 12.59 10.71 9.3a.9959.9959 0 0 0-1.41 0L6 12.59 3 9.58V5c0-1.1.9-2 2-2h14c1.1 0 2 .9 2 2zm-3 6.42 3 3.01V19c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2v-6.58l2.29 2.29c.39.39 1.02.39 1.41 0l3.3-3.3 3.29 3.29c.39.39 1.02.39 1.41 0l3.3-3.28z"})}),ee=t.forwardRef(({src:e,alt:i="",position:a="relative",fit:r="cover",style:I,className:S="",showLoading:l=!1,errorIcon:c=!0,shift:n=!1,distance:M=100,shiftDuration:z=void 0,bgColor:w="inherit",wrapperStyle:C,iconWrapperStyle:k,wrapperClassName:B="",iconWrapperClassName:O="",duration:q=3e3,easing:R="cubic-bezier(0.7, 0, 0.6, 1)",onLoad:f,onError:g,sx:W,component:$="img",...s},P)=>{const[d,b]=t.useState(!1),[y,j]=t.useState(!1),{ref:D,width:_,height:x}=Z.default({ref:P}),F=s.height?s.height:"100%",H=s.width?s.width:"100%",N=t.useCallback(()=>{b(!0),j(!1),f&&f()},[f]),A=t.useCallback(()=>{j(!0),b(!1),g&&g()},[g]),E=n!==void 0&&n!==!1&&n!==null?{[n]:d?0:M}:{},T=typeof c!="boolean"&&c||o.jsx(p,{sx:{fontSize:56,color:"#bdbdbd"}}),L=typeof l!="boolean"&&l||o.jsx(Y.default,{size:56,thickness:6});return o.jsxs(ie,{className:h.default("MuiImageAlter-wrapper",B),sx:W,style:C,bgColor:w,rootHeight:x||F,rootWidth:_||H,children:[o.jsx(te,{ref:D,as:$,src:e,alt:i,style:I,className:h.default("MuiImageAlter-img",S),onLoad:N,onError:A,position:a,fit:r,shift:n,shiftDuration:z,shiftStyles:E,duration:q,easing:R,loaded:d,...s}),(!!l||!!c)&&o.jsxs(oe,{className:h.default("MuiImageAlter-iconWrapper",O),style:k,loaded:d,children:[!!c&&y&&T,!!l&&!y&&!d&&L]})]})}),v=(e,i)=>!i.includes(e),te=t.memo(m.styled("img",{shouldForwardProp:e=>v(e.toString(),["position","fit","shift","shiftDuration","shiftStyles","duration","easing","loaded","sx","as"])})(e=>({"@keyframes materialize":{"0%":{filter:"saturate(20%) contrast(50%) brightness(120%)"},"75%":{filter:"saturate(60%) contrast(100%) brightness(100%)"},"100%":{filter:"saturate(100%) contrast(100%) brightness(100%)"}},position:e.position,objectFit:e.fit,transitionProperty:`${e.shift?`${e.shift}, `:""}opacity`,transitionDuration:`${e.shift?`${e.shiftDuration||e.duration*.3}ms, `:""}${e.duration/2}ms`,transitionTimingFunction:e.easing,opacity:e.loaded?1:0,animation:e.loaded?`materialize ${e.duration}ms 1 ${e.easing}`:"",...!!e.shift&&e.shiftStyles}))),ie=t.memo(m.styled("div",{shouldForwardProp:e=>v(e.toString(),["bgColor","sx","rootHeight","rootWidth"])})(e=>({display:"flex",justifyContent:"center",alignItems:"center",backgroundColor:e.bgColor,height:e.rootHeight,width:e.rootWidth}))),oe=t.memo(m.styled("div",{shouldForwardProp:e=>e!=="loaded"})(e=>({width:"100%",marginLeft:"-100%",display:"flex",justifyContent:"center",alignItems:"center",opacity:e.loaded?0:1})));exports.Image=ee;
@@ -0,0 +1,138 @@
1
+ /// <reference types="react" />
2
+
3
+ import { OverridableComponent } from '@mui/types';
4
+ import { OverridableTypeMap } from '@mui/types';
5
+ import { OverrideProps } from '@mui/types';
6
+ import { SxProps } from '@mui/material/styles';
7
+ import { Theme } from '@mui/material/styles';
8
+
9
+ /**
10
+ * A custom image component that satisfy the Material guidelines for loading images.
11
+ *
12
+ * Fork by mddanish00. Original by benmneb.
13
+ *
14
+ * API: https://github.com/mddanish00/mui-image/blob/master/README.md
15
+ */
16
+ declare const Image_2: MuiImage<ImageTypeMap>;
17
+ export { Image_2 as Image }
18
+
19
+ export declare type ImageProps<D extends React.ElementType = ImageTypeMap['defaultComponent'], P = {}> = OverrideProps<ImageTypeMap<P, D>, D>;
20
+
21
+ /**
22
+ * Based on MUI component types in @mui/material-next,
23
+ * Some of these props are directly copied from @types/mui-image.
24
+ *
25
+ * Below is the notice included in @types/mui-image:
26
+ *
27
+ * Type definitions for mui-image 1.0
28
+ *
29
+ * Project: https://github.com/benmneb/mui-image
30
+ *
31
+ * Definitions by: benmneb <https://github.com/benmneb>
32
+ *
33
+ * Definitions: https://github.com/DefinitelyTyped/mui-image
34
+ *
35
+ * (With a little help from Natalia <https://github.com/CodeMeNatalie>)
36
+ *
37
+ * All types packages by DefinitelyTyped licensed under MIT License.
38
+ */
39
+ declare type ImageTypeMap<P = {}, D extends React.ElementType = 'img'> = {
40
+ props: P & {
41
+ /**
42
+ * Text description of the image.
43
+ */
44
+ alt?: string;
45
+ /**
46
+ * Color the image transitions in from.
47
+ */
48
+ bgColor?: React.CSSProperties['backgroundColor'];
49
+ /**
50
+ * ClassName for the component image root element.
51
+ */
52
+ className?: string;
53
+ /**
54
+ * CSS length value for the shift animation.
55
+ */
56
+ distance?: string | number;
57
+ /**
58
+ * CSS transition-duration value.
59
+ * Duration of the transition when the image finishes loading.
60
+ */
61
+ duration?: number;
62
+ /**
63
+ * CSS transition-timing-function value.
64
+ * Easing function for the transition when the image finishes loading.
65
+ */
66
+ easing?: React.CSSProperties['transitionTimingFunction'];
67
+ /**
68
+ * Display default error icon or a custom one.
69
+ */
70
+ errorIcon?: boolean | React.ReactElement;
71
+ /**
72
+ * CSS object-fit value.
73
+ * Specifies how the image should be resized to fit within its container.
74
+ */
75
+ fit?: React.CSSProperties['objectFit'];
76
+ /**
77
+ * ClassName for the icon wrapper.
78
+ */
79
+ iconWrapperClassName?: string;
80
+ /**
81
+ * Inline styles for the icon wrapper.
82
+ */
83
+ iconWrapperStyle?: React.CSSProperties;
84
+ onError?: (...args: any[]) => void;
85
+ onLoad?: (...args: any[]) => void;
86
+ /**
87
+ * CSS position value.
88
+ * Specifies the positioning of the image within its container.
89
+ */
90
+ position?: React.CSSProperties['position'];
91
+ /**
92
+ * Direction for the shift animation.
93
+ */
94
+ shift?: 'left' | 'right' | 'top' | 'bottom' | false | null;
95
+ /**
96
+ * Duration of the shift animation in milliseconds.
97
+ */
98
+ shiftDuration?: number;
99
+ /**
100
+ * Display default loading spinner or a custom one.
101
+ */
102
+ showLoading?: boolean | React.ReactElement;
103
+ /**
104
+ * Path to the image.
105
+ * Should be a valid URL or file path to the image.
106
+ */
107
+ src: string;
108
+ /**
109
+ * Inline styles for the component image root element.
110
+ */
111
+ style?: React.CSSProperties;
112
+ /**
113
+ * The className for the root wrapper.
114
+ */
115
+ wrapperClassName?: string;
116
+ /**
117
+ * Inline styles for the root wrapper.
118
+ */
119
+ wrapperStyle?: React.CSSProperties;
120
+ /**
121
+ * Defining system overrides as well as additional CSS styles.
122
+ * Works same as official MUI components.
123
+ */
124
+ sx?: SxProps<Theme>;
125
+ };
126
+ defaultComponent: D;
127
+ };
128
+
129
+ /**
130
+ * A custom image component that satisfy the Material guidelines for loading images.
131
+ *
132
+ * Fork by mddanish00. Original by benmneb.
133
+ *
134
+ * API: https://github.com/mddanish00/mui-image/blob/master/README.md
135
+ */
136
+ declare type MuiImage<M extends OverridableTypeMap> = OverridableComponent<M>;
137
+
138
+ export { }
@@ -0,0 +1,138 @@
1
+ /// <reference types="react" />
2
+
3
+ import { OverridableComponent } from '@mui/types';
4
+ import { OverridableTypeMap } from '@mui/types';
5
+ import { OverrideProps } from '@mui/types';
6
+ import { SxProps } from '@mui/material/styles';
7
+ import { Theme } from '@mui/material/styles';
8
+
9
+ /**
10
+ * A custom image component that satisfy the Material guidelines for loading images.
11
+ *
12
+ * Fork by mddanish00. Original by benmneb.
13
+ *
14
+ * API: https://github.com/mddanish00/mui-image/blob/master/README.md
15
+ */
16
+ declare const Image_2: MuiImage<ImageTypeMap>;
17
+ export { Image_2 as Image }
18
+
19
+ export declare type ImageProps<D extends React.ElementType = ImageTypeMap['defaultComponent'], P = {}> = OverrideProps<ImageTypeMap<P, D>, D>;
20
+
21
+ /**
22
+ * Based on MUI component types in @mui/material-next,
23
+ * Some of these props are directly copied from @types/mui-image.
24
+ *
25
+ * Below is the notice included in @types/mui-image:
26
+ *
27
+ * Type definitions for mui-image 1.0
28
+ *
29
+ * Project: https://github.com/benmneb/mui-image
30
+ *
31
+ * Definitions by: benmneb <https://github.com/benmneb>
32
+ *
33
+ * Definitions: https://github.com/DefinitelyTyped/mui-image
34
+ *
35
+ * (With a little help from Natalia <https://github.com/CodeMeNatalie>)
36
+ *
37
+ * All types packages by DefinitelyTyped licensed under MIT License.
38
+ */
39
+ declare type ImageTypeMap<P = {}, D extends React.ElementType = 'img'> = {
40
+ props: P & {
41
+ /**
42
+ * Text description of the image.
43
+ */
44
+ alt?: string;
45
+ /**
46
+ * Color the image transitions in from.
47
+ */
48
+ bgColor?: React.CSSProperties['backgroundColor'];
49
+ /**
50
+ * ClassName for the component image root element.
51
+ */
52
+ className?: string;
53
+ /**
54
+ * CSS length value for the shift animation.
55
+ */
56
+ distance?: string | number;
57
+ /**
58
+ * CSS transition-duration value.
59
+ * Duration of the transition when the image finishes loading.
60
+ */
61
+ duration?: number;
62
+ /**
63
+ * CSS transition-timing-function value.
64
+ * Easing function for the transition when the image finishes loading.
65
+ */
66
+ easing?: React.CSSProperties['transitionTimingFunction'];
67
+ /**
68
+ * Display default error icon or a custom one.
69
+ */
70
+ errorIcon?: boolean | React.ReactElement;
71
+ /**
72
+ * CSS object-fit value.
73
+ * Specifies how the image should be resized to fit within its container.
74
+ */
75
+ fit?: React.CSSProperties['objectFit'];
76
+ /**
77
+ * ClassName for the icon wrapper.
78
+ */
79
+ iconWrapperClassName?: string;
80
+ /**
81
+ * Inline styles for the icon wrapper.
82
+ */
83
+ iconWrapperStyle?: React.CSSProperties;
84
+ onError?: (...args: any[]) => void;
85
+ onLoad?: (...args: any[]) => void;
86
+ /**
87
+ * CSS position value.
88
+ * Specifies the positioning of the image within its container.
89
+ */
90
+ position?: React.CSSProperties['position'];
91
+ /**
92
+ * Direction for the shift animation.
93
+ */
94
+ shift?: 'left' | 'right' | 'top' | 'bottom' | false | null;
95
+ /**
96
+ * Duration of the shift animation in milliseconds.
97
+ */
98
+ shiftDuration?: number;
99
+ /**
100
+ * Display default loading spinner or a custom one.
101
+ */
102
+ showLoading?: boolean | React.ReactElement;
103
+ /**
104
+ * Path to the image.
105
+ * Should be a valid URL or file path to the image.
106
+ */
107
+ src: string;
108
+ /**
109
+ * Inline styles for the component image root element.
110
+ */
111
+ style?: React.CSSProperties;
112
+ /**
113
+ * The className for the root wrapper.
114
+ */
115
+ wrapperClassName?: string;
116
+ /**
117
+ * Inline styles for the root wrapper.
118
+ */
119
+ wrapperStyle?: React.CSSProperties;
120
+ /**
121
+ * Defining system overrides as well as additional CSS styles.
122
+ * Works same as official MUI components.
123
+ */
124
+ sx?: SxProps<Theme>;
125
+ };
126
+ defaultComponent: D;
127
+ };
128
+
129
+ /**
130
+ * A custom image component that satisfy the Material guidelines for loading images.
131
+ *
132
+ * Fork by mddanish00. Original by benmneb.
133
+ *
134
+ * API: https://github.com/mddanish00/mui-image/blob/master/README.md
135
+ */
136
+ declare type MuiImage<M extends OverridableTypeMap> = OverridableComponent<M>;
137
+
138
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,151 @@
1
+ "use client";
2
+ import { jsxs as I, jsx as a } from "react/jsx-runtime";
3
+ import * as e from "react";
4
+ import { styled as h } from "@mui/material/styles";
5
+ import G from "@mui/material/SvgIcon";
6
+ import J from "@mui/material/CircularProgress";
7
+ import m from "clsx";
8
+ import K from "use-resize-observer";
9
+ const Q = (t) => /* @__PURE__ */ a(G, { ...t, children: /* @__PURE__ */ a("path", { d: "M21 5v6.59l-2.29-2.3c-.39-.39-1.03-.39-1.42 0L14 12.59 10.71 9.3a.9959.9959 0 0 0-1.41 0L6 12.59 3 9.58V5c0-1.1.9-2 2-2h14c1.1 0 2 .9 2 2zm-3 6.42 3 3.01V19c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2v-6.58l2.29 2.29c.39.39 1.02.39 1.41 0l3.3-3.3 3.29 3.29c.39.39 1.02.39 1.41 0l3.3-3.28z" }) }), ot = e.forwardRef(
10
+ ({
11
+ src: t,
12
+ alt: l = "",
13
+ position: x = "relative",
14
+ fit: S = "cover",
15
+ style: w,
16
+ className: z = "",
17
+ showLoading: n = !1,
18
+ errorIcon: r = !0,
19
+ shift: i = !1,
20
+ distance: B = 100,
21
+ shiftDuration: C = void 0,
22
+ bgColor: k = "inherit",
23
+ wrapperStyle: M,
24
+ iconWrapperStyle: W,
25
+ wrapperClassName: $ = "",
26
+ iconWrapperClassName: j = "",
27
+ duration: F = 3e3,
28
+ easing: H = "cubic-bezier(0.7, 0, 0.6, 1)",
29
+ // "heavy move" from https://sprawledoctopus.com/easing/,
30
+ onLoad: c,
31
+ onError: d,
32
+ sx: R,
33
+ component: A = "img",
34
+ ...o
35
+ }, D) => {
36
+ const [s, f] = e.useState(!1), [u, g] = e.useState(!1), { ref: E, width: b, height: y } = K({ ref: D }), N = o.height ? o.height : "100%", L = o.width ? o.width : "100%", P = e.useCallback(() => {
37
+ f(!0), g(!1), c && c();
38
+ }, [c]), V = e.useCallback(() => {
39
+ g(!0), f(!1), d && d();
40
+ }, [d]), O = i !== void 0 && i !== !1 && i !== null ? {
41
+ [i]: s ? 0 : B
42
+ } : {}, T = typeof r != "boolean" && r || /* @__PURE__ */ a(Q, { sx: { fontSize: 56, color: "#bdbdbd" } }), q = typeof n != "boolean" && n || /* @__PURE__ */ a(J, { size: 56, thickness: 6 });
43
+ return /* @__PURE__ */ I(
44
+ X,
45
+ {
46
+ className: m("MuiImageAlter-wrapper", $),
47
+ sx: R,
48
+ style: M,
49
+ bgColor: k,
50
+ rootHeight: y || N,
51
+ rootWidth: b || L,
52
+ children: [
53
+ /* @__PURE__ */ a(
54
+ U,
55
+ {
56
+ ref: E,
57
+ as: A,
58
+ src: t,
59
+ alt: l,
60
+ style: w,
61
+ className: m("MuiImageAlter-img", z),
62
+ onLoad: P,
63
+ onError: V,
64
+ position: x,
65
+ fit: S,
66
+ shift: i,
67
+ shiftDuration: C,
68
+ shiftStyles: O,
69
+ duration: F,
70
+ easing: H,
71
+ loaded: s,
72
+ ...o
73
+ }
74
+ ),
75
+ (!!n || !!r) && /* @__PURE__ */ I(
76
+ Y,
77
+ {
78
+ className: m("MuiImageAlter-iconWrapper", j),
79
+ style: W,
80
+ loaded: s,
81
+ children: [
82
+ !!r && u && T,
83
+ !!n && !u && !s && q
84
+ ]
85
+ }
86
+ )
87
+ ]
88
+ }
89
+ );
90
+ }
91
+ ), v = (t, l) => !l.includes(t), U = e.memo(
92
+ h("img", {
93
+ shouldForwardProp: (t) => v(t.toString(), [
94
+ "position",
95
+ "fit",
96
+ "shift",
97
+ "shiftDuration",
98
+ "shiftStyles",
99
+ "duration",
100
+ "easing",
101
+ "loaded",
102
+ "sx",
103
+ "as"
104
+ ])
105
+ })((t) => ({
106
+ "@keyframes materialize": {
107
+ "0%": {
108
+ filter: "saturate(20%) contrast(50%) brightness(120%)"
109
+ },
110
+ "75%": {
111
+ filter: "saturate(60%) contrast(100%) brightness(100%)"
112
+ },
113
+ "100%": {
114
+ filter: "saturate(100%) contrast(100%) brightness(100%)"
115
+ }
116
+ },
117
+ position: t.position,
118
+ objectFit: t.fit,
119
+ transitionProperty: `${t.shift ? `${t.shift}, ` : ""}opacity`,
120
+ transitionDuration: `${t.shift ? `${t.shiftDuration || t.duration * 0.3}ms, ` : ""}${t.duration / 2}ms`,
121
+ transitionTimingFunction: t.easing,
122
+ opacity: t.loaded ? 1 : 0,
123
+ animation: t.loaded ? `materialize ${t.duration}ms 1 ${t.easing}` : "",
124
+ ...!!t.shift && t.shiftStyles
125
+ }))
126
+ ), X = e.memo(
127
+ h("div", {
128
+ shouldForwardProp: (t) => v(t.toString(), ["bgColor", "sx", "rootHeight", "rootWidth"])
129
+ })((t) => ({
130
+ display: "flex",
131
+ justifyContent: "center",
132
+ alignItems: "center",
133
+ backgroundColor: t.bgColor,
134
+ height: t.rootHeight,
135
+ width: t.rootWidth
136
+ }))
137
+ ), Y = e.memo(
138
+ h("div", {
139
+ shouldForwardProp: (t) => t !== "loaded"
140
+ })((t) => ({
141
+ width: "100%",
142
+ marginLeft: "-100%",
143
+ display: "flex",
144
+ justifyContent: "center",
145
+ alignItems: "center",
146
+ opacity: t.loaded ? 0 : 1
147
+ }))
148
+ );
149
+ export {
150
+ ot as Image
151
+ };
package/package.json ADDED
@@ -0,0 +1,100 @@
1
+ {
2
+ "name": "mui-image-alter",
3
+ "version": "3.0.0",
4
+ "description": "Fork of mui-image. Display images as per the Material guidelines using Material-UI v5. With component prop support.",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "types": "./dist/index.d.cts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.cts",
16
+ "default": "./dist/index.cjs"
17
+ }
18
+ }
19
+ },
20
+ "files": [
21
+ "dist"
22
+ ],
23
+ "scripts": {
24
+ "dev": "vite",
25
+ "build": "vite build",
26
+ "build:demo": "vite --config vite.democonfig.ts build",
27
+ "preview": "vite preview",
28
+ "size": "size-limit",
29
+ "format": "prettier {demo,src}/**/*.{js,jsx,ts,tsx,json} --write",
30
+ "clean": "rimraf dist es lib umd coverage jest-setup.d.ts mui-image-alter-*",
31
+ "prepare": "npm run build",
32
+ "preversion": "npm run clean && npm run format",
33
+ "postversion": "git push && git push --tags",
34
+ "test": "vitest run",
35
+ "test:watch": "vitest",
36
+ "test:coverage": "vitest run --coverage",
37
+ "test:coverage-ci": "vitest run --coverage.enabled --coverage.reporter='text-summary'"
38
+ },
39
+ "peerDependencies": {
40
+ "@mui/material": "^5.0.1",
41
+ "react": "^17.0.2 || ^18.0.0"
42
+ },
43
+ "devDependencies": {
44
+ "@emotion/react": "^11.11.1",
45
+ "@emotion/styled": "^11.11.0",
46
+ "@fontsource/fira-code": "^5.0.15",
47
+ "@mui/types": "^7.2.10",
48
+ "@size-limit/preset-small-lib": "^11.0.0",
49
+ "@testing-library/jest-dom": "^6.1.5",
50
+ "@testing-library/react": "^14.1.2",
51
+ "@types/react": "^18.2.42",
52
+ "@types/react-dom": "^18.2.17",
53
+ "@vitejs/plugin-react": "^4.2.1",
54
+ "@vitest/coverage-v8": "^0.34.6",
55
+ "jsdom": "^22.1.0",
56
+ "prettier": "^3.1.0",
57
+ "react-dom": "^18.2.0",
58
+ "rimraf": "^5.0.5",
59
+ "size-limit": "^11.0.0",
60
+ "typeit-react": "^2.7.0",
61
+ "typescript": "^5.3.2",
62
+ "vite": "^5.0.5",
63
+ "vite-plugin-dts": "^3.6.4",
64
+ "vitest": "^0.34.6"
65
+ },
66
+ "size-limit": [
67
+ {
68
+ "name": "cjs",
69
+ "path": "dist/index.cjs",
70
+ "gzip": true
71
+ },
72
+ {
73
+ "name": "esm",
74
+ "path": "dist/index.js",
75
+ "gzip": true
76
+ }
77
+ ],
78
+ "author": "mddanish00",
79
+ "contributors": [
80
+ "benmneb"
81
+ ],
82
+ "homepage": "https://mddanish00.github.io/mui-image-alter",
83
+ "license": "ISC",
84
+ "repository": {
85
+ "type": "git",
86
+ "url": "git+https://github.com/mddanish00/mui-image-alter.git"
87
+ },
88
+ "keywords": [
89
+ "material-ui",
90
+ "material-ui image",
91
+ "material-ui-image",
92
+ "material design",
93
+ "react",
94
+ "loading image"
95
+ ],
96
+ "dependencies": {
97
+ "clsx": "^2.0.0",
98
+ "use-resize-observer": "^9.1.0"
99
+ }
100
+ }