@lessly/ui 0.22.0 → 0.23.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,90 @@ 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
+ /** Disables the submit button and swaps its label while the caller's check is in flight. */
1481
+ submitting?: boolean;
1482
+ /** Rendered as an alert above the field — typically a rejected code. */
1483
+ error?: string | null;
1484
+ /** Social sign-in buttons, rendered above an "or" divider. Without it there is no divider. */
1485
+ socialAuth?: React$1.ReactNode;
1486
+ /** Target of the waitlist link in the default description. */
1487
+ waitlistHref?: string;
1488
+ /** Renders "Already have an account? Sign in" as a link. */
1489
+ signInHref?: string;
1490
+ /** Renders the same affordance as a button. Ignored when `signInHref` is given. */
1491
+ onSignIn?: () => void;
1492
+ submitLabel?: React$1.ReactNode;
1493
+ /** Brand mark above the headline. */
1494
+ logo?: React$1.ReactNode;
1495
+ /** Rendered top-right. Defaults to the kit's own `ThemeToggle`; pass your own node to
1496
+ * replace it, or `null` to drop it. */
1497
+ themeToggle?: React$1.ReactNode;
1498
+ title?: React$1.ReactNode;
1499
+ description?: React$1.ReactNode;
1500
+ /** Muted footer signature. Absent by default; pass a node to render one. */
1501
+ footer?: React$1.ReactNode;
1502
+ }
1503
+ /**
1504
+ * The gate in front of registration while the product is in closed beta: a single access
1505
+ * code, optionally preceded by social sign-in. Presentational and self-contained — it never
1506
+ * validates the code, never calls an API and never navigates; the caller handles the
1507
+ * outcome of `onSubmit`.
1508
+ */
1509
+ declare function BetaGateScreen({ onSubmit, defaultCode, submitting, error, socialAuth, waitlistHref, signInHref, onSignIn, submitLabel, logo, themeToggle, title, description, footer, ...props }: BetaGateScreenProps): React$1.JSX.Element;
1510
+
1511
+ /** The submit payload — what a registration endpoint takes, minus anything the caller owns
1512
+ * (the beta code, the invite, the return URL). */
1513
+ interface SignupScreenSubmit {
1514
+ name: string;
1515
+ email: string;
1516
+ password: string;
1517
+ }
1518
+ interface SignupScreenProps extends Omit<React$1.HTMLAttributes<HTMLDivElement>, 'title' | 'onSubmit'> {
1519
+ onSubmit: (payload: SignupScreenSubmit) => void;
1520
+ defaultValues?: Partial<SignupScreenSubmit>;
1521
+ /** Disables the submit button and swaps its label while the caller's request is in flight. */
1522
+ submitting?: boolean;
1523
+ serverError?: string | null;
1524
+ /** Field-level messages returned alongside a server error. */
1525
+ violations?: string[];
1526
+ /** Social sign-in buttons, rendered above an "or continue with email" divider. Not shown
1527
+ * when `children` take over the body. */
1528
+ socialAuth?: React$1.ReactNode;
1529
+ /** Renders "Use a different code" under the form — the way back to the beta gate. */
1530
+ onEditCode?: () => void;
1531
+ /** Renders "Already have an account? Sign in" as a link. */
1532
+ signInHref?: string;
1533
+ /** Renders the same affordance as a button. Ignored when `signInHref` is given. */
1534
+ onSignIn?: () => void;
1535
+ submitLabel?: React$1.ReactNode;
1536
+ /**
1537
+ * Replaces the whole body — social auth, divider, register form and all. This is the seam
1538
+ * the consumer uses to host steps the kit deliberately does not know about (MFA challenge,
1539
+ * TOTP enrolment) inside the same window.
1540
+ */
1541
+ children?: React$1.ReactNode;
1542
+ /** Brand mark above the headline. */
1543
+ logo?: React$1.ReactNode;
1544
+ /** Rendered top-right. Defaults to the kit's own `ThemeToggle`; pass your own node to
1545
+ * replace it, or `null` to drop it. */
1546
+ themeToggle?: React$1.ReactNode;
1547
+ title?: React$1.ReactNode;
1548
+ description?: React$1.ReactNode;
1549
+ /** Muted footer signature. Absent by default; pass a node to render one. */
1550
+ footer?: React$1.ReactNode;
1551
+ }
1552
+ /**
1553
+ * The registration window: social sign-in, then name / email / password. Presentational and
1554
+ * self-contained — it never calls an API and never navigates; the caller handles the outcome
1555
+ * of `onSubmit`. Password rules are checked here because they are the same rules the
1556
+ * registration endpoint enforces, and failing them client-side saves a round trip.
1557
+ */
1558
+ 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;
1559
+
1476
1560
  /** One beneficial owner, in the shape the organization API takes it. */
1477
1561
  interface BeneficialOwnerPayload {
1478
1562
  name: string;
@@ -1622,4 +1706,4 @@ interface ProductCreateScreenProps extends Omit<React$1.HTMLAttributes<HTMLDivEl
1622
1706
  */
1623
1707
  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
1708
 
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 };
1709
+ 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,348 @@ 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
+ /* @__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
+ submitting,
5299
+ error,
5300
+ socialAuth,
5301
+ waitlistHref = DEFAULT_WAITLIST_HREF,
5302
+ signInHref,
5303
+ onSignIn,
5304
+ submitLabel = "Continue",
5305
+ logo,
5306
+ themeToggle,
5307
+ title = "We're in closed beta",
5308
+ description,
5309
+ footer,
5310
+ ...props
5311
+ }) {
5312
+ const [code, setCode] = React65.useState(defaultCode);
5313
+ const submittingRef = React65.useRef(false);
5314
+ const trimmed = code.trim();
5315
+ const canSubmit = trimmed !== "" && !submitting;
5316
+ React65.useEffect(() => {
5317
+ submittingRef.current = false;
5318
+ }, [code, submitting, error]);
5319
+ const handleSubmit = (event) => {
5320
+ event.preventDefault();
5321
+ if (!canSubmit || submittingRef.current) return;
5322
+ submittingRef.current = true;
5323
+ onSubmit(trimmed);
5324
+ };
5325
+ const defaultDescription = /* @__PURE__ */ jsxs47(Fragment9, { children: [
5326
+ "A beta access code is required to join. or",
5327
+ " ",
5328
+ /* @__PURE__ */ jsx81("a", { href: waitlistHref, className: LINK, children: "join the waitlist" }),
5329
+ " ",
5330
+ "to request one."
5331
+ ] });
5332
+ return /* @__PURE__ */ jsxs47(
5333
+ OnboardingScreenShell,
5334
+ {
5335
+ logo,
5336
+ themeToggle,
5337
+ title,
5338
+ description: description ?? defaultDescription,
5339
+ footer,
5340
+ ...props,
5341
+ children: [
5342
+ socialAuth && /* @__PURE__ */ jsxs47(Fragment9, { children: [
5343
+ /* @__PURE__ */ jsx81("div", { "data-testid": "beta-gate-social-auth", children: socialAuth }),
5344
+ /* @__PURE__ */ jsx81(AuthDivider, { label: "or" })
5345
+ ] }),
5346
+ error && /* @__PURE__ */ jsx81(InlineError, { "data-testid": "beta-gate-error", className: "mb-4 text-center", children: error }),
5347
+ /* @__PURE__ */ jsxs47("form", { onSubmit: handleSubmit, className: "space-y-4", noValidate: true, children: [
5348
+ /* @__PURE__ */ jsxs47("div", { className: "space-y-1.5", children: [
5349
+ /* @__PURE__ */ jsx81(Label2, { htmlFor: "beta-code", className: "sr-only", children: "Lessly beta access code" }),
5350
+ /* @__PURE__ */ jsx81(
5351
+ Input,
5352
+ {
5353
+ id: "beta-code",
5354
+ "data-testid": "beta-code-input",
5355
+ value: code,
5356
+ autoComplete: "off",
5357
+ placeholder: "Lessly beta access code",
5358
+ onChange: (event) => setCode(event.target.value)
5359
+ }
5360
+ )
5361
+ ] }),
5362
+ /* @__PURE__ */ jsx81("div", { className: "pt-1", children: /* @__PURE__ */ jsx81(
5363
+ "button",
5364
+ {
5365
+ type: "submit",
5366
+ "data-testid": "submit-beta-code",
5367
+ disabled: !canSubmit,
5368
+ className: AUTH_FILLED_BUTTON,
5369
+ style: { boxShadow: AUTH_BUTTON_SHADOW },
5370
+ children: submitting ? "Checking\u2026" : submitLabel
5371
+ }
5372
+ ) })
5373
+ ] }),
5374
+ (signInHref || onSignIn) && /* @__PURE__ */ jsxs47("p", { className: "mt-5 text-center text-sm text-text-secondary", children: [
5375
+ "Already have an account?",
5376
+ " ",
5377
+ signInHref ? /* @__PURE__ */ jsx81("a", { "data-testid": "beta-gate-signin", href: signInHref, className: LINK, children: "Sign in" }) : /* @__PURE__ */ jsx81(
5378
+ "button",
5379
+ {
5380
+ type: "button",
5381
+ "data-testid": "beta-gate-signin",
5382
+ onClick: onSignIn,
5383
+ className: LINK,
5384
+ children: "Sign in"
5385
+ }
5386
+ )
5387
+ ] })
5388
+ ]
5389
+ }
5390
+ );
5391
+ }
5392
+
5393
+ // src/components/signup-screen.tsx
5394
+ import * as React66 from "react";
5395
+ import { Fragment as Fragment10, jsx as jsx82, jsxs as jsxs48 } from "react/jsx-runtime";
5396
+ var LINK2 = "font-medium text-text-link hover:text-text-link-hover";
5397
+ function SignupScreen({
5398
+ onSubmit,
5399
+ defaultValues,
5400
+ submitting,
5401
+ serverError,
5402
+ violations,
5403
+ socialAuth,
5404
+ onEditCode,
5405
+ signInHref,
5406
+ onSignIn,
5407
+ submitLabel = "Create account",
5408
+ children,
5409
+ logo,
5410
+ themeToggle,
5411
+ title = "Create your account",
5412
+ description,
5413
+ footer,
5414
+ ...props
5415
+ }) {
5416
+ const [name, setName] = React66.useState(defaultValues?.name ?? "");
5417
+ const [email, setEmail] = React66.useState(defaultValues?.email ?? "");
5418
+ const [password, setPassword] = React66.useState(defaultValues?.password ?? "");
5419
+ const [passwordError, setPasswordError] = React66.useState(null);
5420
+ const submittingRef = React66.useRef(false);
5421
+ const trimmedName = name.trim();
5422
+ const trimmedEmail = email.trim();
5423
+ const canSubmit = trimmedName !== "" && trimmedEmail !== "" && password !== "" && !submitting;
5424
+ React66.useEffect(() => {
5425
+ submittingRef.current = false;
5426
+ }, [name, email, password, submitting, serverError]);
5427
+ const handleSubmit = (event) => {
5428
+ event.preventDefault();
5429
+ if (!canSubmit || submittingRef.current) return;
5430
+ const failure = validatePassword(password);
5431
+ if (failure) {
5432
+ setPasswordError(failure);
5433
+ return;
5434
+ }
5435
+ setPasswordError(null);
5436
+ submittingRef.current = true;
5437
+ onSubmit({ name: trimmedName, email: trimmedEmail, password });
5438
+ };
5439
+ const body = children ?? /* @__PURE__ */ jsxs48(Fragment10, { children: [
5440
+ socialAuth && /* @__PURE__ */ jsxs48(Fragment10, { children: [
5441
+ /* @__PURE__ */ jsx82("div", { "data-testid": "signup-social-auth", children: socialAuth }),
5442
+ /* @__PURE__ */ jsx82(AuthDivider, { label: "or continue with email" })
5443
+ ] }),
5444
+ /* @__PURE__ */ jsxs48("form", { onSubmit: handleSubmit, className: "space-y-4", noValidate: true, children: [
5445
+ /* @__PURE__ */ jsxs48("div", { className: "space-y-1.5", children: [
5446
+ /* @__PURE__ */ jsx82(Label2, { htmlFor: "signup-name", children: "Full name" }),
5447
+ /* @__PURE__ */ jsx82(
5448
+ Input,
5449
+ {
5450
+ id: "signup-name",
5451
+ "data-testid": "signup-name",
5452
+ value: name,
5453
+ disabled: submitting,
5454
+ placeholder: "Jane Smith",
5455
+ onChange: (event) => setName(event.target.value)
5456
+ }
5457
+ )
5458
+ ] }),
5459
+ /* @__PURE__ */ jsxs48("div", { className: "space-y-1.5", children: [
5460
+ /* @__PURE__ */ jsx82(Label2, { htmlFor: "signup-email", children: "Email" }),
5461
+ /* @__PURE__ */ jsx82(
5462
+ Input,
5463
+ {
5464
+ id: "signup-email",
5465
+ "data-testid": "signup-email",
5466
+ type: "email",
5467
+ value: email,
5468
+ disabled: submitting,
5469
+ autoComplete: "email",
5470
+ placeholder: "you@example.com",
5471
+ onChange: (event) => setEmail(event.target.value)
5472
+ }
5473
+ )
5474
+ ] }),
5475
+ /* @__PURE__ */ jsxs48("div", { className: "space-y-1.5", children: [
5476
+ /* @__PURE__ */ jsx82(Label2, { htmlFor: "signup-password", children: "Password" }),
5477
+ /* @__PURE__ */ jsx82(
5478
+ Input,
5479
+ {
5480
+ id: "signup-password",
5481
+ "data-testid": "signup-password",
5482
+ type: "password",
5483
+ value: password,
5484
+ disabled: submitting,
5485
+ autoComplete: "new-password",
5486
+ placeholder: "Min 8 chars, 1 uppercase, 1 number",
5487
+ onChange: (event) => {
5488
+ setPassword(event.target.value);
5489
+ if (passwordError) setPasswordError(null);
5490
+ }
5491
+ }
5492
+ )
5493
+ ] }),
5494
+ passwordError && /* @__PURE__ */ jsx82(InlineError, { "data-testid": "signup-password-error", children: passwordError }),
5495
+ (serverError || violations && violations.length > 0) && /* @__PURE__ */ jsxs48(InlineError, { "data-testid": "signup-error", children: [
5496
+ serverError,
5497
+ 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)) })
5498
+ ] }),
5499
+ /* @__PURE__ */ jsx82("div", { className: "pt-1", children: /* @__PURE__ */ jsx82(
5500
+ "button",
5501
+ {
5502
+ type: "submit",
5503
+ "data-testid": "submit-signup",
5504
+ disabled: !canSubmit,
5505
+ className: AUTH_FILLED_BUTTON,
5506
+ style: { boxShadow: AUTH_BUTTON_SHADOW },
5507
+ children: submitting ? "Creating account\u2026" : submitLabel
5508
+ }
5509
+ ) })
5510
+ ] }),
5511
+ onEditCode && /* @__PURE__ */ jsx82("p", { className: "mt-4 text-center text-sm text-text-secondary", children: /* @__PURE__ */ jsx82(
5512
+ "button",
5513
+ {
5514
+ type: "button",
5515
+ "data-testid": "signup-edit-code",
5516
+ onClick: onEditCode,
5517
+ className: LINK2,
5518
+ children: "Use a different code"
5519
+ }
5520
+ ) })
5521
+ ] });
5522
+ return /* @__PURE__ */ jsxs48(
5523
+ OnboardingScreenShell,
5524
+ {
5525
+ logo,
5526
+ themeToggle,
5527
+ title,
5528
+ description,
5529
+ footer,
5530
+ ...props,
5531
+ children: [
5532
+ body,
5533
+ (signInHref || onSignIn) && /* @__PURE__ */ jsxs48("p", { className: "mt-5 text-center text-sm text-text-secondary", children: [
5534
+ "Already have an account?",
5535
+ " ",
5536
+ 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" })
5537
+ ] })
5538
+ ]
5539
+ }
5540
+ );
5541
+ }
5542
+ function validatePassword(password) {
5543
+ if (password.length < 8) return "Password must be at least 8 characters.";
5544
+ if (!/[A-Z]/.test(password)) return "Password must contain at least 1 uppercase letter.";
5545
+ if (!/[0-9]/.test(password)) return "Password must contain at least 1 number.";
5546
+ return null;
5547
+ }
5548
+
5219
5549
  // src/components/organization-onboarding-form.tsx
5220
- import { jsx as jsx79, jsxs as jsxs45 } from "react/jsx-runtime";
5550
+ import * as React67 from "react";
5551
+ import { jsx as jsx83, jsxs as jsxs49 } from "react/jsx-runtime";
5221
5552
  var CONTROLLER_SHARE_PCT = 50;
5222
5553
  var MAX_BENEFICIAL_OWNERS = 50;
5223
5554
  function parseShare(raw) {
@@ -5248,21 +5579,21 @@ function OrganizationOnboardingForm({
5248
5579
  onCancel,
5249
5580
  className
5250
5581
  }) {
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(
5582
+ const [name, setName] = React67.useState(defaultValues?.name ?? "");
5583
+ const [legalName, setLegalName] = React67.useState(defaultValues?.legal_name ?? "");
5584
+ const [ownerName, setOwnerName] = React67.useState(defaultValues?.owner_name ?? "");
5585
+ const [countryOfIncorporation, setCountryOfIncorporation] = React67.useState(
5255
5586
  defaultValues?.country_of_incorporation ?? ""
5256
5587
  );
5257
- const [residencyCountry, setResidencyCountry] = React65.useState(
5588
+ const [residencyCountry, setResidencyCountry] = React67.useState(
5258
5589
  defaultValues?.residency_country ?? ""
5259
5590
  );
5260
- const [owners, setOwners] = React65.useState(
5591
+ const [owners, setOwners] = React67.useState(
5261
5592
  () => initialRows(defaultValues?.beneficial_owners)
5262
5593
  );
5263
- const [ownershipConfirmed, setOwnershipConfirmed] = React65.useState(false);
5264
- const nextKeyRef = React65.useRef(owners.length);
5265
- const submittingRef = React65.useRef(false);
5594
+ const [ownershipConfirmed, setOwnershipConfirmed] = React67.useState(false);
5595
+ const nextKeyRef = React67.useRef(owners.length);
5596
+ const submittingRef = React67.useRef(false);
5266
5597
  const trimmed = name.trim();
5267
5598
  const filledOwners = owners.filter((row) => !isRowBlank(row));
5268
5599
  const ownerShares = filledOwners.map((row) => parseShare(row.share));
@@ -5307,7 +5638,7 @@ function OrganizationOnboardingForm({
5307
5638
  ...needsOwnershipConfirmation ? { ownership_confirmed: ownershipConfirmed } : {}
5308
5639
  });
5309
5640
  };
5310
- React65.useEffect(() => {
5641
+ React67.useEffect(() => {
5311
5642
  submittingRef.current = false;
5312
5643
  }, [
5313
5644
  name,
@@ -5320,12 +5651,12 @@ function OrganizationOnboardingForm({
5320
5651
  submitting,
5321
5652
  serverError
5322
5653
  ]);
5323
- const countryField = (params) => /* @__PURE__ */ jsxs45("div", { className: "space-y-1.5", children: [
5324
- /* @__PURE__ */ jsxs45(Label2, { htmlFor: params.id, children: [
5654
+ const countryField = (params) => /* @__PURE__ */ jsxs49("div", { className: "space-y-1.5", children: [
5655
+ /* @__PURE__ */ jsxs49(Label2, { htmlFor: params.id, children: [
5325
5656
  params.label,
5326
- params.required && /* @__PURE__ */ jsx79("span", { className: "text-text-danger", children: " *" })
5657
+ params.required && /* @__PURE__ */ jsx83("span", { className: "text-text-danger", children: " *" })
5327
5658
  ] }),
5328
- /* @__PURE__ */ jsx79(
5659
+ /* @__PURE__ */ jsx83(
5329
5660
  Select,
5330
5661
  {
5331
5662
  id: params.id,
@@ -5338,10 +5669,10 @@ function OrganizationOnboardingForm({
5338
5669
  }
5339
5670
  )
5340
5671
  ] });
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(
5672
+ return /* @__PURE__ */ jsxs49("form", { onSubmit: handleSubmit, className: cn("space-y-4", className), children: [
5673
+ /* @__PURE__ */ jsxs49("div", { className: "space-y-1.5", children: [
5674
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: "create-org-name", children: "Organization name" }),
5675
+ /* @__PURE__ */ jsx83(
5345
5676
  Input,
5346
5677
  {
5347
5678
  id: "create-org-name",
@@ -5352,9 +5683,9 @@ function OrganizationOnboardingForm({
5352
5683
  }
5353
5684
  )
5354
5685
  ] }),
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(
5686
+ /* @__PURE__ */ jsxs49("div", { className: "space-y-1.5", children: [
5687
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: "create-org-legal-name", children: "Legal name" }),
5688
+ /* @__PURE__ */ jsx83(
5358
5689
  Input,
5359
5690
  {
5360
5691
  id: "create-org-legal-name",
@@ -5365,9 +5696,9 @@ function OrganizationOnboardingForm({
5365
5696
  }
5366
5697
  )
5367
5698
  ] }),
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(
5699
+ /* @__PURE__ */ jsxs49("div", { className: "space-y-1.5", children: [
5700
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: "create-org-owner-name", children: "Owner name" }),
5701
+ /* @__PURE__ */ jsx83(
5371
5702
  Input,
5372
5703
  {
5373
5704
  id: "create-org-owner-name",
@@ -5392,10 +5723,10 @@ function OrganizationOnboardingForm({
5392
5723
  onChange: setResidencyCountry,
5393
5724
  required: false
5394
5725
  }),
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(
5726
+ /* @__PURE__ */ jsxs49("div", { className: "space-y-2", children: [
5727
+ /* @__PURE__ */ jsxs49("div", { className: "flex items-center justify-between", children: [
5728
+ /* @__PURE__ */ jsx83(Label2, { children: "Beneficial owners" }),
5729
+ /* @__PURE__ */ jsx83(
5399
5730
  Button,
5400
5731
  {
5401
5732
  type: "button",
@@ -5408,16 +5739,16 @@ function OrganizationOnboardingForm({
5408
5739
  }
5409
5740
  )
5410
5741
  ] }),
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(
5742
+ owners.length === 0 && /* @__PURE__ */ jsx83("p", { className: "text-xs text-text-tertiary", children: "List the natural persons who ultimately own or control the organization." }),
5743
+ owners.map((row) => /* @__PURE__ */ jsxs49(
5413
5744
  "div",
5414
5745
  {
5415
5746
  "data-testid": `beneficial-owner-row-${row.key}`,
5416
5747
  className: "flex items-end gap-2",
5417
5748
  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(
5749
+ /* @__PURE__ */ jsxs49("div", { className: "flex-1 space-y-1", children: [
5750
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: `bo-name-${row.key}`, className: "text-xs", children: "Name" }),
5751
+ /* @__PURE__ */ jsx83(
5421
5752
  Input,
5422
5753
  {
5423
5754
  id: `bo-name-${row.key}`,
@@ -5427,9 +5758,9 @@ function OrganizationOnboardingForm({
5427
5758
  }
5428
5759
  )
5429
5760
  ] }),
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(
5761
+ /* @__PURE__ */ jsxs49("div", { className: "w-40 space-y-1", children: [
5762
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: `bo-country-${row.key}`, className: "text-xs", children: "Country" }),
5763
+ /* @__PURE__ */ jsx83(
5433
5764
  Select,
5434
5765
  {
5435
5766
  id: `bo-country-${row.key}`,
@@ -5442,9 +5773,9 @@ function OrganizationOnboardingForm({
5442
5773
  }
5443
5774
  )
5444
5775
  ] }),
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(
5776
+ /* @__PURE__ */ jsxs49("div", { className: "w-24 space-y-1", children: [
5777
+ /* @__PURE__ */ jsx83(Label2, { htmlFor: `bo-share-${row.key}`, className: "text-xs", children: "Share %" }),
5778
+ /* @__PURE__ */ jsx83(
5448
5779
  Input,
5449
5780
  {
5450
5781
  id: `bo-share-${row.key}`,
@@ -5455,7 +5786,7 @@ function OrganizationOnboardingForm({
5455
5786
  }
5456
5787
  )
5457
5788
  ] }),
5458
- /* @__PURE__ */ jsx79(
5789
+ /* @__PURE__ */ jsx83(
5459
5790
  Button,
5460
5791
  {
5461
5792
  type: "button",
@@ -5470,15 +5801,15 @@ function OrganizationOnboardingForm({
5470
5801
  },
5471
5802
  row.key
5472
5803
  )),
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: [
5804
+ !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." }),
5805
+ shareSum > 100 && /* @__PURE__ */ jsxs49("p", { "data-testid": "beneficial-owners-sum-warning", className: "text-xs text-text-warning", children: [
5475
5806
  "The listed shares add up to ",
5476
5807
  shareSum,
5477
5808
  "%, which is more than 100%."
5478
5809
  ] })
5479
5810
  ] }),
5480
- needsOwnershipConfirmation && /* @__PURE__ */ jsxs45("div", { className: "flex items-start gap-2", children: [
5481
- /* @__PURE__ */ jsx79(
5811
+ needsOwnershipConfirmation && /* @__PURE__ */ jsxs49("div", { className: "flex items-start gap-2", children: [
5812
+ /* @__PURE__ */ jsx83(
5482
5813
  Checkbox,
5483
5814
  {
5484
5815
  id: "create-org-ownership-confirmed",
@@ -5487,24 +5818,24 @@ function OrganizationOnboardingForm({
5487
5818
  onCheckedChange: (value) => setOwnershipConfirmed(value === true)
5488
5819
  }
5489
5820
  ),
5490
- /* @__PURE__ */ jsxs45(
5821
+ /* @__PURE__ */ jsxs49(
5491
5822
  Label2,
5492
5823
  {
5493
5824
  htmlFor: "create-org-ownership-confirmed",
5494
5825
  className: "text-xs font-normal leading-snug",
5495
5826
  children: [
5496
5827
  "I confirm the ownership structure above is complete and correct",
5497
- requireSanctionsFields && /* @__PURE__ */ jsx79("span", { className: "text-text-danger", children: " *" })
5828
+ requireSanctionsFields && /* @__PURE__ */ jsx83("span", { className: "text-text-danger", children: " *" })
5498
5829
  ]
5499
5830
  }
5500
5831
  )
5501
5832
  ] }),
5502
- (serverError || violations && violations.length > 0) && /* @__PURE__ */ jsxs45(InlineError, { children: [
5833
+ (serverError || violations && violations.length > 0) && /* @__PURE__ */ jsxs49(InlineError, { children: [
5503
5834
  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)) })
5835
+ 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
5836
  ] }),
5506
- /* @__PURE__ */ jsxs45("div", { className: "space-y-2 pt-1", children: [
5507
- /* @__PURE__ */ jsx79(
5837
+ /* @__PURE__ */ jsxs49("div", { className: "space-y-2 pt-1", children: [
5838
+ /* @__PURE__ */ jsx83(
5508
5839
  "button",
5509
5840
  {
5510
5841
  type: "submit",
@@ -5515,76 +5846,13 @@ function OrganizationOnboardingForm({
5515
5846
  children: submitting ? "Creating\u2026" : submitLabel
5516
5847
  }
5517
5848
  ),
5518
- onCancel && /* @__PURE__ */ jsx79("button", { type: "button", onClick: onCancel, className: AUTH_QUIET_BUTTON, children: "Cancel" })
5849
+ onCancel && /* @__PURE__ */ jsx83("button", { type: "button", onClick: onCancel, className: AUTH_QUIET_BUTTON, children: "Cancel" })
5519
5850
  ] })
5520
5851
  ] });
5521
5852
  }
5522
5853
 
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
5854
  // src/components/organization-create-screen.tsx
5587
- import { jsx as jsx81 } from "react/jsx-runtime";
5855
+ import { jsx as jsx84 } from "react/jsx-runtime";
5588
5856
  function OrganizationCreateScreen({
5589
5857
  requireSanctionsFields,
5590
5858
  onSubmit,
@@ -5602,7 +5870,7 @@ function OrganizationCreateScreen({
5602
5870
  footer,
5603
5871
  ...props
5604
5872
  }) {
5605
- return /* @__PURE__ */ jsx81(
5873
+ return /* @__PURE__ */ jsx84(
5606
5874
  OnboardingScreenShell,
5607
5875
  {
5608
5876
  logo,
@@ -5612,7 +5880,7 @@ function OrganizationCreateScreen({
5612
5880
  footer,
5613
5881
  width: "lg",
5614
5882
  ...props,
5615
- children: /* @__PURE__ */ jsx81(
5883
+ children: /* @__PURE__ */ jsx84(
5616
5884
  OrganizationOnboardingForm,
5617
5885
  {
5618
5886
  requireSanctionsFields,
@@ -5631,8 +5899,8 @@ function OrganizationCreateScreen({
5631
5899
  }
5632
5900
 
5633
5901
  // src/components/product-create-screen.tsx
5634
- import * as React66 from "react";
5635
- import { jsx as jsx82, jsxs as jsxs47 } from "react/jsx-runtime";
5902
+ import * as React68 from "react";
5903
+ import { jsx as jsx85, jsxs as jsxs50 } from "react/jsx-runtime";
5636
5904
  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
5905
  function ProductCreateScreen({
5638
5906
  // Destructured only to keep it out of `...props`, which is spread onto a <div>.
@@ -5658,11 +5926,11 @@ function ProductCreateScreen({
5658
5926
  footer,
5659
5927
  ...props
5660
5928
  }) {
5661
- const [name, setName] = React66.useState(defaultName);
5662
- const submittingRef = React66.useRef(false);
5929
+ const [name, setName] = React68.useState(defaultName);
5930
+ const submittingRef = React68.useRef(false);
5663
5931
  const trimmed = name.trim();
5664
5932
  const canSubmit = trimmed !== "" && !submitting;
5665
- React66.useEffect(() => {
5933
+ React68.useEffect(() => {
5666
5934
  submittingRef.current = false;
5667
5935
  }, [name, submitting, serverError]);
5668
5936
  const handleSubmit = (event) => {
@@ -5674,7 +5942,7 @@ function ProductCreateScreen({
5674
5942
  const products = existingProducts ?? [];
5675
5943
  const orgs = organizations ?? [];
5676
5944
  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(
5945
+ const productList = /* @__PURE__ */ jsx85("ul", { className: "flex flex-col gap-1", children: products.map((product) => /* @__PURE__ */ jsx85("li", { children: onOpenProduct ? /* @__PURE__ */ jsxs50(
5678
5946
  "button",
5679
5947
  {
5680
5948
  type: "button",
@@ -5685,15 +5953,15 @@ function ProductCreateScreen({
5685
5953
  "hover:bg-bg-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus"
5686
5954
  ),
5687
5955
  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 })
5956
+ /* @__PURE__ */ jsx85("span", { className: "truncate", children: product.name }),
5957
+ product.slug && /* @__PURE__ */ jsx85("span", { className: "ml-2 truncate text-text-tertiary", children: product.slug })
5690
5958
  ]
5691
5959
  }
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 })
5960
+ ) : /* @__PURE__ */ jsxs50("div", { className: productRow, children: [
5961
+ /* @__PURE__ */ jsx85("span", { className: "truncate", children: product.name }),
5962
+ product.slug && /* @__PURE__ */ jsx85("span", { className: "ml-2 truncate text-text-tertiary", children: product.slug })
5695
5963
  ] }) }, product.id)) });
5696
- return /* @__PURE__ */ jsxs47(
5964
+ return /* @__PURE__ */ jsxs50(
5697
5965
  OnboardingScreenShell,
5698
5966
  {
5699
5967
  logo,
@@ -5703,10 +5971,10 @@ function ProductCreateScreen({
5703
5971
  footer,
5704
5972
  ...props,
5705
5973
  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(
5974
+ pickerLayout && /* @__PURE__ */ jsxs50("div", { className: "mb-4 space-y-4", children: [
5975
+ /* @__PURE__ */ jsxs50("div", { className: "space-y-1.5", children: [
5976
+ /* @__PURE__ */ jsx85(Label2, { htmlFor: "create-product-org-select", children: "Organization" }),
5977
+ /* @__PURE__ */ jsx85(
5710
5978
  Select,
5711
5979
  {
5712
5980
  id: "create-product-org-select",
@@ -5720,15 +5988,15 @@ function ProductCreateScreen({
5720
5988
  }
5721
5989
  )
5722
5990
  ] }),
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
5991
+ /* @__PURE__ */ jsxs50("div", { "data-testid": "existing-products", className: "space-y-1.5", children: [
5992
+ /* @__PURE__ */ jsx85(Label2, { children: existingProductsLabel }),
5993
+ 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
5994
  ] })
5727
5995
  ] }),
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(
5996
+ /* @__PURE__ */ jsxs50("form", { onSubmit: handleSubmit, className: "space-y-4", noValidate: true, children: [
5997
+ /* @__PURE__ */ jsxs50("div", { className: "space-y-1.5", children: [
5998
+ /* @__PURE__ */ jsx85(Label2, { htmlFor: "create-product-name", children: "Product name" }),
5999
+ /* @__PURE__ */ jsx85(
5732
6000
  Input,
5733
6001
  {
5734
6002
  id: "create-product-name",
@@ -5739,9 +6007,9 @@ function ProductCreateScreen({
5739
6007
  }
5740
6008
  )
5741
6009
  ] }),
5742
- serverError && /* @__PURE__ */ jsx82(InlineError, { children: serverError }),
5743
- /* @__PURE__ */ jsxs47("div", { className: "space-y-2 pt-1", children: [
5744
- /* @__PURE__ */ jsx82(
6010
+ serverError && /* @__PURE__ */ jsx85(InlineError, { children: serverError }),
6011
+ /* @__PURE__ */ jsxs50("div", { className: "space-y-2 pt-1", children: [
6012
+ /* @__PURE__ */ jsx85(
5745
6013
  "button",
5746
6014
  {
5747
6015
  type: "submit",
@@ -5752,16 +6020,16 @@ function ProductCreateScreen({
5752
6020
  children: submitting ? "Creating\u2026" : submitLabel
5753
6021
  }
5754
6022
  ),
5755
- onCancel && /* @__PURE__ */ jsx82("button", { type: "button", onClick: onCancel, className: AUTH_QUIET_BUTTON, children: "Cancel" })
6023
+ onCancel && /* @__PURE__ */ jsx85("button", { type: "button", onClick: onCancel, className: AUTH_QUIET_BUTTON, children: "Cancel" })
5756
6024
  ] })
5757
6025
  ] }),
5758
- !pickerLayout && products.length > 0 && /* @__PURE__ */ jsxs47(
6026
+ !pickerLayout && products.length > 0 && /* @__PURE__ */ jsxs50(
5759
6027
  "div",
5760
6028
  {
5761
6029
  "data-testid": "existing-products",
5762
6030
  className: "mt-6 space-y-2 border-t border-border-default pt-5",
5763
6031
  children: [
5764
- /* @__PURE__ */ jsx82(Label2, { children: existingProductsLabel }),
6032
+ /* @__PURE__ */ jsx85(Label2, { children: existingProductsLabel }),
5765
6033
  productList
5766
6034
  ]
5767
6035
  }
@@ -5797,6 +6065,7 @@ export {
5797
6065
  AvatarFallback,
5798
6066
  AvatarImage,
5799
6067
  Badge,
6068
+ BetaGateScreen,
5800
6069
  Breadcrumb,
5801
6070
  BreadcrumbEllipsis,
5802
6071
  BreadcrumbItem,
@@ -5986,6 +6255,7 @@ export {
5986
6255
  SidebarNav,
5987
6256
  SidebarNavLink,
5988
6257
  SidebarProductHeader,
6258
+ SignupScreen,
5989
6259
  Skeleton,
5990
6260
  Slider,
5991
6261
  StatCard,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lessly/ui",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "Lessly design system — shared UI primitives, tokens, and theme",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.30.3",