@herowcode/utils 1.4.8 → 1.5.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,110 @@
1
+ 'use strict';
2
+
3
+ var clsx = require('clsx');
4
+ var Image = require('next/image');
5
+ var react = require('react');
6
+ var tailwindMerge = require('tailwind-merge');
7
+ var jsxRuntime = require('react/jsx-runtime');
8
+
9
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
+
11
+ var clsx__default = /*#__PURE__*/_interopDefault(clsx);
12
+ var Image__default = /*#__PURE__*/_interopDefault(Image);
13
+
14
+ // src/nextjs/optimized-image.tsx
15
+ function cn(...inputs) {
16
+ return tailwindMerge.twMerge(clsx__default.default(inputs));
17
+ }
18
+ var OptimizedImage = react.forwardRef(
19
+ function OptimizedImage2({
20
+ src,
21
+ alt,
22
+ width,
23
+ height,
24
+ className,
25
+ fallbackText = "Falha ao carregar a imagem",
26
+ lazyLoad = true,
27
+ onLoad,
28
+ sizes,
29
+ ...props
30
+ }, ref) {
31
+ const containerRef = react.useRef(null);
32
+ const [isLoading, setIsLoading] = react.useState(true);
33
+ const [hasError, setHasError] = react.useState(false);
34
+ const [isInView, setIsInView] = react.useState(!lazyLoad);
35
+ react.useEffect(() => {
36
+ if (!lazyLoad || !containerRef.current) {
37
+ setIsInView(true);
38
+ return;
39
+ }
40
+ const observer = new IntersectionObserver(
41
+ ([entry]) => {
42
+ if (entry.isIntersecting) {
43
+ setIsInView(true);
44
+ observer.disconnect();
45
+ }
46
+ },
47
+ { rootMargin: "200px" }
48
+ );
49
+ observer.observe(containerRef.current);
50
+ return () => {
51
+ observer.disconnect();
52
+ };
53
+ }, [lazyLoad]);
54
+ const handleLoad = (ev) => {
55
+ setIsLoading(false);
56
+ onLoad == null ? void 0 : onLoad(ev);
57
+ };
58
+ const handleError = () => {
59
+ setIsLoading(false);
60
+ setHasError(true);
61
+ };
62
+ return /* @__PURE__ */ jsxRuntime.jsxs(
63
+ "div",
64
+ {
65
+ ref: containerRef,
66
+ className: "relative overflow-hidden",
67
+ style: {
68
+ width: width != null ? `${Number(width)}px` : "100%",
69
+ height: height != null ? `${Number(height)}px` : "100%"
70
+ },
71
+ children: [
72
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx(
73
+ "div",
74
+ {
75
+ className: "bg-muted absolute inset-0 animate-pulse rounded-md",
76
+ style: { width: "100%", height: "100%" }
77
+ }
78
+ ),
79
+ hasError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-muted text-muted-foreground absolute inset-0 flex items-center justify-center rounded-md text-center text-sm", children: fallbackText }) : isInView && /* @__PURE__ */ jsxRuntime.jsx(
80
+ Image__default.default,
81
+ {
82
+ ref,
83
+ src: src || "/placeholder.svg",
84
+ alt,
85
+ width: width ? Number(width) : void 0,
86
+ height: height ? Number(height) : void 0,
87
+ sizes: sizes || "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw",
88
+ quality: 80,
89
+ loading: props.priority ? "eager" : "lazy",
90
+ className: cn(
91
+ "rounded-md object-cover transition-opacity duration-300",
92
+ isLoading ? "opacity-0" : "opacity-100",
93
+ className
94
+ ),
95
+ onLoad: handleLoad,
96
+ onError: handleError,
97
+ placeholder: "blur",
98
+ blurDataURL: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAEtAI8V7yQCgAAAABJRU5ErkJggg==",
99
+ ...props
100
+ }
101
+ )
102
+ ]
103
+ }
104
+ );
105
+ }
106
+ );
107
+
108
+ exports.OptimizedImage = OptimizedImage;
109
+ //# sourceMappingURL=index.browser.cjs.map
110
+ //# sourceMappingURL=index.browser.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/nextjs/optimized-image.tsx"],"names":["twMerge","clsx","forwardRef","OptimizedImage","useRef","useState","useEffect","jsxs","jsx","Image"],"mappings":"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","file":"index.browser.cjs","sourcesContent":["\"use client\"\n\nimport clsx, { type ClassValue } from \"clsx\"\nimport Image from \"next/image\"\nimport type React from \"react\"\nimport { forwardRef, useEffect, useRef, useState } from \"react\"\nimport { twMerge } from \"tailwind-merge\"\n\nfunction cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\ninterface OptimizedImageProps\n extends React.ComponentPropsWithoutRef<typeof Image> {\n fallbackText?: string\n lazyLoad?: boolean\n}\n\nexport const OptimizedImage = forwardRef<HTMLImageElement, OptimizedImageProps>(\n function OptimizedImage(\n {\n src,\n alt,\n width,\n height,\n className,\n fallbackText = \"Falha ao carregar a imagem\",\n lazyLoad = true,\n onLoad,\n sizes,\n ...props\n },\n ref,\n ) {\n const containerRef = useRef<HTMLDivElement>(null)\n const [isLoading, setIsLoading] = useState(true)\n const [hasError, setHasError] = useState(false)\n const [isInView, setIsInView] = useState(!lazyLoad)\n\n useEffect(() => {\n if (!lazyLoad || !containerRef.current) {\n setIsInView(true)\n return\n }\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setIsInView(true)\n observer.disconnect()\n }\n },\n { rootMargin: \"200px\" },\n )\n\n observer.observe(containerRef.current)\n\n return () => {\n observer.disconnect()\n }\n }, [lazyLoad])\n\n const handleLoad = (ev: React.SyntheticEvent<HTMLImageElement, Event>) => {\n setIsLoading(false)\n onLoad?.(ev)\n }\n\n const handleError = () => {\n setIsLoading(false)\n setHasError(true)\n }\n\n return (\n <div\n ref={containerRef}\n className=\"relative overflow-hidden\"\n style={{\n width: width != null ? `${Number(width)}px` : \"100%\",\n height: height != null ? `${Number(height)}px` : \"100%\",\n }}\n >\n {isLoading && (\n <div\n className=\"bg-muted absolute inset-0 animate-pulse rounded-md\"\n style={{ width: \"100%\", height: \"100%\" }}\n />\n )}\n\n {hasError ? (\n <div className=\"bg-muted text-muted-foreground absolute inset-0 flex items-center justify-center rounded-md text-center text-sm\">\n {fallbackText}\n </div>\n ) : (\n isInView && (\n <Image\n ref={ref}\n src={src || \"/placeholder.svg\"}\n alt={alt}\n width={width ? Number(width) : undefined}\n height={height ? Number(height) : undefined}\n sizes={\n sizes ||\n \"(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw\"\n }\n quality={80}\n loading={props.priority ? \"eager\" : \"lazy\"}\n className={cn(\n \"rounded-md object-cover transition-opacity duration-300\",\n isLoading ? \"opacity-0\" : \"opacity-100\",\n className,\n )}\n onLoad={handleLoad}\n onError={handleError}\n placeholder=\"blur\"\n blurDataURL=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAEtAI8V7yQCgAAAABJRU5ErkJggg==\"\n {...props}\n />\n )\n )}\n </div>\n )\n },\n)\n"]}
@@ -0,0 +1,10 @@
1
+ import Image from 'next/image';
2
+ import React from 'react';
3
+
4
+ interface OptimizedImageProps extends React.ComponentPropsWithoutRef<typeof Image> {
5
+ fallbackText?: string;
6
+ lazyLoad?: boolean;
7
+ }
8
+ declare const OptimizedImage: React.ForwardRefExoticComponent<OptimizedImageProps & React.RefAttributes<HTMLImageElement>>;
9
+
10
+ export { OptimizedImage };
@@ -0,0 +1,10 @@
1
+ import Image from 'next/image';
2
+ import React from 'react';
3
+
4
+ interface OptimizedImageProps extends React.ComponentPropsWithoutRef<typeof Image> {
5
+ fallbackText?: string;
6
+ lazyLoad?: boolean;
7
+ }
8
+ declare const OptimizedImage: React.ForwardRefExoticComponent<OptimizedImageProps & React.RefAttributes<HTMLImageElement>>;
9
+
10
+ export { OptimizedImage };
@@ -0,0 +1,103 @@
1
+ import clsx from 'clsx';
2
+ import Image from 'next/image';
3
+ import { forwardRef, useRef, useState, useEffect } from 'react';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ // src/nextjs/optimized-image.tsx
8
+ function cn(...inputs) {
9
+ return twMerge(clsx(inputs));
10
+ }
11
+ var OptimizedImage = forwardRef(
12
+ function OptimizedImage2({
13
+ src,
14
+ alt,
15
+ width,
16
+ height,
17
+ className,
18
+ fallbackText = "Falha ao carregar a imagem",
19
+ lazyLoad = true,
20
+ onLoad,
21
+ sizes,
22
+ ...props
23
+ }, ref) {
24
+ const containerRef = useRef(null);
25
+ const [isLoading, setIsLoading] = useState(true);
26
+ const [hasError, setHasError] = useState(false);
27
+ const [isInView, setIsInView] = useState(!lazyLoad);
28
+ useEffect(() => {
29
+ if (!lazyLoad || !containerRef.current) {
30
+ setIsInView(true);
31
+ return;
32
+ }
33
+ const observer = new IntersectionObserver(
34
+ ([entry]) => {
35
+ if (entry.isIntersecting) {
36
+ setIsInView(true);
37
+ observer.disconnect();
38
+ }
39
+ },
40
+ { rootMargin: "200px" }
41
+ );
42
+ observer.observe(containerRef.current);
43
+ return () => {
44
+ observer.disconnect();
45
+ };
46
+ }, [lazyLoad]);
47
+ const handleLoad = (ev) => {
48
+ setIsLoading(false);
49
+ onLoad == null ? void 0 : onLoad(ev);
50
+ };
51
+ const handleError = () => {
52
+ setIsLoading(false);
53
+ setHasError(true);
54
+ };
55
+ return /* @__PURE__ */ jsxs(
56
+ "div",
57
+ {
58
+ ref: containerRef,
59
+ className: "relative overflow-hidden",
60
+ style: {
61
+ width: width != null ? `${Number(width)}px` : "100%",
62
+ height: height != null ? `${Number(height)}px` : "100%"
63
+ },
64
+ children: [
65
+ isLoading && /* @__PURE__ */ jsx(
66
+ "div",
67
+ {
68
+ className: "bg-muted absolute inset-0 animate-pulse rounded-md",
69
+ style: { width: "100%", height: "100%" }
70
+ }
71
+ ),
72
+ hasError ? /* @__PURE__ */ jsx("div", { className: "bg-muted text-muted-foreground absolute inset-0 flex items-center justify-center rounded-md text-center text-sm", children: fallbackText }) : isInView && /* @__PURE__ */ jsx(
73
+ Image,
74
+ {
75
+ ref,
76
+ src: src || "/placeholder.svg",
77
+ alt,
78
+ width: width ? Number(width) : void 0,
79
+ height: height ? Number(height) : void 0,
80
+ sizes: sizes || "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw",
81
+ quality: 80,
82
+ loading: props.priority ? "eager" : "lazy",
83
+ className: cn(
84
+ "rounded-md object-cover transition-opacity duration-300",
85
+ isLoading ? "opacity-0" : "opacity-100",
86
+ className
87
+ ),
88
+ onLoad: handleLoad,
89
+ onError: handleError,
90
+ placeholder: "blur",
91
+ blurDataURL: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAEtAI8V7yQCgAAAABJRU5ErkJggg==",
92
+ ...props
93
+ }
94
+ )
95
+ ]
96
+ }
97
+ );
98
+ }
99
+ );
100
+
101
+ export { OptimizedImage };
102
+ //# sourceMappingURL=index.browser.js.map
103
+ //# sourceMappingURL=index.browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/nextjs/optimized-image.tsx"],"names":["OptimizedImage"],"mappings":"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","file":"index.browser.js","sourcesContent":["\"use client\"\n\nimport clsx, { type ClassValue } from \"clsx\"\nimport Image from \"next/image\"\nimport type React from \"react\"\nimport { forwardRef, useEffect, useRef, useState } from \"react\"\nimport { twMerge } from \"tailwind-merge\"\n\nfunction cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\ninterface OptimizedImageProps\n extends React.ComponentPropsWithoutRef<typeof Image> {\n fallbackText?: string\n lazyLoad?: boolean\n}\n\nexport const OptimizedImage = forwardRef<HTMLImageElement, OptimizedImageProps>(\n function OptimizedImage(\n {\n src,\n alt,\n width,\n height,\n className,\n fallbackText = \"Falha ao carregar a imagem\",\n lazyLoad = true,\n onLoad,\n sizes,\n ...props\n },\n ref,\n ) {\n const containerRef = useRef<HTMLDivElement>(null)\n const [isLoading, setIsLoading] = useState(true)\n const [hasError, setHasError] = useState(false)\n const [isInView, setIsInView] = useState(!lazyLoad)\n\n useEffect(() => {\n if (!lazyLoad || !containerRef.current) {\n setIsInView(true)\n return\n }\n\n const observer = new IntersectionObserver(\n ([entry]) => {\n if (entry.isIntersecting) {\n setIsInView(true)\n observer.disconnect()\n }\n },\n { rootMargin: \"200px\" },\n )\n\n observer.observe(containerRef.current)\n\n return () => {\n observer.disconnect()\n }\n }, [lazyLoad])\n\n const handleLoad = (ev: React.SyntheticEvent<HTMLImageElement, Event>) => {\n setIsLoading(false)\n onLoad?.(ev)\n }\n\n const handleError = () => {\n setIsLoading(false)\n setHasError(true)\n }\n\n return (\n <div\n ref={containerRef}\n className=\"relative overflow-hidden\"\n style={{\n width: width != null ? `${Number(width)}px` : \"100%\",\n height: height != null ? `${Number(height)}px` : \"100%\",\n }}\n >\n {isLoading && (\n <div\n className=\"bg-muted absolute inset-0 animate-pulse rounded-md\"\n style={{ width: \"100%\", height: \"100%\" }}\n />\n )}\n\n {hasError ? (\n <div className=\"bg-muted text-muted-foreground absolute inset-0 flex items-center justify-center rounded-md text-center text-sm\">\n {fallbackText}\n </div>\n ) : (\n isInView && (\n <Image\n ref={ref}\n src={src || \"/placeholder.svg\"}\n alt={alt}\n width={width ? Number(width) : undefined}\n height={height ? Number(height) : undefined}\n sizes={\n sizes ||\n \"(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw\"\n }\n quality={80}\n loading={props.priority ? \"eager\" : \"lazy\"}\n className={cn(\n \"rounded-md object-cover transition-opacity duration-300\",\n isLoading ? \"opacity-0\" : \"opacity-100\",\n className,\n )}\n onLoad={handleLoad}\n onError={handleError}\n placeholder=\"blur\"\n blurDataURL=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAEtAI8V7yQCgAAAABJRU5ErkJggg==\"\n {...props}\n />\n )\n )}\n </div>\n )\n },\n)\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@herowcode/utils",
3
- "version": "1.4.8",
3
+ "version": "1.5.0",
4
4
  "description": "A lightweight collection of utility functions for everyday JavaScript/TypeScript development",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -86,6 +86,18 @@
86
86
  "default": "./dist/function/index.cjs"
87
87
  }
88
88
  },
89
+ "./nextjs": {
90
+ "browser": {
91
+ "import": {
92
+ "types": "./dist/nextjs/index.browser.d.mts",
93
+ "default": "./dist/nextjs/index.browser.js"
94
+ },
95
+ "require": {
96
+ "types": "./dist/nextjs/index.browser.d.ts",
97
+ "default": "./dist/nextjs/index.browser.cjs"
98
+ }
99
+ }
100
+ },
89
101
  "./string": {
90
102
  "import": {
91
103
  "types": "./dist/string/index.d.mts",
@@ -133,7 +145,7 @@
133
145
  "scripts": {
134
146
  "prebuild": "node scripts/sync-exports.cjs",
135
147
  "build": "tsup --config tsup.config.ts",
136
- "lint": "biome check --write --unsafe",
148
+ "lint": "biome check --write --unsafe && tsc --noEmit",
137
149
  "test": "vitest",
138
150
  "test:ui": "vitest --ui",
139
151
  "test:run": "vitest run",
@@ -156,7 +168,21 @@
156
168
  ],
157
169
  "dependencies": {
158
170
  "axios": "1.12.2",
159
- "dayjs": "^1.11.10"
171
+ "clsx": "^2.1.1",
172
+ "dayjs": "^1.11.10",
173
+ "tailwind-merge": "3.5.0"
174
+ },
175
+ "peerDependencies": {
176
+ "next": ">=13",
177
+ "react": ">=18"
178
+ },
179
+ "peerDependenciesMeta": {
180
+ "next": {
181
+ "optional": true
182
+ },
183
+ "react": {
184
+ "optional": true
185
+ }
160
186
  },
161
187
  "devDependencies": {
162
188
  "@biomejs/biome": "2.1.4",
@@ -171,6 +197,8 @@
171
197
  "@vitest/ui": "3.2.4",
172
198
  "jest-environment-jsdom": "30.1.2",
173
199
  "jsdom": "26.1.0",
200
+ "next": "15",
201
+ "react": "19.1.1",
174
202
  "react-dom": "19.1.1",
175
203
  "tsup": "8.5.1",
176
204
  "typescript": "^5.2.2",