@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.cjs CHANGED
@@ -6662,7 +6662,12 @@ function TimeCombobox({
6662
6662
  setDraft(formatTimeDisplay(value));
6663
6663
  }
6664
6664
  };
6665
- return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, children: [
6665
+ const handleListWheel = (e) => {
6666
+ e.currentTarget.scrollTop += e.deltaY;
6667
+ e.preventDefault();
6668
+ e.stopPropagation();
6669
+ };
6670
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: setOpen, modal: true, children: [
6666
6671
  /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
6667
6672
  "button",
6668
6673
  {
@@ -6714,38 +6719,46 @@ function TimeCombobox({
6714
6719
  "aria-label": ariaLabel
6715
6720
  }
6716
6721
  ) }),
6717
- /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: listRef, className: "max-h-56 overflow-y-auto py-1", children: [
6718
- filtered.map((slot) => {
6719
- const selected = slot === value;
6720
- const label = formatTimeDisplay(slot);
6721
- const hint = durationFrom != null ? formatDurationHintClean(durationFrom, slot) : null;
6722
- return /* @__PURE__ */ jsxRuntime.jsxs(
6723
- "button",
6724
- {
6725
- ref: selected ? selectedRef : void 0,
6726
- type: "button",
6727
- className: cn(
6728
- "flex w-full items-center justify-between px-3 py-1.5 text-left text-sm tabular-nums hover:bg-accent",
6729
- selected && "bg-accent font-medium"
6730
- ),
6731
- onMouseDown: (e) => {
6732
- e.preventDefault();
6733
- },
6734
- onClick: () => {
6735
- onChange(slot);
6736
- setDraft(formatTimeDisplay(slot));
6737
- setOpen(false);
6738
- },
6739
- children: [
6740
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
6741
- hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-xs text-muted-foreground", children: hint })
6742
- ]
6743
- },
6744
- slot
6745
- );
6746
- }),
6747
- filtered.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 py-2 text-xs text-muted-foreground", children: "No matching times" })
6748
- ] })
6722
+ /* @__PURE__ */ jsxRuntime.jsxs(
6723
+ "div",
6724
+ {
6725
+ ref: listRef,
6726
+ className: "max-h-56 overflow-y-auto py-1",
6727
+ onWheel: handleListWheel,
6728
+ children: [
6729
+ filtered.map((slot) => {
6730
+ const selected = slot === value;
6731
+ const label = formatTimeDisplay(slot);
6732
+ const hint = durationFrom != null ? formatDurationHintClean(durationFrom, slot) : null;
6733
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6734
+ "button",
6735
+ {
6736
+ ref: selected ? selectedRef : void 0,
6737
+ type: "button",
6738
+ className: cn(
6739
+ "flex w-full items-center justify-between px-3 py-1.5 text-left text-sm tabular-nums hover:bg-accent",
6740
+ selected && "bg-accent font-medium"
6741
+ ),
6742
+ onMouseDown: (e) => {
6743
+ e.preventDefault();
6744
+ },
6745
+ onClick: () => {
6746
+ onChange(slot);
6747
+ setDraft(formatTimeDisplay(slot));
6748
+ setOpen(false);
6749
+ },
6750
+ children: [
6751
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
6752
+ hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-xs text-muted-foreground", children: hint })
6753
+ ]
6754
+ },
6755
+ slot
6756
+ );
6757
+ }),
6758
+ filtered.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-3 py-2 text-xs text-muted-foreground", children: "No matching times" })
6759
+ ]
6760
+ }
6761
+ )
6749
6762
  ]
6750
6763
  }
6751
6764
  )
@@ -7978,6 +7991,94 @@ function useChatRoom(roomId, config, options = {}) {
7978
7991
  isInitialLoading
7979
7992
  };
7980
7993
  }
7994
+ function AuthenticatedAttachment({
7995
+ url,
7996
+ getToken,
7997
+ fileName,
7998
+ fileSize,
7999
+ mimeType,
8000
+ formatFileSize
8001
+ }) {
8002
+ const [blobUrl, setBlobUrl] = React7.useState(null);
8003
+ const [failed, setFailed] = React7.useState(false);
8004
+ const isImage2 = mimeType.startsWith("image/");
8005
+ React7.useEffect(() => {
8006
+ let cancelled = false;
8007
+ let objectUrl = null;
8008
+ void (async () => {
8009
+ try {
8010
+ const jwt = await getToken();
8011
+ if (!jwt) throw new Error("No auth token");
8012
+ const res = await fetch(url, {
8013
+ headers: { Authorization: `Bearer ${jwt}` }
8014
+ });
8015
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
8016
+ const blob = await res.blob();
8017
+ if (cancelled) return;
8018
+ objectUrl = URL.createObjectURL(blob);
8019
+ setBlobUrl(objectUrl);
8020
+ } catch {
8021
+ if (!cancelled) setFailed(true);
8022
+ }
8023
+ })();
8024
+ return () => {
8025
+ cancelled = true;
8026
+ if (objectUrl) URL.revokeObjectURL(objectUrl);
8027
+ };
8028
+ }, [url, getToken]);
8029
+ if (failed) {
8030
+ return /* @__PURE__ */ jsxRuntime.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: [
8031
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileIcon, { className: "h-3.5 w-3.5 flex-shrink-0" }),
8032
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: fileName })
8033
+ ] });
8034
+ }
8035
+ if (!blobUrl) {
8036
+ return /* @__PURE__ */ jsxRuntime.jsx(
8037
+ "div",
8038
+ {
8039
+ 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",
8040
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin text-muted-foreground" })
8041
+ }
8042
+ );
8043
+ }
8044
+ if (isImage2) {
8045
+ return /* @__PURE__ */ jsxRuntime.jsx(
8046
+ "a",
8047
+ {
8048
+ href: blobUrl,
8049
+ target: "_blank",
8050
+ rel: "noopener noreferrer",
8051
+ className: "block max-w-[200px] overflow-hidden rounded-lg border",
8052
+ children: /* @__PURE__ */ jsxRuntime.jsx(
8053
+ "img",
8054
+ {
8055
+ src: blobUrl,
8056
+ alt: fileName,
8057
+ className: "h-auto w-full object-cover"
8058
+ }
8059
+ )
8060
+ }
8061
+ );
8062
+ }
8063
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8064
+ "a",
8065
+ {
8066
+ href: blobUrl,
8067
+ download: fileName,
8068
+ target: "_blank",
8069
+ rel: "noopener noreferrer",
8070
+ className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-2 py-1.5 text-xs transition-colors hover:bg-muted",
8071
+ children: [
8072
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileIcon, { className: "h-3.5 w-3.5 flex-shrink-0 text-muted-foreground" }),
8073
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
8074
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate font-medium", children: fileName }),
8075
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-muted-foreground", children: formatFileSize(fileSize) })
8076
+ ] }),
8077
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { className: "h-3.5 w-3.5 flex-shrink-0 text-muted-foreground" })
8078
+ ]
8079
+ }
8080
+ );
8081
+ }
7981
8082
  var roleColors = {
7982
8083
  client: "bg-blue-500/10 text-blue-600 dark:text-blue-400",
7983
8084
  seller: "bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
@@ -8265,44 +8366,18 @@ function ChatRoomView({
8265
8366
  children: message.content
8266
8367
  }
8267
8368
  ),
8268
- message.attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 flex flex-col gap-1", children: message.attachments.map(
8269
- (att) => att.mimeType.startsWith("image/") ? /* @__PURE__ */ jsxRuntime.jsx(
8270
- "a",
8271
- {
8272
- href: getAttachmentUrl(att.id),
8273
- target: "_blank",
8274
- rel: "noopener noreferrer",
8275
- className: "block max-w-[200px] overflow-hidden rounded-lg border",
8276
- children: /* @__PURE__ */ jsxRuntime.jsx(
8277
- "img",
8278
- {
8279
- src: getAttachmentUrl(att.id),
8280
- alt: att.fileName,
8281
- className: "h-auto w-full object-cover",
8282
- loading: "lazy"
8283
- }
8284
- )
8285
- },
8286
- att.id
8287
- ) : /* @__PURE__ */ jsxRuntime.jsxs(
8288
- "a",
8289
- {
8290
- href: getAttachmentUrl(att.id),
8291
- target: "_blank",
8292
- rel: "noopener noreferrer",
8293
- className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-2 py-1.5 text-xs transition-colors hover:bg-muted",
8294
- children: [
8295
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileIcon, { className: "h-3.5 w-3.5 flex-shrink-0 text-muted-foreground" }),
8296
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1", children: [
8297
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate font-medium", children: att.fileName }),
8298
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-muted-foreground", children: formatFileSize(att.fileSize) })
8299
- ] }),
8300
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { className: "h-3.5 w-3.5 flex-shrink-0 text-muted-foreground" })
8301
- ]
8302
- },
8303
- att.id
8304
- )
8305
- ) }),
8369
+ message.attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 flex flex-col gap-1", children: message.attachments.map((att) => /* @__PURE__ */ jsxRuntime.jsx(
8370
+ AuthenticatedAttachment,
8371
+ {
8372
+ url: getAttachmentUrl(att.id),
8373
+ getToken: config.getToken,
8374
+ fileName: att.fileName,
8375
+ fileSize: att.fileSize,
8376
+ mimeType: att.mimeType,
8377
+ formatFileSize
8378
+ },
8379
+ att.id
8380
+ )) }),
8306
8381
  isCurrentUser && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-0.5 flex items-center gap-0.5 text-[10px] text-muted-foreground", children: seen ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8307
8382
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCheck, { className: "h-3 w-3 text-primary" }),
8308
8383
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: labels.seen ?? "Seen" })