@getgreenline/blaze-ui 1.0.3 → 1.0.4-5.02-beta

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.
Files changed (258) hide show
  1. package/dist/components/accordion.d.ts +8 -0
  2. package/dist/components/accordion.d.ts.map +1 -0
  3. package/dist/components/accordion.js +19 -0
  4. package/dist/components/alert-dialog.d.ts +18 -0
  5. package/dist/components/alert-dialog.d.ts.map +1 -0
  6. package/dist/components/alert-dialog.js +41 -0
  7. package/dist/components/alert.d.ts +10 -0
  8. package/dist/components/alert.d.ts.map +1 -0
  9. package/dist/components/alert.js +26 -0
  10. package/dist/components/aspect-ratio.d.ts +4 -0
  11. package/dist/components/aspect-ratio.d.ts.map +1 -0
  12. package/dist/components/aspect-ratio.js +8 -0
  13. package/dist/components/avatar.d.ts +7 -0
  14. package/dist/components/avatar.d.ts.map +1 -0
  15. package/dist/components/avatar.js +15 -0
  16. package/dist/components/badge.d.ts +10 -0
  17. package/dist/components/badge.d.ts.map +1 -0
  18. package/dist/components/badge.js +24 -0
  19. package/dist/components/breadcrumb.d.ts +12 -0
  20. package/dist/components/breadcrumb.d.ts.map +1 -0
  21. package/dist/components/breadcrumb.js +29 -0
  22. package/dist/components/button-group.d.ts +12 -0
  23. package/dist/components/button-group.d.ts.map +1 -0
  24. package/dist/components/button-group.js +29 -0
  25. package/dist/components/button.d.ts +16 -0
  26. package/dist/components/button.d.ts.map +1 -0
  27. package/dist/components/button.js +37 -0
  28. package/dist/components/card.d.ts +10 -0
  29. package/dist/components/card.d.ts.map +1 -0
  30. package/dist/components/card.js +26 -0
  31. package/dist/components/carousel.d.ts +20 -0
  32. package/dist/components/carousel.d.ts.map +1 -0
  33. package/dist/components/carousel.js +92 -0
  34. package/dist/components/chart.d.ts +63 -0
  35. package/dist/components/chart.d.ts.map +1 -0
  36. package/dist/components/chart.js +133 -0
  37. package/dist/components/checkbox.d.ts +5 -0
  38. package/dist/components/checkbox.d.ts.map +1 -0
  39. package/dist/components/checkbox.js +10 -0
  40. package/dist/components/collapsible.d.ts +6 -0
  41. package/dist/components/collapsible.d.ts.map +1 -0
  42. package/dist/components/collapsible.js +15 -0
  43. package/dist/components/command.d.ts +19 -0
  44. package/dist/components/command.d.ts.map +1 -0
  45. package/dist/components/command.js +35 -0
  46. package/dist/components/context-menu.d.ts +26 -0
  47. package/dist/components/context-menu.d.ts.map +1 -0
  48. package/dist/components/context-menu.js +52 -0
  49. package/dist/components/data-table.d.ts +85 -0
  50. package/dist/components/data-table.d.ts.map +1 -0
  51. package/dist/components/data-table.js +390 -0
  52. package/dist/components/dialog.d.ts +16 -0
  53. package/dist/components/dialog.d.ts.map +1 -0
  54. package/dist/components/dialog.js +37 -0
  55. package/dist/components/drawer.d.ts +14 -0
  56. package/dist/components/drawer.d.ts.map +1 -0
  57. package/dist/components/drawer.js +36 -0
  58. package/dist/components/dropdown-menu.d.ts +26 -0
  59. package/dist/components/dropdown-menu.d.ts.map +1 -0
  60. package/dist/components/dropdown-menu.js +52 -0
  61. package/dist/components/empty.d.ts +12 -0
  62. package/dist/components/empty.d.ts.map +1 -0
  63. package/dist/components/empty.js +35 -0
  64. package/dist/components/field.d.ts +25 -0
  65. package/dist/components/field.d.ts.map +1 -0
  66. package/dist/components/field.js +74 -0
  67. package/dist/components/form.d.ts +25 -0
  68. package/dist/components/form.d.ts.map +1 -0
  69. package/dist/components/form.js +60 -0
  70. package/dist/components/header-app-switcher.d.ts +53 -0
  71. package/dist/components/header-app-switcher.d.ts.map +1 -0
  72. package/dist/components/header-app-switcher.js +154 -0
  73. package/dist/components/hierarchical-select.d.ts +31 -0
  74. package/dist/components/hierarchical-select.d.ts.map +1 -0
  75. package/dist/components/hierarchical-select.js +143 -0
  76. package/dist/components/hover-card.d.ts +7 -0
  77. package/dist/components/hover-card.d.ts.map +1 -0
  78. package/dist/components/hover-card.js +15 -0
  79. package/dist/components/input-group.d.ts +17 -0
  80. package/dist/components/input-group.d.ts.map +1 -0
  81. package/dist/components/input-group.js +66 -0
  82. package/dist/components/input-otp.d.ts +12 -0
  83. package/dist/components/input-otp.d.ts.map +1 -0
  84. package/dist/components/input-otp.js +22 -0
  85. package/dist/components/input.d.ts +8 -0
  86. package/dist/components/input.d.ts.map +1 -0
  87. package/dist/components/input.js +15 -0
  88. package/dist/components/item.d.ts +24 -0
  89. package/dist/components/item.d.ts.map +1 -0
  90. package/dist/components/item.js +68 -0
  91. package/dist/components/kbd.d.ts +4 -0
  92. package/dist/components/kbd.d.ts.map +1 -0
  93. package/dist/components/kbd.js +11 -0
  94. package/dist/components/label.d.ts +8 -0
  95. package/dist/components/label.d.ts.map +1 -0
  96. package/dist/components/label.js +9 -0
  97. package/dist/components/login-screen.d.ts +4 -0
  98. package/dist/components/login-screen.d.ts.map +1 -0
  99. package/dist/components/login-screen.js +300 -0
  100. package/dist/components/login-screen.types.d.ts +82 -0
  101. package/dist/components/login-screen.types.d.ts.map +1 -0
  102. package/dist/components/login-screen.views.d.ts +114 -0
  103. package/dist/components/login-screen.views.d.ts.map +1 -0
  104. package/dist/components/login-screen.views.js +53 -0
  105. package/dist/components/menubar.d.ts +27 -0
  106. package/dist/components/menubar.d.ts.map +1 -0
  107. package/dist/components/menubar.js +55 -0
  108. package/dist/components/multi-search-select.d.ts +24 -0
  109. package/dist/components/multi-search-select.d.ts.map +1 -0
  110. package/dist/components/multi-search-select.js +125 -0
  111. package/dist/components/multi-select.d.ts +19 -0
  112. package/dist/components/multi-select.d.ts.map +1 -0
  113. package/dist/components/multi-select.js +87 -0
  114. package/dist/components/navigation-menu.d.ts +15 -0
  115. package/dist/components/navigation-menu.d.ts.map +1 -0
  116. package/dist/components/navigation-menu.js +33 -0
  117. package/dist/components/page-header/actions.d.ts +9 -0
  118. package/dist/components/page-header/actions.d.ts.map +1 -0
  119. package/dist/components/page-header/actions.js +21 -0
  120. package/dist/components/page-header/types.d.ts +33 -0
  121. package/dist/components/page-header/types.d.ts.map +1 -0
  122. package/dist/components/page-header/utils.d.ts +4 -0
  123. package/dist/components/page-header/utils.d.ts.map +1 -0
  124. package/dist/components/page-header/utils.js +17 -0
  125. package/dist/components/page-header.d.ts +4 -0
  126. package/dist/components/page-header.d.ts.map +1 -0
  127. package/dist/components/page-header.js +12 -0
  128. package/dist/components/pagination.d.ts +14 -0
  129. package/dist/components/pagination.d.ts.map +1 -0
  130. package/dist/components/pagination.js +31 -0
  131. package/dist/components/popover.d.ts +8 -0
  132. package/dist/components/popover.d.ts.map +1 -0
  133. package/dist/components/popover.js +18 -0
  134. package/dist/components/progress.d.ts +5 -0
  135. package/dist/components/progress.d.ts.map +1 -0
  136. package/dist/components/progress.js +9 -0
  137. package/dist/components/radio-group.d.ts +6 -0
  138. package/dist/components/radio-group.d.ts.map +1 -0
  139. package/dist/components/radio-group.js +13 -0
  140. package/dist/components/resizable.d.ts +9 -0
  141. package/dist/components/resizable.d.ts.map +1 -0
  142. package/dist/components/resizable.js +16 -0
  143. package/dist/components/scroll-area.d.ts +6 -0
  144. package/dist/components/scroll-area.d.ts.map +1 -0
  145. package/dist/components/scroll-area.js +14 -0
  146. package/dist/components/search-bar.d.ts +15 -0
  147. package/dist/components/search-bar.d.ts.map +1 -0
  148. package/dist/components/search-bar.js +25 -0
  149. package/dist/components/segmented-control.d.ts +24 -0
  150. package/dist/components/segmented-control.d.ts.map +1 -0
  151. package/dist/components/segmented-control.js +88 -0
  152. package/dist/components/select.d.ts +16 -0
  153. package/dist/components/select.d.ts.map +1 -0
  154. package/dist/components/select.js +39 -0
  155. package/dist/components/selection-panel.d.ts +29 -0
  156. package/dist/components/selection-panel.d.ts.map +1 -0
  157. package/dist/components/selection-panel.js +255 -0
  158. package/dist/components/separator.d.ts +5 -0
  159. package/dist/components/separator.d.ts.map +1 -0
  160. package/dist/components/separator.js +11 -0
  161. package/dist/components/sheet.d.ts +17 -0
  162. package/dist/components/sheet.d.ts.map +1 -0
  163. package/dist/components/sheet.js +42 -0
  164. package/dist/components/sidebar.d.ts +70 -0
  165. package/dist/components/sidebar.d.ts.map +1 -0
  166. package/dist/components/sidebar.js +213 -0
  167. package/dist/components/skeleton.d.ts +3 -0
  168. package/dist/components/skeleton.d.ts.map +1 -0
  169. package/dist/components/skeleton.js +8 -0
  170. package/dist/components/slider.d.ts +5 -0
  171. package/dist/components/slider.d.ts.map +1 -0
  172. package/dist/components/slider.js +19 -0
  173. package/dist/components/sonner.d.ts +4 -0
  174. package/dist/components/sonner.d.ts.map +1 -0
  175. package/dist/components/sonner.js +22 -0
  176. package/dist/components/spinner.d.ts +4 -0
  177. package/dist/components/spinner.d.ts.map +1 -0
  178. package/dist/components/spinner.js +9 -0
  179. package/dist/components/switch.d.ts +5 -0
  180. package/dist/components/switch.d.ts.map +1 -0
  181. package/dist/components/switch.js +9 -0
  182. package/dist/components/table.d.ts +11 -0
  183. package/dist/components/table.d.ts.map +1 -0
  184. package/dist/components/table.js +29 -0
  185. package/dist/components/tabs.d.ts +8 -0
  186. package/dist/components/tabs.d.ts.map +1 -0
  187. package/dist/components/tabs.js +18 -0
  188. package/dist/components/textarea.d.ts +8 -0
  189. package/dist/components/textarea.d.ts.map +1 -0
  190. package/dist/components/textarea.js +15 -0
  191. package/dist/components/toggle-group.d.ts +8 -0
  192. package/dist/components/toggle-group.d.ts.map +1 -0
  193. package/dist/components/toggle-group.js +22 -0
  194. package/dist/components/toggle.d.ts +10 -0
  195. package/dist/components/toggle.d.ts.map +1 -0
  196. package/dist/components/toggle.js +27 -0
  197. package/dist/components/tooltip.d.ts +8 -0
  198. package/dist/components/tooltip.d.ts.map +1 -0
  199. package/dist/components/tooltip.js +18 -0
  200. package/dist/components/visually-hidden.d.ts +16 -0
  201. package/dist/components/visually-hidden.d.ts.map +1 -0
  202. package/dist/components/visually-hidden.js +22 -0
  203. package/dist/globals.css +719 -0
  204. package/dist/hooks/use-invalid-attention.d.ts +20 -0
  205. package/dist/hooks/use-invalid-attention.d.ts.map +1 -0
  206. package/dist/hooks/use-invalid-attention.js +65 -0
  207. package/dist/hooks/use-mobile.d.ts +2 -0
  208. package/dist/hooks/use-mobile.d.ts.map +1 -0
  209. package/dist/hooks/use-mobile.js +18 -0
  210. package/dist/index.d.ts +68 -0
  211. package/dist/index.d.ts.map +1 -0
  212. package/dist/index.js +68 -0
  213. package/dist/lib/portal-wrapper.d.ts +32 -0
  214. package/dist/lib/portal-wrapper.d.ts.map +1 -0
  215. package/dist/lib/portal-wrapper.js +34 -0
  216. package/dist/lib/utils.js +8 -0
  217. package/dist/svgs/blaze-dispatch-logo.d.ts +5 -0
  218. package/dist/svgs/blaze-dispatch-logo.d.ts.map +1 -0
  219. package/dist/svgs/blaze-ecom-logo.d.ts +7 -0
  220. package/dist/svgs/blaze-ecom-logo.d.ts.map +1 -0
  221. package/dist/svgs/blaze-insights-logo.d.ts +5 -0
  222. package/dist/svgs/blaze-insights-logo.d.ts.map +1 -0
  223. package/dist/svgs/blaze-lighthouse-logo.d.ts +6 -0
  224. package/dist/svgs/blaze-lighthouse-logo.d.ts.map +1 -0
  225. package/dist/svgs/blaze-pay-logo.d.ts +5 -0
  226. package/dist/svgs/blaze-pay-logo.d.ts.map +1 -0
  227. package/dist/svgs/blaze-pos-logo.d.ts +5 -0
  228. package/dist/svgs/blaze-pos-logo.d.ts.map +1 -0
  229. package/dist/svgs/blaze-retail-logo.d.ts +7 -0
  230. package/dist/svgs/blaze-retail-logo.d.ts.map +1 -0
  231. package/dist/svgs/blaze-sites-logo.d.ts +5 -0
  232. package/dist/svgs/blaze-sites-logo.d.ts.map +1 -0
  233. package/dist/svgs/header-app-switcher-logos.d.ts +15 -0
  234. package/dist/svgs/header-app-switcher-logos.d.ts.map +1 -0
  235. package/dist/svgs/header-app-switcher-logos.js +22 -0
  236. package/package.json +95 -31
  237. package/README.md +0 -80
  238. package/build/components/button.d.ts +0 -12
  239. package/build/components/button.d.ts.map +0 -1
  240. package/build/components/button.js +0 -106
  241. package/build/components/button.js.map +0 -1
  242. package/build/index.d.ts +0 -4
  243. package/build/index.d.ts.map +0 -1
  244. package/build/index.js +0 -11
  245. package/build/index.js.map +0 -1
  246. package/build/index.mjs +0 -6
  247. package/build/lib/utils.js +0 -9
  248. package/build/lib/utils.js.map +0 -1
  249. package/build/styles/blaze-ui.css +0 -97
  250. package/build/styles/blaze-ui.css.map +0 -1
  251. package/build/styles/styles.d.ts +0 -3
  252. package/build/styles/styles.d.ts.map +0 -1
  253. package/build/styles/styles.js +0 -8
  254. package/build/styles/styles.js.map +0 -1
  255. package/src/styles/blaze-ui.css +0 -157
  256. package/src/styles/styles.ts +0 -5
  257. /package/{build → dist}/lib/utils.d.ts +0 -0
  258. /package/{build → dist}/lib/utils.d.ts.map +0 -0
@@ -0,0 +1,300 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { cn } from '../lib/utils.js';
4
+ import { SignInView, ForgotPasswordView, ForgotPasswordSentView, SsoEmailView, FooterLinks, SplitMediaPane } from './login-screen.views.js';
5
+
6
+ const DEFAULT_FOOTER_LINKS = [
7
+ { label: "Help", href: "#" },
8
+ { label: "Privacy", href: "#" },
9
+ { label: "Terms", href: "#" },
10
+ ];
11
+ const DEFAULT_TESTIMONIAL = {
12
+ quote: '"BLAZE has completely transformed how we manage our dispensary. The platform is intuitive, fast, and our team loves it."',
13
+ authorName: "Sarah Johnson",
14
+ authorTitle: "Operations Director, Green Valley Dispensary",
15
+ };
16
+ const DEFAULT_LEGAL_NOTICE = (jsxs(Fragment, { children: ["By continuing, you agree to our", " ", jsx("a", { href: "#", className: "tw:underline tw:hover:text-foreground", children: "Terms of Service" }), " ", "and", " ", jsx("a", { href: "#", className: "tw:underline tw:hover:text-foreground", children: "Privacy Policy" })] }));
17
+ function clampPercent(value) {
18
+ if (Number.isNaN(value)) {
19
+ return 40;
20
+ }
21
+ return Math.min(100, Math.max(0, value));
22
+ }
23
+ function clampOpacity(value) {
24
+ if (Number.isNaN(value)) {
25
+ return 0.35;
26
+ }
27
+ return Math.min(1, Math.max(0, value));
28
+ }
29
+ function getIdentifierInputType(mode) {
30
+ if (mode === "phone") {
31
+ return "tel";
32
+ }
33
+ if (mode === "email-or-phone") {
34
+ return "text";
35
+ }
36
+ return "email";
37
+ }
38
+ function getIdentifierDefaults(mode) {
39
+ if (mode === "phone") {
40
+ return {
41
+ label: "Phone number",
42
+ placeholder: "Enter your phone number",
43
+ };
44
+ }
45
+ if (mode === "email-or-phone") {
46
+ return {
47
+ label: "Email or phone",
48
+ placeholder: "Enter your email or phone number",
49
+ };
50
+ }
51
+ return {
52
+ label: "Email",
53
+ placeholder: "Enter your email address",
54
+ };
55
+ }
56
+ function LoginScreen({ className, splitLayout = true, splitImageWidthPercent = 40, imageSrc = "/login-bg.jpg", imageAlt = "Login background", imageOverlayContent, testimonial = DEFAULT_TESTIMONIAL, imageOverlayOpacity = 0.35, logo, title = "Welcome to Blaze", description = "Sign in with your email and password", tabs = [], defaultTabId, tabId, onTabChange, identifierMode = "email", identifierLabel, identifierPlaceholder, passwordLabel = "Password", passwordPlaceholder = "Enter your password", rememberMeLabel = "Remember Me", forgotPasswordLabel = "Forgot Password?", forgotPasswordTitle = "Reset your password", forgotPasswordDescription = "Enter your email and we will send reset instructions.", forgotPasswordEmailLabel = "Email", forgotPasswordEmailPlaceholder = "Enter your email address", forgotPasswordSubmitLabel = "Send Reset Link", forgotPasswordBackLabel = "Back to sign in", forgotPasswordSentTitle = "Check your email", forgotPasswordSentDescriptionPrefix = "We sent a password reset link to", forgotPasswordSentInstructions = "Click the link in the email to reset your password. If you don't see it, check your spam folder.", forgotPasswordResendLabel = "Resend email", forgotPasswordResendDelaySeconds = 60, submitLabel = "Log In", submitLoadingLabel = "Signing in...", ssoLabel = "Or", ssoButtonLabel = "Continue with Enterprise SSO", ssoEmailTitle = "Enter your email", ssoEmailDescription = "We'll check if you have an existing account or need to create one", ssoEmailLabel = "Email address", ssoEmailPlaceholder = "name@company.com", ssoEmailSubmitLabel = "Continue", ssoEmailHint = "Enterprise users will be redirected to their company's SSO portal", ssoEmailBackAriaLabel = "Go back", legalNotice, footerLinks = DEFAULT_FOOTER_LINKS, isSubmitting = false, isForgotPasswordSubmitting = false, isSsoSubmitting = false, onSubmit, onForgotPasswordSubmit, onSsoClick, onSsoSubmit, }) {
57
+ const id = React.useId();
58
+ const identifierId = `${id}-identifier`;
59
+ const passwordId = `${id}-password`;
60
+ const rememberId = `${id}-remember`;
61
+ const forgotEmailId = `${id}-forgot-email`;
62
+ const ssoEmailId = `${id}-sso-email`;
63
+ const [mode, setMode] = React.useState("sign-in");
64
+ const [identifier, setIdentifier] = React.useState("");
65
+ const [password, setPassword] = React.useState("");
66
+ const [forgotEmail, setForgotEmail] = React.useState("");
67
+ const [ssoEmail, setSsoEmail] = React.useState("");
68
+ const [rememberMe, setRememberMe] = React.useState(false);
69
+ const [showPassword, setShowPassword] = React.useState(false);
70
+ const [isResending, setIsResending] = React.useState(false);
71
+ const [imageLoadError, setImageLoadError] = React.useState(false);
72
+ const [logoLoadError, setLogoLoadError] = React.useState(false);
73
+ const [isSplitViewport, setIsSplitViewport] = React.useState(true);
74
+ const [forgotPasswordError, setForgotPasswordError] = React.useState(null);
75
+ const tabListRef = React.useRef(null);
76
+ const resendDelaySeconds = React.useMemo(() => {
77
+ if (Number.isNaN(forgotPasswordResendDelaySeconds)) {
78
+ return 60;
79
+ }
80
+ return Math.max(0, Math.floor(forgotPasswordResendDelaySeconds));
81
+ }, [forgotPasswordResendDelaySeconds]);
82
+ const [resendCountdown, setResendCountdown] = React.useState(resendDelaySeconds);
83
+ const firstTabId = tabs[0]?.id ?? null;
84
+ const [internalTabId, setInternalTabId] = React.useState(defaultTabId ?? firstTabId);
85
+ React.useEffect(() => {
86
+ if (tabId !== undefined) {
87
+ return;
88
+ }
89
+ if (!internalTabId && firstTabId) {
90
+ setInternalTabId(firstTabId);
91
+ }
92
+ }, [firstTabId, internalTabId, tabId]);
93
+ React.useEffect(() => {
94
+ setImageLoadError(false);
95
+ }, [imageSrc]);
96
+ React.useEffect(() => {
97
+ const handleResize = () => {
98
+ setIsSplitViewport(window.innerWidth >= 768);
99
+ };
100
+ handleResize();
101
+ window.addEventListener("resize", handleResize);
102
+ return () => {
103
+ window.removeEventListener("resize", handleResize);
104
+ };
105
+ }, []);
106
+ const activeTabId = tabId ?? internalTabId ?? firstTabId;
107
+ const shouldShowSplitPane = splitLayout && isSplitViewport;
108
+ const hasSplitImage = Boolean(imageSrc) && !imageLoadError;
109
+ const imageWidth = clampPercent(splitImageWidthPercent);
110
+ const overlayOpacity = clampOpacity(imageOverlayOpacity);
111
+ const resolvedTestimonial = testimonial === null
112
+ ? null
113
+ : {
114
+ quote: testimonial?.quote || DEFAULT_TESTIMONIAL.quote,
115
+ authorName: testimonial?.authorName || DEFAULT_TESTIMONIAL.authorName,
116
+ authorTitle: testimonial?.authorTitle === undefined
117
+ ? DEFAULT_TESTIMONIAL.authorTitle
118
+ : testimonial.authorTitle,
119
+ };
120
+ const identifierDefaults = React.useMemo(() => getIdentifierDefaults(identifierMode), [identifierMode]);
121
+ const resolvedIdentifierLabel = identifierLabel ?? identifierDefaults.label;
122
+ const resolvedIdentifierPlaceholder = identifierPlaceholder ?? identifierDefaults.placeholder;
123
+ const setTabSelection = React.useCallback((tab) => {
124
+ if (tab.disabled) {
125
+ return;
126
+ }
127
+ if (tabId === undefined) {
128
+ setInternalTabId(tab.id);
129
+ }
130
+ onTabChange?.(tab.id);
131
+ }, [onTabChange, tabId]);
132
+ const handleTabClick = React.useCallback((tab, options = {}) => {
133
+ if (tab.disabled) {
134
+ return;
135
+ }
136
+ setTabSelection(tab);
137
+ if (tab.onSelect) {
138
+ tab.onSelect(tab.id);
139
+ return;
140
+ }
141
+ if (options.allowNavigation === false ||
142
+ !tab.href ||
143
+ typeof window === "undefined") {
144
+ return;
145
+ }
146
+ if (tab.external) {
147
+ window.open(tab.href, "_blank", "noopener,noreferrer");
148
+ return;
149
+ }
150
+ window.location.assign(tab.href);
151
+ }, [setTabSelection]);
152
+ const handleTabKeyDown = React.useCallback((event, currentIndex) => {
153
+ const enabledTabIndices = tabs.reduce((acc, tab, index) => {
154
+ if (!tab.disabled) {
155
+ acc.push(index);
156
+ }
157
+ return acc;
158
+ }, []);
159
+ if (enabledTabIndices.length === 0) {
160
+ return;
161
+ }
162
+ const isPrev = event.key === "ArrowLeft" || event.key === "ArrowUp";
163
+ const isNext = event.key === "ArrowRight" || event.key === "ArrowDown";
164
+ const isHome = event.key === "Home";
165
+ const isEnd = event.key === "End";
166
+ if (!isPrev && !isNext && !isHome && !isEnd) {
167
+ return;
168
+ }
169
+ event.preventDefault();
170
+ let nextIndex;
171
+ if (isHome) {
172
+ nextIndex = enabledTabIndices[0] ?? currentIndex;
173
+ }
174
+ else if (isEnd) {
175
+ nextIndex =
176
+ enabledTabIndices[enabledTabIndices.length - 1] ?? currentIndex;
177
+ }
178
+ else {
179
+ const enabledPosition = enabledTabIndices.indexOf(currentIndex);
180
+ const currentEnabledPosition = enabledPosition === -1 ? 0 : enabledPosition;
181
+ const delta = isNext ? 1 : -1;
182
+ const nextEnabledPosition = (currentEnabledPosition + delta + enabledTabIndices.length) %
183
+ enabledTabIndices.length;
184
+ nextIndex = enabledTabIndices[nextEnabledPosition] ?? currentIndex;
185
+ }
186
+ const nextTab = tabs[nextIndex];
187
+ if (!nextTab) {
188
+ return;
189
+ }
190
+ handleTabClick(nextTab, { allowNavigation: false });
191
+ const tabButtons = tabListRef.current?.querySelectorAll('[role="tab"]');
192
+ tabButtons?.[nextIndex]?.focus();
193
+ }, [handleTabClick, tabs]);
194
+ const handleSignInSubmit = async (event) => {
195
+ event.preventDefault();
196
+ const nextIdentifier = identifier.trim();
197
+ const nextPassword = password.trim();
198
+ if (!nextIdentifier || !nextPassword) {
199
+ return;
200
+ }
201
+ await onSubmit?.({
202
+ identifier: nextIdentifier,
203
+ password: nextPassword,
204
+ rememberMe,
205
+ tabId: activeTabId,
206
+ });
207
+ };
208
+ const handleForgotPasswordClick = () => {
209
+ if (identifier.includes("@")) {
210
+ setForgotEmail(identifier.trim());
211
+ }
212
+ setForgotPasswordError(null);
213
+ setMode("forgot-password");
214
+ };
215
+ const handleBackToSignIn = () => {
216
+ setForgotPasswordError(null);
217
+ setMode("sign-in");
218
+ };
219
+ const handleForgotPasswordSubmit = async (event) => {
220
+ event.preventDefault();
221
+ const nextForgotEmail = forgotEmail.trim();
222
+ if (!nextForgotEmail) {
223
+ return;
224
+ }
225
+ setForgotPasswordError(null);
226
+ try {
227
+ await onForgotPasswordSubmit?.(nextForgotEmail);
228
+ }
229
+ catch (error) {
230
+ const message = error instanceof Error && error.message
231
+ ? error.message
232
+ : "Failed to send reset email. Please try again.";
233
+ setForgotPasswordError(message);
234
+ return;
235
+ }
236
+ setResendCountdown(resendDelaySeconds);
237
+ setMode("forgot-password-sent");
238
+ };
239
+ const handleSsoClick = async () => {
240
+ if (onSsoClick) {
241
+ await onSsoClick();
242
+ return;
243
+ }
244
+ if (identifier.includes("@")) {
245
+ setSsoEmail(identifier.trim());
246
+ }
247
+ setMode("sso-email");
248
+ };
249
+ const handleSsoEmailSubmit = async (event) => {
250
+ event.preventDefault();
251
+ const nextSsoEmail = ssoEmail.trim();
252
+ if (!nextSsoEmail) {
253
+ return;
254
+ }
255
+ await onSsoSubmit?.(nextSsoEmail);
256
+ };
257
+ const handleResendEmail = async () => {
258
+ const nextForgotEmail = forgotEmail.trim();
259
+ if (!nextForgotEmail) {
260
+ return;
261
+ }
262
+ setForgotPasswordError(null);
263
+ setIsResending(true);
264
+ try {
265
+ await onForgotPasswordSubmit?.(nextForgotEmail);
266
+ setResendCountdown(resendDelaySeconds);
267
+ }
268
+ catch (error) {
269
+ const message = error instanceof Error && error.message
270
+ ? error.message
271
+ : "Failed to resend reset email. Please try again.";
272
+ setForgotPasswordError(message);
273
+ }
274
+ finally {
275
+ setIsResending(false);
276
+ }
277
+ };
278
+ React.useEffect(() => {
279
+ if (mode !== "forgot-password-sent") {
280
+ return;
281
+ }
282
+ if (resendCountdown <= 0) {
283
+ return;
284
+ }
285
+ const timeoutId = window.setTimeout(() => {
286
+ setResendCountdown((previous) => Math.max(0, previous - 1));
287
+ }, 1000);
288
+ return () => {
289
+ window.clearTimeout(timeoutId);
290
+ };
291
+ }, [mode, resendCountdown]);
292
+ const modeView = mode === "sign-in" ? (jsx(SignInView, { tabs: tabs, activeTabId: activeTabId, tabListRef: tabListRef, onTabClick: (tab) => handleTabClick(tab), onTabKeyDown: handleTabKeyDown, identifierId: identifierId, identifierLabel: resolvedIdentifierLabel, identifierType: getIdentifierInputType(identifierMode), identifierPlaceholder: resolvedIdentifierPlaceholder, identifier: identifier, onIdentifierChange: setIdentifier, passwordId: passwordId, passwordLabel: passwordLabel, passwordPlaceholder: passwordPlaceholder, password: password, onPasswordChange: setPassword, showPassword: showPassword, onTogglePassword: () => setShowPassword((previous) => !previous), rememberId: rememberId, rememberMe: rememberMe, onRememberMeChange: setRememberMe, rememberMeLabel: rememberMeLabel, forgotPasswordLabel: forgotPasswordLabel, onForgotPasswordClick: handleForgotPasswordClick, isSubmitting: isSubmitting, submitLabel: submitLabel, submitLoadingLabel: submitLoadingLabel, onSubmit: handleSignInSubmit, ssoLabel: ssoLabel, ssoButtonLabel: ssoButtonLabel, onSsoClick: handleSsoClick, legalNotice: legalNotice ?? DEFAULT_LEGAL_NOTICE, logo: logo, logoLoadError: logoLoadError, onLogoError: () => setLogoLoadError(true), title: title, description: description, autoCompleteIdentifier: identifierMode === "phone" ? "tel" : "email" })) : mode === "forgot-password" ? (jsx(ForgotPasswordView, { title: forgotPasswordTitle, description: forgotPasswordDescription, emailId: forgotEmailId, emailLabel: forgotPasswordEmailLabel, email: forgotEmail, onEmailChange: setForgotEmail, emailPlaceholder: forgotPasswordEmailPlaceholder, submitLabel: forgotPasswordSubmitLabel, backLabel: forgotPasswordBackLabel, isSubmitting: isForgotPasswordSubmitting, onSubmit: handleForgotPasswordSubmit, onBack: handleBackToSignIn, error: forgotPasswordError })) : mode === "forgot-password-sent" ? (jsx(ForgotPasswordSentView, { backAriaLabel: ssoEmailBackAriaLabel, onBack: handleBackToSignIn, title: forgotPasswordSentTitle, descriptionPrefix: forgotPasswordSentDescriptionPrefix, email: forgotEmail, instructions: forgotPasswordSentInstructions, resendLabel: forgotPasswordResendLabel, resendCountdown: resendCountdown, onResend: handleResendEmail, isResending: isResending, error: forgotPasswordError, backLabel: forgotPasswordBackLabel })) : (jsx(SsoEmailView, { backAriaLabel: ssoEmailBackAriaLabel, onBack: () => setMode("sign-in"), title: ssoEmailTitle, description: ssoEmailDescription, emailId: ssoEmailId, emailLabel: ssoEmailLabel, email: ssoEmail, onEmailChange: setSsoEmail, emailPlaceholder: ssoEmailPlaceholder, submitLabel: ssoEmailSubmitLabel, isSubmitting: isSsoSubmitting, onSubmit: handleSsoEmailSubmit, hint: ssoEmailHint }));
293
+ const content = (jsxs("div", { className: "tw:w-full tw:max-w-md", children: [jsx("div", { className: "tw:rounded-xl tw:border tw:border-border tw:bg-card tw:p-6 tw:shadow-sm sm:tw:p-8", children: jsx("div", { className: "tw:flex tw:flex-col tw:gap-8", children: modeView }) }), jsx(FooterLinks, { links: footerLinks })] }));
294
+ if (!splitLayout) {
295
+ return (jsx("div", { className: cn("tw:min-h-svh tw:w-full tw:bg-background", className), children: jsx("div", { className: "tw:flex tw:min-h-svh tw:w-full tw:items-center tw:justify-center tw:p-6 sm:tw:p-12", children: content }) }));
296
+ }
297
+ return (jsx("div", { className: cn("tw:min-h-svh tw:w-full tw:bg-background", className), children: jsxs("div", { className: "tw:flex tw:min-h-svh tw:w-full", children: [shouldShowSplitPane ? (jsx(SplitMediaPane, { widthPercent: imageWidth, hasSplitImage: hasSplitImage, imageSrc: imageSrc, imageAlt: imageAlt, onImageError: () => setImageLoadError(true), overlayOpacity: overlayOpacity, imageOverlayContent: imageOverlayContent, testimonial: resolvedTestimonial })) : null, jsx("div", { className: cn("tw:flex tw:w-full tw:items-center tw:justify-center tw:p-6 sm:tw:p-12", shouldShowSplitPane && "tw:flex-1"), children: content })] }) }));
298
+ }
299
+
300
+ export { LoginScreen };
@@ -0,0 +1,82 @@
1
+ import type * as React from "react";
2
+ export type LoginScreenIdentifierMode = "email" | "phone" | "email-or-phone";
3
+ export type LoginScreenTab = {
4
+ id: string;
5
+ label: string;
6
+ href?: string;
7
+ external?: boolean;
8
+ onSelect?: (tabId: string) => void;
9
+ disabled?: boolean;
10
+ };
11
+ export type LoginScreenFooterLink = {
12
+ label: string;
13
+ href: string;
14
+ external?: boolean;
15
+ };
16
+ export type LoginScreenSubmitPayload = {
17
+ identifier: string;
18
+ password: string;
19
+ rememberMe: boolean;
20
+ tabId: string | null;
21
+ };
22
+ export type LoginScreenTestimonial = {
23
+ quote: string;
24
+ authorName: string;
25
+ authorTitle?: string;
26
+ };
27
+ export interface LoginScreenProps {
28
+ className?: string;
29
+ splitLayout?: boolean;
30
+ splitImageWidthPercent?: number;
31
+ imageSrc?: string;
32
+ imageAlt?: string;
33
+ imageOverlayContent?: React.ReactNode;
34
+ testimonial?: LoginScreenTestimonial | null;
35
+ imageOverlayOpacity?: number;
36
+ logo?: React.ReactNode;
37
+ title?: string;
38
+ description?: string;
39
+ tabs?: LoginScreenTab[];
40
+ defaultTabId?: string;
41
+ tabId?: string;
42
+ onTabChange?: (tabId: string) => void;
43
+ identifierMode?: LoginScreenIdentifierMode;
44
+ identifierLabel?: string;
45
+ identifierPlaceholder?: string;
46
+ passwordLabel?: string;
47
+ passwordPlaceholder?: string;
48
+ rememberMeLabel?: string;
49
+ forgotPasswordLabel?: string;
50
+ forgotPasswordTitle?: string;
51
+ forgotPasswordDescription?: string;
52
+ forgotPasswordEmailLabel?: string;
53
+ forgotPasswordEmailPlaceholder?: string;
54
+ forgotPasswordSubmitLabel?: string;
55
+ forgotPasswordBackLabel?: string;
56
+ forgotPasswordSentTitle?: string;
57
+ forgotPasswordSentDescriptionPrefix?: string;
58
+ forgotPasswordSentInstructions?: string;
59
+ forgotPasswordResendLabel?: string;
60
+ forgotPasswordResendDelaySeconds?: number;
61
+ submitLabel?: string;
62
+ submitLoadingLabel?: string;
63
+ ssoLabel?: string | null;
64
+ ssoButtonLabel?: string;
65
+ ssoEmailTitle?: string;
66
+ ssoEmailDescription?: string;
67
+ ssoEmailLabel?: string;
68
+ ssoEmailPlaceholder?: string;
69
+ ssoEmailSubmitLabel?: string;
70
+ ssoEmailHint?: string;
71
+ ssoEmailBackAriaLabel?: string;
72
+ legalNotice?: React.ReactNode;
73
+ footerLinks?: LoginScreenFooterLink[];
74
+ isSubmitting?: boolean;
75
+ isForgotPasswordSubmitting?: boolean;
76
+ isSsoSubmitting?: boolean;
77
+ onSubmit?: (payload: LoginScreenSubmitPayload) => void | Promise<void>;
78
+ onForgotPasswordSubmit?: (email: string) => void | Promise<void>;
79
+ onSsoClick?: () => void;
80
+ onSsoSubmit?: (email: string) => void | Promise<void>;
81
+ }
82
+ //# sourceMappingURL=login-screen.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-screen.types.d.ts","sourceRoot":"","sources":["../../src/components/login-screen.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ import * as React from "react";
2
+ import type { LoginScreenFooterLink, LoginScreenTab, LoginScreenTestimonial } from "./login-screen.types";
3
+ interface BrandHeaderProps {
4
+ logo?: React.ReactNode;
5
+ logoLoadError: boolean;
6
+ onLogoError: () => void;
7
+ title: string;
8
+ description?: string;
9
+ }
10
+ interface SignInViewProps {
11
+ tabs: LoginScreenTab[];
12
+ activeTabId: string | null;
13
+ tabListRef: React.RefObject<HTMLDivElement | null>;
14
+ onTabClick: (tab: LoginScreenTab) => void;
15
+ onTabKeyDown: (event: React.KeyboardEvent<HTMLButtonElement>, currentIndex: number) => void;
16
+ identifierId: string;
17
+ identifierLabel: string;
18
+ identifierType: React.HTMLInputTypeAttribute;
19
+ identifierPlaceholder: string;
20
+ identifier: string;
21
+ onIdentifierChange: (value: string) => void;
22
+ passwordId: string;
23
+ passwordLabel: string;
24
+ passwordPlaceholder: string;
25
+ password: string;
26
+ onPasswordChange: (value: string) => void;
27
+ showPassword: boolean;
28
+ onTogglePassword: () => void;
29
+ rememberId: string;
30
+ rememberMe: boolean;
31
+ onRememberMeChange: (checked: boolean) => void;
32
+ rememberMeLabel: string;
33
+ forgotPasswordLabel: string;
34
+ onForgotPasswordClick: () => void;
35
+ isSubmitting: boolean;
36
+ submitLabel: string;
37
+ submitLoadingLabel: string;
38
+ onSubmit: (event: React.FormEvent<HTMLFormElement>) => void | Promise<void>;
39
+ ssoLabel: string | null;
40
+ ssoButtonLabel: string;
41
+ onSsoClick: () => void | Promise<void>;
42
+ legalNotice: React.ReactNode;
43
+ logo?: React.ReactNode;
44
+ logoLoadError: boolean;
45
+ onLogoError: () => void;
46
+ title: string;
47
+ description?: string;
48
+ autoCompleteIdentifier?: string;
49
+ }
50
+ interface ForgotPasswordViewProps {
51
+ title: string;
52
+ description: string;
53
+ emailId: string;
54
+ emailLabel: string;
55
+ email: string;
56
+ onEmailChange: (value: string) => void;
57
+ emailPlaceholder: string;
58
+ submitLabel: string;
59
+ backLabel: string;
60
+ isSubmitting: boolean;
61
+ onSubmit: (event: React.FormEvent<HTMLFormElement>) => void | Promise<void>;
62
+ onBack: () => void;
63
+ error: string | null;
64
+ }
65
+ interface ForgotPasswordSentViewProps {
66
+ backAriaLabel: string;
67
+ onBack: () => void;
68
+ title: string;
69
+ descriptionPrefix: string;
70
+ email: string;
71
+ instructions: string;
72
+ resendLabel: string;
73
+ resendCountdown: number;
74
+ onResend: () => void | Promise<void>;
75
+ isResending: boolean;
76
+ error: string | null;
77
+ backLabel: string;
78
+ }
79
+ interface SsoEmailViewProps {
80
+ backAriaLabel: string;
81
+ onBack: () => void;
82
+ title: string;
83
+ description: string;
84
+ emailId: string;
85
+ emailLabel: string;
86
+ email: string;
87
+ onEmailChange: (value: string) => void;
88
+ emailPlaceholder: string;
89
+ submitLabel: string;
90
+ isSubmitting: boolean;
91
+ onSubmit: (event: React.FormEvent<HTMLFormElement>) => void | Promise<void>;
92
+ hint: string;
93
+ }
94
+ interface SplitMediaPaneProps {
95
+ widthPercent: number;
96
+ hasSplitImage: boolean;
97
+ imageSrc?: string;
98
+ imageAlt: string;
99
+ onImageError: () => void;
100
+ overlayOpacity: number;
101
+ imageOverlayContent?: React.ReactNode;
102
+ testimonial: LoginScreenTestimonial | null;
103
+ }
104
+ export declare function BrandHeader({ logo, logoLoadError, onLogoError, title, description, }: BrandHeaderProps): import("react/jsx-runtime").JSX.Element;
105
+ export declare function SignInView({ tabs, activeTabId, tabListRef, onTabClick, onTabKeyDown, identifierId, identifierLabel, identifierType, identifierPlaceholder, identifier, onIdentifierChange, passwordId, passwordLabel, passwordPlaceholder, password, onPasswordChange, showPassword, onTogglePassword, rememberId, rememberMe, onRememberMeChange, rememberMeLabel, forgotPasswordLabel, onForgotPasswordClick, isSubmitting, submitLabel, submitLoadingLabel, onSubmit, ssoLabel, ssoButtonLabel, onSsoClick, legalNotice, logo, logoLoadError, onLogoError, title, description, autoCompleteIdentifier, }: SignInViewProps): import("react/jsx-runtime").JSX.Element;
106
+ export declare function ForgotPasswordView({ title, description, emailId, emailLabel, email, onEmailChange, emailPlaceholder, submitLabel, backLabel, isSubmitting, onSubmit, onBack, error, }: ForgotPasswordViewProps): import("react/jsx-runtime").JSX.Element;
107
+ export declare function ForgotPasswordSentView({ backAriaLabel, onBack, title, descriptionPrefix, email, instructions, resendLabel, resendCountdown, onResend, isResending, error, backLabel, }: ForgotPasswordSentViewProps): import("react/jsx-runtime").JSX.Element;
108
+ export declare function SsoEmailView({ backAriaLabel, onBack, title, description, emailId, emailLabel, email, onEmailChange, emailPlaceholder, submitLabel, isSubmitting, onSubmit, hint, }: SsoEmailViewProps): import("react/jsx-runtime").JSX.Element;
109
+ export declare function SplitMediaPane({ widthPercent, hasSplitImage, imageSrc, imageAlt, onImageError, overlayOpacity, imageOverlayContent, testimonial, }: SplitMediaPaneProps): import("react/jsx-runtime").JSX.Element;
110
+ export declare function FooterLinks({ links }: {
111
+ links: LoginScreenFooterLink[];
112
+ }): import("react/jsx-runtime").JSX.Element | null;
113
+ export {};
114
+ //# sourceMappingURL=login-screen.views.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-screen.views.d.ts","sourceRoot":"","sources":["../../src/components/login-screen.views.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { EyeOff, Eye, Building2, ArrowLeft, LockKeyhole } from 'lucide-react';
4
+ import { cn } from '../lib/utils.js';
5
+ import { Button } from './button.js';
6
+ import { Checkbox } from './checkbox.js';
7
+ import { Input } from './input.js';
8
+ import { Label } from './label.js';
9
+
10
+ function getLinkAttributes(external) {
11
+ if (!external) {
12
+ return {};
13
+ }
14
+ return {
15
+ target: "_blank",
16
+ rel: "noopener noreferrer",
17
+ };
18
+ }
19
+ function BrandHeader({ logo, logoLoadError, onLogoError, title, description, }) {
20
+ return (jsxs("div", { className: "tw:flex tw:flex-col tw:items-center tw:gap-4 tw:text-center", children: [logo ??
21
+ (logoLoadError ? (jsx("div", { className: "tw:flex tw:size-16 tw:items-center tw:justify-center tw:rounded-xl tw:bg-sky-100 tw:text-xl tw:font-semibold tw:text-primary", children: "B" })) : (jsx("img", { src: "/blaze-logo.png", alt: "Blaze", className: "tw:h-16 tw:w-16", onError: onLogoError }))), jsxs("div", { className: "tw:space-y-2", children: [jsx("h1", { className: "tw:text-3xl tw:font-semibold tw:tracking-tight", children: title }), description ? (jsx("p", { className: "tw:text-sm tw:text-muted-foreground", children: description })) : null] })] }));
22
+ }
23
+ function SignInView({ tabs, activeTabId, tabListRef, onTabClick, onTabKeyDown, identifierId, identifierLabel, identifierType, identifierPlaceholder, identifier, onIdentifierChange, passwordId, passwordLabel, passwordPlaceholder, password, onPasswordChange, showPassword, onTogglePassword, rememberId, rememberMe, onRememberMeChange, rememberMeLabel, forgotPasswordLabel, onForgotPasswordClick, isSubmitting, submitLabel, submitLoadingLabel, onSubmit, ssoLabel, ssoButtonLabel, onSsoClick, legalNotice, logo, logoLoadError, onLogoError, title, description, autoCompleteIdentifier, }) {
24
+ return (jsxs(Fragment, { children: [jsx(BrandHeader, { logo: logo, logoLoadError: logoLoadError, onLogoError: onLogoError, title: title, description: description }), tabs.length > 0 ? (jsx("div", { role: "tablist", ref: tabListRef, "aria-label": "Login destinations", className: "tw:inline-flex tw:w-full tw:items-center tw:rounded-lg tw:bg-muted tw:p-1", children: tabs.map((tab, index) => {
25
+ const isActive = tab.id === activeTabId;
26
+ return (jsx("button", { type: "button", role: "tab", "aria-selected": isActive, "aria-disabled": tab.disabled, tabIndex: isActive ? 0 : -1, disabled: tab.disabled, onClick: () => onTabClick(tab), onKeyDown: (event) => onTabKeyDown(event, index), className: cn("tw:flex-1 tw:rounded-md tw:px-3 tw:py-2 tw:text-sm tw:font-medium tw:transition-colors", "tw:outline-none tw:focus-visible:ring-2 tw:focus-visible:ring-ring tw:focus-visible:ring-offset-2", isActive
27
+ ? "tw:bg-background tw:text-foreground tw:shadow-sm"
28
+ : "tw:text-muted-foreground hover:tw:text-foreground", tab.disabled && "tw:cursor-not-allowed tw:opacity-50"), children: tab.label }, tab.id));
29
+ }) })) : null, jsxs("form", { onSubmit: onSubmit, className: "tw:flex tw:flex-col tw:gap-5", children: [jsxs("div", { className: "tw:flex tw:flex-col tw:gap-2", children: [jsx(Label, { htmlFor: identifierId, children: identifierLabel }), jsx(Input, { id: identifierId, type: identifierType, placeholder: identifierPlaceholder, value: identifier, onChange: (event) => onIdentifierChange(event.target.value), autoComplete: autoCompleteIdentifier, className: "tw:h-12", disabled: isSubmitting, required: true })] }), jsxs("div", { className: "tw:flex tw:flex-col tw:gap-2", children: [jsx(Label, { htmlFor: passwordId, children: passwordLabel }), jsxs("div", { className: "tw:relative", children: [jsx(Input, { id: passwordId, type: showPassword ? "text" : "password", placeholder: passwordPlaceholder, value: password, onChange: (event) => onPasswordChange(event.target.value), autoComplete: "current-password", className: "tw:h-12 tw:pr-10", disabled: isSubmitting, required: true }), jsx("button", { type: "button", className: "tw:absolute tw:right-3 tw:top-1/2 tw:-translate-y-1/2 tw:text-muted-foreground hover:tw:text-foreground", onClick: onTogglePassword, "aria-label": showPassword ? "Hide password" : "Show password", children: showPassword ? (jsx(EyeOff, { className: "tw:size-4" })) : (jsx(Eye, { className: "tw:size-4" })) })] })] }), jsxs("div", { className: "tw:flex tw:items-center tw:justify-between", children: [jsxs("div", { className: "tw:flex tw:items-center tw:gap-2", children: [jsx(Checkbox, { id: rememberId, checked: rememberMe, onCheckedChange: (checked) => onRememberMeChange(checked === true), disabled: isSubmitting }), jsx(Label, { htmlFor: rememberId, className: "tw:cursor-pointer tw:text-sm tw:font-normal", children: rememberMeLabel })] }), jsx("button", { type: "button", className: "tw:text-sm tw:text-primary hover:tw:underline", onClick: onForgotPasswordClick, disabled: isSubmitting, children: forgotPasswordLabel })] }), jsx(Button, { type: "submit", className: "tw:h-12 tw:w-full", loading: isSubmitting, loadingText: submitLoadingLabel, disabled: !identifier.trim() || !password.trim(), children: submitLabel })] }), ssoLabel !== null ? (jsxs(Fragment, { children: [jsxs("div", { className: "tw:relative", children: [jsx("div", { className: "tw:absolute tw:inset-0 tw:flex tw:items-center", children: jsx("span", { className: "tw:w-full tw:border-t tw:border-border" }) }), jsx("div", { className: "tw:relative tw:flex tw:justify-center tw:text-xs tw:uppercase", children: jsx("span", { className: "tw:bg-card tw:px-2 tw:text-muted-foreground", children: ssoLabel }) })] }), jsxs(Button, { type: "button", variant: "outline", className: "tw:h-12 tw:w-full", onClick: onSsoClick, disabled: isSubmitting, children: [jsx(Building2, { className: "tw:size-4" }), ssoButtonLabel] })] })) : null, jsx("p", { className: "tw:text-center tw:text-xs tw:text-muted-foreground", children: legalNotice })] }));
30
+ }
31
+ function ForgotPasswordView({ title, description, emailId, emailLabel, email, onEmailChange, emailPlaceholder, submitLabel, backLabel, isSubmitting, onSubmit, onBack, error, }) {
32
+ return (jsxs("form", { onSubmit: onSubmit, className: "tw:flex tw:flex-col tw:gap-5", children: [jsxs("div", { className: "tw:space-y-2 tw:text-center", children: [jsx("h2", { className: "tw:text-xl tw:font-semibold", children: title }), jsx("p", { className: "tw:text-sm tw:text-muted-foreground", children: description })] }), jsxs("div", { className: "tw:flex tw:flex-col tw:gap-2", children: [jsx(Label, { htmlFor: emailId, children: emailLabel }), jsx(Input, { id: emailId, type: "email", value: email, onChange: (event) => onEmailChange(event.target.value), placeholder: emailPlaceholder, autoComplete: "email", className: "tw:h-12", disabled: isSubmitting, required: true })] }), jsx(Button, { type: "submit", className: "tw:h-12 tw:w-full", loading: isSubmitting, loadingText: submitLabel, disabled: !email.trim(), children: submitLabel }), error ? (jsx("p", { className: "tw:text-center tw:text-sm tw:text-destructive", children: error })) : null, jsx(Button, { type: "button", variant: "ghost", className: "tw:w-full", onClick: onBack, disabled: isSubmitting, children: backLabel })] }));
33
+ }
34
+ function ForgotPasswordSentView({ backAriaLabel, onBack, title, descriptionPrefix, email, instructions, resendLabel, resendCountdown, onResend, isResending, error, backLabel, }) {
35
+ return (jsxs("div", { className: "tw:flex tw:flex-col tw:gap-8", children: [jsx("div", { className: "tw:flex tw:items-center", children: jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: onBack, "aria-label": backAriaLabel, children: jsx(ArrowLeft, { className: "tw:size-4" }) }) }), jsxs("div", { className: "tw:flex tw:flex-col tw:items-center tw:gap-4 tw:text-center", children: [jsx("div", { className: "tw:flex tw:size-12 tw:items-center tw:justify-center tw:rounded-xl tw:bg-sky-100 tw:text-primary", children: jsx(LockKeyhole, { className: "tw:size-6" }) }), jsx("h2", { className: "tw:text-3xl tw:font-semibold tw:tracking-tight", children: title }), jsxs("p", { className: "tw:text-sm tw:text-muted-foreground", children: [descriptionPrefix, jsx("br", {}), email] })] }), jsxs("div", { className: "tw:flex tw:flex-col tw:gap-4 tw:text-center", children: [jsx("p", { className: "tw:text-sm tw:text-muted-foreground", children: instructions }), resendCountdown > 0 ? (jsxs("p", { className: "tw:text-sm tw:text-muted-foreground", children: [resendLabel, " in ", resendCountdown, "s"] })) : (jsx(Button, { type: "button", variant: "outline", className: "tw:mx-auto", loading: isResending, loadingText: `${resendLabel}...`, onClick: onResend, children: resendLabel })), error ? (jsx("p", { className: "tw:text-center tw:text-sm tw:text-destructive", children: error })) : null, jsx(Button, { type: "button", variant: "ghost", className: "tw:w-full", onClick: onBack, disabled: isResending, children: backLabel })] })] }));
36
+ }
37
+ function SsoEmailView({ backAriaLabel, onBack, title, description, emailId, emailLabel, email, onEmailChange, emailPlaceholder, submitLabel, isSubmitting, onSubmit, hint, }) {
38
+ return (jsxs("div", { className: "tw:flex tw:flex-col tw:gap-8", children: [jsx("div", { className: "tw:flex tw:items-center", children: jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: onBack, "aria-label": backAriaLabel, children: jsx(ArrowLeft, { className: "tw:size-4" }) }) }), jsxs("div", { className: "tw:flex tw:flex-col tw:items-center tw:gap-4 tw:text-center", children: [jsx("div", { className: "tw:flex tw:size-12 tw:items-center tw:justify-center tw:rounded-xl tw:bg-sky-100 tw:text-primary", children: jsx(LockKeyhole, { className: "tw:size-6" }) }), jsxs("div", { className: "tw:space-y-2", children: [jsx("h2", { className: "tw:text-3xl tw:font-semibold tw:tracking-tight", children: title }), jsx("p", { className: "tw:text-sm tw:text-muted-foreground", children: description })] })] }), jsxs("form", { onSubmit: onSubmit, className: "tw:flex tw:flex-col tw:gap-5", children: [jsxs("div", { className: "tw:flex tw:flex-col tw:gap-2", children: [jsx(Label, { htmlFor: emailId, children: emailLabel }), jsx(Input, { id: emailId, type: "email", value: email, onChange: (event) => onEmailChange(event.target.value), placeholder: emailPlaceholder, autoComplete: "email", className: "tw:h-12", disabled: isSubmitting, required: true })] }), jsx(Button, { type: "submit", className: "tw:h-12 tw:w-full", loading: isSubmitting, loadingText: submitLabel, disabled: !email.trim(), children: submitLabel })] }), jsx("p", { className: "tw:text-center tw:text-sm tw:text-muted-foreground", children: hint })] }));
39
+ }
40
+ function SplitMediaPane({ widthPercent, hasSplitImage, imageSrc, imageAlt, onImageError, overlayOpacity, imageOverlayContent, testimonial, }) {
41
+ const splitImageStyle = {
42
+ width: `${widthPercent}%`,
43
+ };
44
+ return (jsxs("div", { className: "tw:relative tw:overflow-hidden tw:shrink-0", style: splitImageStyle, children: [hasSplitImage ? (jsx("img", { src: imageSrc, alt: imageAlt, className: "tw:h-full tw:w-full tw:object-cover", onError: onImageError })) : (jsx("div", { className: "tw:h-full tw:w-full tw:bg-gradient-to-br tw:from-slate-700 tw:via-slate-600 tw:to-slate-900" })), jsx("div", { className: "tw:absolute tw:inset-0 tw:bg-black", style: { opacity: overlayOpacity } }), jsx("div", { className: "tw:absolute tw:inset-0 tw:bg-gradient-to-t tw:from-black/85 tw:via-black/45 tw:to-black/20" }), imageOverlayContent || testimonial ? (jsx("div", { className: "tw:absolute tw:inset-x-0 tw:bottom-0 tw:z-10 tw:p-8 tw:pb-12", children: imageOverlayContent ?? (jsxs("blockquote", { className: "tw:text-white", children: [jsx("p", { className: "tw:text-lg tw:font-medium tw:leading-relaxed tw:[text-shadow:0_2px_12px_rgba(0,0,0,0.85)]", children: testimonial?.quote }), jsxs("footer", { className: "tw:mt-4 tw:[text-shadow:0_2px_8px_rgba(0,0,0,0.8)]", children: [jsx("p", { className: "tw:text-sm tw:font-semibold tw:text-white", children: testimonial?.authorName }), testimonial?.authorTitle ? (jsx("p", { className: "tw:text-sm tw:text-white/80", children: testimonial.authorTitle })) : null] })] })) })) : null] }));
45
+ }
46
+ function FooterLinks({ links }) {
47
+ if (links.length === 0) {
48
+ return null;
49
+ }
50
+ return (jsx("div", { className: "tw:mt-6 tw:flex tw:flex-wrap tw:items-center tw:justify-center tw:gap-4 tw:text-xs tw:text-muted-foreground", children: links.map((link, index) => (jsxs(React.Fragment, { children: [index > 0 ? jsx("span", { "aria-hidden": "true", children: "·" }) : null, jsx("a", { href: link.href, ...getLinkAttributes(link.external), className: "hover:tw:text-foreground hover:tw:underline", children: link.label })] }, `${link.label}-${index}`))) }));
51
+ }
52
+
53
+ export { BrandHeader, FooterLinks, ForgotPasswordSentView, ForgotPasswordView, SignInView, SplitMediaPane, SsoEmailView };
@@ -0,0 +1,27 @@
1
+ import * as React from "react";
2
+ import * as MenubarPrimitive from "@radix-ui/react-menubar";
3
+ declare function Menubar({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Root>): import("react/jsx-runtime").JSX.Element;
4
+ declare function MenubarMenu({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Menu>): import("react/jsx-runtime").JSX.Element;
5
+ declare function MenubarGroup({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Group>): import("react/jsx-runtime").JSX.Element;
6
+ declare function MenubarPortal({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Portal>): import("react/jsx-runtime").JSX.Element;
7
+ declare function MenubarRadioGroup({ ...props }: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>): import("react/jsx-runtime").JSX.Element;
8
+ declare function MenubarTrigger({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Trigger>): import("react/jsx-runtime").JSX.Element;
9
+ declare function MenubarContent({ className, align, alignOffset, sideOffset, ...props }: React.ComponentProps<typeof MenubarPrimitive.Content>): import("react/jsx-runtime").JSX.Element;
10
+ declare function MenubarItem({ className, inset, variant, ...props }: React.ComponentProps<typeof MenubarPrimitive.Item> & {
11
+ inset?: boolean;
12
+ variant?: "default" | "destructive";
13
+ }): import("react/jsx-runtime").JSX.Element;
14
+ declare function MenubarCheckboxItem({ className, children, checked, ...props }: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>): import("react/jsx-runtime").JSX.Element;
15
+ declare function MenubarRadioItem({ className, children, ...props }: React.ComponentProps<typeof MenubarPrimitive.RadioItem>): import("react/jsx-runtime").JSX.Element;
16
+ declare function MenubarLabel({ className, inset, ...props }: React.ComponentProps<typeof MenubarPrimitive.Label> & {
17
+ inset?: boolean;
18
+ }): import("react/jsx-runtime").JSX.Element;
19
+ declare function MenubarSeparator({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Separator>): import("react/jsx-runtime").JSX.Element;
20
+ declare function MenubarShortcut({ className, ...props }: React.ComponentProps<"span">): import("react/jsx-runtime").JSX.Element;
21
+ declare function MenubarSub({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Sub>): import("react/jsx-runtime").JSX.Element;
22
+ declare function MenubarSubTrigger({ className, inset, children, ...props }: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & {
23
+ inset?: boolean;
24
+ }): import("react/jsx-runtime").JSX.Element;
25
+ declare function MenubarSubContent({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.SubContent>): import("react/jsx-runtime").JSX.Element;
26
+ export { Menubar, MenubarPortal, MenubarMenu, MenubarTrigger, MenubarContent, MenubarGroup, MenubarSeparator, MenubarLabel, MenubarItem, MenubarShortcut, MenubarCheckboxItem, MenubarRadioGroup, MenubarRadioItem, MenubarSub, MenubarSubTrigger, MenubarSubContent, };
27
+ //# sourceMappingURL=menubar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menubar.d.ts","sourceRoot":"","sources":["../../src/components/menubar.tsx"],"names":[],"mappings":"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"}