@sensiblestats/widget-react 0.26.0 → 0.26.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @sensiblestats/widget-react
2
2
 
3
+ ## 0.26.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Keep the start of a new turn in view instead of scrolling to the bottom of the reply. When a response arrives the message list now pins the start of the turn to the top — the user's question for a normal turn, or the assistant message itself for an auto-greeting or greeting dashboard — so a long answer reads from its beginning rather than landing the reader on its last line.
8
+
3
9
  ## 0.26.0
4
10
 
5
11
  ### Minor Changes
package/dist/index.cjs CHANGED
@@ -1843,12 +1843,12 @@ function FanDashboardCard({ card, onTap, ui }) {
1843
1843
  var import_jsx_runtime38 = require("react/jsx-runtime");
1844
1844
  function ChatMessage({ message, disabled, onAct, onTap, ui, slip }) {
1845
1845
  if (message.role === "user") {
1846
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "ss-w-msg ss-w-user", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "ss-w-bubble", children: message.text }) });
1846
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "ss-w-msg ss-w-user", "data-msg-id": message.id, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "ss-w-bubble", children: message.text }) });
1847
1847
  }
1848
1848
  const onFanDashboardTap = (card) => {
1849
1849
  onAct({ message: card.actionLabel, actionRef: card.actionRef, label: card.actionLabel || card.title || "" });
1850
1850
  };
1851
- return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "ss-w-msg ss-w-bot", children: [
1851
+ return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "ss-w-msg ss-w-bot", "data-msg-id": message.id, children: [
1852
1852
  message.text && !message.greetingDashboard && !message.clubFanDashboard ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Markdown, { text: message.text }) : null,
1853
1853
  message.greetingDashboard && !message.clubFanDashboard ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(GreetingDashboard, { dashboard: message.greetingDashboard, onTap }) : null,
1854
1854
  message.clubFanDashboard ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(ClubFanDashboard, { dashboard: message.clubFanDashboard, onTap: onFanDashboardTap, ui }) : null,
@@ -1875,12 +1875,26 @@ function isPinnedToBottom(el, threshold = PIN_THRESHOLD) {
1875
1875
 
1876
1876
  // src/components/MessageList.tsx
1877
1877
  var import_jsx_runtime40 = require("react/jsx-runtime");
1878
+ function turnAnchor(messages) {
1879
+ const last = messages[messages.length - 1];
1880
+ if (!last || last.role !== "assistant") return null;
1881
+ const prev = messages[messages.length - 2];
1882
+ return { turnId: last.id, anchorId: prev && prev.role === "user" ? prev.id : last.id };
1883
+ }
1878
1884
  function MessageList({ controller, ui, slip, onDashboardTap }) {
1879
1885
  const { state, send } = controller;
1880
1886
  const listRef = (0, import_react10.useRef)(null);
1881
1887
  const endRef = (0, import_react10.useRef)(null);
1882
1888
  const pinnedRef = (0, import_react10.useRef)(true);
1889
+ const anchoredTurnRef = (0, import_react10.useRef)(null);
1883
1890
  (0, import_react10.useEffect)(() => {
1891
+ const anchor = turnAnchor(state.messages);
1892
+ if (anchor && anchor.turnId !== anchoredTurnRef.current) {
1893
+ anchoredTurnRef.current = anchor.turnId;
1894
+ pinnedRef.current = false;
1895
+ listRef.current?.querySelector(`[data-msg-id="${anchor.anchorId}"]`)?.scrollIntoView({ block: "start" });
1896
+ return;
1897
+ }
1884
1898
  if (pinnedRef.current) endRef.current?.scrollIntoView({ block: "end" });
1885
1899
  }, [state.messages, state.status]);
1886
1900
  const hasUserMessage = state.messages.some((m) => m.role === "user");
@@ -2039,7 +2053,7 @@ var WIDGET_CSS = `.ss-w-root { all: revert; }
2039
2053
  .ss-w-close { margin-left: auto; background: none; border: none; color: var(--ss-w-faint); cursor: pointer; font-size: 16px; display: grid; place-items: center; }
2040
2054
 
2041
2055
  /* messages */
2042
- .ss-w-list { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 12px; }
2056
+ .ss-w-list { flex: 1; overflow-y: auto; padding: 14px; display: flex; flex-direction: column; gap: 12px; scroll-padding-top: 14px; }
2043
2057
  .ss-w-msg { display: flex; }
2044
2058
  .ss-w-user { justify-content: flex-end; }
2045
2059
  .ss-w-user .ss-w-bubble { background: color-mix(in srgb, var(--ss-w-accent) 14%, var(--ss-w-panel)); border: 1px solid color-mix(in srgb, var(--ss-w-accent) 30%, var(--ss-w-line)); border-radius: 14px; padding: 8px 12px; max-width: 80%; }