@tarunachyutuni/images 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+
2
+ > @tarunachyutuni/images@2.0.0 build C:\Users\Tarun\lumina\packages\images
3
+ > tsc
4
+
@@ -0,0 +1,60 @@
1
+ export interface ImageProps {
2
+ src: string;
3
+ alt: string;
4
+ width?: number;
5
+ height?: number;
6
+ loading?: "lazy" | "eager";
7
+ decoding?: "async" | "sync";
8
+ className?: string;
9
+ sizes?: string;
10
+ srcSet?: string;
11
+ }
12
+ export interface ImageOptimization {
13
+ format: "webp" | "avif" | "jpeg" | "png";
14
+ quality: number;
15
+ width: number;
16
+ height?: number;
17
+ }
18
+ export interface ResponsiveImageSet {
19
+ breakpoints: {
20
+ width: number;
21
+ src: string;
22
+ }[];
23
+ alt: string;
24
+ sizes: string;
25
+ }
26
+ export declare const IMAGE_FORMATS: {
27
+ readonly webp: {
28
+ readonly mime: "image/webp";
29
+ readonly ext: ".webp";
30
+ };
31
+ readonly avif: {
32
+ readonly mime: "image/avif";
33
+ readonly ext: ".avif";
34
+ };
35
+ readonly jpeg: {
36
+ readonly mime: "image/jpeg";
37
+ readonly ext: ".jpg";
38
+ };
39
+ readonly png: {
40
+ readonly mime: "image/png";
41
+ readonly ext: ".png";
42
+ };
43
+ };
44
+ export declare class ImageAgent {
45
+ generateSrcSet(baseUrl: string, widths?: number[]): string;
46
+ generateSizes(breakpoints: {
47
+ minWidth: string;
48
+ size: string;
49
+ }[]): string;
50
+ generateAltText(imageUrl: string, context?: string): Promise<string>;
51
+ optimizeImage(src: string, optimization: ImageOptimization): string;
52
+ generatePlaceholder(width: number, height: number, text?: string): string;
53
+ generateBlurHash(width: number, height: number): string;
54
+ validateImageProps(props: ImageProps): {
55
+ valid: boolean;
56
+ issues: string[];
57
+ };
58
+ responsiveSet(baseUrl: string, aspectRatio?: string): ResponsiveImageSet;
59
+ }
60
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;CAKhB,CAAC;AAEX,qBAAa,UAAU;IACrB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,EAAsC,GAAG,MAAM;IAI7F,aAAa,CAAC,WAAW,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,MAAM;IAIlE,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAI1E,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,iBAAiB,GAAG,MAAM;IAMnE,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAQzE,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IASvD,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE;IAc3E,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,GAAE,MAAe,GAAG,kBAAkB;CAajF"}
package/dist/index.js ADDED
@@ -0,0 +1,64 @@
1
+ // =============================================================================
2
+ // @tarunachyutuni/images — Intelligent Image Handling
3
+ // =============================================================================
4
+ export const IMAGE_FORMATS = {
5
+ webp: { mime: "image/webp", ext: ".webp" },
6
+ avif: { mime: "image/avif", ext: ".avif" },
7
+ jpeg: { mime: "image/jpeg", ext: ".jpg" },
8
+ png: { mime: "image/png", ext: ".png" },
9
+ };
10
+ export class ImageAgent {
11
+ generateSrcSet(baseUrl, widths = [320, 640, 768, 1024, 1280, 1920]) {
12
+ return widths.map((w) => `${baseUrl}?w=${w} ${w}w`).join(", ");
13
+ }
14
+ generateSizes(breakpoints) {
15
+ return breakpoints.map((b) => `${b.minWidth} ${b.size}`).join(", ");
16
+ }
17
+ async generateAltText(imageUrl, context) {
18
+ return context ?? "Image description";
19
+ }
20
+ optimizeImage(src, optimization) {
21
+ const { format, quality, width } = optimization;
22
+ if (src.includes("?"))
23
+ return `${src}&fm=${format === "jpeg" ? "jpg" : format}&q=${quality}&w=${width}`;
24
+ return `${src}?fm=${format === "jpeg" ? "jpg" : format}&q=${quality}&w=${width}`;
25
+ }
26
+ generatePlaceholder(width, height, text) {
27
+ return `data:image/svg+xml,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" fill="%23f5f5f5">
28
+ <text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle" font-family="system-ui" font-size="14" fill="%23999">${text ?? `${width}×${height}`}</text>
29
+ </svg>`)}`;
30
+ }
31
+ generateBlurHash(width, height) {
32
+ return `data:image/svg+xml,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
33
+ <filter id="blur"><feGaussianBlur stdDeviation="20"/></filter>
34
+ <rect width="100%" height="100%" fill="#e2e8f0" filter="url(#blur)"/>
35
+ </svg>`)}`;
36
+ }
37
+ validateImageProps(props) {
38
+ const issues = [];
39
+ if (!props.alt || props.alt.length < 5) {
40
+ issues.push("Alt text too short — should be descriptive");
41
+ }
42
+ if (!props.width || !props.height) {
43
+ issues.push("Missing width/height — causes layout shift (CLS)");
44
+ }
45
+ if (!props.loading || props.loading !== "lazy") {
46
+ issues.push("Consider loading='lazy' for below-fold images");
47
+ }
48
+ return { valid: issues.length === 0, issues };
49
+ }
50
+ responsiveSet(baseUrl, aspectRatio = "16/9") {
51
+ return {
52
+ breakpoints: [
53
+ { width: 320, src: `${baseUrl}?w=320` },
54
+ { width: 640, src: `${baseUrl}?w=640` },
55
+ { width: 768, src: `${baseUrl}?w=768` },
56
+ { width: 1024, src: `${baseUrl}?w=1024` },
57
+ { width: 1280, src: `${baseUrl}?w=1280` },
58
+ ],
59
+ alt: "",
60
+ sizes: "(max-width: 320px) 320px, (max-width: 640px) 640px, (max-width: 768px) 768px, (max-width: 1024px) 1024px, 1280px",
61
+ };
62
+ }
63
+ }
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "@tarunachyutuni/images",
3
+ "version": "2.0.0",
4
+ "description": "Images package for Lumina",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist-index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "dependencies": {
16
+ "@tarunachyutuni/types": "2.0.0"
17
+ },
18
+ "devDependencies": {
19
+ "typescript": "^5.5.0"
20
+ },
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "typecheck": "tsc --noEmit"
27
+ }
28
+ }
package/src/index.ts ADDED
@@ -0,0 +1,101 @@
1
+ // =============================================================================
2
+ // @tarunachyutuni/images — Intelligent Image Handling
3
+ // =============================================================================
4
+
5
+ export interface ImageProps {
6
+ src: string;
7
+ alt: string;
8
+ width?: number;
9
+ height?: number;
10
+ loading?: "lazy" | "eager";
11
+ decoding?: "async" | "sync";
12
+ className?: string;
13
+ sizes?: string;
14
+ srcSet?: string;
15
+ }
16
+
17
+ export interface ImageOptimization {
18
+ format: "webp" | "avif" | "jpeg" | "png";
19
+ quality: number;
20
+ width: number;
21
+ height?: number;
22
+ }
23
+
24
+ export interface ResponsiveImageSet {
25
+ breakpoints: { width: number; src: string }[];
26
+ alt: string;
27
+ sizes: string;
28
+ }
29
+
30
+ export const IMAGE_FORMATS = {
31
+ webp: { mime: "image/webp", ext: ".webp" },
32
+ avif: { mime: "image/avif", ext: ".avif" },
33
+ jpeg: { mime: "image/jpeg", ext: ".jpg" },
34
+ png: { mime: "image/png", ext: ".png" },
35
+ } as const;
36
+
37
+ export class ImageAgent {
38
+ generateSrcSet(baseUrl: string, widths: number[] = [320, 640, 768, 1024, 1280, 1920]): string {
39
+ return widths.map((w) => `${baseUrl}?w=${w} ${w}w`).join(", ");
40
+ }
41
+
42
+ generateSizes(breakpoints: { minWidth: string; size: string }[]): string {
43
+ return breakpoints.map((b) => `${b.minWidth} ${b.size}`).join(", ");
44
+ }
45
+
46
+ async generateAltText(imageUrl: string, context?: string): Promise<string> {
47
+ return context ?? "Image description";
48
+ }
49
+
50
+ optimizeImage(src: string, optimization: ImageOptimization): string {
51
+ const { format, quality, width } = optimization;
52
+ if (src.includes("?")) return `${src}&fm=${format === "jpeg" ? "jpg" : format}&q=${quality}&w=${width}`;
53
+ return `${src}?fm=${format === "jpeg" ? "jpg" : format}&q=${quality}&w=${width}`;
54
+ }
55
+
56
+ generatePlaceholder(width: number, height: number, text?: string): string {
57
+ return `data:image/svg+xml,${encodeURIComponent(
58
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" fill="%23f5f5f5">
59
+ <text x="50%" y="50%" text-anchor="middle" dominant-baseline="middle" font-family="system-ui" font-size="14" fill="%23999">${text ?? `${width}×${height}`}</text>
60
+ </svg>`
61
+ )}`;
62
+ }
63
+
64
+ generateBlurHash(width: number, height: number): string {
65
+ return `data:image/svg+xml,${encodeURIComponent(
66
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
67
+ <filter id="blur"><feGaussianBlur stdDeviation="20"/></filter>
68
+ <rect width="100%" height="100%" fill="#e2e8f0" filter="url(#blur)"/>
69
+ </svg>`
70
+ )}`;
71
+ }
72
+
73
+ validateImageProps(props: ImageProps): { valid: boolean; issues: string[] } {
74
+ const issues: string[] = [];
75
+ if (!props.alt || props.alt.length < 5) {
76
+ issues.push("Alt text too short — should be descriptive");
77
+ }
78
+ if (!props.width || !props.height) {
79
+ issues.push("Missing width/height — causes layout shift (CLS)");
80
+ }
81
+ if (!props.loading || props.loading !== "lazy") {
82
+ issues.push("Consider loading='lazy' for below-fold images");
83
+ }
84
+ return { valid: issues.length === 0, issues };
85
+ }
86
+
87
+ responsiveSet(baseUrl: string, aspectRatio: string = "16/9"): ResponsiveImageSet {
88
+ return {
89
+ breakpoints: [
90
+ { width: 320, src: `${baseUrl}?w=320` },
91
+ { width: 640, src: `${baseUrl}?w=640` },
92
+ { width: 768, src: `${baseUrl}?w=768` },
93
+ { width: 1024, src: `${baseUrl}?w=1024` },
94
+ { width: 1280, src: `${baseUrl}?w=1280` },
95
+ ],
96
+ alt: "",
97
+ sizes: "(max-width: 320px) 320px, (max-width: 640px) 640px, (max-width: 768px) 768px, (max-width: 1024px) 1024px, 1280px",
98
+ };
99
+ }
100
+ }
101
+
package/tsconfig.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": { "outDir": "./dist", "rootDir": "./src" },
4
+ "include": ["src/**/*"]
5
+ }