@kushagradhawan/kookie-ui 0.1.8 → 0.1.10
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 +156 -97
- package/dist/cjs/components/image.d.ts +2 -2
- 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/cjs/components/image.props.d.ts +16 -0
- package/dist/cjs/components/image.props.d.ts.map +1 -1
- package/dist/cjs/components/image.props.js +1 -1
- package/dist/cjs/components/image.props.js.map +3 -3
- package/dist/esm/components/image.d.ts +2 -2
- 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/dist/esm/components/image.props.d.ts +16 -0
- package/dist/esm/components/image.props.d.ts.map +1 -1
- package/dist/esm/components/image.props.js +1 -1
- package/dist/esm/components/image.props.js.map +3 -3
- package/package.json +1 -1
- package/src/components/button.css +8 -8
- package/src/components/icon-button.css +8 -8
- package/src/components/image.css +89 -1
- package/src/components/image.props.ts +17 -0
- package/src/components/image.tsx +133 -4
- package/styles.css +156 -97
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import*as
|
|
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};
|
|
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.\n */\n alt
|
|
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,CACJ,UAAAC,EACA,OAAAC,EACA,MAAAC,EACA,QAAAC,EAAU,OACV,IAAAC,EACA,GAAGC,CACL,
|
|
6
|
-
"names": ["React", "classNames", "imagePropDefs", "extractProps", "marginPropDefs", "widthPropDefs", "heightPropDefs", "Image", "props", "forwardedRef", "className", "radius", "style", "loading", "alt", "imgProps"]
|
|
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 = '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,IAAAC,EAAM,QAAS,SAAAC,CAAS,EAAIJ,EACnD,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"]
|
|
7
7
|
}
|
|
@@ -28,6 +28,22 @@ declare const imagePropDefs: {
|
|
|
28
28
|
default: "cover";
|
|
29
29
|
responsive: true;
|
|
30
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* Sets the visual variant of the image.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* variant="surface"
|
|
36
|
+
* variant="blur"
|
|
37
|
+
*/
|
|
38
|
+
variant: {
|
|
39
|
+
type: "enum";
|
|
40
|
+
className: string;
|
|
41
|
+
values: readonly ["surface", "blur"];
|
|
42
|
+
default: "surface";
|
|
43
|
+
};
|
|
44
|
+
asChild: {
|
|
45
|
+
type: "boolean";
|
|
46
|
+
};
|
|
31
47
|
};
|
|
32
48
|
export { imagePropDefs };
|
|
33
49
|
//# sourceMappingURL=image.props.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.props.d.ts","sourceRoot":"","sources":["../../../src/components/image.props.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"image.props.d.ts","sourceRoot":"","sources":["../../../src/components/image.props.ts"],"names":[],"mappings":"AASA,QAAA,MAAM,aAAa;;;;;;;;;;;;IAEjB;;;;;;;;;;OAUG;;;;;;;;IAQH;;;;;;OAMG;;;;;;;;;;CAYJ,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{asChildPropDef as e}from"../props/as-child.prop.js";import{radiusPropDef as r}from"../props/radius.prop.js";import{shadowPropDefs as o}from"../props/shadow.props.js";const t=["cover","contain","fill","scale-down","none"],s=["surface","blur"],a={...e,fit:{type:"enum",className:"rt-r-fit",values:t,default:"cover",responsive:!0},variant:{type:"enum",className:"rt-variant",values:s,default:"surface"},...r,...o};export{a as imagePropDefs};
|
|
2
2
|
//# sourceMappingURL=image.props.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/components/image.props.ts"],
|
|
4
|
-
"sourcesContent": ["import { radiusPropDef } from '../props/radius.prop.js';\nimport { shadowPropDefs } from '../props/shadow.props.js';\n\nimport type { PropDef } from '../props/prop-def.js';\n\nconst objectFitValues = ['cover', 'contain', 'fill', 'scale-down', 'none'] as const;\n\nconst imagePropDefs = {\n /**\n * Sets the CSS **object-fit** property.\n * Controls how the image should be resized to fit its container.\n *\n * @example\n * fit=\"cover\"\n * fit=\"contain\"\n *\n * @link\n * https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit\n */\n fit: {\n type: 'enum',\n className: 'rt-r-fit',\n values: objectFitValues,\n default: 'cover',\n responsive: true,\n },\n ...radiusPropDef,\n ...shadowPropDefs,\n} satisfies {\n fit: PropDef<(typeof objectFitValues)[number]>;\n};\n\nexport { imagePropDefs };\n"],
|
|
5
|
-
"mappings": "AAAA,OAAS,
|
|
6
|
-
"names": ["radiusPropDef", "shadowPropDefs", "objectFitValues", "imagePropDefs"]
|
|
4
|
+
"sourcesContent": ["import { asChildPropDef } from '../props/as-child.prop.js';\nimport { radiusPropDef } from '../props/radius.prop.js';\nimport { shadowPropDefs } from '../props/shadow.props.js';\n\nimport type { PropDef } from '../props/prop-def.js';\n\nconst objectFitValues = ['cover', 'contain', 'fill', 'scale-down', 'none'] as const;\nconst variants = ['surface', 'blur'] as const;\n\nconst imagePropDefs = {\n ...asChildPropDef,\n /**\n * Sets the CSS **object-fit** property.\n * Controls how the image should be resized to fit its container.\n *\n * @example\n * fit=\"cover\"\n * fit=\"contain\"\n *\n * @link\n * https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit\n */\n fit: {\n type: 'enum',\n className: 'rt-r-fit',\n values: objectFitValues,\n default: 'cover',\n responsive: true,\n },\n /**\n * Sets the visual variant of the image.\n *\n * @example\n * variant=\"surface\"\n * variant=\"blur\"\n */\n variant: {\n type: 'enum',\n className: 'rt-variant',\n values: variants,\n default: 'surface',\n },\n ...radiusPropDef,\n ...shadowPropDefs,\n} satisfies {\n fit: PropDef<(typeof objectFitValues)[number]>;\n variant: PropDef<(typeof variants)[number]>;\n};\n\nexport { imagePropDefs };\n"],
|
|
5
|
+
"mappings": "AAAA,OAAS,kBAAAA,MAAsB,4BAC/B,OAAS,iBAAAC,MAAqB,0BAC9B,OAAS,kBAAAC,MAAsB,2BAI/B,MAAMC,EAAkB,CAAC,QAAS,UAAW,OAAQ,aAAc,MAAM,EACnEC,EAAW,CAAC,UAAW,MAAM,EAE7BC,EAAgB,CACpB,GAAGL,EAYH,IAAK,CACH,KAAM,OACN,UAAW,WACX,OAAQG,EACR,QAAS,QACT,WAAY,EACd,EAQA,QAAS,CACP,KAAM,OACN,UAAW,aACX,OAAQC,EACR,QAAS,SACX,EACA,GAAGH,EACH,GAAGC,CACL",
|
|
6
|
+
"names": ["asChildPropDef", "radiusPropDef", "shadowPropDefs", "objectFitValues", "variants", "imagePropDefs"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
|
|
32
32
|
/* stylelint-disable-next-line selector-max-type */
|
|
33
33
|
& :where(svg) {
|
|
34
|
-
width:
|
|
35
|
-
height:
|
|
34
|
+
width: 16px;
|
|
35
|
+
height: 16px;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
&:where(:not(.rt-variant-ghost)) {
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
|
|
54
54
|
/* stylelint-disable-next-line selector-max-type */
|
|
55
55
|
& :where(svg) {
|
|
56
|
-
width:
|
|
57
|
-
height:
|
|
56
|
+
width: 18px;
|
|
57
|
+
height: 18px;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
&:where(:not(.rt-variant-ghost)) {
|
|
@@ -75,8 +75,8 @@
|
|
|
75
75
|
|
|
76
76
|
/* stylelint-disable-next-line selector-max-type */
|
|
77
77
|
& :where(svg) {
|
|
78
|
-
width:
|
|
79
|
-
height:
|
|
78
|
+
width: 20px;
|
|
79
|
+
height: 20px;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
&:where(:not(.rt-variant-ghost)) {
|
|
@@ -97,8 +97,8 @@
|
|
|
97
97
|
|
|
98
98
|
/* stylelint-disable-next-line selector-max-type */
|
|
99
99
|
& :where(svg) {
|
|
100
|
-
width:
|
|
101
|
-
height:
|
|
100
|
+
width: 22px;
|
|
101
|
+
height: 22px;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
&:where(:not(.rt-variant-ghost)) {
|
|
@@ -16,29 +16,29 @@
|
|
|
16
16
|
&:where(.rt-r-size-1) {
|
|
17
17
|
/* stylelint-disable-next-line selector-max-type */
|
|
18
18
|
& :where(svg) {
|
|
19
|
-
width:
|
|
20
|
-
height:
|
|
19
|
+
width: 16px;
|
|
20
|
+
height: 16px;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
&:where(.rt-r-size-2) {
|
|
24
24
|
/* stylelint-disable-next-line selector-max-type */
|
|
25
25
|
& :where(svg) {
|
|
26
|
-
width:
|
|
27
|
-
height:
|
|
26
|
+
width: 18px;
|
|
27
|
+
height: 18px;
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
&:where(.rt-r-size-3) {
|
|
31
31
|
/* stylelint-disable-next-line selector-max-type */
|
|
32
32
|
& :where(svg) {
|
|
33
|
-
width:
|
|
34
|
-
height:
|
|
33
|
+
width: 20px;
|
|
34
|
+
height: 20px;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
&:where(.rt-r-size-4) {
|
|
38
38
|
/* stylelint-disable-next-line selector-max-type */
|
|
39
39
|
& :where(svg) {
|
|
40
|
-
width:
|
|
41
|
-
height:
|
|
40
|
+
width: 22px;
|
|
41
|
+
height: 22px;
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
}
|
package/src/components/image.css
CHANGED
|
@@ -1,8 +1,96 @@
|
|
|
1
|
+
/* stylelint-disable selector-max-type */
|
|
2
|
+
/* Disable selector-max-type rule to target `button` and `a` tags. */
|
|
3
|
+
/* Make sure these tags are wrapped in `:where()` for 0 specificity. */
|
|
4
|
+
|
|
1
5
|
.rt-Image {
|
|
2
6
|
display: block;
|
|
3
7
|
object-fit: var(--object-fit);
|
|
4
8
|
box-shadow: var(--box-shadow);
|
|
5
|
-
border-radius: max(var(--radius-
|
|
9
|
+
border-radius: max(var(--radius-4), var(--radius-full));
|
|
10
|
+
transition: var(--transition-button);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Interactive states - follows Card pattern */
|
|
14
|
+
.rt-Image:where(:any-link, button, label) {
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
|
|
17
|
+
@media (hover: hover) {
|
|
18
|
+
&:where(:hover) {
|
|
19
|
+
transform: scale(1.02);
|
|
20
|
+
box-shadow:
|
|
21
|
+
var(--box-shadow, var(--shadow-2)),
|
|
22
|
+
0 0 0 1px var(--gray-a4);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&:where(:focus-visible) {
|
|
27
|
+
outline: 2px solid var(--focus-8);
|
|
28
|
+
outline-offset: 2px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&:where(:active) {
|
|
32
|
+
transform: scale(0.98);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Blur variant wrapper */
|
|
37
|
+
.rt-variant-blur {
|
|
38
|
+
position: relative;
|
|
39
|
+
display: inline-block;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Interactive states for blur variant - follows Card pattern */
|
|
43
|
+
.rt-variant-blur:where(:any-link, button, label) {
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
transition: var(--transition-button);
|
|
46
|
+
|
|
47
|
+
@media (hover: hover) {
|
|
48
|
+
&:where(:hover) {
|
|
49
|
+
transform: scale(1.02);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
&:where(:focus-visible) {
|
|
54
|
+
outline: 2px solid var(--focus-8);
|
|
55
|
+
outline-offset: 2px;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
&:where(:active) {
|
|
59
|
+
transform: scale(0.98);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Disable individual image interactions when inside blur variant */
|
|
64
|
+
/* stylelint-disable-next-line selector-max-specificity */
|
|
65
|
+
.rt-variant-blur:where(:any-link, button, label) .rt-Image {
|
|
66
|
+
cursor: inherit;
|
|
67
|
+
transform: none !important;
|
|
68
|
+
outline: none !important;
|
|
69
|
+
box-shadow: var(--box-shadow) !important;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Blur background image */
|
|
73
|
+
.rt-Image--blur-bg {
|
|
74
|
+
position: absolute;
|
|
75
|
+
top: var(--blur-offset-y, 8px);
|
|
76
|
+
left: var(--blur-offset-x, 0);
|
|
77
|
+
filter: var(--blur-filter);
|
|
78
|
+
opacity: var(--blur-opacity);
|
|
79
|
+
z-index: -1;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Blur variant CSS variables */
|
|
83
|
+
.rt-variant-blur {
|
|
84
|
+
--blur-filter: blur(16px) saturate(1.5);
|
|
85
|
+
--blur-opacity: 0.5;
|
|
86
|
+
--blur-offset-y: 8px;
|
|
87
|
+
--blur-offset-x: 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Image inside blur variant gets positioned */
|
|
91
|
+
.rt-Image--blur {
|
|
92
|
+
position: relative;
|
|
93
|
+
z-index: 1;
|
|
6
94
|
}
|
|
7
95
|
|
|
8
96
|
/* Object fit variants */
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { asChildPropDef } from '../props/as-child.prop.js';
|
|
1
2
|
import { radiusPropDef } from '../props/radius.prop.js';
|
|
2
3
|
import { shadowPropDefs } from '../props/shadow.props.js';
|
|
3
4
|
|
|
4
5
|
import type { PropDef } from '../props/prop-def.js';
|
|
5
6
|
|
|
6
7
|
const objectFitValues = ['cover', 'contain', 'fill', 'scale-down', 'none'] as const;
|
|
8
|
+
const variants = ['surface', 'blur'] as const;
|
|
7
9
|
|
|
8
10
|
const imagePropDefs = {
|
|
11
|
+
...asChildPropDef,
|
|
9
12
|
/**
|
|
10
13
|
* Sets the CSS **object-fit** property.
|
|
11
14
|
* Controls how the image should be resized to fit its container.
|
|
@@ -24,10 +27,24 @@ const imagePropDefs = {
|
|
|
24
27
|
default: 'cover',
|
|
25
28
|
responsive: true,
|
|
26
29
|
},
|
|
30
|
+
/**
|
|
31
|
+
* Sets the visual variant of the image.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* variant="surface"
|
|
35
|
+
* variant="blur"
|
|
36
|
+
*/
|
|
37
|
+
variant: {
|
|
38
|
+
type: 'enum',
|
|
39
|
+
className: 'rt-variant',
|
|
40
|
+
values: variants,
|
|
41
|
+
default: 'surface',
|
|
42
|
+
},
|
|
27
43
|
...radiusPropDef,
|
|
28
44
|
...shadowPropDefs,
|
|
29
45
|
} satisfies {
|
|
30
46
|
fit: PropDef<(typeof objectFitValues)[number]>;
|
|
47
|
+
variant: PropDef<(typeof variants)[number]>;
|
|
31
48
|
};
|
|
32
49
|
|
|
33
50
|
export { imagePropDefs };
|
package/src/components/image.tsx
CHANGED
|
@@ -28,32 +28,161 @@ interface ImageProps
|
|
|
28
28
|
ImageOwnProps {
|
|
29
29
|
/**
|
|
30
30
|
* The alt attribute provides alternative information for an image if a user for some reason cannot view it.
|
|
31
|
-
* Required for accessibility.
|
|
31
|
+
* Required for accessibility when not using asChild.
|
|
32
32
|
*/
|
|
33
|
-
alt
|
|
33
|
+
alt?: string;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
const Image = React.forwardRef<ImageElement, ImageProps>((props, forwardedRef) => {
|
|
37
|
+
const { variant = 'surface', fit = 'cover', children } = props;
|
|
37
38
|
const {
|
|
39
|
+
asChild,
|
|
38
40
|
className,
|
|
39
41
|
radius,
|
|
40
42
|
style,
|
|
41
43
|
loading = 'lazy',
|
|
42
44
|
alt,
|
|
45
|
+
src,
|
|
46
|
+
children: _children, // Extract children to exclude from imgProps
|
|
43
47
|
...imgProps
|
|
44
48
|
} = extractProps(props, imagePropDefs, marginPropDefs, widthPropDefs, heightPropDefs);
|
|
45
49
|
|
|
46
|
-
|
|
50
|
+
// Create the standard img element
|
|
51
|
+
const imgElement = (
|
|
47
52
|
<img
|
|
48
53
|
data-radius={radius}
|
|
49
54
|
loading={loading}
|
|
50
55
|
style={style}
|
|
51
|
-
className={classNames(
|
|
56
|
+
className={classNames(
|
|
57
|
+
'rt-reset',
|
|
58
|
+
'rt-Image',
|
|
59
|
+
variant === 'blur' && 'rt-Image--blur',
|
|
60
|
+
className,
|
|
61
|
+
)}
|
|
52
62
|
alt={alt}
|
|
63
|
+
src={src}
|
|
53
64
|
{...imgProps}
|
|
54
65
|
ref={forwardedRef}
|
|
55
66
|
/>
|
|
56
67
|
);
|
|
68
|
+
|
|
69
|
+
// Handle asChild - inject img into the child element
|
|
70
|
+
if (asChild && children) {
|
|
71
|
+
const child = React.Children.only(children) as React.ReactElement<any>;
|
|
72
|
+
|
|
73
|
+
if (variant === 'blur') {
|
|
74
|
+
// For blur variant with asChild
|
|
75
|
+
return React.cloneElement(child, {
|
|
76
|
+
className: classNames(child.props?.className, 'rt-variant-blur'),
|
|
77
|
+
style: {
|
|
78
|
+
position: 'relative',
|
|
79
|
+
display: 'inline-block',
|
|
80
|
+
textDecoration: 'none', // Reset link underlines
|
|
81
|
+
color: 'inherit', // Reset link colors
|
|
82
|
+
border: 'none', // Reset button borders
|
|
83
|
+
background: 'none', // Reset button backgrounds
|
|
84
|
+
padding: 0, // Reset button padding
|
|
85
|
+
font: 'inherit', // Reset button fonts
|
|
86
|
+
cursor: 'pointer', // Ensure interactive cursor
|
|
87
|
+
...child.props?.style,
|
|
88
|
+
},
|
|
89
|
+
children: (
|
|
90
|
+
<>
|
|
91
|
+
{/* Background blurred image */}
|
|
92
|
+
<img
|
|
93
|
+
data-radius={radius}
|
|
94
|
+
loading={loading}
|
|
95
|
+
style={{
|
|
96
|
+
...style,
|
|
97
|
+
position: 'absolute',
|
|
98
|
+
top: '8px',
|
|
99
|
+
left: '0',
|
|
100
|
+
}}
|
|
101
|
+
className={classNames(
|
|
102
|
+
'rt-reset',
|
|
103
|
+
'rt-Image',
|
|
104
|
+
'rt-Image--blur',
|
|
105
|
+
'rt-Image--blur-bg',
|
|
106
|
+
className,
|
|
107
|
+
)}
|
|
108
|
+
alt=""
|
|
109
|
+
src={src}
|
|
110
|
+
{...imgProps}
|
|
111
|
+
/>
|
|
112
|
+
{/* Foreground image */}
|
|
113
|
+
<img
|
|
114
|
+
data-radius={radius}
|
|
115
|
+
loading={loading}
|
|
116
|
+
style={{ ...style, position: 'relative', zIndex: 1 }}
|
|
117
|
+
className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}
|
|
118
|
+
alt={alt}
|
|
119
|
+
src={src}
|
|
120
|
+
{...imgProps}
|
|
121
|
+
ref={forwardedRef}
|
|
122
|
+
/>
|
|
123
|
+
</>
|
|
124
|
+
),
|
|
125
|
+
});
|
|
126
|
+
} else {
|
|
127
|
+
// For surface variant with asChild
|
|
128
|
+
return React.cloneElement(child, {
|
|
129
|
+
className: classNames(child.props?.className, 'rt-Image'),
|
|
130
|
+
style: {
|
|
131
|
+
textDecoration: 'none', // Reset link underlines
|
|
132
|
+
color: 'inherit', // Reset link colors
|
|
133
|
+
border: 'none', // Reset button borders
|
|
134
|
+
background: 'none', // Reset button backgrounds
|
|
135
|
+
padding: 0, // Reset button padding
|
|
136
|
+
font: 'inherit', // Reset button fonts
|
|
137
|
+
cursor: 'pointer', // Ensure interactive cursor
|
|
138
|
+
...child.props?.style, // Allow user overrides
|
|
139
|
+
},
|
|
140
|
+
children: imgElement,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Regular rendering without asChild
|
|
146
|
+
if (variant === 'blur') {
|
|
147
|
+
return (
|
|
148
|
+
<div className="rt-variant-blur" style={{ position: 'relative', display: 'inline-block' }}>
|
|
149
|
+
{/* Background blurred image */}
|
|
150
|
+
<img
|
|
151
|
+
data-radius={radius}
|
|
152
|
+
loading={loading}
|
|
153
|
+
style={{
|
|
154
|
+
...style,
|
|
155
|
+
position: 'absolute',
|
|
156
|
+
top: '8px',
|
|
157
|
+
left: '0',
|
|
158
|
+
}}
|
|
159
|
+
className={classNames(
|
|
160
|
+
'rt-reset',
|
|
161
|
+
'rt-Image',
|
|
162
|
+
'rt-Image--blur',
|
|
163
|
+
'rt-Image--blur-bg',
|
|
164
|
+
className,
|
|
165
|
+
)}
|
|
166
|
+
alt=""
|
|
167
|
+
src={src}
|
|
168
|
+
{...imgProps}
|
|
169
|
+
/>
|
|
170
|
+
{/* Foreground image */}
|
|
171
|
+
<img
|
|
172
|
+
data-radius={radius}
|
|
173
|
+
loading={loading}
|
|
174
|
+
style={{ ...style, position: 'relative', zIndex: 1 }}
|
|
175
|
+
className={classNames('rt-reset', 'rt-Image', 'rt-Image--blur', className)}
|
|
176
|
+
alt={alt}
|
|
177
|
+
src={src}
|
|
178
|
+
{...imgProps}
|
|
179
|
+
ref={forwardedRef}
|
|
180
|
+
/>
|
|
181
|
+
</div>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return imgElement;
|
|
57
186
|
});
|
|
58
187
|
|
|
59
188
|
Image.displayName = 'Image';
|