@forgedevstack/bear 1.2.4 → 1.2.5

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.
Files changed (40) hide show
  1. package/dist/components/Card/Card.types.d.ts +1 -2
  2. package/dist/components/Chat/Chat.const.cjs +1 -1
  3. package/dist/components/Chat/Chat.const.d.ts +1 -1
  4. package/dist/components/Chat/Chat.const.js +1 -1
  5. package/dist/components/ColorSwatch/ColorSwatch.cjs +1 -1
  6. package/dist/components/ColorSwatch/ColorSwatch.js +8 -8
  7. package/dist/components/CommandPalette/CommandPalette.cjs +1 -1
  8. package/dist/components/CommandPalette/CommandPalette.js +71 -71
  9. package/dist/components/DiffSquares/DiffSquares.cjs +1 -1
  10. package/dist/components/DiffSquares/DiffSquares.js +11 -11
  11. package/dist/components/MentionsInput/MentionsInput.cjs +1 -1
  12. package/dist/components/MentionsInput/MentionsInput.js +114 -92
  13. package/dist/components/MentionsInput/MentionsInput.types.d.ts +4 -0
  14. package/dist/components/MessageList/MessageList.cjs +1 -0
  15. package/dist/components/MessageList/MessageList.const.cjs +1 -0
  16. package/dist/components/MessageList/MessageList.const.d.ts +23 -0
  17. package/dist/components/MessageList/MessageList.const.js +30 -0
  18. package/dist/components/MessageList/MessageList.d.ts +19 -0
  19. package/dist/components/MessageList/MessageList.js +182 -0
  20. package/dist/components/MessageList/MessageList.types.d.ts +72 -0
  21. package/dist/components/MessageList/MessageList.utils.cjs +1 -0
  22. package/dist/components/MessageList/MessageList.utils.d.ts +6 -0
  23. package/dist/components/MessageList/MessageList.utils.js +35 -0
  24. package/dist/components/MessageList/index.d.ts +2 -0
  25. package/dist/components/Toast/Toast.cjs +1 -1
  26. package/dist/components/Toast/Toast.d.ts +3 -6
  27. package/dist/components/Toast/Toast.js +82 -76
  28. package/dist/components/Toast/Toast.types.d.ts +9 -0
  29. package/dist/components/Toast/index.d.ts +1 -1
  30. package/dist/components/TreeSelect/TreeSelect.cjs +1 -1
  31. package/dist/components/TreeSelect/TreeSelect.js +22 -22
  32. package/dist/components/index.cjs +1 -1
  33. package/dist/components/index.d.ts +3 -1
  34. package/dist/components/index.js +144 -142
  35. package/dist/index.cjs +1 -1
  36. package/dist/index.js +228 -226
  37. package/dist/styles/_message-list.css +42 -0
  38. package/dist/styles/main.css +1 -0
  39. package/dist/styles.css +47 -0
  40. package/package.json +15 -2
@@ -1,149 +1,171 @@
1
- import { jsxs as T, jsx as l } from "react/jsx-runtime";
2
- import { useState as c, useRef as p, useCallback as J, useEffect as d } from "react";
3
- import { cn as z } from "../../utils/cn.js";
4
- import { Portal as X } from "../Portal/Portal.js";
5
- import { defaultFilter as Y } from "./MentionsInput.utils.js";
6
- const C = 1e4, ee = {
1
+ import { jsxs as K, jsx as s } from "react/jsx-runtime";
2
+ import { useState as b, useRef as w, useCallback as X, useEffect as d } from "react";
3
+ import { cn as g } from "../../utils/cn.js";
4
+ import { Portal as Y } from "../Portal/Portal.js";
5
+ import { defaultFilter as ee } from "./MentionsInput.utils.js";
6
+ const re = 1e4, te = 3, ae = {
7
7
  sm: "bear-h-8 bear-text-sm bear-px-3",
8
8
  md: "bear-h-10 bear-text-base bear-px-4",
9
9
  lg: "bear-h-12 bear-text-lg bear-px-5"
10
- }, oe = ({
11
- value: w,
12
- defaultValue: A = "",
13
- onChange: s,
14
- onMentionSelect: x,
10
+ }, ne = {
11
+ sm: "bear-text-sm bear-px-3 bear-py-2",
12
+ md: "bear-text-base bear-px-4 bear-py-2",
13
+ lg: "bear-text-lg bear-px-5 bear-py-3"
14
+ }, ce = ({
15
+ value: y,
16
+ defaultValue: U = "",
17
+ onChange: o,
18
+ onMentionSelect: v,
15
19
  options: $,
16
- trigger: o = "@",
17
- placeholder: j = "Type @ to mention...",
18
- disabled: I = !1,
19
- maxSuggestions: B = 5,
20
- filterOptions: K = Y,
21
- size: Q = "md",
22
- fullWidth: S = !1,
23
- className: _
20
+ trigger: i = "@",
21
+ placeholder: L = "Type @ to mention...",
22
+ disabled: f = !1,
23
+ maxSuggestions: j = 5,
24
+ filterOptions: B = ee,
25
+ size: N = "md",
26
+ fullWidth: F = !1,
27
+ className: Q,
28
+ multiline: W = !1,
29
+ rows: H = te
24
30
  }) => {
25
- const [F, N] = c(A), [f, H] = c(""), [U, h] = c(!1), [u, m] = c(0), [g, V] = c(null), L = p(null), v = p(null), y = p(null), q = p(null), [k, W] = c({ top: 0, left: 0, width: 0 }), a = w ?? F, b = K($, f).slice(0, B), M = U && f.length >= 0, E = M && b.length > 0, O = J(() => {
26
- const e = a.lastIndexOf(o);
31
+ const [V, D] = b(U), [h, Z] = b(""), [C, p] = b(!1), [c, x] = b(0), [k, G] = b(null), M = w(null), m = w(null), z = w(null), O = w(null), [E, J] = b({ top: 0, left: 0, width: 0 }), a = y ?? V, u = B($, h).slice(0, j), R = C && h.length >= 0, I = R && u.length > 0, q = X(() => {
32
+ const e = a.lastIndexOf(i);
27
33
  if (e === -1) return { query: "", start: null };
28
- const t = a.slice(e + o.length), r = t.indexOf(" ");
29
- return { query: r === -1 ? t : t.slice(0, r), start: e };
30
- }, [a, o]);
34
+ const r = a.slice(e + i.length), t = r.indexOf(" ");
35
+ return { query: t === -1 ? r : r.slice(0, t), start: e };
36
+ }, [a, i]);
31
37
  d(() => {
32
- const { query: e, start: t } = O();
33
- H(e), V(t), h(t !== null && !e.includes(" "));
34
- }, [a, O]), d(() => {
35
- m(0);
36
- }, [f]), d(() => {
37
- if (u >= 0 && y.current) {
38
- const e = y.current.children[u];
38
+ const { query: e, start: r } = q();
39
+ Z(e), G(r), p(r !== null && !e.includes(" "));
40
+ }, [a, q]), d(() => {
41
+ x(0);
42
+ }, [h]), d(() => {
43
+ if (c >= 0 && z.current) {
44
+ const e = z.current.children[c];
39
45
  e == null || e.scrollIntoView({ block: "nearest" });
40
46
  }
41
- }, [u]), d(() => {
42
- if (!E) return;
47
+ }, [c]), d(() => {
48
+ if (!I) return;
43
49
  const e = () => {
44
- var r;
45
- const t = (r = v.current) == null ? void 0 : r.getBoundingClientRect();
46
- t && W({
47
- top: t.bottom + 4,
48
- left: Math.max(8, Math.min(t.left, window.innerWidth - t.width - 8)),
49
- width: t.width
50
+ var t;
51
+ const r = (t = m.current) == null ? void 0 : t.getBoundingClientRect();
52
+ r && J({
53
+ top: r.bottom + 4,
54
+ left: Math.max(8, Math.min(r.left, window.innerWidth - r.width - 8)),
55
+ width: r.width
50
56
  });
51
57
  };
52
58
  return e(), window.addEventListener("resize", e), window.addEventListener("scroll", e, !0), () => {
53
59
  window.removeEventListener("resize", e), window.removeEventListener("scroll", e, !0);
54
60
  };
55
- }, [E]), d(() => {
56
- const e = (t) => {
57
- var n, i;
58
- const r = t.target;
59
- (n = L.current) != null && n.contains(r) || (i = q.current) != null && i.contains(r) || h(!1);
61
+ }, [I]), d(() => {
62
+ const e = (r) => {
63
+ var n, l;
64
+ const t = r.target;
65
+ (n = M.current) != null && n.contains(t) || (l = O.current) != null && l.contains(t) || p(!1);
60
66
  };
61
67
  return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
62
68
  }, []);
63
- const R = (e) => {
64
- const t = new RegExp(`${o}(\\w+)`, "g"), r = [];
69
+ const P = (e) => {
70
+ const r = new RegExp(`${i}(\\w+)`, "g"), t = [];
65
71
  let n;
66
- for (; (n = t.exec(e)) !== null; )
67
- r.push(n[1]);
68
- return [...new Set(r)];
69
- }, Z = (e) => {
70
- const t = e.target.value;
71
- w === void 0 && N(t), s == null || s(t, R(t));
72
- }, D = (e) => {
73
- var P;
74
- if (g == null) return;
75
- const t = a.slice(0, g), r = a.slice(g + o.length + f.length), n = `${o}${e.value}`, i = t + n + " " + r;
76
- w === void 0 && N(i), s == null || s(i, R(i)), x == null || x(e), h(!1), (P = v.current) == null || P.focus();
77
- }, G = (e) => {
78
- if (!(!M || b.length === 0)) {
72
+ for (; (n = r.exec(e)) !== null; )
73
+ t.push(n[1]);
74
+ return [...new Set(t)];
75
+ }, T = (e) => {
76
+ const r = e.target.value;
77
+ y === void 0 && D(r), o == null || o(r, P(r));
78
+ }, A = (e) => {
79
+ var _;
80
+ if (k == null) return;
81
+ const r = a.slice(0, k), t = a.slice(k + i.length + h.length), n = `${i}${e.value}`, l = r + n + " " + t;
82
+ y === void 0 && D(l), o == null || o(l, P(l)), v == null || v(e), p(!1), (_ = m.current) == null || _.focus();
83
+ }, S = (e) => {
84
+ if (!(!R || u.length === 0)) {
79
85
  if (e.key === "ArrowDown") {
80
- e.preventDefault(), m((t) => Math.min(t + 1, b.length - 1));
86
+ e.preventDefault(), x((r) => Math.min(r + 1, u.length - 1));
81
87
  return;
82
88
  }
83
89
  if (e.key === "ArrowUp") {
84
- e.preventDefault(), m((t) => Math.max(t - 1, 0));
90
+ e.preventDefault(), x((r) => Math.max(r - 1, 0));
85
91
  return;
86
92
  }
87
93
  if (e.key === "Enter" || e.key === "Tab") {
88
94
  e.preventDefault();
89
- const t = b[u];
90
- t && D(t);
95
+ const r = u[c];
96
+ r && A(r);
91
97
  return;
92
98
  }
93
- e.key === "Escape" && h(!1);
99
+ e.key === "Escape" && p(!1);
94
100
  }
95
101
  };
96
- return /* @__PURE__ */ T(
102
+ return /* @__PURE__ */ K(
97
103
  "div",
98
104
  {
99
- ref: L,
100
- className: z(
105
+ ref: M,
106
+ className: g(
101
107
  "Bear-MentionsInput bear-relative",
102
- S && "bear-w-full",
103
- _
108
+ F && "bear-w-full",
109
+ Q
104
110
  ),
105
111
  children: [
106
- /* @__PURE__ */ l(
112
+ W ? /* @__PURE__ */ s(
113
+ "textarea",
114
+ {
115
+ ref: m,
116
+ value: a,
117
+ rows: H,
118
+ onChange: T,
119
+ onKeyDown: S,
120
+ placeholder: L,
121
+ disabled: f,
122
+ className: g(
123
+ "bear-w-full bear-rounded-lg bear-border bear-border-gray-300 dark:bear-border-zinc-600 bear-bg-white dark:bear-bg-zinc-900 bear-text-gray-900 dark:bear-text-white placeholder:bear-text-gray-500 dark:placeholder:bear-text-zinc-500 bear-outline-none bear-transition-colors focus:bear-border-bear-500 focus:bear-ring-2 focus:bear-ring-bear-500/20 bear-resize-none",
124
+ f && "bear-opacity-50 bear-cursor-not-allowed",
125
+ ne[N]
126
+ )
127
+ }
128
+ ) : /* @__PURE__ */ s(
107
129
  "input",
108
130
  {
109
- ref: v,
131
+ ref: m,
110
132
  type: "text",
111
133
  value: a,
112
- onChange: Z,
113
- onKeyDown: G,
114
- placeholder: j,
115
- disabled: I,
116
- className: z(
134
+ onChange: T,
135
+ onKeyDown: S,
136
+ placeholder: L,
137
+ disabled: f,
138
+ className: g(
117
139
  "bear-w-full bear-rounded-lg bear-border bear-border-gray-300 dark:bear-border-zinc-600 bear-bg-white dark:bear-bg-zinc-900 bear-text-gray-900 dark:bear-text-white placeholder:bear-text-gray-500 dark:placeholder:bear-text-zinc-500 bear-outline-none bear-transition-colors focus:bear-border-bear-500 focus:bear-ring-2 focus:bear-ring-bear-500/20",
118
- I && "bear-opacity-50 bear-cursor-not-allowed",
119
- ee[Q]
140
+ f && "bear-opacity-50 bear-cursor-not-allowed",
141
+ ae[N]
120
142
  )
121
143
  }
122
144
  ),
123
- E && /* @__PURE__ */ l(X, { children: /* @__PURE__ */ l(
145
+ I && /* @__PURE__ */ s(Y, { children: /* @__PURE__ */ s(
124
146
  "div",
125
147
  {
126
- ref: q,
148
+ ref: O,
127
149
  className: "bear-fixed bear-rounded-lg bear-border bear-border-gray-200 dark:bear-border-zinc-600 bear-bg-white dark:bear-bg-zinc-800 bear-shadow-lg",
128
150
  style: {
129
- top: k.top,
130
- left: k.left,
131
- width: k.width,
132
- zIndex: C
151
+ top: E.top,
152
+ left: E.left,
153
+ width: E.width,
154
+ zIndex: re
133
155
  },
134
- children: /* @__PURE__ */ l("div", { ref: y, className: "bear-max-h-48 bear-overflow-auto bear-py-1", children: b.map((e, t) => /* @__PURE__ */ T(
156
+ children: /* @__PURE__ */ s("div", { ref: z, className: "bear-max-h-48 bear-overflow-auto bear-py-1", children: u.map((e, r) => /* @__PURE__ */ K(
135
157
  "button",
136
158
  {
137
159
  type: "button",
138
- className: z(
160
+ className: g(
139
161
  "bear-w-full bear-flex bear-items-center bear-gap-2 bear-px-3 bear-py-2 bear-text-left bear-text-gray-800 dark:bear-text-zinc-200 hover:bear-bg-gray-100 dark:hover:bear-bg-zinc-700 bear-transition-colors",
140
- t === u && "bear-bg-gray-100 dark:bear-bg-zinc-700"
162
+ r === c && "bear-bg-gray-100 dark:bear-bg-zinc-700"
141
163
  ),
142
- onMouseEnter: () => m(t),
143
- onClick: () => D(e),
164
+ onMouseEnter: () => x(r),
165
+ onClick: () => A(e),
144
166
  children: [
145
- e.avatar && /* @__PURE__ */ l("span", { className: "bear-shrink-0", children: e.avatar }),
146
- /* @__PURE__ */ l("span", { children: e.label })
167
+ e.avatar && /* @__PURE__ */ s("span", { className: "bear-shrink-0", children: e.avatar }),
168
+ /* @__PURE__ */ s("span", { children: e.label })
147
169
  ]
148
170
  },
149
171
  e.value
@@ -155,5 +177,5 @@ const C = 1e4, ee = {
155
177
  );
156
178
  };
157
179
  export {
158
- oe as MentionsInput
180
+ ce as MentionsInput
159
181
  };
@@ -20,4 +20,8 @@ export interface MentionsInputProps {
20
20
  size?: 'sm' | 'md' | 'lg';
21
21
  fullWidth?: boolean;
22
22
  className?: string;
23
+ /** Render a textarea instead of a single-line input */
24
+ multiline?: boolean;
25
+ /** Visible rows when multiline */
26
+ rows?: number;
23
27
  }
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("react/jsx-runtime"),E=require("react"),g=require("../Avatar/Avatar.cjs"),a=require("../Typography/Typography.cjs"),S=require("./MessageList.const.cjs"),d=require("./MessageList.utils.cjs"),s=require("../../utils/cn.cjs"),w=require("../../utils/generateBearId.utils.cjs"),Y=require("../../utils/useBearId.cjs"),W=({id:m,testId:p,messages:n,currentUserId:y,groupWindowMs:N=S.MESSAGE_LIST_GROUP_WINDOW_MS,showDaySeparators:x=!0,showAvatars:B=!0,showTimestamps:M=!0,autoScroll:u=!0,height:r=S.MESSAGE_LIST_DEFAULT_HEIGHT,renderMessage:A,emptyState:j,formatDayLabel:l,formatTimestamp:L,translations:v,onNewMessagesClick:i,className:b})=>{const $=Y.useBearId("MessageList"),f=w.resolveBearId(m,$),o=E.useRef(null),G=E.useRef(!0),T=E.useRef(null),[P,O]=E.useState(!1),I={...S.MESSAGE_LIST_DEFAULT_TRANSLATIONS,...v},R=d.buildMessageListItems(n,y,N,x),U=e=>(l==null?void 0:l(e))??d.getDefaultDayLabel(e,I),h=e=>(L==null?void 0:L(e))??d.getDefaultTimestamp(e),C=e=>{const t=o.current;t&&t.scrollTo({top:t.scrollHeight,behavior:e?"smooth":"auto"})},q=()=>{const e=o.current;if(!e)return;const c=e.scrollHeight-e.scrollTop-e.clientHeight<=S.MESSAGE_LIST_BOTTOM_THRESHOLD_PX;G.current=c,c&&O(!1)};E.useEffect(()=>{const e=n.length>0?n[n.length-1].id:null,t=T.current===null,c=e!==null&&e!==T.current;if(T.current=e,!!c){if(t||u&&G.current){C(!t);return}O(!0)}},[n,u]);const D=()=>{C(!0),O(!1),i==null||i()},H=e=>_.jsxs("div",{className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__group`,S.MESSAGE_LIST_GROUP_CLASSES,e.isOwn&&S.MESSAGE_LIST_GROUP_OWN_CLASSES),children:[B&&!e.isOwn&&_.jsx(g.Avatar,{src:e.author.avatar,initials:e.author.name[0],size:"sm",className:"bear-flex-shrink-0"}),_.jsxs("div",{className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__group-body`,S.MESSAGE_LIST_GROUP_BODY_CLASSES,e.isOwn&&S.MESSAGE_LIST_GROUP_BODY_OWN_CLASSES),children:[!e.isOwn&&_.jsxs("div",{className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__meta`,S.MESSAGE_LIST_META_CLASSES),children:[_.jsx(a.Typography,{variant:"caption",component:"span",className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__author`,S.MESSAGE_LIST_AUTHOR_CLASSES),children:e.author.name}),M&&_.jsx(a.Typography,{variant:"caption",component:"span",className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__timestamp`,S.MESSAGE_LIST_TIMESTAMP_CLASSES),children:h(e.messages[0].timestamp)})]}),e.messages.map(t=>_.jsx("div",{className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__bubble`,S.MESSAGE_LIST_BUBBLE_CLASSES,e.isOwn&&`${S.MESSAGE_LIST_ROOT_CLASS}__bubble--own`,e.isOwn&&S.MESSAGE_LIST_BUBBLE_OWN_CLASSES),children:(A==null?void 0:A(t))??t.content},t.id)),e.isOwn&&M&&_.jsx(a.Typography,{variant:"caption",component:"span",className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__timestamp`,S.MESSAGE_LIST_TIMESTAMP_CLASSES),children:h(e.messages[e.messages.length-1].timestamp)})]})]},e.key);return _.jsxs("div",{id:f,"data-testid":p,className:s.cn(S.MESSAGE_LIST_ROOT_CLASS,S.MESSAGE_LIST_BASE_CLASSES,b),style:{height:typeof r=="number"?`${r}px`:r},children:[_.jsxs("div",{ref:o,onScroll:q,className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__scroller`,S.MESSAGE_LIST_SCROLLER_CLASSES),role:"log","aria-live":"polite",children:[R.length===0&&_.jsx("div",{className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__empty`,S.MESSAGE_LIST_EMPTY_CLASSES),children:j??_.jsx(a.Typography,{variant:"body2",component:"span",children:I.emptyLabel})}),R.map(e=>e.kind==="day"?_.jsxs("div",{className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__day-separator`,S.MESSAGE_LIST_DAY_SEPARATOR_CLASSES),children:[_.jsx("span",{className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__day-line`,S.MESSAGE_LIST_DAY_LINE_CLASSES)}),_.jsx("span",{className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__day-label`,S.MESSAGE_LIST_DAY_LABEL_CLASSES),children:U(e.date)}),_.jsx("span",{className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__day-line`,S.MESSAGE_LIST_DAY_LINE_CLASSES)})]},e.key):H(e))]}),P&&_.jsx("button",{type:"button",onClick:D,className:s.cn(`${S.MESSAGE_LIST_ROOT_CLASS}__new-messages`,S.MESSAGE_LIST_NEW_MESSAGES_CLASSES),children:I.newMessages})]})};exports.MessageList=W;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S="Bear-MessageList",E=400,_=300*1e3,e=40,A=1440*60*1e3,L={newMessages:"New messages",today:"Today",yesterday:"Yesterday",emptyLabel:"No messages yet"},r="bear-relative bear-flex bear-flex-col bear-rounded-xl bear-border bear-overflow-hidden",a="bear-flex-1 bear-overflow-y-auto bear-p-4 bear-flex bear-flex-col bear-gap-3",T="bear-flex bear-items-center bear-gap-3 bear-my-1",b="bear-flex-1 bear-h-px",t="bear-text-xs bear-font-medium bear-whitespace-nowrap",M="bear-flex bear-gap-2",s="bear-flex-row-reverse",G="bear-flex bear-flex-col bear-gap-1 bear-min-w-0 bear-flex-1",o="bear-items-end",I="bear-px-4 bear-py-2 bear-rounded-2xl bear-text-sm bear-max-w-[70%] bear-w-fit",n="bear-self-end",O="bear-flex bear-items-baseline bear-gap-2 bear-mb-1",C="bear-text-xs bear-font-semibold",c="bear-text-xs",l="bear-absolute-x-center bear-bottom-4 bear-flex bear-items-center bear-gap-2 bear-px-4 bear-py-2 bear-rounded-full bear-border-none bear-cursor-pointer bear-shadow-lg bear-text-xs bear-font-medium hover:bear-opacity-90",x="bear-flex-1 bear-flex bear-items-center bear-justify-center bear-text-sm";exports.MESSAGE_LIST_AUTHOR_CLASSES=C;exports.MESSAGE_LIST_BASE_CLASSES=r;exports.MESSAGE_LIST_BOTTOM_THRESHOLD_PX=e;exports.MESSAGE_LIST_BUBBLE_CLASSES=I;exports.MESSAGE_LIST_BUBBLE_OWN_CLASSES=n;exports.MESSAGE_LIST_DAY_LABEL_CLASSES=t;exports.MESSAGE_LIST_DAY_LINE_CLASSES=b;exports.MESSAGE_LIST_DAY_SEPARATOR_CLASSES=T;exports.MESSAGE_LIST_DEFAULT_HEIGHT=E;exports.MESSAGE_LIST_DEFAULT_TRANSLATIONS=L;exports.MESSAGE_LIST_EMPTY_CLASSES=x;exports.MESSAGE_LIST_GROUP_BODY_CLASSES=G;exports.MESSAGE_LIST_GROUP_BODY_OWN_CLASSES=o;exports.MESSAGE_LIST_GROUP_CLASSES=M;exports.MESSAGE_LIST_GROUP_OWN_CLASSES=s;exports.MESSAGE_LIST_GROUP_WINDOW_MS=_;exports.MESSAGE_LIST_META_CLASSES=O;exports.MESSAGE_LIST_MS_PER_DAY=A;exports.MESSAGE_LIST_NEW_MESSAGES_CLASSES=l;exports.MESSAGE_LIST_ROOT_CLASS=S;exports.MESSAGE_LIST_SCROLLER_CLASSES=a;exports.MESSAGE_LIST_TIMESTAMP_CLASSES=c;
@@ -0,0 +1,23 @@
1
+ import { MessageListTranslations } from './MessageList.types';
2
+ export declare const MESSAGE_LIST_ROOT_CLASS = "Bear-MessageList";
3
+ export declare const MESSAGE_LIST_DEFAULT_HEIGHT = 400;
4
+ export declare const MESSAGE_LIST_GROUP_WINDOW_MS: number;
5
+ export declare const MESSAGE_LIST_BOTTOM_THRESHOLD_PX = 40;
6
+ export declare const MESSAGE_LIST_MS_PER_DAY: number;
7
+ export declare const MESSAGE_LIST_DEFAULT_TRANSLATIONS: MessageListTranslations;
8
+ export declare const MESSAGE_LIST_BASE_CLASSES = "bear-relative bear-flex bear-flex-col bear-rounded-xl bear-border bear-overflow-hidden";
9
+ export declare const MESSAGE_LIST_SCROLLER_CLASSES = "bear-flex-1 bear-overflow-y-auto bear-p-4 bear-flex bear-flex-col bear-gap-3";
10
+ export declare const MESSAGE_LIST_DAY_SEPARATOR_CLASSES = "bear-flex bear-items-center bear-gap-3 bear-my-1";
11
+ export declare const MESSAGE_LIST_DAY_LINE_CLASSES = "bear-flex-1 bear-h-px";
12
+ export declare const MESSAGE_LIST_DAY_LABEL_CLASSES = "bear-text-xs bear-font-medium bear-whitespace-nowrap";
13
+ export declare const MESSAGE_LIST_GROUP_CLASSES = "bear-flex bear-gap-2";
14
+ export declare const MESSAGE_LIST_GROUP_OWN_CLASSES = "bear-flex-row-reverse";
15
+ export declare const MESSAGE_LIST_GROUP_BODY_CLASSES = "bear-flex bear-flex-col bear-gap-1 bear-min-w-0 bear-flex-1";
16
+ export declare const MESSAGE_LIST_GROUP_BODY_OWN_CLASSES = "bear-items-end";
17
+ export declare const MESSAGE_LIST_BUBBLE_CLASSES = "bear-px-4 bear-py-2 bear-rounded-2xl bear-text-sm bear-max-w-[70%] bear-w-fit";
18
+ export declare const MESSAGE_LIST_BUBBLE_OWN_CLASSES = "bear-self-end";
19
+ export declare const MESSAGE_LIST_META_CLASSES = "bear-flex bear-items-baseline bear-gap-2 bear-mb-1";
20
+ export declare const MESSAGE_LIST_AUTHOR_CLASSES = "bear-text-xs bear-font-semibold";
21
+ export declare const MESSAGE_LIST_TIMESTAMP_CLASSES = "bear-text-xs";
22
+ export declare const MESSAGE_LIST_NEW_MESSAGES_CLASSES = "bear-absolute-x-center bear-bottom-4 bear-flex bear-items-center bear-gap-2 bear-px-4 bear-py-2 bear-rounded-full bear-border-none bear-cursor-pointer bear-shadow-lg bear-text-xs bear-font-medium hover:bear-opacity-90";
23
+ export declare const MESSAGE_LIST_EMPTY_CLASSES = "bear-flex-1 bear-flex bear-items-center bear-justify-center bear-text-sm";
@@ -0,0 +1,30 @@
1
+ const e = "Bear-MessageList", S = 400, r = 3e5, a = 40, E = 864e5, _ = {
2
+ newMessages: "New messages",
3
+ today: "Today",
4
+ yesterday: "Yesterday",
5
+ emptyLabel: "No messages yet"
6
+ }, b = "bear-relative bear-flex bear-flex-col bear-rounded-xl bear-border bear-overflow-hidden", t = "bear-flex-1 bear-overflow-y-auto bear-p-4 bear-flex bear-flex-col bear-gap-3", s = "bear-flex bear-items-center bear-gap-3 bear-my-1", A = "bear-flex-1 bear-h-px", o = "bear-text-xs bear-font-medium bear-whitespace-nowrap", L = "bear-flex bear-gap-2", n = "bear-flex-row-reverse", T = "bear-flex bear-flex-col bear-gap-1 bear-min-w-0 bear-flex-1", x = "bear-items-end", c = "bear-px-4 bear-py-2 bear-rounded-2xl bear-text-sm bear-max-w-[70%] bear-w-fit", l = "bear-self-end", M = "bear-flex bear-items-baseline bear-gap-2 bear-mb-1", G = "bear-text-xs bear-font-semibold", I = "bear-text-xs", f = "bear-absolute-x-center bear-bottom-4 bear-flex bear-items-center bear-gap-2 bear-px-4 bear-py-2 bear-rounded-full bear-border-none bear-cursor-pointer bear-shadow-lg bear-text-xs bear-font-medium hover:bear-opacity-90", d = "bear-flex-1 bear-flex bear-items-center bear-justify-center bear-text-sm";
7
+ export {
8
+ G as MESSAGE_LIST_AUTHOR_CLASSES,
9
+ b as MESSAGE_LIST_BASE_CLASSES,
10
+ a as MESSAGE_LIST_BOTTOM_THRESHOLD_PX,
11
+ c as MESSAGE_LIST_BUBBLE_CLASSES,
12
+ l as MESSAGE_LIST_BUBBLE_OWN_CLASSES,
13
+ o as MESSAGE_LIST_DAY_LABEL_CLASSES,
14
+ A as MESSAGE_LIST_DAY_LINE_CLASSES,
15
+ s as MESSAGE_LIST_DAY_SEPARATOR_CLASSES,
16
+ S as MESSAGE_LIST_DEFAULT_HEIGHT,
17
+ _ as MESSAGE_LIST_DEFAULT_TRANSLATIONS,
18
+ d as MESSAGE_LIST_EMPTY_CLASSES,
19
+ T as MESSAGE_LIST_GROUP_BODY_CLASSES,
20
+ x as MESSAGE_LIST_GROUP_BODY_OWN_CLASSES,
21
+ L as MESSAGE_LIST_GROUP_CLASSES,
22
+ n as MESSAGE_LIST_GROUP_OWN_CLASSES,
23
+ r as MESSAGE_LIST_GROUP_WINDOW_MS,
24
+ M as MESSAGE_LIST_META_CLASSES,
25
+ E as MESSAGE_LIST_MS_PER_DAY,
26
+ f as MESSAGE_LIST_NEW_MESSAGES_CLASSES,
27
+ e as MESSAGE_LIST_ROOT_CLASS,
28
+ t as MESSAGE_LIST_SCROLLER_CLASSES,
29
+ I as MESSAGE_LIST_TIMESTAMP_CLASSES
30
+ };
@@ -0,0 +1,19 @@
1
+ import { FC } from 'react';
2
+ import { MessageListProps } from './MessageList.types';
3
+ /**
4
+ * MessageList - Chat message list with consecutive-author grouping,
5
+ * day separators, and auto-scroll with a "new messages" affordance.
6
+ *
7
+ * Rendering is plain (non-virtualized); virtualization is planned as
8
+ * future work for very long conversations.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <MessageList
13
+ * messages={messages}
14
+ * currentUserId="me"
15
+ * height={420}
16
+ * />
17
+ * ```
18
+ */
19
+ export declare const MessageList: FC<MessageListProps>;
@@ -0,0 +1,182 @@
1
+ import { jsxs as _, jsx as n } from "react/jsx-runtime";
2
+ import { useRef as I, useState as j, useEffect as k } from "react";
3
+ import { Avatar as z } from "../Avatar/Avatar.js";
4
+ import { Typography as r } from "../Typography/Typography.js";
5
+ import { MESSAGE_LIST_DEFAULT_HEIGHT as X, MESSAGE_LIST_DEFAULT_TRANSLATIONS as q, MESSAGE_LIST_EMPTY_CLASSES as J, MESSAGE_LIST_ROOT_CLASS as t, MESSAGE_LIST_DAY_LINE_CLASSES as N, MESSAGE_LIST_DAY_LABEL_CLASSES as K, MESSAGE_LIST_DAY_SEPARATOR_CLASSES as Q, MESSAGE_LIST_SCROLLER_CLASSES as V, MESSAGE_LIST_NEW_MESSAGES_CLASSES as Z, MESSAGE_LIST_BASE_CLASSES as g, MESSAGE_LIST_GROUP_WINDOW_MS as SS, MESSAGE_LIST_AUTHOR_CLASSES as tS, MESSAGE_LIST_TIMESTAMP_CLASSES as f, MESSAGE_LIST_META_CLASSES as eS, MESSAGE_LIST_BUBBLE_OWN_CLASSES as sS, MESSAGE_LIST_BUBBLE_CLASSES as nS, MESSAGE_LIST_GROUP_BODY_OWN_CLASSES as _S, MESSAGE_LIST_GROUP_BODY_CLASSES as aS, MESSAGE_LIST_GROUP_OWN_CLASSES as lS, MESSAGE_LIST_GROUP_CLASSES as rS, MESSAGE_LIST_BOTTOM_THRESHOLD_PX as cS } from "./MessageList.const.js";
6
+ import { buildMessageListItems as oS, getDefaultDayLabel as ES, getDefaultTimestamp as iS } from "./MessageList.utils.js";
7
+ import { cn as e } from "../../utils/cn.js";
8
+ import { resolveBearId as AS } from "../../utils/generateBearId.utils.js";
9
+ import { useBearId as LS } from "../../utils/useBearId.js";
10
+ const OS = ({
11
+ id: B,
12
+ testId: R,
13
+ messages: a,
14
+ currentUserId: v,
15
+ groupWindowMs: C = SS,
16
+ showDaySeparators: $ = !0,
17
+ showAvatars: b = !0,
18
+ showTimestamps: h = !0,
19
+ autoScroll: u = !0,
20
+ height: c = X,
21
+ renderMessage: o,
22
+ emptyState: y,
23
+ formatDayLabel: E,
24
+ formatTimestamp: i,
25
+ translations: U,
26
+ onNewMessagesClick: A,
27
+ className: H
28
+ }) => {
29
+ const P = LS("MessageList"), w = AS(B, P), L = I(null), G = I(!0), d = I(null), [D, m] = j(!1), T = { ...q, ...U }, p = oS(a, v, C, $), W = (S) => (E == null ? void 0 : E(S)) ?? ES(S, T), M = (S) => (i == null ? void 0 : i(S)) ?? iS(S), O = (S) => {
30
+ const s = L.current;
31
+ s && s.scrollTo({ top: s.scrollHeight, behavior: S ? "smooth" : "auto" });
32
+ }, Y = () => {
33
+ const S = L.current;
34
+ if (!S) return;
35
+ const l = S.scrollHeight - S.scrollTop - S.clientHeight <= cS;
36
+ G.current = l, l && m(!1);
37
+ };
38
+ k(() => {
39
+ const S = a.length > 0 ? a[a.length - 1].id : null, s = d.current === null, l = S !== null && S !== d.current;
40
+ if (d.current = S, !!l) {
41
+ if (s || u && G.current) {
42
+ O(!s);
43
+ return;
44
+ }
45
+ m(!0);
46
+ }
47
+ }, [a, u]);
48
+ const x = () => {
49
+ O(!0), m(!1), A == null || A();
50
+ }, F = (S) => /* @__PURE__ */ _(
51
+ "div",
52
+ {
53
+ className: e(
54
+ `${t}__group`,
55
+ rS,
56
+ S.isOwn && lS
57
+ ),
58
+ children: [
59
+ b && !S.isOwn && /* @__PURE__ */ n(
60
+ z,
61
+ {
62
+ src: S.author.avatar,
63
+ initials: S.author.name[0],
64
+ size: "sm",
65
+ className: "bear-flex-shrink-0"
66
+ }
67
+ ),
68
+ /* @__PURE__ */ _(
69
+ "div",
70
+ {
71
+ className: e(
72
+ `${t}__group-body`,
73
+ aS,
74
+ S.isOwn && _S
75
+ ),
76
+ children: [
77
+ !S.isOwn && /* @__PURE__ */ _("div", { className: e(`${t}__meta`, eS), children: [
78
+ /* @__PURE__ */ n(
79
+ r,
80
+ {
81
+ variant: "caption",
82
+ component: "span",
83
+ className: e(`${t}__author`, tS),
84
+ children: S.author.name
85
+ }
86
+ ),
87
+ h && /* @__PURE__ */ n(
88
+ r,
89
+ {
90
+ variant: "caption",
91
+ component: "span",
92
+ className: e(`${t}__timestamp`, f),
93
+ children: M(S.messages[0].timestamp)
94
+ }
95
+ )
96
+ ] }),
97
+ S.messages.map((s) => /* @__PURE__ */ n(
98
+ "div",
99
+ {
100
+ className: e(
101
+ `${t}__bubble`,
102
+ nS,
103
+ S.isOwn && `${t}__bubble--own`,
104
+ S.isOwn && sS
105
+ ),
106
+ children: (o == null ? void 0 : o(s)) ?? s.content
107
+ },
108
+ s.id
109
+ )),
110
+ S.isOwn && h && /* @__PURE__ */ n(
111
+ r,
112
+ {
113
+ variant: "caption",
114
+ component: "span",
115
+ className: e(`${t}__timestamp`, f),
116
+ children: M(S.messages[S.messages.length - 1].timestamp)
117
+ }
118
+ )
119
+ ]
120
+ }
121
+ )
122
+ ]
123
+ },
124
+ S.key
125
+ );
126
+ return /* @__PURE__ */ _(
127
+ "div",
128
+ {
129
+ id: w,
130
+ "data-testid": R,
131
+ className: e(t, g, H),
132
+ style: { height: typeof c == "number" ? `${c}px` : c },
133
+ children: [
134
+ /* @__PURE__ */ _(
135
+ "div",
136
+ {
137
+ ref: L,
138
+ onScroll: Y,
139
+ className: e(`${t}__scroller`, V),
140
+ role: "log",
141
+ "aria-live": "polite",
142
+ children: [
143
+ p.length === 0 && /* @__PURE__ */ n("div", { className: e(`${t}__empty`, J), children: y ?? /* @__PURE__ */ n(r, { variant: "body2", component: "span", children: T.emptyLabel }) }),
144
+ p.map(
145
+ (S) => S.kind === "day" ? /* @__PURE__ */ _(
146
+ "div",
147
+ {
148
+ className: e(
149
+ `${t}__day-separator`,
150
+ Q
151
+ ),
152
+ children: [
153
+ /* @__PURE__ */ n("span", { className: e(`${t}__day-line`, N) }),
154
+ /* @__PURE__ */ n("span", { className: e(`${t}__day-label`, K), children: W(S.date) }),
155
+ /* @__PURE__ */ n("span", { className: e(`${t}__day-line`, N) })
156
+ ]
157
+ },
158
+ S.key
159
+ ) : F(S)
160
+ )
161
+ ]
162
+ }
163
+ ),
164
+ D && /* @__PURE__ */ n(
165
+ "button",
166
+ {
167
+ type: "button",
168
+ onClick: x,
169
+ className: e(
170
+ `${t}__new-messages`,
171
+ Z
172
+ ),
173
+ children: T.newMessages
174
+ }
175
+ )
176
+ ]
177
+ }
178
+ );
179
+ };
180
+ export {
181
+ OS as MessageList
182
+ };
@@ -0,0 +1,72 @@
1
+ import { ReactNode } from 'react';
2
+ export interface MessageListAuthor {
3
+ /** Unique author identifier — used for consecutive message grouping */
4
+ id: string;
5
+ /** Display name */
6
+ name: string;
7
+ /** Avatar image URL */
8
+ avatar?: string;
9
+ }
10
+ export interface MessageListMessage {
11
+ /** Unique message identifier */
12
+ id: string;
13
+ /** Message author */
14
+ author: MessageListAuthor;
15
+ /** Message content */
16
+ content: ReactNode;
17
+ /** Message timestamp — required for grouping and day separators */
18
+ timestamp: Date;
19
+ }
20
+ export interface MessageListTranslations {
21
+ newMessages: string;
22
+ today: string;
23
+ yesterday: string;
24
+ emptyLabel: string;
25
+ }
26
+ export interface MessageListDayItem {
27
+ kind: 'day';
28
+ key: string;
29
+ date: Date;
30
+ }
31
+ export interface MessageListGroupItem {
32
+ kind: 'group';
33
+ key: string;
34
+ author: MessageListAuthor;
35
+ isOwn: boolean;
36
+ messages: MessageListMessage[];
37
+ }
38
+ export type MessageListItem = MessageListDayItem | MessageListGroupItem;
39
+ export interface MessageListProps {
40
+ id?: string;
41
+ testId?: string;
42
+ /** Messages in chronological order (oldest first) */
43
+ messages: MessageListMessage[];
44
+ /** Author id whose messages are aligned right as "own" messages */
45
+ currentUserId?: string;
46
+ /** Max gap in ms between consecutive messages of the same author to stay in one group */
47
+ groupWindowMs?: number;
48
+ /** Show day separator rows between messages of different days */
49
+ showDaySeparators?: boolean;
50
+ /** Show author avatars */
51
+ showAvatars?: boolean;
52
+ /** Show group timestamps */
53
+ showTimestamps?: boolean;
54
+ /** Auto-scroll to bottom on new messages when already at the bottom */
55
+ autoScroll?: boolean;
56
+ /** Height of the scrollable area */
57
+ height?: number | string;
58
+ /** Custom message content renderer */
59
+ renderMessage?: (message: MessageListMessage) => ReactNode;
60
+ /** Content rendered when there are no messages */
61
+ emptyState?: ReactNode;
62
+ /** Custom day separator label formatter */
63
+ formatDayLabel?: (date: Date) => string;
64
+ /** Custom timestamp formatter */
65
+ formatTimestamp?: (date: Date) => string;
66
+ /** Replaceable user-facing strings */
67
+ translations?: Partial<MessageListTranslations>;
68
+ /** Callback when the "new messages" affordance is clicked */
69
+ onNewMessagesClick?: () => void;
70
+ /** Additional CSS class */
71
+ className?: string;
72
+ }
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("./MessageList.const.cjs"),n=(e,s)=>e.getFullYear()===s.getFullYear()&&e.getMonth()===s.getMonth()&&e.getDate()===s.getDate(),u=e=>`${e.getFullYear()}-${e.getMonth()}-${e.getDate()}`,c=(e,s)=>{const o=new Date;if(n(e,o))return s.today;const g=new Date(o.getTime()-y.MESSAGE_LIST_MS_PER_DAY);return n(e,g)?s.yesterday:e.toLocaleDateString([],{year:"numeric",month:"long",day:"numeric"})},d=e=>e.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"}),D=(e,s,o,g)=>{const i=[];let r=null;for(const t of e){const m=r===null||!n(r,t.timestamp);g&&m&&i.push({kind:"day",key:`day-${u(t.timestamp)}`,date:t.timestamp});const a=i[i.length-1],l=a!==void 0&&a.kind==="group"&&a.author.id===t.author.id&&t.timestamp.getTime()-a.messages[a.messages.length-1].timestamp.getTime()<=o;a!==void 0&&a.kind==="group"&&l?a.messages.push(t):i.push({kind:"group",key:`group-${t.id}`,author:t.author,isOwn:t.author.id===s,messages:[t]}),r=t.timestamp}return i};exports.buildMessageListItems=D;exports.getDayKey=u;exports.getDefaultDayLabel=c;exports.getDefaultTimestamp=d;exports.isSameDay=n;
@@ -0,0 +1,6 @@
1
+ import { MessageListItem, MessageListMessage, MessageListTranslations } from './MessageList.types';
2
+ export declare const isSameDay: (a: Date, b: Date) => boolean;
3
+ export declare const getDayKey: (date: Date) => string;
4
+ export declare const getDefaultDayLabel: (date: Date, translations: MessageListTranslations) => string;
5
+ export declare const getDefaultTimestamp: (date: Date) => string;
6
+ export declare const buildMessageListItems: (messages: MessageListMessage[], currentUserId: string | undefined, groupWindowMs: number, showDaySeparators: boolean) => MessageListItem[];