@kushagradhawan/kookie-ui 0.1.13 → 0.1.15

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/components.css CHANGED
@@ -3254,7 +3254,7 @@
3254
3254
  }
3255
3255
  .rt-Card:where(.rt-variant-soft) {
3256
3256
  --card-border-width: 0px;
3257
- --card-background-color: var(--gray-a3);
3257
+ --card-background-color: var(--gray-a2);
3258
3258
  }
3259
3259
  .rt-Card:where(.rt-variant-soft)::before {
3260
3260
  background-color: var(--card-background-color);
@@ -3272,14 +3272,14 @@
3272
3272
  }
3273
3273
  @media (hover: hover) {
3274
3274
  .rt-Card:where(.rt-variant-soft):where(:any-link, button, label):where(:hover)::before {
3275
- background-color: var(--gray-a4);
3275
+ background-color: var(--gray-a3);
3276
3276
  }
3277
3277
  }
3278
3278
  .rt-Card:where(.rt-variant-soft):where(:any-link, button, label):where([data-state='open'])::before {
3279
- background-color: var(--gray-a4);
3279
+ background-color: var(--gray-a3);
3280
3280
  }
3281
3281
  .rt-Card:where(.rt-variant-soft):where(:any-link, button, label):where(:active:not([data-state='open']))::before {
3282
- background-color: var(--gray-a5);
3282
+ background-color: var(--gray-a4);
3283
3283
  }
3284
3284
  @media (pointer: coarse) {
3285
3285
  .rt-Card:where(:any-link, button, label):where(:active:not(:focus-visible, [data-state='open']))::before {
@@ -6198,6 +6198,9 @@
6198
6198
  .rt-r-shadow-6 {
6199
6199
  --box-shadow: var(--shadow-6);
6200
6200
  }
6201
+ .rt-Image--placeholder {
6202
+ z-index: 0;
6203
+ }
6201
6204
  .rt-Inset {
6202
6205
  box-sizing: border-box;
6203
6206
  --margin-top: 0px;
@@ -7,13 +7,30 @@ import type { HeightProps } from '../props/height.props.js';
7
7
  import type { GetPropDefTypes } from '../props/prop-def.js';
8
8
  type ImageOwnProps = GetPropDefTypes<typeof imagePropDefs> & {
9
9
  loading?: 'eager' | 'lazy';
10
+ /**
11
+ * Placeholder image URL to show while the main image is loading.
12
+ * Can be a low-quality/blurred version of the main image.
13
+ */
14
+ placeholder?: string;
15
+ /**
16
+ * Shows a skeleton placeholder while loading instead of a blank space.
17
+ */
18
+ showSkeleton?: boolean;
19
+ /**
20
+ * Callback fired when the image successfully loads.
21
+ */
22
+ onLoad?: (event: React.SyntheticEvent<HTMLImageElement>) => void;
23
+ /**
24
+ * Callback fired when the image fails to load.
25
+ */
26
+ onError?: (event: React.SyntheticEvent<HTMLImageElement>) => void;
10
27
  };
11
28
  interface ImageProps extends ComponentPropsWithout<'img', RemovedProps | 'color' | 'width' | 'height' | 'alt'>, MarginProps, WidthProps, HeightProps, ImageOwnProps {
12
29
  /**
13
30
  * The alt attribute provides alternative information for an image if a user for some reason cannot view it.
14
- * Required for accessibility when not using asChild.
31
+ * Required for accessibility when not using asChild. Use empty string for decorative images.
15
32
  */
16
- alt?: string;
33
+ alt: string;
17
34
  }
18
35
  declare const Image: React.ForwardRefExoticComponent<ImageProps & React.RefAttributes<HTMLImageElement>>;
19
36
  export { Image };
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/components/image.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMjD,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG5D,KAAK,aAAa,GAAG,eAAe,CAAC,OAAO,aAAa,CAAC,GAAG;IAC3D,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC5B,CAAC;AAEF,UAAU,UACR,SAAQ,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC,EACvF,WAAW,EACX,UAAU,EACV,WAAW,EACX,aAAa;IACf;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,QAAA,MAAM,KAAK,qFAsJT,CAAC;AAIH,OAAO,EAAE,KAAK,EAAE,CAAC;AACjB,YAAY,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/components/image.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOjD,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG5D,KAAK,aAAa,GAAG,eAAe,CAAC,OAAO,aAAa,CAAC,GAAG;IAC3D,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACjE;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;CACnE,CAAC;AAEF,UAAU,UACR,SAAQ,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC,EACvF,WAAW,EACX,UAAU,EACV,WAAW,EACX,aAAa;IACf;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,QAAA,MAAM,KAAK,qFA+PT,CAAC;AAIH,OAAO,EAAE,KAAK,EAAE,CAAC;AACjB,YAAY,EAAE,UAAU,EAAE,CAAC"}
@@ -1,2 +1,2 @@
1
- "use strict";"use client";var j=Object.create;var c=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var z=Object.getPrototypeOf,C=Object.prototype.hasOwnProperty;var W=(e,r)=>{for(var t in r)c(e,t,{get:r[t],enumerable:!0})},I=(e,r,t,f)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of w(r))!C.call(e,s)&&s!==t&&c(e,s,{get:()=>r[s],enumerable:!(f=k(r,s))||f.enumerable});return e};var P=(e,r,t)=>(t=e!=null?j(z(e)):{},I(r||!e||!e.__esModule?c(t,"default",{value:e,enumerable:!0}):t,e)),G=e=>I(c({},"__esModule",{value:!0}),e);var H={};W(H,{Image:()=>y});module.exports=G(H);var o=P(require("react")),a=P(require("classnames")),b=require("./image.props.js"),N=require("../helpers/extract-props.js"),v=require("../props/margin.props.js"),x=require("../props/width.props.js"),D=require("../props/height.props.js");const y=o.forwardRef((e,r)=>{const{variant:t="surface",fit:f="cover",children:s}=e,{asChild:E,className:p,radius:l,style:n,loading:m="lazy",alt:u,src:g,children:M,...d}=(0,N.extractProps)(e,b.imagePropDefs,v.marginPropDefs,x.widthPropDefs,D.heightPropDefs),h=o.createElement("img",{"data-radius":l,loading:m,style:n,className:(0,a.default)("rt-reset","rt-Image",t==="blur"&&"rt-Image--blur",p),alt:u,src:g,...d,ref:r});if(E&&s){const i=o.Children.only(s);return t==="blur"?o.cloneElement(i,{className:(0,a.default)(i.props?.className,"rt-variant-blur"),style:{position:"relative",display:"inline-block",textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...i.props?.style},children:o.createElement(o.Fragment,null,o.createElement("img",{"data-radius":l,loading:m,style:{...n,position:"absolute",top:"8px",left:"0"},className:(0,a.default)("rt-reset","rt-Image","rt-Image--blur","rt-Image--blur-bg",p),alt:"",src:g,...d}),o.createElement("img",{"data-radius":l,loading:m,style:{...n,position:"relative",zIndex:1},className:(0,a.default)("rt-reset","rt-Image","rt-Image--blur",p),alt:u,src:g,...d,ref:r}))}):o.cloneElement(i,{className:(0,a.default)(i.props?.className,"rt-Image"),style:{textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...i.props?.style},children:h})}return t==="blur"?o.createElement("div",{className:"rt-variant-blur",style:{position:"relative",display:"inline-block"}},o.createElement("img",{"data-radius":l,loading:m,style:{...n,position:"absolute",top:"8px",left:"0"},className:(0,a.default)("rt-reset","rt-Image","rt-Image--blur","rt-Image--blur-bg",p),alt:"",src:g,...d}),o.createElement("img",{"data-radius":l,loading:m,style:{...n,position:"relative",zIndex:1},className:(0,a.default)("rt-reset","rt-Image","rt-Image--blur",p),alt:u,src:g,...d,ref:r})):h});y.displayName="Image";
1
+ "use strict";"use client";var $=Object.create;var y=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var F=Object.getPrototypeOf,J=Object.prototype.hasOwnProperty;var K=(t,r)=>{for(var o in r)y(t,o,{get:r[o],enumerable:!0})},D=(t,r,o,d)=>{if(r&&typeof r=="object"||typeof r=="function")for(let i of B(r))!J.call(t,i)&&i!==o&&y(t,i,{get:()=>r[i],enumerable:!(d=A(r,i))||d.enumerable});return t};var C=(t,r,o)=>(o=t!=null?$(F(t)):{},D(r||!t||!t.__esModule?y(o,"default",{value:t,enumerable:!0}):o,t)),Q=t=>D(y({},"__esModule",{value:!0}),t);var R={};K(R,{Image:()=>P});module.exports=Q(R);var e=C(require("react")),s=C(require("classnames")),H=require("./image.props.js"),M=require("../helpers/extract-props.js"),T=require("../props/margin.props.js"),j=require("../props/width.props.js"),W=require("../props/height.props.js"),z=require("./skeleton.js");const P=e.forwardRef((t,r)=>{const{variant:o="surface",children:d}=t,{asChild:i,className:l,radius:n,style:p,loading:c="lazy",alt:u,src:m,placeholder:h,showSkeleton:E=!1,onLoad:v,onError:N,children:U,...g}=(0,M.extractProps)(t,H.imagePropDefs,T.marginPropDefs,j.widthPropDefs,W.heightPropDefs),[f,w]=e.useState(!1),[O,L]=e.useState(!1),[q,x]=e.useState(!!h),I=e.useCallback(a=>{w(!0),L(!1),x(!1),v?.(a)},[v]),b=e.useCallback(a=>{w(!1),L(!0),x(!1),N?.(a)},[N]);if(!m)return console.warn("Image component: src prop is required"),null;!i&&u===void 0&&console.warn("Image component: alt prop is required for accessibility when not using asChild");const G=E&&!f&&!O?e.createElement(z.Skeleton,{style:{...p,width:"100%",height:"100px",borderRadius:n?`var(--radius-${n})`:void 0},className:l}):null,_=h&&q?e.createElement("img",{"data-radius":n,style:{...p,position:"absolute",top:0,left:0,width:"100%",height:"100%",filter:"blur(4px)",opacity:.7,transition:"opacity 0.3s ease-out"},className:(0,s.default)("rt-reset","rt-Image","rt-Image--placeholder",l),alt:"",src:h}):null,k=e.createElement("img",{"data-radius":n,loading:c,style:{...p,opacity:f?1:0,transition:"opacity 0.3s ease-out"},className:(0,s.default)("rt-reset","rt-Image",o==="blur"&&"rt-Image--blur",l),alt:u,src:m,onLoad:I,onError:b,...g,ref:r}),S=h||E?e.createElement("div",{style:{position:"relative",display:"inline-block"}},G,_,k):k;if(i&&d){const a=e.Children.only(d);return o==="blur"?e.cloneElement(a,{className:(0,s.default)(a.props?.className,"rt-variant-blur"),style:{position:"relative",display:"inline-block",textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...a.props?.style},children:e.createElement(e.Fragment,null,e.createElement("img",{"data-radius":n,loading:c,style:{...p,position:"absolute",top:"8px",left:"0"},className:(0,s.default)("rt-reset","rt-Image","rt-Image--blur","rt-Image--blur-bg",l),alt:"",src:m,...g}),e.createElement("img",{"data-radius":n,loading:c,style:{...p,position:"relative",zIndex:1,opacity:f?1:0,transition:"opacity 0.3s ease-out"},className:(0,s.default)("rt-reset","rt-Image","rt-Image--blur",l),alt:u,src:m,onLoad:I,onError:b,...g,ref:r}))}):e.cloneElement(a,{className:(0,s.default)(a.props?.className,"rt-Image"),style:{textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...a.props?.style},children:S})}return o==="blur"?e.createElement("div",{className:"rt-variant-blur",style:{position:"relative",display:"inline-block"}},e.createElement("img",{"data-radius":n,loading:c,style:{...p,position:"absolute",top:"8px",left:"0"},className:(0,s.default)("rt-reset","rt-Image","rt-Image--blur","rt-Image--blur-bg",l),alt:"",src:m,...g}),e.createElement("img",{"data-radius":n,loading:c,style:{...p,position:"relative",zIndex:1,opacity:f?1:0,transition:"opacity 0.3s ease-out"},className:(0,s.default)("rt-reset","rt-Image","rt-Image--blur",l),alt:u,src:m,onLoad:I,onError:b,...g,ref:r})):S});P.displayName="Image";
2
2
  //# sourceMappingURL=image.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/image.tsx"],
4
- "sourcesContent": ["'use client';\n\nimport * as React from 'react';\nimport classNames from 'classnames';\n\nimport { imagePropDefs } from './image.props.js';\nimport { extractProps } from '../helpers/extract-props.js';\nimport { marginPropDefs } from '../props/margin.props.js';\nimport { widthPropDefs } from '../props/width.props.js';\nimport { heightPropDefs } from '../props/height.props.js';\n\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\nimport type { MarginProps } from '../props/margin.props.js';\nimport type { WidthProps } from '../props/width.props.js';\nimport type { HeightProps } from '../props/height.props.js';\nimport type { GetPropDefTypes } from '../props/prop-def.js';\n\ntype ImageElement = React.ElementRef<'img'>;\ntype ImageOwnProps = GetPropDefTypes<typeof imagePropDefs> & {\n loading?: 'eager' | 'lazy';\n};\n\ninterface ImageProps\n extends ComponentPropsWithout<'img', RemovedProps | 'color' | 'width' | 'height' | 'alt'>,\n MarginProps,\n WidthProps,\n HeightProps,\n ImageOwnProps {\n /**\n * The alt attribute provides alternative information for an image if a user for some reason cannot view it.\n * Required for accessibility when not using asChild.\n */\n alt?: string;\n}\n\nconst Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) => {\n const { variant = 'surface', fit: _fit = 'cover', children } = props;\n const {\n asChild,\n className,\n radius,\n style,\n loading = 'lazy',\n alt,\n src,\n children: _children, // Extract children to exclude from imgProps\n ...imgProps\n } = extractProps(props, imagePropDefs, marginPropDefs, widthPropDefs, heightPropDefs);\n\n // Create the standard img element\n const imgElement = (\n <img\n data-radius={radius}\n loading={loading}\n style={style}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n variant === 'blur' && 'rt-Image--blur',\n className,\n )}\n alt={alt}\n src={src}\n {...imgProps}\n ref={forwardedRef}\n />\n );\n\n // Handle asChild - inject img into the child element\n if (asChild && children) {\n const child = React.Children.only(children) as React.ReactElement<any>;\n\n if (variant === 'blur') {\n // For blur variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className, 'rt-variant-blur'),\n style: {\n position: 'relative',\n display: 'inline-block',\n textDecoration: 'none', // Reset link underlines\n color: 'inherit', // Reset link colors\n border: 'none', // Reset button borders\n background: 'none', // Reset button backgrounds\n padding: 0, // Reset button padding\n font: 'inherit', // Reset button fonts\n cursor: 'pointer', // Ensure interactive cursor\n ...child.props?.style,\n },\n children: (\n <>\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n ...style,\n position: 'absolute',\n top: '8px',\n left: '0',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n 'rt-Image--blur',\n 'rt-Image--blur-bg',\n className,\n )}\n alt=\"\"\n src={src}\n {...imgProps}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{ ...style, position: 'relative', zIndex: 1 }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n {...imgProps}\n ref={forwardedRef}\n />\n </>\n ),\n });\n } else {\n // For surface variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className, 'rt-Image'),\n style: {\n textDecoration: 'none', // Reset link underlines\n color: 'inherit', // Reset link colors\n border: 'none', // Reset button borders\n background: 'none', // Reset button backgrounds\n padding: 0, // Reset button padding\n font: 'inherit', // Reset button fonts\n cursor: 'pointer', // Ensure interactive cursor\n ...child.props?.style, // Allow user overrides\n },\n children: imgElement,\n });\n }\n }\n\n // Regular rendering without asChild\n if (variant === 'blur') {\n return (\n <div className=\"rt-variant-blur\" style={{ position: 'relative', display: 'inline-block' }}>\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n ...style,\n position: 'absolute',\n top: '8px',\n left: '0',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n 'rt-Image--blur',\n 'rt-Image--blur-bg',\n className,\n )}\n alt=\"\"\n src={src}\n {...imgProps}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{ ...style, position: 'relative', zIndex: 1 }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n {...imgProps}\n ref={forwardedRef}\n />\n </div>\n );\n }\n\n return imgElement;\n});\n\nImage.displayName = 'Image';\n\nexport { Image };\nexport type { ImageProps };\n"],
5
- "mappings": "ukBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,WAAAE,IAAA,eAAAC,EAAAH,GAEA,IAAAI,EAAuB,oBACvBC,EAAuB,yBAEvBC,EAA8B,4BAC9BC,EAA6B,uCAC7BC,EAA+B,oCAC/BC,EAA8B,mCAC9BC,EAA+B,oCA0B/B,MAAMR,EAAQE,EAAM,WAAqC,CAACO,EAAOC,IAAiB,CAChF,KAAM,CAAE,QAAAC,EAAU,UAAW,IAAKC,EAAO,QAAS,SAAAC,CAAS,EAAIJ,EACzD,CACJ,QAAAK,EACA,UAAAC,EACA,OAAAC,EACA,MAAAC,EACA,QAAAC,EAAU,OACV,IAAAC,EACA,IAAAC,EACA,SAAUC,EACV,GAAGC,CACL,KAAI,gBAAab,EAAO,gBAAe,iBAAgB,gBAAe,gBAAc,EAG9Ec,EACJrB,EAAA,cAAC,OACC,cAAac,EACb,QAASE,EACT,MAAOD,EACP,aAAW,EAAAO,SACT,WACA,WACAb,IAAY,QAAU,iBACtBI,CACF,EACA,IAAKI,EACL,IAAKC,EACJ,GAAGE,EACJ,IAAKZ,EACP,EAIF,GAAII,GAAWD,EAAU,CACvB,MAAMY,EAAQvB,EAAM,SAAS,KAAKW,CAAQ,EAE1C,OAAIF,IAAY,OAEPT,EAAM,aAAauB,EAAO,CAC/B,aAAW,EAAAD,SAAWC,EAAM,OAAO,UAAW,iBAAiB,EAC/D,MAAO,CACL,SAAU,WACV,QAAS,eACT,eAAgB,OAChB,MAAO,UACP,OAAQ,OACR,WAAY,OACZ,QAAS,EACT,KAAM,UACN,OAAQ,UACR,GAAGA,EAAM,OAAO,KAClB,EACA,SACEvB,EAAA,cAAAA,EAAA,cAEEA,EAAA,cAAC,OACC,cAAac,EACb,QAASE,EACT,MAAO,CACL,GAAGD,EACH,SAAU,WACV,IAAK,MACL,KAAM,GACR,EACA,aAAW,EAAAO,SACT,WACA,WACA,iBACA,oBACAT,CACF,EACA,IAAI,GACJ,IAAKK,EACJ,GAAGE,EACN,EAEApB,EAAA,cAAC,OACC,cAAac,EACb,QAASE,EACT,MAAO,CAAE,GAAGD,EAAO,SAAU,WAAY,OAAQ,CAAE,EACnD,aAAW,EAAAO,SAAW,WAAY,WAAY,iBAAkBT,CAAS,EACzE,IAAKI,EACL,IAAKC,EACJ,GAAGE,EACJ,IAAKZ,EACP,CACF,CAEJ,CAAC,EAGMR,EAAM,aAAauB,EAAO,CAC/B,aAAW,EAAAD,SAAWC,EAAM,OAAO,UAAW,UAAU,EACxD,MAAO,CACL,eAAgB,OAChB,MAAO,UACP,OAAQ,OACR,WAAY,OACZ,QAAS,EACT,KAAM,UACN,OAAQ,UACR,GAAGA,EAAM,OAAO,KAClB,EACA,SAAUF,CACZ,CAAC,CAEL,CAGA,OAAIZ,IAAY,OAEZT,EAAA,cAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,SAAU,WAAY,QAAS,cAAe,GAEtFA,EAAA,cAAC,OACC,cAAac,EACb,QAASE,EACT,MAAO,CACL,GAAGD,EACH,SAAU,WACV,IAAK,MACL,KAAM,GACR,EACA,aAAW,EAAAO,SACT,WACA,WACA,iBACA,oBACAT,CACF,EACA,IAAI,GACJ,IAAKK,EACJ,GAAGE,EACN,EAEApB,EAAA,cAAC,OACC,cAAac,EACb,QAASE,EACT,MAAO,CAAE,GAAGD,EAAO,SAAU,WAAY,OAAQ,CAAE,EACnD,aAAW,EAAAO,SAAW,WAAY,WAAY,iBAAkBT,CAAS,EACzE,IAAKI,EACL,IAAKC,EACJ,GAAGE,EACJ,IAAKZ,EACP,CACF,EAIGa,CACT,CAAC,EAEDvB,EAAM,YAAc",
6
- "names": ["image_exports", "__export", "Image", "__toCommonJS", "React", "import_classnames", "import_image_props", "import_extract_props", "import_margin_props", "import_width_props", "import_height_props", "props", "forwardedRef", "variant", "_fit", "children", "asChild", "className", "radius", "style", "loading", "alt", "src", "_children", "imgProps", "imgElement", "classNames", "child"]
4
+ "sourcesContent": ["'use client';\n\nimport * as React from 'react';\nimport classNames from 'classnames';\n\nimport { imagePropDefs } from './image.props.js';\nimport { extractProps } from '../helpers/extract-props.js';\nimport { marginPropDefs } from '../props/margin.props.js';\nimport { widthPropDefs } from '../props/width.props.js';\nimport { heightPropDefs } from '../props/height.props.js';\nimport { Skeleton } from './skeleton.js';\n\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\nimport type { MarginProps } from '../props/margin.props.js';\nimport type { WidthProps } from '../props/width.props.js';\nimport type { HeightProps } from '../props/height.props.js';\nimport type { GetPropDefTypes } from '../props/prop-def.js';\n\ntype ImageElement = React.ElementRef<'img'>;\ntype ImageOwnProps = GetPropDefTypes<typeof imagePropDefs> & {\n loading?: 'eager' | 'lazy';\n /**\n * Placeholder image URL to show while the main image is loading.\n * Can be a low-quality/blurred version of the main image.\n */\n placeholder?: string;\n /**\n * Shows a skeleton placeholder while loading instead of a blank space.\n */\n showSkeleton?: boolean;\n /**\n * Callback fired when the image successfully loads.\n */\n onLoad?: (event: React.SyntheticEvent<HTMLImageElement>) => void;\n /**\n * Callback fired when the image fails to load.\n */\n onError?: (event: React.SyntheticEvent<HTMLImageElement>) => void;\n};\n\ninterface ImageProps\n extends ComponentPropsWithout<'img', RemovedProps | 'color' | 'width' | 'height' | 'alt'>,\n MarginProps,\n WidthProps,\n HeightProps,\n ImageOwnProps {\n /**\n * The alt attribute provides alternative information for an image if a user for some reason cannot view it.\n * Required for accessibility when not using asChild. Use empty string for decorative images.\n */\n alt: string;\n}\n\nconst Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) => {\n const { variant = 'surface', children } = props;\n const {\n asChild,\n className,\n radius,\n style,\n loading = 'lazy',\n alt,\n src,\n placeholder,\n showSkeleton = false,\n onLoad: userOnLoad,\n onError: userOnError,\n children: _children, // Extract children to exclude from imgProps\n ...imgProps\n } = extractProps(props, imagePropDefs, marginPropDefs, widthPropDefs, heightPropDefs);\n\n // Loading state management\n const [imageLoaded, setImageLoaded] = React.useState(false);\n const [imageError, setImageError] = React.useState(false);\n const [showPlaceholder, setShowPlaceholder] = React.useState(!!placeholder);\n\n // Handle image load - moved to top to avoid conditional hook call\n const handleLoad = React.useCallback((event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(true);\n setImageError(false);\n setShowPlaceholder(false);\n userOnLoad?.(event);\n }, [userOnLoad]);\n\n // Handle image error - moved to top to avoid conditional hook call\n const handleError = React.useCallback((event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(false);\n setImageError(true);\n setShowPlaceholder(false);\n userOnError?.(event);\n }, [userOnError]);\n\n // Validate required props\n if (!src) {\n console.warn('Image component: src prop is required');\n return null;\n }\n\n if (!asChild && alt === undefined) {\n console.warn('Image component: alt prop is required for accessibility when not using asChild');\n }\n\n // Create skeleton placeholder\n const skeletonElement = showSkeleton && !imageLoaded && !imageError ? (\n <Skeleton\n style={{\n ...style,\n width: '100%',\n height: '100px', // Default height, can be overridden by style\n borderRadius: radius ? `var(--radius-${radius})` : undefined,\n }}\n className={className}\n />\n ) : null;\n\n // Create placeholder image element\n const placeholderElement = placeholder && showPlaceholder ? (\n <img\n data-radius={radius}\n style={{\n ...style,\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n filter: 'blur(4px)',\n opacity: 0.7,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n 'rt-Image--placeholder',\n className,\n )}\n alt=\"\"\n src={placeholder}\n />\n ) : null;\n\n // Create the standard img element\n const imgElement = (\n <img\n data-radius={radius}\n loading={loading}\n style={{\n ...style,\n opacity: imageLoaded ? 1 : 0,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n variant === 'blur' && 'rt-Image--blur',\n className,\n )}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n {...imgProps}\n ref={forwardedRef}\n />\n );\n\n // Wrapper for images with placeholders\n const imageWithPlaceholder = (placeholder || showSkeleton) ? (\n <div style={{ position: 'relative', display: 'inline-block' }}>\n {skeletonElement}\n {placeholderElement}\n {imgElement}\n </div>\n ) : imgElement;\n\n // Handle asChild - inject img into the child element\n if (asChild && children) {\n const child = React.Children.only(children) as React.ReactElement<any>;\n\n if (variant === 'blur') {\n // For blur variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className, 'rt-variant-blur'),\n style: {\n position: 'relative',\n display: 'inline-block',\n textDecoration: 'none', // Reset link underlines\n color: 'inherit', // Reset link colors\n border: 'none', // Reset button borders\n background: 'none', // Reset button backgrounds\n padding: 0, // Reset button padding\n font: 'inherit', // Reset button fonts\n cursor: 'pointer', // Ensure interactive cursor\n ...child.props?.style,\n },\n children: (\n <>\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n ...style,\n position: 'absolute',\n top: '8px',\n left: '0',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n 'rt-Image--blur',\n 'rt-Image--blur-bg',\n className,\n )}\n alt=\"\"\n src={src}\n {...imgProps}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{ \n ...style, \n position: 'relative', \n zIndex: 1,\n opacity: imageLoaded ? 1 : 0,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n {...imgProps}\n ref={forwardedRef}\n />\n </>\n ),\n });\n } else {\n // For surface variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className, 'rt-Image'),\n style: {\n textDecoration: 'none', // Reset link underlines\n color: 'inherit', // Reset link colors\n border: 'none', // Reset button borders\n background: 'none', // Reset button backgrounds\n padding: 0, // Reset button padding\n font: 'inherit', // Reset button fonts\n cursor: 'pointer', // Ensure interactive cursor\n ...child.props?.style, // Allow user overrides\n },\n children: imageWithPlaceholder,\n });\n }\n }\n\n // Regular rendering without asChild\n if (variant === 'blur') {\n return (\n <div className=\"rt-variant-blur\" style={{ position: 'relative', display: 'inline-block' }}>\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n ...style,\n position: 'absolute',\n top: '8px',\n left: '0',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n 'rt-Image--blur',\n 'rt-Image--blur-bg',\n className,\n )}\n alt=\"\"\n src={src}\n {...imgProps}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{ \n ...style, \n position: 'relative', \n zIndex: 1,\n opacity: imageLoaded ? 1 : 0,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n {...imgProps}\n ref={forwardedRef}\n />\n </div>\n );\n }\n\n return imageWithPlaceholder;\n});\n\nImage.displayName = 'Image';\n\nexport { Image };\nexport type { ImageProps };\n"],
5
+ "mappings": "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",
6
+ "names": ["image_exports", "__export", "Image", "__toCommonJS", "React", "import_classnames", "import_image_props", "import_extract_props", "import_margin_props", "import_width_props", "import_height_props", "import_skeleton", "props", "forwardedRef", "variant", "children", "asChild", "className", "radius", "style", "loading", "alt", "src", "placeholder", "showSkeleton", "userOnLoad", "userOnError", "_children", "imgProps", "imageLoaded", "setImageLoaded", "imageError", "setImageError", "showPlaceholder", "setShowPlaceholder", "handleLoad", "event", "handleError", "skeletonElement", "placeholderElement", "classNames", "imgElement", "imageWithPlaceholder", "child"]
7
7
  }
@@ -7,13 +7,30 @@ import type { HeightProps } from '../props/height.props.js';
7
7
  import type { GetPropDefTypes } from '../props/prop-def.js';
8
8
  type ImageOwnProps = GetPropDefTypes<typeof imagePropDefs> & {
9
9
  loading?: 'eager' | 'lazy';
10
+ /**
11
+ * Placeholder image URL to show while the main image is loading.
12
+ * Can be a low-quality/blurred version of the main image.
13
+ */
14
+ placeholder?: string;
15
+ /**
16
+ * Shows a skeleton placeholder while loading instead of a blank space.
17
+ */
18
+ showSkeleton?: boolean;
19
+ /**
20
+ * Callback fired when the image successfully loads.
21
+ */
22
+ onLoad?: (event: React.SyntheticEvent<HTMLImageElement>) => void;
23
+ /**
24
+ * Callback fired when the image fails to load.
25
+ */
26
+ onError?: (event: React.SyntheticEvent<HTMLImageElement>) => void;
10
27
  };
11
28
  interface ImageProps extends ComponentPropsWithout<'img', RemovedProps | 'color' | 'width' | 'height' | 'alt'>, MarginProps, WidthProps, HeightProps, ImageOwnProps {
12
29
  /**
13
30
  * The alt attribute provides alternative information for an image if a user for some reason cannot view it.
14
- * Required for accessibility when not using asChild.
31
+ * Required for accessibility when not using asChild. Use empty string for decorative images.
15
32
  */
16
- alt?: string;
33
+ alt: string;
17
34
  }
18
35
  declare const Image: React.ForwardRefExoticComponent<ImageProps & React.RefAttributes<HTMLImageElement>>;
19
36
  export { Image };
@@ -1 +1 @@
1
- {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/components/image.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAMjD,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG5D,KAAK,aAAa,GAAG,eAAe,CAAC,OAAO,aAAa,CAAC,GAAG;IAC3D,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC5B,CAAC;AAEF,UAAU,UACR,SAAQ,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC,EACvF,WAAW,EACX,UAAU,EACV,WAAW,EACX,aAAa;IACf;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,QAAA,MAAM,KAAK,qFAsJT,CAAC;AAIH,OAAO,EAAE,KAAK,EAAE,CAAC;AACjB,YAAY,EAAE,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../../src/components/image.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAOjD,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG5D,KAAK,aAAa,GAAG,eAAe,CAAC,OAAO,aAAa,CAAC,GAAG;IAC3D,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;IACjE;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,KAAK,IAAI,CAAC;CACnE,CAAC;AAEF,UAAU,UACR,SAAQ,qBAAqB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC,EACvF,WAAW,EACX,UAAU,EACV,WAAW,EACX,aAAa;IACf;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,QAAA,MAAM,KAAK,qFA+PT,CAAC;AAIH,OAAO,EAAE,KAAK,EAAE,CAAC;AACjB,YAAY,EAAE,UAAU,EAAE,CAAC"}
@@ -1,2 +1,2 @@
1
- "use client";import*as e from"react";import r from"classnames";import{imagePropDefs as h}from"./image.props.js";import{extractProps as I}from"../helpers/extract-props.js";import{marginPropDefs as P}from"../props/margin.props.js";import{widthPropDefs as b}from"../props/width.props.js";import{heightPropDefs as N}from"../props/height.props.js";const u=e.forwardRef((d,n)=>{const{variant:m="surface",fit:v="cover",children:c}=d,{asChild:y,className:o,radius:s,style:a,loading:i="lazy",alt:g,src:p,children:x,...l}=I(d,h,P,b,N),f=e.createElement("img",{"data-radius":s,loading:i,style:a,className:r("rt-reset","rt-Image",m==="blur"&&"rt-Image--blur",o),alt:g,src:p,...l,ref:n});if(y&&c){const t=e.Children.only(c);return m==="blur"?e.cloneElement(t,{className:r(t.props?.className,"rt-variant-blur"),style:{position:"relative",display:"inline-block",textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...t.props?.style},children:e.createElement(e.Fragment,null,e.createElement("img",{"data-radius":s,loading:i,style:{...a,position:"absolute",top:"8px",left:"0"},className:r("rt-reset","rt-Image","rt-Image--blur","rt-Image--blur-bg",o),alt:"",src:p,...l}),e.createElement("img",{"data-radius":s,loading:i,style:{...a,position:"relative",zIndex:1},className:r("rt-reset","rt-Image","rt-Image--blur",o),alt:g,src:p,...l,ref:n}))}):e.cloneElement(t,{className:r(t.props?.className,"rt-Image"),style:{textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...t.props?.style},children:f})}return m==="blur"?e.createElement("div",{className:"rt-variant-blur",style:{position:"relative",display:"inline-block"}},e.createElement("img",{"data-radius":s,loading:i,style:{...a,position:"absolute",top:"8px",left:"0"},className:r("rt-reset","rt-Image","rt-Image--blur","rt-Image--blur-bg",o),alt:"",src:p,...l}),e.createElement("img",{"data-radius":s,loading:i,style:{...a,position:"relative",zIndex:1},className:r("rt-reset","rt-Image","rt-Image--blur",o),alt:g,src:p,...l,ref:n})):f});u.displayName="Image";export{u as Image};
1
+ "use client";import*as e from"react";import o from"classnames";import{imagePropDefs as M}from"./image.props.js";import{extractProps as T}from"../helpers/extract-props.js";import{marginPropDefs as j}from"../props/margin.props.js";import{widthPropDefs as W}from"../props/width.props.js";import{heightPropDefs as z}from"../props/height.props.js";import{Skeleton as O}from"./skeleton.js";const k=e.forwardRef((f,c)=>{const{variant:g="surface",children:y}=f,{asChild:I,className:a,radius:r,style:s,loading:n="lazy",alt:p,src:i,placeholder:m,showSkeleton:b=!1,onLoad:P,onError:E,children:q,...l}=T(f,M,j,W,z),[d,v]=e.useState(!1),[S,N]=e.useState(!1),[D,w]=e.useState(!!m),u=e.useCallback(t=>{v(!0),N(!1),w(!1),P?.(t)},[P]),h=e.useCallback(t=>{v(!1),N(!0),w(!1),E?.(t)},[E]);if(!i)return console.warn("Image component: src prop is required"),null;!I&&p===void 0&&console.warn("Image component: alt prop is required for accessibility when not using asChild");const C=b&&!d&&!S?e.createElement(O,{style:{...s,width:"100%",height:"100px",borderRadius:r?`var(--radius-${r})`:void 0},className:a}):null,H=m&&D?e.createElement("img",{"data-radius":r,style:{...s,position:"absolute",top:0,left:0,width:"100%",height:"100%",filter:"blur(4px)",opacity:.7,transition:"opacity 0.3s ease-out"},className:o("rt-reset","rt-Image","rt-Image--placeholder",a),alt:"",src:m}):null,L=e.createElement("img",{"data-radius":r,loading:n,style:{...s,opacity:d?1:0,transition:"opacity 0.3s ease-out"},className:o("rt-reset","rt-Image",g==="blur"&&"rt-Image--blur",a),alt:p,src:i,onLoad:u,onError:h,...l,ref:c}),x=m||b?e.createElement("div",{style:{position:"relative",display:"inline-block"}},C,H,L):L;if(I&&y){const t=e.Children.only(y);return g==="blur"?e.cloneElement(t,{className:o(t.props?.className,"rt-variant-blur"),style:{position:"relative",display:"inline-block",textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...t.props?.style},children:e.createElement(e.Fragment,null,e.createElement("img",{"data-radius":r,loading:n,style:{...s,position:"absolute",top:"8px",left:"0"},className:o("rt-reset","rt-Image","rt-Image--blur","rt-Image--blur-bg",a),alt:"",src:i,...l}),e.createElement("img",{"data-radius":r,loading:n,style:{...s,position:"relative",zIndex:1,opacity:d?1:0,transition:"opacity 0.3s ease-out"},className:o("rt-reset","rt-Image","rt-Image--blur",a),alt:p,src:i,onLoad:u,onError:h,...l,ref:c}))}):e.cloneElement(t,{className:o(t.props?.className,"rt-Image"),style:{textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...t.props?.style},children:x})}return g==="blur"?e.createElement("div",{className:"rt-variant-blur",style:{position:"relative",display:"inline-block"}},e.createElement("img",{"data-radius":r,loading:n,style:{...s,position:"absolute",top:"8px",left:"0"},className:o("rt-reset","rt-Image","rt-Image--blur","rt-Image--blur-bg",a),alt:"",src:i,...l}),e.createElement("img",{"data-radius":r,loading:n,style:{...s,position:"relative",zIndex:1,opacity:d?1:0,transition:"opacity 0.3s ease-out"},className:o("rt-reset","rt-Image","rt-Image--blur",a),alt:p,src:i,onLoad:u,onError:h,...l,ref:c})):x});k.displayName="Image";export{k as Image};
2
2
  //# sourceMappingURL=image.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/image.tsx"],
4
- "sourcesContent": ["'use client';\n\nimport * as React from 'react';\nimport classNames from 'classnames';\n\nimport { imagePropDefs } from './image.props.js';\nimport { extractProps } from '../helpers/extract-props.js';\nimport { marginPropDefs } from '../props/margin.props.js';\nimport { widthPropDefs } from '../props/width.props.js';\nimport { heightPropDefs } from '../props/height.props.js';\n\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\nimport type { MarginProps } from '../props/margin.props.js';\nimport type { WidthProps } from '../props/width.props.js';\nimport type { HeightProps } from '../props/height.props.js';\nimport type { GetPropDefTypes } from '../props/prop-def.js';\n\ntype ImageElement = React.ElementRef<'img'>;\ntype ImageOwnProps = GetPropDefTypes<typeof imagePropDefs> & {\n loading?: 'eager' | 'lazy';\n};\n\ninterface ImageProps\n extends ComponentPropsWithout<'img', RemovedProps | 'color' | 'width' | 'height' | 'alt'>,\n MarginProps,\n WidthProps,\n HeightProps,\n ImageOwnProps {\n /**\n * The alt attribute provides alternative information for an image if a user for some reason cannot view it.\n * Required for accessibility when not using asChild.\n */\n alt?: string;\n}\n\nconst Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) => {\n const { variant = 'surface', fit: _fit = 'cover', children } = props;\n const {\n asChild,\n className,\n radius,\n style,\n loading = 'lazy',\n alt,\n src,\n children: _children, // Extract children to exclude from imgProps\n ...imgProps\n } = extractProps(props, imagePropDefs, marginPropDefs, widthPropDefs, heightPropDefs);\n\n // Create the standard img element\n const imgElement = (\n <img\n data-radius={radius}\n loading={loading}\n style={style}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n variant === 'blur' && 'rt-Image--blur',\n className,\n )}\n alt={alt}\n src={src}\n {...imgProps}\n ref={forwardedRef}\n />\n );\n\n // Handle asChild - inject img into the child element\n if (asChild && children) {\n const child = React.Children.only(children) as React.ReactElement<any>;\n\n if (variant === 'blur') {\n // For blur variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className, 'rt-variant-blur'),\n style: {\n position: 'relative',\n display: 'inline-block',\n textDecoration: 'none', // Reset link underlines\n color: 'inherit', // Reset link colors\n border: 'none', // Reset button borders\n background: 'none', // Reset button backgrounds\n padding: 0, // Reset button padding\n font: 'inherit', // Reset button fonts\n cursor: 'pointer', // Ensure interactive cursor\n ...child.props?.style,\n },\n children: (\n <>\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n ...style,\n position: 'absolute',\n top: '8px',\n left: '0',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n 'rt-Image--blur',\n 'rt-Image--blur-bg',\n className,\n )}\n alt=\"\"\n src={src}\n {...imgProps}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{ ...style, position: 'relative', zIndex: 1 }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n {...imgProps}\n ref={forwardedRef}\n />\n </>\n ),\n });\n } else {\n // For surface variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className, 'rt-Image'),\n style: {\n textDecoration: 'none', // Reset link underlines\n color: 'inherit', // Reset link colors\n border: 'none', // Reset button borders\n background: 'none', // Reset button backgrounds\n padding: 0, // Reset button padding\n font: 'inherit', // Reset button fonts\n cursor: 'pointer', // Ensure interactive cursor\n ...child.props?.style, // Allow user overrides\n },\n children: imgElement,\n });\n }\n }\n\n // Regular rendering without asChild\n if (variant === 'blur') {\n return (\n <div className=\"rt-variant-blur\" style={{ position: 'relative', display: 'inline-block' }}>\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n ...style,\n position: 'absolute',\n top: '8px',\n left: '0',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n 'rt-Image--blur',\n 'rt-Image--blur-bg',\n className,\n )}\n alt=\"\"\n src={src}\n {...imgProps}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{ ...style, position: 'relative', zIndex: 1 }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n {...imgProps}\n ref={forwardedRef}\n />\n </div>\n );\n }\n\n return imgElement;\n});\n\nImage.displayName = 'Image';\n\nexport { Image };\nexport type { ImageProps };\n"],
5
- "mappings": "aAEA,UAAYA,MAAW,QACvB,OAAOC,MAAgB,aAEvB,OAAS,iBAAAC,MAAqB,mBAC9B,OAAS,gBAAAC,MAAoB,8BAC7B,OAAS,kBAAAC,MAAsB,2BAC/B,OAAS,iBAAAC,MAAqB,0BAC9B,OAAS,kBAAAC,MAAsB,2BA0B/B,MAAMC,EAAQP,EAAM,WAAqC,CAACQ,EAAOC,IAAiB,CAChF,KAAM,CAAE,QAAAC,EAAU,UAAW,IAAKC,EAAO,QAAS,SAAAC,CAAS,EAAIJ,EACzD,CACJ,QAAAK,EACA,UAAAC,EACA,OAAAC,EACA,MAAAC,EACA,QAAAC,EAAU,OACV,IAAAC,EACA,IAAAC,EACA,SAAUC,EACV,GAAGC,CACL,EAAIlB,EAAaK,EAAON,EAAeE,EAAgBC,EAAeC,CAAc,EAG9EgB,EACJtB,EAAA,cAAC,OACC,cAAae,EACb,QAASE,EACT,MAAOD,EACP,UAAWf,EACT,WACA,WACAS,IAAY,QAAU,iBACtBI,CACF,EACA,IAAKI,EACL,IAAKC,EACJ,GAAGE,EACJ,IAAKZ,EACP,EAIF,GAAII,GAAWD,EAAU,CACvB,MAAMW,EAAQvB,EAAM,SAAS,KAAKY,CAAQ,EAE1C,OAAIF,IAAY,OAEPV,EAAM,aAAauB,EAAO,CAC/B,UAAWtB,EAAWsB,EAAM,OAAO,UAAW,iBAAiB,EAC/D,MAAO,CACL,SAAU,WACV,QAAS,eACT,eAAgB,OAChB,MAAO,UACP,OAAQ,OACR,WAAY,OACZ,QAAS,EACT,KAAM,UACN,OAAQ,UACR,GAAGA,EAAM,OAAO,KAClB,EACA,SACEvB,EAAA,cAAAA,EAAA,cAEEA,EAAA,cAAC,OACC,cAAae,EACb,QAASE,EACT,MAAO,CACL,GAAGD,EACH,SAAU,WACV,IAAK,MACL,KAAM,GACR,EACA,UAAWf,EACT,WACA,WACA,iBACA,oBACAa,CACF,EACA,IAAI,GACJ,IAAKK,EACJ,GAAGE,EACN,EAEArB,EAAA,cAAC,OACC,cAAae,EACb,QAASE,EACT,MAAO,CAAE,GAAGD,EAAO,SAAU,WAAY,OAAQ,CAAE,EACnD,UAAWf,EAAW,WAAY,WAAY,iBAAkBa,CAAS,EACzE,IAAKI,EACL,IAAKC,EACJ,GAAGE,EACJ,IAAKZ,EACP,CACF,CAEJ,CAAC,EAGMT,EAAM,aAAauB,EAAO,CAC/B,UAAWtB,EAAWsB,EAAM,OAAO,UAAW,UAAU,EACxD,MAAO,CACL,eAAgB,OAChB,MAAO,UACP,OAAQ,OACR,WAAY,OACZ,QAAS,EACT,KAAM,UACN,OAAQ,UACR,GAAGA,EAAM,OAAO,KAClB,EACA,SAAUD,CACZ,CAAC,CAEL,CAGA,OAAIZ,IAAY,OAEZV,EAAA,cAAC,OAAI,UAAU,kBAAkB,MAAO,CAAE,SAAU,WAAY,QAAS,cAAe,GAEtFA,EAAA,cAAC,OACC,cAAae,EACb,QAASE,EACT,MAAO,CACL,GAAGD,EACH,SAAU,WACV,IAAK,MACL,KAAM,GACR,EACA,UAAWf,EACT,WACA,WACA,iBACA,oBACAa,CACF,EACA,IAAI,GACJ,IAAKK,EACJ,GAAGE,EACN,EAEArB,EAAA,cAAC,OACC,cAAae,EACb,QAASE,EACT,MAAO,CAAE,GAAGD,EAAO,SAAU,WAAY,OAAQ,CAAE,EACnD,UAAWf,EAAW,WAAY,WAAY,iBAAkBa,CAAS,EACzE,IAAKI,EACL,IAAKC,EACJ,GAAGE,EACJ,IAAKZ,EACP,CACF,EAIGa,CACT,CAAC,EAEDf,EAAM,YAAc",
6
- "names": ["React", "classNames", "imagePropDefs", "extractProps", "marginPropDefs", "widthPropDefs", "heightPropDefs", "Image", "props", "forwardedRef", "variant", "_fit", "children", "asChild", "className", "radius", "style", "loading", "alt", "src", "_children", "imgProps", "imgElement", "child"]
4
+ "sourcesContent": ["'use client';\n\nimport * as React from 'react';\nimport classNames from 'classnames';\n\nimport { imagePropDefs } from './image.props.js';\nimport { extractProps } from '../helpers/extract-props.js';\nimport { marginPropDefs } from '../props/margin.props.js';\nimport { widthPropDefs } from '../props/width.props.js';\nimport { heightPropDefs } from '../props/height.props.js';\nimport { Skeleton } from './skeleton.js';\n\nimport type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';\nimport type { MarginProps } from '../props/margin.props.js';\nimport type { WidthProps } from '../props/width.props.js';\nimport type { HeightProps } from '../props/height.props.js';\nimport type { GetPropDefTypes } from '../props/prop-def.js';\n\ntype ImageElement = React.ElementRef<'img'>;\ntype ImageOwnProps = GetPropDefTypes<typeof imagePropDefs> & {\n loading?: 'eager' | 'lazy';\n /**\n * Placeholder image URL to show while the main image is loading.\n * Can be a low-quality/blurred version of the main image.\n */\n placeholder?: string;\n /**\n * Shows a skeleton placeholder while loading instead of a blank space.\n */\n showSkeleton?: boolean;\n /**\n * Callback fired when the image successfully loads.\n */\n onLoad?: (event: React.SyntheticEvent<HTMLImageElement>) => void;\n /**\n * Callback fired when the image fails to load.\n */\n onError?: (event: React.SyntheticEvent<HTMLImageElement>) => void;\n};\n\ninterface ImageProps\n extends ComponentPropsWithout<'img', RemovedProps | 'color' | 'width' | 'height' | 'alt'>,\n MarginProps,\n WidthProps,\n HeightProps,\n ImageOwnProps {\n /**\n * The alt attribute provides alternative information for an image if a user for some reason cannot view it.\n * Required for accessibility when not using asChild. Use empty string for decorative images.\n */\n alt: string;\n}\n\nconst Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) => {\n const { variant = 'surface', children } = props;\n const {\n asChild,\n className,\n radius,\n style,\n loading = 'lazy',\n alt,\n src,\n placeholder,\n showSkeleton = false,\n onLoad: userOnLoad,\n onError: userOnError,\n children: _children, // Extract children to exclude from imgProps\n ...imgProps\n } = extractProps(props, imagePropDefs, marginPropDefs, widthPropDefs, heightPropDefs);\n\n // Loading state management\n const [imageLoaded, setImageLoaded] = React.useState(false);\n const [imageError, setImageError] = React.useState(false);\n const [showPlaceholder, setShowPlaceholder] = React.useState(!!placeholder);\n\n // Handle image load - moved to top to avoid conditional hook call\n const handleLoad = React.useCallback((event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(true);\n setImageError(false);\n setShowPlaceholder(false);\n userOnLoad?.(event);\n }, [userOnLoad]);\n\n // Handle image error - moved to top to avoid conditional hook call\n const handleError = React.useCallback((event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(false);\n setImageError(true);\n setShowPlaceholder(false);\n userOnError?.(event);\n }, [userOnError]);\n\n // Validate required props\n if (!src) {\n console.warn('Image component: src prop is required');\n return null;\n }\n\n if (!asChild && alt === undefined) {\n console.warn('Image component: alt prop is required for accessibility when not using asChild');\n }\n\n // Create skeleton placeholder\n const skeletonElement = showSkeleton && !imageLoaded && !imageError ? (\n <Skeleton\n style={{\n ...style,\n width: '100%',\n height: '100px', // Default height, can be overridden by style\n borderRadius: radius ? `var(--radius-${radius})` : undefined,\n }}\n className={className}\n />\n ) : null;\n\n // Create placeholder image element\n const placeholderElement = placeholder && showPlaceholder ? (\n <img\n data-radius={radius}\n style={{\n ...style,\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n filter: 'blur(4px)',\n opacity: 0.7,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n 'rt-Image--placeholder',\n className,\n )}\n alt=\"\"\n src={placeholder}\n />\n ) : null;\n\n // Create the standard img element\n const imgElement = (\n <img\n data-radius={radius}\n loading={loading}\n style={{\n ...style,\n opacity: imageLoaded ? 1 : 0,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n variant === 'blur' && 'rt-Image--blur',\n className,\n )}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n {...imgProps}\n ref={forwardedRef}\n />\n );\n\n // Wrapper for images with placeholders\n const imageWithPlaceholder = (placeholder || showSkeleton) ? (\n <div style={{ position: 'relative', display: 'inline-block' }}>\n {skeletonElement}\n {placeholderElement}\n {imgElement}\n </div>\n ) : imgElement;\n\n // Handle asChild - inject img into the child element\n if (asChild && children) {\n const child = React.Children.only(children) as React.ReactElement<any>;\n\n if (variant === 'blur') {\n // For blur variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className, 'rt-variant-blur'),\n style: {\n position: 'relative',\n display: 'inline-block',\n textDecoration: 'none', // Reset link underlines\n color: 'inherit', // Reset link colors\n border: 'none', // Reset button borders\n background: 'none', // Reset button backgrounds\n padding: 0, // Reset button padding\n font: 'inherit', // Reset button fonts\n cursor: 'pointer', // Ensure interactive cursor\n ...child.props?.style,\n },\n children: (\n <>\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n ...style,\n position: 'absolute',\n top: '8px',\n left: '0',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n 'rt-Image--blur',\n 'rt-Image--blur-bg',\n className,\n )}\n alt=\"\"\n src={src}\n {...imgProps}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{ \n ...style, \n position: 'relative', \n zIndex: 1,\n opacity: imageLoaded ? 1 : 0,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n {...imgProps}\n ref={forwardedRef}\n />\n </>\n ),\n });\n } else {\n // For surface variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className, 'rt-Image'),\n style: {\n textDecoration: 'none', // Reset link underlines\n color: 'inherit', // Reset link colors\n border: 'none', // Reset button borders\n background: 'none', // Reset button backgrounds\n padding: 0, // Reset button padding\n font: 'inherit', // Reset button fonts\n cursor: 'pointer', // Ensure interactive cursor\n ...child.props?.style, // Allow user overrides\n },\n children: imageWithPlaceholder,\n });\n }\n }\n\n // Regular rendering without asChild\n if (variant === 'blur') {\n return (\n <div className=\"rt-variant-blur\" style={{ position: 'relative', display: 'inline-block' }}>\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n ...style,\n position: 'absolute',\n top: '8px',\n left: '0',\n }}\n className={classNames(\n 'rt-reset',\n 'rt-Image',\n 'rt-Image--blur',\n 'rt-Image--blur-bg',\n className,\n )}\n alt=\"\"\n src={src}\n {...imgProps}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{ \n ...style, \n position: 'relative', \n zIndex: 1,\n opacity: imageLoaded ? 1 : 0,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n {...imgProps}\n ref={forwardedRef}\n />\n </div>\n );\n }\n\n return imageWithPlaceholder;\n});\n\nImage.displayName = 'Image';\n\nexport { Image };\nexport type { ImageProps };\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "classNames", "imagePropDefs", "extractProps", "marginPropDefs", "widthPropDefs", "heightPropDefs", "Skeleton", "Image", "props", "forwardedRef", "variant", "children", "asChild", "className", "radius", "style", "loading", "alt", "src", "placeholder", "showSkeleton", "userOnLoad", "userOnError", "_children", "imgProps", "imageLoaded", "setImageLoaded", "imageError", "setImageError", "showPlaceholder", "setShowPlaceholder", "handleLoad", "event", "handleError", "skeletonElement", "placeholderElement", "imgElement", "imageWithPlaceholder", "child"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kushagradhawan/kookie-ui",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "A modern React component library with beautiful design tokens, flexible theming, and comprehensive docs",
5
5
  "keywords": [
6
6
  "react",
@@ -203,7 +203,7 @@
203
203
 
204
204
  .rt-Card:where(.rt-variant-soft) {
205
205
  --card-border-width: 0px;
206
- --card-background-color: var(--gray-a3);
206
+ --card-background-color: var(--gray-a2);
207
207
 
208
208
  &::before {
209
209
  background-color: var(--card-background-color);
@@ -224,18 +224,18 @@
224
224
  @media (hover: hover) {
225
225
  &:where(:hover) {
226
226
  &::before {
227
- background-color: var(--gray-a4);
227
+ background-color: var(--gray-a3);
228
228
  }
229
229
  }
230
230
  }
231
231
  &:where([data-state='open']) {
232
232
  &::before {
233
- background-color: var(--gray-a4);
233
+ background-color: var(--gray-a3);
234
234
  }
235
235
  }
236
236
  &:where(:active:not([data-state='open'])) {
237
237
  &::before {
238
- background-color: var(--gray-a5);
238
+ background-color: var(--gray-a4);
239
239
  }
240
240
  }
241
241
  }
@@ -138,3 +138,8 @@
138
138
  .rt-r-shadow-6 {
139
139
  --box-shadow: var(--shadow-6);
140
140
  }
141
+
142
+ /* Loading states */
143
+ .rt-Image--placeholder {
144
+ z-index: 0;
145
+ }
@@ -8,6 +8,7 @@ import { extractProps } from '../helpers/extract-props.js';
8
8
  import { marginPropDefs } from '../props/margin.props.js';
9
9
  import { widthPropDefs } from '../props/width.props.js';
10
10
  import { heightPropDefs } from '../props/height.props.js';
11
+ import { Skeleton } from './skeleton.js';
11
12
 
12
13
  import type { ComponentPropsWithout, RemovedProps } from '../helpers/component-props.js';
13
14
  import type { MarginProps } from '../props/margin.props.js';
@@ -18,6 +19,23 @@ import type { GetPropDefTypes } from '../props/prop-def.js';
18
19
  type ImageElement = React.ElementRef<'img'>;
19
20
  type ImageOwnProps = GetPropDefTypes<typeof imagePropDefs> & {
20
21
  loading?: 'eager' | 'lazy';
22
+ /**
23
+ * Placeholder image URL to show while the main image is loading.
24
+ * Can be a low-quality/blurred version of the main image.
25
+ */
26
+ placeholder?: string;
27
+ /**
28
+ * Shows a skeleton placeholder while loading instead of a blank space.
29
+ */
30
+ showSkeleton?: boolean;
31
+ /**
32
+ * Callback fired when the image successfully loads.
33
+ */
34
+ onLoad?: (event: React.SyntheticEvent<HTMLImageElement>) => void;
35
+ /**
36
+ * Callback fired when the image fails to load.
37
+ */
38
+ onError?: (event: React.SyntheticEvent<HTMLImageElement>) => void;
21
39
  };
22
40
 
23
41
  interface ImageProps
@@ -28,13 +46,13 @@ interface ImageProps
28
46
  ImageOwnProps {
29
47
  /**
30
48
  * The alt attribute provides alternative information for an image if a user for some reason cannot view it.
31
- * Required for accessibility when not using asChild.
49
+ * Required for accessibility when not using asChild. Use empty string for decorative images.
32
50
  */
33
- alt?: string;
51
+ alt: string;
34
52
  }
35
53
 
36
54
  const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) => {
37
- const { variant = 'surface', fit: _fit = 'cover', children } = props;
55
+ const { variant = 'surface', children } = props;
38
56
  const {
39
57
  asChild,
40
58
  className,
@@ -43,16 +61,94 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
43
61
  loading = 'lazy',
44
62
  alt,
45
63
  src,
64
+ placeholder,
65
+ showSkeleton = false,
66
+ onLoad: userOnLoad,
67
+ onError: userOnError,
46
68
  children: _children, // Extract children to exclude from imgProps
47
69
  ...imgProps
48
70
  } = extractProps(props, imagePropDefs, marginPropDefs, widthPropDefs, heightPropDefs);
49
71
 
72
+ // Loading state management
73
+ const [imageLoaded, setImageLoaded] = React.useState(false);
74
+ const [imageError, setImageError] = React.useState(false);
75
+ const [showPlaceholder, setShowPlaceholder] = React.useState(!!placeholder);
76
+
77
+ // Handle image load - moved to top to avoid conditional hook call
78
+ const handleLoad = React.useCallback((event: React.SyntheticEvent<HTMLImageElement>) => {
79
+ setImageLoaded(true);
80
+ setImageError(false);
81
+ setShowPlaceholder(false);
82
+ userOnLoad?.(event);
83
+ }, [userOnLoad]);
84
+
85
+ // Handle image error - moved to top to avoid conditional hook call
86
+ const handleError = React.useCallback((event: React.SyntheticEvent<HTMLImageElement>) => {
87
+ setImageLoaded(false);
88
+ setImageError(true);
89
+ setShowPlaceholder(false);
90
+ userOnError?.(event);
91
+ }, [userOnError]);
92
+
93
+ // Validate required props
94
+ if (!src) {
95
+ console.warn('Image component: src prop is required');
96
+ return null;
97
+ }
98
+
99
+ if (!asChild && alt === undefined) {
100
+ console.warn('Image component: alt prop is required for accessibility when not using asChild');
101
+ }
102
+
103
+ // Create skeleton placeholder
104
+ const skeletonElement = showSkeleton && !imageLoaded && !imageError ? (
105
+ <Skeleton
106
+ style={{
107
+ ...style,
108
+ width: '100%',
109
+ height: '100px', // Default height, can be overridden by style
110
+ borderRadius: radius ? `var(--radius-${radius})` : undefined,
111
+ }}
112
+ className={className}
113
+ />
114
+ ) : null;
115
+
116
+ // Create placeholder image element
117
+ const placeholderElement = placeholder && showPlaceholder ? (
118
+ <img
119
+ data-radius={radius}
120
+ style={{
121
+ ...style,
122
+ position: 'absolute',
123
+ top: 0,
124
+ left: 0,
125
+ width: '100%',
126
+ height: '100%',
127
+ filter: 'blur(4px)',
128
+ opacity: 0.7,
129
+ transition: 'opacity 0.3s ease-out',
130
+ }}
131
+ className={classNames(
132
+ 'rt-reset',
133
+ 'rt-Image',
134
+ 'rt-Image--placeholder',
135
+ className,
136
+ )}
137
+ alt=""
138
+ src={placeholder}
139
+ />
140
+ ) : null;
141
+
50
142
  // Create the standard img element
51
143
  const imgElement = (
52
144
  <img
53
145
  data-radius={radius}
54
146
  loading={loading}
55
- style={style}
147
+ style={{
148
+ ...style,
149
+ opacity: imageLoaded ? 1 : 0,
150
+ transition: 'opacity 0.3s ease-out',
151
+ }}
56
152
  className={classNames(
57
153
  'rt-reset',
58
154
  'rt-Image',
@@ -61,11 +157,22 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
61
157
  )}
62
158
  alt={alt}
63
159
  src={src}
160
+ onLoad={handleLoad}
161
+ onError={handleError}
64
162
  {...imgProps}
65
163
  ref={forwardedRef}
66
164
  />
67
165
  );
68
166
 
167
+ // Wrapper for images with placeholders
168
+ const imageWithPlaceholder = (placeholder || showSkeleton) ? (
169
+ <div style={{ position: 'relative', display: 'inline-block' }}>
170
+ {skeletonElement}
171
+ {placeholderElement}
172
+ {imgElement}
173
+ </div>
174
+ ) : imgElement;
175
+
69
176
  // Handle asChild - inject img into the child element
70
177
  if (asChild && children) {
71
178
  const child = React.Children.only(children) as React.ReactElement<any>;
@@ -113,10 +220,18 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
113
220
  <img
114
221
  data-radius={radius}
115
222
  loading={loading}
116
- style={{ ...style, position: 'relative', zIndex: 1 }}
223
+ style={{
224
+ ...style,
225
+ position: 'relative',
226
+ zIndex: 1,
227
+ opacity: imageLoaded ? 1 : 0,
228
+ transition: 'opacity 0.3s ease-out',
229
+ }}
117
230
  className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}
118
231
  alt={alt}
119
232
  src={src}
233
+ onLoad={handleLoad}
234
+ onError={handleError}
120
235
  {...imgProps}
121
236
  ref={forwardedRef}
122
237
  />
@@ -137,7 +252,7 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
137
252
  cursor: 'pointer', // Ensure interactive cursor
138
253
  ...child.props?.style, // Allow user overrides
139
254
  },
140
- children: imgElement,
255
+ children: imageWithPlaceholder,
141
256
  });
142
257
  }
143
258
  }
@@ -171,10 +286,18 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
171
286
  <img
172
287
  data-radius={radius}
173
288
  loading={loading}
174
- style={{ ...style, position: 'relative', zIndex: 1 }}
289
+ style={{
290
+ ...style,
291
+ position: 'relative',
292
+ zIndex: 1,
293
+ opacity: imageLoaded ? 1 : 0,
294
+ transition: 'opacity 0.3s ease-out',
295
+ }}
175
296
  className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}
176
297
  alt={alt}
177
298
  src={src}
299
+ onLoad={handleLoad}
300
+ onError={handleError}
178
301
  {...imgProps}
179
302
  ref={forwardedRef}
180
303
  />
@@ -182,7 +305,7 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
182
305
  );
183
306
  }
184
307
 
185
- return imgElement;
308
+ return imageWithPlaceholder;
186
309
  });
187
310
 
188
311
  Image.displayName = 'Image';
package/styles.css CHANGED
@@ -7981,7 +7981,7 @@
7981
7981
  }
7982
7982
  .rt-Card:where(.rt-variant-soft) {
7983
7983
  --card-border-width: 0px;
7984
- --card-background-color: var(--gray-a3);
7984
+ --card-background-color: var(--gray-a2);
7985
7985
  }
7986
7986
  .rt-Card:where(.rt-variant-soft)::before {
7987
7987
  background-color: var(--card-background-color);
@@ -7999,14 +7999,14 @@
7999
7999
  }
8000
8000
  @media (hover: hover) {
8001
8001
  .rt-Card:where(.rt-variant-soft):where(:any-link, button, label):where(:hover)::before {
8002
- background-color: var(--gray-a4);
8002
+ background-color: var(--gray-a3);
8003
8003
  }
8004
8004
  }
8005
8005
  .rt-Card:where(.rt-variant-soft):where(:any-link, button, label):where([data-state='open'])::before {
8006
- background-color: var(--gray-a4);
8006
+ background-color: var(--gray-a3);
8007
8007
  }
8008
8008
  .rt-Card:where(.rt-variant-soft):where(:any-link, button, label):where(:active:not([data-state='open']))::before {
8009
- background-color: var(--gray-a5);
8009
+ background-color: var(--gray-a4);
8010
8010
  }
8011
8011
  @media (pointer: coarse) {
8012
8012
  .rt-Card:where(:any-link, button, label):where(:active:not(:focus-visible, [data-state='open']))::before {
@@ -10925,6 +10925,9 @@
10925
10925
  .rt-r-shadow-6 {
10926
10926
  --box-shadow: var(--shadow-6);
10927
10927
  }
10928
+ .rt-Image--placeholder {
10929
+ z-index: 0;
10930
+ }
10928
10931
  .rt-Inset {
10929
10932
  box-sizing: border-box;
10930
10933
  --margin-top: 0px;