@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.
- package/dist/nextjs/index.browser.cjs +110 -0
- package/dist/nextjs/index.browser.cjs.map +1 -0
- package/dist/nextjs/index.browser.d.mts +10 -0
- package/dist/nextjs/index.browser.d.ts +10 -0
- package/dist/nextjs/index.browser.js +103 -0
- package/dist/nextjs/index.browser.js.map +1 -0
- package/package.json +31 -3
|
@@ -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.
|
|
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
|
-
"
|
|
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",
|