@herowcode/utils 1.4.8 → 1.5.1
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 -5
|
@@ -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.1",
|
|
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",
|
|
@@ -131,14 +143,12 @@
|
|
|
131
143
|
"dist"
|
|
132
144
|
],
|
|
133
145
|
"scripts": {
|
|
134
|
-
"prebuild": "node scripts/sync-exports.cjs",
|
|
135
146
|
"build": "tsup --config tsup.config.ts",
|
|
136
|
-
"lint": "biome check --write --unsafe",
|
|
147
|
+
"lint": "biome check --write --unsafe && tsc --noEmit",
|
|
137
148
|
"test": "vitest",
|
|
138
149
|
"test:ui": "vitest --ui",
|
|
139
150
|
"test:run": "vitest run",
|
|
140
151
|
"test:coverage": "vitest run --coverage",
|
|
141
|
-
"prepare": "pnpm build",
|
|
142
152
|
"prepublishOnly": "pnpm lint && pnpm test:run && pnpm build",
|
|
143
153
|
"version:patch": "pnpm lint && pnpm test:run && pnpm build && npm version patch && git push && git push --tags",
|
|
144
154
|
"version:minor": "pnpm lint && pnpm test:run && pnpm build && npm version minor && git push && git push --tags",
|
|
@@ -156,7 +166,21 @@
|
|
|
156
166
|
],
|
|
157
167
|
"dependencies": {
|
|
158
168
|
"axios": "1.12.2",
|
|
159
|
-
"
|
|
169
|
+
"clsx": "^2.1.1",
|
|
170
|
+
"dayjs": "^1.11.10",
|
|
171
|
+
"tailwind-merge": "3.5.0"
|
|
172
|
+
},
|
|
173
|
+
"peerDependencies": {
|
|
174
|
+
"next": ">=13",
|
|
175
|
+
"react": ">=18"
|
|
176
|
+
},
|
|
177
|
+
"peerDependenciesMeta": {
|
|
178
|
+
"next": {
|
|
179
|
+
"optional": true
|
|
180
|
+
},
|
|
181
|
+
"react": {
|
|
182
|
+
"optional": true
|
|
183
|
+
}
|
|
160
184
|
},
|
|
161
185
|
"devDependencies": {
|
|
162
186
|
"@biomejs/biome": "2.1.4",
|
|
@@ -171,6 +195,8 @@
|
|
|
171
195
|
"@vitest/ui": "3.2.4",
|
|
172
196
|
"jest-environment-jsdom": "30.1.2",
|
|
173
197
|
"jsdom": "26.1.0",
|
|
198
|
+
"next": "15",
|
|
199
|
+
"react": "19.1.1",
|
|
174
200
|
"react-dom": "19.1.1",
|
|
175
201
|
"tsup": "8.5.1",
|
|
176
202
|
"typescript": "^5.2.2",
|