@hexdspace/react 0.1.8 → 0.1.9

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/index.js CHANGED
@@ -15,6 +15,26 @@ var ui = {
15
15
  // src/util/responsive-query/use-responsive-mutation.ts
16
16
  import { useMutation } from "@tanstack/react-query";
17
17
 
18
+ // src/feature/notifier/application/use-case/send-notification-use-case.ts
19
+ var SendNotificationUseCase = class {
20
+ constructor(bus2) {
21
+ this.bus = bus2;
22
+ }
23
+ async execute(channel, notification) {
24
+ this.bus.publish(channel, notification);
25
+ }
26
+ };
27
+
28
+ // src/feature/notifier/application/use-case/subscribe-use-case.ts
29
+ var SubscribeUseCase = class {
30
+ constructor(bus2) {
31
+ this.bus = bus2;
32
+ }
33
+ async execute(channel, observer) {
34
+ return this.bus.subscribe(channel, observer);
35
+ }
36
+ };
37
+
18
38
  // src/feature/notifier/entity/notification-bus.ts
19
39
  var NotificationBus = class {
20
40
  channels = /* @__PURE__ */ new Map();
@@ -51,26 +71,6 @@ var NotificationBus = class {
51
71
  }
52
72
  };
53
73
 
54
- // src/feature/notifier/application/use-case/send-notification-use-case.ts
55
- var SendNotificationUseCase = class {
56
- constructor(bus2) {
57
- this.bus = bus2;
58
- }
59
- async execute(channel, notification) {
60
- this.bus.publish(channel, notification);
61
- }
62
- };
63
-
64
- // src/feature/notifier/application/use-case/subscribe-use-case.ts
65
- var SubscribeUseCase = class {
66
- constructor(bus2) {
67
- this.bus = bus2;
68
- }
69
- async execute(channel, observer) {
70
- return this.bus.subscribe(channel, observer);
71
- }
72
- };
73
-
74
74
  // src/feature/notifier/infra/controllers/notifier-controller.ts
75
75
  var NotifierController = class {
76
76
  constructor(sender, subscriber) {
@@ -91,15 +91,87 @@ var notifierController = new NotifierController(sendNotification, subscribe);
91
91
 
92
92
  // src/feature/notifier/infra/web/react/NotificationHost.tsx
93
93
  import { useCallback, useEffect, useMemo as useMemo2 } from "react";
94
- import { cssTransition, Slide, toast as toast2, ToastContainer } from "react-toastify";
94
+ import {
95
+ Slide,
96
+ ToastContainer,
97
+ cssTransition,
98
+ toast as toast2
99
+ } from "react-toastify";
95
100
 
96
101
  // src/feature/notifier/entity/notification.ts
97
102
  var DEFAULT_NOTIFICATION_CHANNEL = "app.notifications";
98
103
 
104
+ // src/feature/notifier/entity/toast-theme.ts
105
+ var DEFAULT_ACTION_THEME = {
106
+ padding: "0.35rem 0.75rem",
107
+ borderRadius: "var(--radius-btn)",
108
+ background: "color-mix(in oklab, var(--brand), transparent 88%)",
109
+ hoverBackground: "color-mix(in oklab, currentColor, transparent 92%)",
110
+ focusOutline: "2px solid var(--focus)",
111
+ focusOutlineOffset: "2px",
112
+ fontWeight: 600,
113
+ transition: "background-color var(--motion-med) ease, color var(--motion-med) ease, transform var(--motion-med) ease",
114
+ focusTransform: "translateY(-1px)",
115
+ activeTransform: "translateY(0)",
116
+ marginLeft: "auto",
117
+ marginTop: "0.15rem"
118
+ };
119
+ var DEFAULT_ICON_COLORS = {
120
+ info: "var(--info)",
121
+ success: "var(--success)",
122
+ warning: "var(--warning)",
123
+ error: "var(--danger)"
124
+ };
125
+ var DEFAULT_THEME_BASE = {
126
+ lightBg: "var(--surface-3)",
127
+ lightText: "var(--text-1)",
128
+ lightProgress: "var(--brand)",
129
+ darkBg: "var(--surface-1)",
130
+ darkText: "var(--text-1)",
131
+ darkProgress: "var(--brand)",
132
+ progressInfo: "var(--info)",
133
+ progressSuccess: "var(--success)",
134
+ progressWarning: "var(--warning)",
135
+ progressError: "var(--danger)",
136
+ width: "min(24rem, calc(100vw - 2rem))",
137
+ toastRadius: "var(--radius-card)",
138
+ contentPadding: "0.5rem 0.75rem 1rem 0.5rem",
139
+ bodyColumnGap: "0.75rem",
140
+ bodyRowGap: "0.25rem"
141
+ };
142
+ function resolveToastTheme(theme) {
143
+ return {
144
+ lightBg: theme?.lightBg ?? DEFAULT_THEME_BASE.lightBg,
145
+ lightText: theme?.lightText ?? DEFAULT_THEME_BASE.lightText,
146
+ lightProgress: theme?.lightProgress ?? DEFAULT_THEME_BASE.lightProgress,
147
+ darkBg: theme?.darkBg ?? DEFAULT_THEME_BASE.darkBg,
148
+ darkText: theme?.darkText ?? DEFAULT_THEME_BASE.darkText,
149
+ darkProgress: theme?.darkProgress ?? DEFAULT_THEME_BASE.darkProgress,
150
+ progressInfo: theme?.progressInfo ?? DEFAULT_THEME_BASE.progressInfo,
151
+ progressSuccess: theme?.progressSuccess ?? DEFAULT_THEME_BASE.progressSuccess,
152
+ progressWarning: theme?.progressWarning ?? DEFAULT_THEME_BASE.progressWarning,
153
+ progressError: theme?.progressError ?? DEFAULT_THEME_BASE.progressError,
154
+ width: theme?.width ?? DEFAULT_THEME_BASE.width,
155
+ toastRadius: theme?.toastRadius ?? DEFAULT_THEME_BASE.toastRadius,
156
+ contentPadding: theme?.contentPadding ?? DEFAULT_THEME_BASE.contentPadding,
157
+ bodyColumnGap: theme?.bodyColumnGap ?? DEFAULT_THEME_BASE.bodyColumnGap,
158
+ bodyRowGap: theme?.bodyRowGap ?? DEFAULT_THEME_BASE.bodyRowGap,
159
+ transition: theme?.transition,
160
+ action: {
161
+ ...DEFAULT_ACTION_THEME,
162
+ ...theme?.action ?? {}
163
+ },
164
+ iconColors: {
165
+ ...DEFAULT_ICON_COLORS,
166
+ ...theme?.iconColors ?? {}
167
+ }
168
+ };
169
+ }
170
+
99
171
  // src/feature/notifier/infra/web/react/ToastContent.tsx
172
+ import { AlertTriangleIcon, CheckCircleIcon, InfoIcon, XCircleIcon } from "lucide-react";
100
173
  import { useMemo, useState } from "react";
101
174
  import { toast } from "react-toastify";
102
- import { AlertTriangleIcon, CheckCircleIcon, InfoIcon, XCircleIcon } from "lucide-react";
103
175
  import { jsx, jsxs } from "react/jsx-runtime";
104
176
  var DEFAULT_NOTIFICATION_VARIANT = "info";
105
177
  var TOAST_ICON_BY_VARIANT = {
@@ -120,7 +192,8 @@ var ToastContent = ({ notification, theme, mode }) => {
120
192
  const actionTextColor = theme.action.color ?? textColor;
121
193
  const actionHoverColor = theme.action.hoverColor ?? actionTextColor;
122
194
  const actionStyle = useMemo(() => {
123
- const background = isHovered ? theme.action.hoverBackground : theme.action.background;
195
+ const hoverOverlay = theme.action.hoverBackground;
196
+ const background = isHovered ? `linear-gradient(0deg, ${hoverOverlay}, ${hoverOverlay}), ${theme.action.background}` : theme.action.background;
124
197
  const color = isHovered ? actionHoverColor : actionTextColor;
125
198
  const transform = isActive ? theme.action.activeTransform : isFocused ? theme.action.focusTransform : void 0;
126
199
  return {
@@ -173,7 +246,13 @@ var ToastContent = ({ notification, theme, mode }) => {
173
246
  /* @__PURE__ */ jsx(
174
247
  Icon,
175
248
  {
176
- style: { color: iconColor, padding: "0.125rem", width: "1.25rem", height: "1.25rem", flexShrink: 0 },
249
+ style: {
250
+ color: iconColor,
251
+ padding: "0.125rem",
252
+ width: "1.25rem",
253
+ height: "1.25rem",
254
+ flexShrink: 0
255
+ },
177
256
  "aria-hidden": "true"
178
257
  }
179
258
  ),
@@ -239,74 +318,33 @@ var ToastContent = ({ notification, theme, mode }) => {
239
318
  );
240
319
  };
241
320
 
242
- // src/feature/notifier/entity/toast-theme.ts
243
- var DEFAULT_ACTION_THEME = {
244
- padding: "0.35rem 0.75rem",
245
- borderRadius: "0.5rem",
246
- background: "rgba(79, 70, 229, 0.12)",
247
- hoverBackground: "rgba(79, 70, 229, 0.2)",
248
- focusOutline: "2px solid #4338ca",
249
- focusOutlineOffset: "2px",
250
- fontWeight: 600,
251
- transition: "background-color 0.2s ease, color 0.2s ease, transform 0.2s ease",
252
- focusTransform: "translateY(-1px)",
253
- activeTransform: "translateY(0)",
254
- marginLeft: "auto",
255
- marginTop: "0.15rem"
256
- };
257
- var DEFAULT_ICON_COLORS = {
258
- info: "#2563eb",
259
- success: "#16a34a",
260
- warning: "#f59e0b",
261
- error: "#dc2626"
262
- };
263
- var DEFAULT_THEME_BASE = {
264
- lightBg: "#f8fafc",
265
- lightText: "#0f172a",
266
- lightProgress: "#4f46e5",
267
- darkBg: "#111827",
268
- darkText: "#e5e7eb",
269
- darkProgress: "#a5b4fc",
270
- progressInfo: "#60a5fa",
271
- progressSuccess: "#34d399",
272
- progressWarning: "#fbbf24",
273
- progressError: "#f87171",
274
- width: "min(24rem, calc(100vw - 2rem))",
275
- contentPadding: "0.5rem 0.75rem 1rem 0.5rem",
276
- bodyColumnGap: "0.75rem",
277
- bodyRowGap: "0.25rem"
278
- };
279
- function resolveToastTheme(theme) {
280
- return {
281
- lightBg: theme?.lightBg ?? DEFAULT_THEME_BASE.lightBg,
282
- lightText: theme?.lightText ?? DEFAULT_THEME_BASE.lightText,
283
- lightProgress: theme?.lightProgress ?? DEFAULT_THEME_BASE.lightProgress,
284
- darkBg: theme?.darkBg ?? DEFAULT_THEME_BASE.darkBg,
285
- darkText: theme?.darkText ?? DEFAULT_THEME_BASE.darkText,
286
- darkProgress: theme?.darkProgress ?? DEFAULT_THEME_BASE.darkProgress,
287
- progressInfo: theme?.progressInfo ?? DEFAULT_THEME_BASE.progressInfo,
288
- progressSuccess: theme?.progressSuccess ?? DEFAULT_THEME_BASE.progressSuccess,
289
- progressWarning: theme?.progressWarning ?? DEFAULT_THEME_BASE.progressWarning,
290
- progressError: theme?.progressError ?? DEFAULT_THEME_BASE.progressError,
291
- width: theme?.width ?? DEFAULT_THEME_BASE.width,
292
- contentPadding: theme?.contentPadding ?? DEFAULT_THEME_BASE.contentPadding,
293
- bodyColumnGap: theme?.bodyColumnGap ?? DEFAULT_THEME_BASE.bodyColumnGap,
294
- bodyRowGap: theme?.bodyRowGap ?? DEFAULT_THEME_BASE.bodyRowGap,
295
- transition: theme?.transition,
296
- action: {
297
- ...DEFAULT_ACTION_THEME,
298
- ...theme?.action ?? {}
299
- },
300
- iconColors: {
301
- ...DEFAULT_ICON_COLORS,
302
- ...theme?.iconColors ?? {}
303
- }
304
- };
305
- }
306
-
307
321
  // src/feature/notifier/infra/web/react/NotificationHost.tsx
308
322
  import { jsx as jsx2 } from "react/jsx-runtime";
309
- var NotificationHost = ({ channel = DEFAULT_NOTIFICATION_CHANNEL, isDark, theme }) => {
323
+ var ToastCloseButton = ({ closeToast, theme, ariaLabel }) => /* @__PURE__ */ jsx2(
324
+ "button",
325
+ {
326
+ type: "button",
327
+ className: `Toastify__close-button Toastify__close-button--${theme}`,
328
+ "aria-label": ariaLabel ?? "close",
329
+ onClick: (event) => {
330
+ event.stopPropagation();
331
+ closeToast(true);
332
+ },
333
+ style: { color: "var(--text-1)" },
334
+ children: /* @__PURE__ */ jsx2("svg", { "aria-hidden": "true", viewBox: "0 0 14 16", children: /* @__PURE__ */ jsx2(
335
+ "path",
336
+ {
337
+ fillRule: "evenodd",
338
+ d: "M7.71 8.23l3.75 3.75-1.48 1.48-3.75-3.75-3.75 3.75L1 11.98l3.75-3.75L1 4.48 2.48 3l3.75 3.75L9.98 3l1.48 1.48-3.75 3.75z"
339
+ }
340
+ ) })
341
+ }
342
+ );
343
+ var NotificationHost = ({
344
+ channel = DEFAULT_NOTIFICATION_CHANNEL,
345
+ isDark,
346
+ theme
347
+ }) => {
310
348
  const resolvedTheme = useMemo2(() => resolveToastTheme(theme), [theme]);
311
349
  const mode = useMemo2(() => {
312
350
  if (!isDark) {
@@ -318,27 +356,34 @@ var NotificationHost = ({ channel = DEFAULT_NOTIFICATION_CHANNEL, isDark, theme
318
356
  const config = resolvedTheme.transition;
319
357
  return config ? cssTransition(config) : Slide;
320
358
  }, [resolvedTheme.transition]);
321
- const style = useMemo2(() => ({
322
- "--toastify-color-light": resolvedTheme.lightBg,
323
- "--toastify-text-color-light": resolvedTheme.lightText,
324
- "--toastify-color-progress-light": resolvedTheme.lightProgress,
325
- "--toastify-color-dark": resolvedTheme.darkBg,
326
- "--toastify-text-color-dark": resolvedTheme.darkText,
327
- "--toastify-color-progress-dark": resolvedTheme.darkProgress,
328
- "--toastify-color-progress-info": resolvedTheme.progressInfo,
329
- "--toastify-color-progress-success": resolvedTheme.progressSuccess,
330
- "--toastify-color-progress-warning": resolvedTheme.progressWarning,
331
- "--toastify-color-progress-error": resolvedTheme.progressError,
332
- "--toastify-toast-width": resolvedTheme.width
333
- }), [resolvedTheme]);
334
- const renderToast = useCallback((notification) => {
335
- const variant = notification.variant ?? "info";
336
- toast2(/* @__PURE__ */ jsx2(ToastContent, { notification, theme: resolvedTheme, mode }), {
337
- toastId: notification.id,
338
- icon: false,
339
- type: variant
340
- });
341
- }, [mode, resolvedTheme]);
359
+ const style = useMemo2(
360
+ () => ({
361
+ "--toastify-color-light": resolvedTheme.lightBg,
362
+ "--toastify-text-color-light": resolvedTheme.lightText,
363
+ "--toastify-color-progress-light": resolvedTheme.lightProgress,
364
+ "--toastify-color-dark": resolvedTheme.darkBg,
365
+ "--toastify-text-color-dark": resolvedTheme.darkText,
366
+ "--toastify-color-progress-dark": resolvedTheme.darkProgress,
367
+ "--toastify-color-progress-info": resolvedTheme.progressInfo,
368
+ "--toastify-color-progress-success": resolvedTheme.progressSuccess,
369
+ "--toastify-color-progress-warning": resolvedTheme.progressWarning,
370
+ "--toastify-color-progress-error": resolvedTheme.progressError,
371
+ "--toastify-toast-width": resolvedTheme.width,
372
+ "--toastify-toast-bd-radius": resolvedTheme.toastRadius
373
+ }),
374
+ [resolvedTheme]
375
+ );
376
+ const renderToast = useCallback(
377
+ (notification) => {
378
+ const variant = notification.variant ?? "info";
379
+ toast2(/* @__PURE__ */ jsx2(ToastContent, { notification, theme: resolvedTheme, mode }), {
380
+ toastId: notification.id,
381
+ icon: false,
382
+ type: variant
383
+ });
384
+ },
385
+ [mode, resolvedTheme]
386
+ );
342
387
  useEffect(() => {
343
388
  let unsub;
344
389
  let disposed = false;
@@ -361,6 +406,8 @@ var NotificationHost = ({ channel = DEFAULT_NOTIFICATION_CHANNEL, isDark, theme
361
406
  ToastContainer,
362
407
  {
363
408
  style,
409
+ toastStyle: { overflow: "hidden" },
410
+ closeButton: ToastCloseButton,
364
411
  position: "bottom-right",
365
412
  transition,
366
413
  newestOnTop: true,
@@ -399,7 +446,7 @@ function useResponsiveMutation(responsiveMutation, queryClient) {
399
446
  });
400
447
  }
401
448
  var executeEffects = (effects, ctx) => {
402
- effects.forEach((effect) => {
449
+ for (const effect of effects) {
403
450
  if (effect.type === "invalidate") {
404
451
  void ctx.queryClient.invalidateQueries({ queryKey: effect.queryKey });
405
452
  } else if (effect.type === "update") {
@@ -412,7 +459,7 @@ var executeEffects = (effects, ctx) => {
412
459
  } else if (effect.type === "custom") {
413
460
  void effect.run(ctx);
414
461
  }
415
- });
462
+ }
416
463
  };
417
464
 
418
465
  // src/util/controller-factory.ts
@@ -553,13 +600,14 @@ async function refresh(httpClient2) {
553
600
  } catch (err) {
554
601
  if (err instanceof HttpError) {
555
602
  return nok(err);
556
- } else {
557
- return nok(new HttpError("Unknown error during refresh", 0, {
603
+ }
604
+ return nok(
605
+ new HttpError("Unknown error during refresh", 0, {
558
606
  name: "Error",
559
607
  message: JSON.stringify(err),
560
608
  status: 500
561
- }));
562
- }
609
+ })
610
+ );
563
611
  }
564
612
  }
565
613
  var httpClient = new AutoRefreshDecorator(new FetchHttpClient(), refresh);
@@ -604,6 +652,46 @@ var MockHttpClient = class {
604
652
  }
605
653
  };
606
654
 
655
+ // src/feature/auth/application/use-case/get-authenticated-user-use-case.ts
656
+ var GetAuthenticatedUserUseCase = class {
657
+ constructor(authProvider) {
658
+ this.authProvider = authProvider;
659
+ }
660
+ execute() {
661
+ return this.authProvider.getAuthenticatedUser();
662
+ }
663
+ };
664
+
665
+ // src/feature/auth/application/use-case/login-user-use-case.ts
666
+ var LoginUserUseCase = class {
667
+ constructor(authProvider) {
668
+ this.authProvider = authProvider;
669
+ }
670
+ execute(email, password) {
671
+ return this.authProvider.login(email, password);
672
+ }
673
+ };
674
+
675
+ // src/feature/auth/application/use-case/logout-user-use-case.ts
676
+ var LogoutUserUseCase = class {
677
+ constructor(authProvider) {
678
+ this.authProvider = authProvider;
679
+ }
680
+ execute() {
681
+ return this.authProvider.logout();
682
+ }
683
+ };
684
+
685
+ // src/feature/auth/application/use-case/register-user-use-case.ts
686
+ var RegisterUserUseCase = class {
687
+ constructor(authProvider) {
688
+ this.authProvider = authProvider;
689
+ }
690
+ execute(email, password, attributes) {
691
+ return this.authProvider.register(email, password, attributes);
692
+ }
693
+ };
694
+
607
695
  // src/feature/auth/infra/http-cookie-auth-provider.ts
608
696
  import { nok as nok2, ok as ok2 } from "@hexdspace/util";
609
697
  var HttpCookieAuthProvider = class {
@@ -617,11 +705,11 @@ var HttpCookieAuthProvider = class {
617
705
  } catch (err) {
618
706
  if (isUnauthorizedError(err)) {
619
707
  return ok2(null);
620
- } else if (err instanceof Error) {
708
+ }
709
+ if (err instanceof Error) {
621
710
  return nok2(err);
622
- } else {
623
- return nok2(new Error("Unknown error during authentication"));
624
711
  }
712
+ return nok2(new Error("Unknown error during authentication"));
625
713
  }
626
714
  }
627
715
  async login(email, password) {
@@ -633,24 +721,23 @@ var HttpCookieAuthProvider = class {
633
721
  } catch (err) {
634
722
  if (err instanceof Error) {
635
723
  return nok2(err);
636
- } else {
637
- return nok2(new Error("Unknown error during authentication"));
638
724
  }
725
+ return nok2(new Error("Unknown error during authentication"));
639
726
  }
640
727
  }
641
728
  async register(email, password, attributes) {
642
729
  try {
643
- const res = await this.httpClient.post(
644
- "/auth/register",
645
- { email, password, ...attributes ?? {} }
646
- );
730
+ const res = await this.httpClient.post("/auth/register", {
731
+ email,
732
+ password,
733
+ ...attributes ?? {}
734
+ });
647
735
  return ok2(res.data);
648
736
  } catch (err) {
649
737
  if (err instanceof Error) {
650
738
  return nok2(err);
651
- } else {
652
- return nok2(new Error("Unknown error during authentication"));
653
739
  }
740
+ return nok2(new Error("Unknown error during authentication"));
654
741
  }
655
742
  }
656
743
  async logout() {
@@ -660,9 +747,8 @@ var HttpCookieAuthProvider = class {
660
747
  } catch (err) {
661
748
  if (err instanceof Error) {
662
749
  return nok2(err);
663
- } else {
664
- return nok2(new Error("Unknown error during logout"));
665
750
  }
751
+ return nok2(new Error("Unknown error during logout"));
666
752
  }
667
753
  }
668
754
  };
@@ -670,46 +756,6 @@ function isUnauthorizedError(error) {
670
756
  return error instanceof HttpError && error.status === 401;
671
757
  }
672
758
 
673
- // src/feature/auth/application/use-case/login-user-use-case.ts
674
- var LoginUserUseCase = class {
675
- constructor(authProvider) {
676
- this.authProvider = authProvider;
677
- }
678
- execute(email, password) {
679
- return this.authProvider.login(email, password);
680
- }
681
- };
682
-
683
- // src/feature/auth/application/use-case/logout-user-use-case.ts
684
- var LogoutUserUseCase = class {
685
- constructor(authProvider) {
686
- this.authProvider = authProvider;
687
- }
688
- execute() {
689
- return this.authProvider.logout();
690
- }
691
- };
692
-
693
- // src/feature/auth/application/use-case/register-user-use-case.ts
694
- var RegisterUserUseCase = class {
695
- constructor(authProvider) {
696
- this.authProvider = authProvider;
697
- }
698
- execute(email, password, attributes) {
699
- return this.authProvider.register(email, password, attributes);
700
- }
701
- };
702
-
703
- // src/feature/auth/application/use-case/get-authenticated-user-use-case.ts
704
- var GetAuthenticatedUserUseCase = class {
705
- constructor(authProvider) {
706
- this.authProvider = authProvider;
707
- }
708
- execute() {
709
- return this.authProvider.getAuthenticatedUser();
710
- }
711
- };
712
-
713
759
  // src/feature/auth/interface/controller/auth-controller.ts
714
760
  var AuthController = class {
715
761
  constructor(loginUser, logoutUser, registerUser, getAuthenticatedUser) {
@@ -732,12 +778,7 @@ var AuthController = class {
732
778
  }
733
779
  };
734
780
  var createAuthController = controllerFactory(
735
- (deps) => new AuthController(
736
- deps.loginUser,
737
- deps.logoutUser,
738
- deps.registerUser,
739
- deps.getAuthenticatedUser
740
- ),
781
+ (deps) => new AuthController(deps.loginUser, deps.logoutUser, deps.registerUser, deps.getAuthenticatedUser),
741
782
  (overrides) => {
742
783
  const httpClient2 = overrides.httpClient ?? httpClient;
743
784
  const authProvider = overrides.authProvider ?? new HttpCookieAuthProvider(httpClient2);
@@ -759,24 +800,6 @@ import { useContext as useContext2 } from "react";
759
800
  // src/feature/auth/interface/web/react/AuthProvider.tsx
760
801
  import { createContext as createContext2, useEffect as useEffect2, useReducer } from "react";
761
802
 
762
- // src/feature/auth/interface/web/react/state/auth-reducer.ts
763
- function authStateReducer(_state, action) {
764
- switch (action.type) {
765
- case "REQUEST":
766
- return { status: "loading" };
767
- case "SUCCESS":
768
- return { status: "unauthenticated", message: action.message };
769
- case "FAILED":
770
- return { status: "error", error: action.error };
771
- case "LOGOUT":
772
- return { status: "unauthenticated" };
773
- case "COMPLETE":
774
- return { status: "authenticated", user: action.user };
775
- default:
776
- throw new Error(`Unknown state: ${JSON.stringify(action)}`);
777
- }
778
- }
779
-
780
803
  // src/feature/auth/interface/web/react/hook/useAuthController.tsx
781
804
  import { useContext } from "react";
782
805
 
@@ -797,6 +820,24 @@ function useAuthController() {
797
820
  return authController2;
798
821
  }
799
822
 
823
+ // src/feature/auth/interface/web/react/state/auth-reducer.ts
824
+ function authStateReducer(_state, action) {
825
+ switch (action.type) {
826
+ case "REQUEST":
827
+ return { status: "loading" };
828
+ case "SUCCESS":
829
+ return { status: "unauthenticated", message: action.message };
830
+ case "FAILED":
831
+ return { status: "error", error: action.error };
832
+ case "LOGOUT":
833
+ return { status: "unauthenticated" };
834
+ case "COMPLETE":
835
+ return { status: "authenticated", user: action.user };
836
+ default:
837
+ throw new Error(`Unknown state: ${JSON.stringify(action)}`);
838
+ }
839
+ }
840
+
800
841
  // src/feature/auth/interface/web/react/AuthProvider.tsx
801
842
  import { jsx as jsx4 } from "react/jsx-runtime";
802
843
  var AuthStateCtx = createContext2(null);
@@ -820,7 +861,7 @@ function AuthProvider({ children }) {
820
861
  }
821
862
  };
822
863
  void fetchActiveUser();
823
- }, [dispatch, authController2]);
864
+ }, [authController2]);
824
865
  return /* @__PURE__ */ jsx4(AuthDispatchCtx.Provider, { value: dispatch, children: /* @__PURE__ */ jsx4(AuthStateCtx.Provider, { value: state, children }) });
825
866
  }
826
867
 
@@ -850,21 +891,27 @@ function useAuthDispatch() {
850
891
  function useAuthActions() {
851
892
  const dispatch = useAuthDispatch();
852
893
  const authController2 = useAuthController();
853
- const login = useCallback2(async (email, password) => {
854
- dispatch({ type: "REQUEST" });
855
- const res = await authController2.login(email, password);
856
- dispatchLoginResult(res, dispatch);
857
- return res;
858
- }, [dispatch, authController2]);
894
+ const login = useCallback2(
895
+ async (email, password) => {
896
+ dispatch({ type: "REQUEST" });
897
+ const res = await authController2.login(email, password);
898
+ dispatchLoginResult(res, dispatch);
899
+ return res;
900
+ },
901
+ [dispatch, authController2]
902
+ );
859
903
  const logout = useCallback2(() => {
860
904
  authController2.logout().then(() => dispatch({ type: "LOGOUT" }));
861
905
  }, [dispatch, authController2]);
862
- const register = useCallback2(async (email, password, attributes) => {
863
- dispatch({ type: "REQUEST" });
864
- const res = await authController2.register(email, password, attributes);
865
- dispatchRegisterResult(res, dispatch);
866
- return res;
867
- }, [dispatch, authController2]);
906
+ const register = useCallback2(
907
+ async (email, password, attributes) => {
908
+ dispatch({ type: "REQUEST" });
909
+ const res = await authController2.register(email, password, attributes);
910
+ dispatchRegisterResult(res, dispatch);
911
+ return res;
912
+ },
913
+ [dispatch, authController2]
914
+ );
868
915
  return { login, logout, register };
869
916
  }
870
917
  function dispatchLoginResult(res, dispatch) {
@@ -1019,9 +1066,9 @@ var MockAuthHttpClient = class extends MockHttpClient {
1019
1066
  };
1020
1067
 
1021
1068
  // src/ui/components/Button.tsx
1022
- import * as React3 from "react";
1023
- import { Slot } from "radix-ui";
1024
1069
  import { cva } from "class-variance-authority";
1070
+ import { Slot } from "radix-ui";
1071
+ import * as React from "react";
1025
1072
 
1026
1073
  // src/ui/utils/cn.ts
1027
1074
  import { clsx } from "clsx";
@@ -1064,11 +1111,7 @@ var insetChrome = cn(
1064
1111
  "border-[color:color-mix(in_oklab,var(--border),transparent_35%)]",
1065
1112
  "shadow-[inset_0_2px_6px_rgba(0,0,0,0.18)]"
1066
1113
  );
1067
- var glassChrome = cn(
1068
- "backdrop-blur-[2px]",
1069
- "border",
1070
- "shadow-[0_8px_18px_rgba(0,0,0,0.12)]"
1071
- );
1114
+ var glassChrome = cn("backdrop-blur-[2px]", "border", "shadow-[0_8px_18px_rgba(0,0,0,0.12)]");
1072
1115
  var glowChrome = cn(
1073
1116
  "border",
1074
1117
  "shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_40%),0_6px_16px_color-mix(in_oklab,var(--border),transparent_70%)]",
@@ -1119,60 +1162,297 @@ var buttonVariants = cva(buttonBase, {
1119
1162
  { chrome: "glass", className: "text-[color:var(--text-1)]" },
1120
1163
  { chrome: "push", variant: "primary", className: "border-b-[color:var(--brand-strong)]" },
1121
1164
  { chrome: "push", variant: "accent", className: "border-b-[color:var(--accent-strong)]" },
1122
- { chrome: "push", variant: "secondary", className: "border-b-[color:color-mix(in_oklab,var(--border),transparent 50%)]" },
1123
- { chrome: "push", variant: "outline", className: "border-b-[color:color-mix(in_oklab,var(--border),transparent 50%)]" },
1165
+ {
1166
+ chrome: "push",
1167
+ variant: "secondary",
1168
+ className: "border-b-[color:color-mix(in_oklab,var(--border),transparent 50%)]"
1169
+ },
1170
+ {
1171
+ chrome: "push",
1172
+ variant: "outline",
1173
+ className: "border-b-[color:color-mix(in_oklab,var(--border),transparent 50%)]"
1174
+ },
1124
1175
  { chrome: "push", variant: "ghost", className: "border-b-transparent shadow-none" },
1125
1176
  { chrome: "push", variant: "success", className: "border-b-[color:var(--success-80)]" },
1126
1177
  { chrome: "push", variant: "info", className: "border-b-[color:var(--info-80)]" },
1127
1178
  { chrome: "push", variant: "warning", className: "border-b-[color:var(--warning-80)]" },
1128
1179
  { chrome: "push", variant: "danger", className: "border-b-[color:var(--danger-80)]" },
1129
1180
  { chrome: "push", variant: "link", className: "border-b-0 shadow-none" },
1130
- { 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_85%)]", "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--brand),transparent_70%)]") },
1131
- { chrome: "soft", variant: "accent", className: cn("bg-[color:color-mix(in_oklab,var(--accent),transparent_70%)]", "border-[color:color-mix(in_oklab,var(--accent),transparent_85%)]", "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--accent),transparent_70%)]") },
1132
- { 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_45%)]", "shadow-[0_0_2px_1px_rgba(255,255,255,0.1)_inset,0_2px_4px_color-mix(in_oklab,var(--border),transparent_70%)]") },
1133
- { chrome: "soft", variant: "outline", className: cn("border-[color:color-mix(in_oklab,var(--border),transparent_45%)]", "shadow-[0_0_2px_1px_rgba(255,255,255,0.1)_inset,0_2px_4px_color-mix(in_oklab,var(--border),transparent_70%)]") },
1134
- { chrome: "soft", variant: "ghost", className: "shadow-[0_2px_4px_color-mix(in_oklab,var(--border),transparent_75%)]" },
1135
- { 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_75%)]", "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--success),transparent_70%)]") },
1136
- { 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_75%)]", "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--info),transparent_70%)]") },
1137
- { 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_75%)]", "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--warning),transparent_70%)]") },
1138
- { 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_75%)]", "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--danger),transparent_70%)]") },
1139
- { chrome: "soft", variant: "link", className: cn("text-[color:var(--link)]", "shadow-[0_2px_4px_color-mix(in_oklab,var(--link),transparent_75%)]") },
1140
- { chrome: "glass", variant: "primary", className: cn("bg-[color:color-mix(in_oklab,var(--brand),transparent_65%)]", "border-[color:var(--brand)]") },
1141
- { chrome: "glass", variant: "accent", className: cn("bg-[color:color-mix(in_oklab,var(--accent),transparent_65%)]", "border-[color:var(--accent)]") },
1142
- { 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%)]") },
1181
+ {
1182
+ chrome: "soft",
1183
+ variant: "primary",
1184
+ className: cn(
1185
+ "bg-[color:color-mix(in_oklab,var(--brand),transparent_70%)]",
1186
+ "border-[color:color-mix(in_oklab,var(--brand),transparent_85%)]",
1187
+ "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--brand),transparent_70%)]"
1188
+ )
1189
+ },
1190
+ {
1191
+ chrome: "soft",
1192
+ variant: "accent",
1193
+ className: cn(
1194
+ "bg-[color:color-mix(in_oklab,var(--accent),transparent_70%)]",
1195
+ "border-[color:color-mix(in_oklab,var(--accent),transparent_85%)]",
1196
+ "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--accent),transparent_70%)]"
1197
+ )
1198
+ },
1199
+ {
1200
+ chrome: "soft",
1201
+ variant: "secondary",
1202
+ className: cn(
1203
+ "bg-[color:color-mix(in_oklab,var(--surface-2),transparent_25%)]",
1204
+ "border-[color:color-mix(in_oklab,var(--border),transparent_45%)]",
1205
+ "shadow-[0_0_2px_1px_rgba(255,255,255,0.1)_inset,0_2px_4px_color-mix(in_oklab,var(--border),transparent_70%)]"
1206
+ )
1207
+ },
1208
+ {
1209
+ chrome: "soft",
1210
+ variant: "outline",
1211
+ className: cn(
1212
+ "border-[color:color-mix(in_oklab,var(--border),transparent_45%)]",
1213
+ "shadow-[0_0_2px_1px_rgba(255,255,255,0.1)_inset,0_2px_4px_color-mix(in_oklab,var(--border),transparent_70%)]"
1214
+ )
1215
+ },
1216
+ {
1217
+ chrome: "soft",
1218
+ variant: "ghost",
1219
+ className: "shadow-[0_2px_4px_color-mix(in_oklab,var(--border),transparent_75%)]"
1220
+ },
1221
+ {
1222
+ chrome: "soft",
1223
+ variant: "success",
1224
+ className: cn(
1225
+ "bg-[color:color-mix(in_oklab,var(--success),transparent_70%)]",
1226
+ "border-[color:color-mix(in_oklab,var(--success),transparent_75%)]",
1227
+ "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--success),transparent_70%)]"
1228
+ )
1229
+ },
1230
+ {
1231
+ chrome: "soft",
1232
+ variant: "info",
1233
+ className: cn(
1234
+ "bg-[color:color-mix(in_oklab,var(--info),transparent_70%)]",
1235
+ "border-[color:color-mix(in_oklab,var(--info),transparent_75%)]",
1236
+ "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--info),transparent_70%)]"
1237
+ )
1238
+ },
1239
+ {
1240
+ chrome: "soft",
1241
+ variant: "warning",
1242
+ className: cn(
1243
+ "bg-[color:color-mix(in_oklab,var(--warning),transparent_70%)]",
1244
+ "border-[color:color-mix(in_oklab,var(--warning),transparent_75%)]",
1245
+ "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--warning),transparent_70%)]"
1246
+ )
1247
+ },
1248
+ {
1249
+ chrome: "soft",
1250
+ variant: "danger",
1251
+ className: cn(
1252
+ "bg-[color:color-mix(in_oklab,var(--danger),transparent_70%)]",
1253
+ "border-[color:color-mix(in_oklab,var(--danger),transparent_75%)]",
1254
+ "shadow-[0_0_2px_1px_rgba(255,255,255,0.2)_inset,0_2px_4px_color-mix(in_oklab,var(--danger),transparent_70%)]"
1255
+ )
1256
+ },
1257
+ {
1258
+ chrome: "soft",
1259
+ variant: "link",
1260
+ className: cn(
1261
+ "text-[color:var(--link)]",
1262
+ "shadow-[0_2px_4px_color-mix(in_oklab,var(--link),transparent_75%)]"
1263
+ )
1264
+ },
1265
+ {
1266
+ chrome: "glass",
1267
+ variant: "primary",
1268
+ className: cn("bg-[color:color-mix(in_oklab,var(--brand),transparent_65%)]", "border-[color:var(--brand)]")
1269
+ },
1270
+ {
1271
+ chrome: "glass",
1272
+ variant: "accent",
1273
+ className: cn(
1274
+ "bg-[color:color-mix(in_oklab,var(--accent),transparent_65%)]",
1275
+ "border-[color:var(--accent)]"
1276
+ )
1277
+ },
1278
+ {
1279
+ chrome: "glass",
1280
+ variant: "secondary",
1281
+ className: cn(
1282
+ "bg-[color:color-mix(in_oklab,var(--surface-2),transparent_35%)]",
1283
+ "border-[color:color-mix(in_oklab,var(--border),transparent_70%)]"
1284
+ )
1285
+ },
1143
1286
  { chrome: "glass", variant: "outline", className: "" },
1144
1287
  { chrome: "glass", variant: "ghost", className: "" },
1145
- { chrome: "glass", variant: "success", className: cn("bg-[color:color-mix(in_oklab,var(--success),transparent_65%)]", "border-[color:var(--success)]") },
1146
- { chrome: "glass", variant: "info", className: cn("bg-[color:color-mix(in_oklab,var(--info),transparent_65%)]", "border-[color:var(--info)]") },
1147
- { chrome: "glass", variant: "warning", className: cn("bg-[color:color-mix(in_oklab,var(--warning),transparent_65%)]", "border-[color:var(--warning)]") },
1148
- { chrome: "glass", variant: "danger", className: cn("bg-[color:color-mix(in_oklab,var(--danger),transparent_65%)]", "border-[color:var(--danger)]") },
1288
+ {
1289
+ chrome: "glass",
1290
+ variant: "success",
1291
+ className: cn(
1292
+ "bg-[color:color-mix(in_oklab,var(--success),transparent_65%)]",
1293
+ "border-[color:var(--success)]"
1294
+ )
1295
+ },
1296
+ {
1297
+ chrome: "glass",
1298
+ variant: "info",
1299
+ className: cn("bg-[color:color-mix(in_oklab,var(--info),transparent_65%)]", "border-[color:var(--info)]")
1300
+ },
1301
+ {
1302
+ chrome: "glass",
1303
+ variant: "warning",
1304
+ className: cn(
1305
+ "bg-[color:color-mix(in_oklab,var(--warning),transparent_65%)]",
1306
+ "border-[color:var(--warning)]"
1307
+ )
1308
+ },
1309
+ {
1310
+ chrome: "glass",
1311
+ variant: "danger",
1312
+ className: cn(
1313
+ "bg-[color:color-mix(in_oklab,var(--danger),transparent_65%)]",
1314
+ "border-[color:var(--danger)]"
1315
+ )
1316
+ },
1149
1317
  { chrome: "glass", variant: "link", className: "text-[color:var(--link)]" },
1150
- { chrome: "glow", variant: "primary", className: cn("border-[color: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%)]") },
1151
- { chrome: "glow", variant: "accent", className: cn("border-[color:var(--accent)]", "shadow-[0_0_0_1px_color-mix(in_oklab,var(--accent),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--accent),transparent_55%)]", "hover:shadow-[0_0_0_1px_color-mix(in_oklab,var(--accent),transparent_10%),0_14px_34px_color-mix(in_oklab,var(--accent),transparent_40%)]", "dark:shadow-[0_0_0_1px_color-mix(in_oklab,var(--accent),transparent_30%),0_8px_22px_color-mix(in_oklab,var(--accent),transparent_70%)]", "dark:hover:shadow-[0_0_0_1px_color-mix(in_oklab,var(--accent),transparent_15%),0_12px_30px_color-mix(in_oklab,var(--accent),transparent_55%)]") },
1152
- { 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%)]") },
1153
- { 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%)]") },
1318
+ {
1319
+ chrome: "glow",
1320
+ variant: "primary",
1321
+ className: cn(
1322
+ "border-[color:var(--brand)]",
1323
+ "shadow-[0_0_0_1px_color-mix(in_oklab,var(--brand),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--brand),transparent_55%)]",
1324
+ "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%)]",
1325
+ "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%)]",
1326
+ "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%)]"
1327
+ )
1328
+ },
1329
+ {
1330
+ chrome: "glow",
1331
+ variant: "accent",
1332
+ className: cn(
1333
+ "border-[color:var(--accent)]",
1334
+ "shadow-[0_0_0_1px_color-mix(in_oklab,var(--accent),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--accent),transparent_55%)]",
1335
+ "hover:shadow-[0_0_0_1px_color-mix(in_oklab,var(--accent),transparent_10%),0_14px_34px_color-mix(in_oklab,var(--accent),transparent_40%)]",
1336
+ "dark:shadow-[0_0_0_1px_color-mix(in_oklab,var(--accent),transparent_30%),0_8px_22px_color-mix(in_oklab,var(--accent),transparent_70%)]",
1337
+ "dark:hover:shadow-[0_0_0_1px_color-mix(in_oklab,var(--accent),transparent_15%),0_12px_30px_color-mix(in_oklab,var(--accent),transparent_55%)]"
1338
+ )
1339
+ },
1340
+ {
1341
+ chrome: "glow",
1342
+ variant: "secondary",
1343
+ className: cn(
1344
+ "border-[color:color-mix(in_oklab,var(--border),transparent_20%)]",
1345
+ "shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--border),transparent_60%)]",
1346
+ "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%)]",
1347
+ "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%)]",
1348
+ "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%)]"
1349
+ )
1350
+ },
1351
+ {
1352
+ chrome: "glow",
1353
+ variant: "outline",
1354
+ className: cn(
1355
+ "border-[color:color-mix(in_oklab,var(--border),transparent_20%)]",
1356
+ "shadow-[0_0_0_1px_color-mix(in_oklab,var(--border),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--border),transparent_60%)]",
1357
+ "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%)]",
1358
+ "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%)]",
1359
+ "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%)]"
1360
+ )
1361
+ },
1154
1362
  { chrome: "glow", variant: "ghost", className: "shadow-none border-transparent" },
1155
- { chrome: "glow", variant: "success", className: cn("border-[color: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%)]") },
1156
- { chrome: "glow", variant: "info", className: cn("border-[color: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%)]") },
1157
- { chrome: "glow", variant: "warning", className: cn("border-[color: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%)]") },
1158
- { chrome: "glow", variant: "danger", className: cn("border-[color: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%)]") },
1363
+ {
1364
+ chrome: "glow",
1365
+ variant: "success",
1366
+ className: cn(
1367
+ "border-[color:var(--success)]",
1368
+ "shadow-[0_0_0_1px_color-mix(in_oklab,var(--success),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--success),transparent_55%)]",
1369
+ "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%)]",
1370
+ "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%)]",
1371
+ "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%)]"
1372
+ )
1373
+ },
1374
+ {
1375
+ chrome: "glow",
1376
+ variant: "info",
1377
+ className: cn(
1378
+ "border-[color:var(--info)]",
1379
+ "shadow-[0_0_0_1px_color-mix(in_oklab,var(--info),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--info),transparent_55%)]",
1380
+ "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%)]",
1381
+ "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%)]",
1382
+ "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%)]"
1383
+ )
1384
+ },
1385
+ {
1386
+ chrome: "glow",
1387
+ variant: "warning",
1388
+ className: cn(
1389
+ "border-[color:var(--warning)]",
1390
+ "shadow-[0_0_0_1px_color-mix(in_oklab,var(--warning),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--warning),transparent_55%)]",
1391
+ "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%)]",
1392
+ "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%)]",
1393
+ "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%)]"
1394
+ )
1395
+ },
1396
+ {
1397
+ chrome: "glow",
1398
+ variant: "danger",
1399
+ className: cn(
1400
+ "border-[color:var(--danger)]",
1401
+ "shadow-[0_0_0_1px_color-mix(in_oklab,var(--danger),transparent_20%),0_10px_26px_color-mix(in_oklab,var(--danger),transparent_55%)]",
1402
+ "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%)]",
1403
+ "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%)]",
1404
+ "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%)]"
1405
+ )
1406
+ },
1159
1407
  { chrome: "glow", variant: "link", className: "text-[color:var(--link)] shadow-none border-transparent" },
1160
- { chrome: "hairline", variant: "primary", className: "border-[color:color-mix(in_oklab,var(--brand-contrast),transparent_20%)] text-[color:var(--brand-contrast)]" },
1161
- { chrome: "hairline", variant: "accent", className: "border-[color:color-mix(in_oklab,var(--accent-contrast),transparent_20%)] text-[color:var(--accent-contrast)]" },
1162
- { chrome: "hairline", variant: "secondary", className: "border-[color:color-mix(in_oklab,var(--border),transparent_20%)] text-[color:var(--text-1)]" },
1163
- { chrome: "hairline", variant: "outline", className: "border-[color:color-mix(in_oklab,var(--border),transparent_20%)] text-[color:var(--text-1)]" },
1408
+ {
1409
+ chrome: "hairline",
1410
+ variant: "primary",
1411
+ className: "border-[color:color-mix(in_oklab,var(--brand-contrast),transparent_20%)] text-[color:var(--brand-contrast)]"
1412
+ },
1413
+ {
1414
+ chrome: "hairline",
1415
+ variant: "accent",
1416
+ className: "border-[color:color-mix(in_oklab,var(--accent-contrast),transparent_20%)] text-[color:var(--accent-contrast)]"
1417
+ },
1418
+ {
1419
+ chrome: "hairline",
1420
+ variant: "secondary",
1421
+ className: "border-[color:color-mix(in_oklab,var(--border),transparent_20%)] text-[color:var(--text-1)]"
1422
+ },
1423
+ {
1424
+ chrome: "hairline",
1425
+ variant: "outline",
1426
+ className: "border-[color:color-mix(in_oklab,var(--border),transparent_20%)] text-[color:var(--text-1)]"
1427
+ },
1164
1428
  { chrome: "hairline", variant: "ghost", className: "border-transparent text-[color:var(--text-1)]" },
1165
- { chrome: "hairline", variant: "success", className: "border-[color:color-mix(in_oklab,var(--success),transparent_20%)] text-[color:var(--success-contrast)]" },
1166
- { chrome: "hairline", variant: "info", className: "border-[color:color-mix(in_oklab,var(--info),transparent_20%)] text-[color:var(--info-contrast)]" },
1167
- { chrome: "hairline", variant: "warning", className: "border-[color:color-mix(in_oklab,var(--warning),transparent_20%)] text-[color:var(--warning-contrast)]" },
1168
- { chrome: "hairline", variant: "danger", className: "border-[color:color-mix(in_oklab,var(--danger),transparent_20%)] text-[color:var(--danger-contrast)]" },
1429
+ {
1430
+ chrome: "hairline",
1431
+ variant: "success",
1432
+ className: "border-[color:color-mix(in_oklab,var(--success),transparent_20%)] text-[color:var(--success-contrast)]"
1433
+ },
1434
+ {
1435
+ chrome: "hairline",
1436
+ variant: "info",
1437
+ className: "border-[color:color-mix(in_oklab,var(--info),transparent_20%)] text-[color:var(--info-contrast)]"
1438
+ },
1439
+ {
1440
+ chrome: "hairline",
1441
+ variant: "warning",
1442
+ className: "border-[color:color-mix(in_oklab,var(--warning),transparent_20%)] text-[color:var(--warning-contrast)]"
1443
+ },
1444
+ {
1445
+ chrome: "hairline",
1446
+ variant: "danger",
1447
+ className: "border-[color:color-mix(in_oklab,var(--danger),transparent_20%)] text-[color:var(--danger-contrast)]"
1448
+ },
1169
1449
  { chrome: "hairline", variant: "link", className: "text-[color:var(--link)] border-transparent" }
1170
1450
  ],
1171
1451
  defaultVariants: { variant: "primary", size: "md", chrome: "flat", fullWidth: false }
1172
1452
  });
1173
1453
  var iconSlotBase = cn("inline-flex items-center justify-center", "shrink-0");
1174
1454
  var iconSlotReserve = "min-w-4 min-h-4";
1175
- var Button = React3.forwardRef(
1455
+ var Button = React.forwardRef(
1176
1456
  ({
1177
1457
  asChild = false,
1178
1458
  variant,
@@ -1258,21 +1538,20 @@ var Button = React3.forwardRef(
1258
1538
  Button.displayName = "Button";
1259
1539
 
1260
1540
  // src/ui/components/Field.tsx
1261
- import * as React5 from "react";
1541
+ import * as React3 from "react";
1262
1542
 
1263
1543
  // src/ui/components/Label.tsx
1264
- import * as React4 from "react";
1544
+ import * as React2 from "react";
1265
1545
  import { jsx as jsx7 } from "react/jsx-runtime";
1266
- var Label = React4.forwardRef(
1267
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx7(
1546
+ var Label = React2.forwardRef(
1547
+ ({ className, htmlFor, children, ...props }, ref) => /* @__PURE__ */ jsx7(
1268
1548
  "label",
1269
1549
  {
1270
1550
  ref,
1271
- className: cn(
1272
- "inline-flex items-center gap-2 text-sm font-medium text-[color:var(--text-1)]",
1273
- className
1274
- ),
1275
- ...props
1551
+ htmlFor,
1552
+ className: cn("inline-flex items-center gap-2 text-sm font-medium text-(--text-1)", className),
1553
+ ...props,
1554
+ children
1276
1555
  }
1277
1556
  )
1278
1557
  );
@@ -1281,46 +1560,40 @@ Label.displayName = "Label";
1281
1560
  // src/ui/components/Field.tsx
1282
1561
  import { jsx as jsx8, jsxs as jsxs3 } from "react/jsx-runtime";
1283
1562
  function Field({ label, hint, error, required, disabled, id, children, className, ...props }) {
1284
- const reactId = React5.useId();
1563
+ const reactId = React3.useId();
1285
1564
  const controlId = id ?? `field-${reactId}`;
1286
1565
  const hintId = hint ? `${controlId}-hint` : void 0;
1287
1566
  const errorId = error ? `${controlId}-error` : void 0;
1288
1567
  const childInvalid = Boolean(children.props.invalid);
1289
1568
  const invalid = Boolean(error) || childInvalid;
1290
- const describedByParts = [
1291
- children.props["aria-describedby"],
1292
- hintId,
1293
- errorId
1294
- ].filter(Boolean);
1569
+ const describedByParts = [children.props["aria-describedby"], errorId, hintId].filter(Boolean);
1295
1570
  const ariaDescribedBy = describedByParts.length ? describedByParts.join(" ") : void 0;
1296
- const control = React5.cloneElement(children, {
1571
+ const resolvedDisabled = disabled ?? children.props.disabled;
1572
+ const resolvedRequired = required ?? children.props.required;
1573
+ const control = React3.cloneElement(children, {
1297
1574
  id: controlId,
1298
- disabled: disabled ?? children.props.disabled,
1299
- required: required ?? children.props.required,
1575
+ disabled: resolvedDisabled,
1576
+ required: resolvedRequired,
1300
1577
  invalid,
1301
1578
  "aria-describedby": ariaDescribedBy
1302
1579
  });
1303
1580
  return /* @__PURE__ */ jsxs3("div", { className: cn("grid gap-1.5", className), ...props, children: [
1304
1581
  label ? /* @__PURE__ */ jsx8("div", { className: "flex items-center justify-between gap-3", children: /* @__PURE__ */ jsxs3(Label, { htmlFor: controlId, children: [
1305
1582
  label,
1306
- required ? /* @__PURE__ */ jsx8("span", { "aria-hidden": "true", className: "text-(--muted)", children: " * " }) : null
1583
+ resolvedRequired ? /* @__PURE__ */ jsxs3("span", { "aria-hidden": "true", className: "text-(--muted)", children: [
1584
+ " ",
1585
+ "*"
1586
+ ] }) : null
1307
1587
  ] }) }) : null,
1308
1588
  control,
1309
- error ? /* @__PURE__ */ jsx8(
1310
- "p",
1311
- {
1312
- id: errorId,
1313
- className: "text-xs leading-5 text-(--danger-contrast)",
1314
- role: "alert",
1315
- children: error
1316
- }
1317
- ) : hint ? /* @__PURE__ */ jsx8("p", { id: hintId, className: "text-xs leading-5 text-(--muted)", children: hint }) : null
1589
+ error ? /* @__PURE__ */ jsx8("p", { id: errorId, className: "text-xs leading-5 text-(--danger-contrast)", role: "alert", children: error }) : null,
1590
+ hint ? /* @__PURE__ */ jsx8("p", { id: hintId, className: "text-xs leading-5 text-(--muted)", children: hint }) : null
1318
1591
  ] });
1319
1592
  }
1320
1593
 
1321
1594
  // src/ui/components/Input.tsx
1322
- import * as React6 from "react";
1323
1595
  import { cva as cva2 } from "class-variance-authority";
1596
+ import * as React4 from "react";
1324
1597
  import { jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
1325
1598
  var controlShellBase = cn(
1326
1599
  "relative inline-flex items-center gap-2",
@@ -1341,10 +1614,7 @@ var controlShellBase = cn(
1341
1614
  var controlShellVariants = cva2(controlShellBase, {
1342
1615
  variants: {
1343
1616
  variant: {
1344
- surface: cn(
1345
- "bg-[color:var(--surface-2)]",
1346
- "hover:bg-[color:var(--surface-hover)]"
1347
- ),
1617
+ surface: cn("bg-[color:var(--surface-2)]", "hover:bg-[color:var(--surface-hover)]"),
1348
1618
  outline: cn(
1349
1619
  "bg-transparent",
1350
1620
  "hover:bg-[color:color-mix(in_oklab,var(--surface-2),transparent_40%)]",
@@ -1379,7 +1649,7 @@ var slotBase = cn(
1379
1649
  "data-[disabled]:text-[color:var(--disabled-fg)]"
1380
1650
  );
1381
1651
  var slotReserve = "min-w-[var(--input-slot-size)]";
1382
- var Input = React6.forwardRef(
1652
+ var Input = React4.forwardRef(
1383
1653
  ({
1384
1654
  variant,
1385
1655
  size,
@@ -1437,10 +1707,92 @@ var Input = React6.forwardRef(
1437
1707
  );
1438
1708
  Input.displayName = "Input";
1439
1709
 
1440
- // src/ui/components/Textarea.tsx
1441
- import * as React7 from "react";
1710
+ // src/ui/components/Skeleton.tsx
1442
1711
  import { cva as cva3 } from "class-variance-authority";
1712
+ import * as React5 from "react";
1443
1713
  import { jsx as jsx10 } from "react/jsx-runtime";
1714
+ var skeletonBase = cn(
1715
+ "relative isolate inline-flex overflow-hidden",
1716
+ "bg-[color:color-mix(in_oklab,var(--surface-2),var(--border)_25%)]",
1717
+ "text-transparent select-none",
1718
+ "[--skeleton-shimmer:color-mix(in_oklab,var(--surface-1),white_35%)]"
1719
+ );
1720
+ var shimmerEffect = cn(
1721
+ "before:content-[''] before:absolute before:inset-0",
1722
+ "before:bg-[linear-gradient(110deg,transparent_0%,color-mix(in_oklab,var(--skeleton-shimmer),transparent_100%)_25%,color-mix(in_oklab,var(--skeleton-shimmer),transparent_55%)_50%,color-mix(in_oklab,var(--skeleton-shimmer),transparent_100%)_75%,transparent_100%)]",
1723
+ "before:[background-size:200%_100%]",
1724
+ "before:animate-[skeleton-shimmer_1.6s_linear_infinite] motion-reduce:before:animate-none"
1725
+ );
1726
+ var skeletonVariants = cva3(skeletonBase, {
1727
+ variants: {
1728
+ variant: {
1729
+ surface: "",
1730
+ outline: cn("bg-transparent", "border border-[color:color-mix(in_oklab,var(--border),transparent_65%)]")
1731
+ },
1732
+ size: {
1733
+ sm: "h-3",
1734
+ md: "h-4",
1735
+ lg: "h-5"
1736
+ },
1737
+ radius: {
1738
+ none: "rounded-[var(--shape-radius-0)]",
1739
+ sm: "rounded-[var(--shape-radius-10)]",
1740
+ md: "rounded-[var(--radius-input)]",
1741
+ lg: "rounded-[var(--radius-card)]",
1742
+ full: "rounded-full"
1743
+ },
1744
+ fullWidth: { true: "w-full", false: "w-auto" },
1745
+ animation: {
1746
+ none: "",
1747
+ pulse: "animate-pulse motion-reduce:animate-none",
1748
+ shimmer: shimmerEffect
1749
+ },
1750
+ preset: {
1751
+ none: "",
1752
+ avatar: "h-12 w-12 rounded-full",
1753
+ title: "h-6 w-2/3",
1754
+ button: "h-10 w-28 rounded-[var(--radius-btn)]",
1755
+ card: "h-40 w-full rounded-[var(--radius-card)]"
1756
+ }
1757
+ },
1758
+ defaultVariants: {
1759
+ variant: "surface",
1760
+ size: "md",
1761
+ radius: "md",
1762
+ fullWidth: true,
1763
+ animation: "shimmer",
1764
+ preset: "none"
1765
+ }
1766
+ });
1767
+ var Skeleton = React5.forwardRef(
1768
+ ({ variant, size, radius, fullWidth, animation, preset, animate, className, ...props }, ref) => {
1769
+ const resolvedAnimation = animation ?? (animate === false ? "none" : animate ? "pulse" : void 0);
1770
+ return /* @__PURE__ */ jsx10(
1771
+ "div",
1772
+ {
1773
+ ref,
1774
+ className: cn(
1775
+ skeletonVariants({
1776
+ variant,
1777
+ size,
1778
+ radius,
1779
+ fullWidth,
1780
+ animation: resolvedAnimation,
1781
+ preset
1782
+ }),
1783
+ className
1784
+ ),
1785
+ ...props
1786
+ }
1787
+ );
1788
+ }
1789
+ );
1790
+ Skeleton.displayName = "Skeleton";
1791
+
1792
+ // src/ui/components/Textarea.tsx
1793
+ import { cva as cva4 } from "class-variance-authority";
1794
+ import * as React6 from "react";
1795
+ import { jsx as jsx11 } from "react/jsx-runtime";
1444
1796
  var controlShellBase2 = cn(
1445
1797
  "relative inline-flex w-full",
1446
1798
  "rounded-[var(--radius-input)]",
@@ -1457,13 +1809,10 @@ var controlShellBase2 = cn(
1457
1809
  "data-[disabled]:border-[color:var(--disabled-border)]",
1458
1810
  "data-[disabled]:cursor-not-allowed"
1459
1811
  );
1460
- var textareaShellVariants = cva3(controlShellBase2, {
1812
+ var textareaShellVariants = cva4(controlShellBase2, {
1461
1813
  variants: {
1462
1814
  variant: {
1463
- surface: cn(
1464
- "bg-[color:var(--surface-2)]",
1465
- "hover:bg-[color:var(--surface-hover)]"
1466
- ),
1815
+ surface: cn("bg-[color:var(--surface-2)]", "hover:bg-[color:var(--surface-hover)]"),
1467
1816
  outline: cn(
1468
1817
  "bg-transparent",
1469
1818
  "hover:bg-[color:color-mix(in_oklab,var(--surface-2),transparent_40%)]",
@@ -1493,7 +1842,19 @@ var textareaBase = cn(
1493
1842
  "disabled:cursor-not-allowed",
1494
1843
  "read-only:cursor-default"
1495
1844
  );
1496
- var Textarea = React7.forwardRef(
1845
+ function mergeRefs(...refs) {
1846
+ return (node) => {
1847
+ for (const ref of refs) {
1848
+ if (!ref) continue;
1849
+ if (typeof ref === "function") {
1850
+ ref(node);
1851
+ } else {
1852
+ ref.current = node;
1853
+ }
1854
+ }
1855
+ };
1856
+ }
1857
+ var Textarea = React6.forwardRef(
1497
1858
  ({
1498
1859
  variant,
1499
1860
  size,
@@ -1503,34 +1864,49 @@ var Textarea = React7.forwardRef(
1503
1864
  textareaClassName,
1504
1865
  disabled,
1505
1866
  autoResize,
1867
+ maxHeightPx,
1506
1868
  onInput,
1507
1869
  rows = 4,
1870
+ value,
1508
1871
  ...props
1509
1872
  }, ref) => {
1510
1873
  const isDisabled = Boolean(disabled);
1874
+ const innerRef = React6.useRef(null);
1875
+ const resize = React6.useCallback(() => {
1876
+ if (!autoResize) return;
1877
+ const el = innerRef.current;
1878
+ if (!el) return;
1879
+ el.style.height = "auto";
1880
+ const next = el.scrollHeight;
1881
+ el.style.height = maxHeightPx ? `${Math.min(next, maxHeightPx)}px` : `${next}px`;
1882
+ }, [autoResize, maxHeightPx]);
1511
1883
  const handleInput = (e) => {
1512
- if (autoResize) {
1513
- const el = e.currentTarget;
1514
- el.style.height = "auto";
1515
- el.style.height = `${el.scrollHeight}px`;
1516
- }
1884
+ resize();
1517
1885
  onInput?.(e);
1518
1886
  };
1519
- return /* @__PURE__ */ jsx10(
1887
+ React6.useLayoutEffect(() => {
1888
+ resize();
1889
+ }, [resize, value]);
1890
+ return /* @__PURE__ */ jsx11(
1520
1891
  "div",
1521
1892
  {
1522
1893
  className: cn(textareaShellVariants({ variant, size, fullWidth }), className),
1523
1894
  "data-invalid": invalid ? "" : void 0,
1524
1895
  "data-disabled": isDisabled ? "" : void 0,
1525
- children: /* @__PURE__ */ jsx10(
1896
+ children: /* @__PURE__ */ jsx11(
1526
1897
  "textarea",
1527
1898
  {
1528
- ref,
1899
+ ref: mergeRefs(innerRef, ref),
1529
1900
  disabled: isDisabled,
1530
1901
  "aria-invalid": invalid || void 0,
1531
- className: cn(textareaBase, textareaClassName),
1902
+ className: cn(
1903
+ textareaBase,
1904
+ autoResize ? "resize-none overflow-hidden" : "resize-y",
1905
+ textareaClassName
1906
+ ),
1532
1907
  rows,
1533
1908
  onInput: handleInput,
1909
+ value,
1534
1910
  ...props
1535
1911
  }
1536
1912
  )
@@ -1557,6 +1933,7 @@ export {
1557
1933
  NotifierController,
1558
1934
  RedirectIfAuthed,
1559
1935
  RequireAuth,
1936
+ Skeleton,
1560
1937
  Textarea,
1561
1938
  authController,
1562
1939
  controllerFactory,