@ai-matrx/messaging 0.3.0 → 0.6.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/react.cjs CHANGED
@@ -61,7 +61,6 @@ __export(react_exports, {
61
61
  asMessageId: () => asMessageId,
62
62
  asOrganizationId: () => asOrganizationId,
63
63
  asUserId: () => asUserId,
64
- avatarPaletteIndex: () => avatarPaletteIndex,
65
64
  composeFence: () => composeFence,
66
65
  conversationTopic: () => conversationTopic,
67
66
  createActionRegistry: () => createActionRegistry,
@@ -79,7 +78,6 @@ __export(react_exports, {
79
78
  formatLastSeen: () => formatLastSeen,
80
79
  formatMessageTime: () => formatMessageTime,
81
80
  formatTypists: () => formatTypists,
82
- getInitials: () => getInitials,
83
81
  groupMessages: () => groupMessages,
84
82
  inboxTopic: () => inboxTopic,
85
83
  invalidResponse: () => invalidResponse,
@@ -316,21 +314,32 @@ function splitText(content) {
316
314
  if (start > cursor) {
317
315
  segments.push({ type: "text", value: content.slice(cursor, start) });
318
316
  }
319
- parseFenceBody(match[1] ?? "").forEach((reference) => {
320
- segments.push({ type: "reference", reference });
321
- });
317
+ const body = match[1] ?? "";
318
+ const references = parseFenceBody(body);
319
+ if (references.length === 0) {
320
+ segments.push({ type: "fence", body });
321
+ } else {
322
+ references.forEach((reference) => {
323
+ segments.push({ type: "reference", reference });
324
+ });
325
+ }
322
326
  cursor = start + match[0].length;
323
327
  }
324
328
  if (cursor < content.length) {
325
329
  segments.push({ type: "text", value: content.slice(cursor) });
326
330
  }
327
331
  return segments.filter(
328
- (segment) => segment.type === "reference" || segment.value.trim().length > 0
332
+ (segment) => segment.type !== "text" || segment.value.trim().length > 0
329
333
  );
330
334
  }
331
335
  function summarizeText(content, maxLength = 140) {
332
336
  const parts = splitText(content).map(
333
- (segment) => segment.type === "text" ? segment.value : segment.reference.label
337
+ (segment) => segment.type === "text" ? segment.value : segment.type === "reference" ? segment.reference.label : (
338
+ // A fence we cannot read still SAYS something. Collapsing it to
339
+ // nothing is how a reference-only message becomes an inbox row that
340
+ // reads "No messages yet" — a screen telling a lie.
341
+ "Reference"
342
+ )
334
343
  );
335
344
  const flattened = parts.join(" ").replace(/\s+/g, " ").trim();
336
345
  if (flattened.length <= maxLength) return flattened;
@@ -1886,6 +1895,7 @@ function MessagingRuntime(props) {
1886
1895
  return map;
1887
1896
  }, [renderers]);
1888
1897
  const renderReference = props.renderReference ?? null;
1898
+ const renderFence = props.renderFence ?? null;
1889
1899
  const wrapMessage = props.wrapMessage ?? null;
1890
1900
  const wrapConversationRow = props.wrapConversationRow ?? null;
1891
1901
  const host = (0, import_react.useMemo)(() => {
@@ -1898,10 +1908,20 @@ function MessagingRuntime(props) {
1898
1908
  openReference: referenceRef.current ?? null,
1899
1909
  actionRenderers: rendererMap,
1900
1910
  renderReference,
1911
+ renderFence,
1901
1912
  wrapMessage,
1902
1913
  wrapConversationRow
1903
1914
  };
1904
- }, [engine, actionRegistry, ai, rendererMap, renderReference, wrapMessage, wrapConversationRow]);
1915
+ }, [
1916
+ engine,
1917
+ actionRegistry,
1918
+ ai,
1919
+ rendererMap,
1920
+ renderReference,
1921
+ renderFence,
1922
+ wrapMessage,
1923
+ wrapConversationRow
1924
+ ]);
1905
1925
  const MessagingContext = messagingContext();
1906
1926
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MessagingContext.Provider, { value: host, children });
1907
1927
  }
@@ -1977,20 +1997,6 @@ function formatDateSeparator(isoString, now = Date.now(), locale) {
1977
1997
  day: "numeric"
1978
1998
  });
1979
1999
  }
1980
- function getInitials(name) {
1981
- const parts = name.trim().split(/\s+/).filter(Boolean);
1982
- if (parts.length === 0) return "?";
1983
- const first = parts[0]?.[0] ?? "";
1984
- const last = parts.length > 1 ? parts.at(-1)?.[0] ?? "" : "";
1985
- return `${first}${last}`.toUpperCase() || "?";
1986
- }
1987
- function avatarPaletteIndex(seed, buckets = 8) {
1988
- let hash = 0;
1989
- for (let index = 0; index < seed.length; index += 1) {
1990
- hash = hash * 31 + seed.charCodeAt(index) | 0;
1991
- }
1992
- return Math.abs(hash) % buckets;
1993
- }
1994
2000
  function groupMessages(messages, args = {}) {
1995
2001
  const windowMs = args.windowMs ?? 5 * MINUTE;
1996
2002
  const now = args.now ?? Date.now();
@@ -2359,6 +2365,9 @@ function resolveActor(message, sender) {
2359
2365
  };
2360
2366
  }
2361
2367
 
2368
+ // src/react/parts.tsx
2369
+ var import_format2 = require("@ai-matrx/kit/format");
2370
+
2362
2371
  // src/react/icons.tsx
2363
2372
  var import_jsx_runtime2 = require("react/jsx-runtime");
2364
2373
  function Icon(props) {
@@ -2454,7 +2463,7 @@ var UsersIcon = (props) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2454
2463
  var import_jsx_runtime3 = require("react/jsx-runtime");
2455
2464
  function Avatar(props) {
2456
2465
  const seed = props.seed ?? props.name;
2457
- const paletteIndex = avatarPaletteIndex(seed);
2466
+ const paletteIndex = (0, import_format2.avatarPaletteIndex)(seed);
2458
2467
  const className = `mx-msg__avatar${props.small === true ? " mx-msg__avatar--sm" : ""}`;
2459
2468
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2460
2469
  "span",
@@ -2463,7 +2472,7 @@ function Avatar(props) {
2463
2472
  style: { background: `var(--mx-msg-avatar-${paletteIndex})` },
2464
2473
  "aria-hidden": "true",
2465
2474
  children: [
2466
- props.imageUrl != null && props.imageUrl.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("img", { className: "mx-msg__avatar-img", src: props.imageUrl, alt: "", loading: "lazy" }) : getInitials(props.name),
2475
+ props.imageUrl != null && props.imageUrl.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("img", { className: "mx-msg__avatar-img", src: props.imageUrl, alt: "", loading: "lazy" }) : (0, import_format2.getInitials)(props.name),
2467
2476
  props.online === true ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", { className: "mx-msg__presence" }) : null
2468
2477
  ]
2469
2478
  }
@@ -2492,6 +2501,20 @@ function DeliveryTick(props) {
2492
2501
  return null;
2493
2502
  }
2494
2503
  }
2504
+ function UnreadableReference() {
2505
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2506
+ "span",
2507
+ {
2508
+ className: "mx-msg__reference mx-msg__reference--inert",
2509
+ title: "This message names something in a reference format this app has not wired. Pass renderFence to <MessagingProvider> to render it.",
2510
+ children: [
2511
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LinkIcon, {}),
2512
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-msg__reference-type", children: "reference" }),
2513
+ "Reference"
2514
+ ]
2515
+ }
2516
+ );
2517
+ }
2495
2518
  function ReferenceCard(props) {
2496
2519
  const { reference, onOpen } = props;
2497
2520
  const href = reference.href;
@@ -2856,6 +2879,7 @@ function MessageBubble(props) {
2856
2879
  const { message, isMine } = props;
2857
2880
  const host = useMessagingHost();
2858
2881
  const HostReference = host?.renderReference ?? null;
2882
+ const HostFence = host?.renderFence ?? null;
2859
2883
  const MessageChrome = host?.wrapMessage ?? null;
2860
2884
  if (message.deletedAt !== null) {
2861
2885
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-msg__bubble mx-msg__bubble--deleted", children: "Message deleted" });
@@ -2870,7 +2894,7 @@ function MessageBubble(props) {
2870
2894
  const bubble = /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
2871
2895
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: classes, children: [
2872
2896
  splitText(message.content).map(
2873
- (segment, index) => segment.type === "text" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: segment.value }, index) : HostReference !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2897
+ (segment, index) => segment.type === "text" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: segment.value }, index) : segment.type === "fence" ? HostFence !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HostFence, { body: segment.body }, `fence:${index}`) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(UnreadableReference, {}, `fence:${index}`) : HostReference !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2874
2898
  HostReference,
2875
2899
  {
2876
2900
  reference: segment.reference