@dravyn/auth-js 0.1.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,87 @@
1
+ import React from 'react';
2
+
3
+ /**
4
+ * @dravyn/auth-js — Client SDK
5
+ *
6
+ * Drop-in auth state for React / Next.js projects.
7
+ *
8
+ * Usage:
9
+ * // 1. Wrap your app
10
+ * import { AuthProvider } from '@dravyn/auth-js'
11
+ * <AuthProvider apiBase="https://api.dravyn.it.com"><App /></AuthProvider>
12
+ *
13
+ * // 2. Use anywhere inside the tree
14
+ * import { useAuth } from '@dravyn/auth-js'
15
+ * const { user, login, logout, isLoading } = useAuth()
16
+ *
17
+ * // 3. Protect routes
18
+ * import { ProtectedRoute } from '@dravyn/auth-js'
19
+ * <ProtectedRoute><Dashboard /></ProtectedRoute>
20
+ */
21
+
22
+ interface AuthUser {
23
+ id: string;
24
+ email: string;
25
+ firstName: string;
26
+ lastName: string;
27
+ name: string;
28
+ avatar?: string;
29
+ role: 'user' | 'admin';
30
+ verified: boolean;
31
+ createdAt: string;
32
+ }
33
+ interface AuthState {
34
+ user: AuthUser | null;
35
+ token: string | null;
36
+ isLoading: boolean;
37
+ isLoggedIn: boolean;
38
+ }
39
+ interface LoginPayload {
40
+ email: string;
41
+ password: string;
42
+ }
43
+ interface AuthResponse {
44
+ accessToken: string;
45
+ refreshToken: string;
46
+ user: AuthUser;
47
+ }
48
+ interface AuthContextValue extends AuthState {
49
+ /** Sign in with email + password */
50
+ login: (payload: LoginPayload) => Promise<AuthResponse>;
51
+ /** Sign out and clear session */
52
+ logout: () => Promise<void>;
53
+ /** Manually set user (e.g. after OAuth callback) */
54
+ setUser: (user: AuthUser, token: string) => void;
55
+ /** Silently refresh the access token */
56
+ refreshToken: () => Promise<string | null>;
57
+ /** The API base URL this provider was configured with */
58
+ apiBase: string;
59
+ }
60
+ interface AuthProviderProps {
61
+ children: React.ReactNode;
62
+ /** Your Dravyn Auth API base URL */
63
+ apiBase?: string;
64
+ /** Where to redirect on logout */
65
+ loginPath?: string;
66
+ }
67
+ declare const AuthProvider: React.FC<AuthProviderProps>;
68
+ declare function useAuth(): AuthContextValue;
69
+ interface ProtectedRouteProps {
70
+ children: React.ReactNode;
71
+ /** Where to redirect unauthenticated users — default '/auth/login' */
72
+ redirectTo?: string;
73
+ /** Show this while auth state is loading — default null (nothing) */
74
+ loadingFallback?: React.ReactNode;
75
+ /** Required role — if set, redirects users without the role */
76
+ requiredRole?: 'admin' | 'user';
77
+ /** Where to redirect users who don't have the required role */
78
+ unauthorizedRedirect?: string;
79
+ }
80
+ declare const ProtectedRoute: React.FC<ProtectedRouteProps>;
81
+ declare function withAuth<P extends object>(Component: React.ComponentType<P & {
82
+ user: AuthUser;
83
+ }>, options?: {
84
+ redirectTo?: string;
85
+ }): React.FC<P>;
86
+
87
+ export { type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthResponse, type AuthState, type AuthUser, type LoginPayload, ProtectedRoute, type ProtectedRouteProps, useAuth, withAuth };
@@ -0,0 +1,87 @@
1
+ import React from 'react';
2
+
3
+ /**
4
+ * @dravyn/auth-js — Client SDK
5
+ *
6
+ * Drop-in auth state for React / Next.js projects.
7
+ *
8
+ * Usage:
9
+ * // 1. Wrap your app
10
+ * import { AuthProvider } from '@dravyn/auth-js'
11
+ * <AuthProvider apiBase="https://api.dravyn.it.com"><App /></AuthProvider>
12
+ *
13
+ * // 2. Use anywhere inside the tree
14
+ * import { useAuth } from '@dravyn/auth-js'
15
+ * const { user, login, logout, isLoading } = useAuth()
16
+ *
17
+ * // 3. Protect routes
18
+ * import { ProtectedRoute } from '@dravyn/auth-js'
19
+ * <ProtectedRoute><Dashboard /></ProtectedRoute>
20
+ */
21
+
22
+ interface AuthUser {
23
+ id: string;
24
+ email: string;
25
+ firstName: string;
26
+ lastName: string;
27
+ name: string;
28
+ avatar?: string;
29
+ role: 'user' | 'admin';
30
+ verified: boolean;
31
+ createdAt: string;
32
+ }
33
+ interface AuthState {
34
+ user: AuthUser | null;
35
+ token: string | null;
36
+ isLoading: boolean;
37
+ isLoggedIn: boolean;
38
+ }
39
+ interface LoginPayload {
40
+ email: string;
41
+ password: string;
42
+ }
43
+ interface AuthResponse {
44
+ accessToken: string;
45
+ refreshToken: string;
46
+ user: AuthUser;
47
+ }
48
+ interface AuthContextValue extends AuthState {
49
+ /** Sign in with email + password */
50
+ login: (payload: LoginPayload) => Promise<AuthResponse>;
51
+ /** Sign out and clear session */
52
+ logout: () => Promise<void>;
53
+ /** Manually set user (e.g. after OAuth callback) */
54
+ setUser: (user: AuthUser, token: string) => void;
55
+ /** Silently refresh the access token */
56
+ refreshToken: () => Promise<string | null>;
57
+ /** The API base URL this provider was configured with */
58
+ apiBase: string;
59
+ }
60
+ interface AuthProviderProps {
61
+ children: React.ReactNode;
62
+ /** Your Dravyn Auth API base URL */
63
+ apiBase?: string;
64
+ /** Where to redirect on logout */
65
+ loginPath?: string;
66
+ }
67
+ declare const AuthProvider: React.FC<AuthProviderProps>;
68
+ declare function useAuth(): AuthContextValue;
69
+ interface ProtectedRouteProps {
70
+ children: React.ReactNode;
71
+ /** Where to redirect unauthenticated users — default '/auth/login' */
72
+ redirectTo?: string;
73
+ /** Show this while auth state is loading — default null (nothing) */
74
+ loadingFallback?: React.ReactNode;
75
+ /** Required role — if set, redirects users without the role */
76
+ requiredRole?: 'admin' | 'user';
77
+ /** Where to redirect users who don't have the required role */
78
+ unauthorizedRedirect?: string;
79
+ }
80
+ declare const ProtectedRoute: React.FC<ProtectedRouteProps>;
81
+ declare function withAuth<P extends object>(Component: React.ComponentType<P & {
82
+ user: AuthUser;
83
+ }>, options?: {
84
+ redirectTo?: string;
85
+ }): React.FC<P>;
86
+
87
+ export { type AuthContextValue, AuthProvider, type AuthProviderProps, type AuthResponse, type AuthState, type AuthUser, type LoginPayload, ProtectedRoute, type ProtectedRouteProps, useAuth, withAuth };
package/dist/index.js ADDED
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ "use client";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+
31
+ // src/index.tsx
32
+ var index_exports = {};
33
+ __export(index_exports, {
34
+ AuthProvider: () => AuthProvider,
35
+ ProtectedRoute: () => ProtectedRoute,
36
+ useAuth: () => useAuth,
37
+ withAuth: () => withAuth
38
+ });
39
+ module.exports = __toCommonJS(index_exports);
40
+ var import_react = __toESM(require("react"));
41
+ var AuthContext = import_react.default.createContext(null);
42
+ var STORAGE_TOKEN = "dravyn_token";
43
+ var STORAGE_REFRESH = "dravyn_refresh";
44
+ var STORAGE_USER = "dravyn_user";
45
+ function readStorage() {
46
+ if (typeof window === "undefined") return { token: null, user: null };
47
+ try {
48
+ const token = localStorage.getItem(STORAGE_TOKEN);
49
+ const raw = localStorage.getItem(STORAGE_USER);
50
+ const user = raw ? JSON.parse(raw) : null;
51
+ return { token, user };
52
+ } catch {
53
+ return { token: null, user: null };
54
+ }
55
+ }
56
+ function writeStorage(token, refreshToken, user) {
57
+ localStorage.setItem(STORAGE_TOKEN, token);
58
+ localStorage.setItem(STORAGE_REFRESH, refreshToken);
59
+ localStorage.setItem(STORAGE_USER, JSON.stringify(user));
60
+ }
61
+ function clearStorage() {
62
+ localStorage.removeItem(STORAGE_TOKEN);
63
+ localStorage.removeItem(STORAGE_REFRESH);
64
+ localStorage.removeItem(STORAGE_USER);
65
+ }
66
+ var AuthProvider = ({
67
+ children,
68
+ apiBase = process.env.NEXT_PUBLIC_AUTH_API_URL ?? "http://localhost:3001",
69
+ loginPath = "/auth/login"
70
+ }) => {
71
+ const [user, setUserState] = import_react.default.useState(null);
72
+ const [token, setTokenState] = import_react.default.useState(null);
73
+ const [isLoading, setIsLoading] = import_react.default.useState(true);
74
+ import_react.default.useEffect(() => {
75
+ const { token: t, user: u } = readStorage();
76
+ if (t && u) {
77
+ setTokenState(t);
78
+ setUserState(u);
79
+ }
80
+ setIsLoading(false);
81
+ }, []);
82
+ import_react.default.useEffect(() => {
83
+ if (!token) return;
84
+ const original = window.fetch;
85
+ window.fetch = (input, init = {}) => {
86
+ const url = typeof input === "string" ? input : input.url;
87
+ if (url.startsWith(apiBase)) {
88
+ init.headers = {
89
+ ...init.headers,
90
+ Authorization: `Bearer ${token}`
91
+ };
92
+ }
93
+ return original(input, init);
94
+ };
95
+ return () => {
96
+ window.fetch = original;
97
+ };
98
+ }, [token, apiBase]);
99
+ const login = import_react.default.useCallback(async (payload) => {
100
+ const res = await fetch(`${apiBase}/auth/login`, {
101
+ method: "POST",
102
+ headers: { "Content-Type": "application/json" },
103
+ body: JSON.stringify(payload)
104
+ });
105
+ if (!res.ok) {
106
+ const err = await res.json().catch(() => ({}));
107
+ throw new Error(err.message ?? "Login failed");
108
+ }
109
+ const data = await res.json();
110
+ writeStorage(data.accessToken, data.refreshToken, data.user);
111
+ setTokenState(data.accessToken);
112
+ setUserState(data.user);
113
+ return data;
114
+ }, [apiBase]);
115
+ const logout = import_react.default.useCallback(async () => {
116
+ try {
117
+ const refresh = localStorage.getItem(STORAGE_REFRESH);
118
+ await fetch(`${apiBase}/auth/logout`, {
119
+ method: "POST",
120
+ headers: {
121
+ "Content-Type": "application/json",
122
+ "Authorization": `Bearer ${token}`
123
+ },
124
+ body: JSON.stringify({ refreshToken: refresh })
125
+ });
126
+ } catch {
127
+ }
128
+ clearStorage();
129
+ setTokenState(null);
130
+ setUserState(null);
131
+ window.location.href = loginPath;
132
+ }, [apiBase, token, loginPath]);
133
+ const setUser = import_react.default.useCallback((u, t) => {
134
+ setUserState(u);
135
+ setTokenState(t);
136
+ }, []);
137
+ const refreshToken = import_react.default.useCallback(async () => {
138
+ try {
139
+ const refresh = localStorage.getItem(STORAGE_REFRESH);
140
+ if (!refresh) return null;
141
+ const res = await fetch(`${apiBase}/auth/refresh`, {
142
+ method: "POST",
143
+ headers: { "Content-Type": "application/json" },
144
+ body: JSON.stringify({ refreshToken: refresh })
145
+ });
146
+ if (!res.ok) {
147
+ await logout();
148
+ return null;
149
+ }
150
+ const data = await res.json();
151
+ localStorage.setItem(STORAGE_TOKEN, data.accessToken);
152
+ setTokenState(data.accessToken);
153
+ return data.accessToken;
154
+ } catch {
155
+ return null;
156
+ }
157
+ }, [apiBase, logout]);
158
+ const value = {
159
+ user,
160
+ token,
161
+ isLoading,
162
+ isLoggedIn: !!user && !!token,
163
+ login,
164
+ logout,
165
+ setUser,
166
+ refreshToken,
167
+ apiBase
168
+ };
169
+ return /* @__PURE__ */ import_react.default.createElement(AuthContext.Provider, { value }, children);
170
+ };
171
+ function useAuth() {
172
+ const ctx = import_react.default.useContext(AuthContext);
173
+ if (!ctx) {
174
+ throw new Error(
175
+ "useAuth() must be called inside an <AuthProvider>. Wrap your app (or layout.tsx) with <AuthProvider>."
176
+ );
177
+ }
178
+ return ctx;
179
+ }
180
+ var ProtectedRoute = ({
181
+ children,
182
+ redirectTo = "/auth/login",
183
+ loadingFallback = null,
184
+ requiredRole,
185
+ unauthorizedRedirect = "/"
186
+ }) => {
187
+ const { isLoggedIn, isLoading, user } = useAuth();
188
+ import_react.default.useEffect(() => {
189
+ if (isLoading) return;
190
+ if (!isLoggedIn) {
191
+ window.location.href = `${redirectTo}?next=${encodeURIComponent(window.location.pathname)}`;
192
+ return;
193
+ }
194
+ if (requiredRole && user?.role !== requiredRole) {
195
+ window.location.href = unauthorizedRedirect;
196
+ }
197
+ }, [isLoading, isLoggedIn, user, redirectTo, requiredRole, unauthorizedRedirect]);
198
+ if (isLoading) return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, loadingFallback);
199
+ if (!isLoggedIn) return null;
200
+ if (requiredRole && user?.role !== requiredRole) return null;
201
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, children);
202
+ };
203
+ function withAuth(Component, options = {}) {
204
+ const WrappedComponent = (props) => {
205
+ const { user } = useAuth();
206
+ return /* @__PURE__ */ import_react.default.createElement(ProtectedRoute, { redirectTo: options.redirectTo }, user && /* @__PURE__ */ import_react.default.createElement(Component, { ...props, user }));
207
+ };
208
+ WrappedComponent.displayName = `withAuth(${Component.displayName ?? Component.name})`;
209
+ return WrappedComponent;
210
+ }
211
+ // Annotate the CommonJS export names for ESM import in node:
212
+ 0 && (module.exports = {
213
+ AuthProvider,
214
+ ProtectedRoute,
215
+ useAuth,
216
+ withAuth
217
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,180 @@
1
+ "use client";
2
+
3
+ // src/index.tsx
4
+ import React from "react";
5
+ var AuthContext = React.createContext(null);
6
+ var STORAGE_TOKEN = "dravyn_token";
7
+ var STORAGE_REFRESH = "dravyn_refresh";
8
+ var STORAGE_USER = "dravyn_user";
9
+ function readStorage() {
10
+ if (typeof window === "undefined") return { token: null, user: null };
11
+ try {
12
+ const token = localStorage.getItem(STORAGE_TOKEN);
13
+ const raw = localStorage.getItem(STORAGE_USER);
14
+ const user = raw ? JSON.parse(raw) : null;
15
+ return { token, user };
16
+ } catch {
17
+ return { token: null, user: null };
18
+ }
19
+ }
20
+ function writeStorage(token, refreshToken, user) {
21
+ localStorage.setItem(STORAGE_TOKEN, token);
22
+ localStorage.setItem(STORAGE_REFRESH, refreshToken);
23
+ localStorage.setItem(STORAGE_USER, JSON.stringify(user));
24
+ }
25
+ function clearStorage() {
26
+ localStorage.removeItem(STORAGE_TOKEN);
27
+ localStorage.removeItem(STORAGE_REFRESH);
28
+ localStorage.removeItem(STORAGE_USER);
29
+ }
30
+ var AuthProvider = ({
31
+ children,
32
+ apiBase = process.env.NEXT_PUBLIC_AUTH_API_URL ?? "http://localhost:3001",
33
+ loginPath = "/auth/login"
34
+ }) => {
35
+ const [user, setUserState] = React.useState(null);
36
+ const [token, setTokenState] = React.useState(null);
37
+ const [isLoading, setIsLoading] = React.useState(true);
38
+ React.useEffect(() => {
39
+ const { token: t, user: u } = readStorage();
40
+ if (t && u) {
41
+ setTokenState(t);
42
+ setUserState(u);
43
+ }
44
+ setIsLoading(false);
45
+ }, []);
46
+ React.useEffect(() => {
47
+ if (!token) return;
48
+ const original = window.fetch;
49
+ window.fetch = (input, init = {}) => {
50
+ const url = typeof input === "string" ? input : input.url;
51
+ if (url.startsWith(apiBase)) {
52
+ init.headers = {
53
+ ...init.headers,
54
+ Authorization: `Bearer ${token}`
55
+ };
56
+ }
57
+ return original(input, init);
58
+ };
59
+ return () => {
60
+ window.fetch = original;
61
+ };
62
+ }, [token, apiBase]);
63
+ const login = React.useCallback(async (payload) => {
64
+ const res = await fetch(`${apiBase}/auth/login`, {
65
+ method: "POST",
66
+ headers: { "Content-Type": "application/json" },
67
+ body: JSON.stringify(payload)
68
+ });
69
+ if (!res.ok) {
70
+ const err = await res.json().catch(() => ({}));
71
+ throw new Error(err.message ?? "Login failed");
72
+ }
73
+ const data = await res.json();
74
+ writeStorage(data.accessToken, data.refreshToken, data.user);
75
+ setTokenState(data.accessToken);
76
+ setUserState(data.user);
77
+ return data;
78
+ }, [apiBase]);
79
+ const logout = React.useCallback(async () => {
80
+ try {
81
+ const refresh = localStorage.getItem(STORAGE_REFRESH);
82
+ await fetch(`${apiBase}/auth/logout`, {
83
+ method: "POST",
84
+ headers: {
85
+ "Content-Type": "application/json",
86
+ "Authorization": `Bearer ${token}`
87
+ },
88
+ body: JSON.stringify({ refreshToken: refresh })
89
+ });
90
+ } catch {
91
+ }
92
+ clearStorage();
93
+ setTokenState(null);
94
+ setUserState(null);
95
+ window.location.href = loginPath;
96
+ }, [apiBase, token, loginPath]);
97
+ const setUser = React.useCallback((u, t) => {
98
+ setUserState(u);
99
+ setTokenState(t);
100
+ }, []);
101
+ const refreshToken = React.useCallback(async () => {
102
+ try {
103
+ const refresh = localStorage.getItem(STORAGE_REFRESH);
104
+ if (!refresh) return null;
105
+ const res = await fetch(`${apiBase}/auth/refresh`, {
106
+ method: "POST",
107
+ headers: { "Content-Type": "application/json" },
108
+ body: JSON.stringify({ refreshToken: refresh })
109
+ });
110
+ if (!res.ok) {
111
+ await logout();
112
+ return null;
113
+ }
114
+ const data = await res.json();
115
+ localStorage.setItem(STORAGE_TOKEN, data.accessToken);
116
+ setTokenState(data.accessToken);
117
+ return data.accessToken;
118
+ } catch {
119
+ return null;
120
+ }
121
+ }, [apiBase, logout]);
122
+ const value = {
123
+ user,
124
+ token,
125
+ isLoading,
126
+ isLoggedIn: !!user && !!token,
127
+ login,
128
+ logout,
129
+ setUser,
130
+ refreshToken,
131
+ apiBase
132
+ };
133
+ return /* @__PURE__ */ React.createElement(AuthContext.Provider, { value }, children);
134
+ };
135
+ function useAuth() {
136
+ const ctx = React.useContext(AuthContext);
137
+ if (!ctx) {
138
+ throw new Error(
139
+ "useAuth() must be called inside an <AuthProvider>. Wrap your app (or layout.tsx) with <AuthProvider>."
140
+ );
141
+ }
142
+ return ctx;
143
+ }
144
+ var ProtectedRoute = ({
145
+ children,
146
+ redirectTo = "/auth/login",
147
+ loadingFallback = null,
148
+ requiredRole,
149
+ unauthorizedRedirect = "/"
150
+ }) => {
151
+ const { isLoggedIn, isLoading, user } = useAuth();
152
+ React.useEffect(() => {
153
+ if (isLoading) return;
154
+ if (!isLoggedIn) {
155
+ window.location.href = `${redirectTo}?next=${encodeURIComponent(window.location.pathname)}`;
156
+ return;
157
+ }
158
+ if (requiredRole && user?.role !== requiredRole) {
159
+ window.location.href = unauthorizedRedirect;
160
+ }
161
+ }, [isLoading, isLoggedIn, user, redirectTo, requiredRole, unauthorizedRedirect]);
162
+ if (isLoading) return /* @__PURE__ */ React.createElement(React.Fragment, null, loadingFallback);
163
+ if (!isLoggedIn) return null;
164
+ if (requiredRole && user?.role !== requiredRole) return null;
165
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
166
+ };
167
+ function withAuth(Component, options = {}) {
168
+ const WrappedComponent = (props) => {
169
+ const { user } = useAuth();
170
+ return /* @__PURE__ */ React.createElement(ProtectedRoute, { redirectTo: options.redirectTo }, user && /* @__PURE__ */ React.createElement(Component, { ...props, user }));
171
+ };
172
+ WrappedComponent.displayName = `withAuth(${Component.displayName ?? Component.name})`;
173
+ return WrappedComponent;
174
+ }
175
+ export {
176
+ AuthProvider,
177
+ ProtectedRoute,
178
+ useAuth,
179
+ withAuth
180
+ };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@dravyn/auth-js",
3
+ "version": "0.1.0",
4
+ "description": "Dravyn Auth — React/Next.js SDK. AuthProvider, useAuth, ProtectedRoute, withAuth.",
5
+ "author": "Durotoye Jeremiah Adeniyi <team@dravyn.it.com>",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/Dravyn-tech/auth.git"
10
+ },
11
+ "main": "./dist/index.js",
12
+ "module": "./dist/index.mjs",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.mjs",
18
+ "require": "./dist/index.js"
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "sideEffects": false,
25
+ "peerDependencies": {
26
+ "react": ">=17.0.0",
27
+ "react-dom": ">=17.0.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^25.9.1",
31
+ "@types/react": "^18.0.0",
32
+ "tsup": "^8.0.0",
33
+ "typescript": "^5.0.0"
34
+ },
35
+ "scripts": {
36
+ "build": "tsup src/index.tsx --format cjs,esm --dts --clean",
37
+ "dev": "tsup src/index.tsx --format cjs,esm --dts --watch"
38
+ }
39
+ }