@hexdspace/react 0.0.26 → 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.
@@ -72,7 +72,7 @@
72
72
  @layer components {
73
73
  .card {
74
74
  background: var(--surface-2);
75
- border: 1px solid color-mix(in oklab, var(--border), transparent 45%);
75
+ border: 1px solid color-mix(in oklab, var(--border), transparent 80%);
76
76
  border-radius: var(--radius-card);
77
77
  box-shadow: var(--shadow-elevated);
78
78
  }
@@ -115,32 +115,60 @@
115
115
 
116
116
  @layer utilities {
117
117
  .brand-gradient {
118
- background: linear-gradient(90deg, var(--accent-strong) 0%, var(--accent) 30%);
118
+ background: linear-gradient(90deg, var(--brand-strong) 0%, var(--brand) 30%);
119
119
  -webkit-background-clip: text;
120
120
  -webkit-text-fill-color: transparent;
121
121
  }
122
122
 
123
123
  .btn {
124
- @apply state-layer inline-flex items-center justify-center gap-2 px-3.5 py-2.5
125
- text-sm font-medium select-none cursor-pointer
126
- transition-[background,color,box-shadow,transform] duration-150;
124
+ @apply inline-flex items-center justify-center gap-2 leading-none
125
+ state-layer text-sm font-medium select-none cursor-pointer;
127
126
  position: relative;
128
127
  border-radius: var(--radius-btn);
129
128
  box-shadow: var(--shadow-10);
129
+ transition-property: background-color, color, box-shadow, transform;
130
+ transition-duration: 150ms;
131
+ transition-timing-function: ease;
132
+ }
133
+
134
+ .btn.shadow-none {
135
+ box-shadow: none;
130
136
  }
131
137
 
132
138
  .btn:disabled, .btn.disabled {
133
139
  opacity: 0.5;
134
140
  pointer-events: none;
141
+ cursor: not-allowed;
135
142
  }
136
143
 
137
144
  .btn-primary {
138
- background: var(--accent);
145
+ background: var(--brand);
139
146
  color: var(--text-inverted);
140
147
  }
141
148
 
142
149
  .btn-secondary {
143
150
  border: 1px solid var(--border);
151
+ background: var(--surface-2);
152
+ }
153
+
154
+ .btn-success {
155
+ background: var(--success);
156
+ color: var(--on-success);
157
+ }
158
+
159
+ .btn-info {
160
+ background: var(--info);
161
+ color: var(--on-info);
162
+ }
163
+
164
+ .btn-warning {
165
+ background: var(--warning);
166
+ color: var(--on-warning);
167
+ }
168
+
169
+ .btn-danger {
170
+ background: var(--danger);
171
+ color: var(--on-danger);
144
172
  }
145
173
 
146
174
  :root .prose code {
@@ -4,8 +4,8 @@
4
4
  :root {
5
5
  /* Surfaces */
6
6
  --bg: var(--ink-10);
7
- --surface-1: color-mix(in oklab, var(--ink-10), black 12%);
8
- --surface-2: color-mix(in oklab, var(--ink-10), black 8%);
7
+ --surface-1: color-mix(in oklab, var(--ink-10), black 8%);
8
+ --surface-2: color-mix(in oklab, var(--ink-10), black 6%);
9
9
  --surface-3: color-mix(in oklab, var(--ink-10), black 4%);
10
10
 
11
11
  /* Typography */
package/dist/index.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
2
  import { QueryClient, QueryKey } from '@tanstack/react-query';
3
3
  import { ResultOk, ResultError, AsyncResult, Result } from '@hexdspace/util';
4
- import * as react from 'react';
5
- import react__default, { CSSProperties, Dispatch, ReactNode } from 'react';
4
+ import * as React from 'react';
5
+ import React__default, { CSSProperties, Dispatch, ReactNode } from 'react';
6
6
  import * as react_jsx_runtime from 'react/jsx-runtime';
7
+ import * as class_variance_authority_types from 'class-variance-authority/types';
8
+ import { VariantProps } from 'class-variance-authority';
7
9
 
8
10
  type NotificationVariant = 'success' | 'warning' | 'error' | 'info';
9
11
  declare const DEFAULT_NOTIFICATION_CHANNEL = "app.notifications";
@@ -120,7 +122,7 @@ type NotificationHostProps = {
120
122
  isDark?: () => boolean;
121
123
  theme?: ToastTheme;
122
124
  };
123
- declare const NotificationHost: react__default.FC<NotificationHostProps>;
125
+ declare const NotificationHost: React__default.FC<NotificationHostProps>;
124
126
 
125
127
  type InstructionContext = {
126
128
  queryClient: QueryClient;
@@ -255,7 +257,7 @@ interface LogoutUser {
255
257
  }
256
258
 
257
259
  interface RegisterUser {
258
- execute(email: string, password: string): AsyncResult<Error, GenericResponse>;
260
+ execute(email: string, password: string, attributes?: Record<string, string>): AsyncResult<Error, GenericResponse>;
259
261
  }
260
262
 
261
263
  interface GetAuthenticatedUser {
@@ -265,7 +267,7 @@ interface GetAuthenticatedUser {
265
267
  interface AuthProvider$1 {
266
268
  getAuthenticatedUser(): AsyncResult<Error, User | null>;
267
269
  login(email: string, password: string): AsyncResult<Error, User>;
268
- register(email: string, password: string): AsyncResult<Error, GenericResponse>;
270
+ register(email: string, password: string, attributes?: Record<string, string>): AsyncResult<Error, GenericResponse>;
269
271
  logout(): AsyncResult<Error, null>;
270
272
  }
271
273
 
@@ -277,7 +279,7 @@ declare class AuthController {
277
279
  constructor(loginUser: LoginUser, logoutUser: LogoutUser, registerUser: RegisterUser, getAuthenticatedUser: GetAuthenticatedUser);
278
280
  login(email: string, password: string): AsyncResult<Error, User>;
279
281
  logout(): AsyncResult<Error, null>;
280
- register(email: string, password: string): AsyncResult<Error, {
282
+ register(email: string, password: string, attributes?: Record<string, string>): AsyncResult<Error, {
281
283
  message: string;
282
284
  }>;
283
285
  getCurrentUser(): AsyncResult<Error, User | null>;
@@ -311,7 +313,7 @@ declare function useAuth(): AuthState;
311
313
  declare function useAuthActions(): {
312
314
  login: (email: string, password: string) => Promise<Result<Error, User>>;
313
315
  logout: () => void;
314
- register: (email: string, password: string) => Promise<Result<Error, {
316
+ register: (email: string, password: string, attributes?: Record<string, string>) => Promise<Result<Error, {
315
317
  message: string;
316
318
  }>>;
317
319
  };
@@ -337,13 +339,13 @@ type AuthAction = {
337
339
 
338
340
  declare function useAuthDispatch(): Dispatch<AuthAction>;
339
341
 
340
- declare const AuthStateCtx: react.Context<AuthState | null>;
341
- declare const AuthDispatchCtx: react.Context<Dispatch<AuthAction> | null>;
342
+ declare const AuthStateCtx: React.Context<AuthState | null>;
343
+ declare const AuthDispatchCtx: React.Context<Dispatch<AuthAction> | null>;
342
344
  declare function AuthProvider({ children }: {
343
345
  readonly children: ReactNode;
344
346
  }): react_jsx_runtime.JSX.Element;
345
347
 
346
- declare const AuthControllerCtx: react.Context<AuthController | null>;
348
+ declare const AuthControllerCtx: React.Context<AuthController | null>;
347
349
  type AuthControllerProviderProps = {
348
350
  readonly children: ReactNode;
349
351
  readonly controller: AuthController;
@@ -355,11 +357,11 @@ interface InputProps {
355
357
  label: string;
356
358
  type: string;
357
359
  value: string;
358
- onChange: (e: react__default.ChangeEvent<HTMLInputElement>) => void;
360
+ onChange: (e: React__default.ChangeEvent<HTMLInputElement>) => void;
359
361
  placeholder: string;
360
362
  className?: string;
361
363
  }
362
- declare const AuthFormInputField: react__default.FC<InputProps>;
364
+ declare const AuthFormInputField: React__default.FC<InputProps>;
363
365
 
364
366
  type RequireAuthProps = {
365
367
  guarded?: ReactNode;
@@ -397,4 +399,19 @@ declare class MockAuthHttpClient extends MockHttpClient {
397
399
  private registerAuthRoutes;
398
400
  }
399
401
 
400
- export { AuthController, AuthControllerCtx, type AuthControllerDeps, AuthControllerProvider, AuthDispatchCtx, AuthFormInputField, AuthProvider, type AuthState, AuthStateCtx, type CacheInstruction, type CustomInstruction, DEFAULT_NOTIFICATION_CHANNEL, type ErrorResponse, type GenericResponse, type HttpClient, HttpError, type HttpMethod, type HttpResponse, type Instruction, type InstructionContext, MockAuthHttpClient, MockHttpClient, type MutationFn, type Notification, type NotificationAction, NotificationHost, type NotificationInstruction, type NotificationVariant, NotifierController, type OnSuccessFn, type OptimisticSnapshot, type OptimisticUpdateFn, RedirectIfAuthed, type RedirectIfAuthedProps, type RequestConfig, RequireAuth, type RequireAuthProps, type ResolvedToastTheme, type ResponsiveMutation, type ToastActionTheme, type ToastTheme, type ToastTransition, type ToastifyCSSVars, type UIFail, type UIOk, type UIResult, type User, authController, controllerFactory, createAuthController, httpClient as fetchHttpClient, notifierController, resolveToastTheme, ui, useAuth, useAuthActions, useAuthController, useAuthDispatch, useAuthedUser, useResponsiveMutation };
402
+ declare const buttonVariants: (props?: ({
403
+ variant?: "success" | "warning" | "info" | "link" | "primary" | "secondary" | "outline" | "ghost" | "danger" | null | undefined;
404
+ size?: "icon" | "sm" | "md" | "lg" | null | undefined;
405
+ chrome?: "push" | "flat" | "inset" | "soft" | "glass" | "glow" | "hairline" | null | undefined;
406
+ fullWidth?: boolean | null | undefined;
407
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
408
+ interface ButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children">, VariantProps<typeof buttonVariants> {
409
+ asChild?: boolean;
410
+ children?: React.ReactNode;
411
+ loading?: boolean;
412
+ leftIcon?: React.ReactNode;
413
+ rightIcon?: React.ReactNode;
414
+ }
415
+ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
416
+
417
+ export { AuthController, AuthControllerCtx, type AuthControllerDeps, AuthControllerProvider, AuthDispatchCtx, AuthFormInputField, AuthProvider, type AuthState, AuthStateCtx, Button, type ButtonProps, type CacheInstruction, type CustomInstruction, DEFAULT_NOTIFICATION_CHANNEL, type ErrorResponse, type GenericResponse, type HttpClient, HttpError, type HttpMethod, type HttpResponse, type Instruction, type InstructionContext, MockAuthHttpClient, MockHttpClient, type MutationFn, type Notification, type NotificationAction, NotificationHost, type NotificationInstruction, type NotificationVariant, NotifierController, type OnSuccessFn, type OptimisticSnapshot, type OptimisticUpdateFn, RedirectIfAuthed, type RedirectIfAuthedProps, type RequestConfig, RequireAuth, type RequireAuthProps, type ResolvedToastTheme, type ResponsiveMutation, type ToastActionTheme, type ToastTheme, type ToastTransition, type ToastifyCSSVars, type UIFail, type UIOk, type UIResult, type User, authController, controllerFactory, createAuthController, httpClient as fetchHttpClient, notifierController, resolveToastTheme, ui, useAuth, useAuthActions, useAuthController, useAuthDispatch, useAuthedUser, useResponsiveMutation };
package/dist/index.js CHANGED
@@ -638,9 +638,12 @@ var HttpCookieAuthProvider = class {
638
638
  }
639
639
  }
640
640
  }
641
- async register(email, password) {
641
+ async register(email, password, attributes) {
642
642
  try {
643
- const res = await this.httpClient.post("/auth/register", { email, password });
643
+ const res = await this.httpClient.post(
644
+ "/auth/register",
645
+ { email, password, ...attributes ?? {} }
646
+ );
644
647
  return ok2(res.data);
645
648
  } catch (err) {
646
649
  if (err instanceof Error) {
@@ -692,8 +695,8 @@ var RegisterUserUseCase = class {
692
695
  constructor(authProvider) {
693
696
  this.authProvider = authProvider;
694
697
  }
695
- execute(email, password) {
696
- return this.authProvider.register(email, password);
698
+ execute(email, password, attributes) {
699
+ return this.authProvider.register(email, password, attributes);
697
700
  }
698
701
  };
699
702
 
@@ -721,8 +724,8 @@ var AuthController = class {
721
724
  async logout() {
722
725
  return this.logoutUser.execute();
723
726
  }
724
- async register(email, password) {
725
- return this.registerUser.execute(email, password);
727
+ async register(email, password, attributes) {
728
+ return this.registerUser.execute(email, password, attributes);
726
729
  }
727
730
  async getCurrentUser() {
728
731
  return this.getAuthenticatedUser.execute();
@@ -856,9 +859,9 @@ function useAuthActions() {
856
859
  const logout = useCallback2(() => {
857
860
  authController2.logout().then(() => dispatch({ type: "LOGOUT" }));
858
861
  }, [dispatch, authController2]);
859
- const register = useCallback2(async (email, password) => {
862
+ const register = useCallback2(async (email, password, attributes) => {
860
863
  dispatch({ type: "REQUEST" });
861
- const res = await authController2.register(email, password);
864
+ const res = await authController2.register(email, password, attributes);
862
865
  dispatchRegisterResult(res, dispatch);
863
866
  return res;
864
867
  }, [dispatch, authController2]);
@@ -1047,6 +1050,215 @@ var MockAuthHttpClient = class extends MockHttpClient {
1047
1050
  });
1048
1051
  }
1049
1052
  };
1053
+
1054
+ // src/ui/components/Button.tsx
1055
+ import * as React3 from "react";
1056
+ import { Slot } from "radix-ui";
1057
+ import { cva } from "class-variance-authority";
1058
+
1059
+ // src/ui/utils/cn.ts
1060
+ import { clsx } from "clsx";
1061
+ import { twMerge } from "tailwind-merge";
1062
+ function cn(...inputs) {
1063
+ return twMerge(clsx(inputs));
1064
+ }
1065
+
1066
+ // src/ui/components/Button.tsx
1067
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
1068
+ var pushChrome = cn(
1069
+ "!border-b-[4px]",
1070
+ "!transition-all",
1071
+ "!duration-100",
1072
+ "ease-out",
1073
+ "!shadow-[0_2px_4px_rgba(0,0,0,0.28),0_8px_16px_rgba(0,0,0,0.14)]",
1074
+ "hover:!shadow-[0_3px_6px_rgba(0,0,0,0.30),0_12px_22px_rgba(0,0,0,0.18)]",
1075
+ "hover:-translate-y-[2px]",
1076
+ "active:translate-y-[1px]"
1077
+ );
1078
+ var softChrome = cn(
1079
+ "border",
1080
+ "!border-[color:color-mix(in_oklab,var(--border),transparent_20%)]",
1081
+ "!shadow-[0_1px_0_rgba(255,255,255,0.65)_inset,0_3px_8px_rgba(0,0,0,0.14)]"
1082
+ );
1083
+ var insetChrome = cn(
1084
+ "border",
1085
+ "!border-[color:color-mix(in_oklab,var(--border),transparent_35%)]",
1086
+ "!shadow-[inset_0_2px_6px_rgba(0,0,0,0.18)]"
1087
+ );
1088
+ var glassChrome = cn(
1089
+ "!backdrop-blur-[6px]",
1090
+ "!border",
1091
+ "!shadow-[0_8px_18px_rgba(0,0,0,0.12)]"
1092
+ );
1093
+ var glowChrome = cn(
1094
+ "!border",
1095
+ "!shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_40%),0_6px_16px_color-mix(in_oklab,var(--border),transparent_70%)]",
1096
+ "hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_25%),0_10px_26px_color-mix(in_oklab,var(--border),transparent_60%)]"
1097
+ );
1098
+ var hairlineChrome = cn(
1099
+ "!border",
1100
+ "!border-[color:color-mix(in_oklab,var(--border),transparent_60%)]",
1101
+ "!bg-transparent",
1102
+ "!font-thin",
1103
+ "!shadow-none"
1104
+ );
1105
+ var buttonVariants = cva("btn", {
1106
+ variants: {
1107
+ variant: {
1108
+ primary: "btn-primary",
1109
+ secondary: "btn-secondary text-[var(--text-1)]",
1110
+ outline: "bg-transparent text-[var(--text-1)] border border-[var(--border)] shadow-none",
1111
+ ghost: "bg-transparent text-[var(--text-1)] shadow-none",
1112
+ success: "btn-success",
1113
+ info: "btn-info",
1114
+ warning: "btn-warning",
1115
+ danger: "btn-danger",
1116
+ link: "bg-transparent p-0 h-auto shadow-none text-[var(--link)] hover:underline hover:text-[var(--link-hover)]"
1117
+ },
1118
+ size: {
1119
+ sm: "px-3 py-1.5",
1120
+ md: "px-3.5 py-2.5 !text-base",
1121
+ lg: "px-4.5 py-3 !text-base",
1122
+ icon: "h-10 w-10 p-0"
1123
+ },
1124
+ chrome: {
1125
+ flat: "",
1126
+ push: pushChrome,
1127
+ soft: softChrome,
1128
+ inset: insetChrome,
1129
+ glass: glassChrome,
1130
+ glow: glowChrome,
1131
+ hairline: hairlineChrome
1132
+ },
1133
+ fullWidth: { true: "w-full", false: "" }
1134
+ },
1135
+ compoundVariants: [
1136
+ { variant: "ghost", className: "!border-0" },
1137
+ { variant: "link", className: "!border-0" },
1138
+ { chrome: "soft", className: "!text-[var(--text-1)]" },
1139
+ { chrome: "glass", className: "!text-[var(--text-1)]" },
1140
+ { chrome: "push", variant: "primary", className: "border-b-[color:var(--brand-90)]" },
1141
+ { chrome: "push", variant: "secondary", className: "border-b-[color:color-mix(in oklab, var(--border), transparent 50%)]" },
1142
+ { chrome: "push", variant: "outline", className: "border-b-[color:color-mix(in oklab, var(--border), transparent 50%)]" },
1143
+ { chrome: "push", variant: "ghost", className: "border-b-transparent !shadow-none" },
1144
+ { chrome: "push", variant: "success", className: "border-b-[color:var(--success-80)]" },
1145
+ { chrome: "push", variant: "info", className: "border-b-[color:var(--info-80)]" },
1146
+ { chrome: "push", variant: "warning", className: "border-b-[color:var(--warning-80)]" },
1147
+ { chrome: "push", variant: "danger", className: "border-b-[color:var(--danger-80)]" },
1148
+ { chrome: "push", variant: "link", className: "border-b-0 !shadow-none" },
1149
+ { chrome: "soft", variant: "primary", className: cn("!bg-[color:color-mix(in_oklab,var(--brand),transparent_70%)]", "!border-[color:color-mix(in_oklab,var(--brand),transparent_55%)]", "!shadow-[0_1px_0_rgba(255,255,255,0.5)_inset,0_3px_8px_color-mix(in_oklab,var(--brand),transparent_70%)]") },
1150
+ { chrome: "soft", variant: "secondary", className: cn("!bg-[color:color-mix(in_oklab,var(--surface-2),transparent_25%)]", "!border-[color:color-mix(in_oklab,var(--border),transparent_15%)]", "!shadow-[0_1px_0_rgba(255,255,255,0.5)_inset,0_3px_8px_color-mix(in_oklab,var(--border),transparent_70%)]") },
1151
+ { chrome: "soft", variant: "outline", className: cn("!border-[color:color-mix(in_oklab,var(--border),transparent_15%)]", "!shadow-[0_1px_0_rgba(255,255,255,0.5)_inset,0_3px_8px_color-mix(in_oklab,var(--border),transparent_70%)]") },
1152
+ { chrome: "soft", variant: "ghost", className: "!shadow-[0_3px_8px_color-mix(in_oklab,var(--border),transparent_75%)]" },
1153
+ { chrome: "soft", variant: "success", className: cn("!bg-[color:color-mix(in_oklab,var(--success),transparent_70%)]", "!border-[color:color-mix(in_oklab,var(--success),transparent_55%)]", "!shadow-[0_1px_0_rgba(255,255,255,0.5)_inset,0_3px_8px_color-mix(in_oklab,var(--success),transparent_70%)]") },
1154
+ { chrome: "soft", variant: "info", className: cn("!bg-[color:color-mix(in_oklab,var(--info),transparent_70%)]", "!border-[color:color-mix(in_oklab,var(--info),transparent_55%)]", "!shadow-[0_1px_0_rgba(255,255,255,0.5)_inset,0_3px_8px_color-mix(in_oklab,var(--info),transparent_70%)]") },
1155
+ { chrome: "soft", variant: "warning", className: cn("!bg-[color:color-mix(in_oklab,var(--warning),transparent_70%)]", "!border-[color:color-mix(in_oklab,var(--warning),transparent_55%)]", "!shadow-[0_1px_0_rgba(255,255,255,0.5)_inset,0_3px_8px_color-mix(in_oklab,var(--warning),transparent_70%)]") },
1156
+ { chrome: "soft", variant: "danger", className: cn("!bg-[color:color-mix(in_oklab,var(--danger),transparent_70%)]", "!border-[color:color-mix(in_oklab,var(--danger),transparent_55%)]", "!shadow-[0_1px_0_rgba(255,255,255,0.5)_inset,0_3px_8px_color-mix(in_oklab,var(--danger),transparent_70%)]") },
1157
+ { chrome: "soft", variant: "link", className: cn("!text-[var(--link)]", "!shadow-[0_3px_8px_color-mix(in_oklab,var(--link),transparent_75%)]") },
1158
+ { chrome: "glass", variant: "primary", className: cn("!bg-[color:color-mix(in_oklab,var(--brand),transparent_65%)]", "!border-[var(--brand)]") },
1159
+ { chrome: "glass", variant: "secondary", className: cn("!bg-[color:color-mix(in_oklab,var(--surface-2),transparent_35%)]", "!border-[color:color-mix(in_oklab,var(--border),transparent_70%)]") },
1160
+ { chrome: "glass", variant: "outline", className: "" },
1161
+ { chrome: "glass", variant: "ghost", className: "" },
1162
+ { chrome: "glass", variant: "success", className: cn("!bg-[color:color-mix(in_oklab,var(--success),transparent_65%)]", "!border-[var(--success)]") },
1163
+ { chrome: "glass", variant: "info", className: cn("!bg-[color:color-mix(in_oklab,var(--info),transparent_65%)]", "!border-[var(--info)]") },
1164
+ { chrome: "glass", variant: "warning", className: cn("!bg-[color:color-mix(in_oklab,var(--warning),transparent_65%)]", "!border-[var(--warning)]") },
1165
+ { chrome: "glass", variant: "danger", className: cn("!bg-[color:color-mix(in_oklab,var(--danger),transparent_65%)]", "!border-[var(--danger)]") },
1166
+ { chrome: "glass", variant: "link", className: "!text-[var(--link)]" },
1167
+ { chrome: "glow", variant: "primary", className: cn("!border-[var(--brand)]", "!shadow-[0_0_0_1px_color-mix(in_oklab,var(--brand),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--brand),transparent_55%)]", "hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--brand),transparent_10%),0_14px_34px_color-mix(in_oklab,var(--brand),transparent_40%)]", "dark:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--brand),transparent_30%),0_8px_22px_color-mix(in_oklab,var(--brand),transparent_70%)]", "dark:hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--brand),transparent_15%),0_12px_30px_color-mix(in_oklab,var(--brand),transparent_55%)]") },
1168
+ { chrome: "glow", variant: "secondary", className: cn("!border-[color:color-mix(in_oklab,var(--border),transparent_20%)]", "!shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--border),transparent_60%)]", "hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_15%),0_14px_34px_color-mix(in_oklab,var(--border),transparent_45%)]", "dark:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_30%),0_8px_22px_color-mix(in_oklab,var(--border),transparent_75%)]", "dark:hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_20%),0_12px_30px_color-mix(in_oklab,var(--border),transparent_60%)]") },
1169
+ { chrome: "glow", variant: "outline", className: cn("!border-[color:color-mix(in_oklab,var(--border),transparent_20%)]", "!shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--border),transparent_60%)]", "hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_15%),0_14px_34px_color-mix(in_oklab,var(--border),transparent_45%)]", "dark:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_30%),0_8px_22px_color-mix(in_oklab,var(--border),transparent_75%)]", "dark:hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_20%),0_12px_30px_color-mix(in_oklab,var(--border),transparent_60%)]") },
1170
+ { chrome: "glow", variant: "ghost", className: "!shadow-none !border-transparent" },
1171
+ { chrome: "glow", variant: "success", className: cn("!border-[var(--success)]", "!shadow-[0_0_0_1px_color-mix(in_oklab,var(--success),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--success),transparent_55%)]", "hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--success),transparent_10%),0_14px_34px_color-mix(in_oklab,var(--success),transparent_40%)]", "dark:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--success),transparent_30%),0_8px_22px_color-mix(in_oklab,var(--success),transparent_70%)]", "dark:hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--success),transparent_15%),0_12px_30px_color-mix(in_oklab,var(--success),transparent_55%)]") },
1172
+ { chrome: "glow", variant: "info", className: cn("!border-[var(--info)]", "!shadow-[0_0_0_1px_color-mix(in_oklab,var(--info),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--info),transparent_55%)]", "hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--info),transparent_10%),0_14px_34px_color-mix(in_oklab,var(--info),transparent_40%)]", "dark:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--info),transparent_30%),0_8px_22px_color-mix(in_oklab,var(--info),transparent_70%)]", "dark:hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--info),transparent_15%),0_12px_30px_color-mix(in_oklab,var(--info),transparent_55%)]") },
1173
+ { chrome: "glow", variant: "warning", className: cn("!border-[var(--warning)]", "!shadow-[0_0_0_1px_color-mix(in_oklab,var(--warning),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--warning),transparent_55%)]", "hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--warning),transparent_10%),0_14px_34px_color-mix(in_oklab,var(--warning),transparent_40%)]", "dark:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--warning),transparent_30%),0_8px_22px_color-mix(in_oklab,var(--warning),transparent_70%)]", "dark:hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--warning),transparent_15%),0_12px_30px_color-mix(in_oklab,var(--warning),transparent_55%)]") },
1174
+ { chrome: "glow", variant: "danger", className: cn("!border-[var(--danger)]", "!shadow-[0_0_0_1px_color-mix(in_oklab,var(--danger),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--danger),transparent_55%)]", "hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--danger),transparent_10%),0_14px_34px_color-mix(in_oklab,var(--danger),transparent_40%)]", "dark:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--danger),transparent_30%),0_8px_22px_color-mix(in_oklab,var(--danger),transparent_70%)]", "dark:hover:!shadow-[0_0_0_1px_color-mix(in_oklab,var(--danger),transparent_15%),0_12px_30px_color-mix(in_oklab,var(--danger),transparent_55%)]") },
1175
+ { chrome: "glow", variant: "link", className: "!text-[var(--link)] !shadow-none !border-transparent" },
1176
+ { chrome: "hairline", variant: "primary", className: "!border-[color:color-mix(in_oklab,var(--brand),transparent_20%)] !text-[var(--brand)]" },
1177
+ { chrome: "hairline", variant: "secondary", className: "!border-[color:color-mix(in_oklab,var(--border),transparent_20%)] !text-[var(--text-1)]" },
1178
+ { chrome: "hairline", variant: "outline", className: "!border-[color:color-mix(in_oklab,var(--border),transparent_20%)] !text-[var(--text-1)]" },
1179
+ { chrome: "hairline", variant: "ghost", className: "!border-transparent !text-[var(--text-1)]" },
1180
+ { chrome: "hairline", variant: "success", className: "!border-[color:color-mix(in_oklab,var(--success),transparent_20%)] !text-[var(--success)]" },
1181
+ { chrome: "hairline", variant: "info", className: "!border-[color:color-mix(in_oklab,var(--info),transparent_20%)] !text-[var(--info)]" },
1182
+ { chrome: "hairline", variant: "warning", className: "!border-[color:color-mix(in_oklab,var(--warning),transparent_20%)] !text-[var(--warning)]" },
1183
+ { chrome: "hairline", variant: "danger", className: "!border-[color:color-mix(in_oklab,var(--danger),transparent_20%)] !text-[var(--danger)]" },
1184
+ { chrome: "hairline", variant: "link", className: "!text-[var(--link)] !border-transparent" }
1185
+ ],
1186
+ defaultVariants: { variant: "primary", size: "md", chrome: "flat", fullWidth: false }
1187
+ });
1188
+ var Button = React3.forwardRef(
1189
+ ({
1190
+ asChild = false,
1191
+ variant,
1192
+ size,
1193
+ chrome,
1194
+ fullWidth,
1195
+ className,
1196
+ loading = false,
1197
+ disabled,
1198
+ leftIcon,
1199
+ rightIcon,
1200
+ children,
1201
+ onClick,
1202
+ type,
1203
+ ...props
1204
+ }, ref) => {
1205
+ const isDisabled = disabled || loading;
1206
+ const classes = cn(buttonVariants({ variant, size, chrome, fullWidth }), className);
1207
+ const hasText = React3.Children.count(children) > 0;
1208
+ const content = /* @__PURE__ */ jsxs3(Fragment2, { children: [
1209
+ loading ? /* @__PURE__ */ jsx7(
1210
+ "span",
1211
+ {
1212
+ "aria-hidden": "true",
1213
+ className: [
1214
+ "inline-block h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent",
1215
+ hasText ? "mr-2" : ""
1216
+ ].join(" ")
1217
+ }
1218
+ ) : leftIcon,
1219
+ hasText ? /* @__PURE__ */ jsx7("span", { children }) : null,
1220
+ hasText ? rightIcon : null
1221
+ ] });
1222
+ if (asChild) {
1223
+ return /* @__PURE__ */ jsx7(
1224
+ Slot.Root,
1225
+ {
1226
+ ref,
1227
+ className: classes,
1228
+ "aria-disabled": isDisabled || void 0,
1229
+ "aria-busy": loading || void 0,
1230
+ "data-loading": loading ? "" : void 0,
1231
+ tabIndex: isDisabled ? -1 : void 0,
1232
+ onClick: (e) => {
1233
+ if (isDisabled) {
1234
+ e.preventDefault?.();
1235
+ e.stopPropagation?.();
1236
+ return;
1237
+ }
1238
+ onClick?.(e);
1239
+ },
1240
+ ...props,
1241
+ children: content
1242
+ }
1243
+ );
1244
+ }
1245
+ return /* @__PURE__ */ jsx7(
1246
+ "button",
1247
+ {
1248
+ ref,
1249
+ type: type ?? "button",
1250
+ className: classes,
1251
+ disabled: isDisabled,
1252
+ "aria-busy": loading || void 0,
1253
+ "data-loading": loading ? "" : void 0,
1254
+ onClick,
1255
+ ...props,
1256
+ children: content
1257
+ }
1258
+ );
1259
+ }
1260
+ );
1261
+ Button.displayName = "Button";
1050
1262
  export {
1051
1263
  AuthController,
1052
1264
  AuthControllerCtx,
@@ -1055,6 +1267,7 @@ export {
1055
1267
  AuthFormInputField,
1056
1268
  AuthProvider,
1057
1269
  AuthStateCtx,
1270
+ Button,
1058
1271
  DEFAULT_NOTIFICATION_CHANNEL,
1059
1272
  HttpError,
1060
1273
  MockAuthHttpClient,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexdspace/react",
3
- "version": "0.0.26",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -27,29 +27,53 @@
27
27
  "access": "public"
28
28
  },
29
29
  "dependencies": {
30
- "@tanstack/react-query": "^5.90.11",
31
- "lucide-react": "^0.555.0",
32
- "react-router-dom": "^7.10.1",
33
- "react-toastify": "^11.0.5",
34
- "tailwind-scrollbar": "^4.0.2",
30
+ "class-variance-authority": "^0.7.1",
31
+ "clsx": "^2.1.1",
32
+ "tailwind-merge": "^3.4.0",
35
33
  "uuid": "^13.0.0",
36
34
  "@hexdspace/util": "0.0.25"
37
35
  },
38
36
  "peerDependencies": {
39
37
  "@tanstack/react-query": "^5.90.11",
40
- "react": "^19.2.0"
38
+ "lucide-react": "^0.555.0",
39
+ "radix-ui": "^1.4.3",
40
+ "react": "^19.2.3",
41
+ "react-dom": "^19.2.3",
42
+ "react-router-dom": "^7.10.1",
43
+ "react-toastify": "^11.0.5"
41
44
  },
42
45
  "devDependencies": {
46
+ "@chromatic-com/storybook": "^4.1.3",
47
+ "@storybook/addon-a11y": "^10.1.10",
48
+ "@storybook/addon-docs": "^10.1.10",
49
+ "@storybook/addon-onboarding": "^10.1.10",
50
+ "@storybook/addon-vitest": "^10.1.10",
51
+ "@storybook/react-vite": "^10.1.10",
52
+ "@tailwindcss/cli": "^4.1.18",
53
+ "@tailwindcss/vite": "^4.1.18",
43
54
  "@tanstack/react-query": "^5.90.11",
44
55
  "@types/react": "^19.2.7",
56
+ "@vitest/browser": "^3.2.4",
57
+ "@vitest/coverage-v8": "^3.2.4",
45
58
  "autoprefixer": "^10.4.22",
59
+ "lucide-react": "^0.555.0",
60
+ "playwright": "^1.57.0",
46
61
  "postcss": "^8.5.6",
47
- "react": "^19.2.0",
48
- "tailwindcss": "^4.1.17"
62
+ "radix-ui": "^1.4.3",
63
+ "react": "^19.2.3",
64
+ "react-dom": "^19.2.3",
65
+ "react-router-dom": "^7.10.1",
66
+ "react-toastify": "^11.0.5",
67
+ "storybook": "^10.1.10",
68
+ "tailwind-scrollbar": "^4.0.2",
69
+ "tailwindcss": "^4.1.17",
70
+ "vite": "^7.2.4"
49
71
  },
50
72
  "scripts": {
51
73
  "build": "tsup src/index.ts --dts --format esm --clean && pnpm run build:css",
52
- "build:css": "mkdir -p dist/css && cp -R src/feature/theme/css/* dist/css/",
53
- "test": "vitest"
74
+ "build:css": "mkdir -p dist/css && cp -R src/ui/theme/css/* dist/css/ && tailwindcss -i src/ui/theme/css/base-theme.css -o dist/css/base-theme.css --config tailwind.config.mjs",
75
+ "test": "vitest",
76
+ "storybook": "storybook dev -p 6006",
77
+ "build-storybook": "storybook build"
54
78
  }
55
79
  }