@usecrow/ui 0.1.10 → 0.1.11

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
@@ -1149,7 +1149,9 @@ function useWidgetStyles2() {
1149
1149
  const context = React3.useContext(WidgetStyleContext);
1150
1150
  return context?.styles ?? DEFAULT_WIDGET_STYLES;
1151
1151
  }
1152
- var CopilotStyleContext = React3.createContext(null);
1152
+ var CopilotStyleContext = React3.createContext(
1153
+ null
1154
+ );
1153
1155
  function CopilotStyleProvider({
1154
1156
  children,
1155
1157
  styles,
@@ -1175,6 +1177,7 @@ function useCopilotStyles2() {
1175
1177
  const context = React3.useContext(CopilotStyleContext);
1176
1178
  return context?.styles ?? DEFAULT_COPILOT_STYLES;
1177
1179
  }
1180
+ var PASSTHROUGH_KEYS = /* @__PURE__ */ new Set(["Escape", "Tab"]);
1178
1181
  function ShadowContainer({
1179
1182
  children,
1180
1183
  styles,
@@ -1189,6 +1192,51 @@ function ShadowContainer({
1189
1192
  setShadowRoot(shadow);
1190
1193
  }
1191
1194
  }, []);
1195
+ React3.useEffect(() => {
1196
+ if (!shadowRoot || !hostRef.current) return;
1197
+ const hostElement = hostRef.current;
1198
+ const stopPropagationHandler = (e) => {
1199
+ const keyEvent = e;
1200
+ if (keyEvent.key && PASSTHROUGH_KEYS.has(keyEvent.key)) {
1201
+ return;
1202
+ }
1203
+ e.stopPropagation();
1204
+ };
1205
+ shadowRoot.addEventListener("keydown", stopPropagationHandler);
1206
+ shadowRoot.addEventListener("keyup", stopPropagationHandler);
1207
+ shadowRoot.addEventListener("keypress", stopPropagationHandler);
1208
+ let lastFocusedElement = null;
1209
+ const trackFocus = (e) => {
1210
+ lastFocusedElement = e.target;
1211
+ };
1212
+ const protectFocus = (e) => {
1213
+ if (e.key && PASSTHROUGH_KEYS.has(e.key)) {
1214
+ return;
1215
+ }
1216
+ const path = e.composedPath();
1217
+ if (!path.includes(hostElement) && !path.includes(shadowRoot)) {
1218
+ return;
1219
+ }
1220
+ if (lastFocusedElement) {
1221
+ const elementToRestore = lastFocusedElement;
1222
+ queueMicrotask(() => {
1223
+ const activeInShadow = shadowRoot.activeElement;
1224
+ if (!activeInShadow) {
1225
+ elementToRestore.focus();
1226
+ }
1227
+ });
1228
+ }
1229
+ };
1230
+ shadowRoot.addEventListener("focusin", trackFocus);
1231
+ document.addEventListener("keydown", protectFocus, { capture: true });
1232
+ return () => {
1233
+ shadowRoot.removeEventListener("keydown", stopPropagationHandler);
1234
+ shadowRoot.removeEventListener("keyup", stopPropagationHandler);
1235
+ shadowRoot.removeEventListener("keypress", stopPropagationHandler);
1236
+ shadowRoot.removeEventListener("focusin", trackFocus);
1237
+ document.removeEventListener("keydown", protectFocus, { capture: true });
1238
+ };
1239
+ }, [shadowRoot]);
1192
1240
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: hostRef, id: hostId, className: hostClassName, children: shadowRoot && reactDom.createPortal(
1193
1241
  /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1194
1242
  /* @__PURE__ */ jsxRuntime.jsx("style", { children: styles }),
@@ -1706,64 +1754,62 @@ function MessageList({
1706
1754
  msg.id
1707
1755
  )) });
1708
1756
  }
1709
- var MessagesContainer = React3.forwardRef(
1710
- ({ children }, ref) => {
1711
- const styles = useWidgetStyles2();
1712
- const internalRef = React3.useRef(null);
1713
- const lastScrollHeightRef = React3.useRef(0);
1714
- const isUserScrollingRef = React3.useRef(false);
1715
- const containerRef = ref || internalRef;
1716
- const isNearBottom = React3.useCallback(() => {
1717
- const container = containerRef.current;
1718
- if (!container) return true;
1719
- const threshold = 100;
1720
- return container.scrollHeight - container.scrollTop - container.clientHeight < threshold;
1721
- }, [containerRef]);
1722
- const scrollToBottom = React3.useCallback(() => {
1723
- const container = containerRef.current;
1724
- if (!container) return;
1725
- container.scrollTo({
1726
- top: container.scrollHeight,
1727
- behavior: "smooth"
1728
- });
1729
- }, [containerRef]);
1730
- React3.useEffect(() => {
1731
- const container = containerRef.current;
1732
- if (!container) return;
1733
- const handleScroll = () => {
1734
- isUserScrollingRef.current = !isNearBottom();
1735
- };
1736
- container.addEventListener("scroll", handleScroll, { passive: true });
1737
- return () => container.removeEventListener("scroll", handleScroll);
1738
- }, [containerRef, isNearBottom]);
1739
- React3.useEffect(() => {
1740
- const container = containerRef.current;
1741
- if (!container) return;
1742
- const currentHeight = container.scrollHeight;
1743
- const heightChanged = currentHeight !== lastScrollHeightRef.current;
1744
- if (heightChanged) {
1745
- lastScrollHeightRef.current = currentHeight;
1746
- if (!isUserScrollingRef.current || isNearBottom()) {
1747
- scrollToBottom();
1748
- }
1749
- }
1757
+ var MessagesContainer = React3.forwardRef(({ children }, ref) => {
1758
+ const styles = useWidgetStyles2();
1759
+ const internalRef = React3.useRef(null);
1760
+ const lastScrollHeightRef = React3.useRef(0);
1761
+ const isUserScrollingRef = React3.useRef(false);
1762
+ const containerRef = ref || internalRef;
1763
+ const isNearBottom = React3.useCallback(() => {
1764
+ const container = containerRef.current;
1765
+ if (!container) return true;
1766
+ const threshold = 100;
1767
+ return container.scrollHeight - container.scrollTop - container.clientHeight < threshold;
1768
+ }, [containerRef]);
1769
+ const scrollToBottom = React3.useCallback(() => {
1770
+ const container = containerRef.current;
1771
+ if (!container) return;
1772
+ container.scrollTo({
1773
+ top: container.scrollHeight,
1774
+ behavior: "smooth"
1750
1775
  });
1751
- return /* @__PURE__ */ jsxRuntime.jsx(
1752
- framerMotion.motion.div,
1753
- {
1754
- ref: containerRef,
1755
- id: MESSAGES_CONTAINER_ID,
1756
- initial: { opacity: 0 },
1757
- animate: { opacity: 1 },
1758
- exit: { opacity: 0 },
1759
- transition: { duration: styles.animations.duration },
1760
- className: "crow-relative crow-flex-1 crow-min-h-0 crow-rounded-2xl crow-mb-3 crow-overflow-y-auto crow-p-4 crow-space-y-3 crow-pointer-events-auto",
1761
- style: { background: styles.colors.messagesBackground },
1762
- children
1776
+ }, [containerRef]);
1777
+ React3.useEffect(() => {
1778
+ const container = containerRef.current;
1779
+ if (!container) return;
1780
+ const handleScroll = () => {
1781
+ isUserScrollingRef.current = !isNearBottom();
1782
+ };
1783
+ container.addEventListener("scroll", handleScroll, { passive: true });
1784
+ return () => container.removeEventListener("scroll", handleScroll);
1785
+ }, [containerRef, isNearBottom]);
1786
+ React3.useEffect(() => {
1787
+ const container = containerRef.current;
1788
+ if (!container) return;
1789
+ const currentHeight = container.scrollHeight;
1790
+ const heightChanged = currentHeight !== lastScrollHeightRef.current;
1791
+ if (heightChanged) {
1792
+ lastScrollHeightRef.current = currentHeight;
1793
+ if (!isUserScrollingRef.current || isNearBottom()) {
1794
+ scrollToBottom();
1763
1795
  }
1764
- );
1765
- }
1766
- );
1796
+ }
1797
+ });
1798
+ return /* @__PURE__ */ jsxRuntime.jsx(
1799
+ framerMotion.motion.div,
1800
+ {
1801
+ ref: containerRef,
1802
+ id: MESSAGES_CONTAINER_ID,
1803
+ initial: { opacity: 0 },
1804
+ animate: { opacity: 1 },
1805
+ exit: { opacity: 0 },
1806
+ transition: { duration: styles.animations.duration },
1807
+ className: "crow-relative crow-flex-1 crow-min-h-0 crow-rounded-2xl crow-mb-3 crow-overflow-y-auto crow-p-4 crow-space-y-3 crow-pointer-events-auto",
1808
+ style: { background: styles.colors.messagesBackground },
1809
+ children
1810
+ }
1811
+ );
1812
+ });
1767
1813
  MessagesContainer.displayName = "MessagesContainer";
1768
1814
  function ConversationList({
1769
1815
  conversations,
@@ -2035,7 +2081,13 @@ var PromptInput = React3__default.default.forwardRef(
2035
2081
  }
2036
2082
  );
2037
2083
  PromptInput.displayName = "PromptInput";
2038
- var PromptInputTextarea = ({ className, onKeyDown, disableAutosize = false, placeholder, ...props }) => {
2084
+ var PromptInputTextarea = ({
2085
+ className,
2086
+ onKeyDown,
2087
+ disableAutosize = false,
2088
+ placeholder,
2089
+ ...props
2090
+ }) => {
2039
2091
  const { value, setValue, maxHeight, onSubmit, disabled } = usePromptInput();
2040
2092
  const textareaRef = React3__default.default.useRef(null);
2041
2093
  React3__default.default.useEffect(() => {
@@ -2068,7 +2120,14 @@ var PromptInputActions = ({
2068
2120
  children,
2069
2121
  className,
2070
2122
  ...props
2071
- }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("crow-flex crow-items-center crow-gap-2", className), ...props, children });
2123
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
2124
+ "div",
2125
+ {
2126
+ className: cn("crow-flex crow-items-center crow-gap-2", className),
2127
+ ...props,
2128
+ children
2129
+ }
2130
+ );
2072
2131
  var PromptInputAction = ({
2073
2132
  tooltip,
2074
2133
  children,
@@ -2115,7 +2174,13 @@ var PromptInputBox = React3__default.default.forwardRef(
2115
2174
  disabled: isLoading,
2116
2175
  ref: ref || promptBoxRef,
2117
2176
  children: [
2118
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-transition-all crow-duration-300 crow-opacity-100", children: /* @__PURE__ */ jsxRuntime.jsx(PromptInputTextarea, { placeholder, className: "crow-text-base" }) }),
2177
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-transition-all crow-duration-300 crow-opacity-100", children: /* @__PURE__ */ jsxRuntime.jsx(
2178
+ PromptInputTextarea,
2179
+ {
2180
+ placeholder,
2181
+ className: "crow-text-base"
2182
+ }
2183
+ ) }),
2119
2184
  /* @__PURE__ */ jsxRuntime.jsxs(PromptInputActions, { className: "crow-flex crow-items-center crow-justify-between crow-gap-2 crow-p-0 crow-pt-1", children: [
2120
2185
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "crow-flex crow-items-center", children: availableModels.length > 0 && onModelChange && /* @__PURE__ */ jsxRuntime.jsx(
2121
2186
  ModelSelector,
@@ -2148,10 +2213,21 @@ var PromptInputBox = React3__default.default.forwardRef(
2148
2213
  handleSubmit();
2149
2214
  }
2150
2215
  },
2151
- children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Square, { className: "crow-h-3.5 crow-w-3.5 crow-text-white", style: { fill: "white" } }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: cn(
2152
- "crow-h-3.5 crow-w-3.5",
2153
- hasContent ? "crow-text-white" : "crow-text-gray-400"
2154
- ) })
2216
+ children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(
2217
+ lucideReact.Square,
2218
+ {
2219
+ className: "crow-h-3.5 crow-w-3.5 crow-text-white",
2220
+ style: { fill: "white" }
2221
+ }
2222
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
2223
+ lucideReact.ArrowUp,
2224
+ {
2225
+ className: cn(
2226
+ "crow-h-3.5 crow-w-3.5",
2227
+ hasContent ? "crow-text-white" : "crow-text-gray-400"
2228
+ )
2229
+ }
2230
+ )
2155
2231
  }
2156
2232
  )
2157
2233
  }