@kushagradhawan/kookie-ui 0.1.23 → 0.1.24
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 +2 -16
- package/dist/cjs/components/image.d.ts.map +1 -1
- package/dist/cjs/components/image.js +1 -1
- package/dist/cjs/components/image.js.map +3 -3
- package/dist/esm/components/image.d.ts.map +1 -1
- package/dist/esm/components/image.js +1 -1
- package/dist/esm/components/image.js.map +3 -3
- package/package.json +1 -1
- package/src/components/image.css +8 -18
- package/src/components/image.tsx +124 -112
- package/src/styles/tokens/constants.css +1 -1
- package/styles.css +3 -17
- package/tokens.css +1 -1
package/components.css
CHANGED
|
@@ -7832,11 +7832,9 @@
|
|
|
7832
7832
|
}
|
|
7833
7833
|
.rt-variant-blur {
|
|
7834
7834
|
position: relative;
|
|
7835
|
+
}
|
|
7836
|
+
.rt-variant-blur--as-child {
|
|
7835
7837
|
display: inline-block;
|
|
7836
|
-
--blur-filter: blur(16px) saturate(1.5);
|
|
7837
|
-
--blur-opacity: 0.5;
|
|
7838
|
-
--blur-offset-y: 8px;
|
|
7839
|
-
--blur-offset-x: 0;
|
|
7840
7838
|
}
|
|
7841
7839
|
.rt-variant-blur:where(:any-link, button, label) {
|
|
7842
7840
|
cursor: pointer;
|
|
@@ -7860,18 +7858,6 @@
|
|
|
7860
7858
|
outline: none !important;
|
|
7861
7859
|
box-shadow: var(--box-shadow) !important;
|
|
7862
7860
|
}
|
|
7863
|
-
.rt-Image--blur-bg {
|
|
7864
|
-
position: absolute;
|
|
7865
|
-
top: var(--blur-offset-y, 8px);
|
|
7866
|
-
left: var(--blur-offset-x, 0);
|
|
7867
|
-
filter: var(--blur-filter);
|
|
7868
|
-
opacity: var(--blur-opacity);
|
|
7869
|
-
z-index: -1;
|
|
7870
|
-
}
|
|
7871
|
-
.rt-Image--blur {
|
|
7872
|
-
position: relative;
|
|
7873
|
-
z-index: 1;
|
|
7874
|
-
}
|
|
7875
7861
|
.rt-r-fit-cover {
|
|
7876
7862
|
--object-fit: cover;
|
|
7877
7863
|
}
|
|
@@ -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;AASjD,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,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,OAAO,CAAC;IACjB;;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;IAClE;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CACpC,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,WAAW,EACX,aAAa;IACf;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,QAAA,MAAM,KAAK,
|
|
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;AASjD,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,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,OAAO,CAAC;IACjB;;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;IAClE;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CACpC,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,WAAW,EACX,aAAa;IACf;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,QAAA,MAAM,KAAK,qFA0TT,CAAC;AAIH,OAAO,EAAE,KAAK,EAAE,CAAC;AACjB,YAAY,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";"use client";var V=Object.create;var b=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var Z=Object.getPrototypeOf,_=Object.prototype.hasOwnProperty;var R=(o,e)=>{for(var
|
|
1
|
+
"use strict";"use client";var V=Object.create;var b=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var Z=Object.getPrototypeOf,_=Object.prototype.hasOwnProperty;var R=(o,e)=>{for(var s in e)b(o,s,{get:e[s],enumerable:!0})},z=(o,e,s,y)=>{if(e&&typeof e=="object"||typeof e=="function")for(let p of Y(e))!_.call(o,p)&&p!==s&&b(o,p,{get:()=>e[p],enumerable:!(y=X(e,p))||y.enumerable});return o};var O=(o,e,s)=>(s=o!=null?V(Z(o)):{},z(e||!o||!o.__esModule?b(s,"default",{value:o,enumerable:!0}):s,o)),ee=o=>z(b({},"__esModule",{value:!0}),o);var te={};R(te,{Image:()=>x});module.exports=ee(te);var t=O(require("react")),a=O(require("classnames")),B=require("./image.props.js"),q=require("../helpers/extract-props.js"),A=require("../props/margin.props.js"),G=require("../props/width.props.js"),F=require("../props/height.props.js"),$=require("../props/layout.props.js"),J=require("./skeleton.js"),v=require("./box.js");const x=t.forwardRef((o,e)=>{const{variant:s="surface",wrapperStyle:y,...p}=o,{asChild:D,className:n,radius:l,style:d,loading:c="lazy",alt:u,src:i,placeholder:E,showSkeleton:K=!1,fadeIn:k=!0,onLoad:C,onError:w,children:H,...M}=(0,q.extractProps)(p,B.imagePropDefs,A.marginPropDefs,G.widthPropDefs,F.heightPropDefs,$.layoutPropDefs),[T,S]=t.useState(!1),[Q,L]=t.useState(!1),[U,N]=t.useState(!!E),g=t.useRef(null),f=t.useCallback(r=>{S(!0),L(!1),N(!1),C?.(r)},[C]),I=t.useCallback(r=>{S(!1),L(!0),N(!1),w?.(r)},[w]);if(t.useEffect(()=>{const r=g.current;r&&r.complete&&r.naturalWidth>0&&(S(!0),L(!1),N(!1))},[i]),!i)return console.warn("Image component: src prop is required"),null;!D&&u===void 0&&console.warn("Image component: alt prop is required for accessibility when not using asChild");const h={width:"100%",height:"100%",display:"block",opacity:k?T?1:0:1,transition:k?"opacity 0.3s ease-out":"none",...d},P={position:"relative",display:"block",...y},j=K&&!T&&!Q?t.createElement(J.Skeleton,{width:"100%",height:"100px",style:{borderRadius:l?`var(--radius-${l})`:void 0},className:n}):null,W=E&&U?t.createElement("img",{"data-radius":l,style:{...h,filter:"blur(4px)",opacity:.7,transition:"opacity 0.3s ease-out"},className:(0,a.default)("rt-reset","rt-Image","rt-Image--placeholder",n),alt:"",src:E}):null;if(D&&H){const r=t.Children.only(H);return s==="blur"?t.cloneElement(r,{className:(0,a.default)(r.props?.className,"rt-variant-blur"),style:{textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...P,...d,...r.props?.style},children:t.createElement(t.Fragment,null,t.createElement("img",{"data-radius":l,loading:c,style:{position:"absolute",top:"0",left:"0",width:"105%",height:"105%",transform:"translate(-2.5%, -2.5%)",filter:"blur(16px) saturate(1.5)",opacity:.5,zIndex:-1},className:(0,a.default)("rt-reset","rt-Image","rt-Image--blur-bg",n),alt:"",src:i}),t.createElement("img",{"data-radius":l,loading:c,style:h,className:(0,a.default)("rt-reset","rt-Image","rt-Image--blur",n),alt:u,src:i,onLoad:f,onError:I,ref:m=>{g.current=m,typeof e=="function"?e(m):e&&(e.current=m)}}))}):t.cloneElement(r,{className:(0,a.default)(r.props?.className),style:{textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...P,...r.props?.style},children:t.createElement(t.Fragment,null,j,W,t.createElement("img",{"data-radius":l,loading:c,style:h,className:(0,a.default)("rt-reset","rt-Image",n),alt:u,src:i,onLoad:f,onError:I,ref:m=>{g.current=m,typeof e=="function"?e(m):e&&(e.current=m)}}))})}return s==="blur"?t.createElement(v.Box,{className:(0,a.default)("rt-variant-blur",n),style:{...d,...P},...M},t.createElement("img",{"data-radius":l,loading:c,style:{position:"absolute",top:"0",left:"0",width:"105%",height:"105%",transform:"translate(-2.5%, -2.5%)",filter:"blur(16px) saturate(1.5)",opacity:.5,zIndex:-1},className:(0,a.default)("rt-reset","rt-Image","rt-Image--blur-bg",n),alt:"",src:i}),t.createElement("img",{"data-radius":l,loading:c,style:h,className:(0,a.default)("rt-reset","rt-Image","rt-Image--blur",n),alt:u,src:i,onLoad:f,onError:I,ref:r=>{g.current=r,typeof e=="function"?e(r):e&&(e.current=r)}})):t.createElement(v.Box,{className:n,style:{...d,...P},...M},j,W,t.createElement("img",{"data-radius":l,loading:c,style:h,className:(0,a.default)("rt-reset","rt-Image",n),alt:u,src:i,onLoad:f,onError:I,ref:r=>{g.current=r,typeof e=="function"?e(r):e&&(e.current=r)}}))});x.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';\nimport { layoutPropDefs } from '../props/layout.props.js';\nimport { Skeleton } from './skeleton.js';\nimport { Box } from './box.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 { LayoutProps } from '../props/layout.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 * Whether the image should fade in when loaded. Set to false for background images or when you want immediate visibility.\n */\n fadeIn?: 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 * Style object to apply to the wrapper container. Useful for overriding display, width, height, etc.\n */\n wrapperStyle?: React.CSSProperties;\n};\n\ninterface ImageProps\n extends ComponentPropsWithout<'img', RemovedProps | 'color' | 'width' | 'height' | 'alt'>,\n MarginProps,\n WidthProps,\n HeightProps,\n LayoutProps,\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', wrapperStyle, ...restProps } = props;\n const {\n asChild,\n className,\n radius,\n style,\n loading = 'lazy',\n alt,\n src,\n placeholder,\n showSkeleton = false,\n fadeIn = true,\n onLoad: userOnLoad,\n onError: userOnError,\n children,\n ...imgProps\n } = extractProps(\n restProps,\n imagePropDefs,\n marginPropDefs,\n widthPropDefs,\n heightPropDefs,\n layoutPropDefs,\n );\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 // Ref to check if image is already loaded (for cached images)\n const imgRef = React.useRef<HTMLImageElement>(null);\n\n // Handle image load - moved to top to avoid conditional hook call\n const handleLoad = React.useCallback(\n (event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(true);\n setImageError(false);\n setShowPlaceholder(false);\n userOnLoad?.(event);\n },\n [userOnLoad],\n );\n\n // Handle image error - moved to top to avoid conditional hook call\n const handleError = React.useCallback(\n (event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(false);\n setImageError(true);\n setShowPlaceholder(false);\n userOnError?.(event);\n },\n [userOnError],\n );\n\n // Check if image is already loaded (for cached images)\n React.useEffect(() => {\n const img = imgRef.current;\n if (img && img.complete && img.naturalWidth > 0) {\n setImageLoaded(true);\n setImageError(false);\n setShowPlaceholder(false);\n }\n }, [src]);\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 =\n showSkeleton && !imageLoaded && !imageError ? (\n <Skeleton\n width=\"100%\"\n height=\"100px\" // Default height, can be overridden by style\n style={{\n ...style,\n borderRadius: radius ? `var(--radius-${radius})` : undefined,\n }}\n className={className}\n />\n ) : null;\n\n // Create placeholder image element\n const placeholderElement =\n placeholder && showPlaceholder ? (\n <img\n data-radius={radius}\n style={{\n ...style,\n filter: 'blur(4px)',\n opacity: 0.7,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--placeholder', className)}\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: fadeIn ? (imageLoaded ? (style?.opacity ?? 1) : 0) : (style?.opacity ?? 1),\n transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',\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={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n );\n\n // Wrapper for images with placeholders\n const imageWithPlaceholder =\n placeholder || showSkeleton ? (\n <Box position=\"relative\" display=\"inline-block\" style={wrapperStyle}>\n {skeletonElement}\n {placeholderElement}\n {imgElement}\n </Box>\n ) : (\n imgElement\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 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 <Box position=\"relative\" display=\"inline-block\" style={wrapperStyle}>\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: fadeIn ? (imageLoaded ? (style?.opacity ?? 1) : 0) : (style?.opacity ?? 1),\n transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',\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={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </Box>\n ),\n });\n } else {\n // For surface variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className),\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 display: 'inline-block', // Ensure proper sizing\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 <Box\n className=\"rt-variant-blur\"\n position=\"relative\"\n display=\"inline-block\"\n style={wrapperStyle}\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: fadeIn ? (imageLoaded ? (style?.opacity ?? 1) : 0) : (style?.opacity ?? 1),\n transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',\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={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </Box>\n );\n }\n\n return imageWithPlaceholder;\n});\n\nImage.displayName = 'Image';\n\nexport { Image };\nexport type { ImageProps };\n"],
|
|
5
|
-
"mappings": "wkBAAA,IAAAA,GAAA,GAAAC,EAAAD,GAAA,WAAAE,IAAA,eAAAC,GAAAH,IAEA,IAAAI,EAAuB,oBACvBC,EAAuB,yBAEvBC,EAA8B,4BAC9BC,EAA6B,uCAC7BC,EAA+B,oCAC/BC,EAA8B,mCAC9BC,EAA+B,oCAC/BC,EAA+B,oCAC/BC,EAAyB,yBACzBC,EAAoB,oBAqDpB,MAAMX,EAAQE,EAAM,WAAqC,CAACU,EAAOC,IAAiB,CAChF,KAAM,CAAE,QAAAC,EAAU,UAAW,aAAAC,EAAc,GAAGC,CAAU,EAAIJ,EACtD,CACJ,QAAAK,EACA,UAAAC,EACA,OAAAC,EACA,MAAAC,EACA,QAAAC,EAAU,OACV,IAAAC,EACA,IAAAC,EACA,YAAAC,EACA,aAAAC,EAAe,GACf,OAAAC,EAAS,GACT,OAAQC,EACR,QAASC,EACT,SAAAC,EACA,GAAGC,CACL,KAAI,gBACFd,EACA,gBACA,iBACA,gBACA,iBACA,gBACF,EAGM,CAACe,EAAaC,CAAc,EAAI9B,EAAM,SAAS,EAAK,EACpD,CAAC+B,EAAYC,CAAa,EAAIhC,EAAM,SAAS,EAAK,EAClD,CAACiC,EAAiBC,CAAkB,EAAIlC,EAAM,SAAS,CAAC,CAACsB,CAAW,EAGpEa,EAASnC,EAAM,OAAyB,IAAI,EAG5CoC,EAAapC,EAAM,YACtBqC,GAAkD,CACjDP,EAAe,EAAI,EACnBE,EAAc,EAAK,EACnBE,EAAmB,EAAK,EACxBT,IAAaY,CAAK,CACpB,EACA,CAACZ,CAAU,CACb,EAGMa,EAActC,EAAM,YACvBqC,GAAkD,CACjDP,EAAe,EAAK,EACpBE,EAAc,EAAI,EAClBE,EAAmB,EAAK,EACxBR,IAAcW,CAAK,CACrB,EACA,CAACX,CAAW,CACd,EAaA,GAVA1B,EAAM,UAAU,IAAM,CACpB,MAAMuC,EAAMJ,EAAO,QACfI,GAAOA,EAAI,UAAYA,EAAI,aAAe,IAC5CT,EAAe,EAAI,EACnBE,EAAc,EAAK,EACnBE,EAAmB,EAAK,EAE5B,EAAG,CAACb,CAAG,CAAC,EAGJ,CAACA,EACH,eAAQ,KAAK,uCAAuC,EAC7C,KAGL,CAACN,GAAWK,IAAQ,QACtB,QAAQ,KAAK,gFAAgF,EAI/F,MAAMoB,
|
|
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_layout_props", "import_skeleton", "import_box", "props", "forwardedRef", "variant", "wrapperStyle", "restProps", "asChild", "className", "radius", "style", "loading", "alt", "src", "placeholder", "showSkeleton", "fadeIn", "userOnLoad", "userOnError", "children", "
|
|
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 { layoutPropDefs } from '../props/layout.props.js';\nimport { Skeleton } from './skeleton.js';\nimport { Box } from './box.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 { LayoutProps } from '../props/layout.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 * Whether the image should fade in when loaded. Set to false for background images or when you want immediate visibility.\n */\n fadeIn?: 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 * Style object to apply to the wrapper container. Useful for overriding display, width, height, etc.\n */\n wrapperStyle?: React.CSSProperties;\n};\n\ninterface ImageProps\n extends ComponentPropsWithout<'img', RemovedProps | 'color' | 'width' | 'height' | 'alt'>,\n MarginProps,\n WidthProps,\n HeightProps,\n LayoutProps,\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', wrapperStyle, ...restProps } = props;\n const {\n asChild,\n className,\n radius,\n style,\n loading = 'lazy',\n alt,\n src,\n placeholder,\n showSkeleton = false,\n fadeIn = true,\n onLoad: userOnLoad,\n onError: userOnError,\n children,\n ...wrapperProps\n } = extractProps(\n restProps,\n imagePropDefs,\n marginPropDefs,\n widthPropDefs,\n heightPropDefs,\n layoutPropDefs,\n );\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 // Ref to check if image is already loaded (for cached images)\n const imgRef = React.useRef<HTMLImageElement>(null);\n\n // Handle image load\n const handleLoad = React.useCallback(\n (event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(true);\n setImageError(false);\n setShowPlaceholder(false);\n userOnLoad?.(event);\n },\n [userOnLoad],\n );\n\n // Handle image error\n const handleError = React.useCallback(\n (event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(false);\n setImageError(true);\n setShowPlaceholder(false);\n userOnError?.(event);\n },\n [userOnError],\n );\n\n // Check if image is already loaded (for cached images)\n React.useEffect(() => {\n const img = imgRef.current;\n if (img && img.complete && img.naturalWidth > 0) {\n setImageLoaded(true);\n setImageError(false);\n setShowPlaceholder(false);\n }\n }, [src]);\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 // Common image styles that apply to the actual img element\n const imgStyle: React.CSSProperties = {\n width: '100%',\n height: '100%',\n display: 'block',\n opacity: fadeIn ? (imageLoaded ? 1 : 0) : 1,\n transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',\n ...style, // Allow style overrides for the image\n };\n\n // Wrapper styles that get all the sizing and positioning\n const wrapperStyleFinal: React.CSSProperties = {\n position: 'relative',\n display: 'block', // Use block instead of inline-block to work better with AspectRatio\n ...wrapperStyle,\n };\n\n // Create skeleton placeholder\n const skeletonElement =\n showSkeleton && !imageLoaded && !imageError ? (\n <Skeleton\n width=\"100%\"\n height=\"100px\" // Default height, can be overridden by wrapper\n style={{\n borderRadius: radius ? `var(--radius-${radius})` : undefined,\n }}\n className={className}\n />\n ) : null;\n\n // Create placeholder image element\n const placeholderElement =\n placeholder && showPlaceholder ? (\n <img\n data-radius={radius}\n style={{\n ...imgStyle,\n filter: 'blur(4px)',\n opacity: 0.7,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--placeholder', className)}\n alt=\"\"\n src={placeholder}\n />\n ) : null;\n\n // Handle asChild - inject content 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 textDecoration: 'none',\n color: 'inherit',\n border: 'none',\n background: 'none',\n padding: 0,\n font: 'inherit',\n cursor: 'pointer',\n ...wrapperStyleFinal,\n ...style, // Apply sizing to the child element\n ...child.props?.style,\n },\n children: (\n <>\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n position: 'absolute',\n top: '0',\n left: '0',\n width: '105%',\n height: '105%',\n transform: 'translate(-2.5%, -2.5%)',\n filter: 'blur(16px) saturate(1.5)',\n opacity: 0.5,\n zIndex: -1,\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur-bg', className)}\n alt=\"\"\n src={src}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={imgStyle}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n ref={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </>\n ),\n });\n } else {\n // For surface variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className),\n style: {\n textDecoration: 'none',\n color: 'inherit',\n border: 'none',\n background: 'none',\n padding: 0,\n font: 'inherit',\n cursor: 'pointer',\n ...wrapperStyleFinal,\n ...child.props?.style,\n },\n children: (\n <>\n {skeletonElement}\n {placeholderElement}\n <img\n data-radius={radius}\n loading={loading}\n style={imgStyle}\n className={classNames('rt-reset', 'rt-Image', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n ref={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </>\n ),\n });\n }\n }\n\n // Regular rendering without asChild - both variants use Box wrapper\n if (variant === 'blur') {\n return (\n <Box\n className={classNames('rt-variant-blur', className)}\n style={{\n ...style, // Include the width/height styles from extractProps\n ...wrapperStyleFinal,\n }}\n {...wrapperProps} // Apply other props to wrapper\n >\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n position: 'absolute',\n top: '0',\n left: '0',\n width: '105%',\n height: '105%',\n transform: 'translate(-2.5%, -2.5%)',\n filter: 'blur(16px) saturate(1.5)',\n opacity: 0.5,\n zIndex: -1,\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur-bg', className)}\n alt=\"\"\n src={src}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={imgStyle}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n ref={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </Box>\n );\n }\n\n // Surface variant - also use Box wrapper for consistency\n return (\n <Box\n className={className}\n style={{\n ...style, // Include the width/height styles from extractProps\n ...wrapperStyleFinal,\n }}\n {...wrapperProps} // Apply other props to wrapper\n >\n {skeletonElement}\n {placeholderElement}\n <img\n data-radius={radius}\n loading={loading}\n style={imgStyle}\n className={classNames('rt-reset', 'rt-Image', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n ref={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </Box>\n );\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_layout_props", "import_skeleton", "import_box", "props", "forwardedRef", "variant", "wrapperStyle", "restProps", "asChild", "className", "radius", "style", "loading", "alt", "src", "placeholder", "showSkeleton", "fadeIn", "userOnLoad", "userOnError", "children", "wrapperProps", "imageLoaded", "setImageLoaded", "imageError", "setImageError", "showPlaceholder", "setShowPlaceholder", "imgRef", "handleLoad", "event", "handleError", "img", "imgStyle", "wrapperStyleFinal", "skeletonElement", "placeholderElement", "classNames", "child", "node"]
|
|
7
7
|
}
|
|
@@ -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;AASjD,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,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,OAAO,CAAC;IACjB;;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;IAClE;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CACpC,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,WAAW,EACX,aAAa;IACf;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,QAAA,MAAM,KAAK,
|
|
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;AASjD,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,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,OAAO,CAAC;IACjB;;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;IAClE;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CACpC,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,WAAW,EACX,aAAa;IACf;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;CACb;AAED,QAAA,MAAM,KAAK,qFA0TT,CAAC;AAIH,OAAO,EAAE,KAAK,EAAE,CAAC;AACjB,YAAY,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import*as
|
|
1
|
+
"use client";import*as e from"react";import s from"classnames";import{imagePropDefs as B}from"./image.props.js";import{extractProps as q}from"../helpers/extract-props.js";import{marginPropDefs as A}from"../props/margin.props.js";import{widthPropDefs as G}from"../props/width.props.js";import{heightPropDefs as F}from"../props/height.props.js";import{layoutPropDefs as $}from"../props/layout.props.js";import{Skeleton as J}from"./skeleton.js";import{Box as w}from"./box.js";const H=e.forwardRef((M,r)=>{const{variant:b="surface",wrapperStyle:T,...j}=M,{asChild:E,className:o,radius:a,style:u,loading:i="lazy",alt:p,src:n,placeholder:d,showSkeleton:W=!1,fadeIn:S=!0,onLoad:L,onError:N,children:v,...x}=q(j,B,A,G,F,$),[D,f]=e.useState(!1),[z,I]=e.useState(!1),[O,P]=e.useState(!!d),m=e.useRef(null),g=e.useCallback(t=>{f(!0),I(!1),P(!1),L?.(t)},[L]),h=e.useCallback(t=>{f(!1),I(!0),P(!1),N?.(t)},[N]);if(e.useEffect(()=>{const t=m.current;t&&t.complete&&t.naturalWidth>0&&(f(!0),I(!1),P(!1))},[n]),!n)return console.warn("Image component: src prop is required"),null;!E&&p===void 0&&console.warn("Image component: alt prop is required for accessibility when not using asChild");const c={width:"100%",height:"100%",display:"block",opacity:S?D?1:0:1,transition:S?"opacity 0.3s ease-out":"none",...u},y={position:"relative",display:"block",...T},k=W&&!D&&!z?e.createElement(J,{width:"100%",height:"100px",style:{borderRadius:a?`var(--radius-${a})`:void 0},className:o}):null,C=d&&O?e.createElement("img",{"data-radius":a,style:{...c,filter:"blur(4px)",opacity:.7,transition:"opacity 0.3s ease-out"},className:s("rt-reset","rt-Image","rt-Image--placeholder",o),alt:"",src:d}):null;if(E&&v){const t=e.Children.only(v);return b==="blur"?e.cloneElement(t,{className:s(t.props?.className,"rt-variant-blur"),style:{textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...y,...u,...t.props?.style},children:e.createElement(e.Fragment,null,e.createElement("img",{"data-radius":a,loading:i,style:{position:"absolute",top:"0",left:"0",width:"105%",height:"105%",transform:"translate(-2.5%, -2.5%)",filter:"blur(16px) saturate(1.5)",opacity:.5,zIndex:-1},className:s("rt-reset","rt-Image","rt-Image--blur-bg",o),alt:"",src:n}),e.createElement("img",{"data-radius":a,loading:i,style:c,className:s("rt-reset","rt-Image","rt-Image--blur",o),alt:p,src:n,onLoad:g,onError:h,ref:l=>{m.current=l,typeof r=="function"?r(l):r&&(r.current=l)}}))}):e.cloneElement(t,{className:s(t.props?.className),style:{textDecoration:"none",color:"inherit",border:"none",background:"none",padding:0,font:"inherit",cursor:"pointer",...y,...t.props?.style},children:e.createElement(e.Fragment,null,k,C,e.createElement("img",{"data-radius":a,loading:i,style:c,className:s("rt-reset","rt-Image",o),alt:p,src:n,onLoad:g,onError:h,ref:l=>{m.current=l,typeof r=="function"?r(l):r&&(r.current=l)}}))})}return b==="blur"?e.createElement(w,{className:s("rt-variant-blur",o),style:{...u,...y},...x},e.createElement("img",{"data-radius":a,loading:i,style:{position:"absolute",top:"0",left:"0",width:"105%",height:"105%",transform:"translate(-2.5%, -2.5%)",filter:"blur(16px) saturate(1.5)",opacity:.5,zIndex:-1},className:s("rt-reset","rt-Image","rt-Image--blur-bg",o),alt:"",src:n}),e.createElement("img",{"data-radius":a,loading:i,style:c,className:s("rt-reset","rt-Image","rt-Image--blur",o),alt:p,src:n,onLoad:g,onError:h,ref:t=>{m.current=t,typeof r=="function"?r(t):r&&(r.current=t)}})):e.createElement(w,{className:o,style:{...u,...y},...x},k,C,e.createElement("img",{"data-radius":a,loading:i,style:c,className:s("rt-reset","rt-Image",o),alt:p,src:n,onLoad:g,onError:h,ref:t=>{m.current=t,typeof r=="function"?r(t):r&&(r.current=t)}}))});H.displayName="Image";export{H 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';\nimport { layoutPropDefs } from '../props/layout.props.js';\nimport { Skeleton } from './skeleton.js';\nimport { Box } from './box.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 { LayoutProps } from '../props/layout.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 * Whether the image should fade in when loaded. Set to false for background images or when you want immediate visibility.\n */\n fadeIn?: 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 * Style object to apply to the wrapper container. Useful for overriding display, width, height, etc.\n */\n wrapperStyle?: React.CSSProperties;\n};\n\ninterface ImageProps\n extends ComponentPropsWithout<'img', RemovedProps | 'color' | 'width' | 'height' | 'alt'>,\n MarginProps,\n WidthProps,\n HeightProps,\n LayoutProps,\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', wrapperStyle, ...restProps } = props;\n const {\n asChild,\n className,\n radius,\n style,\n loading = 'lazy',\n alt,\n src,\n placeholder,\n showSkeleton = false,\n fadeIn = true,\n onLoad: userOnLoad,\n onError: userOnError,\n children,\n ...imgProps\n } = extractProps(\n restProps,\n imagePropDefs,\n marginPropDefs,\n widthPropDefs,\n heightPropDefs,\n layoutPropDefs,\n );\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 // Ref to check if image is already loaded (for cached images)\n const imgRef = React.useRef<HTMLImageElement>(null);\n\n // Handle image load - moved to top to avoid conditional hook call\n const handleLoad = React.useCallback(\n (event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(true);\n setImageError(false);\n setShowPlaceholder(false);\n userOnLoad?.(event);\n },\n [userOnLoad],\n );\n\n // Handle image error - moved to top to avoid conditional hook call\n const handleError = React.useCallback(\n (event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(false);\n setImageError(true);\n setShowPlaceholder(false);\n userOnError?.(event);\n },\n [userOnError],\n );\n\n // Check if image is already loaded (for cached images)\n React.useEffect(() => {\n const img = imgRef.current;\n if (img && img.complete && img.naturalWidth > 0) {\n setImageLoaded(true);\n setImageError(false);\n setShowPlaceholder(false);\n }\n }, [src]);\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 =\n showSkeleton && !imageLoaded && !imageError ? (\n <Skeleton\n width=\"100%\"\n height=\"100px\" // Default height, can be overridden by style\n style={{\n ...style,\n borderRadius: radius ? `var(--radius-${radius})` : undefined,\n }}\n className={className}\n />\n ) : null;\n\n // Create placeholder image element\n const placeholderElement =\n placeholder && showPlaceholder ? (\n <img\n data-radius={radius}\n style={{\n ...style,\n filter: 'blur(4px)',\n opacity: 0.7,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--placeholder', className)}\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: fadeIn ? (imageLoaded ? (style?.opacity ?? 1) : 0) : (style?.opacity ?? 1),\n transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',\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={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n );\n\n // Wrapper for images with placeholders\n const imageWithPlaceholder =\n placeholder || showSkeleton ? (\n <Box position=\"relative\" display=\"inline-block\" style={wrapperStyle}>\n {skeletonElement}\n {placeholderElement}\n {imgElement}\n </Box>\n ) : (\n imgElement\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 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 <Box position=\"relative\" display=\"inline-block\" style={wrapperStyle}>\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: fadeIn ? (imageLoaded ? (style?.opacity ?? 1) : 0) : (style?.opacity ?? 1),\n transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',\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={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </Box>\n ),\n });\n } else {\n // For surface variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className),\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 display: 'inline-block', // Ensure proper sizing\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 <Box\n className=\"rt-variant-blur\"\n position=\"relative\"\n display=\"inline-block\"\n style={wrapperStyle}\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: fadeIn ? (imageLoaded ? (style?.opacity ?? 1) : 0) : (style?.opacity ?? 1),\n transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',\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={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </Box>\n );\n }\n\n return imageWithPlaceholder;\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,2BAC/B,OAAS,kBAAAC,MAAsB,2BAC/B,OAAS,YAAAC,MAAgB,gBACzB,OAAS,OAAAC,MAAW,WAqDpB,MAAMC,EAAQV,EAAM,WAAqC,CAACW,EAAOC,IAAiB,CAChF,KAAM,CAAE,QAAAC,EAAU,UAAW,aAAAC,EAAc,GAAGC,CAAU,EAAIJ,EACtD,CACJ,QAAAK,EACA,UAAAC,EACA,OAAAC,EACA,MAAAC,EACA,QAAAC,EAAU,OACV,IAAAC,EACA,IAAAC,EACA,YAAAC,EACA,aAAAC,EAAe,GACf,OAAAC,EAAS,GACT,OAAQC,EACR,QAASC,EACT,SAAAC,EACA,GAAGC,CACL,EAAI1B,EACFY,EACAb,EACAE,EACAC,EACAC,EACAC,CACF,EAGM,CAACuB,EAAaC,CAAc,EAAI/B,EAAM,SAAS,EAAK,EACpD,CAACgC,EAAYC,CAAa,EAAIjC,EAAM,SAAS,EAAK,EAClD,CAACkC,EAAiBC,CAAkB,EAAInC,EAAM,SAAS,CAAC,CAACuB,CAAW,EAGpEa,EAASpC,EAAM,OAAyB,IAAI,EAG5CqC,EAAarC,EAAM,YACtBsC,GAAkD,CACjDP,EAAe,EAAI,EACnBE,EAAc,EAAK,EACnBE,EAAmB,EAAK,EACxBT,IAAaY,CAAK,CACpB,EACA,CAACZ,CAAU,CACb,EAGMa,EAAcvC,EAAM,YACvBsC,GAAkD,CACjDP,EAAe,EAAK,EACpBE,EAAc,EAAI,EAClBE,EAAmB,EAAK,EACxBR,IAAcW,CAAK,CACrB,EACA,CAACX,CAAW,CACd,EAaA,GAVA3B,EAAM,UAAU,IAAM,CACpB,MAAMwC,EAAMJ,EAAO,QACfI,GAAOA,EAAI,UAAYA,EAAI,aAAe,IAC5CT,EAAe,EAAI,EACnBE,EAAc,EAAK,EACnBE,EAAmB,EAAK,EAE5B,EAAG,CAACb,CAAG,CAAC,EAGJ,CAACA,EACH,eAAQ,KAAK,uCAAuC,EAC7C,KAGL,CAACN,GAAWK,IAAQ,QACtB,QAAQ,KAAK,gFAAgF,EAI/F,MAAMoB,
|
|
6
|
-
"names": ["React", "classNames", "imagePropDefs", "extractProps", "marginPropDefs", "widthPropDefs", "heightPropDefs", "layoutPropDefs", "Skeleton", "Box", "Image", "props", "forwardedRef", "variant", "wrapperStyle", "restProps", "asChild", "className", "radius", "style", "loading", "alt", "src", "placeholder", "showSkeleton", "fadeIn", "userOnLoad", "userOnError", "children", "
|
|
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 { layoutPropDefs } from '../props/layout.props.js';\nimport { Skeleton } from './skeleton.js';\nimport { Box } from './box.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 { LayoutProps } from '../props/layout.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 * Whether the image should fade in when loaded. Set to false for background images or when you want immediate visibility.\n */\n fadeIn?: 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 * Style object to apply to the wrapper container. Useful for overriding display, width, height, etc.\n */\n wrapperStyle?: React.CSSProperties;\n};\n\ninterface ImageProps\n extends ComponentPropsWithout<'img', RemovedProps | 'color' | 'width' | 'height' | 'alt'>,\n MarginProps,\n WidthProps,\n HeightProps,\n LayoutProps,\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', wrapperStyle, ...restProps } = props;\n const {\n asChild,\n className,\n radius,\n style,\n loading = 'lazy',\n alt,\n src,\n placeholder,\n showSkeleton = false,\n fadeIn = true,\n onLoad: userOnLoad,\n onError: userOnError,\n children,\n ...wrapperProps\n } = extractProps(\n restProps,\n imagePropDefs,\n marginPropDefs,\n widthPropDefs,\n heightPropDefs,\n layoutPropDefs,\n );\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 // Ref to check if image is already loaded (for cached images)\n const imgRef = React.useRef<HTMLImageElement>(null);\n\n // Handle image load\n const handleLoad = React.useCallback(\n (event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(true);\n setImageError(false);\n setShowPlaceholder(false);\n userOnLoad?.(event);\n },\n [userOnLoad],\n );\n\n // Handle image error\n const handleError = React.useCallback(\n (event: React.SyntheticEvent<HTMLImageElement>) => {\n setImageLoaded(false);\n setImageError(true);\n setShowPlaceholder(false);\n userOnError?.(event);\n },\n [userOnError],\n );\n\n // Check if image is already loaded (for cached images)\n React.useEffect(() => {\n const img = imgRef.current;\n if (img && img.complete && img.naturalWidth > 0) {\n setImageLoaded(true);\n setImageError(false);\n setShowPlaceholder(false);\n }\n }, [src]);\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 // Common image styles that apply to the actual img element\n const imgStyle: React.CSSProperties = {\n width: '100%',\n height: '100%',\n display: 'block',\n opacity: fadeIn ? (imageLoaded ? 1 : 0) : 1,\n transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',\n ...style, // Allow style overrides for the image\n };\n\n // Wrapper styles that get all the sizing and positioning\n const wrapperStyleFinal: React.CSSProperties = {\n position: 'relative',\n display: 'block', // Use block instead of inline-block to work better with AspectRatio\n ...wrapperStyle,\n };\n\n // Create skeleton placeholder\n const skeletonElement =\n showSkeleton && !imageLoaded && !imageError ? (\n <Skeleton\n width=\"100%\"\n height=\"100px\" // Default height, can be overridden by wrapper\n style={{\n borderRadius: radius ? `var(--radius-${radius})` : undefined,\n }}\n className={className}\n />\n ) : null;\n\n // Create placeholder image element\n const placeholderElement =\n placeholder && showPlaceholder ? (\n <img\n data-radius={radius}\n style={{\n ...imgStyle,\n filter: 'blur(4px)',\n opacity: 0.7,\n transition: 'opacity 0.3s ease-out',\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--placeholder', className)}\n alt=\"\"\n src={placeholder}\n />\n ) : null;\n\n // Handle asChild - inject content 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 textDecoration: 'none',\n color: 'inherit',\n border: 'none',\n background: 'none',\n padding: 0,\n font: 'inherit',\n cursor: 'pointer',\n ...wrapperStyleFinal,\n ...style, // Apply sizing to the child element\n ...child.props?.style,\n },\n children: (\n <>\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n position: 'absolute',\n top: '0',\n left: '0',\n width: '105%',\n height: '105%',\n transform: 'translate(-2.5%, -2.5%)',\n filter: 'blur(16px) saturate(1.5)',\n opacity: 0.5,\n zIndex: -1,\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur-bg', className)}\n alt=\"\"\n src={src}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={imgStyle}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n ref={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </>\n ),\n });\n } else {\n // For surface variant with asChild\n return React.cloneElement(child, {\n className: classNames(child.props?.className),\n style: {\n textDecoration: 'none',\n color: 'inherit',\n border: 'none',\n background: 'none',\n padding: 0,\n font: 'inherit',\n cursor: 'pointer',\n ...wrapperStyleFinal,\n ...child.props?.style,\n },\n children: (\n <>\n {skeletonElement}\n {placeholderElement}\n <img\n data-radius={radius}\n loading={loading}\n style={imgStyle}\n className={classNames('rt-reset', 'rt-Image', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n ref={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </>\n ),\n });\n }\n }\n\n // Regular rendering without asChild - both variants use Box wrapper\n if (variant === 'blur') {\n return (\n <Box\n className={classNames('rt-variant-blur', className)}\n style={{\n ...style, // Include the width/height styles from extractProps\n ...wrapperStyleFinal,\n }}\n {...wrapperProps} // Apply other props to wrapper\n >\n {/* Background blurred image */}\n <img\n data-radius={radius}\n loading={loading}\n style={{\n position: 'absolute',\n top: '0',\n left: '0',\n width: '105%',\n height: '105%',\n transform: 'translate(-2.5%, -2.5%)',\n filter: 'blur(16px) saturate(1.5)',\n opacity: 0.5,\n zIndex: -1,\n }}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur-bg', className)}\n alt=\"\"\n src={src}\n />\n {/* Foreground image */}\n <img\n data-radius={radius}\n loading={loading}\n style={imgStyle}\n className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n ref={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </Box>\n );\n }\n\n // Surface variant - also use Box wrapper for consistency\n return (\n <Box\n className={className}\n style={{\n ...style, // Include the width/height styles from extractProps\n ...wrapperStyleFinal,\n }}\n {...wrapperProps} // Apply other props to wrapper\n >\n {skeletonElement}\n {placeholderElement}\n <img\n data-radius={radius}\n loading={loading}\n style={imgStyle}\n className={classNames('rt-reset', 'rt-Image', className)}\n alt={alt}\n src={src}\n onLoad={handleLoad}\n onError={handleError}\n ref={(node) => {\n imgRef.current = node;\n if (typeof forwardedRef === 'function') {\n forwardedRef(node);\n } else if (forwardedRef) {\n forwardedRef.current = node;\n }\n }}\n />\n </Box>\n );\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", "layoutPropDefs", "Skeleton", "Box", "Image", "props", "forwardedRef", "variant", "wrapperStyle", "restProps", "asChild", "className", "radius", "style", "loading", "alt", "src", "placeholder", "showSkeleton", "fadeIn", "userOnLoad", "userOnError", "children", "wrapperProps", "imageLoaded", "setImageLoaded", "imageError", "setImageError", "showPlaceholder", "setShowPlaceholder", "imgRef", "handleLoad", "event", "handleError", "img", "imgStyle", "wrapperStyleFinal", "skeletonElement", "placeholderElement", "child", "node"]
|
|
7
7
|
}
|
package/package.json
CHANGED
package/src/components/image.css
CHANGED
|
@@ -60,6 +60,10 @@
|
|
|
60
60
|
/* Blur variant wrapper */
|
|
61
61
|
.rt-variant-blur {
|
|
62
62
|
position: relative;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Blur variant when used with asChild - use inline-block for proper sizing */
|
|
66
|
+
.rt-variant-blur--as-child {
|
|
63
67
|
display: inline-block;
|
|
64
68
|
}
|
|
65
69
|
|
|
@@ -93,28 +97,14 @@
|
|
|
93
97
|
box-shadow: var(--box-shadow) !important;
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
/* Blur background image */
|
|
100
|
+
/* Blur background image - simplified */
|
|
97
101
|
.rt-Image--blur-bg {
|
|
98
|
-
|
|
99
|
-
top: var(--blur-offset-y, 8px);
|
|
100
|
-
left: var(--blur-offset-x, 0);
|
|
101
|
-
filter: var(--blur-filter);
|
|
102
|
-
opacity: var(--blur-opacity);
|
|
103
|
-
z-index: -1;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/* Blur variant CSS variables */
|
|
107
|
-
.rt-variant-blur {
|
|
108
|
-
--blur-filter: blur(16px) saturate(1.5);
|
|
109
|
-
--blur-opacity: 0.5;
|
|
110
|
-
--blur-offset-y: 8px;
|
|
111
|
-
--blur-offset-x: 0;
|
|
102
|
+
/* No additional styles needed - all handled inline */
|
|
112
103
|
}
|
|
113
104
|
|
|
114
|
-
/* Image inside blur variant
|
|
105
|
+
/* Image inside blur variant - simplified */
|
|
115
106
|
.rt-Image--blur {
|
|
116
|
-
|
|
117
|
-
z-index: 1;
|
|
107
|
+
/* No additional styles needed - all handled inline */
|
|
118
108
|
}
|
|
119
109
|
|
|
120
110
|
/* Object fit variants */
|
package/src/components/image.tsx
CHANGED
|
@@ -79,7 +79,7 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
|
|
|
79
79
|
onLoad: userOnLoad,
|
|
80
80
|
onError: userOnError,
|
|
81
81
|
children,
|
|
82
|
-
...
|
|
82
|
+
...wrapperProps
|
|
83
83
|
} = extractProps(
|
|
84
84
|
restProps,
|
|
85
85
|
imagePropDefs,
|
|
@@ -97,7 +97,7 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
|
|
|
97
97
|
// Ref to check if image is already loaded (for cached images)
|
|
98
98
|
const imgRef = React.useRef<HTMLImageElement>(null);
|
|
99
99
|
|
|
100
|
-
// Handle image load
|
|
100
|
+
// Handle image load
|
|
101
101
|
const handleLoad = React.useCallback(
|
|
102
102
|
(event: React.SyntheticEvent<HTMLImageElement>) => {
|
|
103
103
|
setImageLoaded(true);
|
|
@@ -108,7 +108,7 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
|
|
|
108
108
|
[userOnLoad],
|
|
109
109
|
);
|
|
110
110
|
|
|
111
|
-
// Handle image error
|
|
111
|
+
// Handle image error
|
|
112
112
|
const handleError = React.useCallback(
|
|
113
113
|
(event: React.SyntheticEvent<HTMLImageElement>) => {
|
|
114
114
|
setImageLoaded(false);
|
|
@@ -139,14 +139,30 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
|
|
|
139
139
|
console.warn('Image component: alt prop is required for accessibility when not using asChild');
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
// Common image styles that apply to the actual img element
|
|
143
|
+
const imgStyle: React.CSSProperties = {
|
|
144
|
+
width: '100%',
|
|
145
|
+
height: '100%',
|
|
146
|
+
display: 'block',
|
|
147
|
+
opacity: fadeIn ? (imageLoaded ? 1 : 0) : 1,
|
|
148
|
+
transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',
|
|
149
|
+
...style, // Allow style overrides for the image
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// Wrapper styles that get all the sizing and positioning
|
|
153
|
+
const wrapperStyleFinal: React.CSSProperties = {
|
|
154
|
+
position: 'relative',
|
|
155
|
+
display: 'block', // Use block instead of inline-block to work better with AspectRatio
|
|
156
|
+
...wrapperStyle,
|
|
157
|
+
};
|
|
158
|
+
|
|
142
159
|
// Create skeleton placeholder
|
|
143
160
|
const skeletonElement =
|
|
144
161
|
showSkeleton && !imageLoaded && !imageError ? (
|
|
145
162
|
<Skeleton
|
|
146
163
|
width="100%"
|
|
147
|
-
height="100px" // Default height, can be overridden by
|
|
164
|
+
height="100px" // Default height, can be overridden by wrapper
|
|
148
165
|
style={{
|
|
149
|
-
...style,
|
|
150
166
|
borderRadius: radius ? `var(--radius-${radius})` : undefined,
|
|
151
167
|
}}
|
|
152
168
|
className={className}
|
|
@@ -159,7 +175,7 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
|
|
|
159
175
|
<img
|
|
160
176
|
data-radius={radius}
|
|
161
177
|
style={{
|
|
162
|
-
...
|
|
178
|
+
...imgStyle,
|
|
163
179
|
filter: 'blur(4px)',
|
|
164
180
|
opacity: 0.7,
|
|
165
181
|
transition: 'opacity 0.3s ease-out',
|
|
@@ -170,51 +186,7 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
|
|
|
170
186
|
/>
|
|
171
187
|
) : null;
|
|
172
188
|
|
|
173
|
-
//
|
|
174
|
-
const imgElement = (
|
|
175
|
-
<img
|
|
176
|
-
data-radius={radius}
|
|
177
|
-
loading={loading}
|
|
178
|
-
style={{
|
|
179
|
-
...style,
|
|
180
|
-
opacity: fadeIn ? (imageLoaded ? (style?.opacity ?? 1) : 0) : (style?.opacity ?? 1),
|
|
181
|
-
transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',
|
|
182
|
-
}}
|
|
183
|
-
className={classNames(
|
|
184
|
-
'rt-reset',
|
|
185
|
-
'rt-Image',
|
|
186
|
-
variant === 'blur' && 'rt-Image--blur',
|
|
187
|
-
className,
|
|
188
|
-
)}
|
|
189
|
-
alt={alt}
|
|
190
|
-
src={src}
|
|
191
|
-
onLoad={handleLoad}
|
|
192
|
-
onError={handleError}
|
|
193
|
-
{...imgProps}
|
|
194
|
-
ref={(node) => {
|
|
195
|
-
imgRef.current = node;
|
|
196
|
-
if (typeof forwardedRef === 'function') {
|
|
197
|
-
forwardedRef(node);
|
|
198
|
-
} else if (forwardedRef) {
|
|
199
|
-
forwardedRef.current = node;
|
|
200
|
-
}
|
|
201
|
-
}}
|
|
202
|
-
/>
|
|
203
|
-
);
|
|
204
|
-
|
|
205
|
-
// Wrapper for images with placeholders
|
|
206
|
-
const imageWithPlaceholder =
|
|
207
|
-
placeholder || showSkeleton ? (
|
|
208
|
-
<Box position="relative" display="inline-block" style={wrapperStyle}>
|
|
209
|
-
{skeletonElement}
|
|
210
|
-
{placeholderElement}
|
|
211
|
-
{imgElement}
|
|
212
|
-
</Box>
|
|
213
|
-
) : (
|
|
214
|
-
imgElement
|
|
215
|
-
);
|
|
216
|
-
|
|
217
|
-
// Handle asChild - inject img into the child element
|
|
189
|
+
// Handle asChild - inject content into the child element
|
|
218
190
|
if (asChild && children) {
|
|
219
191
|
const child = React.Children.only(children) as React.ReactElement<any>;
|
|
220
192
|
|
|
@@ -223,55 +195,48 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
|
|
|
223
195
|
return React.cloneElement(child, {
|
|
224
196
|
className: classNames(child.props?.className, 'rt-variant-blur'),
|
|
225
197
|
style: {
|
|
226
|
-
textDecoration: 'none',
|
|
227
|
-
color: 'inherit',
|
|
228
|
-
border: 'none',
|
|
229
|
-
background: 'none',
|
|
230
|
-
padding: 0,
|
|
231
|
-
font: 'inherit',
|
|
232
|
-
cursor: 'pointer',
|
|
198
|
+
textDecoration: 'none',
|
|
199
|
+
color: 'inherit',
|
|
200
|
+
border: 'none',
|
|
201
|
+
background: 'none',
|
|
202
|
+
padding: 0,
|
|
203
|
+
font: 'inherit',
|
|
204
|
+
cursor: 'pointer',
|
|
205
|
+
...wrapperStyleFinal,
|
|
206
|
+
...style, // Apply sizing to the child element
|
|
233
207
|
...child.props?.style,
|
|
234
208
|
},
|
|
235
209
|
children: (
|
|
236
|
-
|
|
210
|
+
<>
|
|
237
211
|
{/* Background blurred image */}
|
|
238
212
|
<img
|
|
239
213
|
data-radius={radius}
|
|
240
214
|
loading={loading}
|
|
241
215
|
style={{
|
|
242
|
-
...style,
|
|
243
216
|
position: 'absolute',
|
|
244
|
-
top: '
|
|
217
|
+
top: '0',
|
|
245
218
|
left: '0',
|
|
219
|
+
width: '105%',
|
|
220
|
+
height: '105%',
|
|
221
|
+
transform: 'translate(-2.5%, -2.5%)',
|
|
222
|
+
filter: 'blur(16px) saturate(1.5)',
|
|
223
|
+
opacity: 0.5,
|
|
224
|
+
zIndex: -1,
|
|
246
225
|
}}
|
|
247
|
-
className={classNames(
|
|
248
|
-
'rt-reset',
|
|
249
|
-
'rt-Image',
|
|
250
|
-
'rt-Image--blur',
|
|
251
|
-
'rt-Image--blur-bg',
|
|
252
|
-
className,
|
|
253
|
-
)}
|
|
226
|
+
className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur-bg', className)}
|
|
254
227
|
alt=""
|
|
255
228
|
src={src}
|
|
256
|
-
{...imgProps}
|
|
257
229
|
/>
|
|
258
230
|
{/* Foreground image */}
|
|
259
231
|
<img
|
|
260
232
|
data-radius={radius}
|
|
261
233
|
loading={loading}
|
|
262
|
-
style={
|
|
263
|
-
...style,
|
|
264
|
-
position: 'relative',
|
|
265
|
-
zIndex: 1,
|
|
266
|
-
opacity: fadeIn ? (imageLoaded ? (style?.opacity ?? 1) : 0) : (style?.opacity ?? 1),
|
|
267
|
-
transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',
|
|
268
|
-
}}
|
|
234
|
+
style={imgStyle}
|
|
269
235
|
className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}
|
|
270
236
|
alt={alt}
|
|
271
237
|
src={src}
|
|
272
238
|
onLoad={handleLoad}
|
|
273
239
|
onError={handleError}
|
|
274
|
-
{...imgProps}
|
|
275
240
|
ref={(node) => {
|
|
276
241
|
imgRef.current = node;
|
|
277
242
|
if (typeof forwardedRef === 'function') {
|
|
@@ -281,7 +246,7 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
|
|
|
281
246
|
}
|
|
282
247
|
}}
|
|
283
248
|
/>
|
|
284
|
-
|
|
249
|
+
</>
|
|
285
250
|
),
|
|
286
251
|
});
|
|
287
252
|
} else {
|
|
@@ -289,68 +254,84 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
|
|
|
289
254
|
return React.cloneElement(child, {
|
|
290
255
|
className: classNames(child.props?.className),
|
|
291
256
|
style: {
|
|
292
|
-
textDecoration: 'none',
|
|
293
|
-
color: 'inherit',
|
|
294
|
-
border: 'none',
|
|
295
|
-
background: 'none',
|
|
296
|
-
padding: 0,
|
|
297
|
-
font: 'inherit',
|
|
298
|
-
cursor: 'pointer',
|
|
299
|
-
|
|
300
|
-
...child.props?.style,
|
|
257
|
+
textDecoration: 'none',
|
|
258
|
+
color: 'inherit',
|
|
259
|
+
border: 'none',
|
|
260
|
+
background: 'none',
|
|
261
|
+
padding: 0,
|
|
262
|
+
font: 'inherit',
|
|
263
|
+
cursor: 'pointer',
|
|
264
|
+
...wrapperStyleFinal,
|
|
265
|
+
...child.props?.style,
|
|
301
266
|
},
|
|
302
|
-
children:
|
|
267
|
+
children: (
|
|
268
|
+
<>
|
|
269
|
+
{skeletonElement}
|
|
270
|
+
{placeholderElement}
|
|
271
|
+
<img
|
|
272
|
+
data-radius={radius}
|
|
273
|
+
loading={loading}
|
|
274
|
+
style={imgStyle}
|
|
275
|
+
className={classNames('rt-reset', 'rt-Image', className)}
|
|
276
|
+
alt={alt}
|
|
277
|
+
src={src}
|
|
278
|
+
onLoad={handleLoad}
|
|
279
|
+
onError={handleError}
|
|
280
|
+
ref={(node) => {
|
|
281
|
+
imgRef.current = node;
|
|
282
|
+
if (typeof forwardedRef === 'function') {
|
|
283
|
+
forwardedRef(node);
|
|
284
|
+
} else if (forwardedRef) {
|
|
285
|
+
forwardedRef.current = node;
|
|
286
|
+
}
|
|
287
|
+
}}
|
|
288
|
+
/>
|
|
289
|
+
</>
|
|
290
|
+
),
|
|
303
291
|
});
|
|
304
292
|
}
|
|
305
293
|
}
|
|
306
294
|
|
|
307
|
-
// Regular rendering without asChild
|
|
295
|
+
// Regular rendering without asChild - both variants use Box wrapper
|
|
308
296
|
if (variant === 'blur') {
|
|
309
297
|
return (
|
|
310
298
|
<Box
|
|
311
|
-
className=
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
299
|
+
className={classNames('rt-variant-blur', className)}
|
|
300
|
+
style={{
|
|
301
|
+
...style, // Include the width/height styles from extractProps
|
|
302
|
+
...wrapperStyleFinal,
|
|
303
|
+
}}
|
|
304
|
+
{...wrapperProps} // Apply other props to wrapper
|
|
315
305
|
>
|
|
316
306
|
{/* Background blurred image */}
|
|
317
307
|
<img
|
|
318
308
|
data-radius={radius}
|
|
319
309
|
loading={loading}
|
|
320
310
|
style={{
|
|
321
|
-
...style,
|
|
322
311
|
position: 'absolute',
|
|
323
|
-
top: '
|
|
312
|
+
top: '0',
|
|
324
313
|
left: '0',
|
|
314
|
+
width: '105%',
|
|
315
|
+
height: '105%',
|
|
316
|
+
transform: 'translate(-2.5%, -2.5%)',
|
|
317
|
+
filter: 'blur(16px) saturate(1.5)',
|
|
318
|
+
opacity: 0.5,
|
|
319
|
+
zIndex: -1,
|
|
325
320
|
}}
|
|
326
|
-
className={classNames(
|
|
327
|
-
'rt-reset',
|
|
328
|
-
'rt-Image',
|
|
329
|
-
'rt-Image--blur',
|
|
330
|
-
'rt-Image--blur-bg',
|
|
331
|
-
className,
|
|
332
|
-
)}
|
|
321
|
+
className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur-bg', className)}
|
|
333
322
|
alt=""
|
|
334
323
|
src={src}
|
|
335
|
-
{...imgProps}
|
|
336
324
|
/>
|
|
337
325
|
{/* Foreground image */}
|
|
338
326
|
<img
|
|
339
327
|
data-radius={radius}
|
|
340
328
|
loading={loading}
|
|
341
|
-
style={
|
|
342
|
-
...style,
|
|
343
|
-
position: 'relative',
|
|
344
|
-
zIndex: 1,
|
|
345
|
-
opacity: fadeIn ? (imageLoaded ? (style?.opacity ?? 1) : 0) : (style?.opacity ?? 1),
|
|
346
|
-
transition: fadeIn ? 'opacity 0.3s ease-out' : 'none',
|
|
347
|
-
}}
|
|
329
|
+
style={imgStyle}
|
|
348
330
|
className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}
|
|
349
331
|
alt={alt}
|
|
350
332
|
src={src}
|
|
351
333
|
onLoad={handleLoad}
|
|
352
334
|
onError={handleError}
|
|
353
|
-
{...imgProps}
|
|
354
335
|
ref={(node) => {
|
|
355
336
|
imgRef.current = node;
|
|
356
337
|
if (typeof forwardedRef === 'function') {
|
|
@@ -364,7 +345,38 @@ const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) =
|
|
|
364
345
|
);
|
|
365
346
|
}
|
|
366
347
|
|
|
367
|
-
|
|
348
|
+
// Surface variant - also use Box wrapper for consistency
|
|
349
|
+
return (
|
|
350
|
+
<Box
|
|
351
|
+
className={className}
|
|
352
|
+
style={{
|
|
353
|
+
...style, // Include the width/height styles from extractProps
|
|
354
|
+
...wrapperStyleFinal,
|
|
355
|
+
}}
|
|
356
|
+
{...wrapperProps} // Apply other props to wrapper
|
|
357
|
+
>
|
|
358
|
+
{skeletonElement}
|
|
359
|
+
{placeholderElement}
|
|
360
|
+
<img
|
|
361
|
+
data-radius={radius}
|
|
362
|
+
loading={loading}
|
|
363
|
+
style={imgStyle}
|
|
364
|
+
className={classNames('rt-reset', 'rt-Image', className)}
|
|
365
|
+
alt={alt}
|
|
366
|
+
src={src}
|
|
367
|
+
onLoad={handleLoad}
|
|
368
|
+
onError={handleError}
|
|
369
|
+
ref={(node) => {
|
|
370
|
+
imgRef.current = node;
|
|
371
|
+
if (typeof forwardedRef === 'function') {
|
|
372
|
+
forwardedRef(node);
|
|
373
|
+
} else if (forwardedRef) {
|
|
374
|
+
forwardedRef.current = node;
|
|
375
|
+
}
|
|
376
|
+
}}
|
|
377
|
+
/>
|
|
378
|
+
</Box>
|
|
379
|
+
);
|
|
368
380
|
});
|
|
369
381
|
|
|
370
382
|
Image.displayName = 'Image';
|
package/styles.css
CHANGED
|
@@ -3329,7 +3329,7 @@
|
|
|
3329
3329
|
--backdrop-blur-dialog: 32px;
|
|
3330
3330
|
--panel-opacity-light: 0.75;
|
|
3331
3331
|
--panel-opacity-heavy: 0.75;
|
|
3332
|
-
--surface-opacity-light: 0.
|
|
3332
|
+
--surface-opacity-light: 0.5;
|
|
3333
3333
|
--surface-opacity-heavy: 0.75;
|
|
3334
3334
|
--surface-opacity-dark: 0.25;
|
|
3335
3335
|
--dialog-opacity-light: 0.75;
|
|
@@ -12730,11 +12730,9 @@
|
|
|
12730
12730
|
}
|
|
12731
12731
|
.rt-variant-blur {
|
|
12732
12732
|
position: relative;
|
|
12733
|
+
}
|
|
12734
|
+
.rt-variant-blur--as-child {
|
|
12733
12735
|
display: inline-block;
|
|
12734
|
-
--blur-filter: blur(16px) saturate(1.5);
|
|
12735
|
-
--blur-opacity: 0.5;
|
|
12736
|
-
--blur-offset-y: 8px;
|
|
12737
|
-
--blur-offset-x: 0;
|
|
12738
12736
|
}
|
|
12739
12737
|
.rt-variant-blur:where(:any-link, button, label) {
|
|
12740
12738
|
cursor: pointer;
|
|
@@ -12758,18 +12756,6 @@
|
|
|
12758
12756
|
outline: none !important;
|
|
12759
12757
|
box-shadow: var(--box-shadow) !important;
|
|
12760
12758
|
}
|
|
12761
|
-
.rt-Image--blur-bg {
|
|
12762
|
-
position: absolute;
|
|
12763
|
-
top: var(--blur-offset-y, 8px);
|
|
12764
|
-
left: var(--blur-offset-x, 0);
|
|
12765
|
-
filter: var(--blur-filter);
|
|
12766
|
-
opacity: var(--blur-opacity);
|
|
12767
|
-
z-index: -1;
|
|
12768
|
-
}
|
|
12769
|
-
.rt-Image--blur {
|
|
12770
|
-
position: relative;
|
|
12771
|
-
z-index: 1;
|
|
12772
|
-
}
|
|
12773
12759
|
.rt-r-fit-cover {
|
|
12774
12760
|
--object-fit: cover;
|
|
12775
12761
|
}
|
package/tokens.css
CHANGED
|
@@ -3313,7 +3313,7 @@
|
|
|
3313
3313
|
--backdrop-blur-dialog: 32px;
|
|
3314
3314
|
--panel-opacity-light: 0.75;
|
|
3315
3315
|
--panel-opacity-heavy: 0.75;
|
|
3316
|
-
--surface-opacity-light: 0.
|
|
3316
|
+
--surface-opacity-light: 0.5;
|
|
3317
3317
|
--surface-opacity-heavy: 0.75;
|
|
3318
3318
|
--surface-opacity-dark: 0.25;
|
|
3319
3319
|
--dialog-opacity-light: 0.75;
|