@lessly/ui 0.22.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1473,6 +1473,98 @@ declare const NotificationToaster: React$1.ForwardRefExoticComponent<Notificatio
1473
1473
  */
1474
1474
  declare const COUNTRY_OPTIONS: SelectOption[];
1475
1475
 
1476
+ interface BetaGateScreenProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'title' | 'onSubmit'> {
1477
+ /** Fires with the trimmed code. The screen never checks it — the caller does. */
1478
+ onSubmit: (code: string) => void;
1479
+ defaultCode?: string;
1480
+ /** Fires with the raw field value on every keystroke — the seam a caller uses to clear
1481
+ * its own `error` as the user starts correcting the code. */
1482
+ onCodeChange?: (code: string) => void;
1483
+ /** Focuses the access-code field on mount. On by default: the screen is one field, so
1484
+ * that is where the caret belongs. Pass `false` to leave the focus alone. */
1485
+ autoFocus?: boolean;
1486
+ /** Disables the submit button and swaps its label while the caller's check is in flight. */
1487
+ submitting?: boolean;
1488
+ /** Rendered as an alert above the field — typically a rejected code. */
1489
+ error?: string | null;
1490
+ /** Social sign-in buttons, rendered above an "or" divider. Without it there is no divider. */
1491
+ socialAuth?: React$1.ReactNode;
1492
+ /** Target of the waitlist link in the default description. */
1493
+ waitlistHref?: string;
1494
+ /** Renders "Already have an account? Sign in" as a link. */
1495
+ signInHref?: string;
1496
+ /** Renders the same affordance as a button. Ignored when `signInHref` is given. */
1497
+ onSignIn?: () => void;
1498
+ submitLabel?: React$1.ReactNode;
1499
+ /** Brand mark above the headline. */
1500
+ logo?: React$1.ReactNode;
1501
+ /** Rendered top-right. Defaults to the kit's own `ThemeToggle`; pass your own node to
1502
+ * replace it, or `null` to drop it. */
1503
+ themeToggle?: React$1.ReactNode;
1504
+ /** Pass `null` to render no page heading — same meaning as on `SignupScreen`. */
1505
+ title?: React$1.ReactNode;
1506
+ description?: React$1.ReactNode;
1507
+ /** Muted footer signature. Absent by default; pass a node to render one. */
1508
+ footer?: React$1.ReactNode;
1509
+ }
1510
+ /**
1511
+ * The gate in front of registration while the product is in closed beta: a single access
1512
+ * code, optionally preceded by social sign-in. Presentational and self-contained — it never
1513
+ * validates the code, never calls an API and never navigates; the caller handles the
1514
+ * outcome of `onSubmit`.
1515
+ */
1516
+ declare function BetaGateScreen({ onSubmit, defaultCode, onCodeChange, autoFocus, submitting, error, socialAuth, waitlistHref, signInHref, onSignIn, submitLabel, logo, themeToggle, title, description, footer, ...props }: BetaGateScreenProps): React$1.JSX.Element;
1517
+
1518
+ /** The submit payload — what a registration endpoint takes, minus anything the caller owns
1519
+ * (the beta code, the invite, the return URL). */
1520
+ interface SignupScreenSubmit {
1521
+ name: string;
1522
+ email: string;
1523
+ password: string;
1524
+ }
1525
+ interface SignupScreenProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'title' | 'onSubmit'> {
1526
+ onSubmit: (payload: SignupScreenSubmit) => void;
1527
+ defaultValues?: Partial<SignupScreenSubmit>;
1528
+ /** Disables the submit button and swaps its label while the caller's request is in flight. */
1529
+ submitting?: boolean;
1530
+ serverError?: string | null;
1531
+ /** Field-level messages returned alongside a server error. */
1532
+ violations?: string[];
1533
+ /** Social sign-in buttons, rendered above an "or continue with email" divider. Not shown
1534
+ * when `children` take over the body. */
1535
+ socialAuth?: React$1.ReactNode;
1536
+ /** Renders "Use a different code" under the form — the way back to the beta gate. */
1537
+ onEditCode?: () => void;
1538
+ /** Renders "Already have an account? Sign in" as a link. */
1539
+ signInHref?: string;
1540
+ /** Renders the same affordance as a button. Ignored when `signInHref` is given. */
1541
+ onSignIn?: () => void;
1542
+ submitLabel?: React$1.ReactNode;
1543
+ /**
1544
+ * Replaces the whole body — social auth, divider, register form and all. This is the seam
1545
+ * the consumer uses to host steps the kit deliberately does not know about (MFA challenge,
1546
+ * TOTP enrolment) inside the same window.
1547
+ */
1548
+ children?: React$1.ReactNode;
1549
+ /** Brand mark above the headline. */
1550
+ logo?: React$1.ReactNode;
1551
+ /** Rendered top-right. Defaults to the kit's own `ThemeToggle`; pass your own node to
1552
+ * replace it, or `null` to drop it. */
1553
+ themeToggle?: React$1.ReactNode;
1554
+ /** Pass `null` to render no page heading — for a body (MFA steps) that brings its own. */
1555
+ title?: React$1.ReactNode;
1556
+ description?: React$1.ReactNode;
1557
+ /** Muted footer signature. Absent by default; pass a node to render one. */
1558
+ footer?: React$1.ReactNode;
1559
+ }
1560
+ /**
1561
+ * The registration window: social sign-in, then name / email / password. Presentational and
1562
+ * self-contained — it never calls an API and never navigates; the caller handles the outcome
1563
+ * of `onSubmit`. Password rules are checked here because they are the same rules the
1564
+ * registration endpoint enforces, and failing them client-side saves a round trip.
1565
+ */
1566
+ declare function SignupScreen({ onSubmit, defaultValues, submitting, serverError, violations, socialAuth, onEditCode, signInHref, onSignIn, submitLabel, children, logo, themeToggle, title, description, footer, ...props }: SignupScreenProps): React$1.JSX.Element;
1567
+
1476
1568
  /** One beneficial owner, in the shape the organization API takes it. */
1477
1569
  interface BeneficialOwnerPayload {
1478
1570
  name: string;
@@ -1622,4 +1714,4 @@ interface ProductCreateScreenProps extends Omit<React$1.HTMLAttributes<HTMLDivEl
1622
1714
  */
1623
1715
  declare function ProductCreateScreen({ organizationName: _organizationName, organizations, selectedOrganizationId, onOrganizationChange, productsLoading, onSubmit, defaultName, submitting, serverError, existingProducts, onOpenProduct, existingProductsLabel, submitLabel, onCancel, logo, themeToggle, title, description, footer, ...props }: ProductCreateScreenProps): React$1.JSX.Element;
1624
1716
 
1625
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, type AppShellProps, AppSidebar, type AppSidebarProps, AspectRatio, AuthenticatedLayout, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, type BeneficialOwnerPayload, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, type ButtonProps, COUNTRY_OPTIONS, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, type CarouselApi, CarouselContent, type CarouselContextProps, CarouselItem, CarouselNext, type CarouselOptions, type CarouselPlugin, CarouselPrevious, type CarouselProps, Checkbox, Code, CodeBlock, type CodeBlockProps, type CodeLang, type CodeProps, Col, type ColProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ConfirmDialog, type ConfirmDialogProps, type ConnectionAuth, ConnectionCard, type ConnectionCardProps, type ConnectionScope, type ConnectionStatus, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, type CopyButtonProps, type CreateProductSubmit, CreateProductWindow, type CreateProductWindowOrganization, type CreateProductWindowProduct, type CreateProductWindowProps, DatePicker, type DatePickerProps, type DeltaDirection, type DeltaTone, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DocsLink, type DocsLinkProps, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ExtensionIcon, type ExtensionIconProps, ExtensionLink, type ExtensionLinkProps, type ExtensionLinkUiMode, FeedbackButton, type FeedbackButtonLabels, type FeedbackButtonProps, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, Grid, GridOverlay, type GridOverlayProps, type GridProps, HoverCard, HoverCardContent, HoverCardTrigger, InlineError, type InlineErrorProps, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Label, MenuDivider, MenuPopup, type MenuPopupProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, type NavItem, type NavLinkComponent, NavRow, type NavRowProps, type NavRowVariant, NavSectionLabel, type NavSectionLabelProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, type NotifClass, type NotificationAction, NotificationBell, type NotificationBellProps, NotificationCenter, type NotificationCenterProps, type NotificationClass, type NotificationDeepLink, type NotificationItem, type NotificationMute, type NotificationPreferences, type NotificationProduct, NotificationSettings, type NotificationSettingsProps, type NotificationSeverity, type NotificationSubscription, type NotificationThreshold, NotificationToast, type NotificationToastDwell, type NotificationToastProps, NotificationToaster, type NotificationToasterPosition, type NotificationToasterProps, OrgProductSwitcher, type OrgProductSwitcherAction, type OrgProductSwitcherItem, type OrgProductSwitcherProps, OrganizationCreateScreen, type OrganizationCreateScreenProps, type OrganizationOnboardingDefaults, OrganizationOnboardingForm, type OrganizationOnboardingFormProps, type OrganizationOnboardingPayload, PageHeader, type PageHeaderProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, type PaginationLinkProps, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ProductCreateScreen, type ProductCreateScreenOrganization, type ProductCreateScreenProduct, type ProductCreateScreenProps, type ProductCreateScreenSubmit, Progress, RadioGroup, RadioGroupItem, RequestRow, type RequestRowProps, type RequestState, type RequestSurface, type ResolvedTheme, type Responsive, ScrollArea, ScrollBar, SectionIntro, type SectionIntroProps, SegmentChip, type SegmentChipProps, Select, type SelectOption, type SelectProps, Separator, type Severity, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarBackHeader, type SidebarBackHeaderProps, SidebarNav, SidebarNavLink, type SidebarNavLinkProps, type SidebarNavProps, SidebarProductHeader, type SidebarProductHeaderProps, Skeleton, Slider, StatCard, type StatCardProps, StatusDot, type StatusDotProps, Switch, type SwitchProps, TOAST_DWELL, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, type TextareaProps, type Theme, ThemeToggle, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UseSidebarOptions, type UseSidebarResult, UserMenu, type UserMenuItem, type UserMenuProps, type UserMenuUser, alertVariants, badgeVariants, buttonVariants, cn, formatRelativeAge, isKnownExtensionIcon, isNotificationSettled, navigationMenuTriggerStyle, segmentChipVariants, severityBadgeVariant, severityLabels, statusDotVariants, toggleVariants, useCarousel, useFormField, useIsMobile, useSidebar, useTheme };
1717
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AppShell, type AppShellProps, AppSidebar, type AppSidebarProps, AspectRatio, AuthenticatedLayout, Avatar, AvatarFallback, AvatarImage, Badge, type BadgeProps, type BeneficialOwnerPayload, BetaGateScreen, type BetaGateScreenProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, type ButtonProps, COUNTRY_OPTIONS, Calendar, type CalendarProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, type CarouselApi, CarouselContent, type CarouselContextProps, CarouselItem, CarouselNext, type CarouselOptions, type CarouselPlugin, CarouselPrevious, type CarouselProps, Checkbox, Code, CodeBlock, type CodeBlockProps, type CodeLang, type CodeProps, Col, type ColProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ConfirmDialog, type ConfirmDialogProps, type ConnectionAuth, ConnectionCard, type ConnectionCardProps, type ConnectionScope, type ConnectionStatus, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, type CopyButtonProps, type CreateProductSubmit, CreateProductWindow, type CreateProductWindowOrganization, type CreateProductWindowProduct, type CreateProductWindowProps, DatePicker, type DatePickerProps, type DeltaDirection, type DeltaTone, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DocsLink, type DocsLinkProps, Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, type EmptyStateProps, ExtensionIcon, type ExtensionIconProps, ExtensionLink, type ExtensionLinkProps, type ExtensionLinkUiMode, FeedbackButton, type FeedbackButtonLabels, type FeedbackButtonProps, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, Grid, GridOverlay, type GridOverlayProps, type GridProps, HoverCard, HoverCardContent, HoverCardTrigger, InlineError, type InlineErrorProps, Input, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, type InputProps, Label, MenuDivider, MenuPopup, type MenuPopupProps, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, type NavItem, type NavLinkComponent, NavRow, type NavRowProps, type NavRowVariant, NavSectionLabel, type NavSectionLabelProps, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, type NotifClass, type NotificationAction, NotificationBell, type NotificationBellProps, NotificationCenter, type NotificationCenterProps, type NotificationClass, type NotificationDeepLink, type NotificationItem, type NotificationMute, type NotificationPreferences, type NotificationProduct, NotificationSettings, type NotificationSettingsProps, type NotificationSeverity, type NotificationSubscription, type NotificationThreshold, NotificationToast, type NotificationToastDwell, type NotificationToastProps, NotificationToaster, type NotificationToasterPosition, type NotificationToasterProps, OrgProductSwitcher, type OrgProductSwitcherAction, type OrgProductSwitcherItem, type OrgProductSwitcherProps, OrganizationCreateScreen, type OrganizationCreateScreenProps, type OrganizationOnboardingDefaults, OrganizationOnboardingForm, type OrganizationOnboardingFormProps, type OrganizationOnboardingPayload, PageHeader, type PageHeaderProps, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, type PaginationLinkProps, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, ProductCreateScreen, type ProductCreateScreenOrganization, type ProductCreateScreenProduct, type ProductCreateScreenProps, type ProductCreateScreenSubmit, Progress, RadioGroup, RadioGroupItem, RequestRow, type RequestRowProps, type RequestState, type RequestSurface, type ResolvedTheme, type Responsive, ScrollArea, ScrollBar, SectionIntro, type SectionIntroProps, SegmentChip, type SegmentChipProps, Select, type SelectOption, type SelectProps, Separator, type Severity, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, SidebarBackHeader, type SidebarBackHeaderProps, SidebarNav, SidebarNavLink, type SidebarNavLinkProps, type SidebarNavProps, SidebarProductHeader, type SidebarProductHeaderProps, SignupScreen, type SignupScreenProps, type SignupScreenSubmit, Skeleton, Slider, StatCard, type StatCardProps, StatusDot, type StatusDotProps, Switch, type SwitchProps, TOAST_DWELL, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, type TextareaProps, type Theme, ThemeToggle, Toaster, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, type UseSidebarOptions, type UseSidebarResult, UserMenu, type UserMenuItem, type UserMenuProps, type UserMenuUser, alertVariants, badgeVariants, buttonVariants, cn, formatRelativeAge, isKnownExtensionIcon, isNotificationSettled, navigationMenuTriggerStyle, segmentChipVariants, severityBadgeVariant, severityLabels, statusDotVariants, toggleVariants, useCarousel, useFormField, useIsMobile, useSidebar, useTheme };
package/dist/index.js CHANGED
@@ -5207,17 +5207,354 @@ var COUNTRY_OPTIONS = [
5207
5207
  { value: "ZW", label: "Zimbabwe" }
5208
5208
  ];
5209
5209
 
5210
- // src/components/organization-onboarding-form.tsx
5210
+ // src/components/beta-gate-screen.tsx
5211
5211
  import * as React65 from "react";
5212
5212
 
5213
+ // src/components/auth-divider.tsx
5214
+ import { jsx as jsx79, jsxs as jsxs45 } from "react/jsx-runtime";
5215
+ function AuthDivider({ label }) {
5216
+ return /* @__PURE__ */ jsxs45("div", { className: "relative my-5", children: [
5217
+ /* @__PURE__ */ jsx79("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx79("div", { className: "w-full border-t border-border-subtle" }) }),
5218
+ /* @__PURE__ */ jsx79("div", { className: "relative flex justify-center text-xs", children: /* @__PURE__ */ jsx79("span", { className: "bg-bg-surface px-2 text-text-tertiary", children: label }) })
5219
+ ] });
5220
+ }
5221
+
5213
5222
  // src/lib/auth-surface.ts
5214
5223
  var AUTH_GLOW_BG = "radial-gradient(560px 320px at 28% 16%, var(--auth-glow-a), transparent 68%),radial-gradient(520px 340px at 78% 90%, var(--auth-glow-b), transparent 66%),var(--bg-sunken)";
5215
5224
  var AUTH_FILLED_BUTTON = "flex h-[46px] w-full items-center justify-center gap-[11px] rounded-[10px] border border-transparent bg-text-primary px-[14px] text-[14.5px] font-semibold tracking-[-0.005em] text-bg-sunken transition-opacity hover:opacity-[0.92] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-text-brand active:translate-y-px disabled:cursor-not-allowed disabled:opacity-[0.55]";
5216
5225
  var AUTH_QUIET_BUTTON = "flex h-[46px] w-full items-center justify-center gap-[11px] rounded-[10px] border border-border-default bg-transparent px-[14px] text-[14.5px] font-medium tracking-[-0.005em] text-text-secondary transition-colors hover:bg-bg-secondary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-text-brand";
5217
5226
  var AUTH_BUTTON_SHADOW = "var(--auth-btn-shadow)";
5218
5227
 
5228
+ // src/components/onboarding-screen-shell.tsx
5229
+ import { jsx as jsx80, jsxs as jsxs46 } from "react/jsx-runtime";
5230
+ var CARD_WIDTH = {
5231
+ md: "max-w-[440px]",
5232
+ lg: "max-w-[560px]"
5233
+ };
5234
+ function OnboardingScreenShell({
5235
+ logo,
5236
+ themeToggle = /* @__PURE__ */ jsx80(ThemeToggle, {}),
5237
+ title,
5238
+ description,
5239
+ footer,
5240
+ width = "md",
5241
+ children,
5242
+ className,
5243
+ ...props
5244
+ }) {
5245
+ return /* @__PURE__ */ jsxs46(
5246
+ "div",
5247
+ {
5248
+ className: cn(
5249
+ "relative flex min-h-screen w-full flex-col items-center justify-center overflow-hidden px-6 py-12 text-text-primary",
5250
+ className
5251
+ ),
5252
+ style: { background: AUTH_GLOW_BG },
5253
+ ...props,
5254
+ children: [
5255
+ themeToggle && /* @__PURE__ */ jsx80("div", { className: "absolute right-6 top-6", children: themeToggle }),
5256
+ /* @__PURE__ */ jsxs46(
5257
+ "div",
5258
+ {
5259
+ className: cn(
5260
+ "relative w-full rounded-2xl bg-bg-surface px-[34px] pb-[30px] pt-[38px] text-center",
5261
+ CARD_WIDTH[width]
5262
+ ),
5263
+ style: {
5264
+ border: "1px solid var(--auth-card-border)",
5265
+ boxShadow: "var(--auth-card-shadow)"
5266
+ },
5267
+ children: [
5268
+ logo && /* @__PURE__ */ jsx80("div", { className: "mb-[22px] flex items-center justify-center text-[24px] font-bold leading-none tracking-[-0.02em] text-text-primary", children: logo }),
5269
+ title != null && /* @__PURE__ */ jsx80(
5270
+ "h1",
5271
+ {
5272
+ className: cn(
5273
+ "text-[20px] font-semibold leading-[1.25] tracking-[-0.015em] text-text-primary",
5274
+ // Without a description the headline itself carries the gap to the form.
5275
+ description ? "mb-[8px]" : "mb-[24px]"
5276
+ ),
5277
+ children: title
5278
+ }
5279
+ ),
5280
+ description && /* @__PURE__ */ jsx80("p", { className: "mx-auto mb-[24px] max-w-[320px] text-[13.5px] leading-[1.5] text-text-secondary", children: description }),
5281
+ /* @__PURE__ */ jsx80("div", { className: "text-left", children }),
5282
+ footer != null && /* @__PURE__ */ jsx80("div", { className: "mt-[24px] text-[11px] tracking-[0.005em] text-text-tertiary", children: footer })
5283
+ ]
5284
+ }
5285
+ )
5286
+ ]
5287
+ }
5288
+ );
5289
+ }
5290
+
5291
+ // src/components/beta-gate-screen.tsx
5292
+ import { Fragment as Fragment9, jsx as jsx81, jsxs as jsxs47 } from "react/jsx-runtime";
5293
+ var DEFAULT_WAITLIST_HREF = "https://lessly.com/#waitlist";
5294
+ var LINK = "font-medium text-text-link hover:text-text-link-hover";
5295
+ function BetaGateScreen({
5296
+ onSubmit,
5297
+ defaultCode = "",
5298
+ onCodeChange,
5299
+ autoFocus = true,
5300
+ submitting,
5301
+ error,
5302
+ socialAuth,
5303
+ waitlistHref = DEFAULT_WAITLIST_HREF,
5304
+ signInHref,
5305
+ onSignIn,
5306
+ submitLabel = "Continue",
5307
+ logo,
5308
+ themeToggle,
5309
+ title = "We're in closed beta",
5310
+ description,
5311
+ footer,
5312
+ ...props
5313
+ }) {
5314
+ const [code, setCode] = React65.useState(defaultCode);
5315
+ const submittingRef = React65.useRef(false);
5316
+ const trimmed = code.trim();
5317
+ const canSubmit = trimmed !== "" && !submitting;
5318
+ React65.useEffect(() => {
5319
+ submittingRef.current = false;
5320
+ }, [code, submitting, error]);
5321
+ const handleSubmit = (event) => {
5322
+ event.preventDefault();
5323
+ if (!canSubmit || submittingRef.current) return;
5324
+ submittingRef.current = true;
5325
+ onSubmit(trimmed);
5326
+ };
5327
+ const defaultDescription = /* @__PURE__ */ jsxs47(Fragment9, { children: [
5328
+ "A beta access code is required to join. or",
5329
+ " ",
5330
+ /* @__PURE__ */ jsx81("a", { href: waitlistHref, className: LINK, children: "join the waitlist" }),
5331
+ " ",
5332
+ "to request one."
5333
+ ] });
5334
+ return /* @__PURE__ */ jsxs47(
5335
+ OnboardingScreenShell,
5336
+ {
5337
+ logo,
5338
+ themeToggle,
5339
+ title,
5340
+ description: description ?? defaultDescription,
5341
+ footer,
5342
+ ...props,
5343
+ children: [
5344
+ socialAuth && /* @__PURE__ */ jsxs47(Fragment9, { children: [
5345
+ /* @__PURE__ */ jsx81("div", { "data-testid": "beta-gate-social-auth", children: socialAuth }),
5346
+ /* @__PURE__ */ jsx81(AuthDivider, { label: "or" })
5347
+ ] }),
5348
+ error && /* @__PURE__ */ jsx81(InlineError, { "data-testid": "beta-gate-error", className: "mb-4 text-center", children: error }),
5349
+ /* @__PURE__ */ jsxs47("form", { onSubmit: handleSubmit, className: "space-y-4", noValidate: true, children: [
5350
+ /* @__PURE__ */ jsxs47("div", { className: "space-y-1.5", children: [
5351
+ /* @__PURE__ */ jsx81(Label2, { htmlFor: "beta-code", className: "sr-only", children: "Lessly beta access code" }),
5352
+ /* @__PURE__ */ jsx81(
5353
+ Input,
5354
+ {
5355
+ id: "beta-code",
5356
+ "data-testid": "beta-code-input",
5357
+ value: code,
5358
+ autoComplete: "off",
5359
+ autoFocus,
5360
+ placeholder: "Lessly beta access code",
5361
+ onChange: (event) => {
5362
+ setCode(event.target.value);
5363
+ onCodeChange?.(event.target.value);
5364
+ }
5365
+ }
5366
+ )
5367
+ ] }),
5368
+ /* @__PURE__ */ jsx81("div", { className: "pt-1", children: /* @__PURE__ */ jsx81(
5369
+ "button",
5370
+ {
5371
+ type: "submit",
5372
+ "data-testid": "submit-beta-code",
5373
+ disabled: !canSubmit,
5374
+ className: AUTH_FILLED_BUTTON,
5375
+ style: { boxShadow: AUTH_BUTTON_SHADOW },
5376
+ children: submitting ? "Checking\u2026" : submitLabel
5377
+ }
5378
+ ) })
5379
+ ] }),
5380
+ (signInHref || onSignIn) && /* @__PURE__ */ jsxs47("p", { className: "mt-5 text-center text-sm text-text-secondary", children: [
5381
+ "Already have an account?",
5382
+ " ",
5383
+ signInHref ? /* @__PURE__ */ jsx81("a", { "data-testid": "beta-gate-signin", href: signInHref, className: LINK, children: "Sign in" }) : /* @__PURE__ */ jsx81(
5384
+ "button",
5385
+ {
5386
+ type: "button",
5387
+ "data-testid": "beta-gate-signin",
5388
+ onClick: onSignIn,
5389
+ className: LINK,
5390
+ children: "Sign in"
5391
+ }
5392
+ )
5393
+ ] })
5394
+ ]
5395
+ }
5396
+ );
5397
+ }
5398
+
5399
+ // src/components/signup-screen.tsx
5400
+ import * as React66 from "react";
5401
+ import { Fragment as Fragment10, jsx as jsx82, jsxs as jsxs48 } from "react/jsx-runtime";
5402
+ var LINK2 = "font-medium text-text-link hover:text-text-link-hover";
5403
+ function SignupScreen({
5404
+ onSubmit,
5405
+ defaultValues,
5406
+ submitting,
5407
+ serverError,
5408
+ violations,
5409
+ socialAuth,
5410
+ onEditCode,
5411
+ signInHref,
5412
+ onSignIn,
5413
+ submitLabel = "Create account",
5414
+ children,
5415
+ logo,
5416
+ themeToggle,
5417
+ title = "Create your account",
5418
+ description,
5419
+ footer,
5420
+ ...props
5421
+ }) {
5422
+ const [name, setName] = React66.useState(defaultValues?.name ?? "");
5423
+ const [email, setEmail] = React66.useState(defaultValues?.email ?? "");
5424
+ const [password, setPassword] = React66.useState(defaultValues?.password ?? "");
5425
+ const [passwordError, setPasswordError] = React66.useState(null);
5426
+ const submittingRef = React66.useRef(false);
5427
+ const trimmedName = name.trim();
5428
+ const trimmedEmail = email.trim();
5429
+ const canSubmit = trimmedName !== "" && trimmedEmail !== "" && password !== "" && !submitting;
5430
+ React66.useEffect(() => {
5431
+ submittingRef.current = false;
5432
+ }, [name, email, password, submitting, serverError]);
5433
+ const handleSubmit = (event) => {
5434
+ event.preventDefault();
5435
+ if (!canSubmit || submittingRef.current) return;
5436
+ const failure = validatePassword(password);
5437
+ if (failure) {
5438
+ setPasswordError(failure);
5439
+ return;
5440
+ }
5441
+ setPasswordError(null);
5442
+ submittingRef.current = true;
5443
+ onSubmit({ name: trimmedName, email: trimmedEmail, password });
5444
+ };
5445
+ const body = children ?? /* @__PURE__ */ jsxs48(Fragment10, { children: [
5446
+ socialAuth && /* @__PURE__ */ jsxs48(Fragment10, { children: [
5447
+ /* @__PURE__ */ jsx82("div", { "data-testid": "signup-social-auth", children: socialAuth }),
5448
+ /* @__PURE__ */ jsx82(AuthDivider, { label: "or continue with email" })
5449
+ ] }),
5450
+ /* @__PURE__ */ jsxs48("form", { onSubmit: handleSubmit, className: "space-y-4", noValidate: true, children: [
5451
+ /* @__PURE__ */ jsxs48("div", { className: "space-y-1.5", children: [
5452
+ /* @__PURE__ */ jsx82(Label2, { htmlFor: "signup-name", children: "Full name" }),
5453
+ /* @__PURE__ */ jsx82(
5454
+ Input,
5455
+ {
5456
+ id: "signup-name",
5457
+ "data-testid": "signup-name",
5458
+ value: name,
5459
+ disabled: submitting,
5460
+ placeholder: "Jane Smith",
5461
+ onChange: (event) => setName(event.target.value)
5462
+ }
5463
+ )
5464
+ ] }),
5465
+ /* @__PURE__ */ jsxs48("div", { className: "space-y-1.5", children: [
5466
+ /* @__PURE__ */ jsx82(Label2, { htmlFor: "signup-email", children: "Email" }),
5467
+ /* @__PURE__ */ jsx82(
5468
+ Input,
5469
+ {
5470
+ id: "signup-email",
5471
+ "data-testid": "signup-email",
5472
+ type: "email",
5473
+ value: email,
5474
+ disabled: submitting,
5475
+ autoComplete: "email",
5476
+ placeholder: "you@example.com",
5477
+ onChange: (event) => setEmail(event.target.value)
5478
+ }
5479
+ )
5480
+ ] }),
5481
+ /* @__PURE__ */ jsxs48("div", { className: "space-y-1.5", children: [
5482
+ /* @__PURE__ */ jsx82(Label2, { htmlFor: "signup-password", children: "Password" }),
5483
+ /* @__PURE__ */ jsx82(
5484
+ Input,
5485
+ {
5486
+ id: "signup-password",
5487
+ "data-testid": "signup-password",
5488
+ type: "password",
5489
+ value: password,
5490
+ disabled: submitting,
5491
+ autoComplete: "new-password",
5492
+ placeholder: "Min 8 chars, 1 uppercase, 1 number",
5493
+ onChange: (event) => {
5494
+ setPassword(event.target.value);
5495
+ if (passwordError) setPasswordError(null);
5496
+ }
5497
+ }
5498
+ )
5499
+ ] }),
5500
+ passwordError && /* @__PURE__ */ jsx82(InlineError, { "data-testid": "signup-password-error", children: passwordError }),
5501
+ (serverError || violations && violations.length > 0) && /* @__PURE__ */ jsxs48(InlineError, { "data-testid": "signup-error", children: [
5502
+ serverError,
5503
+ violations && violations.length > 0 && /* @__PURE__ */ jsx82("ul", { "data-testid": "signup-violations", className: "mt-1 list-disc pl-4", children: violations.map((violation) => /* @__PURE__ */ jsx82("li", { children: violation }, violation)) })
5504
+ ] }),
5505
+ /* @__PURE__ */ jsx82("div", { className: "pt-1", children: /* @__PURE__ */ jsx82(
5506
+ "button",
5507
+ {
5508
+ type: "submit",
5509
+ "data-testid": "submit-signup",
5510
+ disabled: !canSubmit,
5511
+ className: AUTH_FILLED_BUTTON,
5512
+ style: { boxShadow: AUTH_BUTTON_SHADOW },
5513
+ children: submitting ? "Creating account\u2026" : submitLabel
5514
+ }
5515
+ ) })
5516
+ ] }),
5517
+ onEditCode && /* @__PURE__ */ jsx82("p", { className: "mt-4 text-center text-sm text-text-secondary", children: /* @__PURE__ */ jsx82(
5518
+ "button",
5519
+ {
5520
+ type: "button",
5521
+ "data-testid": "signup-edit-code",
5522
+ onClick: onEditCode,
5523
+ className: LINK2,
5524
+ children: "Use a different code"
5525
+ }
5526
+ ) })
5527
+ ] });
5528
+ return /* @__PURE__ */ jsxs48(
5529
+ OnboardingScreenShell,
5530
+ {
5531
+ logo,
5532
+ themeToggle,
5533
+ title,
5534
+ description,
5535
+ footer,
5536
+ ...props,
5537
+ children: [
5538
+ body,
5539
+ (signInHref || onSignIn) && /* @__PURE__ */ jsxs48("p", { className: "mt-5 text-center text-sm text-text-secondary", children: [
5540
+ "Already have an account?",
5541
+ " ",
5542
+ signInHref ? /* @__PURE__ */ jsx82("a", { "data-testid": "signup-signin", href: signInHref, className: LINK2, children: "Sign in" }) : /* @__PURE__ */ jsx82("button", { type: "button", "data-testid": "signup-signin", onClick: onSignIn, className: LINK2, children: "Sign in" })
5543
+ ] })
5544
+ ]
5545
+ }
5546
+ );
5547
+ }
5548
+ function validatePassword(password) {
5549
+ if (password.length < 8) return "Password must be at least 8 characters.";
5550
+ if (!/[A-Z]/.test(password)) return "Password must contain at least 1 uppercase letter.";
5551
+ if (!/[0-9]/.test(password)) return "Password must contain at least 1 number.";
5552
+ return null;
5553
+ }
5554
+
5219
5555
  // src/components/organization-onboarding-form.tsx
5220
- import { jsx as jsx79, jsxs as jsxs45 } from "react/jsx-runtime";
5556
+ import * as React67 from "react";
5557
+ import { jsx as jsx83, jsxs as jsxs49 } from "react/jsx-runtime";
5221
5558
  var CONTROLLER_SHARE_PCT = 50;
5222
5559
  var MAX_BENEFICIAL_OWNERS = 50;
5223
5560
  function parseShare(raw) {
@@ -5248,21 +5585,21 @@ function OrganizationOnboardingForm({
5248
5585
  onCancel,
5249
5586
  className
5250
5587
  }) {
5251
- const [name, setName] = React65.useState(defaultValues?.name ?? "");
5252
- const [legalName, setLegalName] = React65.useState(defaultValues?.legal_name ?? "");
5253
- const [ownerName, setOwnerName] = React65.useState(defaultValues?.owner_name ?? "");
5254
- const [countryOfIncorporation, setCountryOfIncorporation] = React65.useState(
5588
+ const [name, setName] = React67.useState(defaultValues?.name ?? "");
5589
+ const [legalName, setLegalName] = React67.useState(defaultValues?.legal_name ?? "");
5590
+ const [ownerName, setOwnerName] = React67.useState(defaultValues?.owner_name ?? "");
5591
+ const [countryOfIncorporation, setCountryOfIncorporation] = React67.useState(
5255
5592
  defaultValues?.country_of_incorporation ?? ""
5256
5593
  );
5257
- const [residencyCountry, setResidencyCountry] = React65.useState(
5594
+ const [residencyCountry, setResidencyCountry] = React67.useState(
5258
5595
  defaultValues?.residency_country ?? ""
5259
5596
  );
5260
- const [owners, setOwners] = React65.useState(
5597
+ const [owners, setOwners] = React67.useState(
5261
5598
  () => initialRows(defaultValues?.beneficial_owners)
5262
5599
  );
5263
- const [ownershipConfirmed, setOwnershipConfirmed] = React65.useState(false);
5264
- const nextKeyRef = React65.useRef(owners.length);
5265
- const submittingRef = React65.useRef(false);
5600
+ const [ownershipConfirmed, setOwnershipConfirmed] = React67.useState(false);
5601
+ const nextKeyRef = React67.useRef(owners.length);
5602
+ const submittingRef = React67.useRef(false);
5266
5603
  const trimmed = name.trim();
5267
5604
  const filledOwners = owners.filter((row) => !isRowBlank(row));
5268
5605
  const ownerShares = filledOwners.map((row) => parseShare(row.share));
@@ -5307,7 +5644,7 @@ function OrganizationOnboardingForm({
5307
5644
  ...needsOwnershipConfirmation ? { ownership_confirmed: ownershipConfirmed } : {}
5308
5645
  });
5309
5646
  };
5310
- React65.useEffect(() => {
5647
+ React67.useEffect(() => {
5311
5648
  submittingRef.current = false;
5312
5649
  }, [
5313
5650
  name,
@@ -5320,12 +5657,12 @@ function OrganizationOnboardingForm({
5320
5657
  submitting,
5321
5658
  serverError
5322
5659
  ]);
5323
- const countryField = (params) => /* @__PURE__ */ jsxs45("div", { className: "space-y-1.5", children: [
5324
- /* @__PURE__ */ jsxs45(Label2, { htmlFor: params.id, children: [
5660
+ const countryField = (params) => /* @__PURE__ */ jsxs49("div", { className: "space-y-1.5", children: [
5661
+ /* @__PURE__ */ jsxs49(Label2, { htmlFor: params.id, children: [
5325
5662
  params.label,
5326
- params.required && /* @__PURE__ */ jsx79("span", { className: "text-text-danger", children: " *" })
5663
+ params.required && /* @__PURE__ */ jsx83("span", { className: "text-text-danger", children: " *" })
5327
5664
  ] }),
5328
- /* @__PURE__ */ jsx79(
5665
+ /* @__PURE__ */ jsx83(
5329
5666
  Select,
5330
5667
  {
5331
5668
  id: params.id,
@@ -5338,10 +5675,10 @@ function OrganizationOnboardingForm({
5338
5675
  }
5339
5676
  )
5340
5677
  ] });
5341
- return /* @__PURE__ */ jsxs45("form", { onSubmit: handleSubmit, className: cn("space-y-4", className), children: [
5342
- /* @__PURE__ */ jsxs45("div", { className: "space-y-1.5", children: [
5343
- /* @__PURE__ */ jsx79(Label2, { htmlFor: "create-org-name", children: "Organization name" }),
5344
- /* @__PURE__ */ jsx79(
5678
+ return /* @__PURE__ */ jsxs49("form", { onSubmit: handleSubmit, className: cn("space-y-4", className), children: [
5679
+ /* @__PURE__ */ jsxs49("div", { className: "space-y-1.5", children: [
5680
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: "create-org-name", children: "Organization name" }),
5681
+ /* @__PURE__ */ jsx83(
5345
5682
  Input,
5346
5683
  {
5347
5684
  id: "create-org-name",
@@ -5352,9 +5689,9 @@ function OrganizationOnboardingForm({
5352
5689
  }
5353
5690
  )
5354
5691
  ] }),
5355
- /* @__PURE__ */ jsxs45("div", { className: "space-y-1.5", children: [
5356
- /* @__PURE__ */ jsx79(Label2, { htmlFor: "create-org-legal-name", children: "Legal name" }),
5357
- /* @__PURE__ */ jsx79(
5692
+ /* @__PURE__ */ jsxs49("div", { className: "space-y-1.5", children: [
5693
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: "create-org-legal-name", children: "Legal name" }),
5694
+ /* @__PURE__ */ jsx83(
5358
5695
  Input,
5359
5696
  {
5360
5697
  id: "create-org-legal-name",
@@ -5365,9 +5702,9 @@ function OrganizationOnboardingForm({
5365
5702
  }
5366
5703
  )
5367
5704
  ] }),
5368
- /* @__PURE__ */ jsxs45("div", { className: "space-y-1.5", children: [
5369
- /* @__PURE__ */ jsx79(Label2, { htmlFor: "create-org-owner-name", children: "Owner name" }),
5370
- /* @__PURE__ */ jsx79(
5705
+ /* @__PURE__ */ jsxs49("div", { className: "space-y-1.5", children: [
5706
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: "create-org-owner-name", children: "Owner name" }),
5707
+ /* @__PURE__ */ jsx83(
5371
5708
  Input,
5372
5709
  {
5373
5710
  id: "create-org-owner-name",
@@ -5392,10 +5729,10 @@ function OrganizationOnboardingForm({
5392
5729
  onChange: setResidencyCountry,
5393
5730
  required: false
5394
5731
  }),
5395
- /* @__PURE__ */ jsxs45("div", { className: "space-y-2", children: [
5396
- /* @__PURE__ */ jsxs45("div", { className: "flex items-center justify-between", children: [
5397
- /* @__PURE__ */ jsx79(Label2, { children: "Beneficial owners" }),
5398
- /* @__PURE__ */ jsx79(
5732
+ /* @__PURE__ */ jsxs49("div", { className: "space-y-2", children: [
5733
+ /* @__PURE__ */ jsxs49("div", { className: "flex items-center justify-between", children: [
5734
+ /* @__PURE__ */ jsx83(Label2, { children: "Beneficial owners" }),
5735
+ /* @__PURE__ */ jsx83(
5399
5736
  Button,
5400
5737
  {
5401
5738
  type: "button",
@@ -5408,16 +5745,16 @@ function OrganizationOnboardingForm({
5408
5745
  }
5409
5746
  )
5410
5747
  ] }),
5411
- owners.length === 0 && /* @__PURE__ */ jsx79("p", { className: "text-xs text-text-tertiary", children: "List the natural persons who ultimately own or control the organization." }),
5412
- owners.map((row) => /* @__PURE__ */ jsxs45(
5748
+ owners.length === 0 && /* @__PURE__ */ jsx83("p", { className: "text-xs text-text-tertiary", children: "List the natural persons who ultimately own or control the organization." }),
5749
+ owners.map((row) => /* @__PURE__ */ jsxs49(
5413
5750
  "div",
5414
5751
  {
5415
5752
  "data-testid": `beneficial-owner-row-${row.key}`,
5416
5753
  className: "flex items-end gap-2",
5417
5754
  children: [
5418
- /* @__PURE__ */ jsxs45("div", { className: "flex-1 space-y-1", children: [
5419
- /* @__PURE__ */ jsx79(Label2, { htmlFor: `bo-name-${row.key}`, className: "text-xs", children: "Name" }),
5420
- /* @__PURE__ */ jsx79(
5755
+ /* @__PURE__ */ jsxs49("div", { className: "flex-1 space-y-1", children: [
5756
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: `bo-name-${row.key}`, className: "text-xs", children: "Name" }),
5757
+ /* @__PURE__ */ jsx83(
5421
5758
  Input,
5422
5759
  {
5423
5760
  id: `bo-name-${row.key}`,
@@ -5427,9 +5764,9 @@ function OrganizationOnboardingForm({
5427
5764
  }
5428
5765
  )
5429
5766
  ] }),
5430
- /* @__PURE__ */ jsxs45("div", { className: "w-40 space-y-1", children: [
5431
- /* @__PURE__ */ jsx79(Label2, { htmlFor: `bo-country-${row.key}`, className: "text-xs", children: "Country" }),
5432
- /* @__PURE__ */ jsx79(
5767
+ /* @__PURE__ */ jsxs49("div", { className: "w-40 space-y-1", children: [
5768
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: `bo-country-${row.key}`, className: "text-xs", children: "Country" }),
5769
+ /* @__PURE__ */ jsx83(
5433
5770
  Select,
5434
5771
  {
5435
5772
  id: `bo-country-${row.key}`,
@@ -5442,9 +5779,9 @@ function OrganizationOnboardingForm({
5442
5779
  }
5443
5780
  )
5444
5781
  ] }),
5445
- /* @__PURE__ */ jsxs45("div", { className: "w-24 space-y-1", children: [
5446
- /* @__PURE__ */ jsx79(Label2, { htmlFor: `bo-share-${row.key}`, className: "text-xs", children: "Share %" }),
5447
- /* @__PURE__ */ jsx79(
5782
+ /* @__PURE__ */ jsxs49("div", { className: "w-24 space-y-1", children: [
5783
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: `bo-share-${row.key}`, className: "text-xs", children: "Share %" }),
5784
+ /* @__PURE__ */ jsx83(
5448
5785
  Input,
5449
5786
  {
5450
5787
  id: `bo-share-${row.key}`,
@@ -5455,7 +5792,7 @@ function OrganizationOnboardingForm({
5455
5792
  }
5456
5793
  )
5457
5794
  ] }),
5458
- /* @__PURE__ */ jsx79(
5795
+ /* @__PURE__ */ jsx83(
5459
5796
  Button,
5460
5797
  {
5461
5798
  type: "button",
@@ -5470,15 +5807,15 @@ function OrganizationOnboardingForm({
5470
5807
  },
5471
5808
  row.key
5472
5809
  )),
5473
- !ownersValid && /* @__PURE__ */ jsx79("p", { "data-testid": "beneficial-owners-error", className: "text-xs text-text-danger", children: "Every owner needs a name, a country and a share between 0 and 100." }),
5474
- shareSum > 100 && /* @__PURE__ */ jsxs45("p", { "data-testid": "beneficial-owners-sum-warning", className: "text-xs text-text-warning", children: [
5810
+ !ownersValid && /* @__PURE__ */ jsx83("p", { "data-testid": "beneficial-owners-error", className: "text-xs text-text-danger", children: "Every owner needs a name, a country and a share between 0 and 100." }),
5811
+ shareSum > 100 && /* @__PURE__ */ jsxs49("p", { "data-testid": "beneficial-owners-sum-warning", className: "text-xs text-text-warning", children: [
5475
5812
  "The listed shares add up to ",
5476
5813
  shareSum,
5477
5814
  "%, which is more than 100%."
5478
5815
  ] })
5479
5816
  ] }),
5480
- needsOwnershipConfirmation && /* @__PURE__ */ jsxs45("div", { className: "flex items-start gap-2", children: [
5481
- /* @__PURE__ */ jsx79(
5817
+ needsOwnershipConfirmation && /* @__PURE__ */ jsxs49("div", { className: "flex items-start gap-2", children: [
5818
+ /* @__PURE__ */ jsx83(
5482
5819
  Checkbox,
5483
5820
  {
5484
5821
  id: "create-org-ownership-confirmed",
@@ -5487,24 +5824,24 @@ function OrganizationOnboardingForm({
5487
5824
  onCheckedChange: (value) => setOwnershipConfirmed(value === true)
5488
5825
  }
5489
5826
  ),
5490
- /* @__PURE__ */ jsxs45(
5827
+ /* @__PURE__ */ jsxs49(
5491
5828
  Label2,
5492
5829
  {
5493
5830
  htmlFor: "create-org-ownership-confirmed",
5494
5831
  className: "text-xs font-normal leading-snug",
5495
5832
  children: [
5496
5833
  "I confirm the ownership structure above is complete and correct",
5497
- requireSanctionsFields && /* @__PURE__ */ jsx79("span", { className: "text-text-danger", children: " *" })
5834
+ requireSanctionsFields && /* @__PURE__ */ jsx83("span", { className: "text-text-danger", children: " *" })
5498
5835
  ]
5499
5836
  }
5500
5837
  )
5501
5838
  ] }),
5502
- (serverError || violations && violations.length > 0) && /* @__PURE__ */ jsxs45(InlineError, { children: [
5839
+ (serverError || violations && violations.length > 0) && /* @__PURE__ */ jsxs49(InlineError, { children: [
5503
5840
  serverError,
5504
- violations && violations.length > 0 && /* @__PURE__ */ jsx79("ul", { "data-testid": "create-org-violations", className: "mt-1 list-disc pl-4", children: violations.map((violation) => /* @__PURE__ */ jsx79("li", { children: violation }, violation)) })
5841
+ violations && violations.length > 0 && /* @__PURE__ */ jsx83("ul", { "data-testid": "create-org-violations", className: "mt-1 list-disc pl-4", children: violations.map((violation) => /* @__PURE__ */ jsx83("li", { children: violation }, violation)) })
5505
5842
  ] }),
5506
- /* @__PURE__ */ jsxs45("div", { className: "space-y-2 pt-1", children: [
5507
- /* @__PURE__ */ jsx79(
5843
+ /* @__PURE__ */ jsxs49("div", { className: "space-y-2 pt-1", children: [
5844
+ /* @__PURE__ */ jsx83(
5508
5845
  "button",
5509
5846
  {
5510
5847
  type: "submit",
@@ -5515,76 +5852,13 @@ function OrganizationOnboardingForm({
5515
5852
  children: submitting ? "Creating\u2026" : submitLabel
5516
5853
  }
5517
5854
  ),
5518
- onCancel && /* @__PURE__ */ jsx79("button", { type: "button", onClick: onCancel, className: AUTH_QUIET_BUTTON, children: "Cancel" })
5855
+ onCancel && /* @__PURE__ */ jsx83("button", { type: "button", onClick: onCancel, className: AUTH_QUIET_BUTTON, children: "Cancel" })
5519
5856
  ] })
5520
5857
  ] });
5521
5858
  }
5522
5859
 
5523
- // src/components/onboarding-screen-shell.tsx
5524
- import { jsx as jsx80, jsxs as jsxs46 } from "react/jsx-runtime";
5525
- var CARD_WIDTH = {
5526
- md: "max-w-[440px]",
5527
- lg: "max-w-[560px]"
5528
- };
5529
- function OnboardingScreenShell({
5530
- logo,
5531
- themeToggle = /* @__PURE__ */ jsx80(ThemeToggle, {}),
5532
- title,
5533
- description,
5534
- footer,
5535
- width = "md",
5536
- children,
5537
- className,
5538
- ...props
5539
- }) {
5540
- return /* @__PURE__ */ jsxs46(
5541
- "div",
5542
- {
5543
- className: cn(
5544
- "relative flex min-h-screen w-full flex-col items-center justify-center overflow-hidden px-6 py-12 text-text-primary",
5545
- className
5546
- ),
5547
- style: { background: AUTH_GLOW_BG },
5548
- ...props,
5549
- children: [
5550
- themeToggle && /* @__PURE__ */ jsx80("div", { className: "absolute right-6 top-6", children: themeToggle }),
5551
- /* @__PURE__ */ jsxs46(
5552
- "div",
5553
- {
5554
- className: cn(
5555
- "relative w-full rounded-2xl bg-bg-surface px-[34px] pb-[30px] pt-[38px] text-center",
5556
- CARD_WIDTH[width]
5557
- ),
5558
- style: {
5559
- border: "1px solid var(--auth-card-border)",
5560
- boxShadow: "var(--auth-card-shadow)"
5561
- },
5562
- children: [
5563
- logo && /* @__PURE__ */ jsx80("div", { className: "mb-[22px] flex items-center justify-center text-[24px] font-bold leading-none tracking-[-0.02em] text-text-primary", children: logo }),
5564
- /* @__PURE__ */ jsx80(
5565
- "h1",
5566
- {
5567
- className: cn(
5568
- "text-[20px] font-semibold leading-[1.25] tracking-[-0.015em] text-text-primary",
5569
- // Without a description the headline itself carries the gap to the form.
5570
- description ? "mb-[8px]" : "mb-[24px]"
5571
- ),
5572
- children: title
5573
- }
5574
- ),
5575
- description && /* @__PURE__ */ jsx80("p", { className: "mx-auto mb-[24px] max-w-[320px] text-[13.5px] leading-[1.5] text-text-secondary", children: description }),
5576
- /* @__PURE__ */ jsx80("div", { className: "text-left", children }),
5577
- footer != null && /* @__PURE__ */ jsx80("div", { className: "mt-[24px] text-[11px] tracking-[0.005em] text-text-tertiary", children: footer })
5578
- ]
5579
- }
5580
- )
5581
- ]
5582
- }
5583
- );
5584
- }
5585
-
5586
5860
  // src/components/organization-create-screen.tsx
5587
- import { jsx as jsx81 } from "react/jsx-runtime";
5861
+ import { jsx as jsx84 } from "react/jsx-runtime";
5588
5862
  function OrganizationCreateScreen({
5589
5863
  requireSanctionsFields,
5590
5864
  onSubmit,
@@ -5602,7 +5876,7 @@ function OrganizationCreateScreen({
5602
5876
  footer,
5603
5877
  ...props
5604
5878
  }) {
5605
- return /* @__PURE__ */ jsx81(
5879
+ return /* @__PURE__ */ jsx84(
5606
5880
  OnboardingScreenShell,
5607
5881
  {
5608
5882
  logo,
@@ -5612,7 +5886,7 @@ function OrganizationCreateScreen({
5612
5886
  footer,
5613
5887
  width: "lg",
5614
5888
  ...props,
5615
- children: /* @__PURE__ */ jsx81(
5889
+ children: /* @__PURE__ */ jsx84(
5616
5890
  OrganizationOnboardingForm,
5617
5891
  {
5618
5892
  requireSanctionsFields,
@@ -5631,8 +5905,8 @@ function OrganizationCreateScreen({
5631
5905
  }
5632
5906
 
5633
5907
  // src/components/product-create-screen.tsx
5634
- import * as React66 from "react";
5635
- import { jsx as jsx82, jsxs as jsxs47 } from "react/jsx-runtime";
5908
+ import * as React68 from "react";
5909
+ import { jsx as jsx85, jsxs as jsxs50 } from "react/jsx-runtime";
5636
5910
  var productRow = "flex w-full items-center justify-between rounded-md border border-border-default bg-bg-primary px-3 py-2 text-left text-sm text-text-primary";
5637
5911
  function ProductCreateScreen({
5638
5912
  // Destructured only to keep it out of `...props`, which is spread onto a <div>.
@@ -5658,11 +5932,11 @@ function ProductCreateScreen({
5658
5932
  footer,
5659
5933
  ...props
5660
5934
  }) {
5661
- const [name, setName] = React66.useState(defaultName);
5662
- const submittingRef = React66.useRef(false);
5935
+ const [name, setName] = React68.useState(defaultName);
5936
+ const submittingRef = React68.useRef(false);
5663
5937
  const trimmed = name.trim();
5664
5938
  const canSubmit = trimmed !== "" && !submitting;
5665
- React66.useEffect(() => {
5939
+ React68.useEffect(() => {
5666
5940
  submittingRef.current = false;
5667
5941
  }, [name, submitting, serverError]);
5668
5942
  const handleSubmit = (event) => {
@@ -5674,7 +5948,7 @@ function ProductCreateScreen({
5674
5948
  const products = existingProducts ?? [];
5675
5949
  const orgs = organizations ?? [];
5676
5950
  const pickerLayout = orgs.length > 0;
5677
- const productList = /* @__PURE__ */ jsx82("ul", { className: "flex flex-col gap-1", children: products.map((product) => /* @__PURE__ */ jsx82("li", { children: onOpenProduct ? /* @__PURE__ */ jsxs47(
5951
+ const productList = /* @__PURE__ */ jsx85("ul", { className: "flex flex-col gap-1", children: products.map((product) => /* @__PURE__ */ jsx85("li", { children: onOpenProduct ? /* @__PURE__ */ jsxs50(
5678
5952
  "button",
5679
5953
  {
5680
5954
  type: "button",
@@ -5685,15 +5959,15 @@ function ProductCreateScreen({
5685
5959
  "hover:bg-bg-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus"
5686
5960
  ),
5687
5961
  children: [
5688
- /* @__PURE__ */ jsx82("span", { className: "truncate", children: product.name }),
5689
- product.slug && /* @__PURE__ */ jsx82("span", { className: "ml-2 truncate text-text-tertiary", children: product.slug })
5962
+ /* @__PURE__ */ jsx85("span", { className: "truncate", children: product.name }),
5963
+ product.slug && /* @__PURE__ */ jsx85("span", { className: "ml-2 truncate text-text-tertiary", children: product.slug })
5690
5964
  ]
5691
5965
  }
5692
- ) : /* @__PURE__ */ jsxs47("div", { className: productRow, children: [
5693
- /* @__PURE__ */ jsx82("span", { className: "truncate", children: product.name }),
5694
- product.slug && /* @__PURE__ */ jsx82("span", { className: "ml-2 truncate text-text-tertiary", children: product.slug })
5966
+ ) : /* @__PURE__ */ jsxs50("div", { className: productRow, children: [
5967
+ /* @__PURE__ */ jsx85("span", { className: "truncate", children: product.name }),
5968
+ product.slug && /* @__PURE__ */ jsx85("span", { className: "ml-2 truncate text-text-tertiary", children: product.slug })
5695
5969
  ] }) }, product.id)) });
5696
- return /* @__PURE__ */ jsxs47(
5970
+ return /* @__PURE__ */ jsxs50(
5697
5971
  OnboardingScreenShell,
5698
5972
  {
5699
5973
  logo,
@@ -5703,10 +5977,10 @@ function ProductCreateScreen({
5703
5977
  footer,
5704
5978
  ...props,
5705
5979
  children: [
5706
- pickerLayout && /* @__PURE__ */ jsxs47("div", { className: "mb-4 space-y-4", children: [
5707
- /* @__PURE__ */ jsxs47("div", { className: "space-y-1.5", children: [
5708
- /* @__PURE__ */ jsx82(Label2, { htmlFor: "create-product-org-select", children: "Organization" }),
5709
- /* @__PURE__ */ jsx82(
5980
+ pickerLayout && /* @__PURE__ */ jsxs50("div", { className: "mb-4 space-y-4", children: [
5981
+ /* @__PURE__ */ jsxs50("div", { className: "space-y-1.5", children: [
5982
+ /* @__PURE__ */ jsx85(Label2, { htmlFor: "create-product-org-select", children: "Organization" }),
5983
+ /* @__PURE__ */ jsx85(
5710
5984
  Select,
5711
5985
  {
5712
5986
  id: "create-product-org-select",
@@ -5720,15 +5994,15 @@ function ProductCreateScreen({
5720
5994
  }
5721
5995
  )
5722
5996
  ] }),
5723
- /* @__PURE__ */ jsxs47("div", { "data-testid": "existing-products", className: "space-y-1.5", children: [
5724
- /* @__PURE__ */ jsx82(Label2, { children: existingProductsLabel }),
5725
- productsLoading ? /* @__PURE__ */ jsx82("p", { className: "text-sm text-text-tertiary", children: "Loading products\u2026" }) : products.length === 0 ? /* @__PURE__ */ jsx82("p", { className: "text-sm text-text-tertiary", children: "No products yet." }) : productList
5997
+ /* @__PURE__ */ jsxs50("div", { "data-testid": "existing-products", className: "space-y-1.5", children: [
5998
+ /* @__PURE__ */ jsx85(Label2, { children: existingProductsLabel }),
5999
+ productsLoading ? /* @__PURE__ */ jsx85("p", { className: "text-sm text-text-tertiary", children: "Loading products\u2026" }) : products.length === 0 ? /* @__PURE__ */ jsx85("p", { className: "text-sm text-text-tertiary", children: "No products yet." }) : productList
5726
6000
  ] })
5727
6001
  ] }),
5728
- /* @__PURE__ */ jsxs47("form", { onSubmit: handleSubmit, className: "space-y-4", noValidate: true, children: [
5729
- /* @__PURE__ */ jsxs47("div", { className: "space-y-1.5", children: [
5730
- /* @__PURE__ */ jsx82(Label2, { htmlFor: "create-product-name", children: "Product name" }),
5731
- /* @__PURE__ */ jsx82(
6002
+ /* @__PURE__ */ jsxs50("form", { onSubmit: handleSubmit, className: "space-y-4", noValidate: true, children: [
6003
+ /* @__PURE__ */ jsxs50("div", { className: "space-y-1.5", children: [
6004
+ /* @__PURE__ */ jsx85(Label2, { htmlFor: "create-product-name", children: "Product name" }),
6005
+ /* @__PURE__ */ jsx85(
5732
6006
  Input,
5733
6007
  {
5734
6008
  id: "create-product-name",
@@ -5739,9 +6013,9 @@ function ProductCreateScreen({
5739
6013
  }
5740
6014
  )
5741
6015
  ] }),
5742
- serverError && /* @__PURE__ */ jsx82(InlineError, { children: serverError }),
5743
- /* @__PURE__ */ jsxs47("div", { className: "space-y-2 pt-1", children: [
5744
- /* @__PURE__ */ jsx82(
6016
+ serverError && /* @__PURE__ */ jsx85(InlineError, { children: serverError }),
6017
+ /* @__PURE__ */ jsxs50("div", { className: "space-y-2 pt-1", children: [
6018
+ /* @__PURE__ */ jsx85(
5745
6019
  "button",
5746
6020
  {
5747
6021
  type: "submit",
@@ -5752,16 +6026,16 @@ function ProductCreateScreen({
5752
6026
  children: submitting ? "Creating\u2026" : submitLabel
5753
6027
  }
5754
6028
  ),
5755
- onCancel && /* @__PURE__ */ jsx82("button", { type: "button", onClick: onCancel, className: AUTH_QUIET_BUTTON, children: "Cancel" })
6029
+ onCancel && /* @__PURE__ */ jsx85("button", { type: "button", onClick: onCancel, className: AUTH_QUIET_BUTTON, children: "Cancel" })
5756
6030
  ] })
5757
6031
  ] }),
5758
- !pickerLayout && products.length > 0 && /* @__PURE__ */ jsxs47(
6032
+ !pickerLayout && products.length > 0 && /* @__PURE__ */ jsxs50(
5759
6033
  "div",
5760
6034
  {
5761
6035
  "data-testid": "existing-products",
5762
6036
  className: "mt-6 space-y-2 border-t border-border-default pt-5",
5763
6037
  children: [
5764
- /* @__PURE__ */ jsx82(Label2, { children: existingProductsLabel }),
6038
+ /* @__PURE__ */ jsx85(Label2, { children: existingProductsLabel }),
5765
6039
  productList
5766
6040
  ]
5767
6041
  }
@@ -5797,6 +6071,7 @@ export {
5797
6071
  AvatarFallback,
5798
6072
  AvatarImage,
5799
6073
  Badge,
6074
+ BetaGateScreen,
5800
6075
  Breadcrumb,
5801
6076
  BreadcrumbEllipsis,
5802
6077
  BreadcrumbItem,
@@ -5986,6 +6261,7 @@ export {
5986
6261
  SidebarNav,
5987
6262
  SidebarNavLink,
5988
6263
  SidebarProductHeader,
6264
+ SignupScreen,
5989
6265
  Skeleton,
5990
6266
  Slider,
5991
6267
  StatCard,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lessly/ui",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "description": "Lessly design system — shared UI primitives, tokens, and theme",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.30.3",