organify-ui 0.3.22 → 0.3.24

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.
@@ -1,7 +1,7 @@
1
- import { cn, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, ScrollArea, Skeleton, Avatar, AvatarFallback, Drawer, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter, Badge, useOrganifyApi, useOrganifyUser, useOrganifyWorkspace, useOrganifyGql } from './chunk-276ZWKXB.js';
1
+ import { cn, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, ScrollArea, Skeleton, useOrganifyApi, useOrganify, Avatar, AvatarImage, AvatarFallback, Drawer, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter, Badge, useOrganifyUser, useOrganifyWorkspace, useOrganifyGql } from './chunk-276ZWKXB.js';
2
2
  import { OrgPlus, OrgSearch, OrgComment, OrgClose, OrgEdit, OrgTeam, OrgGlobe, OrgLock, OrgCheckCircle, OrgError, OrgWarning, OrgInfo, OrgChevronDown, OrgChevronRight, OrgDoor, OrgTrash, OrgCheck, OrgFolder, OrgChevronLeft } from './chunk-MZKEDV5W.js';
3
3
  import * as React6 from 'react';
4
- import React6__default, { useState, useCallback, useEffect } from 'react';
4
+ import React6__default, { useState, useEffect, useCallback } from 'react';
5
5
  import { Slot } from '@radix-ui/react-slot';
6
6
  import { cva } from 'class-variance-authority';
7
7
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -399,6 +399,236 @@ function ChatSidebar({
399
399
  ] }) }) })
400
400
  ] });
401
401
  }
402
+ var _cache = /* @__PURE__ */ new Map();
403
+ var _inflight = /* @__PURE__ */ new Map();
404
+ var _pendingBatch = /* @__PURE__ */ new Set();
405
+ var _batchTimer = null;
406
+ var _batchResolvers = /* @__PURE__ */ new Map();
407
+ function _flushBatch(gatewayUrl) {
408
+ const ids = Array.from(_pendingBatch);
409
+ _pendingBatch.clear();
410
+ _batchTimer = null;
411
+ if (ids.length === 0) return;
412
+ const p = fetch(`${gatewayUrl}/api/users/profiles/batch`, {
413
+ method: "POST",
414
+ headers: { "Content-Type": "application/json" },
415
+ credentials: "include",
416
+ body: JSON.stringify({ ids })
417
+ }).then((r) => r.ok ? r.json() : null).catch(() => null).then((body) => {
418
+ const results = !body ? [] : Array.isArray(body) ? body : Array.isArray(body.data) ? body.data : [];
419
+ const byId = /* @__PURE__ */ new Map();
420
+ for (const u of results) {
421
+ byId.set(String(u.id), u);
422
+ }
423
+ for (const id of ids) {
424
+ const user = byId.get(id) ?? null;
425
+ _cache.set(id, user);
426
+ _inflight.delete(id);
427
+ const resolvers = _batchResolvers.get(id) ?? [];
428
+ _batchResolvers.delete(id);
429
+ for (const resolve of resolvers) resolve(user);
430
+ }
431
+ });
432
+ for (const id of ids) {
433
+ if (!_batchResolvers.has(id)) _batchResolvers.set(id, []);
434
+ _inflight.set(id, p.then(() => _cache.get(id) ?? null));
435
+ }
436
+ }
437
+ function resolveUser(userId, gatewayUrl) {
438
+ if (_cache.has(userId)) {
439
+ return Promise.resolve(_cache.get(userId));
440
+ }
441
+ if (_inflight.has(userId)) {
442
+ return _inflight.get(userId);
443
+ }
444
+ _pendingBatch.add(userId);
445
+ if (!_batchResolvers.has(userId)) _batchResolvers.set(userId, []);
446
+ if (!_batchTimer) {
447
+ _batchTimer = setTimeout(() => _flushBatch(gatewayUrl), 0);
448
+ }
449
+ const p = new Promise((resolve) => {
450
+ _batchResolvers.get(userId).push(resolve);
451
+ });
452
+ _inflight.set(userId, p);
453
+ return p;
454
+ }
455
+ function invalidateUserCache(userId) {
456
+ _cache.delete(userId);
457
+ _inflight.delete(userId);
458
+ }
459
+ function seedUserCache(users) {
460
+ for (const u of users) {
461
+ _cache.set(String(u.id), u);
462
+ }
463
+ }
464
+ function useResolvedUser(userId) {
465
+ const api = useOrganifyApi();
466
+ const { user: currentUser } = useOrganify();
467
+ const key = userId != null ? String(userId) : void 0;
468
+ if (currentUser?.id != null) {
469
+ const ck = String(currentUser.id);
470
+ if (!_cache.has(ck)) {
471
+ _cache.set(ck, {
472
+ id: currentUser.id,
473
+ name: currentUser.name ?? "",
474
+ avatarUrl: currentUser.avatarUrl ?? void 0
475
+ });
476
+ }
477
+ }
478
+ const [user, setUser] = useState(() => {
479
+ if (!key) return void 0;
480
+ return _cache.has(key) ? _cache.get(key) : void 0;
481
+ });
482
+ useEffect(() => {
483
+ if (!key || !api.gatewayUrl) return;
484
+ let cancelled = false;
485
+ if (_cache.has(key)) {
486
+ setUser(_cache.get(key) ?? null);
487
+ return;
488
+ }
489
+ resolveUser(key, api.gatewayUrl).then((u) => {
490
+ if (!cancelled) setUser(u);
491
+ });
492
+ return () => {
493
+ cancelled = true;
494
+ };
495
+ }, [key, api.gatewayUrl]);
496
+ useEffect(() => {
497
+ if (!key || !currentUser?.id) return;
498
+ if (String(currentUser.id) === key) {
499
+ setUser(_cache.get(key) ?? null);
500
+ }
501
+ }, [key, currentUser]);
502
+ return user;
503
+ }
504
+ function getInitials(name) {
505
+ return name.split(/\s+/).filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");
506
+ }
507
+ function nameToGradient(name) {
508
+ let hash = 0;
509
+ for (let i = 0; i < name.length; i++) {
510
+ hash = name.charCodeAt(i) + ((hash << 5) - hash);
511
+ }
512
+ const gradients = [
513
+ "from-violet-500 to-purple-600",
514
+ "from-blue-500 to-cyan-500",
515
+ "from-emerald-500 to-teal-500",
516
+ "from-orange-500 to-amber-500",
517
+ "from-rose-500 to-pink-500",
518
+ "from-indigo-500 to-blue-600",
519
+ "from-fuchsia-500 to-purple-500",
520
+ "from-teal-500 to-green-500"
521
+ ];
522
+ return gradients[Math.abs(hash) % gradients.length];
523
+ }
524
+ function UserAvatar({
525
+ userId,
526
+ name: nameProp,
527
+ src: srcProp,
528
+ email,
529
+ role,
530
+ showHoverInfo = true,
531
+ fallback,
532
+ extraInfo,
533
+ onClick,
534
+ className,
535
+ size = "default",
536
+ shape = "circle",
537
+ status,
538
+ ...props
539
+ }) {
540
+ const resolved = useResolvedUser(!nameProp && userId != null ? userId : null);
541
+ const name = nameProp ?? resolved?.name ?? "\u2026";
542
+ const src = srcProp ?? resolved?.avatarUrl ?? void 0;
543
+ const isLoading = !nameProp && userId != null && resolved === void 0;
544
+ const initials = getInitials(name);
545
+ const gradient = nameToGradient(name || "unknown");
546
+ const avatarElement = /* @__PURE__ */ jsxs(
547
+ Avatar,
548
+ {
549
+ size,
550
+ shape,
551
+ status,
552
+ gradient,
553
+ className: cn(
554
+ onClick && "cursor-pointer",
555
+ isLoading && "animate-pulse opacity-60",
556
+ className
557
+ ),
558
+ onClick,
559
+ ...props,
560
+ children: [
561
+ src ? /* @__PURE__ */ jsx(AvatarImage, { src, alt: name }) : null,
562
+ /* @__PURE__ */ jsx(
563
+ AvatarFallback,
564
+ {
565
+ className: cn(
566
+ "bg-gradient-to-br text-white font-semibold",
567
+ gradient,
568
+ size === "sm" && "text-xs",
569
+ size === "default" && "text-sm",
570
+ size === "lg" && "text-lg",
571
+ size === "xl" && "text-xl"
572
+ ),
573
+ children: fallback ?? initials
574
+ }
575
+ )
576
+ ]
577
+ }
578
+ );
579
+ if (!showHoverInfo) return avatarElement;
580
+ return /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
581
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: avatarElement }),
582
+ /* @__PURE__ */ jsxs(
583
+ TooltipContent,
584
+ {
585
+ side: "top",
586
+ className: cn(
587
+ "flex items-center gap-3 rounded-xl border border-theme-subtle",
588
+ "bg-card-surface/95 px-4 py-3 shadow-glass-xl backdrop-blur-2xl",
589
+ "max-w-xs"
590
+ ),
591
+ children: [
592
+ /* @__PURE__ */ jsxs(Avatar, { size: "sm", shape, gradient, children: [
593
+ src ? /* @__PURE__ */ jsx(AvatarImage, { src, alt: name }) : null,
594
+ /* @__PURE__ */ jsx(AvatarFallback, { className: cn("bg-gradient-to-br text-white text-xs font-semibold", gradient), children: initials })
595
+ ] }),
596
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 min-w-0", children: [
597
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-white truncate", children: name }),
598
+ email && /* @__PURE__ */ jsx("span", { className: "text-xs text-theme-muted truncate", children: email }),
599
+ role && /* @__PURE__ */ jsx("span", { className: "text-xs text-primary-light/80 capitalize", children: role.toLowerCase() }),
600
+ extraInfo?.map((info) => /* @__PURE__ */ jsxs("span", { className: "text-xs text-theme-muted", children: [
601
+ info.label,
602
+ ": ",
603
+ info.value
604
+ ] }, info.label))
605
+ ] })
606
+ ]
607
+ }
608
+ )
609
+ ] }) });
610
+ }
611
+ UserAvatar.displayName = "UserAvatar";
612
+ function UserDisplayName({
613
+ userId,
614
+ name: nameProp,
615
+ loadingFallback = "\u2026",
616
+ className,
617
+ style
618
+ }) {
619
+ const resolved = useResolvedUser(!nameProp && userId != null ? userId : null);
620
+ const isLoading = !nameProp && userId != null && resolved === void 0;
621
+ const displayName = nameProp ?? resolved?.name ?? (isLoading ? loadingFallback : "?");
622
+ return /* @__PURE__ */ jsx(
623
+ "span",
624
+ {
625
+ className: cn(isLoading && "animate-pulse opacity-60", className),
626
+ style,
627
+ title: displayName,
628
+ children: displayName
629
+ }
630
+ );
631
+ }
402
632
  var actionBarVariants = {
403
633
  hidden: {
404
634
  opacity: 0,
@@ -455,10 +685,6 @@ function formatTime(iso) {
455
685
  minute: "2-digit"
456
686
  });
457
687
  }
458
- function getInitials(name) {
459
- if (!name) return "??";
460
- return name.split(" ").map((w) => w[0]).slice(0, 2).join("").toUpperCase();
461
- }
462
688
  function groupReactions(reactions) {
463
689
  const map = /* @__PURE__ */ new Map();
464
690
  reactions.forEach((r) => {
@@ -796,7 +1022,17 @@ function MessageBubble({
796
1022
  showActions && "bg-theme-subtle"
797
1023
  ),
798
1024
  children: [
799
- /* @__PURE__ */ jsx(motion.div, { whileHover: { scale: 1.05 }, whileTap: { scale: 0.95 }, children: /* @__PURE__ */ jsx(Avatar, { shape: "circle", size: "sm", className: "mt-0.5 shrink-0", children: /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary/20 text-primary-light text-xs font-semibold", children: getInitials(message.authorName || message.authorId) }) }) }),
1025
+ /* @__PURE__ */ jsx(motion.div, { whileHover: { scale: 1.05 }, whileTap: { scale: 0.95 }, children: /* @__PURE__ */ jsx(
1026
+ UserAvatar,
1027
+ {
1028
+ userId: message.authorId,
1029
+ name: message.authorName,
1030
+ src: message.authorAvatarUrl,
1031
+ size: "sm",
1032
+ showHoverInfo: false,
1033
+ className: "mt-0.5 shrink-0"
1034
+ }
1035
+ ) }),
800
1036
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 relative", children: [
801
1037
  /* @__PURE__ */ jsx(
802
1038
  ActionBar,
@@ -837,7 +1073,7 @@ function MessageBubble({
837
1073
  }
838
1074
  ) }),
839
1075
  /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-2 mb-0.5", children: [
840
- /* @__PURE__ */ jsx("span", { className: "text-[13px] font-semibold text-theme", children: message.authorName || message.authorId.substring(0, 8) }),
1076
+ /* @__PURE__ */ jsx("span", { className: "text-[13px] font-semibold text-theme", children: /* @__PURE__ */ jsx(UserDisplayName, { userId: message.authorId, name: message.authorName }) }),
841
1077
  /* @__PURE__ */ jsx("span", { className: "text-[11px] text-theme-muted", children: formatTime(message.createdAt) }),
842
1078
  message.edited && /* @__PURE__ */ jsx(
843
1079
  motion.span,
@@ -4471,6 +4707,6 @@ function useAiInline({ gatewayUrl, workspaceId, projectId }) {
4471
4707
  return { loading, suggestion, requestSuggestion, dismiss };
4472
4708
  }
4473
4709
 
4474
- export { AiChatSidebar, Alert, Button, ChatMessages, ChatSidebar, CommandBar, CreateRoomDialog, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, InlineAiButton, Input, Label, MOCK_PROJECTS, MOCK_USERS, MentionPopover, MessageBubble, MessageInput, OrgLoader, OrgLoaderInline, OrganifyChat, ResponsiveDialog, RoomManagementPanel, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, TypingIndicatorMock, alertVariants, buttonVariants, generateAutoReplies, getMockMentionOptions, getRoomPermissions, inputVariants, orgLoaderVariants, typingIndicator, useAiInline, useChat };
4475
- //# sourceMappingURL=chunk-SNGMKLFD.js.map
4476
- //# sourceMappingURL=chunk-SNGMKLFD.js.map
4710
+ export { AiChatSidebar, Alert, Button, ChatMessages, ChatSidebar, CommandBar, CreateRoomDialog, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, InlineAiButton, Input, Label, MOCK_PROJECTS, MOCK_USERS, MentionPopover, MessageBubble, MessageInput, OrgLoader, OrgLoaderInline, OrganifyChat, ResponsiveDialog, RoomManagementPanel, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, TypingIndicatorMock, UserAvatar, UserDisplayName, alertVariants, buttonVariants, generateAutoReplies, getMockMentionOptions, getRoomPermissions, inputVariants, invalidateUserCache, orgLoaderVariants, resolveUser, seedUserCache, typingIndicator, useAiInline, useChat, useResolvedUser };
4711
+ //# sourceMappingURL=chunk-JGDJNAAW.js.map
4712
+ //# sourceMappingURL=chunk-JGDJNAAW.js.map