@tradalab/lyra 2.0.1 → 2.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/people/types.ts","../../src/people/person-row.tsx","../../src/people/use-principal-search.ts","../../src/people/people-picker.tsx","../../src/people/people-field.tsx"],"names":["React2","jsxs","jsx","React3"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * The shape the pickers render.\n *\n * Deliberately NOT contact's `Person` type. lyra must not know that a service called\n * contact exists: if it imported that type, every field contact adds would force a\n * lyra release and re-lock every app that consumes it. Each app maps its own DTO onto\n * this in about five lines, and only that app changes when its source changes.\n *\n * It covers people AND groups/orgs because the pickers are used to grant access as\n * often as to address a message, and \"share with the Legal team\" is the same gesture\n * as \"share with Ada\".\n */\nexport interface Principal<T = unknown> {\n /**\n * The caller's own object, handed straight back on select.\n *\n * A picker's job is to answer \"which one\", but the app almost always needs more\n * than what it renders — contact needs the contactId to open the right editor,\n * drive needs the grantee kind. Without this the app has to rebuild a lookup from\n * the key it just handed out, which is a map that exists only because the type\n * threw information away.\n */\n data?: T\n /** Stable id in the caller's world: a uid, a group id, an org id. */\n id?: string\n email?: string\n displayName?: string\n avatarUrl?: string\n /** One line under the name: a title, an org, \"in your contacts\". */\n subtitle?: string\n kind?: \"person\" | \"group\" | \"org\"\n}\n\n/**\n * How the app finds candidates. Injected, never implemented here.\n *\n * An EMPTY query is a legitimate call and should return the caller's recent or\n * frequent people — that is what makes a picker feel like it knows you rather than\n * like a search box you have to feed first.\n *\n * The signal is passed so a fast typist does not race their own requests; the picker\n * aborts the previous lookup on every keystroke.\n */\nexport type PrincipalSearch<T = unknown> = (\n query: string,\n signal?: AbortSignal,\n) => Promise<Principal<T>[]>\n\n/** Labels are injected: lyra ships no copy and no i18n runtime. */\nexport interface PeopleLabels {\n placeholder?: string\n /** Shown while the list is empty and nothing has been typed. */\n hint?: string\n noResults?: string\n /** Offer to use a typed address that matched nothing, e.g. \"Use {email}\". */\n useTyped?: string\n /** Marks an entry the caller excluded, e.g. \"already added\". */\n excluded?: string\n remove?: string\n}\n\n/** A plausible email. Not RFC-complete on purpose — this gates a UI affordance,\n * and the server validates for real. Being strict here only refuses addresses that\n * actually work. */\nexport function looksLikeEmail(s: string): boolean {\n const v = s.trim()\n return v.length >= 3 && !/\\s/.test(v) && /^[^@]+@[^@.]+\\.[^@]+$/.test(v)\n}\n\n/** The key a principal is deduped and excluded by. */\nexport function principalKey(p: Principal<unknown>): string {\n return (p.id || p.email || p.displayName || \"\").toLowerCase()\n}\n","\"use client\"\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"~/ui/primitives/avatar.js\"\nimport { cn } from \"~/utils/index.js\"\nimport type { Principal } from \"./types.js\"\n\n/**\n * Initials for the avatar fallback. Falls back through name → email → \"?\" so a\n * principal that is nothing but a typed address still renders as something.\n */\nexport function initials(p: Principal): string {\n const src = (p.displayName || \"\").trim() || p.email || \"?\"\n const parts = src.split(/\\s+/).filter(Boolean)\n if (parts.length >= 2 && parts[0] && parts[1]) {\n return (parts[0][0]! + parts[1][0]!).toUpperCase()\n }\n return src.slice(0, 2).toUpperCase()\n}\n\nexport function PersonAvatar({\n principal,\n className,\n}: {\n principal: Principal\n className?: string\n}) {\n return (\n <Avatar className={className}>\n {principal.avatarUrl ? (\n <AvatarImage src={principal.avatarUrl} alt={principal.displayName ?? \"\"} />\n ) : null}\n <AvatarFallback className=\"text-xs\">{initials(principal)}</AvatarFallback>\n </Avatar>\n )\n}\n\n/**\n * One line: avatar, name, and whatever the app chose to say underneath.\n *\n * Shared by the picker, the token field and any table that lists people — a person\n * rendered three different ways in three apps is how a suite stops feeling like one\n * product.\n */\nexport function PersonRow({\n principal,\n className,\n trailing,\n}: {\n principal: Principal\n className?: string\n /** Slot for whatever the caller attaches per person: a role select, a remove button. */\n trailing?: React.ReactNode\n}) {\n const name = principal.displayName || principal.email || \"—\"\n // The subtitle is dropped when it would just repeat the name — a row reading\n // \"ada@x.com / ada@x.com\" is noise.\n const sub = principal.subtitle && principal.subtitle !== name ? principal.subtitle : undefined\n\n return (\n <div className={cn(\"flex min-w-0 items-center gap-3\", className)}>\n <PersonAvatar principal={principal} className=\"size-8 shrink-0\" />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-sm font-medium\">{name}</div>\n {sub ? <div className=\"text-muted-foreground truncate text-xs\">{sub}</div> : null}\n </div>\n {trailing}\n </div>\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport type { Principal, PrincipalSearch } from \"./types.js\"\nimport { principalKey } from \"./types.js\"\n\nexport interface UsePrincipalSearchOptions<T = unknown> {\n search: PrincipalSearch<T>\n /** Keys (id or email) to mark as already chosen. */\n exclude?: string[]\n /** Milliseconds to wait after the last keystroke. */\n debounceMs?: number\n limit?: number\n}\n\nexport interface PrincipalSearchState<T = unknown> {\n query: string\n setQuery: (q: string) => void\n results: Principal<T>[]\n loading: boolean\n error: string | null\n /** Excluded keys, lowercased — the UI dims these rather than hiding them. */\n excluded: Set<string>\n}\n\n/**\n * The behaviour both pickers share: debounce, abort the previous request, keep the\n * last results visible while the next ones load.\n *\n * Two decisions worth keeping:\n *\n * - **Results are NOT cleared while loading.** Emptying the list on every keystroke\n * makes a picker flicker between \"here they are\" and \"nothing found\", and users\n * read that flash as a failed search.\n * - **Excluded entries stay in the list, dimmed.** Removing them makes the search\n * look broken to the one person who most expects a hit — \"I know Ada is in here,\n * why can't I find her?\" — when the truth is she is already added.\n */\nexport function usePrincipalSearch<T = unknown>({\n search,\n exclude,\n debounceMs = 200,\n limit,\n}: UsePrincipalSearchOptions<T>): PrincipalSearchState<T> {\n const [query, setQuery] = React.useState(\"\")\n const [results, setResults] = React.useState<Principal<T>[]>([])\n const [loading, setLoading] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n\n const excluded = React.useMemo(\n () => new Set((exclude ?? []).filter(Boolean).map((k) => k.toLowerCase())),\n [exclude],\n )\n\n // Keep the latest search in a ref: a caller that re-creates the function every\n // render must not cancel and refire the request on every render.\n const searchRef = React.useRef(search)\n searchRef.current = search\n\n React.useEffect(() => {\n const controller = new AbortController()\n let cancelled = false\n\n const timer = setTimeout(() => {\n setLoading(true)\n setError(null)\n searchRef\n .current(query, controller.signal)\n .then((found) => {\n if (cancelled) return\n const seen = new Set<string>()\n const deduped = found.filter((p) => {\n const k = principalKey(p)\n if (!k || seen.has(k)) return false\n seen.add(k)\n return true\n })\n setResults(limit ? deduped.slice(0, limit) : deduped)\n })\n .catch((e: unknown) => {\n // An abort is the normal path on every keystroke, not a failure.\n if (cancelled || (e instanceof DOMException && e.name === \"AbortError\")) return\n setError(e instanceof Error ? e.message : String(e))\n })\n .finally(() => {\n if (!cancelled) setLoading(false)\n })\n // An empty query still searches: that is how recents appear before typing.\n }, query ? debounceMs : 0)\n\n return () => {\n cancelled = true\n controller.abort()\n clearTimeout(timer)\n }\n }, [query, debounceMs, limit])\n\n return { query, setQuery, results, loading, error, excluded }\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronsUpDown } from \"lucide-react\"\nimport { Button } from \"~/ui/primitives/button.js\"\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"~/ui/primitives/command.js\"\nimport { Popover, PopoverContent, PopoverTrigger } from \"~/ui/primitives/popover.js\"\nimport { cn } from \"~/utils/index.js\"\nimport { PersonRow } from \"./person-row.js\"\nimport type { PeopleLabels, Principal, PrincipalSearch } from \"./types.js\"\nimport { looksLikeEmail, principalKey } from \"./types.js\"\nimport { usePrincipalSearch } from \"./use-principal-search.js\"\n\nexport interface PeoplePickerProps<T = unknown> {\n /** Injected by the app — lyra never knows where people come from. */\n search: PrincipalSearch<T>\n onSelect: (p: Principal<T>) => void\n /** Already-chosen keys (id or email): shown dimmed, not hidden. */\n exclude?: string[]\n /**\n * Offer a typed address that matched nothing. Essential wherever the other party\n * is a stranger by definition (a contract counterparty), and wrong wherever they\n * must already exist (adding somebody to an org).\n */\n allowFreeEntry?: boolean\n labels?: PeopleLabels\n disabled?: boolean\n className?: string\n}\n\n/**\n * Pick one person (or group, or org), from a popover.\n *\n * Filtering is SERVER-side — `shouldFilter={false}` — because ranking is the point:\n * the backend knows who this user actually works with, and cmdk's local fuzzy match\n * would reorder that into alphabetical noise.\n */\nexport function PeoplePicker<T = unknown>({\n search,\n onSelect,\n exclude,\n allowFreeEntry,\n labels,\n disabled,\n className,\n}: PeoplePickerProps<T>) {\n const [open, setOpen] = React.useState(false)\n const { query, setQuery, results, loading, excluded } = usePrincipalSearch({\n search,\n exclude,\n })\n\n const typedEmail = allowFreeEntry && looksLikeEmail(query) ? query.trim() : \"\"\n const alreadyListed = results.some((p) => p.email?.toLowerCase() === typedEmail.toLowerCase())\n const offerTyped = typedEmail !== \"\" && !alreadyListed\n\n function choose(p: Principal<T>) {\n onSelect(p)\n setOpen(false)\n setQuery(\"\")\n }\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n disabled={disabled}\n className={cn(\"text-muted-foreground w-full justify-between font-normal\", className)}\n >\n {labels?.placeholder ?? \"Search people\"}\n <ChevronsUpDown className=\"size-4 opacity-50\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent className=\"w-[22rem] p-0\" align=\"start\">\n <Command shouldFilter={false}>\n <CommandInput\n value={query}\n onValueChange={setQuery}\n placeholder={labels?.placeholder ?? \"Search people\"}\n />\n <CommandList>\n {results.length === 0 && !offerTyped && !loading ? (\n <CommandEmpty>\n {query ? (labels?.noResults ?? \"No matches\") : (labels?.hint ?? \"Start typing\")}\n </CommandEmpty>\n ) : null}\n\n {offerTyped ? (\n <CommandGroup>\n <CommandItem\n value=\"__typed__\"\n onSelect={() => choose({ email: typedEmail, kind: \"person\" })}\n >\n <PersonRow\n principal={{ email: typedEmail, displayName: typedEmail }}\n // The affordance has to name the address, or it reads as a\n // generic \"add\" and people do not trust it with a contract.\n />\n <span className=\"text-muted-foreground ml-auto shrink-0 text-xs\">\n {labels?.useTyped ?? \"Use this address\"}\n </span>\n </CommandItem>\n </CommandGroup>\n ) : null}\n\n {results.length > 0 ? (\n <CommandGroup>\n {results.map((p, i) => {\n const off = excluded.has(principalKey(p))\n return (\n <CommandItem\n key={principalKey(p) || i}\n value={String(i)}\n disabled={off}\n onSelect={() => !off && choose(p)}\n className={cn(off && \"opacity-50\")}\n >\n <PersonRow principal={p} />\n {off ? (\n <span className=\"text-muted-foreground ml-auto shrink-0 text-xs\">\n {labels?.excluded ?? \"already added\"}\n </span>\n ) : null}\n </CommandItem>\n )\n })}\n </CommandGroup>\n ) : null}\n </CommandList>\n </Command>\n </PopoverContent>\n </Popover>\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { X } from \"lucide-react\"\nimport { Input } from \"~/ui/primitives/input.js\"\nimport { cn } from \"~/utils/index.js\"\nimport { PersonAvatar, PersonRow } from \"./person-row.js\"\nimport type { PeopleLabels, Principal, PrincipalSearch } from \"./types.js\"\nimport { looksLikeEmail, principalKey } from \"./types.js\"\nimport { usePrincipalSearch } from \"./use-principal-search.js\"\n\nexport interface PeopleFieldProps<T = unknown> {\n search: PrincipalSearch<T>\n /** Chosen so far — rendered as tokens. */\n value: Principal<T>[]\n onAdd: (p: Principal<T>) => void\n onRemove: (p: Principal<T>) => void\n allowFreeEntry?: boolean\n labels?: PeopleLabels\n disabled?: boolean\n className?: string\n}\n\n/**\n * A To:-style token field: type, pick, repeat.\n *\n * The popover picker and this are NOT the same component with a flag. A \"To\" line is\n * used dozens of times a minute and lives or dies on keyboard flow — type, Enter,\n * type, Enter, Backspace to undo — whereas a share dialog is opened once and clicked\n * through. Forcing one into the other's shape produces something that is bad at both.\n *\n * Paste is handled: a list copied out of a spreadsheet or another mail client arrives\n * as \"a@x.com, b@y.com; c@z.com\" and becomes three tokens, because the alternative is\n * the user hand-splitting it.\n */\nexport function PeopleField<T = unknown>({\n search,\n value,\n onAdd,\n onRemove,\n allowFreeEntry,\n labels,\n disabled,\n className,\n}: PeopleFieldProps<T>) {\n const [focused, setFocused] = React.useState(false)\n const exclude = React.useMemo(() => value.map(principalKey), [value])\n const { query, setQuery, results, excluded } = usePrincipalSearch({ search, exclude, limit: 6 })\n\n const chosen = React.useMemo(() => new Set(exclude), [exclude])\n const typedEmail = allowFreeEntry && looksLikeEmail(query) ? query.trim() : \"\"\n\n function add(p: Principal<T>) {\n const k = principalKey(p)\n if (!k || chosen.has(k)) return\n onAdd(p)\n setQuery(\"\")\n }\n\n function onKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {\n if ((e.key === \"Enter\" || e.key === \"Tab\" || e.key === \",\") && query.trim()) {\n // Enter takes the top-ranked match, or the typed address. Anything else would\n // make the common case — the person you meant is first — need the mouse.\n const pick = results.find((p) => !excluded.has(principalKey(p)))\n if (pick) {\n e.preventDefault()\n add(pick)\n } else if (typedEmail) {\n e.preventDefault()\n add({ email: typedEmail, kind: \"person\" })\n }\n return\n }\n // Backspace on an empty box removes the last token — the universal behaviour of\n // every mail client, and the first thing a user tries.\n if (e.key === \"Backspace\" && query === \"\" && value.length > 0) {\n onRemove(value[value.length - 1]!)\n }\n }\n\n function onPaste(e: React.ClipboardEvent<HTMLInputElement>) {\n const text = e.clipboardData.getData(\"text\")\n const parts = text.split(/[,;\\s]+/).map((s) => s.trim()).filter(Boolean)\n if (parts.length < 2) return // one token: let it type normally\n e.preventDefault()\n for (const part of parts) {\n if (looksLikeEmail(part)) add({ email: part, kind: \"person\" })\n }\n }\n\n return (\n <div className={cn(\"space-y-2\", className)}>\n <div\n className={cn(\n \"border-input focus-within:ring-ring flex min-h-10 flex-wrap items-center gap-1.5 rounded-md border px-2 py-1.5 focus-within:ring-1\",\n disabled && \"opacity-50\",\n )}\n >\n {value.map((p) => (\n <span\n key={principalKey(p)}\n className=\"bg-muted flex items-center gap-1.5 rounded-full py-0.5 pl-0.5 pr-2 text-xs\"\n >\n <PersonAvatar principal={p} className=\"size-5\" />\n <span className=\"max-w-40 truncate\">{p.displayName || p.email}</span>\n <button\n type=\"button\"\n aria-label={labels?.remove ?? \"Remove\"}\n onClick={() => onRemove(p)}\n disabled={disabled}\n className=\"opacity-60 hover:opacity-100\"\n >\n <X className=\"size-3\" />\n </button>\n </span>\n ))}\n <Input\n value={query}\n disabled={disabled}\n placeholder={value.length === 0 ? (labels?.placeholder ?? \"Add people\") : undefined}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n onFocus={() => setFocused(true)}\n // Delayed so a click on a suggestion lands before the list unmounts.\n onBlur={() => setTimeout(() => setFocused(false), 150)}\n className=\"h-7 min-w-40 flex-1 border-0 bg-transparent px-1 shadow-none focus-visible:ring-0\"\n />\n </div>\n\n {focused && (results.length > 0 || typedEmail) ? (\n <div className=\"bg-popover max-h-64 overflow-auto rounded-md border p-1 shadow-md\">\n {typedEmail && !results.some((p) => p.email === typedEmail) ? (\n <button\n type=\"button\"\n onClick={() => add({ email: typedEmail, kind: \"person\" })}\n className=\"hover:bg-accent flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left\"\n >\n <PersonRow principal={{ email: typedEmail, displayName: typedEmail }} />\n <span className=\"text-muted-foreground ml-auto shrink-0 text-xs\">\n {labels?.useTyped ?? \"Use this address\"}\n </span>\n </button>\n ) : null}\n {results.map((p) => {\n const off = excluded.has(principalKey(p))\n return (\n <button\n key={principalKey(p)}\n type=\"button\"\n disabled={off}\n onClick={() => add(p)}\n className={cn(\n \"hover:bg-accent flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left\",\n off && \"opacity-50\",\n )}\n >\n <PersonRow principal={p} />\n {off ? (\n <span className=\"text-muted-foreground ml-auto shrink-0 text-xs\">\n {labels?.excluded ?? \"already added\"}\n </span>\n ) : null}\n </button>\n )\n })}\n </div>\n ) : null}\n </div>\n )\n}\n"]}
@@ -1,8 +1,10 @@
1
1
  "use client";
2
- import { SidebarInset, SidebarProvider, Sidebar, SidebarGroup, SidebarGroupLabel, SidebarGroupContent, SidebarMenu, SidebarMenuItem, SidebarMenuButton, useSidebar, defaultAccountMenuLabels, Avatar, AvatarImage, AvatarFallback, initialsOf, ScrollArea, ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ScrollBar, Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbPage, BreadcrumbLink, BreadcrumbSeparator, InputGroup, InputGroupAddon, InputGroupInput } from '../chunk-2PHVSGAE.js';
2
+ import { SidebarInset, SidebarProvider, Sidebar, SidebarGroup, SidebarGroupLabel, SidebarGroupContent, SidebarMenu, SidebarMenuItem, SidebarMenuButton, useSidebar, defaultAccountMenuLabels, initialsOf, ScrollArea, ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ScrollBar, Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbPage, BreadcrumbLink, BreadcrumbSeparator } from '../chunk-F5HR244O.js';
3
3
  import '../chunk-QYA2HGKW.js';
4
4
  import { Card, CardTitle, CardDescription } from '../chunk-LZZ3UOPT.js';
5
- import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuSeparator, DropdownMenuLabel, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuItem } from '../chunk-SQA4ILAK.js';
5
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuSeparator, DropdownMenuLabel, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuItem } from '../chunk-VEWKPOMS.js';
6
+ import { Avatar, AvatarImage, AvatarFallback, InputGroup, InputGroupAddon, InputGroupInput } from '../chunk-7GY2KYNW.js';
7
+ import '../chunk-PI6SANLG.js';
6
8
  import { Button } from '../chunk-5Q4UTRYU.js';
7
9
  import { cn } from '../chunk-XH55BHUU.js';
8
10
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/shell/app-shell.tsx","../../src/shell/stacked-sidebar.tsx","../../src/shell/nav-group.tsx","../../src/shell/use-active-route.ts","../../src/shell/nav-item.tsx","../../src/shell/nav-section.tsx","../../src/shell/nav-brand.tsx","../../src/shell/app-glyph.tsx","../../src/shell/app-switcher.tsx","../../src/shell/nav-user.tsx","../../src/shell/tab-bar.tsx","../../src/shell/breadcrumbs.tsx","../../src/shell/app-grid.tsx"],"names":["jsx","jsxs","Link","Fragment","ChevronsUpDown"],"mappings":";;;;;;;;;;;;;;AAqCO,SAAS,QAAA,CAAS,EAAE,QAAA,EAAU,GAAG,MAAK,EAAkB;AAC7D,EAAA,uBAAO,GAAA,CAAC,eAAA,EAAA,EAAiB,GAAG,IAAA,EAAO,QAAA,EAAS,CAAA;AAC9C;AAGO,IAAM,YAAA,GAAe;AAGrB,SAAS,cAAA,CAAe;AAAA,EAC7B,SAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAA6B;AAC3B,EAAA,uBACE,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,qDAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG,IAAA;AAAA,MAEH;AAAA;AAAA,GACH;AAEJ;AAGO,SAAS,YAAA,CAAa;AAAA,EAC3B,SAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAA0B;AACxB,EAAA,uBACE,GAAA,CAAC,SAAI,SAAA,EAAW,EAAA,CAAG,wBAAwB,SAAS,CAAA,EAAI,GAAG,IAAA,EACxD,QAAA,EACH,CAAA;AAEJ;AC3CO,SAAS,cAAA,CAAe;AAAA,EAC7B,SAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAmC;AACjC,EAAA,uBACEA,GAAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAQ,SAAA;AAAA,MACR,WAAA,EAAY,MAAA;AAAA,MACX,GAAG,IAAA;AAAA,MACJ,SAAA,EAAW,EAAA;AAAA,QACT,mDAAA;AAAA,QACA;AAAA;AACF;AAAA,GACF;AAEJ;AAUO,SAAS,WAAA,CAAY;AAAA,EAC1B,SAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAmC;AACjC,EAAA,uBACEA,GAAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,WAAA,EAAY,MAAA;AAAA,MACZ,SAAA,EAAW,EAAA;AAAA,QACT,mEAAA;AAAA,QACA;AAAA;AACF;AAAA,GACF;AAEJ;AAMO,SAAS,YAAA,CAAa;AAAA,EAC3B,SAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAmC;AACjC,EAAA,uBACEA,GAAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,WAAA,EAAY,MAAA;AAAA,MACZ,SAAA,EAAW,EAAA,CAAG,wBAAA,EAA0B,SAAS;AAAA;AAAA,GACnD;AAEJ;ACxEO,SAAS,QAAA,CAAS,EAAE,KAAA,EAAO,QAAA,EAAS,EAAkB;AAC3D,EAAA,4BACG,YAAA,EAAA,EACE,QAAA,EAAA;AAAA,IAAA,KAAA,IAAS,IAAA,mBAAOA,GAAAA,CAAC,iBAAA,EAAA,EAAmB,iBAAM,CAAA,GAAuB,IAAA;AAAA,oBAClEA,GAAAA,CAAC,mBAAA,EAAA,EACC,0BAAAA,GAAAA,CAAC,WAAA,EAAA,EAAa,UAAS,CAAA,EACzB;AAAA,GAAA,EACF,CAAA;AAEJ;ACPO,SAAS,cAAA,GAAiC;AAC/C,EAAA,MAAM,QAAA,GAAW,aAAY,IAAK,GAAA;AAClC,EAAA,OAAO;AAAA,IACL,QAAA;AAAA,IACA,QAAA,EAAU,CAAC,IAAA,EAAM,IAAA,GAAO,QAAA,KAAa;AACnC,MAAA,IAAI,IAAA,KAAS,OAAA,IAAW,IAAA,KAAS,GAAA,SAAY,QAAA,KAAa,IAAA;AAC1D,MAAA,OAAO,aAAa,IAAA,IAAQ,QAAA,CAAS,UAAA,CAAW,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,IAC5D;AAAA,GACF;AACF;ACbA,IAAM,aAAA,GAAgB,CAAC,IAAA,KACrB,6BAAA,CAA8B,KAAK,IAAI,CAAA,IAAK,iBAAA,CAAkB,IAAA,CAAK,IAAI,CAAA;AAoBlE,SAAS,OAAA,CAAQ;AAAA,EACtB,IAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA,GAAY,QAAA;AAAA,EACZ;AACF,CAAA,EAAiB;AACf,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,cAAA,EAAe;AACpC,EAAA,MAAM,UAAA,GAAa,QAAA,IAAY,aAAA,CAAc,IAAI,CAAA;AACjD,EAAA,uBACEA,GAAAA,CAAC,eAAA,EAAA,EACC,QAAA,kBAAAA,GAAAA;AAAA,IAAC,iBAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAO,IAAA;AAAA,MACP,QAAA,EAAU,CAAC,UAAA,IAAc,QAAA,CAAS,MAAM,SAAS,CAAA;AAAA,MACjD,OAAA;AAAA,MAEC,QAAA,EAAA,UAAA,mBACCC,IAAAA,CAAC,GAAA,EAAA,EAAE,MAAY,MAAA,EAAO,QAAA,EAAS,KAAI,qBAAA,EAChC,QAAA,EAAA;AAAA,QAAA,IAAA;AAAA,wBACDD,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,KAAA,EAAM;AAAA,OAAA,EACf,CAAA,mBAEAC,IAAAA,CAACC,KAAA,EAAA,EAAK,IAAA,EACH,QAAA,EAAA;AAAA,QAAA,IAAA;AAAA,wBACDF,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,KAAA,EAAM;AAAA,OAAA,EACf;AAAA;AAAA,GAEJ,EACF,CAAA;AAEJ;ACxCO,SAAS,UAAA,CAAW,EAAE,KAAA,EAAO,KAAA,EAAM,EAAoB;AAC5D,EAAA,uBACEA,GAAAA,CAAC,QAAA,EAAA,EAAS,KAAA,EACP,QAAA,EAAA,KAAA,CAAM,IAAI,CAAC,IAAA,qBACVA,GAAAA,CAAC,WAAyB,GAAG,IAAA,EAAA,EAAf,IAAA,CAAK,IAAgB,CACpC,CAAA,EACH,CAAA;AAEJ;AC+BO,IAAM,wBAAA,GAA2B;AAGxC,SAAS,YAAA,CAAa,EAAE,GAAA,EAAI,EAAyB;AACnD,EAAA,uBACEC,IAAAA,CAAAE,UAAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAAH,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sIAAA,EACZ,cAAI,IAAA,EACP,CAAA;AAAA,oBACAC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6CAAA,EACb,QAAA,EAAA;AAAA,sBAAAD,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,wBAAA,EAA0B,cAAI,IAAA,EAAK,CAAA;AAAA,MAClD,GAAA,CAAI,8BACHA,GAAAA,CAAC,UAAK,SAAA,EAAU,wCAAA,EACb,QAAA,EAAA,GAAA,CAAI,WAAA,EACP,CAAA,GACE;AAAA,KAAA,EACN;AAAA,GAAA,EACF,CAAA;AAEJ;AAGA,SAAS,MAAA,CAAO,EAAE,GAAA,EAAI,EAAyB;AAC7C,EAAA,uBACEA,GAAAA,CAAC,gBAAA,EAAA,EAAiB,OAAA,EAAO,IAAA,EAAC,SAAA,EAAU,WAAA,EAClC,QAAA,kBAAAC,IAAAA,CAAC,GAAA,EAAA,EAAE,IAAA,EAAM,GAAA,CAAI,IAAA,EACX,QAAA,EAAA;AAAA,oBAAAD,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8EAAA,EACZ,cAAI,IAAA,EACP,CAAA;AAAA,oBACAA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,UAAA,EAAY,cAAI,IAAA,EAAK;AAAA,GAAA,EACvC,CAAA,EACF,CAAA;AAEJ;AAuBO,SAAS,QAAA,CAAS;AAAA,EACvB,GAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA,GAAY,wBAAA;AAAA,EACZ;AACF,CAAA,EAAkB;AAChB,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,UAAA,EAAW;AAChC,EAAA,MAAM,UAAA,GAAa,MAAA,EAAQ,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAA,CAAE,IAAA,CAAK,MAAA,EAAQ,CAAC,CAAA,IAAK,CAAA;AACrE,EAAA,MAAM,eAAe,IAAA,EAAM,MAAA,IAAU,KAAK,CAAA,IAAK,UAAA,GAAa,KAAK,QAAA,IAAY,IAAA;AAE7E,EAAA,uBACEA,IAAC,WAAA,EAAA,EACC,QAAA,kBAAAA,IAAC,eAAA,EAAA,EACE,QAAA,EAAA,WAAA,mBACCC,IAAAA,CAAC,YAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAAD,GAAAA,CAAC,mBAAA,EAAA,EAAoB,OAAA,EAAO,IAAA,EAC1B,QAAA,kBAAAC,IAAAA;AAAA,MAAC,iBAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,IAAA;AAAA,QACL,SAAS,GAAA,CAAI,IAAA;AAAA,QACb,SAAA,EAAU,sFAAA;AAAA,QAEV,QAAA,EAAA;AAAA,0BAAAD,GAAAA,CAAC,gBAAa,GAAA,EAAU,CAAA;AAAA,0BACxBA,GAAAA,CAAC,cAAA,EAAA,EAAe,SAAA,EAAU,gBAAA,EAAiB;AAAA;AAAA;AAAA,KAC7C,EACF,CAAA;AAAA,oBACAC,IAAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAU,+DAAA;AAAA,QACV,KAAA,EAAM,OAAA;AAAA,QACN,IAAA,EAAM,WAAW,QAAA,GAAW,OAAA;AAAA,QAC5B,UAAA,EAAY,CAAA;AAAA,QAEX,QAAA,EAAA;AAAA,UAAA,UAAA,GAAa,CAAA,GACZ,OAAQ,GAAA,CAAI,CAAC,GAAG,CAAA,qBACdA,KAAC,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,YAAA,CAAA,GAAI,CAAA,mBAAID,GAAAA,CAAC,qBAAA,EAAA,EAAsB,CAAA,GAAK,IAAA;AAAA,YACpC,CAAA,CAAE,wBACDA,GAAAA,CAAC,qBAAkB,SAAA,EAAU,+BAAA,EAC1B,QAAA,EAAA,CAAA,CAAE,KAAA,EACL,CAAA,GACE,IAAA;AAAA,YACH,CAAA,CAAE,IAAA,CAAK,GAAA,CAAI,CAAC,IAAA,qBACXA,GAAAA,CAAC,MAAA,EAAA,EAAuB,GAAA,EAAK,IAAA,EAAA,EAAhB,IAAA,CAAK,IAAiB,CACpC;AAAA,WAAA,EAAA,EATY,EAAE,GAUjB,CACD,oBAEDC,IAAAA,CAAAE,YAAA,EACE,QAAA,EAAA;AAAA,4BAAAH,GAAAA,CAAC,iBAAA,EAAA,EAAkB,SAAA,EAAU,+BAAA,EAC1B,QAAA,EAAA,SAAA,EACH,CAAA;AAAA,YACC,IAAA,EAAM,GAAA,CAAI,CAAC,IAAA,qBACVA,GAAAA,CAAC,MAAA,EAAA,EAAuB,GAAA,EAAK,IAAA,EAAA,EAAhB,IAAA,CAAK,IAAiB,CACpC;AAAA,WAAA,EACH,CAAA;AAAA,UAED,QAAA,mBACCC,IAAAA,CAAAE,UAAAA,EAAA,EACE,QAAA,EAAA;AAAA,4BAAAH,IAAC,qBAAA,EAAA,EAAsB,CAAA;AAAA,YACtB;AAAA,WAAA,EACH,CAAA,GACE;AAAA;AAAA;AAAA;AACN,GAAA,EACF,CAAA,mBAEAA,GAAAA,CAAC,iBAAA,EAAA,EAAkB,IAAA,EAAK,MAAK,OAAA,EAAO,IAAA,EAAC,OAAA,EAAS,GAAA,CAAI,IAAA,EAChD,QAAA,kBAAAA,IAAC,GAAA,EAAA,EAAE,IAAA,EAAM,GAAA,CAAI,IAAA,EACX,QAAA,kBAAAA,GAAAA,CAAC,gBAAa,GAAA,EAAU,CAAA,EAC1B,CAAA,EACF,CAAA,EAEJ,CAAA,EACF,CAAA;AAEJ;ACjLO,IAAM,cAAA,GAAsC;AAEnD,IAAM,aAAA,GAAgB,IAAI,GAAA,CAAY,SAAS,CAAA;AAGxC,SAAS,WAAW,IAAA,EAAsB;AAC/C,EAAA,OAAO,IAAA,CACJ,QAAQ,oBAAA,EAAsB,OAAO,EACrC,OAAA,CAAQ,SAAA,EAAW,GAAG,CAAA,CACtB,WAAA,EAAY;AACjB;AAGO,SAAS,aAAa,IAAA,EAAuB;AAClD,EAAA,OAAO,aAAA,CAAc,GAAA,CAAI,UAAA,CAAW,IAAI,CAAC,CAAA;AAC3C;AAGO,IAAM,UAAA,GAAuB;AAAA,EAClC,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,SAAA;AAAA,EACvD,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW,SAAA;AAAA,EACvD,SAAA;AAAA,EAAW,SAAA;AAAA,EAAW;AACxB;AAEO,SAAS,UAAU,CAAA,EAAoB;AAC5C,EAAA,OAAO,iBAAA,CAAkB,IAAA,CAAK,CAAC,CAAA,IAAK,CAAA,CAAE,WAAW,GAAG,CAAA,IAAK,CAAA,CAAE,UAAA,CAAW,OAAO,CAAA;AAC/E;AAGA,SAAS,IAAA,CAAK,KAAa,KAAA,EAAuB;AAChD,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,GAAG,CAAA,CAAE,QAAA,CAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAA;AAC9D,EAAA,OAAO,mBAAA,CAAoB,KAAK,GAAG,CAAA,GAAI,GAAG,GAAG,CAAA,EAAG,CAAC,CAAA,CAAA,GAAK,GAAA;AACxD;AAaO,SAAS,SAAS,EAAE,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,WAAU,EAAkB;AACxE,EAAA,MAAM,GAAA,GAAM,EAAA,CAAG,+DAAA,EAAiE,SAAS,CAAA;AAEzF,EAAA,IAAI,IAAA,IAAQ,SAAA,CAAU,IAAI,CAAA,EAAG;AAC3B,IAAA,uBACEA,GAAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,aAAA,EAAW,IAAA;AAAA,QACX,SAAA,EAAW,EAAA,CAAG,GAAA,EAAK,6BAA6B,CAAA;AAAA,QAChD,OAAO,EAAE,eAAA,EAAiB,QAAQ,SAAA,CAAU,IAAI,CAAC,CAAA,EAAA,CAAA;AAAK;AAAA,KACxD;AAAA,EAEJ;AAEA,EAAA,MAAM,IAAA,GAAO,QAAQ,EAAE,eAAA,EAAiB,KAAK,KAAA,EAAO,IAAI,GAAE,GAAI,MAAA;AAC9D,EAAA,MAAM,EAAA,GAAK,KAAA,GAAQ,EAAE,KAAA,EAAM,GAAI,MAAA;AAC/B,EAAA,MAAM,QAAA,GAAW,IAAA,GAAO,UAAA,CAAW,IAAI,CAAA,GAAI,EAAA;AAE3C,EAAA,IAAI,QAAA,IAAY,aAAA,CAAc,GAAA,CAAI,QAAQ,CAAA,EAAG;AAC3C,IAAA,uBACEA,GAAAA,CAAC,MAAA,EAAA,EAAK,aAAA,EAAW,MAAC,SAAA,EAAW,EAAA,CAAG,GAAA,EAAK,CAAC,KAAA,IAAS,eAAe,CAAA,EAAG,KAAA,EAAO,MACtE,QAAA,kBAAAA,GAAAA;AAAA,MAAC,WAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAM,QAAA;AAAA,QACN,SAAA,EAAW,EAAA,CAAG,QAAA,EAAU,CAAC,SAAS,cAAc,CAAA;AAAA,QAChD,KAAA,EAAO;AAAA;AAAA,KACT,EACF,CAAA;AAAA,EAEJ;AAEA,EAAA,MAAM,MAAM,IAAA,IAAQ,IAAA,IAAQ,KAAK,MAAA,CAAO,CAAC,EAAE,WAAA,EAAY;AACvD,EAAA,uBACEA,GAAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,aAAA,EAAW,IAAA;AAAA,MACX,WAAW,EAAA,CAAG,GAAA,EAAK,uBAAA,EAAyB,CAAC,SAAS,4BAA4B,CAAA;AAAA,MAClF,OAAO,KAAA,GAAQ,EAAE,GAAG,IAAA,EAAM,GAAG,IAAG,GAAI,MAAA;AAAA,MAEnC,QAAA,EAAA;AAAA;AAAA,GACH;AAEJ;AC9CO,SAAS,WAAA,CAAY;AAAA,EAC1B,GAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,MAAA,GAA0B,QAAA,CAC7B,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,CAC/B,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IACX,KAAK,CAAA,CAAE,GAAA;AAAA,IACP,OAAO,CAAA,CAAE,KAAA;AAAA,IACT,IAAA,EAAM,CAAA,CAAE,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACvB,MAAM,CAAA,CAAE,IAAA;AAAA,MACR,aAAa,CAAA,CAAE,WAAA;AAAA,MACf,MAAM,CAAA,CAAE,GAAA;AAAA,MACR,IAAA,kBAAMA,GAAAA,CAAC,QAAA,EAAA,EAAS,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM,KAAA,EAAO,CAAA,CAAE,KAAA,EAAO,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM;AAAA,KAC9D,CAAE;AAAA,GACJ,CAAE,CAAA;AAEJ,EAAA,uBACEA,GAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,GAAA;AAAA,MACA,MAAA,EAAQ,MAAA,CAAO,MAAA,GAAS,MAAA,GAAS,MAAA;AAAA,MACjC,IAAA,EAAM,MAAA,CAAO,MAAA,GAAS,MAAA,GAAY,QAAA;AAAA,MAClC;AAAA;AAAA,GACF;AAEJ;AChCO,IAAM,yBAAA,GAAgD;AAAA,EAC3D,KAAA,EAAO,OAAA;AAAA,EACP,KAAA,EAAO,OAAA;AAAA,EACP,IAAA,EAAM,MAAA;AAAA,EACN,MAAA,EAAQ;AACV;AA2BA,IAAM,MAAA,GAAS;AAAA,EACb,EAAE,KAAA,EAAO,OAAA,EAAS,GAAA,EAAK,OAAA,EAAS,MAAM,GAAA,EAAI;AAAA,EAC1C,EAAE,KAAA,EAAO,MAAA,EAAQ,GAAA,EAAK,MAAA,EAAQ,MAAM,IAAA,EAAK;AAAA,EACzC,EAAE,KAAA,EAAO,QAAA,EAAU,GAAA,EAAK,QAAA,EAAU,MAAM,OAAA;AAC1C,CAAA;AA8BO,SAAS,OAAA,CAAQ;AAAA,EACtB,IAAA;AAAA,EACA,MAAA;AAAA,EACA,eAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA,GAAY,IAAA;AAAA,EACZ,WAAA;AAAA,EACA;AACF,CAAA,EAAiB;AACf,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,UAAA,EAAW;AAChC,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAS,GAAI,QAAA,EAAS;AACrC,EAAA,MAAM,CAAA,GAAI,EAAE,GAAG,wBAAA,EAA0B,GAAG,MAAA,EAAO;AACnD,EAAA,MAAM,CAAA,GAAI,EAAE,GAAG,yBAAA,EAA2B,GAAG,WAAA,EAAY;AAGzD,EAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,QAAA,EAAU,OAAO,IAAA;AAE/B,EAAA,MAAM,IAAA,GAAO,OAAQ,IAAA,CAAK,IAAA,IAAQ,KAAK,KAAA,IAAS,CAAA,CAAE,UAAW,CAAA,CAAE,KAAA;AAC/D,EAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,IAAS,EAAA;AAE7B,EAAA,MAAM,MAAA,mBACJC,IAAAA,CAAC,MAAA,EAAA,EAAO,WAAU,wCAAA,EACf,QAAA,EAAA;AAAA,IAAA,IAAA,EAAM,KAAA,mBACLD,GAAAA,CAAC,WAAA,EAAA,EAAY,SAAA,EAAU,cAAA,EAAe,GAAA,EAAK,IAAA,CAAK,KAAA,EAAO,GAAA,EAAK,IAAA,EAAM,CAAA,GAChE,IAAA;AAAA,oBACJA,GAAAA,CAAC,cAAA,EAAA,EAAe,SAAA,EAAU,gBACvB,QAAA,EAAA,IAAA,GAAO,UAAA,CAAW,IAAI,CAAA,mBAAIA,GAAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAU,UAAS,CAAA,EAC5D;AAAA,GAAA,EACF,CAAA;AAGF,EAAA,MAAM,YAAA,GAAe,SAAA,mBACnBC,IAAAA,CAAAE,YAAA,EACE,QAAA,EAAA;AAAA,oBAAAH,IAAC,qBAAA,EAAA,EAAsB,CAAA;AAAA,oBACvBC,KAAC,eAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAAA,KAAC,sBAAA,EAAA,EACC,QAAA,EAAA;AAAA,wBAAAD,GAAAA,CAAC,OAAA,EAAA,EAAQ,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,QAChC,CAAA,CAAE;AAAA,OAAA,EACL,CAAA;AAAA,sBACAA,IAAC,sBAAA,EAAA,EACC,QAAA,kBAAAA,IAAC,sBAAA,EAAA,EAAuB,KAAA,EAAO,KAAA,IAAS,QAAA,EAAU,aAAA,EAAe,QAAA,EAC9D,iBAAO,GAAA,CAAI,CAAC,EAAE,KAAA,EAAO,GAAA,EAAK,IAAA,EAAM,MAAK,qBACpCC,IAAAA,CAAC,qBAAA,EAAA,EAAkC,KAAA,EACjC,QAAA,EAAA;AAAA,wBAAAD,GAAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,QAC7B,EAAE,GAAG;AAAA,OAAA,EAAA,EAFoB,KAG5B,CACD,CAAA,EACH,CAAA,EACF;AAAA,KAAA,EACF;AAAA,GAAA,EACF,CAAA,GACE,IAAA;AAEJ,EAAA,uBACEA,IAAC,WAAA,EAAA,EACC,QAAA,kBAAAA,IAAC,eAAA,EAAA,EACC,QAAA,kBAAAC,KAAC,YAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAAD,GAAAA,CAAC,mBAAA,EAAA,EAAoB,OAAA,EAAO,IAAA,EAC1B,QAAA,kBAAAC,IAAAA;AAAA,MAAC,iBAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,IAAA;AAAA,QACL,OAAA,EAAS,IAAA;AAAA,QACT,SAAA,EAAU,sFAAA;AAAA,QAET,QAAA,EAAA;AAAA,UAAA,MAAA;AAAA,0BACDA,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6CAAA,EACb,QAAA,EAAA;AAAA,4BAAAD,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,sBAAA,EAAwB,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,YAC5C,wBACCA,GAAAA,CAAC,UAAK,SAAA,EAAU,wCAAA,EACb,iBACH,CAAA,GACE;AAAA,WAAA,EACN,CAAA;AAAA,0BACAA,GAAAA,CAACI,cAAAA,EAAA,EAAe,WAAU,gBAAA,EAAiB;AAAA;AAAA;AAAA,KAC7C,EACF,CAAA;AAAA,oBACAH,IAAAA;AAAA,MAAC,mBAAA;AAAA,MAAA;AAAA,QACC,SAAA,EAAU,kDAAA;AAAA,QACV,IAAA,EAAM,WAAW,QAAA,GAAW,OAAA;AAAA,QAC5B,KAAA,EAAM,KAAA;AAAA,QACN,UAAA,EAAY,CAAA;AAAA,QAEZ,QAAA,EAAA;AAAA,0BAAAA,IAAAA,CAAC,iBAAA,EAAA,EAAkB,SAAA,EAAU,yBAAA,EAC1B,QAAA,EAAA;AAAA,YAAA,MAAA;AAAA,4BACDA,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qCAAA,EACb,QAAA,EAAA;AAAA,8BAAAD,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,8BAAA,EAAgC,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,cACpD,wBACCA,GAAAA,CAAC,UAAK,SAAA,EAAU,oDAAA,EACb,iBACH,CAAA,GACE;AAAA,aAAA,EACN;AAAA,WAAA,EACF,CAAA;AAAA,UAEC,YAAA;AAAA,UAEA,QAAA,mBACCC,IAAAA,CAAAE,UAAAA,EAAA,EACE,QAAA,EAAA;AAAA,4BAAAH,IAAC,qBAAA,EAAA,EAAsB,CAAA;AAAA,YACtB;AAAA,WAAA,EACH,CAAA,GACE,IAAA;AAAA,UAEH,IAAA,mBACCC,IAAAA,CAAAE,UAAAA,EAAA,EACG,QAAA,EAAA;AAAA,YAAA,eAAA,IAAmB,SAAA,mBAAYH,GAAAA,CAAC,qBAAA,EAAA,EAAsB,CAAA,GAAK,IAAA;AAAA,YAC3D,eAAA,mBACCC,IAAAA,CAAC,gBAAA,EAAA,EAAiB,UAAU,eAAA,EAC1B,QAAA,EAAA;AAAA,8BAAAD,GAAAA,CAAC,YAAA,EAAA,EAAa,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,cACrC,CAAA,CAAE;AAAA,aAAA,EACL,CAAA,GACE,IAAA;AAAA,YACH,4BACCC,IAAAA,CAAC,oBAAiB,OAAA,EAAQ,aAAA,EAAc,UAAU,SAAA,EAChD,QAAA,EAAA;AAAA,8BAAAD,GAAAA,CAAC,MAAA,EAAA,EAAO,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,cAC/B,CAAA,CAAE;AAAA,aAAA,EACL,CAAA,GACE;AAAA,WAAA,EACN,CAAA,mBAEAC,IAAAA,CAAAE,UAAAA,EAAA,EACE,QAAA,EAAA;AAAA,4BAAAH,IAAC,qBAAA,EAAA,EAAsB,CAAA;AAAA,4BACvBC,IAAAA,CAAC,gBAAA,EAAA,EAAiB,QAAA,EAAU,QAAA,EAC1B,QAAA,EAAA;AAAA,8BAAAD,GAAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,cAC9B,CAAA,CAAE;AAAA,aAAA,EACL;AAAA,WAAA,EACF;AAAA;AAAA;AAAA;AAEJ,GAAA,EACF,GACF,CAAA,EACF,CAAA;AAEJ;ACjNO,IAAM,mBAAA,GAAoC;AAAA,EAC/C,KAAA,EAAO,OAAA;AAAA,EACP,MAAA,EAAQ,SAAA;AAAA,EACR,QAAA,EAAU,WAAA;AAAA,EACV,WAAA,EAAa,cAAA;AAAA,EACb,QAAA,EAAU;AACZ;AAqCO,SAAS,MAAA,CAAO;AAAA,EACrB,IAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,EAAgB;AACd,EAAA,MAAM,CAAA,GAAI,EAAE,GAAG,mBAAA,EAAqB,GAAG,MAAA,EAAO;AAC9C,EAAA,MAAM,YAAA,GAAe,OAAuB,IAAI,CAAA;AAGhD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAA,IAAY,aAAa,OAAA,EAAS;AACpC,MAAA,YAAA,CAAa,QAAQ,cAAA,CAAe;AAAA,QAClC,QAAA,EAAU,QAAA;AAAA,QACV,KAAA,EAAO,SAAA;AAAA,QACP,MAAA,EAAQ;AAAA,OACT,CAAA;AAAA,IACH;AAAA,EACF,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAGb,EAAA,MAAM,WAAA,GAAc,CAAC,CAAA,KAAkC;AACrD,IAAA,IAAI,IAAA,CAAK,IAAI,CAAA,CAAE,MAAM,IAAI,IAAA,CAAK,GAAA,CAAI,CAAA,CAAE,MAAM,CAAA,EAAG;AAC3C,MAAA,MAAM,QAAA,GAAW,EAAE,aAAA,CAAc,aAAA;AAAA,QAC/B;AAAA,OACF;AACA,MAAA,IAAI,QAAA,EAAU,QAAA,CAAS,UAAA,IAAc,CAAA,CAAE,MAAA,GAAS,GAAA;AAAA,IAClD;AAAA,EACF,CAAA;AAEA,EAAA,IAAI,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAE9B,EAAA,MAAM,iBAAA,GAAoB,OAAA,CAAQ,WAAA,IAAe,aAAA,IAAiB,UAAU,CAAA;AAE5E,EAAA,uBACEC,IAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,qFAAA;AAAA,MACV,KAAA,EAAO,EAAE,MAAA,EAAQ,mBAAA,EAAoB;AAAA,MAErC,QAAA,EAAA;AAAA,wBAAAA,IAAAA;AAAA,UAAC,UAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,OAAA;AAAA,YACL,SAAA,EAAU,uEAAA;AAAA,YACV,OAAA,EAAS,WAAA;AAAA,YAET,QAAA,EAAA;AAAA,8BAAAD,GAAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAU,+BAAA;AAAA,kBACV,KAAA,EAAO,EAAE,MAAA,EAAQ,mBAAA,EAAoB;AAAA,kBAEpC,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AACjB,oBAAA,MAAM,QAAA,GAAW,aAAa,GAAA,CAAI,EAAA;AAClC,oBAAA,uBACEC,KAAC,WAAA,EAAA,EACC,QAAA,EAAA;AAAA,sCAAAD,GAAAA,CAAC,kBAAA,EAAA,EAAmB,OAAA,EAAO,IAAA,EACzB,QAAA,kBAAAC,IAAAA;AAAA,wBAAC,KAAA;AAAA,wBAAA;AAAA,0BACC,GAAA,EAAK,WAAW,YAAA,GAAe,IAAA;AAAA,0BAC/B,OAAA,EAAS,MAAM,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAAA,0BAC9B,OAAO,GAAA,CAAI,KAAA;AAAA,0BACX,SAAA,EAAW,EAAA;AAAA,4BACT,wIAAA;AAAA,4BACA,WACI,2CAAA,GACA,wFAAA;AAAA,4BACJ,IAAI,MAAA,IAAU;AAAA,2BAChB;AAAA,0BACA,KAAA,EAAO,EAAE,MAAA,EAAQ,mBAAA,EAAoB;AAAA,0BAEpC,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAI,IAAA,mBACHA,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,mBAAA,EACb,QAAA,EAAA;AAAA,8CAAAD,GAAAA;AAAA,gCAAC,MAAA;AAAA,gCAAA;AAAA,kCACC,SAAA,EAAW,EAAA;AAAA,oCACT,uBAAA;AAAA,oCACA,QAAA,IAAY;AAAA,mCACd;AAAA,kCAEC,QAAA,EAAA,GAAA,CAAI;AAAA;AAAA,+BACP;AAAA,8BACC,GAAA,CAAI,MAAA,mBACHA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yEAAA,EACb,QAAA,kBAAAA,GAAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAU,kCAAA,EAAmC,GACpD,CAAA,GACE;AAAA,6BAAA,EACN,CAAA,GACE,IAAA;AAAA,4CACJC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8EAAA,EACb,QAAA,EAAA;AAAA,8CAAAD,GAAAA;AAAA,gCAAC,MAAA;AAAA,gCAAA;AAAA,kCACC,SAAA,EAAW,EAAA;AAAA,oCACT,uCAAA;AAAA,oCACA,QAAA,IAAY;AAAA,mCACd;AAAA,kCAEC,QAAA,EAAA,GAAA,CAAI;AAAA;AAAA,+BACP;AAAA,8BACC,GAAA,CAAI,2BACHA,GAAAA,CAAC,UAAK,SAAA,EAAU,0EAAA,EACb,QAAA,EAAA,GAAA,CAAI,QAAA,EACP,CAAA,GACE;AAAA,6BAAA,EACN,CAAA;AAAA,4CACAA,GAAAA;AAAA,8BAAC,MAAA;AAAA,8BAAA;AAAA,gCACC,OAAA,EAAQ,OAAA;AAAA,gCACR,IAAA,EAAK,MAAA;AAAA,gCACL,OAAO,CAAA,CAAE,KAAA;AAAA,gCACT,SAAA,EAAW,EAAA;AAAA,kCACT,8GAAA;AAAA,kCACA,QAAA,IAAY;AAAA,iCACd;AAAA,gCACA,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,kCAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,kCAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAAA,gCAChB,CAAA;AAAA,gCAEA,QAAA,kBAAAA,GAAAA,CAAC,CAAA,EAAA,EAAE,SAAA,EAAU,QAAA,EAAS;AAAA;AAAA,6BACxB;AAAA,4BACC,2BACCA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,+DAA8D,CAAA,GAC3E;AAAA;AAAA;AAAA,uBACN,EACF,CAAA;AAAA,sBACC,iBAAA,mBACCC,IAAAA,CAAC,kBAAA,EAAA,EAAmB,WAAU,MAAA,EAC3B,QAAA,EAAA;AAAA,wBAAA,WAAA,mBACCA,IAAAA,CAAAE,UAAAA,EAAA,EACE,QAAA,EAAA;AAAA,0CAAAH,GAAAA,CAAC,eAAA,EAAA,EAAgB,OAAA,EAAS,MAAM,WAAA,CAAY,GAAA,CAAI,EAAE,CAAA,EAC/C,QAAA,EAAA,GAAA,CAAI,MAAA,mBACHC,IAAAA,CAAAE,YAAA,EACE,QAAA,EAAA;AAAA,4CAAAH,GAAAA,CAAC,MAAA,EAAA,EAAO,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,4CAChCA,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,CAAA,CAAE,QAAA,EAAS;AAAA,2BAAA,EACpB,CAAA,mBAEAC,IAAAA,CAAAE,UAAAA,EAAA,EACE,QAAA,EAAA;AAAA,4CAAAH,GAAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,4CAC7BA,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,CAAA,CAAE,MAAA,EAAO;AAAA,2BAAA,EAClB,CAAA,EAEJ,CAAA;AAAA,0CACAA,IAAC,oBAAA,EAAA,EAAqB;AAAA,yBAAA,EACxB,CAAA,GACE,IAAA;AAAA,wCACJC,KAAC,eAAA,EAAA,EAAgB,OAAA,EAAS,MAAM,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA,EAC5C,QAAA,EAAA;AAAA,0CAAAD,GAAAA,CAAC,CAAA,EAAA,EAAE,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,0CAC3BA,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,CAAA,CAAE,KAAA,EAAM;AAAA,yBAAA,EACjB,CAAA;AAAA,wBACC,aAAA,mBACCC,IAAAA,CAAC,eAAA,EAAA,EAAgB,SAAS,MAAM,aAAA,CAAc,GAAA,CAAI,EAAE,CAAA,EAClD,QAAA,EAAA;AAAA,0CAAAD,GAAAA,CAAC,KAAA,EAAA,EAAM,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,0CAC/BA,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,CAAA,CAAE,WAAA,EAAY;AAAA,yBAAA,EACvB,CAAA,GACE,IAAA;AAAA,wBACH,6BACCC,IAAAA,CAAC,mBAAgB,OAAA,EAAS,MAAM,YAAW,EACzC,QAAA,EAAA;AAAA,0CAAAD,GAAAA,CAAC,MAAA,EAAA,EAAO,SAAA,EAAU,aAAA,EAAc,CAAA;AAAA,0CAChCA,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,CAAA,CAAE,QAAA,EAAS;AAAA,yBAAA,EACpB,CAAA,GACE;AAAA,uBAAA,EACN,CAAA,GACE;AAAA,qBAAA,EAAA,EAxGY,IAAI,EAyGtB,CAAA;AAAA,kBAEJ,CAAC;AAAA;AAAA,eACH;AAAA,8BACAA,GAAAA,CAAC,SAAA,EAAA,EAAU,WAAA,EAAY,YAAA,EAAa,WAAU,sBAAA,EAAuB;AAAA;AAAA;AAAA,SACvE;AAAA,wBAEAA,GAAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,sDAAA;AAAA,YACV,KAAA,EAAO,EAAE,MAAA,EAAQ,mBAAA,EAAoB;AAAA,YAErC,QAAA,kBAAAC,KAAC,YAAA,EAAA,EACC,QAAA,EAAA;AAAA,8BAAAD,IAAC,mBAAA,EAAA,EAAoB,OAAA,EAAO,MAC1B,QAAA,kBAAAA,GAAAA,CAAC,UAAO,OAAA,EAAQ,OAAA,EAAQ,MAAK,MAAA,EAAO,SAAA,EAAU,8BAC5C,QAAA,kBAAAA,GAAAA,CAAC,eAAY,SAAA,EAAU,QAAA,EAAS,GAClC,CAAA,EACF,CAAA;AAAA,8BACAA,GAAAA;AAAA,gBAAC,mBAAA;AAAA,gBAAA;AAAA,kBACC,KAAA,EAAM,KAAA;AAAA,kBACN,SAAA,EAAU,yCAAA;AAAA,kBAET,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBACTC,IAAAA;AAAA,oBAAC,gBAAA;AAAA,oBAAA;AAAA,sBAEC,OAAA,EAAS,MAAM,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAAA,sBAC9B,OAAO,GAAA,CAAI,KAAA;AAAA,sBACX,SAAA,EAAW,EAAA;AAAA,wBACT,2BAAA;AAAA,wBACA,QAAA,KAAa,IAAI,EAAA,IAAM;AAAA,uBACzB;AAAA,sBAEC,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAI,IAAA,mBACHA,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,mBAAA,EACb,QAAA,EAAA;AAAA,0CAAAD,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2CAAA,EACb,cAAI,IAAA,EACP,CAAA;AAAA,0BACC,IAAI,MAAA,mBACHA,IAAC,GAAA,EAAA,EAAI,SAAA,EAAU,6DAA4D,CAAA,GACzE;AAAA,yBAAA,EACN,CAAA,GACE,IAAA;AAAA,wCACJC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gEAAA,EACb,QAAA,EAAA;AAAA,0CAAAD,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,gCAAA,EAAkC,cAAI,KAAA,EAAM,CAAA;AAAA,0BAC3D,GAAA,CAAI,2BACHA,GAAAA,CAAC,UAAK,SAAA,EAAU,mDAAA,EACb,QAAA,EAAA,GAAA,CAAI,QAAA,EACP,CAAA,GACE;AAAA,yBAAA,EACN,CAAA;AAAA,wCACAA,GAAAA;AAAA,0BAAC,CAAA;AAAA,0BAAA;AAAA,4BACC,SAAA,EAAU,qEAAA;AAAA,4BACV,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,8BAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,8BAAA,OAAA,CAAQ,IAAI,EAAE,CAAA;AAAA,4BAChB;AAAA;AAAA;AACF;AAAA,qBAAA;AAAA,oBAhCK,GAAA,CAAI;AAAA,mBAkCZ;AAAA;AAAA;AACH,aAAA,EACF;AAAA;AAAA;AACF;AAAA;AAAA,GACF;AAEJ;AC9QO,SAAS,YAAY,EAAE,SAAA,EAAW,QAAQ,OAAA,EAAS,GAAG,MAAK,EAAqB;AACrF,EAAA,MAAM,EAAE,QAAA,EAAS,GAAI,cAAA,EAAe;AACpC,EAAA,MAAM,WAAW,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,CAAE,OAAO,OAAO,CAAA;AACnD,EAAA,IAAI,QAAA,CAAS,MAAA,KAAW,CAAA,IAAK,CAAC,SAAS,OAAO,IAAA;AAC9C,EAAA,MAAM,IAAA,GAAO,SAAS,MAAA,GAAS,CAAA;AAC/B,EAAA,MAAM,WAAA,GAAc,SAAS,YAAA,IAAgB,IAAA;AAC7C,EAAA,uBACEA,GAAAA,CAAC,UAAA,EAAA,EAAY,GAAG,IAAA,EACd,QAAA,kBAAAC,KAAC,cAAA,EAAA,EACE,QAAA,EAAA;AAAA,IAAA,OAAA,mBACCD,GAAAA,CAAC,cAAA,EAAA,EAAe,SAAA,EAAW,WAAA,GAAc,oBAAoB,MAAA,EAE1D,QAAA,EAAA,QAAA,CAAS,MAAA,KAAW,CAAA,mBACnBA,GAAAA,CAAC,cAAA,EAAA,EAAgB,QAAA,EAAA,OAAA,CAAQ,KAAA,EAAM,IAC7B,OAAA,CAAQ,IAAA,mBACVA,GAAAA,CAAC,kBAAe,OAAA,EAAO,IAAA,EACrB,QAAA,kBAAAA,GAAAA,CAACE,OAAA,EAAK,IAAA,EAAM,OAAA,CAAQ,IAAA,EAAO,kBAAQ,KAAA,EAAM,CAAA,EAC3C,CAAA,GAEA,OAAA,CAAQ,OAEZ,CAAA,GACE,IAAA;AAAA,IACH,QAAA,CAAS,GAAA,CAAI,CAAC,GAAA,EAAK,CAAA,KAAM;AACxB,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,GAAI,CAAC,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AACpD,MAAA,MAAM,KAAA,GAAQ,MAAA,GAAS,GAAG,CAAA,IAAK,GAAA;AAC/B,MAAA,uBACED,IAAAA,CAACE,QAAAA,EAAA,EACE,QAAA,EAAA;AAAA,QAAA,CAAA,GAAI,CAAA,IAAK,OAAA,mBACRH,GAAAA,CAAC,mBAAA,EAAA,EAAoB,SAAA,EAAW,CAAA,KAAM,CAAA,IAAK,WAAA,IAAe,OAAA,GAAU,iBAAA,GAAoB,MAAA,EACrF,qBACH,CAAA,GACE,IAAA;AAAA,wBACJA,IAAC,cAAA,EAAA,EACE,QAAA,EAAA,CAAA,KAAM,uBACLA,GAAAA,CAAC,cAAA,EAAA,EAAgB,QAAA,EAAA,KAAA,EAAM,CAAA,mBAEvBA,IAAC,cAAA,EAAA,EAAe,OAAA,EAAO,MACrB,QAAA,kBAAAA,GAAAA,CAACE,OAAA,EAAK,IAAA,EAAa,QAAA,EAAA,KAAA,EAAM,CAAA,EAC3B,CAAA,EAEJ;AAAA,OAAA,EAAA,EAda,IAef,CAAA;AAAA,IAEJ,CAAC;AAAA,GAAA,EACH,CAAA,EACF,CAAA;AAEJ;ACXO,IAAM,oBAAA,GAAuB;AAAA,EAClC,iBAAA,EAAmB,mBAAA;AAAA,EACnB,KAAA,EAAO;AACT;AAqBO,SAAS,OAAA,CAAQ;AAAA,EACtB,IAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,aAAA;AAAA,EACA,oBAAoB,oBAAA,CAAqB,iBAAA;AAAA,EACzC,eAAA,GAAkB,KAAA;AAAA,EAClB,aAAa,oBAAA,CAAqB,KAAA;AAAA,EAClC;AACF,CAAA,EAAiB;AACf,EAAA,MAAM,UAAU,MAAA,IAAU,IAAA;AAC1B,EAAA,MAAM,QAAA,GAAW,OAAA,GAAU,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA,GAAI,EAAC;AACtE,EAAA,MAAM,IAAA,GAAO,QAAQ,EAAC;AACtB,EAAA,MAAM,UAAU,OAAA,GAAU,QAAA,CAAS,MAAA,KAAW,CAAA,GAAI,KAAK,MAAA,KAAW,CAAA;AAElE,EAAA,uBACED,IAAAA,CAAC,KAAA,EAAA,EAAI,WAAW,EAAA,CAAG,WAAA,EAAa,SAAS,CAAA,EACtC,QAAA,EAAA;AAAA,IAAA,aAAA,mBACCA,IAAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAU,uBAAA,EACpB,QAAA,EAAA;AAAA,sBAAAD,GAAAA,CAAC,eAAA,EAAA,EACC,QAAA,kBAAAA,GAAAA,CAAC,UAAO,CAAA,EACV,CAAA;AAAA,sBACAA,GAAAA;AAAA,QAAC,eAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,OAAO,KAAA,IAAS,EAAA;AAAA,UAChB,UAAU,CAAC,CAAA,KAAM,aAAA,CAAc,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,UAC7C,WAAA,EAAa,iBAAA;AAAA,UACb,YAAA,EAAY,iBAAA;AAAA,UACZ,SAAA,EAAW;AAAA;AAAA;AACb,KAAA,EACF,CAAA,GACE,IAAA;AAAA,IAEH,OAAA,mBACCA,GAAAA,CAAC,GAAA,EAAA,EAAE,WAAU,iDAAA,EACV,QAAA,EAAA,UAAA,EACH,CAAA,GACE,OAAA,mBACFA,GAAAA,CAAC,SAAI,SAAA,EAAU,YAAA,EACZ,mBAAS,GAAA,CAAI,CAAC,sBACbC,IAAAA,CAAC,SAAA,EAAA,EAAoB,SAAA,EAAU,WAAA,EAC7B,QAAA,EAAA;AAAA,sBAAAA,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,wBAAAD,GAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,sCAAA,EAAwC,YAAE,KAAA,EAAM,CAAA;AAAA,QAC7D,CAAA,CAAE,8BACDA,GAAAA,CAAC,OAAE,SAAA,EAAU,+BAAA,EAAiC,QAAA,EAAA,CAAA,CAAE,WAAA,EAAY,CAAA,GAC1D;AAAA,OAAA,EACN,CAAA;AAAA,sBACAA,GAAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,EAAE,IAAA,EAAM;AAAA,KAAA,EAAA,EAPf,CAAA,CAAE,GAQhB,CACD,CAAA,EACH,oBAEAA,GAAAA,CAAC,WAAA,EAAA,EAAY,IAAA,EAAM,IAAA,EAAM;AAAA,GAAA,EAE7B,CAAA;AAEJ;AAGA,SAAS,WAAA,CAAY,EAAE,IAAA,EAAK,EAA4B;AACtD,EAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sDAAA,EACZ,eAAK,GAAA,CAAI,CAAC,GAAA,qBACTA,IAAC,OAAA,EAAA,EAAsB,GAAA,EAAA,EAAT,GAAA,CAAI,GAAe,CAClC,CAAA,EACH,CAAA;AAEJ;AAMO,SAAS,OAAA,CAAQ,EAAE,GAAA,EAAI,EAAyB;AACrD,EAAA,uBACEA,GAAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,MAAM,GAAA,CAAI,IAAA;AAAA,MACV,MAAA,EAAQ,GAAA,CAAI,QAAA,GAAW,QAAA,GAAW,MAAA;AAAA,MAClC,GAAA,EAAK,GAAA,CAAI,QAAA,GAAW,YAAA,GAAe,MAAA;AAAA,MACnC,SAAA,EAAU,8EAAA;AAAA,MAEV,QAAA,kBAAAC,IAAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,+JAAA,EAGd,QAAA,EAAA;AAAA,wBAAAD,GAAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAW,EAAA;AAAA,cACT,kKAAA;AAAA,cACA,GAAA,CAAI;AAAA,aACN;AAAA,YAEC,QAAA,EAAA,GAAA,CAAI;AAAA;AAAA,SACP;AAAA,wBACAC,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,WAAA,EACb,QAAA,EAAA;AAAA,0BAAAD,GAAAA,CAAC,SAAA,EAAA,EAAW,QAAA,EAAA,GAAA,CAAI,IAAA,EAAK,CAAA;AAAA,UACpB,GAAA,CAAI,8BACHA,GAAAA,CAAC,mBAAgB,SAAA,EAAU,cAAA,EACxB,QAAA,EAAA,GAAA,CAAI,WAAA,EACP,CAAA,GACE;AAAA,SAAA,EACN;AAAA,OAAA,EACF;AAAA;AAAA,GACF;AAEJ","file":"index.js","sourcesContent":["\"use client\"\n\nimport type { ComponentProps, ReactNode } from \"react\"\nimport {\n SidebarInset,\n SidebarProvider,\n} from \"~/ui/primitives/sidebar.js\"\nimport { cn } from \"~/utils/cn.js\"\n\nexport interface AppShellProps\n extends Omit<ComponentProps<typeof SidebarProvider>, \"children\"> {\n children: ReactNode\n}\n\n/**\n * App shell composition root. Wires `SidebarProvider`. Pair with\n * `<Sidebar>` from `@tradalab/lyra/ui` and `<AppShellMain>` for the\n * right-hand pane.\n *\n * @example\n * import { AppShell, AppShellMain, AppShellHeader, AppShellBody, NavGroup, NavItem, Breadcrumbs } from \"@tradalab/lyra/shell\"\n * import { Sidebar, SidebarHeader, SidebarContent, SidebarFooter, SidebarTrigger } from \"@tradalab/lyra/ui\"\n *\n * <AppShell>\n * <Sidebar collapsible=\"icon\">\n * <SidebarHeader>{logo}</SidebarHeader>\n * <SidebarContent>\n * <NavGroup label=\"Primitives\">{...}</NavGroup>\n * </SidebarContent>\n * <SidebarFooter>{user}</SidebarFooter>\n * </Sidebar>\n * <AppShellMain>\n * <AppShellHeader><SidebarTrigger /><Breadcrumbs /></AppShellHeader>\n * <AppShellBody>{children}</AppShellBody>\n * </AppShellMain>\n * </AppShell>\n */\nexport function AppShell({ children, ...rest }: AppShellProps) {\n return <SidebarProvider {...rest}>{children}</SidebarProvider>\n}\n\n/** Right-hand pane container. Alias for `SidebarInset`. */\nexport const AppShellMain = SidebarInset\n\n/** Top bar inside `<AppShellMain>`. Standardizes h-12 + border-b + flex row. */\nexport function AppShellHeader({\n className,\n children,\n ...rest\n}: ComponentProps<\"header\">) {\n return (\n <header\n className={cn(\n \"flex h-12 shrink-0 items-center gap-2 border-b px-3\",\n className,\n )}\n {...rest}\n >\n {children}\n </header>\n )\n}\n\n/** Scroll body inside `<AppShellMain>`. Sibling of `<AppShellHeader>`. */\nexport function AppShellBody({\n className,\n children,\n ...rest\n}: ComponentProps<\"div\">) {\n return (\n <div className={cn(\"flex-1 overflow-auto\", className)} {...rest}>\n {children}\n </div>\n )\n}\n","\"use client\"\n\nimport type { ComponentProps } from \"react\"\nimport { Sidebar } from \"~/ui/primitives/sidebar.js\"\nimport { cn } from \"~/utils/cn.js\"\n\n/**\n * Dual / stacked sidebar wrapper — an icon rail plus one or more content\n * panels rendered side-by-side inside a single `<Sidebar>`. This is the\n * shadcn \"sidebar-07\" pattern.\n *\n * The `*:data-[sidebar=sidebar]:flex-row` trick lays the inner\n * `[data-sidebar=sidebar]` wrappers of the nested {@link SidebarDock} /\n * {@link SidebarPanel} columns out horizontally. `variant`/`collapsible`\n * default to `\"sidebar\"`/`\"icon\"` but can be overridden.\n *\n * @example\n * import { AppShell, AppShellMain, StackedSidebar, SidebarDock, SidebarPanel } from \"@tradalab/lyra/shell\"\n * import { SidebarHeader, SidebarContent, SidebarMenu, SidebarMenuItem, SidebarMenuButton } from \"@tradalab/lyra/ui\"\n *\n * <AppShell>\n * <StackedSidebar>\n * <SidebarDock>\n * <SidebarHeader>{logo}</SidebarHeader>\n * <SidebarContent>{iconButtons}</SidebarContent>\n * </SidebarDock>\n * {tab === \"files\" ? <SidebarPanel>{tree}</SidebarPanel> : null}\n * </StackedSidebar>\n * <AppShellMain>{children}</AppShellMain>\n * </AppShell>\n */\nexport function StackedSidebar({\n className,\n ...rest\n}: ComponentProps<typeof Sidebar>) {\n return (\n <Sidebar\n variant=\"sidebar\"\n collapsible=\"icon\"\n {...rest}\n className={cn(\n \"overflow-hidden *:data-[sidebar=sidebar]:flex-row\",\n className,\n )}\n />\n )\n}\n\n/**\n * Narrow icon-rail column inside a {@link StackedSidebar}. Fixed to the icon\n * width, never collapses on its own (the parent `StackedSidebar` owns the\n * icon-mode toggle).\n *\n * Named `SidebarDock` — not `SidebarRail` — because `SidebarRail` already\n * exists in `@tradalab/lyra/ui` as shadcn's drag-to-resize edge handle.\n */\nexport function SidebarDock({\n className,\n ...rest\n}: ComponentProps<typeof Sidebar>) {\n return (\n <Sidebar\n {...rest}\n collapsible=\"none\"\n className={cn(\n \"w-[calc(var(--sidebar-width-icon)+1px)]! overflow-hidden border-r\",\n className,\n )}\n />\n )\n}\n\n/**\n * Wider content column inside a {@link StackedSidebar} (tree, list, …).\n * Fills remaining width; render conditionally to show/hide per app state.\n */\nexport function SidebarPanel({\n className,\n ...rest\n}: ComponentProps<typeof Sidebar>) {\n return (\n <Sidebar\n {...rest}\n collapsible=\"none\"\n className={cn(\"flex-1 overflow-hidden\", className)}\n />\n )\n}\n","\"use client\"\n\nimport type { ReactNode } from \"react\"\nimport {\n SidebarGroup,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarMenu,\n} from \"~/ui/primitives/sidebar.js\"\n\nexport interface NavGroupProps {\n label?: ReactNode\n children: ReactNode\n}\n\nexport function NavGroup({ label, children }: NavGroupProps) {\n return (\n <SidebarGroup>\n {label != null ? <SidebarGroupLabel>{label}</SidebarGroupLabel> : null}\n <SidebarGroupContent>\n <SidebarMenu>{children}</SidebarMenu>\n </SidebarGroupContent>\n </SidebarGroup>\n )\n}\n","\"use client\"\n\nimport { usePathname } from \"next/navigation\"\n\nexport type MatchMode = \"exact\" | \"prefix\"\n\nexport interface UseActiveRoute {\n pathname: string\n isActive: (href: string, mode?: MatchMode) => boolean\n}\n\n/**\n * App-Router pathname helper. Default `mode` is `\"prefix\"`.\n *\n * Root (`/`) is always exact-matched regardless of `mode` — otherwise the\n * root nav item would light up on every nested page.\n */\nexport function useActiveRoute(): UseActiveRoute {\n const pathname = usePathname() ?? \"/\"\n return {\n pathname,\n isActive: (href, mode = \"prefix\") => {\n if (mode === \"exact\" || href === \"/\") return pathname === href\n return pathname === href || pathname.startsWith(`${href}/`)\n },\n }\n}\n","\"use client\"\n\nimport Link from \"next/link\"\nimport type { ReactNode } from \"react\"\nimport {\n SidebarMenuButton,\n SidebarMenuItem,\n} from \"~/ui/primitives/sidebar.js\"\nimport { useActiveRoute, type MatchMode } from \"./use-active-route.js\"\n\nexport type NavIcon = ReactNode\n\n/** Absolute URLs and mail/tel links leave the app — they can't go through next/link. */\nconst looksExternal = (href: string) =>\n /^([a-z][a-z0-9+.-]*:)?\\/\\//i.test(href) || /^(mailto|tel):/i.test(href)\n\nexport interface NavItemProps {\n href: string\n label: string\n /** Pre-rendered icon element, e.g. `<Globe />`. Element form so the prop is serializable across the RSC boundary. */\n icon?: NavIcon\n /** Sidebar tooltip; visible in collapsed icon mode. */\n tooltip?: string\n /** Default `\"prefix\"` — matches `href` and any nested path. */\n matchMode?: MatchMode\n /**\n * Render a new-tab anchor instead of a `next/link`, and never mark the row\n * active. Defaults to auto-detection: absolute (`https://…`), protocol-\n * relative, `mailto:` and `tel:` hrefs count as external.\n */\n external?: boolean\n}\n\n/** Sidebar nav row. Must be rendered inside a {@link NavGroup}. */\nexport function NavItem({\n href,\n label,\n icon,\n tooltip,\n matchMode = \"prefix\",\n external,\n}: NavItemProps) {\n const { isActive } = useActiveRoute()\n const isExternal = external ?? looksExternal(href)\n return (\n <SidebarMenuItem>\n <SidebarMenuButton\n asChild\n isActive={!isExternal && isActive(href, matchMode)}\n tooltip={tooltip}\n >\n {isExternal ? (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\">\n {icon}\n <span>{label}</span>\n </a>\n ) : (\n <Link href={href}>\n {icon}\n <span>{label}</span>\n </Link>\n )}\n </SidebarMenuButton>\n </SidebarMenuItem>\n )\n}\n","\"use client\"\n\nimport type { ReactNode } from \"react\"\nimport { NavGroup } from \"./nav-group.js\"\nimport { NavItem, type NavItemProps } from \"./nav-item.js\"\n\nexport interface NavSectionProps {\n /** Optional group heading. */\n label?: ReactNode\n /** Nav rows — each rendered as a {@link NavItem}. */\n items: NavItemProps[]\n}\n\n/**\n * Config-driven convenience over {@link NavGroup} + {@link NavItem}: pass a\n * data array instead of hand-mapping JSX. For dynamic or conditional rows,\n * compose `NavGroup`/`NavItem` directly.\n *\n * @example\n * const NAV = [\n * { href: \"/files\", label: \"Files\", icon: <Folder /> },\n * { href: \"/trash\", label: \"Trash\", icon: <Trash2 /> },\n * ]\n * <NavSection label=\"Workspace\" items={NAV} />\n */\nexport function NavSection({ label, items }: NavSectionProps) {\n return (\n <NavGroup label={label}>\n {items.map((item) => (\n <NavItem key={item.href} {...item} />\n ))}\n </NavGroup>\n )\n}\n","\"use client\"\n\nimport { Fragment, type ReactNode } from \"react\"\nimport { ChevronsUpDown } from \"lucide-react\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"~/ui/primitives/dropdown-menu.js\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"~/ui/primitives/sidebar.js\"\n\n/** An application shown in the {@link NavBrand} header / switcher. */\nexport interface NavBrandApp {\n /** Display name. */\n name: string\n /**\n * Pre-rendered icon/logo element, e.g. `<Boxes />`. Element form (not a\n * component reference) so the prop stays serializable across the RSC\n * boundary — same convention as {@link NavItem}'s `icon`.\n */\n icon: ReactNode\n /** Navigation target. Usually an absolute cross-app URL (full navigation). */\n href: string\n /** Optional secondary line under the name (tagline / domain). */\n description?: string\n}\n\n/** A labeled section of apps in the {@link NavBrand} switcher. */\nexport interface NavBrandGroup {\n /** Stable React key. */\n key: string\n /** Section heading. Omit for an unlabeled section (e.g. ungrouped apps). */\n label?: string\n apps: NavBrandApp[]\n}\n\nexport interface NavBrandProps {\n /** The current app, rendered in the sidebar header. */\n app: NavBrandApp\n /**\n * Other apps to switch to (flat, single list). When omitted or empty — and no\n * `groups` — the header renders as a plain link to `app.href`.\n */\n apps?: NavBrandApp[]\n /**\n * Grouped apps — rendered as labeled sections separated by dividers. Takes\n * precedence over `apps`. The caller owns the grouping + ordering.\n */\n groups?: NavBrandGroup[]\n /** Heading above a flat `apps` list. Default `\"Applications\"`. Ignored for `groups`. */\n appsLabel?: string\n /** Extra menu content appended below the app list (e.g. an \"Add app\" row). */\n children?: ReactNode\n}\n\n/** Default English heading for the switcher's app list — override for i18n. */\nexport const defaultNavBrandAppsLabel = \"Applications\"\n\n/** Icon tile + name/description shown inside the header button. */\nfunction BrandContent({ app }: { app: NavBrandApp }) {\n return (\n <>\n <div className=\"bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-none [&_svg]:size-4\">\n {app.icon}\n </div>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-semibold\">{app.name}</span>\n {app.description ? (\n <span className=\"text-muted-foreground truncate text-xs\">\n {app.description}\n </span>\n ) : null}\n </div>\n </>\n )\n}\n\n/** A single switch-to-app row (full-navigation link). */\nfunction AppRow({ app }: { app: NavBrandApp }) {\n return (\n <DropdownMenuItem asChild className=\"gap-2 p-2\">\n <a href={app.href}>\n <div className=\"flex size-6 items-center justify-center rounded-none border [&_svg]:size-3.5\">\n {app.icon}\n </div>\n <span className=\"truncate\">{app.name}</span>\n </a>\n </DropdownMenuItem>\n )\n}\n\n/**\n * Sidebar-header brand block with an optional app switcher — the standardized\n * `SidebarHeader` content for app shells (pairs with {@link NavUser} in the\n * footer). Presentational: the app owns the config, icons, and labels.\n *\n * With `groups` (or `apps`), the header is a dropdown trigger listing the other\n * apps as links; `groups` renders labeled sections, `apps` a single flat list.\n * Without either, the header is a plain link to `app.href`. Cross-app links use\n * a plain `<a>` so switching does a full navigation.\n *\n * Must render inside an `AppShell`/`SidebarProvider`, and below a\n * `TooltipProvider` (the collapsed-mode tooltip needs one).\n *\n * @example\n * <NavBrand\n * app={{ name: \"Admin\", description: \"Platform console\", icon: <ShieldCheck />, href: \"/\" }}\n * groups={[\n * { key: \"workspace\", label: \"Workspace\", apps: [{ name: \"Drive\", icon: <HardDrive />, href: \"https://drive.tradalab.com\" }] },\n * ]}\n * />\n */\nexport function NavBrand({\n app,\n apps,\n groups,\n appsLabel = defaultNavBrandAppsLabel,\n children,\n}: NavBrandProps) {\n const { isMobile } = useSidebar()\n const groupTotal = groups?.reduce((n, g) => n + g.apps.length, 0) ?? 0\n const hasSwitcher = (apps?.length ?? 0) > 0 || groupTotal > 0 || children != null\n\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n {hasSwitcher ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <SidebarMenuButton\n size=\"lg\"\n tooltip={app.name}\n className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"\n >\n <BrandContent app={app} />\n <ChevronsUpDown className=\"ml-auto size-4\" />\n </SidebarMenuButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-none\"\n align=\"start\"\n side={isMobile ? \"bottom\" : \"right\"}\n sideOffset={4}\n >\n {groupTotal > 0 ? (\n groups!.map((g, i) => (\n <Fragment key={g.key}>\n {i > 0 ? <DropdownMenuSeparator /> : null}\n {g.label ? (\n <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n {g.label}\n </DropdownMenuLabel>\n ) : null}\n {g.apps.map((item) => (\n <AppRow key={item.href} app={item} />\n ))}\n </Fragment>\n ))\n ) : (\n <>\n <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n {appsLabel}\n </DropdownMenuLabel>\n {apps?.map((item) => (\n <AppRow key={item.href} app={item} />\n ))}\n </>\n )}\n {children ? (\n <>\n <DropdownMenuSeparator />\n {children}\n </>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n ) : (\n <SidebarMenuButton size=\"lg\" asChild tooltip={app.name}>\n <a href={app.href}>\n <BrandContent app={app} />\n </a>\n </SidebarMenuButton>\n )}\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n","\"use client\"\n\n// Shared visual vocabulary for launcher/registry apps: the FULL lucide icon set\n// (via lucide-react/dynamic — no hand-maintained registry), an accent-color\n// palette, and <AppGlyph> — the single renderer used by the app switcher\n// (NavBrand), the launcher (AppGrid), and each app's Apps admin so a registered\n// app looks identical everywhere.\n//\n// An app's `icon` is a lucide icon name (any of lucide's ~1600 — kebab\n// \"hard-drive\" or Pascal \"HardDrive\"), an image URL, or empty (→ name monogram).\n// `color` is a hex accent (\"\" → theme default).\n\nimport { DynamicIcon, iconNames, type IconName } from \"lucide-react/dynamic\"\n\nimport { cn } from \"~/utils/cn.js\"\n\n/** Every lucide icon name (kebab-case) — the icon picker's source of truth. */\nexport const APP_ICON_NAMES: readonly IconName[] = iconNames\n\nconst ICON_NAME_SET = new Set<string>(iconNames)\n\n/** Normalize a stored name to lucide's kebab-case (\"HardDrive\" → \"hard-drive\"). */\nexport function toIconName(name: string): string {\n return name\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .replace(/[\\s_]+/g, \"-\")\n .toLowerCase()\n}\n\n/** True when `name` resolves to a known lucide icon. */\nexport function isLucideIcon(name: string): boolean {\n return ICON_NAME_SET.has(toIconName(name))\n}\n\n/** Accent palette (tailwind-500 hues) — read well on light + dark surfaces. */\nexport const APP_COLORS: string[] = [\n \"#64748b\", \"#ef4444\", \"#f97316\", \"#f59e0b\", \"#eab308\", \"#22c55e\",\n \"#10b981\", \"#14b8a6\", \"#06b6d4\", \"#3b82f6\", \"#6366f1\", \"#8b5cf6\",\n \"#a855f7\", \"#ec4899\", \"#f43f5e\",\n]\n\nexport function isIconUrl(s: string): boolean {\n return /^(https?:)?\\/\\//.test(s) || s.startsWith(\"/\") || s.startsWith(\"data:\")\n}\n\n/** Append an alpha to a #rrggbb hex → #rrggbbaa (for tinted backgrounds). */\nfunction hexA(hex: string, alpha: number): string {\n const a = Math.round(alpha * 255).toString(16).padStart(2, \"0\")\n return /^#[0-9a-fA-F]{6}$/.test(hex) ? `${hex}${a}` : hex\n}\n\nexport interface AppGlyphProps {\n /** Lucide icon name, image URL, or empty (→ monogram). */\n icon?: string\n /** Hex accent color; \"\" → theme default. */\n color?: string\n /** App name — the monogram fallback + a11y. */\n name?: string\n className?: string\n}\n\n/** The colored glyph for an app: image (URL), lucide icon (name), or monogram. */\nexport function AppGlyph({ icon, color, name, className }: AppGlyphProps) {\n const box = cn(\"flex size-9 shrink-0 items-center justify-center rounded-none\", className)\n\n if (icon && isIconUrl(icon)) {\n return (\n <span\n aria-hidden\n className={cn(box, \"bg-muted bg-cover bg-center\")}\n style={{ backgroundImage: `url(\"${encodeURI(icon)}\")` }}\n />\n )\n }\n\n const tint = color ? { backgroundColor: hexA(color, 0.14) } : undefined\n const fg = color ? { color } : undefined\n const iconName = icon ? toIconName(icon) : \"\"\n\n if (iconName && ICON_NAME_SET.has(iconName)) {\n return (\n <span aria-hidden className={cn(box, !color && \"bg-primary/10\")} style={tint}>\n <DynamicIcon\n name={iconName as IconName}\n className={cn(\"size-5\", !color && \"text-primary\")}\n style={fg}\n />\n </span>\n )\n }\n\n const ch = (name || icon || \"?\").charAt(0).toUpperCase()\n return (\n <span\n aria-hidden\n className={cn(box, \"text-sm font-semibold\", !color && \"bg-primary/10 text-primary\")}\n style={color ? { ...tint, ...fg } : undefined}\n >\n {ch}\n </span>\n )\n}\n","\"use client\"\n\nimport { AppGlyph } from \"./app-glyph.js\"\nimport {\n NavBrand,\n type NavBrandApp,\n type NavBrandGroup,\n} from \"./nav-brand.js\"\n\n/**\n * A registry app in the {@link AppSwitcher} — the shape a launcher endpoint\n * returns (icon + color as strings; the glyph is rendered internally). Structurally\n * matches nekit's `LauncherApp`, so `groupApps(...)` output feeds straight in.\n */\nexport interface AppSwitcherApp {\n name: string\n description?: string\n /** Navigation target (usually an absolute cross-app URL). */\n url: string\n /** Lucide icon name or image URL. */\n icon: string\n /** Hex accent color; \"\" → theme default. */\n color?: string\n}\n\n/** A grouped, ordered section of apps (label omitted for the ungrouped bucket). */\nexport interface AppSwitcherSection {\n key: string\n label?: string\n apps: AppSwitcherApp[]\n}\n\nexport interface AppSwitcherProps {\n /** The current app, shown in the sidebar header. */\n app: NavBrandApp\n /** Grouped registry apps — e.g. nekit `groupApps(data.apps, data.groups)`. */\n sections: AppSwitcherSection[]\n /** Heading for the flat fallback list. */\n appsLabel?: string\n /** Shown when `sections` is empty (registry loading / unavailable) so the\n * switcher never collapses to a plain link. */\n fallback?: NavBrandApp[]\n}\n\n/**\n * The cross-app switcher: a batteries-included wrapper over {@link NavBrand} that\n * takes the launcher registry (grouped `sections` of `{ icon, color, url, … }`)\n * and renders it — labeled group sections, each app's glyph via {@link AppGlyph}.\n * Consumers just fetch + group (nekit) and pass config; icon/render logic lives\n * here. Empty registry → the `fallback` flat list.\n *\n * @example\n * const sections = groupApps(data.apps, data.groups) // @tradalab/nekit/data/launcher\n * <AppSwitcher app={{ name: \"Admin\", icon: <ShieldCheck/>, href: \"/\" }} sections={sections} />\n */\nexport function AppSwitcher({\n app,\n sections,\n appsLabel,\n fallback,\n}: AppSwitcherProps) {\n const groups: NavBrandGroup[] = sections\n .filter((s) => s.apps.length > 0)\n .map((s) => ({\n key: s.key,\n label: s.label,\n apps: s.apps.map((a) => ({\n name: a.name,\n description: a.description,\n href: a.url,\n icon: <AppGlyph icon={a.icon} color={a.color} name={a.name} />,\n })),\n }))\n\n return (\n <NavBrand\n app={app}\n groups={groups.length ? groups : undefined}\n apps={groups.length ? undefined : fallback}\n appsLabel={appsLabel}\n />\n )\n}\n","\"use client\"\n\nimport type { ReactNode } from \"react\"\nimport {\n ChevronsUpDown,\n CircleUser,\n LogIn,\n LogOut,\n Monitor,\n Moon,\n Palette,\n Sun,\n UserRoundCog,\n} from \"lucide-react\"\nimport { useTheme } from \"next-themes\"\nimport { Avatar, AvatarFallback, AvatarImage } from \"~/ui/primitives/avatar.js\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"~/ui/primitives/dropdown-menu.js\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"~/ui/primitives/sidebar.js\"\nimport {\n defaultAccountMenuLabels,\n initialsOf,\n type AccountMenuLabels,\n type AccountMenuUser,\n} from \"~/ui/account-menu.js\"\n\nexport interface NavUserThemeLabels {\n theme: string\n light: string\n dark: string\n system: string\n}\n\n/** Default English theme-submenu labels — spread + override for i18n. */\nexport const defaultNavUserThemeLabels: NavUserThemeLabels = {\n theme: \"Theme\",\n light: \"Light\",\n dark: \"Dark\",\n system: \"System\",\n}\n\nexport interface NavUserProps {\n /**\n * Signed-in user. When `null`/`undefined`, renders a guest menu (icon +\n * theme + Sign in) if `onSignIn` is set, otherwise renders nothing.\n */\n user?: AccountMenuUser | null\n /** Account-action labels — reuses lyra's {@link AccountMenuLabels}. */\n labels?: Partial<AccountMenuLabels>\n /** Switch-account handler (signed-in only). Item hidden if omitted. */\n onSwitchAccount?: () => void\n /** Sign-out handler (signed-in only). Item hidden if omitted. */\n onSignOut?: () => void\n /**\n * Sign-in handler (guest only). When set, a null `user` renders the guest\n * menu with a Sign in action instead of rendering nothing.\n */\n onSignIn?: () => void\n /** Render the light/dark/system theme submenu. Default `true`. */\n showTheme?: boolean\n /** Theme-submenu labels. */\n themeLabels?: Partial<NavUserThemeLabels>\n /** Extra menu content inserted below the theme submenu. */\n children?: ReactNode\n}\n\nconst THEMES = [\n { value: \"light\", key: \"light\", icon: Sun },\n { value: \"dark\", key: \"dark\", icon: Moon },\n { value: \"system\", key: \"system\", icon: Monitor },\n] as const\n\n/**\n * Sidebar-footer account menu — the standardized NavUser for app shells.\n * Avatar trigger (size `lg`) + name/email opening a dropdown with an optional\n * theme switcher and switch-account / sign-out actions. Auth flows stay in the\n * app (callbacks); labels are props for i18n.\n *\n * Differs from {@link AccountMenu} in `@tradalab/lyra/ui`: that one is a\n * generic header dropdown; this is styled for the collapsible sidebar footer\n * and follows `useSidebar()` for mobile placement.\n *\n * Must render inside an `AppShell`/SidebarProvider, and below a\n * `TooltipProvider` (the avatar button's collapsed-mode tooltip requires one —\n * app root providers normally mount it). The theme submenu needs a\n * `next-themes` provider mounted (it no-ops without one); pass\n * `showTheme={false}` for apps with a fixed theme.\n *\n * @example\n * import { NavUser } from \"@tradalab/lyra/shell\"\n * import { SidebarFooter } from \"@tradalab/lyra/ui\"\n *\n * <SidebarFooter>\n * <NavUser\n * user={session.user}\n * onSwitchAccount={() => signIn(\"zitadel\", { redirectTo: \"/\" }, { prompt: \"select_account\" })}\n * onSignOut={() => signOut({ redirectTo: \"/\" })}\n * />\n * </SidebarFooter>\n */\nexport function NavUser({\n user,\n labels,\n onSwitchAccount,\n onSignOut,\n onSignIn,\n showTheme = true,\n themeLabels,\n children,\n}: NavUserProps) {\n const { isMobile } = useSidebar()\n const { theme, setTheme } = useTheme()\n const l = { ...defaultAccountMenuLabels, ...labels }\n const t = { ...defaultNavUserThemeLabels, ...themeLabels }\n\n // Guests render nothing unless a sign-in handler opts them into a guest menu.\n if (!user && !onSignIn) return null\n\n const name = user ? (user.name ?? user.email ?? l.account) : l.guest\n const email = user?.email ?? \"\"\n\n const avatar = (\n <Avatar className=\"size-8 rounded-none after:rounded-none\">\n {user?.image ? (\n <AvatarImage className=\"rounded-none\" src={user.image} alt={name} />\n ) : null}\n <AvatarFallback className=\"rounded-none\">\n {user ? initialsOf(name) : <CircleUser className=\"size-4\" />}\n </AvatarFallback>\n </Avatar>\n )\n\n const themeSubmenu = showTheme ? (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n <Palette className=\"mr-2 size-4\" />\n {t.theme}\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent>\n <DropdownMenuRadioGroup value={theme ?? \"system\"} onValueChange={setTheme}>\n {THEMES.map(({ value, key, icon: Icon }) => (\n <DropdownMenuRadioItem key={value} value={value}>\n <Icon className=\"mr-2 size-4\" />\n {t[key]}\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n </>\n ) : null\n\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <SidebarMenuButton\n size=\"lg\"\n tooltip={name}\n className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"\n >\n {avatar}\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{name}</span>\n {email ? (\n <span className=\"text-muted-foreground truncate text-xs\">\n {email}\n </span>\n ) : null}\n </div>\n <ChevronsUpDown className=\"ml-auto size-4\" />\n </SidebarMenuButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56\"\n side={isMobile ? \"bottom\" : \"right\"}\n align=\"end\"\n sideOffset={4}\n >\n <DropdownMenuLabel className=\"flex items-center gap-2\">\n {avatar}\n <div className=\"grid flex-1 text-left leading-tight\">\n <span className=\"truncate text-sm font-medium\">{name}</span>\n {email ? (\n <span className=\"text-muted-foreground truncate text-xs font-normal\">\n {email}\n </span>\n ) : null}\n </div>\n </DropdownMenuLabel>\n\n {themeSubmenu}\n\n {children ? (\n <>\n <DropdownMenuSeparator />\n {children}\n </>\n ) : null}\n\n {user ? (\n <>\n {onSwitchAccount || onSignOut ? <DropdownMenuSeparator /> : null}\n {onSwitchAccount ? (\n <DropdownMenuItem onSelect={onSwitchAccount}>\n <UserRoundCog className=\"mr-2 size-4\" />\n {l.switchAccount}\n </DropdownMenuItem>\n ) : null}\n {onSignOut ? (\n <DropdownMenuItem variant=\"destructive\" onSelect={onSignOut}>\n <LogOut className=\"mr-2 size-4\" />\n {l.signOut}\n </DropdownMenuItem>\n ) : null}\n </>\n ) : (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem onSelect={onSignIn}>\n <LogIn className=\"mr-2 size-4\" />\n {l.signIn}\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n","\"use client\"\n\nimport { useEffect, useRef, type ReactNode, type WheelEvent } from \"react\"\nimport { ChevronDown, ListX, Pin, PinOff, Trash2, X } from \"lucide-react\"\nimport { Button } from \"~/ui/primitives/button.js\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"~/ui/primitives/dropdown-menu.js\"\nimport { ScrollArea, ScrollBar } from \"~/ui/primitives/scroll-area.js\"\nimport {\n ContextMenu,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuSeparator,\n ContextMenuTrigger,\n} from \"~/ui/primitives/context-menu.js\"\nimport { cn } from \"~/utils/cn.js\"\n\nexport interface TabItem {\n id: string\n title: string\n /** Secondary line under the title (e.g. connection/db, file path). */\n subtitle?: ReactNode\n /** Leading icon element — the app maps its own tab type → icon. */\n icon?: ReactNode\n pinned?: boolean\n}\n\nexport interface TabBarLabels {\n close: string\n pinTab: string\n unpinTab: string\n closeOthers: string\n closeAll: string\n}\n\n/** Default English labels — spread + override for i18n. */\nexport const defaultTabBarLabels: TabBarLabels = {\n close: \"Close\",\n pinTab: \"Pin tab\",\n unpinTab: \"Unpin tab\",\n closeOthers: \"Close others\",\n closeAll: \"Close all\",\n}\n\nexport interface TabBarProps {\n tabs: TabItem[]\n activeId: string | null\n onSelect: (id: string) => void\n onClose: (id: string) => void\n /** Pin row in the context menu is hidden when omitted. */\n onTogglePin?: (id: string) => void\n /** \"Close others\" row is hidden when omitted. */\n onCloseOthers?: (id: string) => void\n /** \"Close all\" row is hidden when omitted. */\n onCloseAll?: () => void\n labels?: Partial<TabBarLabels>\n}\n\n/**\n * Horizontal tab strip for the content area of stacked-sidebar apps\n * (redishub, loom). Presentational + store-agnostic: the app owns tab state\n * and passes `tabs` + callbacks; `icon`/`subtitle` are per-tab so apps map\n * their own tab types, and labels are props for i18n. Renders nothing when\n * `tabs` is empty.\n *\n * Sizes rows from the `--tab-height` CSS var — set it in your globals.\n *\n * @example\n * const s = useTabStore()\n * <TabBar\n * tabs={s.tabs.map(t => ({ id: t.id, title: t.title, pinned: t.pinned, icon: <Icon t={t.type}/>, subtitle: fmt(t) }))}\n * activeId={s.activeTabId}\n * onSelect={s.setActiveTabId}\n * onClose={s.removeTab}\n * onTogglePin={s.togglePin}\n * onCloseOthers={s.closeOthers}\n * onCloseAll={s.closeAll}\n * />\n */\nexport function TabBar({\n tabs,\n activeId,\n onSelect,\n onClose,\n onTogglePin,\n onCloseOthers,\n onCloseAll,\n labels,\n}: TabBarProps) {\n const l = { ...defaultTabBarLabels, ...labels }\n const activeTabRef = useRef<HTMLDivElement>(null)\n\n // Scroll the active tab into view when it changes.\n useEffect(() => {\n if (activeId && activeTabRef.current) {\n activeTabRef.current.scrollIntoView({\n behavior: \"smooth\",\n block: \"nearest\",\n inline: \"nearest\",\n })\n }\n }, [activeId])\n\n // Map vertical wheel scroll to horizontal scroll over the tab strip.\n const handleWheel = (e: WheelEvent<HTMLDivElement>) => {\n if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) {\n const viewport = e.currentTarget.querySelector(\n '[data-slot=\"scroll-area-viewport\"]',\n )\n if (viewport) viewport.scrollLeft += e.deltaY * 0.5\n }\n }\n\n if (tabs.length === 0) return null\n\n const hasContextActions = Boolean(onTogglePin || onCloseOthers || onCloseAll)\n\n return (\n <div\n className=\"group/tabbar flex w-full shrink-0 items-center overflow-hidden border-b bg-muted/30\"\n style={{ height: \"var(--tab-height)\" }}\n >\n <ScrollArea\n type=\"hover\"\n className=\"min-w-0 flex-1 overflow-hidden [&_[data-orientation=vertical]]:hidden\"\n onWheel={handleWheel}\n >\n <div\n className=\"flex w-max items-center gap-0\"\n style={{ height: \"var(--tab-height)\" }}\n >\n {tabs.map((tab) => {\n const isActive = activeId === tab.id\n return (\n <ContextMenu key={tab.id}>\n <ContextMenuTrigger asChild>\n <div\n ref={isActive ? activeTabRef : null}\n onClick={() => onSelect(tab.id)}\n title={tab.title}\n className={cn(\n \"group relative flex min-w-[140px] max-w-[240px] shrink-0 cursor-pointer select-none items-center gap-2 border-r px-3 transition-colors\",\n isActive\n ? \"border-t-2 border-t-primary bg-background\"\n : \"border-t-2 border-t-transparent bg-transparent text-muted-foreground hover:bg-muted/50\",\n tab.pinned && \"min-w-[100px] bg-primary/5\",\n )}\n style={{ height: \"var(--tab-height)\" }}\n >\n {tab.icon ? (\n <div className=\"relative shrink-0\">\n <span\n className={cn(\n \"flex [&_svg]:size-3.5\",\n isActive && \"text-primary\",\n )}\n >\n {tab.icon}\n </span>\n {tab.pinned ? (\n <div className=\"absolute -right-1.5 -top-1.5 rounded-full bg-background p-0.5 shadow-sm\">\n <Pin className=\"size-2 fill-primary text-primary\" />\n </div>\n ) : null}\n </div>\n ) : null}\n <div className=\"flex min-w-0 flex-1 flex-col items-start justify-center overflow-hidden py-1\">\n <span\n className={cn(\n \"w-full truncate text-xs leading-tight\",\n isActive && \"font-medium text-foreground\",\n )}\n >\n {tab.title}\n </span>\n {tab.subtitle ? (\n <span className=\"mt-0.5 w-full truncate text-[10px] leading-none text-muted-foreground/70\">\n {tab.subtitle}\n </span>\n ) : null}\n </div>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n title={l.close}\n className={cn(\n \"size-5 shrink-0 rounded-md opacity-0 transition-opacity hover:bg-muted-foreground/20 group-hover:opacity-100\",\n isActive && \"opacity-100\",\n )}\n onClick={(e) => {\n e.stopPropagation()\n onClose(tab.id)\n }}\n >\n <X className=\"size-3\" />\n </Button>\n {isActive ? (\n <div className=\"absolute bottom-0 left-0 right-0 z-10 h-[2px] bg-background\" />\n ) : null}\n </div>\n </ContextMenuTrigger>\n {hasContextActions ? (\n <ContextMenuContent className=\"w-48\">\n {onTogglePin ? (\n <>\n <ContextMenuItem onClick={() => onTogglePin(tab.id)}>\n {tab.pinned ? (\n <>\n <PinOff className=\"mr-2 size-4\" />\n <span>{l.unpinTab}</span>\n </>\n ) : (\n <>\n <Pin className=\"mr-2 size-4\" />\n <span>{l.pinTab}</span>\n </>\n )}\n </ContextMenuItem>\n <ContextMenuSeparator />\n </>\n ) : null}\n <ContextMenuItem onClick={() => onClose(tab.id)}>\n <X className=\"mr-2 size-4\" />\n <span>{l.close}</span>\n </ContextMenuItem>\n {onCloseOthers ? (\n <ContextMenuItem onClick={() => onCloseOthers(tab.id)}>\n <ListX className=\"mr-2 size-4\" />\n <span>{l.closeOthers}</span>\n </ContextMenuItem>\n ) : null}\n {onCloseAll ? (\n <ContextMenuItem onClick={() => onCloseAll()}>\n <Trash2 className=\"mr-2 size-4\" />\n <span>{l.closeAll}</span>\n </ContextMenuItem>\n ) : null}\n </ContextMenuContent>\n ) : null}\n </ContextMenu>\n )\n })}\n </div>\n <ScrollBar orientation=\"horizontal\" className=\"z-20 h-1.5 hover:h-2\" />\n </ScrollArea>\n\n <div\n className=\"flex shrink-0 items-center border-l bg-muted/30 px-1\"\n style={{ height: \"var(--tab-height)\" }}\n >\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"size-8 shrink-0 rounded-sm\">\n <ChevronDown className=\"size-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n className=\"max-h-[400px] w-[260px] overflow-y-auto\"\n >\n {tabs.map((tab) => (\n <DropdownMenuItem\n key={tab.id}\n onClick={() => onSelect(tab.id)}\n title={tab.title}\n className={cn(\n \"cursor-pointer gap-2 py-2\",\n activeId === tab.id && \"bg-accent\",\n )}\n >\n {tab.icon ? (\n <div className=\"relative shrink-0\">\n <span className=\"flex text-muted-foreground [&_svg]:size-4\">\n {tab.icon}\n </span>\n {tab.pinned ? (\n <Pin className=\"absolute -right-1 -top-1 size-2 fill-primary text-primary\" />\n ) : null}\n </div>\n ) : null}\n <div className=\"flex flex-1 flex-col items-start overflow-hidden leading-tight\">\n <span className=\"w-full flex-1 truncate text-sm\">{tab.title}</span>\n {tab.subtitle ? (\n <span className=\"w-full truncate text-[10px] text-muted-foreground\">\n {tab.subtitle}\n </span>\n ) : null}\n </div>\n <X\n className=\"size-4 shrink-0 rounded-sm p-0.5 hover:bg-red-50 hover:text-red-500\"\n onClick={(e) => {\n e.stopPropagation()\n onClose(tab.id)\n }}\n />\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n )\n}\n","\"use client\"\n\nimport { Fragment, type ComponentProps, type ReactNode } from \"react\"\nimport Link from \"next/link\"\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"~/ui/primitives/breadcrumb.js\"\nimport { useActiveRoute } from \"./use-active-route.js\"\n\nexport interface LeadingCrumb {\n /** Where the crumb links. Omit to render it as plain text. */\n href?: string\n label: ReactNode\n /** Hide on small screens, as app-name crumbs usually should. Default `true`. */\n hideOnMobile?: boolean\n}\n\nexport interface BreadcrumbsProps extends ComponentProps<typeof Breadcrumb> {\n /** Separator content. Falls back to shadcn's chevron when omitted. */\n separator?: ReactNode\n /** Segment-id → display-label map. Unmapped segments render raw. */\n labels?: Record<string, string>\n /**\n * Crumb rendered before the path segments — typically the app name linking\n * home. With it set the trail also renders on the root route (as the current\n * page); without it the root route renders nothing.\n */\n leading?: LeadingCrumb\n}\n\n/** Pathname-derived breadcrumbs. Renders nothing on the root route unless `leading` is set. */\nexport function Breadcrumbs({ separator, labels, leading, ...rest }: BreadcrumbsProps) {\n const { pathname } = useActiveRoute()\n const segments = pathname.split(\"/\").filter(Boolean)\n if (segments.length === 0 && !leading) return null\n const last = segments.length - 1\n const hideLeading = leading?.hideOnMobile ?? true\n return (\n <Breadcrumb {...rest}>\n <BreadcrumbList>\n {leading ? (\n <BreadcrumbItem className={hideLeading ? \"hidden md:block\" : undefined}>\n {/* On the root route the leading crumb IS the current page. */}\n {segments.length === 0 ? (\n <BreadcrumbPage>{leading.label}</BreadcrumbPage>\n ) : leading.href ? (\n <BreadcrumbLink asChild>\n <Link href={leading.href}>{leading.label}</Link>\n </BreadcrumbLink>\n ) : (\n leading.label\n )}\n </BreadcrumbItem>\n ) : null}\n {segments.map((seg, i) => {\n const href = \"/\" + segments.slice(0, i + 1).join(\"/\")\n const label = labels?.[seg] ?? seg\n return (\n <Fragment key={href}>\n {i > 0 || leading ? (\n <BreadcrumbSeparator className={i === 0 && hideLeading && leading ? \"hidden md:block\" : undefined}>\n {separator}\n </BreadcrumbSeparator>\n ) : null}\n <BreadcrumbItem>\n {i === last ? (\n <BreadcrumbPage>{label}</BreadcrumbPage>\n ) : (\n <BreadcrumbLink asChild>\n <Link href={href}>{label}</Link>\n </BreadcrumbLink>\n )}\n </BreadcrumbItem>\n </Fragment>\n )\n })}\n </BreadcrumbList>\n </Breadcrumb>\n )\n}\n","import type { ReactNode } from \"react\"\nimport { Search } from \"lucide-react\"\n\nimport { cn } from \"~/utils/cn.js\"\nimport {\n Card,\n CardDescription,\n CardTitle,\n} from \"~/ui/primitives/card.js\"\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"~/ui/primitives/input-group.js\"\n\n/** One application in the {@link AppGrid} — rendered as an {@link AppTile}. */\nexport interface AppGridItem {\n /** Stable React list key. */\n key: string\n /** Display name. */\n name: string\n /** Optional tagline shown under the name. */\n description?: string\n /** Navigation target (usually an absolute cross-app URL). */\n href: string\n /**\n * Pre-rendered icon element (RSC-serializable), e.g. `<ToolCase />`. Sized by\n * the tile (`[&_svg]:size-7`) — same convention as {@link NavBrandApp}'s icon.\n */\n icon: ReactNode\n /**\n * Tailwind class string tinting the icon tile — `text-…` (colors the icon via\n * currentColor) + `bg-…` (tile background). Pass full class strings, not\n * interpolated fragments, so the JIT keeps them.\n */\n accent?: string\n /** Opens on a different origin (adds `target=\"_blank\"` + `rel`). */\n external?: boolean\n}\n\n/** A titled section of apps for {@link AppGrid}'s grouped mode. */\nexport interface AppGridGroup {\n /** Stable React list key. */\n key: string\n /** Section heading. */\n label: string\n /** Optional sub-heading under the label. */\n description?: string\n /** Apps in this group — already filtered by the caller. */\n apps: AppGridItem[]\n}\n\nexport interface AppGridProps {\n /** Flat mode: apps to render (already filtered). Ignored when `groups` is set. */\n apps?: AppGridItem[]\n /**\n * Grouped mode: titled sections (already filtered). When provided, renders a\n * heading + tile grid per group; empty groups are dropped.\n */\n groups?: AppGridGroup[]\n /** Controlled search value. Pass together with `onQueryChange` to show the search box. */\n query?: string\n onQueryChange?: (query: string) => void\n /** Search input placeholder. */\n searchPlaceholder?: string\n /** Autofocus the search box on mount. Default `false`. */\n autoFocusSearch?: boolean\n /** Message shown when there are no apps. */\n emptyLabel?: string\n className?: string\n}\n\n/** Default English labels — override for i18n. */\nexport const defaultAppGridLabels = {\n searchPlaceholder: \"Search apps…\",\n empty: \"No apps found.\",\n}\n\n/**\n * A responsive grid of application tiles with an optional search box — the \"app\n * grid\" / launcher surface (a portal home / \"all apps\" page). Presentational:\n * the app owns the registry, i18n, icons, and the filter — pass the already-\n * filtered `apps` plus a controlled `query`. Same app/lyra split as\n * {@link NavBrand} and {@link TabBar}.\n *\n * @example\n * const [q, setQ] = useState(\"\")\n * const filtered = APPS.filter(a => match(a, q))\n * <AppGrid\n * apps={filtered.map(a => ({\n * key: a.slug, name: t(a.slug), description: t(`${a.slug}.desc`),\n * href: a.href, icon: <a.Icon />, accent: a.accent, external: true,\n * }))}\n * query={q} onQueryChange={setQ}\n * searchPlaceholder={t(\"search\")} emptyLabel={t(\"empty\")}\n * />\n */\nexport function AppGrid({\n apps,\n groups,\n query,\n onQueryChange,\n searchPlaceholder = defaultAppGridLabels.searchPlaceholder,\n autoFocusSearch = false,\n emptyLabel = defaultAppGridLabels.empty,\n className,\n}: AppGridProps) {\n const grouped = groups != null\n const sections = grouped ? groups.filter((g) => g.apps.length > 0) : []\n const flat = apps ?? []\n const isEmpty = grouped ? sections.length === 0 : flat.length === 0\n\n return (\n <div className={cn(\"space-y-8\", className)}>\n {onQueryChange ? (\n <InputGroup className=\"mx-auto h-10 max-w-md\">\n <InputGroupAddon>\n <Search />\n </InputGroupAddon>\n <InputGroupInput\n type=\"search\"\n value={query ?? \"\"}\n onChange={(e) => onQueryChange(e.target.value)}\n placeholder={searchPlaceholder}\n aria-label={searchPlaceholder}\n autoFocus={autoFocusSearch}\n />\n </InputGroup>\n ) : null}\n\n {isEmpty ? (\n <p className=\"text-muted-foreground py-16 text-center text-sm\">\n {emptyLabel}\n </p>\n ) : grouped ? (\n <div className=\"space-y-10\">\n {sections.map((g) => (\n <section key={g.key} className=\"space-y-4\">\n <div className=\"space-y-1\">\n <h2 className=\"text-sm font-semibold tracking-tight\">{g.label}</h2>\n {g.description ? (\n <p className=\"text-muted-foreground text-xs\">{g.description}</p>\n ) : null}\n </div>\n <AppTileGrid apps={g.apps} />\n </section>\n ))}\n </div>\n ) : (\n <AppTileGrid apps={flat} />\n )}\n </div>\n )\n}\n\n/** The responsive tile grid shared by {@link AppGrid}'s flat and grouped modes. */\nfunction AppTileGrid({ apps }: { apps: AppGridItem[] }) {\n return (\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4\">\n {apps.map((app) => (\n <AppTile key={app.key} app={app} />\n ))}\n </div>\n )\n}\n\n/**\n * A single application tile: the icon in a tinted rounded chip above the name +\n * description. Exported for callers that render their own grid.\n */\nexport function AppTile({ app }: { app: AppGridItem }) {\n return (\n <a\n href={app.href}\n target={app.external ? \"_blank\" : undefined}\n rel={app.external ? \"noreferrer\" : undefined}\n className=\"focus-visible:ring-ring group rounded-none outline-none focus-visible:ring-2\"\n >\n <Card className=\"h-full items-center gap-4 px-6 py-8 text-center transition-all duration-200 group-hover:-translate-y-0.5 group-hover:shadow-md group-hover:ring-foreground/30\">\n {/* Tinted icon tile (sharp — matches lyra's rounded-none aesthetic);\n `accent` carries the text-… (icon, via currentColor) + bg-… tint. */}\n <div\n className={cn(\n \"flex size-14 items-center justify-center rounded-none ring-1 ring-foreground/5 ring-inset transition-transform duration-200 group-hover:scale-105 [&_svg]:size-7\",\n app.accent,\n )}\n >\n {app.icon}\n </div>\n <div className=\"space-y-1\">\n <CardTitle>{app.name}</CardTitle>\n {app.description ? (\n <CardDescription className=\"line-clamp-2\">\n {app.description}\n </CardDescription>\n ) : null}\n </div>\n </Card>\n </a>\n )\n}\n"]}
1
+ {"version":3,"sources":["../../src/shell/app-shell.tsx","../../src/shell/stacked-sidebar.tsx","../../src/shell/nav-group.tsx","../../src/shell/use-active-route.ts","../../src/shell/nav-item.tsx","../../src/shell/nav-section.tsx","../../src/shell/nav-brand.tsx","../../src/shell/app-glyph.tsx","../../src/shell/app-switcher.tsx","../../src/shell/nav-user.tsx","../../src/shell/tab-bar.tsx","../../src/shell/breadcrumbs.tsx","../../src/shell/app-grid.tsx"],"names":["jsx","jsxs","Link","Fragment","ChevronsUpDown"],"mappings":"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","file":"index.js","sourcesContent":["\"use client\"\n\nimport type { ComponentProps, ReactNode } from \"react\"\nimport {\n SidebarInset,\n SidebarProvider,\n} from \"~/ui/primitives/sidebar.js\"\nimport { cn } from \"~/utils/cn.js\"\n\nexport interface AppShellProps\n extends Omit<ComponentProps<typeof SidebarProvider>, \"children\"> {\n children: ReactNode\n}\n\n/**\n * App shell composition root. Wires `SidebarProvider`. Pair with\n * `<Sidebar>` from `@tradalab/lyra/ui` and `<AppShellMain>` for the\n * right-hand pane.\n *\n * @example\n * import { AppShell, AppShellMain, AppShellHeader, AppShellBody, NavGroup, NavItem, Breadcrumbs } from \"@tradalab/lyra/shell\"\n * import { Sidebar, SidebarHeader, SidebarContent, SidebarFooter, SidebarTrigger } from \"@tradalab/lyra/ui\"\n *\n * <AppShell>\n * <Sidebar collapsible=\"icon\">\n * <SidebarHeader>{logo}</SidebarHeader>\n * <SidebarContent>\n * <NavGroup label=\"Primitives\">{...}</NavGroup>\n * </SidebarContent>\n * <SidebarFooter>{user}</SidebarFooter>\n * </Sidebar>\n * <AppShellMain>\n * <AppShellHeader><SidebarTrigger /><Breadcrumbs /></AppShellHeader>\n * <AppShellBody>{children}</AppShellBody>\n * </AppShellMain>\n * </AppShell>\n */\nexport function AppShell({ children, ...rest }: AppShellProps) {\n return <SidebarProvider {...rest}>{children}</SidebarProvider>\n}\n\n/** Right-hand pane container. Alias for `SidebarInset`. */\nexport const AppShellMain = SidebarInset\n\n/** Top bar inside `<AppShellMain>`. Standardizes h-12 + border-b + flex row. */\nexport function AppShellHeader({\n className,\n children,\n ...rest\n}: ComponentProps<\"header\">) {\n return (\n <header\n className={cn(\n \"flex h-12 shrink-0 items-center gap-2 border-b px-3\",\n className,\n )}\n {...rest}\n >\n {children}\n </header>\n )\n}\n\n/** Scroll body inside `<AppShellMain>`. Sibling of `<AppShellHeader>`. */\nexport function AppShellBody({\n className,\n children,\n ...rest\n}: ComponentProps<\"div\">) {\n return (\n <div className={cn(\"flex-1 overflow-auto\", className)} {...rest}>\n {children}\n </div>\n )\n}\n","\"use client\"\n\nimport type { ComponentProps } from \"react\"\nimport { Sidebar } from \"~/ui/primitives/sidebar.js\"\nimport { cn } from \"~/utils/cn.js\"\n\n/**\n * Dual / stacked sidebar wrapper — an icon rail plus one or more content\n * panels rendered side-by-side inside a single `<Sidebar>`. This is the\n * shadcn \"sidebar-07\" pattern.\n *\n * The `*:data-[sidebar=sidebar]:flex-row` trick lays the inner\n * `[data-sidebar=sidebar]` wrappers of the nested {@link SidebarDock} /\n * {@link SidebarPanel} columns out horizontally. `variant`/`collapsible`\n * default to `\"sidebar\"`/`\"icon\"` but can be overridden.\n *\n * @example\n * import { AppShell, AppShellMain, StackedSidebar, SidebarDock, SidebarPanel } from \"@tradalab/lyra/shell\"\n * import { SidebarHeader, SidebarContent, SidebarMenu, SidebarMenuItem, SidebarMenuButton } from \"@tradalab/lyra/ui\"\n *\n * <AppShell>\n * <StackedSidebar>\n * <SidebarDock>\n * <SidebarHeader>{logo}</SidebarHeader>\n * <SidebarContent>{iconButtons}</SidebarContent>\n * </SidebarDock>\n * {tab === \"files\" ? <SidebarPanel>{tree}</SidebarPanel> : null}\n * </StackedSidebar>\n * <AppShellMain>{children}</AppShellMain>\n * </AppShell>\n */\nexport function StackedSidebar({\n className,\n ...rest\n}: ComponentProps<typeof Sidebar>) {\n return (\n <Sidebar\n variant=\"sidebar\"\n collapsible=\"icon\"\n {...rest}\n className={cn(\n \"overflow-hidden *:data-[sidebar=sidebar]:flex-row\",\n className,\n )}\n />\n )\n}\n\n/**\n * Narrow icon-rail column inside a {@link StackedSidebar}. Fixed to the icon\n * width, never collapses on its own (the parent `StackedSidebar` owns the\n * icon-mode toggle).\n *\n * Named `SidebarDock` — not `SidebarRail` — because `SidebarRail` already\n * exists in `@tradalab/lyra/ui` as shadcn's drag-to-resize edge handle.\n */\nexport function SidebarDock({\n className,\n ...rest\n}: ComponentProps<typeof Sidebar>) {\n return (\n <Sidebar\n {...rest}\n collapsible=\"none\"\n className={cn(\n \"w-[calc(var(--sidebar-width-icon)+1px)]! overflow-hidden border-r\",\n className,\n )}\n />\n )\n}\n\n/**\n * Wider content column inside a {@link StackedSidebar} (tree, list, …).\n * Fills remaining width; render conditionally to show/hide per app state.\n */\nexport function SidebarPanel({\n className,\n ...rest\n}: ComponentProps<typeof Sidebar>) {\n return (\n <Sidebar\n {...rest}\n collapsible=\"none\"\n className={cn(\"flex-1 overflow-hidden\", className)}\n />\n )\n}\n","\"use client\"\n\nimport type { ReactNode } from \"react\"\nimport {\n SidebarGroup,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarMenu,\n} from \"~/ui/primitives/sidebar.js\"\n\nexport interface NavGroupProps {\n label?: ReactNode\n children: ReactNode\n}\n\nexport function NavGroup({ label, children }: NavGroupProps) {\n return (\n <SidebarGroup>\n {label != null ? <SidebarGroupLabel>{label}</SidebarGroupLabel> : null}\n <SidebarGroupContent>\n <SidebarMenu>{children}</SidebarMenu>\n </SidebarGroupContent>\n </SidebarGroup>\n )\n}\n","\"use client\"\n\nimport { usePathname } from \"next/navigation\"\n\nexport type MatchMode = \"exact\" | \"prefix\"\n\nexport interface UseActiveRoute {\n pathname: string\n isActive: (href: string, mode?: MatchMode) => boolean\n}\n\n/**\n * App-Router pathname helper. Default `mode` is `\"prefix\"`.\n *\n * Root (`/`) is always exact-matched regardless of `mode` — otherwise the\n * root nav item would light up on every nested page.\n */\nexport function useActiveRoute(): UseActiveRoute {\n const pathname = usePathname() ?? \"/\"\n return {\n pathname,\n isActive: (href, mode = \"prefix\") => {\n if (mode === \"exact\" || href === \"/\") return pathname === href\n return pathname === href || pathname.startsWith(`${href}/`)\n },\n }\n}\n","\"use client\"\n\nimport Link from \"next/link\"\nimport type { ReactNode } from \"react\"\nimport {\n SidebarMenuButton,\n SidebarMenuItem,\n} from \"~/ui/primitives/sidebar.js\"\nimport { useActiveRoute, type MatchMode } from \"./use-active-route.js\"\n\nexport type NavIcon = ReactNode\n\n/** Absolute URLs and mail/tel links leave the app — they can't go through next/link. */\nconst looksExternal = (href: string) =>\n /^([a-z][a-z0-9+.-]*:)?\\/\\//i.test(href) || /^(mailto|tel):/i.test(href)\n\nexport interface NavItemProps {\n href: string\n label: string\n /** Pre-rendered icon element, e.g. `<Globe />`. Element form so the prop is serializable across the RSC boundary. */\n icon?: NavIcon\n /** Sidebar tooltip; visible in collapsed icon mode. */\n tooltip?: string\n /** Default `\"prefix\"` — matches `href` and any nested path. */\n matchMode?: MatchMode\n /**\n * Render a new-tab anchor instead of a `next/link`, and never mark the row\n * active. Defaults to auto-detection: absolute (`https://…`), protocol-\n * relative, `mailto:` and `tel:` hrefs count as external.\n */\n external?: boolean\n}\n\n/** Sidebar nav row. Must be rendered inside a {@link NavGroup}. */\nexport function NavItem({\n href,\n label,\n icon,\n tooltip,\n matchMode = \"prefix\",\n external,\n}: NavItemProps) {\n const { isActive } = useActiveRoute()\n const isExternal = external ?? looksExternal(href)\n return (\n <SidebarMenuItem>\n <SidebarMenuButton\n asChild\n isActive={!isExternal && isActive(href, matchMode)}\n tooltip={tooltip}\n >\n {isExternal ? (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\">\n {icon}\n <span>{label}</span>\n </a>\n ) : (\n <Link href={href}>\n {icon}\n <span>{label}</span>\n </Link>\n )}\n </SidebarMenuButton>\n </SidebarMenuItem>\n )\n}\n","\"use client\"\n\nimport type { ReactNode } from \"react\"\nimport { NavGroup } from \"./nav-group.js\"\nimport { NavItem, type NavItemProps } from \"./nav-item.js\"\n\nexport interface NavSectionProps {\n /** Optional group heading. */\n label?: ReactNode\n /** Nav rows — each rendered as a {@link NavItem}. */\n items: NavItemProps[]\n}\n\n/**\n * Config-driven convenience over {@link NavGroup} + {@link NavItem}: pass a\n * data array instead of hand-mapping JSX. For dynamic or conditional rows,\n * compose `NavGroup`/`NavItem` directly.\n *\n * @example\n * const NAV = [\n * { href: \"/files\", label: \"Files\", icon: <Folder /> },\n * { href: \"/trash\", label: \"Trash\", icon: <Trash2 /> },\n * ]\n * <NavSection label=\"Workspace\" items={NAV} />\n */\nexport function NavSection({ label, items }: NavSectionProps) {\n return (\n <NavGroup label={label}>\n {items.map((item) => (\n <NavItem key={item.href} {...item} />\n ))}\n </NavGroup>\n )\n}\n","\"use client\"\n\nimport { Fragment, type ReactNode } from \"react\"\nimport { ChevronsUpDown } from \"lucide-react\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"~/ui/primitives/dropdown-menu.js\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"~/ui/primitives/sidebar.js\"\n\n/** An application shown in the {@link NavBrand} header / switcher. */\nexport interface NavBrandApp {\n /** Display name. */\n name: string\n /**\n * Pre-rendered icon/logo element, e.g. `<Boxes />`. Element form (not a\n * component reference) so the prop stays serializable across the RSC\n * boundary — same convention as {@link NavItem}'s `icon`.\n */\n icon: ReactNode\n /** Navigation target. Usually an absolute cross-app URL (full navigation). */\n href: string\n /** Optional secondary line under the name (tagline / domain). */\n description?: string\n}\n\n/** A labeled section of apps in the {@link NavBrand} switcher. */\nexport interface NavBrandGroup {\n /** Stable React key. */\n key: string\n /** Section heading. Omit for an unlabeled section (e.g. ungrouped apps). */\n label?: string\n apps: NavBrandApp[]\n}\n\nexport interface NavBrandProps {\n /** The current app, rendered in the sidebar header. */\n app: NavBrandApp\n /**\n * Other apps to switch to (flat, single list). When omitted or empty — and no\n * `groups` — the header renders as a plain link to `app.href`.\n */\n apps?: NavBrandApp[]\n /**\n * Grouped apps — rendered as labeled sections separated by dividers. Takes\n * precedence over `apps`. The caller owns the grouping + ordering.\n */\n groups?: NavBrandGroup[]\n /** Heading above a flat `apps` list. Default `\"Applications\"`. Ignored for `groups`. */\n appsLabel?: string\n /** Extra menu content appended below the app list (e.g. an \"Add app\" row). */\n children?: ReactNode\n}\n\n/** Default English heading for the switcher's app list — override for i18n. */\nexport const defaultNavBrandAppsLabel = \"Applications\"\n\n/** Icon tile + name/description shown inside the header button. */\nfunction BrandContent({ app }: { app: NavBrandApp }) {\n return (\n <>\n <div className=\"bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-none [&_svg]:size-4\">\n {app.icon}\n </div>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-semibold\">{app.name}</span>\n {app.description ? (\n <span className=\"text-muted-foreground truncate text-xs\">\n {app.description}\n </span>\n ) : null}\n </div>\n </>\n )\n}\n\n/** A single switch-to-app row (full-navigation link). */\nfunction AppRow({ app }: { app: NavBrandApp }) {\n return (\n <DropdownMenuItem asChild className=\"gap-2 p-2\">\n <a href={app.href}>\n <div className=\"flex size-6 items-center justify-center rounded-none border [&_svg]:size-3.5\">\n {app.icon}\n </div>\n <span className=\"truncate\">{app.name}</span>\n </a>\n </DropdownMenuItem>\n )\n}\n\n/**\n * Sidebar-header brand block with an optional app switcher — the standardized\n * `SidebarHeader` content for app shells (pairs with {@link NavUser} in the\n * footer). Presentational: the app owns the config, icons, and labels.\n *\n * With `groups` (or `apps`), the header is a dropdown trigger listing the other\n * apps as links; `groups` renders labeled sections, `apps` a single flat list.\n * Without either, the header is a plain link to `app.href`. Cross-app links use\n * a plain `<a>` so switching does a full navigation.\n *\n * Must render inside an `AppShell`/`SidebarProvider`, and below a\n * `TooltipProvider` (the collapsed-mode tooltip needs one).\n *\n * @example\n * <NavBrand\n * app={{ name: \"Admin\", description: \"Platform console\", icon: <ShieldCheck />, href: \"/\" }}\n * groups={[\n * { key: \"workspace\", label: \"Workspace\", apps: [{ name: \"Drive\", icon: <HardDrive />, href: \"https://drive.tradalab.com\" }] },\n * ]}\n * />\n */\nexport function NavBrand({\n app,\n apps,\n groups,\n appsLabel = defaultNavBrandAppsLabel,\n children,\n}: NavBrandProps) {\n const { isMobile } = useSidebar()\n const groupTotal = groups?.reduce((n, g) => n + g.apps.length, 0) ?? 0\n const hasSwitcher = (apps?.length ?? 0) > 0 || groupTotal > 0 || children != null\n\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n {hasSwitcher ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <SidebarMenuButton\n size=\"lg\"\n tooltip={app.name}\n className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"\n >\n <BrandContent app={app} />\n <ChevronsUpDown className=\"ml-auto size-4\" />\n </SidebarMenuButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-none\"\n align=\"start\"\n side={isMobile ? \"bottom\" : \"right\"}\n sideOffset={4}\n >\n {groupTotal > 0 ? (\n groups!.map((g, i) => (\n <Fragment key={g.key}>\n {i > 0 ? <DropdownMenuSeparator /> : null}\n {g.label ? (\n <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n {g.label}\n </DropdownMenuLabel>\n ) : null}\n {g.apps.map((item) => (\n <AppRow key={item.href} app={item} />\n ))}\n </Fragment>\n ))\n ) : (\n <>\n <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n {appsLabel}\n </DropdownMenuLabel>\n {apps?.map((item) => (\n <AppRow key={item.href} app={item} />\n ))}\n </>\n )}\n {children ? (\n <>\n <DropdownMenuSeparator />\n {children}\n </>\n ) : null}\n </DropdownMenuContent>\n </DropdownMenu>\n ) : (\n <SidebarMenuButton size=\"lg\" asChild tooltip={app.name}>\n <a href={app.href}>\n <BrandContent app={app} />\n </a>\n </SidebarMenuButton>\n )}\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n","\"use client\"\n\n// Shared visual vocabulary for launcher/registry apps: the FULL lucide icon set\n// (via lucide-react/dynamic — no hand-maintained registry), an accent-color\n// palette, and <AppGlyph> — the single renderer used by the app switcher\n// (NavBrand), the launcher (AppGrid), and each app's Apps admin so a registered\n// app looks identical everywhere.\n//\n// An app's `icon` is a lucide icon name (any of lucide's ~1600 — kebab\n// \"hard-drive\" or Pascal \"HardDrive\"), an image URL, or empty (→ name monogram).\n// `color` is a hex accent (\"\" → theme default).\n\nimport { DynamicIcon, iconNames, type IconName } from \"lucide-react/dynamic\"\n\nimport { cn } from \"~/utils/cn.js\"\n\n/** Every lucide icon name (kebab-case) — the icon picker's source of truth. */\nexport const APP_ICON_NAMES: readonly IconName[] = iconNames\n\nconst ICON_NAME_SET = new Set<string>(iconNames)\n\n/** Normalize a stored name to lucide's kebab-case (\"HardDrive\" → \"hard-drive\"). */\nexport function toIconName(name: string): string {\n return name\n .replace(/([a-z0-9])([A-Z])/g, \"$1-$2\")\n .replace(/[\\s_]+/g, \"-\")\n .toLowerCase()\n}\n\n/** True when `name` resolves to a known lucide icon. */\nexport function isLucideIcon(name: string): boolean {\n return ICON_NAME_SET.has(toIconName(name))\n}\n\n/** Accent palette (tailwind-500 hues) — read well on light + dark surfaces. */\nexport const APP_COLORS: string[] = [\n \"#64748b\", \"#ef4444\", \"#f97316\", \"#f59e0b\", \"#eab308\", \"#22c55e\",\n \"#10b981\", \"#14b8a6\", \"#06b6d4\", \"#3b82f6\", \"#6366f1\", \"#8b5cf6\",\n \"#a855f7\", \"#ec4899\", \"#f43f5e\",\n]\n\nexport function isIconUrl(s: string): boolean {\n return /^(https?:)?\\/\\//.test(s) || s.startsWith(\"/\") || s.startsWith(\"data:\")\n}\n\n/** Append an alpha to a #rrggbb hex → #rrggbbaa (for tinted backgrounds). */\nfunction hexA(hex: string, alpha: number): string {\n const a = Math.round(alpha * 255).toString(16).padStart(2, \"0\")\n return /^#[0-9a-fA-F]{6}$/.test(hex) ? `${hex}${a}` : hex\n}\n\nexport interface AppGlyphProps {\n /** Lucide icon name, image URL, or empty (→ monogram). */\n icon?: string\n /** Hex accent color; \"\" → theme default. */\n color?: string\n /** App name — the monogram fallback + a11y. */\n name?: string\n className?: string\n}\n\n/** The colored glyph for an app: image (URL), lucide icon (name), or monogram. */\nexport function AppGlyph({ icon, color, name, className }: AppGlyphProps) {\n const box = cn(\"flex size-9 shrink-0 items-center justify-center rounded-none\", className)\n\n if (icon && isIconUrl(icon)) {\n return (\n <span\n aria-hidden\n className={cn(box, \"bg-muted bg-cover bg-center\")}\n style={{ backgroundImage: `url(\"${encodeURI(icon)}\")` }}\n />\n )\n }\n\n const tint = color ? { backgroundColor: hexA(color, 0.14) } : undefined\n const fg = color ? { color } : undefined\n const iconName = icon ? toIconName(icon) : \"\"\n\n if (iconName && ICON_NAME_SET.has(iconName)) {\n return (\n <span aria-hidden className={cn(box, !color && \"bg-primary/10\")} style={tint}>\n <DynamicIcon\n name={iconName as IconName}\n className={cn(\"size-5\", !color && \"text-primary\")}\n style={fg}\n />\n </span>\n )\n }\n\n const ch = (name || icon || \"?\").charAt(0).toUpperCase()\n return (\n <span\n aria-hidden\n className={cn(box, \"text-sm font-semibold\", !color && \"bg-primary/10 text-primary\")}\n style={color ? { ...tint, ...fg } : undefined}\n >\n {ch}\n </span>\n )\n}\n","\"use client\"\n\nimport { AppGlyph } from \"./app-glyph.js\"\nimport {\n NavBrand,\n type NavBrandApp,\n type NavBrandGroup,\n} from \"./nav-brand.js\"\n\n/**\n * A registry app in the {@link AppSwitcher} — the shape a launcher endpoint\n * returns (icon + color as strings; the glyph is rendered internally). Structurally\n * matches nekit's `LauncherApp`, so `groupApps(...)` output feeds straight in.\n */\nexport interface AppSwitcherApp {\n name: string\n description?: string\n /** Navigation target (usually an absolute cross-app URL). */\n url: string\n /** Lucide icon name or image URL. */\n icon: string\n /** Hex accent color; \"\" → theme default. */\n color?: string\n}\n\n/** A grouped, ordered section of apps (label omitted for the ungrouped bucket). */\nexport interface AppSwitcherSection {\n key: string\n label?: string\n apps: AppSwitcherApp[]\n}\n\nexport interface AppSwitcherProps {\n /** The current app, shown in the sidebar header. */\n app: NavBrandApp\n /** Grouped registry apps — e.g. nekit `groupApps(data.apps, data.groups)`. */\n sections: AppSwitcherSection[]\n /** Heading for the flat fallback list. */\n appsLabel?: string\n /** Shown when `sections` is empty (registry loading / unavailable) so the\n * switcher never collapses to a plain link. */\n fallback?: NavBrandApp[]\n}\n\n/**\n * The cross-app switcher: a batteries-included wrapper over {@link NavBrand} that\n * takes the launcher registry (grouped `sections` of `{ icon, color, url, … }`)\n * and renders it — labeled group sections, each app's glyph via {@link AppGlyph}.\n * Consumers just fetch + group (nekit) and pass config; icon/render logic lives\n * here. Empty registry → the `fallback` flat list.\n *\n * @example\n * const sections = groupApps(data.apps, data.groups) // @tradalab/nekit/data/launcher\n * <AppSwitcher app={{ name: \"Admin\", icon: <ShieldCheck/>, href: \"/\" }} sections={sections} />\n */\nexport function AppSwitcher({\n app,\n sections,\n appsLabel,\n fallback,\n}: AppSwitcherProps) {\n const groups: NavBrandGroup[] = sections\n .filter((s) => s.apps.length > 0)\n .map((s) => ({\n key: s.key,\n label: s.label,\n apps: s.apps.map((a) => ({\n name: a.name,\n description: a.description,\n href: a.url,\n icon: <AppGlyph icon={a.icon} color={a.color} name={a.name} />,\n })),\n }))\n\n return (\n <NavBrand\n app={app}\n groups={groups.length ? groups : undefined}\n apps={groups.length ? undefined : fallback}\n appsLabel={appsLabel}\n />\n )\n}\n","\"use client\"\n\nimport type { ReactNode } from \"react\"\nimport {\n ChevronsUpDown,\n CircleUser,\n LogIn,\n LogOut,\n Monitor,\n Moon,\n Palette,\n Sun,\n UserRoundCog,\n} from \"lucide-react\"\nimport { useTheme } from \"next-themes\"\nimport { Avatar, AvatarFallback, AvatarImage } from \"~/ui/primitives/avatar.js\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"~/ui/primitives/dropdown-menu.js\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"~/ui/primitives/sidebar.js\"\nimport {\n defaultAccountMenuLabels,\n initialsOf,\n type AccountMenuLabels,\n type AccountMenuUser,\n} from \"~/ui/account-menu.js\"\n\nexport interface NavUserThemeLabels {\n theme: string\n light: string\n dark: string\n system: string\n}\n\n/** Default English theme-submenu labels — spread + override for i18n. */\nexport const defaultNavUserThemeLabels: NavUserThemeLabels = {\n theme: \"Theme\",\n light: \"Light\",\n dark: \"Dark\",\n system: \"System\",\n}\n\nexport interface NavUserProps {\n /**\n * Signed-in user. When `null`/`undefined`, renders a guest menu (icon +\n * theme + Sign in) if `onSignIn` is set, otherwise renders nothing.\n */\n user?: AccountMenuUser | null\n /** Account-action labels — reuses lyra's {@link AccountMenuLabels}. */\n labels?: Partial<AccountMenuLabels>\n /** Switch-account handler (signed-in only). Item hidden if omitted. */\n onSwitchAccount?: () => void\n /** Sign-out handler (signed-in only). Item hidden if omitted. */\n onSignOut?: () => void\n /**\n * Sign-in handler (guest only). When set, a null `user` renders the guest\n * menu with a Sign in action instead of rendering nothing.\n */\n onSignIn?: () => void\n /** Render the light/dark/system theme submenu. Default `true`. */\n showTheme?: boolean\n /** Theme-submenu labels. */\n themeLabels?: Partial<NavUserThemeLabels>\n /** Extra menu content inserted below the theme submenu. */\n children?: ReactNode\n}\n\nconst THEMES = [\n { value: \"light\", key: \"light\", icon: Sun },\n { value: \"dark\", key: \"dark\", icon: Moon },\n { value: \"system\", key: \"system\", icon: Monitor },\n] as const\n\n/**\n * Sidebar-footer account menu — the standardized NavUser for app shells.\n * Avatar trigger (size `lg`) + name/email opening a dropdown with an optional\n * theme switcher and switch-account / sign-out actions. Auth flows stay in the\n * app (callbacks); labels are props for i18n.\n *\n * Differs from {@link AccountMenu} in `@tradalab/lyra/ui`: that one is a\n * generic header dropdown; this is styled for the collapsible sidebar footer\n * and follows `useSidebar()` for mobile placement.\n *\n * Must render inside an `AppShell`/SidebarProvider, and below a\n * `TooltipProvider` (the avatar button's collapsed-mode tooltip requires one —\n * app root providers normally mount it). The theme submenu needs a\n * `next-themes` provider mounted (it no-ops without one); pass\n * `showTheme={false}` for apps with a fixed theme.\n *\n * @example\n * import { NavUser } from \"@tradalab/lyra/shell\"\n * import { SidebarFooter } from \"@tradalab/lyra/ui\"\n *\n * <SidebarFooter>\n * <NavUser\n * user={session.user}\n * onSwitchAccount={() => signIn(\"zitadel\", { redirectTo: \"/\" }, { prompt: \"select_account\" })}\n * onSignOut={() => signOut({ redirectTo: \"/\" })}\n * />\n * </SidebarFooter>\n */\nexport function NavUser({\n user,\n labels,\n onSwitchAccount,\n onSignOut,\n onSignIn,\n showTheme = true,\n themeLabels,\n children,\n}: NavUserProps) {\n const { isMobile } = useSidebar()\n const { theme, setTheme } = useTheme()\n const l = { ...defaultAccountMenuLabels, ...labels }\n const t = { ...defaultNavUserThemeLabels, ...themeLabels }\n\n // Guests render nothing unless a sign-in handler opts them into a guest menu.\n if (!user && !onSignIn) return null\n\n const name = user ? (user.name ?? user.email ?? l.account) : l.guest\n const email = user?.email ?? \"\"\n\n const avatar = (\n <Avatar className=\"size-8 rounded-none after:rounded-none\">\n {user?.image ? (\n <AvatarImage className=\"rounded-none\" src={user.image} alt={name} />\n ) : null}\n <AvatarFallback className=\"rounded-none\">\n {user ? initialsOf(name) : <CircleUser className=\"size-4\" />}\n </AvatarFallback>\n </Avatar>\n )\n\n const themeSubmenu = showTheme ? (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuSub>\n <DropdownMenuSubTrigger>\n <Palette className=\"mr-2 size-4\" />\n {t.theme}\n </DropdownMenuSubTrigger>\n <DropdownMenuSubContent>\n <DropdownMenuRadioGroup value={theme ?? \"system\"} onValueChange={setTheme}>\n {THEMES.map(({ value, key, icon: Icon }) => (\n <DropdownMenuRadioItem key={value} value={value}>\n <Icon className=\"mr-2 size-4\" />\n {t[key]}\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n </DropdownMenuSubContent>\n </DropdownMenuSub>\n </>\n ) : null\n\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <SidebarMenuButton\n size=\"lg\"\n tooltip={name}\n className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"\n >\n {avatar}\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{name}</span>\n {email ? (\n <span className=\"text-muted-foreground truncate text-xs\">\n {email}\n </span>\n ) : null}\n </div>\n <ChevronsUpDown className=\"ml-auto size-4\" />\n </SidebarMenuButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56\"\n side={isMobile ? \"bottom\" : \"right\"}\n align=\"end\"\n sideOffset={4}\n >\n <DropdownMenuLabel className=\"flex items-center gap-2\">\n {avatar}\n <div className=\"grid flex-1 text-left leading-tight\">\n <span className=\"truncate text-sm font-medium\">{name}</span>\n {email ? (\n <span className=\"text-muted-foreground truncate text-xs font-normal\">\n {email}\n </span>\n ) : null}\n </div>\n </DropdownMenuLabel>\n\n {themeSubmenu}\n\n {children ? (\n <>\n <DropdownMenuSeparator />\n {children}\n </>\n ) : null}\n\n {user ? (\n <>\n {onSwitchAccount || onSignOut ? <DropdownMenuSeparator /> : null}\n {onSwitchAccount ? (\n <DropdownMenuItem onSelect={onSwitchAccount}>\n <UserRoundCog className=\"mr-2 size-4\" />\n {l.switchAccount}\n </DropdownMenuItem>\n ) : null}\n {onSignOut ? (\n <DropdownMenuItem variant=\"destructive\" onSelect={onSignOut}>\n <LogOut className=\"mr-2 size-4\" />\n {l.signOut}\n </DropdownMenuItem>\n ) : null}\n </>\n ) : (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem onSelect={onSignIn}>\n <LogIn className=\"mr-2 size-4\" />\n {l.signIn}\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n","\"use client\"\n\nimport { useEffect, useRef, type ReactNode, type WheelEvent } from \"react\"\nimport { ChevronDown, ListX, Pin, PinOff, Trash2, X } from \"lucide-react\"\nimport { Button } from \"~/ui/primitives/button.js\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"~/ui/primitives/dropdown-menu.js\"\nimport { ScrollArea, ScrollBar } from \"~/ui/primitives/scroll-area.js\"\nimport {\n ContextMenu,\n ContextMenuContent,\n ContextMenuItem,\n ContextMenuSeparator,\n ContextMenuTrigger,\n} from \"~/ui/primitives/context-menu.js\"\nimport { cn } from \"~/utils/cn.js\"\n\nexport interface TabItem {\n id: string\n title: string\n /** Secondary line under the title (e.g. connection/db, file path). */\n subtitle?: ReactNode\n /** Leading icon element — the app maps its own tab type → icon. */\n icon?: ReactNode\n pinned?: boolean\n}\n\nexport interface TabBarLabels {\n close: string\n pinTab: string\n unpinTab: string\n closeOthers: string\n closeAll: string\n}\n\n/** Default English labels — spread + override for i18n. */\nexport const defaultTabBarLabels: TabBarLabels = {\n close: \"Close\",\n pinTab: \"Pin tab\",\n unpinTab: \"Unpin tab\",\n closeOthers: \"Close others\",\n closeAll: \"Close all\",\n}\n\nexport interface TabBarProps {\n tabs: TabItem[]\n activeId: string | null\n onSelect: (id: string) => void\n onClose: (id: string) => void\n /** Pin row in the context menu is hidden when omitted. */\n onTogglePin?: (id: string) => void\n /** \"Close others\" row is hidden when omitted. */\n onCloseOthers?: (id: string) => void\n /** \"Close all\" row is hidden when omitted. */\n onCloseAll?: () => void\n labels?: Partial<TabBarLabels>\n}\n\n/**\n * Horizontal tab strip for the content area of stacked-sidebar apps\n * (redishub, loom). Presentational + store-agnostic: the app owns tab state\n * and passes `tabs` + callbacks; `icon`/`subtitle` are per-tab so apps map\n * their own tab types, and labels are props for i18n. Renders nothing when\n * `tabs` is empty.\n *\n * Sizes rows from the `--tab-height` CSS var — set it in your globals.\n *\n * @example\n * const s = useTabStore()\n * <TabBar\n * tabs={s.tabs.map(t => ({ id: t.id, title: t.title, pinned: t.pinned, icon: <Icon t={t.type}/>, subtitle: fmt(t) }))}\n * activeId={s.activeTabId}\n * onSelect={s.setActiveTabId}\n * onClose={s.removeTab}\n * onTogglePin={s.togglePin}\n * onCloseOthers={s.closeOthers}\n * onCloseAll={s.closeAll}\n * />\n */\nexport function TabBar({\n tabs,\n activeId,\n onSelect,\n onClose,\n onTogglePin,\n onCloseOthers,\n onCloseAll,\n labels,\n}: TabBarProps) {\n const l = { ...defaultTabBarLabels, ...labels }\n const activeTabRef = useRef<HTMLDivElement>(null)\n\n // Scroll the active tab into view when it changes.\n useEffect(() => {\n if (activeId && activeTabRef.current) {\n activeTabRef.current.scrollIntoView({\n behavior: \"smooth\",\n block: \"nearest\",\n inline: \"nearest\",\n })\n }\n }, [activeId])\n\n // Map vertical wheel scroll to horizontal scroll over the tab strip.\n const handleWheel = (e: WheelEvent<HTMLDivElement>) => {\n if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) {\n const viewport = e.currentTarget.querySelector(\n '[data-slot=\"scroll-area-viewport\"]',\n )\n if (viewport) viewport.scrollLeft += e.deltaY * 0.5\n }\n }\n\n if (tabs.length === 0) return null\n\n const hasContextActions = Boolean(onTogglePin || onCloseOthers || onCloseAll)\n\n return (\n <div\n className=\"group/tabbar flex w-full shrink-0 items-center overflow-hidden border-b bg-muted/30\"\n style={{ height: \"var(--tab-height)\" }}\n >\n <ScrollArea\n type=\"hover\"\n className=\"min-w-0 flex-1 overflow-hidden [&_[data-orientation=vertical]]:hidden\"\n onWheel={handleWheel}\n >\n <div\n className=\"flex w-max items-center gap-0\"\n style={{ height: \"var(--tab-height)\" }}\n >\n {tabs.map((tab) => {\n const isActive = activeId === tab.id\n return (\n <ContextMenu key={tab.id}>\n <ContextMenuTrigger asChild>\n <div\n ref={isActive ? activeTabRef : null}\n onClick={() => onSelect(tab.id)}\n title={tab.title}\n className={cn(\n \"group relative flex min-w-[140px] max-w-[240px] shrink-0 cursor-pointer select-none items-center gap-2 border-r px-3 transition-colors\",\n isActive\n ? \"border-t-2 border-t-primary bg-background\"\n : \"border-t-2 border-t-transparent bg-transparent text-muted-foreground hover:bg-muted/50\",\n tab.pinned && \"min-w-[100px] bg-primary/5\",\n )}\n style={{ height: \"var(--tab-height)\" }}\n >\n {tab.icon ? (\n <div className=\"relative shrink-0\">\n <span\n className={cn(\n \"flex [&_svg]:size-3.5\",\n isActive && \"text-primary\",\n )}\n >\n {tab.icon}\n </span>\n {tab.pinned ? (\n <div className=\"absolute -right-1.5 -top-1.5 rounded-full bg-background p-0.5 shadow-sm\">\n <Pin className=\"size-2 fill-primary text-primary\" />\n </div>\n ) : null}\n </div>\n ) : null}\n <div className=\"flex min-w-0 flex-1 flex-col items-start justify-center overflow-hidden py-1\">\n <span\n className={cn(\n \"w-full truncate text-xs leading-tight\",\n isActive && \"font-medium text-foreground\",\n )}\n >\n {tab.title}\n </span>\n {tab.subtitle ? (\n <span className=\"mt-0.5 w-full truncate text-[10px] leading-none text-muted-foreground/70\">\n {tab.subtitle}\n </span>\n ) : null}\n </div>\n <Button\n variant=\"ghost\"\n size=\"icon\"\n title={l.close}\n className={cn(\n \"size-5 shrink-0 rounded-md opacity-0 transition-opacity hover:bg-muted-foreground/20 group-hover:opacity-100\",\n isActive && \"opacity-100\",\n )}\n onClick={(e) => {\n e.stopPropagation()\n onClose(tab.id)\n }}\n >\n <X className=\"size-3\" />\n </Button>\n {isActive ? (\n <div className=\"absolute bottom-0 left-0 right-0 z-10 h-[2px] bg-background\" />\n ) : null}\n </div>\n </ContextMenuTrigger>\n {hasContextActions ? (\n <ContextMenuContent className=\"w-48\">\n {onTogglePin ? (\n <>\n <ContextMenuItem onClick={() => onTogglePin(tab.id)}>\n {tab.pinned ? (\n <>\n <PinOff className=\"mr-2 size-4\" />\n <span>{l.unpinTab}</span>\n </>\n ) : (\n <>\n <Pin className=\"mr-2 size-4\" />\n <span>{l.pinTab}</span>\n </>\n )}\n </ContextMenuItem>\n <ContextMenuSeparator />\n </>\n ) : null}\n <ContextMenuItem onClick={() => onClose(tab.id)}>\n <X className=\"mr-2 size-4\" />\n <span>{l.close}</span>\n </ContextMenuItem>\n {onCloseOthers ? (\n <ContextMenuItem onClick={() => onCloseOthers(tab.id)}>\n <ListX className=\"mr-2 size-4\" />\n <span>{l.closeOthers}</span>\n </ContextMenuItem>\n ) : null}\n {onCloseAll ? (\n <ContextMenuItem onClick={() => onCloseAll()}>\n <Trash2 className=\"mr-2 size-4\" />\n <span>{l.closeAll}</span>\n </ContextMenuItem>\n ) : null}\n </ContextMenuContent>\n ) : null}\n </ContextMenu>\n )\n })}\n </div>\n <ScrollBar orientation=\"horizontal\" className=\"z-20 h-1.5 hover:h-2\" />\n </ScrollArea>\n\n <div\n className=\"flex shrink-0 items-center border-l bg-muted/30 px-1\"\n style={{ height: \"var(--tab-height)\" }}\n >\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"size-8 shrink-0 rounded-sm\">\n <ChevronDown className=\"size-4\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align=\"end\"\n className=\"max-h-[400px] w-[260px] overflow-y-auto\"\n >\n {tabs.map((tab) => (\n <DropdownMenuItem\n key={tab.id}\n onClick={() => onSelect(tab.id)}\n title={tab.title}\n className={cn(\n \"cursor-pointer gap-2 py-2\",\n activeId === tab.id && \"bg-accent\",\n )}\n >\n {tab.icon ? (\n <div className=\"relative shrink-0\">\n <span className=\"flex text-muted-foreground [&_svg]:size-4\">\n {tab.icon}\n </span>\n {tab.pinned ? (\n <Pin className=\"absolute -right-1 -top-1 size-2 fill-primary text-primary\" />\n ) : null}\n </div>\n ) : null}\n <div className=\"flex flex-1 flex-col items-start overflow-hidden leading-tight\">\n <span className=\"w-full flex-1 truncate text-sm\">{tab.title}</span>\n {tab.subtitle ? (\n <span className=\"w-full truncate text-[10px] text-muted-foreground\">\n {tab.subtitle}\n </span>\n ) : null}\n </div>\n <X\n className=\"size-4 shrink-0 rounded-sm p-0.5 hover:bg-red-50 hover:text-red-500\"\n onClick={(e) => {\n e.stopPropagation()\n onClose(tab.id)\n }}\n />\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n )\n}\n","\"use client\"\n\nimport { Fragment, type ComponentProps, type ReactNode } from \"react\"\nimport Link from \"next/link\"\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"~/ui/primitives/breadcrumb.js\"\nimport { useActiveRoute } from \"./use-active-route.js\"\n\nexport interface LeadingCrumb {\n /** Where the crumb links. Omit to render it as plain text. */\n href?: string\n label: ReactNode\n /** Hide on small screens, as app-name crumbs usually should. Default `true`. */\n hideOnMobile?: boolean\n}\n\nexport interface BreadcrumbsProps extends ComponentProps<typeof Breadcrumb> {\n /** Separator content. Falls back to shadcn's chevron when omitted. */\n separator?: ReactNode\n /** Segment-id → display-label map. Unmapped segments render raw. */\n labels?: Record<string, string>\n /**\n * Crumb rendered before the path segments — typically the app name linking\n * home. With it set the trail also renders on the root route (as the current\n * page); without it the root route renders nothing.\n */\n leading?: LeadingCrumb\n}\n\n/** Pathname-derived breadcrumbs. Renders nothing on the root route unless `leading` is set. */\nexport function Breadcrumbs({ separator, labels, leading, ...rest }: BreadcrumbsProps) {\n const { pathname } = useActiveRoute()\n const segments = pathname.split(\"/\").filter(Boolean)\n if (segments.length === 0 && !leading) return null\n const last = segments.length - 1\n const hideLeading = leading?.hideOnMobile ?? true\n return (\n <Breadcrumb {...rest}>\n <BreadcrumbList>\n {leading ? (\n <BreadcrumbItem className={hideLeading ? \"hidden md:block\" : undefined}>\n {/* On the root route the leading crumb IS the current page. */}\n {segments.length === 0 ? (\n <BreadcrumbPage>{leading.label}</BreadcrumbPage>\n ) : leading.href ? (\n <BreadcrumbLink asChild>\n <Link href={leading.href}>{leading.label}</Link>\n </BreadcrumbLink>\n ) : (\n leading.label\n )}\n </BreadcrumbItem>\n ) : null}\n {segments.map((seg, i) => {\n const href = \"/\" + segments.slice(0, i + 1).join(\"/\")\n const label = labels?.[seg] ?? seg\n return (\n <Fragment key={href}>\n {i > 0 || leading ? (\n <BreadcrumbSeparator className={i === 0 && hideLeading && leading ? \"hidden md:block\" : undefined}>\n {separator}\n </BreadcrumbSeparator>\n ) : null}\n <BreadcrumbItem>\n {i === last ? (\n <BreadcrumbPage>{label}</BreadcrumbPage>\n ) : (\n <BreadcrumbLink asChild>\n <Link href={href}>{label}</Link>\n </BreadcrumbLink>\n )}\n </BreadcrumbItem>\n </Fragment>\n )\n })}\n </BreadcrumbList>\n </Breadcrumb>\n )\n}\n","import type { ReactNode } from \"react\"\nimport { Search } from \"lucide-react\"\n\nimport { cn } from \"~/utils/cn.js\"\nimport {\n Card,\n CardDescription,\n CardTitle,\n} from \"~/ui/primitives/card.js\"\nimport {\n InputGroup,\n InputGroupAddon,\n InputGroupInput,\n} from \"~/ui/primitives/input-group.js\"\n\n/** One application in the {@link AppGrid} — rendered as an {@link AppTile}. */\nexport interface AppGridItem {\n /** Stable React list key. */\n key: string\n /** Display name. */\n name: string\n /** Optional tagline shown under the name. */\n description?: string\n /** Navigation target (usually an absolute cross-app URL). */\n href: string\n /**\n * Pre-rendered icon element (RSC-serializable), e.g. `<ToolCase />`. Sized by\n * the tile (`[&_svg]:size-7`) — same convention as {@link NavBrandApp}'s icon.\n */\n icon: ReactNode\n /**\n * Tailwind class string tinting the icon tile — `text-…` (colors the icon via\n * currentColor) + `bg-…` (tile background). Pass full class strings, not\n * interpolated fragments, so the JIT keeps them.\n */\n accent?: string\n /** Opens on a different origin (adds `target=\"_blank\"` + `rel`). */\n external?: boolean\n}\n\n/** A titled section of apps for {@link AppGrid}'s grouped mode. */\nexport interface AppGridGroup {\n /** Stable React list key. */\n key: string\n /** Section heading. */\n label: string\n /** Optional sub-heading under the label. */\n description?: string\n /** Apps in this group — already filtered by the caller. */\n apps: AppGridItem[]\n}\n\nexport interface AppGridProps {\n /** Flat mode: apps to render (already filtered). Ignored when `groups` is set. */\n apps?: AppGridItem[]\n /**\n * Grouped mode: titled sections (already filtered). When provided, renders a\n * heading + tile grid per group; empty groups are dropped.\n */\n groups?: AppGridGroup[]\n /** Controlled search value. Pass together with `onQueryChange` to show the search box. */\n query?: string\n onQueryChange?: (query: string) => void\n /** Search input placeholder. */\n searchPlaceholder?: string\n /** Autofocus the search box on mount. Default `false`. */\n autoFocusSearch?: boolean\n /** Message shown when there are no apps. */\n emptyLabel?: string\n className?: string\n}\n\n/** Default English labels — override for i18n. */\nexport const defaultAppGridLabels = {\n searchPlaceholder: \"Search apps…\",\n empty: \"No apps found.\",\n}\n\n/**\n * A responsive grid of application tiles with an optional search box — the \"app\n * grid\" / launcher surface (a portal home / \"all apps\" page). Presentational:\n * the app owns the registry, i18n, icons, and the filter — pass the already-\n * filtered `apps` plus a controlled `query`. Same app/lyra split as\n * {@link NavBrand} and {@link TabBar}.\n *\n * @example\n * const [q, setQ] = useState(\"\")\n * const filtered = APPS.filter(a => match(a, q))\n * <AppGrid\n * apps={filtered.map(a => ({\n * key: a.slug, name: t(a.slug), description: t(`${a.slug}.desc`),\n * href: a.href, icon: <a.Icon />, accent: a.accent, external: true,\n * }))}\n * query={q} onQueryChange={setQ}\n * searchPlaceholder={t(\"search\")} emptyLabel={t(\"empty\")}\n * />\n */\nexport function AppGrid({\n apps,\n groups,\n query,\n onQueryChange,\n searchPlaceholder = defaultAppGridLabels.searchPlaceholder,\n autoFocusSearch = false,\n emptyLabel = defaultAppGridLabels.empty,\n className,\n}: AppGridProps) {\n const grouped = groups != null\n const sections = grouped ? groups.filter((g) => g.apps.length > 0) : []\n const flat = apps ?? []\n const isEmpty = grouped ? sections.length === 0 : flat.length === 0\n\n return (\n <div className={cn(\"space-y-8\", className)}>\n {onQueryChange ? (\n <InputGroup className=\"mx-auto h-10 max-w-md\">\n <InputGroupAddon>\n <Search />\n </InputGroupAddon>\n <InputGroupInput\n type=\"search\"\n value={query ?? \"\"}\n onChange={(e) => onQueryChange(e.target.value)}\n placeholder={searchPlaceholder}\n aria-label={searchPlaceholder}\n autoFocus={autoFocusSearch}\n />\n </InputGroup>\n ) : null}\n\n {isEmpty ? (\n <p className=\"text-muted-foreground py-16 text-center text-sm\">\n {emptyLabel}\n </p>\n ) : grouped ? (\n <div className=\"space-y-10\">\n {sections.map((g) => (\n <section key={g.key} className=\"space-y-4\">\n <div className=\"space-y-1\">\n <h2 className=\"text-sm font-semibold tracking-tight\">{g.label}</h2>\n {g.description ? (\n <p className=\"text-muted-foreground text-xs\">{g.description}</p>\n ) : null}\n </div>\n <AppTileGrid apps={g.apps} />\n </section>\n ))}\n </div>\n ) : (\n <AppTileGrid apps={flat} />\n )}\n </div>\n )\n}\n\n/** The responsive tile grid shared by {@link AppGrid}'s flat and grouped modes. */\nfunction AppTileGrid({ apps }: { apps: AppGridItem[] }) {\n return (\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4\">\n {apps.map((app) => (\n <AppTile key={app.key} app={app} />\n ))}\n </div>\n )\n}\n\n/**\n * A single application tile: the icon in a tinted rounded chip above the name +\n * description. Exported for callers that render their own grid.\n */\nexport function AppTile({ app }: { app: AppGridItem }) {\n return (\n <a\n href={app.href}\n target={app.external ? \"_blank\" : undefined}\n rel={app.external ? \"noreferrer\" : undefined}\n className=\"focus-visible:ring-ring group rounded-none outline-none focus-visible:ring-2\"\n >\n <Card className=\"h-full items-center gap-4 px-6 py-8 text-center transition-all duration-200 group-hover:-translate-y-0.5 group-hover:shadow-md group-hover:ring-foreground/30\">\n {/* Tinted icon tile (sharp — matches lyra's rounded-none aesthetic);\n `accent` carries the text-… (icon, via currentColor) + bg-… tint. */}\n <div\n className={cn(\n \"flex size-14 items-center justify-center rounded-none ring-1 ring-foreground/5 ring-inset transition-transform duration-200 group-hover:scale-105 [&_svg]:size-7\",\n app.accent,\n )}\n >\n {app.icon}\n </div>\n <div className=\"space-y-1\">\n <CardTitle>{app.name}</CardTitle>\n {app.description ? (\n <CardDescription className=\"line-clamp-2\">\n {app.description}\n </CardDescription>\n ) : null}\n </div>\n </Card>\n </a>\n )\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import * as React$1 from 'react';
2
- import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react';
2
+ import { ComponentProps, ReactNode, ComponentPropsWithoutRef, ElementType } from 'react';
3
3
  import { Accordion as Accordion$1, AlertDialog as AlertDialog$1, AspectRatio as AspectRatio$1, Avatar as Avatar$1, Checkbox as Checkbox$1, Collapsible as Collapsible$1, Dialog as Dialog$1, ContextMenu as ContextMenu$1, Direction, DropdownMenu as DropdownMenu$1, Label as Label$1, HoverCard as HoverCard$1, Menubar as Menubar$1, NavigationMenu as NavigationMenu$1, Popover as Popover$1, Progress as Progress$1, RadioGroup as RadioGroup$1, ScrollArea as ScrollArea$1, Select as Select$1, Slider as Slider$1, Switch as Switch$1, Tabs as Tabs$1, Toggle as Toggle$1, ToggleGroup as ToggleGroup$1 } from 'radix-ui';
4
4
  import * as class_variance_authority_types from 'class-variance-authority/types';
5
5
  import { VariantProps } from 'class-variance-authority';
@@ -595,6 +595,33 @@ declare function ToggleGroup({ className, variant, size, spacing, orientation, c
595
595
  }): React$1.JSX.Element;
596
596
  declare function ToggleGroupItem({ className, children, variant, size, ...props }: React$1.ComponentProps<typeof ToggleGroup$1.Item> & VariantProps<typeof toggleVariants>): React$1.JSX.Element;
597
597
 
598
+ interface ActionButtonProps extends Omit<ComponentProps<typeof Button>, "asChild"> {
599
+ /** Swaps `icon` for a spinner and disables the button. */
600
+ pending?: boolean;
601
+ /** Leading icon, shown when idle. */
602
+ icon?: ReactNode;
603
+ }
604
+ /**
605
+ * A `Button` that shows it is working.
606
+ *
607
+ * The spinner REPLACES `icon` rather than sitting beside it — a second glyph
608
+ * reflows the label mid-click, which reads as the button turning into a
609
+ * different button. Pending also disables: a second click on a long action
610
+ * starts a second one.
611
+ *
612
+ * `asChild` is deliberately not forwarded. `Button` renders a Radix `Slot` for
613
+ * it, which accepts exactly one child, and this always renders two.
614
+ *
615
+ * @example
616
+ * <ActionButton pending={m.isPending} icon={<TrashIcon />} onClick={run}>
617
+ * Delete
618
+ * </ActionButton>
619
+ *
620
+ * // Icon-only: omit children and use an icon size.
621
+ * <ActionButton size="icon-sm" pending={busy} icon={<RefreshCwIcon />} />
622
+ */
623
+ declare function ActionButton({ pending, icon, disabled, children, ...props }: ActionButtonProps): React$1.JSX.Element;
624
+
598
625
  /** Max content width, keyed to Tailwind's `--breakpoint-*` scale. `false` = no cap. */
599
626
  type ContainerMaxWidth = "sm" | "md" | "lg" | "xl" | "2xl" | false;
600
627
  /** Which axis the content is centred on. */
@@ -627,4 +654,4 @@ interface ContainerProps extends ComponentPropsWithoutRef<"div"> {
627
654
  */
628
655
  declare function Container({ as: Component, maxWidth, fluid, center, fullHeight, className, children, ...props }: ContainerProps): React$1.JSX.Element;
629
656
 
630
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertAction, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AspectRatio, Attachment, AttachmentAction, AttachmentActions, AttachmentContent, AttachmentDescription, AttachmentGroup, AttachmentMedia, AttachmentTitle, AttachmentTrigger, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, Bubble, BubbleContent, BubbleGroup, BubbleReactions, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, Calendar, CalendarDayButton, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, type CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxSeparator, ComboboxTrigger, ComboboxValue, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Container, type ContainerCenter, type ContainerMaxWidth, type ContainerProps, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DirectionProvider, 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, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, HoverCard, HoverCardContent, HoverCardTrigger, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Label, Marker, MarkerContent, MarkerIcon, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, NativeSelect, NativeSelectOptGroup, NativeSelectOption, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Skeleton, Slider, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toast, ToastAction, ToastClose, ToastContent, ToastDescription, ToastPortal, ToastProvider, ToastTitle, ToastViewport, Toaster, Toggle, ToggleGroup, ToggleGroupItem, badgeVariants, buttonGroupVariants, createToastManager, markerVariants, navigationMenuTriggerStyle, tabsListVariants, toast, toggleVariants, useCarousel, useComboboxAnchor, useDirection, useToastManager };
657
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActionButton, type ActionButtonProps, Alert, AlertAction, AlertDescription, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, AlertTitle, AspectRatio, Attachment, AttachmentAction, AttachmentActions, AttachmentContent, AttachmentDescription, AttachmentGroup, AttachmentMedia, AttachmentTitle, AttachmentTrigger, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, Bubble, BubbleContent, BubbleGroup, BubbleReactions, Button, ButtonGroup, ButtonGroupSeparator, ButtonGroupText, Calendar, CalendarDayButton, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, type CarouselApi, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, type ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, Checkbox, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxCollection, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxSeparator, ComboboxTrigger, ComboboxValue, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Container, type ContainerCenter, type ContainerMaxWidth, type ContainerProps, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DirectionProvider, 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, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle, HoverCard, HoverCardContent, HoverCardTrigger, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot, Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle, Kbd, KbdGroup, Label, Marker, MarkerContent, MarkerIcon, Menubar, MenubarCheckboxItem, MenubarContent, MenubarGroup, MenubarItem, MenubarLabel, MenubarMenu, MenubarPortal, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, NativeSelect, NativeSelectOptGroup, NativeSelectOption, NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, Popover, PopoverAnchor, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, Progress, RadioGroup, RadioGroupItem, ResizableHandle, ResizablePanel, ResizablePanelGroup, ScrollArea, ScrollBar, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Skeleton, Slider, Spinner, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toast, ToastAction, ToastClose, ToastContent, ToastDescription, ToastPortal, ToastProvider, ToastTitle, ToastViewport, Toaster, Toggle, ToggleGroup, ToggleGroupItem, badgeVariants, buttonGroupVariants, createToastManager, markerVariants, navigationMenuTriggerStyle, tabsListVariants, toast, toggleVariants, useCarousel, useComboboxAnchor, useDirection, useToastManager };