@algenium/blocks 1.20.0 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import * as React7 from 'react';
3
3
  import { createContext, useContext, useState, useCallback, useEffect, useRef, useMemo, useId } from 'react';
4
- import { ChevronsUpDown, CheckIcon, SearchIcon, Loader2, AlertTriangle, Inbox, CircleIcon, ChevronRightIcon, Monitor, Sun, Moon, Building2, Check, Plus, Languages, FlaskConical, X, Upload, Move, ZoomOut, ZoomIn, RotateCcw, RotateCw, Grid3X3, RefreshCw, XIcon, User, Pencil, Bell, CheckCheck, XCircle, CheckCircle, Info, Trash2, Clock, MapPin, Link, CalendarDays, ExternalLink, ChevronLeft, ChevronRight, Search, CheckCircle2, Link2, HelpCircle, Circle, Wifi, WifiOff, MessageSquare, FileIcon, Download, Paperclip, Send, Store, ArrowLeft, Flag, Hash, Lightbulb, Trophy, Plane, Apple, Leaf, Hand, Smile, Play, AlertCircle, VolumeX, Pause, Volume1, Volume2, Settings, PictureInPicture2, Minimize, Maximize, CreditCard, BadgeCheck, CircleCheck, CircleDollarSign, Users } from 'lucide-react';
4
+ import { ChevronsUpDown, CheckIcon, SearchIcon, Loader2, AlertTriangle, Inbox, CircleIcon, ChevronRightIcon, Monitor, Sun, Moon, Building2, Check, Plus, Languages, FlaskConical, X, Upload, Move, ZoomOut, ZoomIn, RotateCcw, RotateCw, Grid3X3, RefreshCw, XIcon, User, Pencil, Bell, CheckCheck, XCircle, CheckCircle, Info, Trash2, Clock, MapPin, Link, CalendarDays, ExternalLink, ChevronLeft, ChevronRight, Search, CheckCircle2, Link2, HelpCircle, Circle, Wifi, WifiOff, MessageSquare, FileIcon, Paperclip, Send, Store, ArrowLeft, Flag, Hash, Lightbulb, Trophy, Plane, Apple, Leaf, Hand, Smile, Play, AlertCircle, VolumeX, Pause, Volume1, Volume2, Settings, PictureInPicture2, Minimize, Maximize, CreditCard, BadgeCheck, CircleCheck, CircleDollarSign, Users, Download } from 'lucide-react';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
  import { useTheme } from 'next-themes';
7
7
  import { AnimatePresence, motion } from 'framer-motion';
@@ -6629,7 +6629,12 @@ function TimeCombobox({
6629
6629
  setDraft(formatTimeDisplay(value));
6630
6630
  }
6631
6631
  };
6632
- return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
6632
+ const handleListWheel = (e) => {
6633
+ e.currentTarget.scrollTop += e.deltaY;
6634
+ e.preventDefault();
6635
+ e.stopPropagation();
6636
+ };
6637
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, modal: true, children: [
6633
6638
  /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
6634
6639
  "button",
6635
6640
  {
@@ -6681,38 +6686,46 @@ function TimeCombobox({
6681
6686
  "aria-label": ariaLabel
6682
6687
  }
6683
6688
  ) }),
6684
- /* @__PURE__ */ jsxs("div", { ref: listRef, className: "max-h-56 overflow-y-auto py-1", children: [
6685
- filtered.map((slot) => {
6686
- const selected = slot === value;
6687
- const label = formatTimeDisplay(slot);
6688
- const hint = durationFrom != null ? formatDurationHintClean(durationFrom, slot) : null;
6689
- return /* @__PURE__ */ jsxs(
6690
- "button",
6691
- {
6692
- ref: selected ? selectedRef : void 0,
6693
- type: "button",
6694
- className: cn(
6695
- "flex w-full items-center justify-between px-3 py-1.5 text-left text-sm tabular-nums hover:bg-accent",
6696
- selected && "bg-accent font-medium"
6697
- ),
6698
- onMouseDown: (e) => {
6699
- e.preventDefault();
6700
- },
6701
- onClick: () => {
6702
- onChange(slot);
6703
- setDraft(formatTimeDisplay(slot));
6704
- setOpen(false);
6705
- },
6706
- children: [
6707
- /* @__PURE__ */ jsx("span", { children: label }),
6708
- hint && /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-muted-foreground", children: hint })
6709
- ]
6710
- },
6711
- slot
6712
- );
6713
- }),
6714
- filtered.length === 0 && /* @__PURE__ */ jsx("p", { className: "px-3 py-2 text-xs text-muted-foreground", children: "No matching times" })
6715
- ] })
6689
+ /* @__PURE__ */ jsxs(
6690
+ "div",
6691
+ {
6692
+ ref: listRef,
6693
+ className: "max-h-56 overflow-y-auto py-1",
6694
+ onWheel: handleListWheel,
6695
+ children: [
6696
+ filtered.map((slot) => {
6697
+ const selected = slot === value;
6698
+ const label = formatTimeDisplay(slot);
6699
+ const hint = durationFrom != null ? formatDurationHintClean(durationFrom, slot) : null;
6700
+ return /* @__PURE__ */ jsxs(
6701
+ "button",
6702
+ {
6703
+ ref: selected ? selectedRef : void 0,
6704
+ type: "button",
6705
+ className: cn(
6706
+ "flex w-full items-center justify-between px-3 py-1.5 text-left text-sm tabular-nums hover:bg-accent",
6707
+ selected && "bg-accent font-medium"
6708
+ ),
6709
+ onMouseDown: (e) => {
6710
+ e.preventDefault();
6711
+ },
6712
+ onClick: () => {
6713
+ onChange(slot);
6714
+ setDraft(formatTimeDisplay(slot));
6715
+ setOpen(false);
6716
+ },
6717
+ children: [
6718
+ /* @__PURE__ */ jsx("span", { children: label }),
6719
+ hint && /* @__PURE__ */ jsx("span", { className: "ml-2 text-xs text-muted-foreground", children: hint })
6720
+ ]
6721
+ },
6722
+ slot
6723
+ );
6724
+ }),
6725
+ filtered.length === 0 && /* @__PURE__ */ jsx("p", { className: "px-3 py-2 text-xs text-muted-foreground", children: "No matching times" })
6726
+ ]
6727
+ }
6728
+ )
6716
6729
  ]
6717
6730
  }
6718
6731
  )
@@ -7945,6 +7958,94 @@ function useChatRoom(roomId, config, options = {}) {
7945
7958
  isInitialLoading
7946
7959
  };
7947
7960
  }
7961
+ function AuthenticatedAttachment({
7962
+ url,
7963
+ getToken,
7964
+ fileName,
7965
+ fileSize,
7966
+ mimeType,
7967
+ formatFileSize
7968
+ }) {
7969
+ const [blobUrl, setBlobUrl] = useState(null);
7970
+ const [failed, setFailed] = useState(false);
7971
+ const isImage2 = mimeType.startsWith("image/");
7972
+ useEffect(() => {
7973
+ let cancelled = false;
7974
+ let objectUrl = null;
7975
+ void (async () => {
7976
+ try {
7977
+ const jwt = await getToken();
7978
+ if (!jwt) throw new Error("No auth token");
7979
+ const res = await fetch(url, {
7980
+ headers: { Authorization: `Bearer ${jwt}` }
7981
+ });
7982
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
7983
+ const blob = await res.blob();
7984
+ if (cancelled) return;
7985
+ objectUrl = URL.createObjectURL(blob);
7986
+ setBlobUrl(objectUrl);
7987
+ } catch {
7988
+ if (!cancelled) setFailed(true);
7989
+ }
7990
+ })();
7991
+ return () => {
7992
+ cancelled = true;
7993
+ if (objectUrl) URL.revokeObjectURL(objectUrl);
7994
+ };
7995
+ }, [url, getToken]);
7996
+ if (failed) {
7997
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-destructive/30 bg-destructive/5 px-2 py-1.5 text-xs text-destructive", children: [
7998
+ /* @__PURE__ */ jsx(FileIcon, { className: "h-3.5 w-3.5 flex-shrink-0" }),
7999
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: fileName })
8000
+ ] });
8001
+ }
8002
+ if (!blobUrl) {
8003
+ return /* @__PURE__ */ jsx(
8004
+ "div",
8005
+ {
8006
+ className: isImage2 ? "flex h-24 w-[200px] items-center justify-center rounded-lg border bg-muted/30" : "flex items-center gap-2 rounded-lg border bg-muted/30 px-2 py-1.5 text-xs",
8007
+ children: /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" })
8008
+ }
8009
+ );
8010
+ }
8011
+ if (isImage2) {
8012
+ return /* @__PURE__ */ jsx(
8013
+ "a",
8014
+ {
8015
+ href: blobUrl,
8016
+ target: "_blank",
8017
+ rel: "noopener noreferrer",
8018
+ className: "block max-w-[200px] overflow-hidden rounded-lg border",
8019
+ children: /* @__PURE__ */ jsx(
8020
+ "img",
8021
+ {
8022
+ src: blobUrl,
8023
+ alt: fileName,
8024
+ className: "h-auto w-full object-cover"
8025
+ }
8026
+ )
8027
+ }
8028
+ );
8029
+ }
8030
+ return /* @__PURE__ */ jsxs(
8031
+ "a",
8032
+ {
8033
+ href: blobUrl,
8034
+ download: fileName,
8035
+ target: "_blank",
8036
+ rel: "noopener noreferrer",
8037
+ className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-2 py-1.5 text-xs transition-colors hover:bg-muted",
8038
+ children: [
8039
+ /* @__PURE__ */ jsx(FileIcon, { className: "h-3.5 w-3.5 flex-shrink-0 text-muted-foreground" }),
8040
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
8041
+ /* @__PURE__ */ jsx("p", { className: "truncate font-medium", children: fileName }),
8042
+ /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground", children: formatFileSize(fileSize) })
8043
+ ] }),
8044
+ /* @__PURE__ */ jsx(Download, { className: "h-3.5 w-3.5 flex-shrink-0 text-muted-foreground" })
8045
+ ]
8046
+ }
8047
+ );
8048
+ }
7948
8049
  var roleColors = {
7949
8050
  client: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
7950
8051
  seller: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
@@ -8232,44 +8333,18 @@ function ChatRoomView({
8232
8333
  children: message.content
8233
8334
  }
8234
8335
  ),
8235
- message.attachments.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-1 flex flex-col gap-1", children: message.attachments.map(
8236
- (att) => att.mimeType.startsWith("image/") ? /* @__PURE__ */ jsx(
8237
- "a",
8238
- {
8239
- href: getAttachmentUrl(att.id),
8240
- target: "_blank",
8241
- rel: "noopener noreferrer",
8242
- className: "block max-w-[200px] overflow-hidden rounded-lg border",
8243
- children: /* @__PURE__ */ jsx(
8244
- "img",
8245
- {
8246
- src: getAttachmentUrl(att.id),
8247
- alt: att.fileName,
8248
- className: "h-auto w-full object-cover",
8249
- loading: "lazy"
8250
- }
8251
- )
8252
- },
8253
- att.id
8254
- ) : /* @__PURE__ */ jsxs(
8255
- "a",
8256
- {
8257
- href: getAttachmentUrl(att.id),
8258
- target: "_blank",
8259
- rel: "noopener noreferrer",
8260
- className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-2 py-1.5 text-xs transition-colors hover:bg-muted",
8261
- children: [
8262
- /* @__PURE__ */ jsx(FileIcon, { className: "h-3.5 w-3.5 flex-shrink-0 text-muted-foreground" }),
8263
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
8264
- /* @__PURE__ */ jsx("p", { className: "truncate font-medium", children: att.fileName }),
8265
- /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground", children: formatFileSize(att.fileSize) })
8266
- ] }),
8267
- /* @__PURE__ */ jsx(Download, { className: "h-3.5 w-3.5 flex-shrink-0 text-muted-foreground" })
8268
- ]
8269
- },
8270
- att.id
8271
- )
8272
- ) }),
8336
+ message.attachments.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-1 flex flex-col gap-1", children: message.attachments.map((att) => /* @__PURE__ */ jsx(
8337
+ AuthenticatedAttachment,
8338
+ {
8339
+ url: getAttachmentUrl(att.id),
8340
+ getToken: config.getToken,
8341
+ fileName: att.fileName,
8342
+ fileSize: att.fileSize,
8343
+ mimeType: att.mimeType,
8344
+ formatFileSize
8345
+ },
8346
+ att.id
8347
+ )) }),
8273
8348
  isCurrentUser && /* @__PURE__ */ jsx("div", { className: "mt-0.5 flex items-center gap-0.5 text-[10px] text-muted-foreground", children: seen ? /* @__PURE__ */ jsxs(Fragment, { children: [
8274
8349
  /* @__PURE__ */ jsx(CheckCheck, { className: "h-3 w-3 text-primary" }),
8275
8350
  /* @__PURE__ */ jsx("span", { children: labels.seen ?? "Seen" })