@olwiba/ui 0.2.20 → 0.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -34,7 +34,7 @@ interface OlwibaUIProviderProps {
34
34
  */
35
35
  mode?: UIMode;
36
36
  }
37
- declare function OlwibaUIProvider({ children, isMobile: isMobileProp, mode: initialMode }: OlwibaUIProviderProps): react_jsx_runtime.JSX.Element;
37
+ declare function OlwibaUIProvider({ children, isMobile: isMobileProp, mode: modeProp }: OlwibaUIProviderProps): react_jsx_runtime.JSX.Element;
38
38
  declare function useOlwibaUI(): OlwibaUIContextValue;
39
39
  /** Returns just the current UI mode from context. */
40
40
  declare function useUIMode(): UIMode;
@@ -231,6 +231,7 @@ interface AppShellUser {
231
231
  onSignOut?: () => void;
232
232
  onBilling?: () => void;
233
233
  onNotifications?: () => void;
234
+ onSettings?: () => void;
234
235
  }
235
236
  interface AppShellBrand {
236
237
  name: ReactNode;
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import { useRef, useEffect, useState, useCallback } from 'react';
5
5
  import { Button as Button$1, Card as Card$1, Input as Input$1, Textarea as Textarea$1, Checkbox as Checkbox$1, Switch as Switch$1, useIsMobile, UIVariantProvider, Badge as Badge$1, cn as cn$1, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Avatar, AvatarImage, AvatarFallback, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, Dialog, DialogTrigger, Progress, useUIVariant, Separator, Accordion, AccordionItem, AccordionTrigger, AccordionContent, Label, Sheet, SheetTrigger, SheetContent, StatusIndicator, CommandDialog, CommandInput, CommandList, CommandEmpty, CommandSeparator, CommandGroup, CommandItem, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, ContextMenu as ContextMenu$1, ContextMenuTrigger, ContextMenuContent, AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, CommandShortcut, Popover, PopoverTrigger, PopoverContent, Spinner, SidebarProvider, SidebarInset, CardHeader, CardTitle, CardDescription, CardContent, InputOTP, InputOTPGroup, InputOTPSlot, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose, ContextMenuSeparator, ContextMenuLabel, ContextMenuSub, ContextMenuSubTrigger, ContextMenuSubContent, ContextMenuItem, ContextMenuShortcut, useSidebar, Sidebar, SidebarHeader, SidebarMenu, SidebarMenuItem, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarMenuButton, SidebarFooter, SidebarTrigger, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup } from '@olwiba/cn';
6
6
  export { CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Enchanted } from '@olwiba/cn';
7
7
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
- import { Search, ArrowUp, ArrowDown, ArrowUpDown, ChevronLeft, ChevronRight, MoreHorizontal, UserPlus, Download, CreditCard, Check, Loader2, ArrowLeft, ArrowUpRight, X, Sparkles, RefreshCw, ArrowRight, Minus, Quote, Star, Twitter, Github, Linkedin, Mail, MessageSquare, ChevronDown, Send, Menu, UploadCloud, File, CheckCircle2, AlertCircle, Bell, Inbox, Activity, TrendingUp, TrendingDown, LayoutGrid, List, Sun, Moon, Palette, AlertTriangle, Rocket, Info, Layers, ShieldCheck, Building2, MoreVerticalIcon, CreditCardIcon, BellIcon, LogOutIcon } from 'lucide-react';
8
+ import { Search, ArrowUp, ArrowDown, ArrowUpDown, ChevronLeft, ChevronRight, MoreHorizontal, UserPlus, Download, CreditCard, Check, Loader2, ArrowLeft, ArrowUpRight, X, Sparkles, RefreshCw, ArrowRight, Minus, Quote, Star, Twitter, Github, Linkedin, Mail, MessageSquare, ChevronDown, Send, Menu, UploadCloud, File, CheckCircle2, AlertCircle, Bell, Inbox, Activity, TrendingUp, TrendingDown, LayoutGrid, List, Sun, Moon, Palette, AlertTriangle, Rocket, Info, Layers, ShieldCheck, Building2, BirdIcon, MoreVerticalIcon, CreditCardIcon, BellIcon, SettingsIcon, LogOutIcon } from 'lucide-react';
9
9
  import { useReactTable, getPaginationRowModel, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
10
10
  import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter } from '@dnd-kit/core';
11
11
  import { sortableKeyboardCoordinates, SortableContext, rectSortingStrategy, horizontalListSortingStrategy, verticalListSortingStrategy, arrayMove, useSortable } from '@dnd-kit/sortable';
@@ -19,10 +19,11 @@ var OlwibaUIContext = React21.createContext({
19
19
  setMode: () => {
20
20
  }
21
21
  });
22
- function OlwibaUIProvider({ children, isMobile: isMobileProp, mode: initialMode = "default" }) {
22
+ function OlwibaUIProvider({ children, isMobile: isMobileProp, mode: modeProp }) {
23
23
  const detectedMobile = useIsMobile();
24
24
  const isMobile = isMobileProp ?? detectedMobile;
25
- const [mode, setMode] = React21.useState(initialMode);
25
+ const [uncontrolledMode, setMode] = React21.useState("default");
26
+ const mode = modeProp ?? uncontrolledMode;
26
27
  const variant = mode !== "default" ? mode : void 0;
27
28
  return /* @__PURE__ */ jsx(OlwibaUIContext.Provider, { value: { isMobile, mode, setMode }, children: /* @__PURE__ */ jsx(UIVariantProvider, { mode: variant, children }) });
28
29
  }
@@ -262,20 +263,23 @@ function PublicPageFrame({
262
263
  return /* @__PURE__ */ jsx("div", { className: cn("min-h-screen", surfaceMap[surface], className), ...props, children: /* @__PURE__ */ jsx("div", { className: cn("flex flex-col", spacingMap2[spacing], maxWidthMap2[maxWidth]), children }) });
263
264
  }
264
265
  var RAIL_SQUARE = "group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!min-w-8 group-data-[collapsible=icon]:!max-w-8 group-data-[collapsible=icon]:!p-0 group-data-[collapsible=icon]:transition-[width,height]";
265
- function initialsOf(source) {
266
- const base = source.includes("@") ? source.split("@")[0] ?? source : source;
267
- const words = base.split(/[\s._-]+/).filter(Boolean);
268
- if (words.length >= 2) return (words[0][0] + words[1][0]).toUpperCase();
269
- return (words[0] ?? base).slice(0, 2).toUpperCase();
270
- }
271
266
  function identityGradient(seed) {
272
- let hash = 0;
267
+ let hash = 2166136261;
273
268
  for (let i = 0; i < seed.length; i += 1) {
274
- hash = hash * 31 + seed.charCodeAt(i) | 0;
269
+ hash ^= seed.charCodeAt(i);
270
+ hash = Math.imul(hash, 16777619);
275
271
  }
276
- const hue = Math.abs(hash) % 360;
272
+ hash >>>= 0;
273
+ const firstHue = hash % 360;
274
+ const secondHue = (firstHue + 55 + (hash >>> 8) % 70) % 360;
275
+ const thirdHue = (firstHue + 190 + (hash >>> 16) % 110) % 360;
276
+ const angleHash = Math.imul(hash ^ hash >>> 15, 2246822519) >>> 0;
277
+ const angle = angleHash % 360;
277
278
  return {
278
- backgroundImage: `linear-gradient(135deg, oklch(0.62 0.15 ${hue}), oklch(0.52 0.16 ${(hue + 28) % 360}))`,
279
+ backgroundImage: [
280
+ `radial-gradient(circle at 28% 18%, oklch(0.94 0.06 ${thirdHue} / 0.78), transparent 34%)`,
281
+ `linear-gradient(${angle}deg, oklch(0.68 0.18 ${firstHue}), oklch(0.55 0.2 ${secondHue}) 52%, oklch(0.62 0.18 ${thirdHue}))`
282
+ ].join(", "),
279
283
  color: "oklch(0.98 0 0)"
280
284
  };
281
285
  }
@@ -283,8 +287,8 @@ function NavUser({ user }) {
283
287
  const { isMobile } = useSidebar();
284
288
  const uiMode = useUIMode();
285
289
  const avatarMode = uiMode !== "default" ? uiMode : void 0;
286
- const initials = initialsOf(user.name ?? user.email);
287
- const identityTint = identityGradient(user.email);
290
+ const identitySeed = `${user.name?.trim().toLocaleLowerCase() ?? ""}|${user.email.toLocaleLowerCase()}`;
291
+ const identityTint = identityGradient(identitySeed);
288
292
  return /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
289
293
  /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
290
294
  SidebarMenuButton,
@@ -298,7 +302,13 @@ function NavUser({ user }) {
298
302
  children: [
299
303
  /* @__PURE__ */ jsxs(Avatar, { mode: avatarMode, size: "sm", children: [
300
304
  user.avatar && /* @__PURE__ */ jsx(AvatarImage, { src: user.avatar, alt: user.name }),
301
- /* @__PURE__ */ jsx(AvatarFallback, { className: "font-medium", style: identityTint, children: initials })
305
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "text-white", style: identityTint, children: /* @__PURE__ */ jsx(
306
+ BirdIcon,
307
+ {
308
+ "aria-hidden": true,
309
+ className: "size-4 drop-shadow-[0_1px_1px_rgb(0_0_0/0.3)]"
310
+ }
311
+ ) })
302
312
  ] }),
303
313
  /* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
304
314
  /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: user.name ?? user.email }),
@@ -319,14 +329,20 @@ function NavUser({ user }) {
319
329
  /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "p-0 font-normal", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-1 py-1.5 text-left text-sm", children: [
320
330
  /* @__PURE__ */ jsxs(Avatar, { mode: avatarMode, size: "sm", children: [
321
331
  user.avatar && /* @__PURE__ */ jsx(AvatarImage, { src: user.avatar, alt: user.name }),
322
- /* @__PURE__ */ jsx(AvatarFallback, { className: "font-medium", style: identityTint, children: initials })
332
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "text-white", style: identityTint, children: /* @__PURE__ */ jsx(
333
+ BirdIcon,
334
+ {
335
+ "aria-hidden": true,
336
+ className: "size-4 drop-shadow-[0_1px_1px_rgb(0_0_0/0.3)]"
337
+ }
338
+ ) })
323
339
  ] }),
324
340
  /* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
325
341
  /* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: user.name ?? user.email }),
326
342
  /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: user.email })
327
343
  ] })
328
344
  ] }) }),
329
- (user.onBilling || user.onNotifications) && /* @__PURE__ */ jsxs(Fragment, { children: [
345
+ (user.onBilling || user.onNotifications || user.onSettings) && /* @__PURE__ */ jsxs(Fragment, { children: [
330
346
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
331
347
  /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
332
348
  user.onBilling && /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: user.onBilling, children: [
@@ -336,6 +352,10 @@ function NavUser({ user }) {
336
352
  user.onNotifications && /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: user.onNotifications, children: [
337
353
  /* @__PURE__ */ jsx(BellIcon, {}),
338
354
  "Notifications"
355
+ ] }),
356
+ user.onSettings && /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: user.onSettings, children: [
357
+ /* @__PURE__ */ jsx(SettingsIcon, {}),
358
+ "Settings"
339
359
  ] })
340
360
  ] })
341
361
  ] }),
@@ -479,7 +499,7 @@ function AppShell({
479
499
  sidebarPosition
480
500
  }
481
501
  ),
482
- /* @__PURE__ */ jsxs(SidebarInset, { className: isContained ? void 0 : "overflow-y-auto", children: [
502
+ /* @__PURE__ */ jsxs(SidebarInset, { className: "overflow-y-auto", children: [
483
503
  /* @__PURE__ */ jsx(ShellHeader, { pageTitle, headerStart, headerEnd }),
484
504
  /* @__PURE__ */ jsx("div", { className: contentClassName, children })
485
505
  ] })
@@ -506,8 +526,14 @@ function AppPageHero({
506
526
  {
507
527
  className: cn(
508
528
  "relative overflow-hidden rounded-3xl border bg-card/80 p-5 shadow-sm sm:p-6",
509
- "before:absolute before:-right-16 before:-top-16 before:size-44 before:rounded-full before:bg-primary/15 before:blur-3xl",
510
- "after:absolute after:-bottom-20 after:left-10 after:size-52 after:rounded-full after:bg-primary/10 after:blur-3xl",
529
+ // The glow blobs are decoration, and `::after` is the section's last
530
+ // child so with everything on `z-index: auto` it paints above the
531
+ // header content and swallows clicks on whatever sits under it. At
532
+ // narrow widths the action row stacks below the copy, right into the
533
+ // bottom-left blob, which is how a visible button stops responding.
534
+ // pointer-events-none keeps them purely visual.
535
+ "before:pointer-events-none before:absolute before:-right-16 before:-top-16 before:size-44 before:rounded-full before:bg-primary/15 before:blur-3xl",
536
+ "after:pointer-events-none after:absolute after:-bottom-20 after:left-10 after:size-52 after:rounded-full after:bg-primary/10 after:blur-3xl",
511
537
  className
512
538
  ),
513
539
  children: [