@betterinternship/components 2.9.1 → 2.9.3
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/components/ui/accordion.js +1 -1
- package/dist/components/ui/accordion.js.map +1 -1
- package/dist/components/ui/app-header.js.map +1 -1
- package/dist/components/ui/checkbox.js +1 -1
- package/dist/components/ui/checkbox.js.map +1 -1
- package/dist/components/ui/fab.js +9 -9
- package/dist/config.d.ts +6 -6
- package/dist/config.js +9 -9
- package/dist/hooks/useClientProcess.d.ts +69 -69
- package/dist/hooks/useClientProcess.js +255 -255
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@ function AccordionItem({ className, ...props }) {
|
|
|
10
10
|
return (jsx(AccordionPrimitive.Item, { "data-slot": "accordion-item", className: cn('border-b last:border-b-0', className), ...props }));
|
|
11
11
|
}
|
|
12
12
|
function AccordionTrigger({ className, children, ...props }) {
|
|
13
|
-
return (jsx(AccordionPrimitive.Header, { className: "flex", children: jsxs(AccordionPrimitive.Trigger, { "data-slot": "accordion-trigger", className: cn('focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-
|
|
13
|
+
return (jsx(AccordionPrimitive.Header, { className: "flex", children: jsxs(AccordionPrimitive.Trigger, { "data-slot": "accordion-trigger", className: cn('focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-[0.33em] py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180', className), ...props, children: [children, jsx(ChevronDownIcon, { className: "text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" })] }) }));
|
|
14
14
|
}
|
|
15
15
|
function AccordionContent({ className, children, ...props }) {
|
|
16
16
|
return (jsx(AccordionPrimitive.Content, { "data-slot": "accordion-content", className: "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm", ...props, children: jsx("div", { className: cn('pt-0 pb-4', className), children: children }) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accordion.js","sources":["../../../src/components/ui/accordion.tsx"],"sourcesContent":["import * as React from 'react';\nimport * as AccordionPrimitive from '@radix-ui/react-accordion';\nimport { ChevronDownIcon } from 'lucide-react';\n\nimport { cn } from '@/utils';\n\nfunction Accordion({\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Root>) {\n return <AccordionPrimitive.Root data-slot=\"accordion\" {...props} />;\n}\n\nfunction AccordionItem({\n className,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Item>) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn('border-b last:border-b-0', className)}\n {...props}\n />\n );\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n 'focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-
|
|
1
|
+
{"version":3,"file":"accordion.js","sources":["../../../src/components/ui/accordion.tsx"],"sourcesContent":["import * as React from 'react';\nimport * as AccordionPrimitive from '@radix-ui/react-accordion';\nimport { ChevronDownIcon } from 'lucide-react';\n\nimport { cn } from '@/utils';\n\nfunction Accordion({\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Root>) {\n return <AccordionPrimitive.Root data-slot=\"accordion\" {...props} />;\n}\n\nfunction AccordionItem({\n className,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Item>) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn('border-b last:border-b-0', className)}\n {...props}\n />\n );\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n 'focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-[0.33em] py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180',\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDownIcon className=\"text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n );\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Content>) {\n return (\n <AccordionPrimitive.Content\n data-slot=\"accordion-content\"\n className=\"data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm\"\n {...props}\n >\n <div className={cn('pt-0 pb-4', className)}>{children}</div>\n </AccordionPrimitive.Content>\n );\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n"],"names":["_jsx","_jsxs"],"mappings":";;;;;AAMA,SAAS,SAAS,CAAC,EACjB,GAAG,KAAK,EAC6C,EAAA;IACrD,OAAOA,GAAA,CAAC,kBAAkB,CAAC,IAAI,iBAAW,WAAW,EAAA,GAAK,KAAK,EAAA,CAAI;AACrE;AAEA,SAAS,aAAa,CAAC,EACrB,SAAS,EACT,GAAG,KAAK,EAC6C,EAAA;IACrD,QACEA,IAAC,kBAAkB,CAAC,IAAI,EAAA,EAAA,WAAA,EACZ,gBAAgB,EAC1B,SAAS,EAAE,EAAE,CAAC,0BAA0B,EAAE,SAAS,CAAC,KAChD,KAAK,EAAA,CACT;AAEN;AAEA,SAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACgD,EAAA;AACxD,IAAA,QACEA,GAAA,CAAC,kBAAkB,CAAC,MAAM,EAAA,EAAC,SAAS,EAAC,MAAM,EAAA,QAAA,EACzCC,IAAA,CAAC,kBAAkB,CAAC,OAAO,iBACf,mBAAmB,EAC7B,SAAS,EAAE,EAAE,CACX,kTAAkT,EAClT,SAAS,CACV,KACG,KAAK,EAAA,QAAA,EAAA,CAER,QAAQ,EACTD,GAAA,CAAC,eAAe,EAAA,EAAC,SAAS,EAAC,6GAA6G,GAAG,CAAA,EAAA,CAChH,EAAA,CACH;AAEhC;AAEA,SAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACgD,EAAA;AACxD,IAAA,QACEA,GAAA,CAAC,kBAAkB,CAAC,OAAO,EAAA,EAAA,WAAA,EACf,mBAAmB,EAC7B,SAAS,EAAC,2GAA2G,EAAA,GACjH,KAAK,EAAA,QAAA,EAETA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,EAAA,QAAA,EAAG,QAAQ,EAAA,CAAO,EAAA,CACjC;AAEjC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-header.js","sources":["../../../src/components/ui/app-header.tsx"],"sourcesContent":["import Link from 'next/link';\nimport Image from 'next/image';\nimport { usePathname, useRouter } from 'next/navigation';\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\nimport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n} from '@/components/ui/dropdown-menu';\nimport { Button } from '@/components/ui/button';\nimport { Separator } from '@/components/ui/separator';\nimport { cn } from '@/utils';\nimport {\n LogOut,\n Menu,\n Search,\n X,\n UserRound,\n ChevronDown,\n ChevronRight,\n Handshake,\n Mail,\n History,\n FileText,\n Users,\n LayoutDashboard,\n FileSignature,\n GraduationCap,\n Building2,\n SearchCheck,\n} from 'lucide-react';\nimport { useState, useEffect } from 'react';\nimport type { ReactNode } from 'react';\nimport type { LucideIcon } from 'lucide-react';\n\nexport interface NavItem {\n href: string;\n label: string;\n badge?: number;\n icon?: LucideIcon;\n}\n\ninterface AppHeaderProps {\n /** Optional site name. */\n siteName?: string;\n homeHref: string;\n nav: NavItem[];\n userPrimary?: string;\n userSecondary?: string;\n logout: () => Promise<unknown>;\n postLogoutPath: string;\n profileHref?: string;\n userAvatarUrl?: string | null;\n accountNav?: NavItem[];\n /** Overrides the hardcoded \"Partners\" brand text. */\n brand?: string;\n /** Overrides the hardcoded \"/betterinternship-logo.png\" logo path. */\n logoPath?: string;\n /** Extra controls rendered next to the nav (desktop) and inside the drawer (mobile). */\n actions?: ReactNode;\n /**\n * Inline search control rendered in the header's center region on desktop\n * (`md` and up only). Purely a layout slot — the consumer owns all search\n * state and behavior. For mobile, pair with `onSearchClick`.\n */\n search?: ReactNode;\n /**\n * When set, renders a search icon button on mobile immediately left of the\n * hamburger. Typically opens a full-screen search overlay owned by the\n * consumer.\n */\n onSearchClick?: () => void;\n /**\n * Set to false to hide the mobile hamburger button and its side drawer\n * entirely — for consumers that provide their own mobile navigation (e.g.\n * a bottom tab bar) and don't want the nav/profile/logout items duplicated.\n * Defaults to true.\n */\n showMobileMenu?: boolean;\n}\n\nfunction labelIcon(label: string): LucideIcon {\n const map: Record<string, LucideIcon> = {\n Partners: Handshake,\n Invites: Mail,\n Invitations: Mail,\n Accounts: Users,\n 'Activity Log': History,\n 'MOA Templates': FileText,\n Universities: GraduationCap,\n Companies: Building2,\n 'Company Reviews': SearchCheck,\n 'Request MOA': FileSignature,\n Dashboard: LayoutDashboard,\n };\n return map[label] ?? Handshake;\n}\n\nexport function AppHeader({\n siteName,\n homeHref,\n nav,\n userPrimary,\n userSecondary,\n logout: logoutFn,\n postLogoutPath,\n profileHref,\n userAvatarUrl,\n accountNav = [],\n brand = 'Partners',\n logoPath = '/betterinternship-logo.png',\n actions,\n search,\n onSearchClick,\n showMobileMenu = true,\n}: AppHeaderProps) {\n const pathname = usePathname() ?? '';\n const router = useRouter();\n const queryClient = useQueryClient();\n const [isDrawerOpen, setIsDrawerOpen] = useState(false);\n\n useEffect(() => {\n setIsDrawerOpen(false);\n }, [pathname]);\n\n useEffect(() => {\n document.body.style.overflow = isDrawerOpen ? 'hidden' : '';\n return () => {\n document.body.style.overflow = '';\n };\n }, [isDrawerOpen]);\n\n const logout = useMutation({\n mutationFn: logoutFn,\n onSettled: () => {\n queryClient.clear();\n router.replace(postLogoutPath);\n },\n });\n\n const isActive = (href: string) =>\n pathname === href || pathname.startsWith(`${href}/`);\n\n return (\n <header className=\"bg-background/70 sticky top-0 z-40 border-b py-1 md:py-2 backdrop-blur\">\n <div className=\"mx-auto flex h-14 items-center justify-between gap-2 px-4 sm:px-6 lg:px-8 md:h-16\">\n {/* Brand */}\n <Link\n href={homeHref}\n aria-label={brand}\n className=\"block shrink-0 border-none text-black! outline-none focus:outline-none\"\n >\n <div className=\"flex items-center gap-2\">\n <Image\n src={logoPath}\n alt=\"\"\n width={25}\n height={25}\n className=\"flex-none\"\n />\n {/* Wordmark hides below md — the logo carries the link, which keeps\n its name via the aria-label above. */}\n <div className=\"hidden items-center md:flex\">\n <h1 className=\"font-display text-lg font-bold text-gray-900\">\n {brand}\n </h1>\n {siteName && (\n <>\n <span className=\"mx-2.5 text-gray-300\" aria-hidden=\"true\">\n |\n </span>\n <span className=\"font-display text-gray-500\">{siteName}</span>\n </>\n )}\n </div>\n </div>\n </Link>\n\n {/* Desktop center: inline search slot. The empty div doubles as the\n spacer that keeps the right cluster right-aligned when no search\n is passed. */}\n <div className=\"hidden min-w-0 flex-1 md:flex md:items-center md:px-4\">\n {search}\n </div>\n\n {/* Desktop right side: nav buttons + user */}\n <div className=\"hidden items-center justify-end gap-2 md:flex\">\n {nav.map((item) => {\n const Icon = item.icon ?? labelIcon(item.label);\n return (\n <Button\n key={item.href}\n variant=\"ghost\"\n className={cn(\n 'relative h-auto min-w-0 flex-col items-center justify-center gap-1 rounded-[0.33em] px-3 py-1',\n isActive(item.href)\n ? 'text-primary'\n : 'opacity-80 hover:bg-gray-100 hover:opacity-100',\n )}\n onClick={() => router.push(item.href)}\n >\n <Icon className=\"h-6! w-6!\" strokeWidth={1.7} />\n <span className=\"text-xs\">{item.label}</span>\n {!!item.badge && (\n <span className=\"absolute -top-0.5 right-5.5 inline-flex h-4 w-4 items-center justify-center rounded-full bg-amber-400 text-[10px] font-bold leading-none text-amber-900\">\n {item.badge}\n </span>\n )}\n </Button>\n );\n })}\n\n {actions}\n\n {/* User dropdown */}\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant=\"ghost\"\n className={cn(\n 'group h-auto w-20 flex-col items-center justify-center gap-1 rounded-[0.33em] px-2 py-1',\n (profileHref && isActive(profileHref)) ||\n accountNav.some((item) => isActive(item.href))\n ? 'text-primary'\n : 'opacity-80 hover:bg-gray-100 hover:opacity-100',\n )}\n >\n <div className=\"flex h-6 w-6 items-center justify-center overflow-hidden rounded-full bg-gray-100\">\n {userAvatarUrl ? (\n <img\n src={userAvatarUrl}\n alt=\"\"\n className=\"h-full w-full object-contain\"\n />\n ) : (\n <UserRound className=\"h-5 w-5 text-gray-500\" />\n )}\n </div>\n <div className=\"flex items-center gap-0.5\">\n <span className=\"text-xs\">Account</span>\n <ChevronDown className=\"h-3! w-3! transition-transform group-data-[state=open]:rotate-180\" />\n </div>\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" className=\"w-max min-w-44\">\n {userPrimary && (\n <div className=\"px-2 py-1.5\">\n <div className=\"text-center text-sm font-medium\">\n {userPrimary}\n </div>\n {userSecondary && (\n <div className=\"text-muted-foreground text-center text-xs\">\n {userSecondary}\n </div>\n )}\n </div>\n )}\n <DropdownMenuSeparator />\n {profileHref && (\n <DropdownMenuItem asChild>\n <Link href={profileHref}>\n <UserRound className=\"h-4 w-4\" />\n Profile\n </Link>\n </DropdownMenuItem>\n )}\n {accountNav.map((item) => {\n const Icon = item.icon ?? labelIcon(item.label);\n return (\n <DropdownMenuItem key={item.href} asChild>\n <Link href={item.href}>\n <Icon className=\"h-4 w-4\" />\n {item.label}\n </Link>\n </DropdownMenuItem>\n );\n })}\n {(profileHref || accountNav.length > 0) && (\n <DropdownMenuSeparator />\n )}\n <DropdownMenuItem\n variant=\"destructive\"\n disabled={logout.isPending}\n onClick={() => logout.mutate()}\n >\n <LogOut className=\"h-4 w-4\" />\n {logout.isPending ? 'Logging out...' : 'Sign Out'}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n\n {/* Mobile: search trigger + hamburger */}\n <div className=\"flex items-center gap-1 md:hidden\">\n {onSearchClick && (\n <button\n type=\"button\"\n aria-label=\"Search\"\n className=\"inline-flex h-10 w-10 items-center justify-center rounded-md border border-gray-300 hover:bg-gray-50\"\n onClick={onSearchClick}\n >\n <Search className=\"h-5 w-5\" />\n </button>\n )}\n {showMobileMenu && (\n <button\n type=\"button\"\n aria-label={isDrawerOpen ? 'Close menu' : 'Open menu'}\n className=\"inline-flex h-10 w-10 items-center justify-center rounded-md border border-gray-300 hover:bg-gray-50\"\n onClick={() => setIsDrawerOpen(!isDrawerOpen)}\n >\n {isDrawerOpen ? (\n <X className=\"h-5 w-5\" />\n ) : (\n <Menu className=\"h-5 w-5\" />\n )}\n </button>\n )}\n </div>\n </div>\n\n {/* Mobile right drawer */}\n {showMobileMenu && isDrawerOpen && (\n <div\n className=\"fixed inset-0 z-[30] duration-200 md:hidden\"\n onClick={() => setIsDrawerOpen(false)}\n />\n )}\n\n {showMobileMenu && (\n <div\n className={cn(\n 'fixed top-0 right-0 z-[31] h-[100svh] w-full max-w-[92%] border-l border-gray-200 bg-white shadow-xl sm:max-w-[420px] md:hidden',\n 'transition-transform duration-250 ease-out',\n isDrawerOpen ? 'translate-x-0' : 'translate-x-full',\n )}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Mobile menu\"\n >\n <div className=\"flex h-full flex-col\">\n <div className=\"mt-1 flex items-center justify-between border-b px-4 py-3\">\n <div className=\"flex items-center gap-2\">\n <Image\n src={logoPath}\n alt=\"\"\n width={25}\n height={25}\n className=\"h-6 w-6 rounded object-contain\"\n />\n <span className=\"text-sm font-semibold\">{brand}</span>\n <span className=\"rounded border border-gray-200 bg-gray-50 px-1 py-0 text-[10px] font-medium text-gray-400 leading-none\">\n {siteName}\n </span>\n </div>\n <button\n type=\"button\"\n aria-label=\"Close menu\"\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md transition-colors hover:bg-gray-100\"\n onClick={() => setIsDrawerOpen(false)}\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n <div className=\"flex-1 overflow-y-auto p-4\">\n {userPrimary && (\n <div className=\"flex items-center gap-2 pb-2\">\n <UserRound className=\"h-5 w-5 text-gray-500\" />\n <span className=\"text-sm font-semibold text-gray-900\">\n {userPrimary}\n </span>\n </div>\n )}\n\n <Separator className=\"my-4\" />\n\n {actions && <div className=\"mb-2\">{actions}</div>}\n\n <nav className=\"space-y-1\">\n {nav.map((item) => {\n const Icon = item.icon ?? labelIcon(item.label);\n return (\n <Link\n key={item.href}\n href={item.href}\n className=\"block w-full\"\n >\n <button className=\"flex w-full items-center justify-between rounded-md border border-transparent px-3 py-2 text-sm transition-colors hover:border-gray-200 hover:bg-gray-50\">\n <div className=\"flex items-center gap-2\">\n <Icon className=\"h-4 w-4 text-gray-500\" />\n <span>{item.label}</span>\n {!!item.badge && (\n <span className=\"inline-flex h-4 w-4 items-center justify-center rounded-full bg-amber-400 text-[10px] font-bold leading-none text-amber-900\">\n !\n </span>\n )}\n </div>\n <ChevronRight className=\"h-4 w-4 text-gray-300\" />\n </button>\n </Link>\n );\n })}\n </nav>\n </div>\n\n <div className=\"mt-auto border-t px-4 py-3 space-y-1\">\n {profileHref && (\n <Link href={profileHref} className=\"block w-full\">\n <button className=\"flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors hover:bg-gray-50\">\n <UserRound className=\"h-4 w-4\" />\n Profile\n </button>\n </Link>\n )}\n {accountNav.map((item) => {\n const Icon = item.icon ?? labelIcon(item.label);\n return (\n <Link\n key={item.href}\n href={item.href}\n className=\"block w-full\"\n >\n <button className=\"flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors hover:bg-gray-50\">\n <Icon className=\"h-4 w-4\" />\n {item.label}\n </button>\n </Link>\n );\n })}\n <button\n onClick={() => logout.mutate()}\n disabled={logout.isPending}\n className=\"flex w-full items-center justify-center gap-2 rounded-md py-2 font-medium text-red-600 transition-colors hover:bg-red-50\"\n >\n <LogOut className=\"h-4 w-4\" />\n {logout.isPending ? 'Logging out...' : 'Sign Out'}\n </button>\n </div>\n </div>\n </div>\n )}\n </header>\n );\n}\n"],"names":["_jsxs","_jsx"],"mappings":";;;;;;;;;;;;AAmFA,SAAS,SAAS,CAAC,KAAa,EAAA;AAC9B,IAAA,MAAM,GAAG,GAA+B;AACtC,QAAA,QAAQ,EAAE,SAAS;AACnB,QAAA,OAAO,EAAE,IAAI;AACb,QAAA,WAAW,EAAE,IAAI;AACjB,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,cAAc,EAAE,OAAO;AACvB,QAAA,eAAe,EAAE,QAAQ;AACzB,QAAA,YAAY,EAAE,aAAa;AAC3B,QAAA,SAAS,EAAE,SAAS;AACpB,QAAA,iBAAiB,EAAE,WAAW;AAC9B,QAAA,aAAa,EAAE,aAAa;AAC5B,QAAA,SAAS,EAAE,eAAe;KAC3B;AACD,IAAA,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,SAAS;AAChC;AAEM,SAAU,SAAS,CAAC,EACxB,QAAQ,EACR,QAAQ,EACR,GAAG,EACH,WAAW,EACX,aAAa,EACb,MAAM,EAAE,QAAQ,EAChB,cAAc,EACd,WAAW,EACX,aAAa,EACb,UAAU,GAAG,EAAE,EACf,KAAK,GAAG,UAAU,EAClB,QAAQ,GAAG,4BAA4B,EACvC,OAAO,EACP,MAAM,EACN,aAAa,EACb,cAAc,GAAG,IAAI,GACN,EAAA;AACf,IAAA,MAAM,QAAQ,GAAG,WAAW,EAAE,IAAI,EAAE;AACpC,IAAA,MAAM,MAAM,GAAG,SAAS,EAAE;AAC1B,IAAA,MAAM,WAAW,GAAG,cAAc,EAAE;IACpC,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAEvD,SAAS,CAAC,MAAK;QACb,eAAe,CAAC,KAAK,CAAC;AACxB,IAAA,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IAEd,SAAS,CAAC,MAAK;AACb,QAAA,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,YAAY,GAAG,QAAQ,GAAG,EAAE;AAC3D,QAAA,OAAO,MAAK;YACV,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE;AACnC,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;IAElB,MAAM,MAAM,GAAG,WAAW,CAAC;AACzB,QAAA,UAAU,EAAE,QAAQ;QACpB,SAAS,EAAE,MAAK;YACd,WAAW,CAAC,KAAK,EAAE;AACnB,YAAA,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC;QAChC,CAAC;AACF,KAAA,CAAC;AAEF,IAAA,MAAM,QAAQ,GAAG,CAAC,IAAY,KAC5B,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAAA,CAAA,CAAG,CAAC;IAEtD,QACEA,IAAA,CAAA,QAAA,EAAA,EAAQ,SAAS,EAAC,wEAAwE,aACxFA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,mFAAmF,EAAA,QAAA,EAAA,CAEhGC,GAAA,CAAC,IAAI,EAAA,EACH,IAAI,EAAE,QAAQ,EAAA,YAAA,EACF,KAAK,EACjB,SAAS,EAAC,wEAAwE,EAAA,QAAA,EAElFD,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,yBAAyB,EAAA,QAAA,EAAA,CACtCC,GAAA,CAAC,KAAK,EAAA,EACJ,GAAG,EAAE,QAAQ,EACb,GAAG,EAAC,EAAE,EACN,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE,EACV,SAAS,EAAC,WAAW,EAAA,CACrB,EAGFD,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,6BAA6B,EAAA,QAAA,EAAA,CAC1CC,GAAA,CAAA,IAAA,EAAA,EAAI,SAAS,EAAC,8CAA8C,YACzD,KAAK,EAAA,CACH,EACJ,QAAQ,KACPD,4BACEC,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,sBAAsB,EAAA,aAAA,EAAa,MAAM,EAAA,QAAA,EAAA,GAAA,EAAA,CAElD,EACPA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,4BAA4B,EAAA,QAAA,EAAE,QAAQ,GAAQ,CAAA,EAAA,CAC7D,CACJ,CAAA,EAAA,CACG,CAAA,EAAA,CACF,EAAA,CACD,EAKPA,aAAK,SAAS,EAAC,uDAAuD,EAAA,QAAA,EACnE,MAAM,EAAA,CACH,EAGND,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,+CAA+C,EAAA,QAAA,EAAA,CAC3D,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AAChB,gCAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;AAC/C,gCAAA,QACEA,IAAA,CAAC,MAAM,IAEL,OAAO,EAAC,OAAO,EACf,SAAS,EAAE,EAAE,CACX,+FAA+F,EAC/F,QAAQ,CAAC,IAAI,CAAC,IAAI;AAChB,0CAAE;AACF,0CAAE,gDAAgD,CACrD,EACD,OAAO,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAA,QAAA,EAAA,CAErCC,GAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,WAAW,EAAC,WAAW,EAAE,GAAG,GAAI,EAChDA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,SAAS,EAAA,QAAA,EAAE,IAAI,CAAC,KAAK,EAAA,CAAQ,EAC5C,CAAC,CAAC,IAAI,CAAC,KAAK,KACXA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,yJAAyJ,EAAA,QAAA,EACtK,IAAI,CAAC,KAAK,EAAA,CACN,CACR,CAAA,EAAA,EAhBI,IAAI,CAAC,IAAI,CAiBP;AAEb,4BAAA,CAAC,CAAC,EAED,OAAO,EAGRD,KAAC,YAAY,EAAA,EAAA,QAAA,EAAA,CACXC,GAAA,CAAC,mBAAmB,EAAA,EAAC,OAAO,EAAA,IAAA,EAAA,QAAA,EAC1BD,IAAA,CAAC,MAAM,EAAA,EACL,OAAO,EAAC,OAAO,EACf,SAAS,EAAE,EAAE,CACX,yFAAyF,EACzF,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,CAAC;AACnC,gDAAA,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;AAC7C,kDAAE;AACF,kDAAE,gDAAgD,CACrD,EAAA,QAAA,EAAA,CAEDC,aAAK,SAAS,EAAC,mFAAmF,EAAA,QAAA,EAC/F,aAAa,IACZA,GAAA,CAAA,KAAA,EAAA,EACE,GAAG,EAAE,aAAa,EAClB,GAAG,EAAC,EAAE,EACN,SAAS,EAAC,8BAA8B,EAAA,CACxC,KAEFA,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAC,uBAAuB,EAAA,CAAG,CAChD,GACG,EACND,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,2BAA2B,EAAA,QAAA,EAAA,CACxCC,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,SAAS,EAAA,QAAA,EAAA,SAAA,EAAA,CAAe,EACxCA,GAAA,CAAC,WAAW,EAAA,EAAC,SAAS,EAAC,mEAAmE,EAAA,CAAG,CAAA,EAAA,CACzF,CAAA,EAAA,CACC,EAAA,CACW,EACtBD,IAAA,CAAC,mBAAmB,EAAA,EAAC,KAAK,EAAC,KAAK,EAAC,SAAS,EAAC,gBAAgB,EAAA,QAAA,EAAA,CACxD,WAAW,KACVA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,aAAa,EAAA,QAAA,EAAA,CAC1BC,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,iCAAiC,EAAA,QAAA,EAC7C,WAAW,EAAA,CACR,EACL,aAAa,KACZA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,2CAA2C,EAAA,QAAA,EACvD,aAAa,EAAA,CACV,CACP,CAAA,EAAA,CACG,CACP,EACDA,GAAA,CAAC,qBAAqB,EAAA,EAAA,CAAG,EACxB,WAAW,KACVA,GAAA,CAAC,gBAAgB,EAAA,EAAC,OAAO,EAAA,IAAA,EAAA,QAAA,EACvBD,IAAA,CAAC,IAAI,EAAA,EAAC,IAAI,EAAE,WAAW,EAAA,QAAA,EAAA,CACrBC,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,eAE5B,EAAA,CACU,CACpB,EACA,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AACvB,gDAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;AAC/C,gDAAA,QACEA,GAAA,CAAC,gBAAgB,EAAA,EAAiB,OAAO,EAAA,IAAA,EAAA,QAAA,EACvCD,IAAA,CAAC,IAAI,EAAA,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAA,QAAA,EAAA,CACnBC,GAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,EAC3B,IAAI,CAAC,KAAK,CAAA,EAAA,CACN,IAJc,IAAI,CAAC,IAAI,CAKb;AAEvB,4CAAA,CAAC,CAAC,EACD,CAAC,WAAW,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,MACpCA,GAAA,CAAC,qBAAqB,EAAA,EAAA,CAAG,CAC1B,EACDD,IAAA,CAAC,gBAAgB,EAAA,EACf,OAAO,EAAC,aAAa,EACrB,QAAQ,EAAE,MAAM,CAAC,SAAS,EAC1B,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,aAE9BC,GAAA,CAAC,MAAM,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,EAC7B,MAAM,CAAC,SAAS,GAAG,gBAAgB,GAAG,UAAU,IAChC,CAAA,EAAA,CACC,CAAA,EAAA,CACT,IACX,EAGND,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,mCAAmC,EAAA,QAAA,EAAA,CAC/C,aAAa,KACZC,GAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,gBACF,QAAQ,EACnB,SAAS,EAAC,sGAAsG,EAChH,OAAO,EAAE,aAAa,EAAA,QAAA,EAEtBA,GAAA,CAAC,MAAM,EAAA,EAAC,SAAS,EAAC,SAAS,GAAG,EAAA,CACvB,CACV,EACA,cAAc,KACbA,GAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,EAAA,YAAA,EACD,YAAY,GAAG,YAAY,GAAG,WAAW,EACrD,SAAS,EAAC,sGAAsG,EAChH,OAAO,EAAE,MAAM,eAAe,CAAC,CAAC,YAAY,CAAC,EAAA,QAAA,EAE5C,YAAY,IACXA,GAAA,CAAC,CAAC,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,KAEzBA,GAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,CAC7B,EAAA,CACM,CACV,CAAA,EAAA,CACG,CAAA,EAAA,CACF,EAGL,cAAc,IAAI,YAAY,KAC7BA,aACE,SAAS,EAAC,6CAA6C,EACvD,OAAO,EAAE,MAAM,eAAe,CAAC,KAAK,CAAC,EAAA,CACrC,CACH,EAEA,cAAc,KACbA,aACE,SAAS,EAAE,EAAE,CACX,iIAAiI,EACjI,4CAA4C,EAC5C,YAAY,GAAG,eAAe,GAAG,kBAAkB,CACpD,EACD,IAAI,EAAC,QAAQ,EAAA,YAAA,EACF,MAAM,gBACN,aAAa,EAAA,QAAA,EAExBD,cAAK,SAAS,EAAC,sBAAsB,EAAA,QAAA,EAAA,CACnCA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,2DAA2D,aACxEA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,yBAAyB,aACtCC,GAAA,CAAC,KAAK,IACJ,GAAG,EAAE,QAAQ,EACb,GAAG,EAAC,EAAE,EACN,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE,EACV,SAAS,EAAC,gCAAgC,GAC1C,EACFA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,uBAAuB,YAAE,KAAK,EAAA,CAAQ,EACtDA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,wGAAwG,EAAA,QAAA,EACrH,QAAQ,EAAA,CACJ,CAAA,EAAA,CACH,EACNA,GAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,gBACF,YAAY,EACvB,SAAS,EAAC,gGAAgG,EAC1G,OAAO,EAAE,MAAM,eAAe,CAAC,KAAK,CAAC,EAAA,QAAA,EAErCA,GAAA,CAAC,CAAC,EAAA,EAAC,SAAS,EAAC,SAAS,GAAG,EAAA,CAClB,CAAA,EAAA,CACL,EAEND,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,4BAA4B,EAAA,QAAA,EAAA,CACxC,WAAW,KACVA,cAAK,SAAS,EAAC,8BAA8B,EAAA,QAAA,EAAA,CAC3CC,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAC,uBAAuB,GAAG,EAC/CA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,qCAAqC,YAClD,WAAW,EAAA,CACP,IACH,CACP,EAEDA,IAAC,SAAS,EAAA,EAAC,SAAS,EAAC,MAAM,GAAG,EAE7B,OAAO,IAAIA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,MAAM,YAAE,OAAO,EAAA,CAAO,EAEjDA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,WAAW,EAAA,QAAA,EACvB,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AAChB,wCAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;AAC/C,wCAAA,QACEA,GAAA,CAAC,IAAI,EAAA,EAEH,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,SAAS,EAAC,cAAc,EAAA,QAAA,EAExBD,IAAA,CAAA,QAAA,EAAA,EAAQ,SAAS,EAAC,0JAA0J,EAAA,QAAA,EAAA,CAC1KA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,yBAAyB,EAAA,QAAA,EAAA,CACtCC,GAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,uBAAuB,GAAG,EAC1CA,GAAA,CAAA,MAAA,EAAA,EAAA,QAAA,EAAO,IAAI,CAAC,KAAK,EAAA,CAAQ,EACxB,CAAC,CAAC,IAAI,CAAC,KAAK,KACXA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,6HAA6H,EAAA,QAAA,EAAA,GAAA,EAAA,CAEtI,CACR,CAAA,EAAA,CACG,EACNA,GAAA,CAAC,YAAY,EAAA,EAAC,SAAS,EAAC,uBAAuB,EAAA,CAAG,CAAA,EAAA,CAC3C,EAAA,EAfJ,IAAI,CAAC,IAAI,CAgBT;oCAEX,CAAC,CAAC,GACE,CAAA,EAAA,CACF,EAEND,cAAK,SAAS,EAAC,sCAAsC,EAAA,QAAA,EAAA,CAClD,WAAW,KACVC,GAAA,CAAC,IAAI,EAAA,EAAC,IAAI,EAAE,WAAW,EAAE,SAAS,EAAC,cAAc,EAAA,QAAA,EAC/CD,iBAAQ,SAAS,EAAC,gGAAgG,EAAA,QAAA,EAAA,CAChHC,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,eAE1B,EAAA,CACJ,CACR,EACA,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AACvB,oCAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;AAC/C,oCAAA,QACEA,GAAA,CAAC,IAAI,EAAA,EAEH,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,SAAS,EAAC,cAAc,EAAA,QAAA,EAExBD,IAAA,CAAA,QAAA,EAAA,EAAQ,SAAS,EAAC,gGAAgG,EAAA,QAAA,EAAA,CAChHC,GAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,SAAS,GAAG,EAC3B,IAAI,CAAC,KAAK,IACJ,EAAA,EAPJ,IAAI,CAAC,IAAI,CAQT;gCAEX,CAAC,CAAC,EACFD,IAAA,CAAA,QAAA,EAAA,EACE,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,EAC9B,QAAQ,EAAE,MAAM,CAAC,SAAS,EAC1B,SAAS,EAAC,0HAA0H,EAAA,QAAA,EAAA,CAEpIC,GAAA,CAAC,MAAM,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,EAC7B,MAAM,CAAC,SAAS,GAAG,gBAAgB,GAAG,UAAU,CAAA,EAAA,CAC1C,CAAA,EAAA,CACL,IACF,EAAA,CACF,CACP,CAAA,EAAA,CACM;AAEb;;;;"}
|
|
1
|
+
{"version":3,"file":"app-header.js","sources":["../../../src/components/ui/app-header.tsx"],"sourcesContent":["import Link from 'next/link';\r\nimport Image from 'next/image';\r\nimport { usePathname, useRouter } from 'next/navigation';\r\nimport { useMutation, useQueryClient } from '@tanstack/react-query';\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuTrigger,\r\n DropdownMenuContent,\r\n DropdownMenuItem,\r\n DropdownMenuSeparator,\r\n} from '@/components/ui/dropdown-menu';\r\nimport { Button } from '@/components/ui/button';\r\nimport { Separator } from '@/components/ui/separator';\r\nimport { cn } from '@/utils';\r\nimport {\r\n LogOut,\r\n Menu,\r\n Search,\r\n X,\r\n UserRound,\r\n ChevronDown,\r\n ChevronRight,\r\n Handshake,\r\n Mail,\r\n History,\r\n FileText,\r\n Users,\r\n LayoutDashboard,\r\n FileSignature,\r\n GraduationCap,\r\n Building2,\r\n SearchCheck,\r\n} from 'lucide-react';\r\nimport { useState, useEffect } from 'react';\r\nimport type { ReactNode } from 'react';\r\nimport type { LucideIcon } from 'lucide-react';\r\n\r\nexport interface NavItem {\r\n href: string;\r\n label: string;\r\n badge?: number;\r\n icon?: LucideIcon;\r\n}\r\n\r\ninterface AppHeaderProps {\r\n /** Optional site name. */\r\n siteName?: string;\r\n homeHref: string;\r\n nav: NavItem[];\r\n userPrimary?: string;\r\n userSecondary?: string;\r\n logout: () => Promise<unknown>;\r\n postLogoutPath: string;\r\n profileHref?: string;\r\n userAvatarUrl?: string | null;\r\n accountNav?: NavItem[];\r\n /** Overrides the hardcoded \"Partners\" brand text. */\r\n brand?: string;\r\n /** Overrides the hardcoded \"/betterinternship-logo.png\" logo path. */\r\n logoPath?: string;\r\n /** Extra controls rendered next to the nav (desktop) and inside the drawer (mobile). */\r\n actions?: ReactNode;\r\n /**\r\n * Inline search control rendered in the header's center region on desktop\r\n * (`md` and up only). Purely a layout slot — the consumer owns all search\r\n * state and behavior. For mobile, pair with `onSearchClick`.\r\n */\r\n search?: ReactNode;\r\n /**\r\n * When set, renders a search icon button on mobile immediately left of the\r\n * hamburger. Typically opens a full-screen search overlay owned by the\r\n * consumer.\r\n */\r\n onSearchClick?: () => void;\r\n /**\r\n * Set to false to hide the mobile hamburger button and its side drawer\r\n * entirely — for consumers that provide their own mobile navigation (e.g.\r\n * a bottom tab bar) and don't want the nav/profile/logout items duplicated.\r\n * Defaults to true.\r\n */\r\n showMobileMenu?: boolean;\r\n}\r\n\r\nfunction labelIcon(label: string): LucideIcon {\r\n const map: Record<string, LucideIcon> = {\r\n Partners: Handshake,\r\n Invites: Mail,\r\n Invitations: Mail,\r\n Accounts: Users,\r\n 'Activity Log': History,\r\n 'MOA Templates': FileText,\r\n Universities: GraduationCap,\r\n Companies: Building2,\r\n 'Company Reviews': SearchCheck,\r\n 'Request MOA': FileSignature,\r\n Dashboard: LayoutDashboard,\r\n };\r\n return map[label] ?? Handshake;\r\n}\r\n\r\nexport function AppHeader({\r\n siteName,\r\n homeHref,\r\n nav,\r\n userPrimary,\r\n userSecondary,\r\n logout: logoutFn,\r\n postLogoutPath,\r\n profileHref,\r\n userAvatarUrl,\r\n accountNav = [],\r\n brand = 'Partners',\r\n logoPath = '/betterinternship-logo.png',\r\n actions,\r\n search,\r\n onSearchClick,\r\n showMobileMenu = true,\r\n}: AppHeaderProps) {\r\n const pathname = usePathname() ?? '';\r\n const router = useRouter();\r\n const queryClient = useQueryClient();\r\n const [isDrawerOpen, setIsDrawerOpen] = useState(false);\r\n\r\n useEffect(() => {\r\n setIsDrawerOpen(false);\r\n }, [pathname]);\r\n\r\n useEffect(() => {\r\n document.body.style.overflow = isDrawerOpen ? 'hidden' : '';\r\n return () => {\r\n document.body.style.overflow = '';\r\n };\r\n }, [isDrawerOpen]);\r\n\r\n const logout = useMutation({\r\n mutationFn: logoutFn,\r\n onSettled: () => {\r\n queryClient.clear();\r\n router.replace(postLogoutPath);\r\n },\r\n });\r\n\r\n const isActive = (href: string) =>\r\n pathname === href || pathname.startsWith(`${href}/`);\r\n\r\n return (\r\n <header className=\"bg-background/70 sticky top-0 z-40 border-b py-1 md:py-2 backdrop-blur\">\r\n <div className=\"mx-auto flex h-14 items-center justify-between gap-2 px-4 sm:px-6 lg:px-8 md:h-16\">\r\n {/* Brand */}\r\n <Link\r\n href={homeHref}\r\n aria-label={brand}\r\n className=\"block shrink-0 border-none text-black! outline-none focus:outline-none\"\r\n >\r\n <div className=\"flex items-center gap-2\">\r\n <Image\r\n src={logoPath}\r\n alt=\"\"\r\n width={25}\r\n height={25}\r\n className=\"flex-none\"\r\n />\r\n {/* Wordmark hides below md — the logo carries the link, which keeps\r\n its name via the aria-label above. */}\r\n <div className=\"hidden items-center md:flex\">\r\n <h1 className=\"font-display text-lg font-bold text-gray-900\">\r\n {brand}\r\n </h1>\r\n {siteName && (\r\n <>\r\n <span className=\"mx-2.5 text-gray-300\" aria-hidden=\"true\">\r\n |\r\n </span>\r\n <span className=\"font-display text-gray-500\">{siteName}</span>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n </Link>\r\n\r\n {/* Desktop center: inline search slot. The empty div doubles as the\r\n spacer that keeps the right cluster right-aligned when no search\r\n is passed. */}\r\n <div className=\"hidden min-w-0 flex-1 md:flex md:items-center md:px-4\">\r\n {search}\r\n </div>\r\n\r\n {/* Desktop right side: nav buttons + user */}\r\n <div className=\"hidden items-center justify-end gap-2 md:flex\">\r\n {nav.map((item) => {\r\n const Icon = item.icon ?? labelIcon(item.label);\r\n return (\r\n <Button\r\n key={item.href}\r\n variant=\"ghost\"\r\n className={cn(\r\n 'relative h-auto min-w-0 flex-col items-center justify-center gap-1 rounded-[0.33em] px-3 py-1',\r\n isActive(item.href)\r\n ? 'text-primary'\r\n : 'opacity-80 hover:bg-gray-100 hover:opacity-100',\r\n )}\r\n onClick={() => router.push(item.href)}\r\n >\r\n <Icon className=\"h-6! w-6!\" strokeWidth={1.7} />\r\n <span className=\"text-xs\">{item.label}</span>\r\n {!!item.badge && (\r\n <span className=\"absolute -top-0.5 right-5.5 inline-flex h-4 w-4 items-center justify-center rounded-full bg-amber-400 text-[10px] font-bold leading-none text-amber-900\">\r\n {item.badge}\r\n </span>\r\n )}\r\n </Button>\r\n );\r\n })}\r\n\r\n {actions}\r\n\r\n {/* User dropdown */}\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button\r\n variant=\"ghost\"\r\n className={cn(\r\n 'group h-auto w-20 flex-col items-center justify-center gap-1 rounded-[0.33em] px-2 py-1',\r\n (profileHref && isActive(profileHref)) ||\r\n accountNav.some((item) => isActive(item.href))\r\n ? 'text-primary'\r\n : 'opacity-80 hover:bg-gray-100 hover:opacity-100',\r\n )}\r\n >\r\n <div className=\"flex h-6 w-6 items-center justify-center overflow-hidden rounded-full bg-gray-100\">\r\n {userAvatarUrl ? (\r\n <img\r\n src={userAvatarUrl}\r\n alt=\"\"\r\n className=\"h-full w-full object-contain\"\r\n />\r\n ) : (\r\n <UserRound className=\"h-5 w-5 text-gray-500\" />\r\n )}\r\n </div>\r\n <div className=\"flex items-center gap-0.5\">\r\n <span className=\"text-xs\">Account</span>\r\n <ChevronDown className=\"h-3! w-3! transition-transform group-data-[state=open]:rotate-180\" />\r\n </div>\r\n </Button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent align=\"end\" className=\"w-max min-w-44\">\r\n {userPrimary && (\r\n <div className=\"px-2 py-1.5\">\r\n <div className=\"text-center text-sm font-medium\">\r\n {userPrimary}\r\n </div>\r\n {userSecondary && (\r\n <div className=\"text-muted-foreground text-center text-xs\">\r\n {userSecondary}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n <DropdownMenuSeparator />\r\n {profileHref && (\r\n <DropdownMenuItem asChild>\r\n <Link href={profileHref}>\r\n <UserRound className=\"h-4 w-4\" />\r\n Profile\r\n </Link>\r\n </DropdownMenuItem>\r\n )}\r\n {accountNav.map((item) => {\r\n const Icon = item.icon ?? labelIcon(item.label);\r\n return (\r\n <DropdownMenuItem key={item.href} asChild>\r\n <Link href={item.href}>\r\n <Icon className=\"h-4 w-4\" />\r\n {item.label}\r\n </Link>\r\n </DropdownMenuItem>\r\n );\r\n })}\r\n {(profileHref || accountNav.length > 0) && (\r\n <DropdownMenuSeparator />\r\n )}\r\n <DropdownMenuItem\r\n variant=\"destructive\"\r\n disabled={logout.isPending}\r\n onClick={() => logout.mutate()}\r\n >\r\n <LogOut className=\"h-4 w-4\" />\r\n {logout.isPending ? 'Logging out...' : 'Sign Out'}\r\n </DropdownMenuItem>\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n </div>\r\n\r\n {/* Mobile: search trigger + hamburger */}\r\n <div className=\"flex items-center gap-1 md:hidden\">\r\n {onSearchClick && (\r\n <button\r\n type=\"button\"\r\n aria-label=\"Search\"\r\n className=\"inline-flex h-10 w-10 items-center justify-center rounded-md border border-gray-300 hover:bg-gray-50\"\r\n onClick={onSearchClick}\r\n >\r\n <Search className=\"h-5 w-5\" />\r\n </button>\r\n )}\r\n {showMobileMenu && (\r\n <button\r\n type=\"button\"\r\n aria-label={isDrawerOpen ? 'Close menu' : 'Open menu'}\r\n className=\"inline-flex h-10 w-10 items-center justify-center rounded-md border border-gray-300 hover:bg-gray-50\"\r\n onClick={() => setIsDrawerOpen(!isDrawerOpen)}\r\n >\r\n {isDrawerOpen ? (\r\n <X className=\"h-5 w-5\" />\r\n ) : (\r\n <Menu className=\"h-5 w-5\" />\r\n )}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Mobile right drawer */}\r\n {showMobileMenu && isDrawerOpen && (\r\n <div\r\n className=\"fixed inset-0 z-[30] duration-200 md:hidden\"\r\n onClick={() => setIsDrawerOpen(false)}\r\n />\r\n )}\r\n\r\n {showMobileMenu && (\r\n <div\r\n className={cn(\r\n 'fixed top-0 right-0 z-[31] h-[100svh] w-full max-w-[92%] border-l border-gray-200 bg-white shadow-xl sm:max-w-[420px] md:hidden',\r\n 'transition-transform duration-250 ease-out',\r\n isDrawerOpen ? 'translate-x-0' : 'translate-x-full',\r\n )}\r\n role=\"dialog\"\r\n aria-modal=\"true\"\r\n aria-label=\"Mobile menu\"\r\n >\r\n <div className=\"flex h-full flex-col\">\r\n <div className=\"mt-1 flex items-center justify-between border-b px-4 py-3\">\r\n <div className=\"flex items-center gap-2\">\r\n <Image\r\n src={logoPath}\r\n alt=\"\"\r\n width={25}\r\n height={25}\r\n className=\"h-6 w-6 rounded object-contain\"\r\n />\r\n <span className=\"text-sm font-semibold\">{brand}</span>\r\n <span className=\"rounded border border-gray-200 bg-gray-50 px-1 py-0 text-[10px] font-medium text-gray-400 leading-none\">\r\n {siteName}\r\n </span>\r\n </div>\r\n <button\r\n type=\"button\"\r\n aria-label=\"Close menu\"\r\n className=\"inline-flex h-9 w-9 items-center justify-center rounded-md transition-colors hover:bg-gray-100\"\r\n onClick={() => setIsDrawerOpen(false)}\r\n >\r\n <X className=\"h-5 w-5\" />\r\n </button>\r\n </div>\r\n\r\n <div className=\"flex-1 overflow-y-auto p-4\">\r\n {userPrimary && (\r\n <div className=\"flex items-center gap-2 pb-2\">\r\n <UserRound className=\"h-5 w-5 text-gray-500\" />\r\n <span className=\"text-sm font-semibold text-gray-900\">\r\n {userPrimary}\r\n </span>\r\n </div>\r\n )}\r\n\r\n <Separator className=\"my-4\" />\r\n\r\n {actions && <div className=\"mb-2\">{actions}</div>}\r\n\r\n <nav className=\"space-y-1\">\r\n {nav.map((item) => {\r\n const Icon = item.icon ?? labelIcon(item.label);\r\n return (\r\n <Link\r\n key={item.href}\r\n href={item.href}\r\n className=\"block w-full\"\r\n >\r\n <button className=\"flex w-full items-center justify-between rounded-md border border-transparent px-3 py-2 text-sm transition-colors hover:border-gray-200 hover:bg-gray-50\">\r\n <div className=\"flex items-center gap-2\">\r\n <Icon className=\"h-4 w-4 text-gray-500\" />\r\n <span>{item.label}</span>\r\n {!!item.badge && (\r\n <span className=\"inline-flex h-4 w-4 items-center justify-center rounded-full bg-amber-400 text-[10px] font-bold leading-none text-amber-900\">\r\n !\r\n </span>\r\n )}\r\n </div>\r\n <ChevronRight className=\"h-4 w-4 text-gray-300\" />\r\n </button>\r\n </Link>\r\n );\r\n })}\r\n </nav>\r\n </div>\r\n\r\n <div className=\"mt-auto border-t px-4 py-3 space-y-1\">\r\n {profileHref && (\r\n <Link href={profileHref} className=\"block w-full\">\r\n <button className=\"flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors hover:bg-gray-50\">\r\n <UserRound className=\"h-4 w-4\" />\r\n Profile\r\n </button>\r\n </Link>\r\n )}\r\n {accountNav.map((item) => {\r\n const Icon = item.icon ?? labelIcon(item.label);\r\n return (\r\n <Link\r\n key={item.href}\r\n href={item.href}\r\n className=\"block w-full\"\r\n >\r\n <button className=\"flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm transition-colors hover:bg-gray-50\">\r\n <Icon className=\"h-4 w-4\" />\r\n {item.label}\r\n </button>\r\n </Link>\r\n );\r\n })}\r\n <button\r\n onClick={() => logout.mutate()}\r\n disabled={logout.isPending}\r\n className=\"flex w-full items-center justify-center gap-2 rounded-md py-2 font-medium text-red-600 transition-colors hover:bg-red-50\"\r\n >\r\n <LogOut className=\"h-4 w-4\" />\r\n {logout.isPending ? 'Logging out...' : 'Sign Out'}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n )}\r\n </header>\r\n );\r\n}\r\n"],"names":["_jsxs","_jsx"],"mappings":";;;;;;;;;;;;AAmFA,SAAS,SAAS,CAAC,KAAa,EAAA;AAC9B,IAAA,MAAM,GAAG,GAA+B;AACtC,QAAA,QAAQ,EAAE,SAAS;AACnB,QAAA,OAAO,EAAE,IAAI;AACb,QAAA,WAAW,EAAE,IAAI;AACjB,QAAA,QAAQ,EAAE,KAAK;AACf,QAAA,cAAc,EAAE,OAAO;AACvB,QAAA,eAAe,EAAE,QAAQ;AACzB,QAAA,YAAY,EAAE,aAAa;AAC3B,QAAA,SAAS,EAAE,SAAS;AACpB,QAAA,iBAAiB,EAAE,WAAW;AAC9B,QAAA,aAAa,EAAE,aAAa;AAC5B,QAAA,SAAS,EAAE,eAAe;KAC3B;AACD,IAAA,OAAO,GAAG,CAAC,KAAK,CAAC,IAAI,SAAS;AAChC;AAEM,SAAU,SAAS,CAAC,EACxB,QAAQ,EACR,QAAQ,EACR,GAAG,EACH,WAAW,EACX,aAAa,EACb,MAAM,EAAE,QAAQ,EAChB,cAAc,EACd,WAAW,EACX,aAAa,EACb,UAAU,GAAG,EAAE,EACf,KAAK,GAAG,UAAU,EAClB,QAAQ,GAAG,4BAA4B,EACvC,OAAO,EACP,MAAM,EACN,aAAa,EACb,cAAc,GAAG,IAAI,GACN,EAAA;AACf,IAAA,MAAM,QAAQ,GAAG,WAAW,EAAE,IAAI,EAAE;AACpC,IAAA,MAAM,MAAM,GAAG,SAAS,EAAE;AAC1B,IAAA,MAAM,WAAW,GAAG,cAAc,EAAE;IACpC,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC;IAEvD,SAAS,CAAC,MAAK;QACb,eAAe,CAAC,KAAK,CAAC;AACxB,IAAA,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IAEd,SAAS,CAAC,MAAK;AACb,QAAA,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,YAAY,GAAG,QAAQ,GAAG,EAAE;AAC3D,QAAA,OAAO,MAAK;YACV,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE;AACnC,QAAA,CAAC;AACH,IAAA,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;IAElB,MAAM,MAAM,GAAG,WAAW,CAAC;AACzB,QAAA,UAAU,EAAE,QAAQ;QACpB,SAAS,EAAE,MAAK;YACd,WAAW,CAAC,KAAK,EAAE;AACnB,YAAA,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC;QAChC,CAAC;AACF,KAAA,CAAC;AAEF,IAAA,MAAM,QAAQ,GAAG,CAAC,IAAY,KAC5B,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,IAAI,CAAA,CAAA,CAAG,CAAC;IAEtD,QACEA,IAAA,CAAA,QAAA,EAAA,EAAQ,SAAS,EAAC,wEAAwE,aACxFA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,mFAAmF,EAAA,QAAA,EAAA,CAEhGC,GAAA,CAAC,IAAI,EAAA,EACH,IAAI,EAAE,QAAQ,EAAA,YAAA,EACF,KAAK,EACjB,SAAS,EAAC,wEAAwE,EAAA,QAAA,EAElFD,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,yBAAyB,EAAA,QAAA,EAAA,CACtCC,GAAA,CAAC,KAAK,EAAA,EACJ,GAAG,EAAE,QAAQ,EACb,GAAG,EAAC,EAAE,EACN,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE,EACV,SAAS,EAAC,WAAW,EAAA,CACrB,EAGFD,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,6BAA6B,EAAA,QAAA,EAAA,CAC1CC,GAAA,CAAA,IAAA,EAAA,EAAI,SAAS,EAAC,8CAA8C,YACzD,KAAK,EAAA,CACH,EACJ,QAAQ,KACPD,4BACEC,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,sBAAsB,EAAA,aAAA,EAAa,MAAM,EAAA,QAAA,EAAA,GAAA,EAAA,CAElD,EACPA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,4BAA4B,EAAA,QAAA,EAAE,QAAQ,GAAQ,CAAA,EAAA,CAC7D,CACJ,CAAA,EAAA,CACG,CAAA,EAAA,CACF,EAAA,CACD,EAKPA,aAAK,SAAS,EAAC,uDAAuD,EAAA,QAAA,EACnE,MAAM,EAAA,CACH,EAGND,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,+CAA+C,EAAA,QAAA,EAAA,CAC3D,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AAChB,gCAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;AAC/C,gCAAA,QACEA,IAAA,CAAC,MAAM,IAEL,OAAO,EAAC,OAAO,EACf,SAAS,EAAE,EAAE,CACX,+FAA+F,EAC/F,QAAQ,CAAC,IAAI,CAAC,IAAI;AAChB,0CAAE;AACF,0CAAE,gDAAgD,CACrD,EACD,OAAO,EAAE,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAA,QAAA,EAAA,CAErCC,GAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,WAAW,EAAC,WAAW,EAAE,GAAG,GAAI,EAChDA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,SAAS,EAAA,QAAA,EAAE,IAAI,CAAC,KAAK,EAAA,CAAQ,EAC5C,CAAC,CAAC,IAAI,CAAC,KAAK,KACXA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,yJAAyJ,EAAA,QAAA,EACtK,IAAI,CAAC,KAAK,EAAA,CACN,CACR,CAAA,EAAA,EAhBI,IAAI,CAAC,IAAI,CAiBP;AAEb,4BAAA,CAAC,CAAC,EAED,OAAO,EAGRD,KAAC,YAAY,EAAA,EAAA,QAAA,EAAA,CACXC,GAAA,CAAC,mBAAmB,EAAA,EAAC,OAAO,EAAA,IAAA,EAAA,QAAA,EAC1BD,IAAA,CAAC,MAAM,EAAA,EACL,OAAO,EAAC,OAAO,EACf,SAAS,EAAE,EAAE,CACX,yFAAyF,EACzF,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,CAAC;AACnC,gDAAA,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;AAC7C,kDAAE;AACF,kDAAE,gDAAgD,CACrD,EAAA,QAAA,EAAA,CAEDC,aAAK,SAAS,EAAC,mFAAmF,EAAA,QAAA,EAC/F,aAAa,IACZA,GAAA,CAAA,KAAA,EAAA,EACE,GAAG,EAAE,aAAa,EAClB,GAAG,EAAC,EAAE,EACN,SAAS,EAAC,8BAA8B,EAAA,CACxC,KAEFA,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAC,uBAAuB,EAAA,CAAG,CAChD,GACG,EACND,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,2BAA2B,EAAA,QAAA,EAAA,CACxCC,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,SAAS,EAAA,QAAA,EAAA,SAAA,EAAA,CAAe,EACxCA,GAAA,CAAC,WAAW,EAAA,EAAC,SAAS,EAAC,mEAAmE,EAAA,CAAG,CAAA,EAAA,CACzF,CAAA,EAAA,CACC,EAAA,CACW,EACtBD,IAAA,CAAC,mBAAmB,EAAA,EAAC,KAAK,EAAC,KAAK,EAAC,SAAS,EAAC,gBAAgB,EAAA,QAAA,EAAA,CACxD,WAAW,KACVA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,aAAa,EAAA,QAAA,EAAA,CAC1BC,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,iCAAiC,EAAA,QAAA,EAC7C,WAAW,EAAA,CACR,EACL,aAAa,KACZA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,2CAA2C,EAAA,QAAA,EACvD,aAAa,EAAA,CACV,CACP,CAAA,EAAA,CACG,CACP,EACDA,GAAA,CAAC,qBAAqB,EAAA,EAAA,CAAG,EACxB,WAAW,KACVA,GAAA,CAAC,gBAAgB,EAAA,EAAC,OAAO,EAAA,IAAA,EAAA,QAAA,EACvBD,IAAA,CAAC,IAAI,EAAA,EAAC,IAAI,EAAE,WAAW,EAAA,QAAA,EAAA,CACrBC,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,eAE5B,EAAA,CACU,CACpB,EACA,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AACvB,gDAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;AAC/C,gDAAA,QACEA,GAAA,CAAC,gBAAgB,EAAA,EAAiB,OAAO,EAAA,IAAA,EAAA,QAAA,EACvCD,IAAA,CAAC,IAAI,EAAA,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAA,QAAA,EAAA,CACnBC,GAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,EAC3B,IAAI,CAAC,KAAK,CAAA,EAAA,CACN,IAJc,IAAI,CAAC,IAAI,CAKb;AAEvB,4CAAA,CAAC,CAAC,EACD,CAAC,WAAW,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,MACpCA,GAAA,CAAC,qBAAqB,EAAA,EAAA,CAAG,CAC1B,EACDD,IAAA,CAAC,gBAAgB,EAAA,EACf,OAAO,EAAC,aAAa,EACrB,QAAQ,EAAE,MAAM,CAAC,SAAS,EAC1B,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,aAE9BC,GAAA,CAAC,MAAM,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,EAC7B,MAAM,CAAC,SAAS,GAAG,gBAAgB,GAAG,UAAU,IAChC,CAAA,EAAA,CACC,CAAA,EAAA,CACT,IACX,EAGND,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,mCAAmC,EAAA,QAAA,EAAA,CAC/C,aAAa,KACZC,GAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,gBACF,QAAQ,EACnB,SAAS,EAAC,sGAAsG,EAChH,OAAO,EAAE,aAAa,EAAA,QAAA,EAEtBA,GAAA,CAAC,MAAM,EAAA,EAAC,SAAS,EAAC,SAAS,GAAG,EAAA,CACvB,CACV,EACA,cAAc,KACbA,GAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,EAAA,YAAA,EACD,YAAY,GAAG,YAAY,GAAG,WAAW,EACrD,SAAS,EAAC,sGAAsG,EAChH,OAAO,EAAE,MAAM,eAAe,CAAC,CAAC,YAAY,CAAC,EAAA,QAAA,EAE5C,YAAY,IACXA,GAAA,CAAC,CAAC,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,KAEzBA,GAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,CAC7B,EAAA,CACM,CACV,CAAA,EAAA,CACG,CAAA,EAAA,CACF,EAGL,cAAc,IAAI,YAAY,KAC7BA,aACE,SAAS,EAAC,6CAA6C,EACvD,OAAO,EAAE,MAAM,eAAe,CAAC,KAAK,CAAC,EAAA,CACrC,CACH,EAEA,cAAc,KACbA,aACE,SAAS,EAAE,EAAE,CACX,iIAAiI,EACjI,4CAA4C,EAC5C,YAAY,GAAG,eAAe,GAAG,kBAAkB,CACpD,EACD,IAAI,EAAC,QAAQ,EAAA,YAAA,EACF,MAAM,gBACN,aAAa,EAAA,QAAA,EAExBD,cAAK,SAAS,EAAC,sBAAsB,EAAA,QAAA,EAAA,CACnCA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,2DAA2D,aACxEA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,yBAAyB,aACtCC,GAAA,CAAC,KAAK,IACJ,GAAG,EAAE,QAAQ,EACb,GAAG,EAAC,EAAE,EACN,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE,EACV,SAAS,EAAC,gCAAgC,GAC1C,EACFA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,uBAAuB,YAAE,KAAK,EAAA,CAAQ,EACtDA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,wGAAwG,EAAA,QAAA,EACrH,QAAQ,EAAA,CACJ,CAAA,EAAA,CACH,EACNA,GAAA,CAAA,QAAA,EAAA,EACE,IAAI,EAAC,QAAQ,gBACF,YAAY,EACvB,SAAS,EAAC,gGAAgG,EAC1G,OAAO,EAAE,MAAM,eAAe,CAAC,KAAK,CAAC,EAAA,QAAA,EAErCA,GAAA,CAAC,CAAC,EAAA,EAAC,SAAS,EAAC,SAAS,GAAG,EAAA,CAClB,CAAA,EAAA,CACL,EAEND,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,4BAA4B,EAAA,QAAA,EAAA,CACxC,WAAW,KACVA,cAAK,SAAS,EAAC,8BAA8B,EAAA,QAAA,EAAA,CAC3CC,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAC,uBAAuB,GAAG,EAC/CA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,qCAAqC,YAClD,WAAW,EAAA,CACP,IACH,CACP,EAEDA,IAAC,SAAS,EAAA,EAAC,SAAS,EAAC,MAAM,GAAG,EAE7B,OAAO,IAAIA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,MAAM,YAAE,OAAO,EAAA,CAAO,EAEjDA,GAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,WAAW,EAAA,QAAA,EACvB,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AAChB,wCAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;AAC/C,wCAAA,QACEA,GAAA,CAAC,IAAI,EAAA,EAEH,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,SAAS,EAAC,cAAc,EAAA,QAAA,EAExBD,IAAA,CAAA,QAAA,EAAA,EAAQ,SAAS,EAAC,0JAA0J,EAAA,QAAA,EAAA,CAC1KA,IAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,yBAAyB,EAAA,QAAA,EAAA,CACtCC,GAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,uBAAuB,GAAG,EAC1CA,GAAA,CAAA,MAAA,EAAA,EAAA,QAAA,EAAO,IAAI,CAAC,KAAK,EAAA,CAAQ,EACxB,CAAC,CAAC,IAAI,CAAC,KAAK,KACXA,GAAA,CAAA,MAAA,EAAA,EAAM,SAAS,EAAC,6HAA6H,EAAA,QAAA,EAAA,GAAA,EAAA,CAEtI,CACR,CAAA,EAAA,CACG,EACNA,GAAA,CAAC,YAAY,EAAA,EAAC,SAAS,EAAC,uBAAuB,EAAA,CAAG,CAAA,EAAA,CAC3C,EAAA,EAfJ,IAAI,CAAC,IAAI,CAgBT;oCAEX,CAAC,CAAC,GACE,CAAA,EAAA,CACF,EAEND,cAAK,SAAS,EAAC,sCAAsC,EAAA,QAAA,EAAA,CAClD,WAAW,KACVC,GAAA,CAAC,IAAI,EAAA,EAAC,IAAI,EAAE,WAAW,EAAE,SAAS,EAAC,cAAc,EAAA,QAAA,EAC/CD,iBAAQ,SAAS,EAAC,gGAAgG,EAAA,QAAA,EAAA,CAChHC,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,eAE1B,EAAA,CACJ,CACR,EACA,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,KAAI;AACvB,oCAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;AAC/C,oCAAA,QACEA,GAAA,CAAC,IAAI,EAAA,EAEH,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,SAAS,EAAC,cAAc,EAAA,QAAA,EAExBD,IAAA,CAAA,QAAA,EAAA,EAAQ,SAAS,EAAC,gGAAgG,EAAA,QAAA,EAAA,CAChHC,GAAA,CAAC,IAAI,EAAA,EAAC,SAAS,EAAC,SAAS,GAAG,EAC3B,IAAI,CAAC,KAAK,IACJ,EAAA,EAPJ,IAAI,CAAC,IAAI,CAQT;gCAEX,CAAC,CAAC,EACFD,IAAA,CAAA,QAAA,EAAA,EACE,OAAO,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,EAC9B,QAAQ,EAAE,MAAM,CAAC,SAAS,EAC1B,SAAS,EAAC,0HAA0H,EAAA,QAAA,EAAA,CAEpIC,GAAA,CAAC,MAAM,EAAA,EAAC,SAAS,EAAC,SAAS,EAAA,CAAG,EAC7B,MAAM,CAAC,SAAS,GAAG,gBAAgB,GAAG,UAAU,CAAA,EAAA,CAC1C,CAAA,EAAA,CACL,IACF,EAAA,CACF,CACP,CAAA,EAAA,CACM;AAEb;;;;"}
|
|
@@ -4,7 +4,7 @@ import { CheckIcon } from 'lucide-react';
|
|
|
4
4
|
import { cn } from '../../utils.js';
|
|
5
5
|
|
|
6
6
|
function Checkbox({ className, ...props }) {
|
|
7
|
-
return (jsx(CheckboxPrimitive.Root, { "data-slot": "checkbox", onClick: (e) => e.stopPropagation(), className: cn('peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 cursor-pointer rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50', className), ...props, children: jsx(CheckboxPrimitive.Indicator, { "data-slot": "checkbox-indicator", className: "flex items-center justify-center text-current transition-none", children: jsx(CheckIcon, { className: "size-3.5" }) }) }));
|
|
7
|
+
return (jsx(CheckboxPrimitive.Root, { "data-slot": "checkbox", onClick: (e) => e.stopPropagation(), className: cn('peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 cursor-pointer rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50', className), ...props, children: jsx(CheckboxPrimitive.Indicator, { "data-slot": "checkbox-indicator", className: "flex items-center justify-center text-current transition-none", children: jsx(CheckIcon, { className: "size-3.5 stroke-3" }) }) }));
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export { Checkbox };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkbox.js","sources":["../../../src/components/ui/checkbox.tsx"],"sourcesContent":["import * as React from 'react';\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox';\nimport { CheckIcon } from 'lucide-react';\n\nimport { cn } from '@/utils';\n\nfunction Checkbox({\n className,\n ...props\n}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n onClick={(e) => e.stopPropagation()}\n className={cn(\n 'peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 cursor-pointer rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"flex items-center justify-center text-current transition-none\"\n >\n <CheckIcon className=\"size-3.5\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n}\n\nexport { Checkbox };\n"],"names":["_jsx"],"mappings":";;;;;AAMA,SAAS,QAAQ,CAAC,EAChB,SAAS,EACT,GAAG,KAAK,EAC4C,EAAA;IACpD,QACEA,GAAA,CAAC,iBAAiB,CAAC,IAAI,iBACX,UAAU,EACpB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,eAAe,EAAE,EACnC,SAAS,EAAE,EAAE,CACX,4fAA4f,EAC5f,SAAS,CACV,EAAA,GACG,KAAK,EAAA,QAAA,EAETA,GAAA,CAAC,iBAAiB,CAAC,SAAS,EAAA,EAAA,WAAA,EAChB,oBAAoB,EAC9B,SAAS,EAAC,+DAA+D,EAAA,QAAA,EAEzEA,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAC,
|
|
1
|
+
{"version":3,"file":"checkbox.js","sources":["../../../src/components/ui/checkbox.tsx"],"sourcesContent":["import * as React from 'react';\nimport * as CheckboxPrimitive from '@radix-ui/react-checkbox';\nimport { CheckIcon } from 'lucide-react';\n\nimport { cn } from '@/utils';\n\nfunction Checkbox({\n className,\n ...props\n}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n onClick={(e) => e.stopPropagation()}\n className={cn(\n 'peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 cursor-pointer rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',\n className,\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"flex items-center justify-center text-current transition-none\"\n >\n <CheckIcon className=\"size-3.5 stroke-3\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n );\n}\n\nexport { Checkbox };\n"],"names":["_jsx"],"mappings":";;;;;AAMA,SAAS,QAAQ,CAAC,EAChB,SAAS,EACT,GAAG,KAAK,EAC4C,EAAA;IACpD,QACEA,GAAA,CAAC,iBAAiB,CAAC,IAAI,iBACX,UAAU,EACpB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,eAAe,EAAE,EACnC,SAAS,EAAE,EAAE,CACX,4fAA4f,EAC5f,SAAS,CACV,EAAA,GACG,KAAK,EAAA,QAAA,EAETA,GAAA,CAAC,iBAAiB,CAAC,SAAS,EAAA,EAAA,WAAA,EAChB,oBAAoB,EAC9B,SAAS,EAAC,+DAA+D,EAAA,QAAA,EAEzEA,GAAA,CAAC,SAAS,EAAA,EAAC,SAAS,EAAC,mBAAmB,EAAA,CAAG,EAAA,CACf,EAAA,CACP;AAE7B;;;;"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { Button } from './button.js';
|
|
3
|
-
|
|
4
|
-
const FloatingActionButton = ({ onClick, children }) => {
|
|
5
|
-
return (jsx(Button, { onClick: onClick, className: "fixed bottom-4 right-4 z-50 rounded-full p-4 shadow-lg bg-primary text-white hover:bg-primary-dark focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary", children: children }));
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export { FloatingActionButton };
|
|
9
|
-
//# sourceMappingURL=fab.js.map
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Button } from './button.js';
|
|
3
|
+
|
|
4
|
+
const FloatingActionButton = ({ onClick, children }) => {
|
|
5
|
+
return (jsx(Button, { onClick: onClick, className: "fixed bottom-4 right-4 z-50 rounded-full p-4 shadow-lg bg-primary text-white hover:bg-primary-dark focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary", children: children }));
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export { FloatingActionButton };
|
|
9
|
+
//# sourceMappingURL=fab.js.map
|
package/dist/config.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
interface PackageConfig {
|
|
2
|
-
orchestratorApi: string;
|
|
3
|
-
}
|
|
4
|
-
export declare let config: PackageConfig;
|
|
5
|
-
export declare const configure: (newConfig: PackageConfig) => void;
|
|
6
|
-
export {};
|
|
1
|
+
interface PackageConfig {
|
|
2
|
+
orchestratorApi: string;
|
|
3
|
+
}
|
|
4
|
+
export declare let config: PackageConfig;
|
|
5
|
+
export declare const configure: (newConfig: PackageConfig) => void;
|
|
6
|
+
export {};
|
package/dist/config.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
let config = {
|
|
2
|
-
orchestratorApi: 'https://orca.betterinternship.com/process',
|
|
3
|
-
};
|
|
4
|
-
const configure = (newConfig) => {
|
|
5
|
-
config = { ...config, ...newConfig };
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export { config, configure };
|
|
9
|
-
//# sourceMappingURL=config.js.map
|
|
1
|
+
let config = {
|
|
2
|
+
orchestratorApi: 'https://orca.betterinternship.com/process',
|
|
3
|
+
};
|
|
4
|
+
const configure = (newConfig) => {
|
|
5
|
+
config = { ...config, ...newConfig };
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export { config, configure };
|
|
9
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
interface ClientProcess<T> {
|
|
2
|
-
dto?: ProcessCallbackDto;
|
|
3
|
-
metadata?: ClientProcessMetadata;
|
|
4
|
-
options?: ClientProcessOptions;
|
|
5
|
-
result?: T;
|
|
6
|
-
success?: boolean;
|
|
7
|
-
pending?: boolean;
|
|
8
|
-
error?: string;
|
|
9
|
-
}
|
|
10
|
-
export interface ProcessCallbackDto {
|
|
11
|
-
processId: string;
|
|
12
|
-
processName: string;
|
|
13
|
-
processCallbackUrl: string;
|
|
14
|
-
}
|
|
15
|
-
export interface ClientProcessOptions {
|
|
16
|
-
onLoading?: (processId: string, processName: string) => void;
|
|
17
|
-
onSuccess?: <R>(processId: string, processName: string, result: R) => void;
|
|
18
|
-
onFailure?: (processId: string, processName: string, error?: string) => void;
|
|
19
|
-
}
|
|
20
|
-
export interface ClientProcessMetadata {
|
|
21
|
-
filterKey: string;
|
|
22
|
-
metadata?: Record<string, string>;
|
|
23
|
-
}
|
|
24
|
-
export interface ProcessResponse {
|
|
25
|
-
processId: string;
|
|
26
|
-
processName: string;
|
|
27
|
-
processCallbackUrl: string;
|
|
28
|
-
success: boolean;
|
|
29
|
-
message?: string;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* This should be at the root layout.
|
|
33
|
-
*
|
|
34
|
-
* @context
|
|
35
|
-
*/
|
|
36
|
-
export declare const ClientProcessesProvider: ({ children, }: {
|
|
37
|
-
children: React.ReactNode;
|
|
38
|
-
}) => import("react/jsx-runtime").JSX.Element;
|
|
39
|
-
/**
|
|
40
|
-
* A simpler version, where u just pass the async function that returns process data.
|
|
41
|
-
*
|
|
42
|
-
* @param caller
|
|
43
|
-
* @returns
|
|
44
|
-
*/
|
|
45
|
-
export declare function useClientProcess<T, R>({ caller, invalidator, filterKey, onLoading, onSuccess, onFailure, }: {
|
|
46
|
-
caller?: (inputs: T) => Promise<ProcessResponse>;
|
|
47
|
-
invalidator?: (result: R) => boolean;
|
|
48
|
-
filterKey: string;
|
|
49
|
-
onLoading?: (processId: string, processName: string) => void;
|
|
50
|
-
onSuccess?: <R>(processId: string, processName: string, result: R) => void;
|
|
51
|
-
onFailure?: (processId: string, processName: string, error?: string) => void;
|
|
52
|
-
}): {
|
|
53
|
-
run: (inputs: T, metadata?: Record<string, string>) => Promise<{
|
|
54
|
-
id: string;
|
|
55
|
-
success: boolean;
|
|
56
|
-
message: string | undefined;
|
|
57
|
-
} | {
|
|
58
|
-
id: null;
|
|
59
|
-
success: boolean;
|
|
60
|
-
message: string;
|
|
61
|
-
}>;
|
|
62
|
-
get: (id: string) => ClientProcess<unknown> | null;
|
|
63
|
-
getAll: () => ClientProcess<unknown>[];
|
|
64
|
-
getAllPending: () => ClientProcess<unknown>[];
|
|
65
|
-
getAllHandled: () => ClientProcess<unknown>[];
|
|
66
|
-
getAllFailed: () => ClientProcess<unknown>[];
|
|
67
|
-
refreshCache: () => Promise<void>;
|
|
68
|
-
};
|
|
69
|
-
export {};
|
|
1
|
+
interface ClientProcess<T> {
|
|
2
|
+
dto?: ProcessCallbackDto;
|
|
3
|
+
metadata?: ClientProcessMetadata;
|
|
4
|
+
options?: ClientProcessOptions;
|
|
5
|
+
result?: T;
|
|
6
|
+
success?: boolean;
|
|
7
|
+
pending?: boolean;
|
|
8
|
+
error?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ProcessCallbackDto {
|
|
11
|
+
processId: string;
|
|
12
|
+
processName: string;
|
|
13
|
+
processCallbackUrl: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ClientProcessOptions {
|
|
16
|
+
onLoading?: (processId: string, processName: string) => void;
|
|
17
|
+
onSuccess?: <R>(processId: string, processName: string, result: R) => void;
|
|
18
|
+
onFailure?: (processId: string, processName: string, error?: string) => void;
|
|
19
|
+
}
|
|
20
|
+
export interface ClientProcessMetadata {
|
|
21
|
+
filterKey: string;
|
|
22
|
+
metadata?: Record<string, string>;
|
|
23
|
+
}
|
|
24
|
+
export interface ProcessResponse {
|
|
25
|
+
processId: string;
|
|
26
|
+
processName: string;
|
|
27
|
+
processCallbackUrl: string;
|
|
28
|
+
success: boolean;
|
|
29
|
+
message?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* This should be at the root layout.
|
|
33
|
+
*
|
|
34
|
+
* @context
|
|
35
|
+
*/
|
|
36
|
+
export declare const ClientProcessesProvider: ({ children, }: {
|
|
37
|
+
children: React.ReactNode;
|
|
38
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
/**
|
|
40
|
+
* A simpler version, where u just pass the async function that returns process data.
|
|
41
|
+
*
|
|
42
|
+
* @param caller
|
|
43
|
+
* @returns
|
|
44
|
+
*/
|
|
45
|
+
export declare function useClientProcess<T, R>({ caller, invalidator, filterKey, onLoading, onSuccess, onFailure, }: {
|
|
46
|
+
caller?: (inputs: T) => Promise<ProcessResponse>;
|
|
47
|
+
invalidator?: (result: R) => boolean;
|
|
48
|
+
filterKey: string;
|
|
49
|
+
onLoading?: (processId: string, processName: string) => void;
|
|
50
|
+
onSuccess?: <R>(processId: string, processName: string, result: R) => void;
|
|
51
|
+
onFailure?: (processId: string, processName: string, error?: string) => void;
|
|
52
|
+
}): {
|
|
53
|
+
run: (inputs: T, metadata?: Record<string, string>) => Promise<{
|
|
54
|
+
id: string;
|
|
55
|
+
success: boolean;
|
|
56
|
+
message: string | undefined;
|
|
57
|
+
} | {
|
|
58
|
+
id: null;
|
|
59
|
+
success: boolean;
|
|
60
|
+
message: string;
|
|
61
|
+
}>;
|
|
62
|
+
get: (id: string) => ClientProcess<unknown> | null;
|
|
63
|
+
getAll: () => ClientProcess<unknown>[];
|
|
64
|
+
getAllPending: () => ClientProcess<unknown>[];
|
|
65
|
+
getAllHandled: () => ClientProcess<unknown>[];
|
|
66
|
+
getAllFailed: () => ClientProcess<unknown>[];
|
|
67
|
+
refreshCache: () => Promise<void>;
|
|
68
|
+
};
|
|
69
|
+
export {};
|
|
@@ -1,255 +1,255 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { createContext, useRef, useState, useEffect, useContext } from 'react';
|
|
4
|
-
import { useQueryClient, useQueries } from '@tanstack/react-query';
|
|
5
|
-
import { config } from '../config.js';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* The orchestrator service to get the process from.
|
|
9
|
-
*
|
|
10
|
-
* @param processId
|
|
11
|
-
* @returns
|
|
12
|
-
*/
|
|
13
|
-
const processStatusChecker = (processId) => {
|
|
14
|
-
if (!processId)
|
|
15
|
-
return { process: null };
|
|
16
|
-
return fetch(`${config.orchestratorApi}/${encodeURIComponent(processId)}`, {
|
|
17
|
-
method: 'GET',
|
|
18
|
-
headers: {
|
|
19
|
-
'Content-Type': 'application/json',
|
|
20
|
-
},
|
|
21
|
-
}).then((response) => response.json());
|
|
22
|
-
};
|
|
23
|
-
/**
|
|
24
|
-
* This fetches from the callback endpoint.
|
|
25
|
-
*
|
|
26
|
-
* @param processId
|
|
27
|
-
* @returns
|
|
28
|
-
*/
|
|
29
|
-
const processCallbackResultFetcher = (processId, processName, processCallbackUrl) => fetch(`${processCallbackUrl}`, {
|
|
30
|
-
method: 'POST',
|
|
31
|
-
headers: {
|
|
32
|
-
'Content-Type': 'application/json',
|
|
33
|
-
},
|
|
34
|
-
body: JSON.stringify({
|
|
35
|
-
processId,
|
|
36
|
-
processName,
|
|
37
|
-
}),
|
|
38
|
-
}).then((response) => response.json());
|
|
39
|
-
/**
|
|
40
|
-
* We need a context to keep track of all client processes.
|
|
41
|
-
* This helps us manage the state of the toasts as well.
|
|
42
|
-
*/
|
|
43
|
-
const clientProcessesContext = createContext({});
|
|
44
|
-
/**
|
|
45
|
-
* This should be at the root layout.
|
|
46
|
-
*
|
|
47
|
-
* @context
|
|
48
|
-
*/
|
|
49
|
-
const ClientProcessesProvider = ({ children, }) => {
|
|
50
|
-
const queryClient = useQueryClient();
|
|
51
|
-
const clientProcessAttempts = useRef({});
|
|
52
|
-
const [clientProcessDtos, setClientProcessDtos] = useState({});
|
|
53
|
-
// Populates the state object with cached data on mount
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
setClientProcessDtos((oldData) => {
|
|
56
|
-
if (Object.keys(oldData).length > 0)
|
|
57
|
-
return oldData;
|
|
58
|
-
const cachedClientProcesses = queryClient
|
|
59
|
-
.getQueryCache()
|
|
60
|
-
.findAll({ queryKey: ['.__process'], exact: false });
|
|
61
|
-
const seededClientProcesses = {};
|
|
62
|
-
for (const query of cachedClientProcesses) {
|
|
63
|
-
const processId = query.queryKey[2];
|
|
64
|
-
if (typeof processId !== 'string')
|
|
65
|
-
continue;
|
|
66
|
-
const data = query.state.data;
|
|
67
|
-
if (!data?.dto || !data?.metadata)
|
|
68
|
-
continue;
|
|
69
|
-
seededClientProcesses[processId] = {
|
|
70
|
-
dto: data.dto,
|
|
71
|
-
metadata: data.metadata,
|
|
72
|
-
options: data.options,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
return { ...oldData, ...seededClientProcesses };
|
|
76
|
-
});
|
|
77
|
-
}, [queryClient]);
|
|
78
|
-
// The query for all the processes, pending and sht
|
|
79
|
-
const clientProcesses = useQueries({
|
|
80
|
-
queries: Object.entries(clientProcessDtos).map(([processId, { dto, metadata, options }]) => ({
|
|
81
|
-
staleTime: Infinity,
|
|
82
|
-
gcTime: 3 * 60 * 1000,
|
|
83
|
-
refetchOnWindowFocus: true,
|
|
84
|
-
refetchIntervalInBackground: true,
|
|
85
|
-
refetchOnMount: true,
|
|
86
|
-
refetchOnReconnect: true,
|
|
87
|
-
queryKey: ['.__process', metadata.filterKey, processId],
|
|
88
|
-
queryFn: async () => {
|
|
89
|
-
if (!processId)
|
|
90
|
-
throw new Error('No processId');
|
|
91
|
-
const { process } = await processStatusChecker(processId);
|
|
92
|
-
// Handled! Return the proper response too
|
|
93
|
-
if (process?.status === 'handled') {
|
|
94
|
-
const result = await processCallbackResultFetcher(process.id, process.name, dto.processCallbackUrl);
|
|
95
|
-
// Log and call runner
|
|
96
|
-
console.warn(`Handled ${process.name} (${process.id})!`);
|
|
97
|
-
options?.onSuccess?.(process.id, process.name, result);
|
|
98
|
-
return {
|
|
99
|
-
dto,
|
|
100
|
-
metadata,
|
|
101
|
-
options,
|
|
102
|
-
success: true,
|
|
103
|
-
pending: false,
|
|
104
|
-
result,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
// Pending or failed
|
|
108
|
-
if (process?.status === 'pending') {
|
|
109
|
-
console.log(`Running process ${process.name} (${process.id})...`);
|
|
110
|
-
options?.onLoading?.(process.id, process.name);
|
|
111
|
-
return { dto, metadata, options, pending: true };
|
|
112
|
-
}
|
|
113
|
-
else if (process?.status === 'failed') {
|
|
114
|
-
console.error(`Failed ${process.name} (${process.id}) - ${process.error}.`);
|
|
115
|
-
return {
|
|
116
|
-
dto,
|
|
117
|
-
metadata,
|
|
118
|
-
options,
|
|
119
|
-
success: false,
|
|
120
|
-
pending: false,
|
|
121
|
-
error: process.error,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
// Return null since no response
|
|
125
|
-
return { dto, metadata, options, pending: true };
|
|
126
|
-
},
|
|
127
|
-
// Returns the next interval length to use to wait for fetch
|
|
128
|
-
refetchInterval: (query) => {
|
|
129
|
-
const data = query.state.data;
|
|
130
|
-
if (data?.success !== undefined)
|
|
131
|
-
return false;
|
|
132
|
-
// If not defined, init to 0
|
|
133
|
-
if (!clientProcessAttempts.current[processId])
|
|
134
|
-
clientProcessAttempts.current[processId] = 0;
|
|
135
|
-
const interval = Math.min(500 * 2 ** clientProcessAttempts.current[processId], 10000);
|
|
136
|
-
clientProcessAttempts.current[processId] += 1;
|
|
137
|
-
return interval;
|
|
138
|
-
},
|
|
139
|
-
})),
|
|
140
|
-
});
|
|
141
|
-
/**
|
|
142
|
-
* Registers a new process to handle
|
|
143
|
-
*
|
|
144
|
-
* @param processId
|
|
145
|
-
* @param processCallbackDto
|
|
146
|
-
* @param options
|
|
147
|
-
*/
|
|
148
|
-
const registerProcess = (processId, processCallbackDto, metadata, options) => {
|
|
149
|
-
setClientProcessDtos({
|
|
150
|
-
...clientProcessDtos,
|
|
151
|
-
[processId]: { dto: processCallbackDto, metadata, options },
|
|
152
|
-
});
|
|
153
|
-
};
|
|
154
|
-
/**
|
|
155
|
-
* Retrieves a process
|
|
156
|
-
*
|
|
157
|
-
* @param processId
|
|
158
|
-
* @returns
|
|
159
|
-
*/
|
|
160
|
-
const getProcess = (processId) => {
|
|
161
|
-
const clientProcess = clientProcesses.find((clientProcess) => clientProcess.data?.dto?.processId === processId)?.data ?? null;
|
|
162
|
-
return clientProcess ?? null;
|
|
163
|
-
};
|
|
164
|
-
/**
|
|
165
|
-
* Filters processes by the provided attribute.
|
|
166
|
-
*
|
|
167
|
-
* @param filterKey
|
|
168
|
-
*/
|
|
169
|
-
const filterProcesses = (filterKey) => {
|
|
170
|
-
return clientProcesses
|
|
171
|
-
.filter((clientProcess) => !!clientProcess.data?.dto)
|
|
172
|
-
.map((clientProcess) => clientProcess.data)
|
|
173
|
-
.filter((clientProcessData) => clientProcessData?.metadata.filterKey === filterKey);
|
|
174
|
-
};
|
|
175
|
-
/**
|
|
176
|
-
* Refreshes the cache and invalidates all related processes.
|
|
177
|
-
*/
|
|
178
|
-
const invalidateBasedOnResult = async (filter, invalidator) => {
|
|
179
|
-
await queryClient.invalidateQueries({
|
|
180
|
-
queryKey: ['.__process', filter],
|
|
181
|
-
exact: false,
|
|
182
|
-
});
|
|
183
|
-
const cachedClientProcesses = queryClient
|
|
184
|
-
.getQueryCache()
|
|
185
|
-
.findAll({ queryKey: ['.__process', filter], exact: false });
|
|
186
|
-
for (const query of cachedClientProcesses) {
|
|
187
|
-
const processId = query.queryKey[2];
|
|
188
|
-
if (typeof processId !== 'string')
|
|
189
|
-
continue;
|
|
190
|
-
const data = query.state.data;
|
|
191
|
-
if (!data.result)
|
|
192
|
-
continue;
|
|
193
|
-
// If invalidator says we gotta clear the cache, we clear it
|
|
194
|
-
if (invalidator && invalidator?.(data.result)) {
|
|
195
|
-
queryClient.removeQueries({ queryKey: query.queryKey });
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
};
|
|
199
|
-
return (jsx(clientProcessesContext.Provider, { value: {
|
|
200
|
-
registerProcess,
|
|
201
|
-
getProcess,
|
|
202
|
-
filterProcesses,
|
|
203
|
-
invalidateBasedOnResult,
|
|
204
|
-
}, children: children }));
|
|
205
|
-
};
|
|
206
|
-
/**
|
|
207
|
-
* A simpler version, where u just pass the async function that returns process data.
|
|
208
|
-
*
|
|
209
|
-
* @param caller
|
|
210
|
-
* @returns
|
|
211
|
-
*/
|
|
212
|
-
function useClientProcess({ caller, invalidator, filterKey, onLoading, onSuccess, onFailure, }) {
|
|
213
|
-
const clientProcessesApi = useContext(clientProcessesContext);
|
|
214
|
-
// Note that the exposed function doesn't return process ids
|
|
215
|
-
// Client should be oblivious to those
|
|
216
|
-
// Abstraction BABY!
|
|
217
|
-
const wrappedCaller = async (inputs, metadata) => {
|
|
218
|
-
const response = await caller?.(inputs);
|
|
219
|
-
if (response) {
|
|
220
|
-
clientProcessesApi.registerProcess(response.processId, response, { filterKey, metadata }, {
|
|
221
|
-
onLoading,
|
|
222
|
-
onSuccess,
|
|
223
|
-
onFailure,
|
|
224
|
-
});
|
|
225
|
-
return {
|
|
226
|
-
id: response.processId,
|
|
227
|
-
success: response.success,
|
|
228
|
-
message: response.message,
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
return {
|
|
232
|
-
id: null,
|
|
233
|
-
success: false,
|
|
234
|
-
message: 'No `caller` specified for useClientProcess().',
|
|
235
|
-
};
|
|
236
|
-
};
|
|
237
|
-
return {
|
|
238
|
-
run: wrappedCaller,
|
|
239
|
-
get: (id) => clientProcessesApi.getProcess(id),
|
|
240
|
-
getAll: () => clientProcessesApi.filterProcesses(filterKey),
|
|
241
|
-
getAllPending: () => clientProcessesApi
|
|
242
|
-
.filterProcesses(filterKey)
|
|
243
|
-
.filter((process) => process.pending),
|
|
244
|
-
getAllHandled: () => clientProcessesApi
|
|
245
|
-
.filterProcesses(filterKey)
|
|
246
|
-
.filter((process) => process.success),
|
|
247
|
-
getAllFailed: () => clientProcessesApi
|
|
248
|
-
.filterProcesses(filterKey)
|
|
249
|
-
.filter((process) => !process.success),
|
|
250
|
-
refreshCache: () => clientProcessesApi.invalidateBasedOnResult(filterKey, invalidator),
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export { ClientProcessesProvider, useClientProcess };
|
|
255
|
-
//# sourceMappingURL=useClientProcess.js.map
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { createContext, useRef, useState, useEffect, useContext } from 'react';
|
|
4
|
+
import { useQueryClient, useQueries } from '@tanstack/react-query';
|
|
5
|
+
import { config } from '../config.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The orchestrator service to get the process from.
|
|
9
|
+
*
|
|
10
|
+
* @param processId
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
const processStatusChecker = (processId) => {
|
|
14
|
+
if (!processId)
|
|
15
|
+
return { process: null };
|
|
16
|
+
return fetch(`${config.orchestratorApi}/${encodeURIComponent(processId)}`, {
|
|
17
|
+
method: 'GET',
|
|
18
|
+
headers: {
|
|
19
|
+
'Content-Type': 'application/json',
|
|
20
|
+
},
|
|
21
|
+
}).then((response) => response.json());
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* This fetches from the callback endpoint.
|
|
25
|
+
*
|
|
26
|
+
* @param processId
|
|
27
|
+
* @returns
|
|
28
|
+
*/
|
|
29
|
+
const processCallbackResultFetcher = (processId, processName, processCallbackUrl) => fetch(`${processCallbackUrl}`, {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: {
|
|
32
|
+
'Content-Type': 'application/json',
|
|
33
|
+
},
|
|
34
|
+
body: JSON.stringify({
|
|
35
|
+
processId,
|
|
36
|
+
processName,
|
|
37
|
+
}),
|
|
38
|
+
}).then((response) => response.json());
|
|
39
|
+
/**
|
|
40
|
+
* We need a context to keep track of all client processes.
|
|
41
|
+
* This helps us manage the state of the toasts as well.
|
|
42
|
+
*/
|
|
43
|
+
const clientProcessesContext = createContext({});
|
|
44
|
+
/**
|
|
45
|
+
* This should be at the root layout.
|
|
46
|
+
*
|
|
47
|
+
* @context
|
|
48
|
+
*/
|
|
49
|
+
const ClientProcessesProvider = ({ children, }) => {
|
|
50
|
+
const queryClient = useQueryClient();
|
|
51
|
+
const clientProcessAttempts = useRef({});
|
|
52
|
+
const [clientProcessDtos, setClientProcessDtos] = useState({});
|
|
53
|
+
// Populates the state object with cached data on mount
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
setClientProcessDtos((oldData) => {
|
|
56
|
+
if (Object.keys(oldData).length > 0)
|
|
57
|
+
return oldData;
|
|
58
|
+
const cachedClientProcesses = queryClient
|
|
59
|
+
.getQueryCache()
|
|
60
|
+
.findAll({ queryKey: ['.__process'], exact: false });
|
|
61
|
+
const seededClientProcesses = {};
|
|
62
|
+
for (const query of cachedClientProcesses) {
|
|
63
|
+
const processId = query.queryKey[2];
|
|
64
|
+
if (typeof processId !== 'string')
|
|
65
|
+
continue;
|
|
66
|
+
const data = query.state.data;
|
|
67
|
+
if (!data?.dto || !data?.metadata)
|
|
68
|
+
continue;
|
|
69
|
+
seededClientProcesses[processId] = {
|
|
70
|
+
dto: data.dto,
|
|
71
|
+
metadata: data.metadata,
|
|
72
|
+
options: data.options,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return { ...oldData, ...seededClientProcesses };
|
|
76
|
+
});
|
|
77
|
+
}, [queryClient]);
|
|
78
|
+
// The query for all the processes, pending and sht
|
|
79
|
+
const clientProcesses = useQueries({
|
|
80
|
+
queries: Object.entries(clientProcessDtos).map(([processId, { dto, metadata, options }]) => ({
|
|
81
|
+
staleTime: Infinity,
|
|
82
|
+
gcTime: 3 * 60 * 1000,
|
|
83
|
+
refetchOnWindowFocus: true,
|
|
84
|
+
refetchIntervalInBackground: true,
|
|
85
|
+
refetchOnMount: true,
|
|
86
|
+
refetchOnReconnect: true,
|
|
87
|
+
queryKey: ['.__process', metadata.filterKey, processId],
|
|
88
|
+
queryFn: async () => {
|
|
89
|
+
if (!processId)
|
|
90
|
+
throw new Error('No processId');
|
|
91
|
+
const { process } = await processStatusChecker(processId);
|
|
92
|
+
// Handled! Return the proper response too
|
|
93
|
+
if (process?.status === 'handled') {
|
|
94
|
+
const result = await processCallbackResultFetcher(process.id, process.name, dto.processCallbackUrl);
|
|
95
|
+
// Log and call runner
|
|
96
|
+
console.warn(`Handled ${process.name} (${process.id})!`);
|
|
97
|
+
options?.onSuccess?.(process.id, process.name, result);
|
|
98
|
+
return {
|
|
99
|
+
dto,
|
|
100
|
+
metadata,
|
|
101
|
+
options,
|
|
102
|
+
success: true,
|
|
103
|
+
pending: false,
|
|
104
|
+
result,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
// Pending or failed
|
|
108
|
+
if (process?.status === 'pending') {
|
|
109
|
+
console.log(`Running process ${process.name} (${process.id})...`);
|
|
110
|
+
options?.onLoading?.(process.id, process.name);
|
|
111
|
+
return { dto, metadata, options, pending: true };
|
|
112
|
+
}
|
|
113
|
+
else if (process?.status === 'failed') {
|
|
114
|
+
console.error(`Failed ${process.name} (${process.id}) - ${process.error}.`);
|
|
115
|
+
return {
|
|
116
|
+
dto,
|
|
117
|
+
metadata,
|
|
118
|
+
options,
|
|
119
|
+
success: false,
|
|
120
|
+
pending: false,
|
|
121
|
+
error: process.error,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
// Return null since no response
|
|
125
|
+
return { dto, metadata, options, pending: true };
|
|
126
|
+
},
|
|
127
|
+
// Returns the next interval length to use to wait for fetch
|
|
128
|
+
refetchInterval: (query) => {
|
|
129
|
+
const data = query.state.data;
|
|
130
|
+
if (data?.success !== undefined)
|
|
131
|
+
return false;
|
|
132
|
+
// If not defined, init to 0
|
|
133
|
+
if (!clientProcessAttempts.current[processId])
|
|
134
|
+
clientProcessAttempts.current[processId] = 0;
|
|
135
|
+
const interval = Math.min(500 * 2 ** clientProcessAttempts.current[processId], 10000);
|
|
136
|
+
clientProcessAttempts.current[processId] += 1;
|
|
137
|
+
return interval;
|
|
138
|
+
},
|
|
139
|
+
})),
|
|
140
|
+
});
|
|
141
|
+
/**
|
|
142
|
+
* Registers a new process to handle
|
|
143
|
+
*
|
|
144
|
+
* @param processId
|
|
145
|
+
* @param processCallbackDto
|
|
146
|
+
* @param options
|
|
147
|
+
*/
|
|
148
|
+
const registerProcess = (processId, processCallbackDto, metadata, options) => {
|
|
149
|
+
setClientProcessDtos({
|
|
150
|
+
...clientProcessDtos,
|
|
151
|
+
[processId]: { dto: processCallbackDto, metadata, options },
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Retrieves a process
|
|
156
|
+
*
|
|
157
|
+
* @param processId
|
|
158
|
+
* @returns
|
|
159
|
+
*/
|
|
160
|
+
const getProcess = (processId) => {
|
|
161
|
+
const clientProcess = clientProcesses.find((clientProcess) => clientProcess.data?.dto?.processId === processId)?.data ?? null;
|
|
162
|
+
return clientProcess ?? null;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Filters processes by the provided attribute.
|
|
166
|
+
*
|
|
167
|
+
* @param filterKey
|
|
168
|
+
*/
|
|
169
|
+
const filterProcesses = (filterKey) => {
|
|
170
|
+
return clientProcesses
|
|
171
|
+
.filter((clientProcess) => !!clientProcess.data?.dto)
|
|
172
|
+
.map((clientProcess) => clientProcess.data)
|
|
173
|
+
.filter((clientProcessData) => clientProcessData?.metadata.filterKey === filterKey);
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Refreshes the cache and invalidates all related processes.
|
|
177
|
+
*/
|
|
178
|
+
const invalidateBasedOnResult = async (filter, invalidator) => {
|
|
179
|
+
await queryClient.invalidateQueries({
|
|
180
|
+
queryKey: ['.__process', filter],
|
|
181
|
+
exact: false,
|
|
182
|
+
});
|
|
183
|
+
const cachedClientProcesses = queryClient
|
|
184
|
+
.getQueryCache()
|
|
185
|
+
.findAll({ queryKey: ['.__process', filter], exact: false });
|
|
186
|
+
for (const query of cachedClientProcesses) {
|
|
187
|
+
const processId = query.queryKey[2];
|
|
188
|
+
if (typeof processId !== 'string')
|
|
189
|
+
continue;
|
|
190
|
+
const data = query.state.data;
|
|
191
|
+
if (!data.result)
|
|
192
|
+
continue;
|
|
193
|
+
// If invalidator says we gotta clear the cache, we clear it
|
|
194
|
+
if (invalidator && invalidator?.(data.result)) {
|
|
195
|
+
queryClient.removeQueries({ queryKey: query.queryKey });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
return (jsx(clientProcessesContext.Provider, { value: {
|
|
200
|
+
registerProcess,
|
|
201
|
+
getProcess,
|
|
202
|
+
filterProcesses,
|
|
203
|
+
invalidateBasedOnResult,
|
|
204
|
+
}, children: children }));
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* A simpler version, where u just pass the async function that returns process data.
|
|
208
|
+
*
|
|
209
|
+
* @param caller
|
|
210
|
+
* @returns
|
|
211
|
+
*/
|
|
212
|
+
function useClientProcess({ caller, invalidator, filterKey, onLoading, onSuccess, onFailure, }) {
|
|
213
|
+
const clientProcessesApi = useContext(clientProcessesContext);
|
|
214
|
+
// Note that the exposed function doesn't return process ids
|
|
215
|
+
// Client should be oblivious to those
|
|
216
|
+
// Abstraction BABY!
|
|
217
|
+
const wrappedCaller = async (inputs, metadata) => {
|
|
218
|
+
const response = await caller?.(inputs);
|
|
219
|
+
if (response) {
|
|
220
|
+
clientProcessesApi.registerProcess(response.processId, response, { filterKey, metadata }, {
|
|
221
|
+
onLoading,
|
|
222
|
+
onSuccess,
|
|
223
|
+
onFailure,
|
|
224
|
+
});
|
|
225
|
+
return {
|
|
226
|
+
id: response.processId,
|
|
227
|
+
success: response.success,
|
|
228
|
+
message: response.message,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
id: null,
|
|
233
|
+
success: false,
|
|
234
|
+
message: 'No `caller` specified for useClientProcess().',
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
return {
|
|
238
|
+
run: wrappedCaller,
|
|
239
|
+
get: (id) => clientProcessesApi.getProcess(id),
|
|
240
|
+
getAll: () => clientProcessesApi.filterProcesses(filterKey),
|
|
241
|
+
getAllPending: () => clientProcessesApi
|
|
242
|
+
.filterProcesses(filterKey)
|
|
243
|
+
.filter((process) => process.pending),
|
|
244
|
+
getAllHandled: () => clientProcessesApi
|
|
245
|
+
.filterProcesses(filterKey)
|
|
246
|
+
.filter((process) => process.success),
|
|
247
|
+
getAllFailed: () => clientProcessesApi
|
|
248
|
+
.filterProcesses(filterKey)
|
|
249
|
+
.filter((process) => !process.success),
|
|
250
|
+
refreshCache: () => clientProcessesApi.invalidateBasedOnResult(filterKey, invalidator),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export { ClientProcessesProvider, useClientProcess };
|
|
255
|
+
//# sourceMappingURL=useClientProcess.js.map
|