@usecrow/ui 0.1.10 → 0.1.12

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.d.cts CHANGED
@@ -705,14 +705,14 @@ interface WidgetStyleContextValue {
705
705
  styles: ResolvedWidgetStyles;
706
706
  agentName: string;
707
707
  isLoading: boolean;
708
- variant: 'floating' | 'embedded';
708
+ variant: "floating" | "embedded";
709
709
  }
710
710
  interface WidgetStyleProviderProps {
711
711
  children: react__default.ReactNode;
712
712
  styles: ResolvedWidgetStyles;
713
713
  agentName?: string;
714
714
  isLoading?: boolean;
715
- variant?: 'floating' | 'embedded';
715
+ variant?: "floating" | "embedded";
716
716
  }
717
717
  /**
718
718
  * Provider for widget styles
@@ -790,7 +790,7 @@ interface ReasoningTraceProps {
790
790
  toolCalls?: ToolCall[];
791
791
  isWaiting?: boolean;
792
792
  }
793
- declare function ReasoningTrace({ thinking, isComplete, toolCalls, isWaiting }: ReasoningTraceProps): react_jsx_runtime.JSX.Element | null;
793
+ declare function ReasoningTrace({ thinking, isComplete, toolCalls, isWaiting, }: ReasoningTraceProps): react_jsx_runtime.JSX.Element | null;
794
794
 
795
795
  interface MessageBubbleProps {
796
796
  message: Message;
package/dist/index.d.ts CHANGED
@@ -705,14 +705,14 @@ interface WidgetStyleContextValue {
705
705
  styles: ResolvedWidgetStyles;
706
706
  agentName: string;
707
707
  isLoading: boolean;
708
- variant: 'floating' | 'embedded';
708
+ variant: "floating" | "embedded";
709
709
  }
710
710
  interface WidgetStyleProviderProps {
711
711
  children: react__default.ReactNode;
712
712
  styles: ResolvedWidgetStyles;
713
713
  agentName?: string;
714
714
  isLoading?: boolean;
715
- variant?: 'floating' | 'embedded';
715
+ variant?: "floating" | "embedded";
716
716
  }
717
717
  /**
718
718
  * Provider for widget styles
@@ -790,7 +790,7 @@ interface ReasoningTraceProps {
790
790
  toolCalls?: ToolCall[];
791
791
  isWaiting?: boolean;
792
792
  }
793
- declare function ReasoningTrace({ thinking, isComplete, toolCalls, isWaiting }: ReasoningTraceProps): react_jsx_runtime.JSX.Element | null;
793
+ declare function ReasoningTrace({ thinking, isComplete, toolCalls, isWaiting, }: ReasoningTraceProps): react_jsx_runtime.JSX.Element | null;
794
794
 
795
795
  interface MessageBubbleProps {
796
796
  message: Message;
package/dist/index.js CHANGED
@@ -93,7 +93,9 @@ function useChat({
93
93
  message,
94
94
  conversation_id: conversationId,
95
95
  identity_token: identityToken,
96
- model: selectedModel
96
+ model: selectedModel,
97
+ user_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
98
+ user_local_time: (/* @__PURE__ */ new Date()).toLocaleString()
97
99
  }),
98
100
  signal: abortControllerRef.current.signal
99
101
  });
@@ -363,7 +365,9 @@ function useChat({
363
365
  tool_name: toolName,
364
366
  result,
365
367
  identity_token: identityToken,
366
- model: selectedModel
368
+ model: selectedModel,
369
+ user_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
370
+ user_local_time: (/* @__PURE__ */ new Date()).toLocaleString()
367
371
  })
368
372
  });
369
373
  if (!response.ok) {
@@ -622,6 +626,16 @@ function useWorkflow({
622
626
  exitWorkflow
623
627
  };
624
628
  }
629
+ var SDK_DEFAULT_TOOLS = {
630
+ refreshPage: async () => {
631
+ try {
632
+ window.location.reload();
633
+ return { status: "success", data: { message: "Page refresh initiated" } };
634
+ } catch (error) {
635
+ return { status: "error", error: String(error) };
636
+ }
637
+ }
638
+ };
625
639
  function useCrowAPI({ onIdentified, onReset } = {}) {
626
640
  const onIdentifiedRef = useRef(onIdentified);
627
641
  const onResetRef = useRef(onReset);
@@ -631,6 +645,15 @@ function useCrowAPI({ onIdentified, onReset } = {}) {
631
645
  onResetRef.current = onReset;
632
646
  });
633
647
  useEffect(() => {
648
+ if (!window.__crow_client_tools) {
649
+ window.__crow_client_tools = {};
650
+ }
651
+ for (const [toolName, handler] of Object.entries(SDK_DEFAULT_TOOLS)) {
652
+ if (!window.__crow_client_tools[toolName]) {
653
+ window.__crow_client_tools[toolName] = handler;
654
+ console.log(`[Crow] Registered default tool: ${toolName}`);
655
+ }
656
+ }
634
657
  window.crow = function(command, options) {
635
658
  const opts = options;
636
659
  switch (command) {
@@ -1123,7 +1146,9 @@ function useWidgetStyles2() {
1123
1146
  const context = useContext(WidgetStyleContext);
1124
1147
  return context?.styles ?? DEFAULT_WIDGET_STYLES;
1125
1148
  }
1126
- var CopilotStyleContext = createContext(null);
1149
+ var CopilotStyleContext = createContext(
1150
+ null
1151
+ );
1127
1152
  function CopilotStyleProvider({
1128
1153
  children,
1129
1154
  styles,
@@ -1149,6 +1174,7 @@ function useCopilotStyles2() {
1149
1174
  const context = useContext(CopilotStyleContext);
1150
1175
  return context?.styles ?? DEFAULT_COPILOT_STYLES;
1151
1176
  }
1177
+ var PASSTHROUGH_KEYS = /* @__PURE__ */ new Set(["Escape", "Tab"]);
1152
1178
  function ShadowContainer({
1153
1179
  children,
1154
1180
  styles,
@@ -1163,6 +1189,51 @@ function ShadowContainer({
1163
1189
  setShadowRoot(shadow);
1164
1190
  }
1165
1191
  }, []);
1192
+ useEffect(() => {
1193
+ if (!shadowRoot || !hostRef.current) return;
1194
+ const hostElement = hostRef.current;
1195
+ const stopPropagationHandler = (e) => {
1196
+ const keyEvent = e;
1197
+ if (keyEvent.key && PASSTHROUGH_KEYS.has(keyEvent.key)) {
1198
+ return;
1199
+ }
1200
+ e.stopPropagation();
1201
+ };
1202
+ shadowRoot.addEventListener("keydown", stopPropagationHandler);
1203
+ shadowRoot.addEventListener("keyup", stopPropagationHandler);
1204
+ shadowRoot.addEventListener("keypress", stopPropagationHandler);
1205
+ let lastFocusedElement = null;
1206
+ const trackFocus = (e) => {
1207
+ lastFocusedElement = e.target;
1208
+ };
1209
+ const protectFocus = (e) => {
1210
+ if (e.key && PASSTHROUGH_KEYS.has(e.key)) {
1211
+ return;
1212
+ }
1213
+ const path = e.composedPath();
1214
+ if (!path.includes(hostElement) && !path.includes(shadowRoot)) {
1215
+ return;
1216
+ }
1217
+ if (lastFocusedElement) {
1218
+ const elementToRestore = lastFocusedElement;
1219
+ queueMicrotask(() => {
1220
+ const activeInShadow = shadowRoot.activeElement;
1221
+ if (!activeInShadow) {
1222
+ elementToRestore.focus();
1223
+ }
1224
+ });
1225
+ }
1226
+ };
1227
+ shadowRoot.addEventListener("focusin", trackFocus);
1228
+ document.addEventListener("keydown", protectFocus, { capture: true });
1229
+ return () => {
1230
+ shadowRoot.removeEventListener("keydown", stopPropagationHandler);
1231
+ shadowRoot.removeEventListener("keyup", stopPropagationHandler);
1232
+ shadowRoot.removeEventListener("keypress", stopPropagationHandler);
1233
+ shadowRoot.removeEventListener("focusin", trackFocus);
1234
+ document.removeEventListener("keydown", protectFocus, { capture: true });
1235
+ };
1236
+ }, [shadowRoot]);
1166
1237
  return /* @__PURE__ */ jsx("div", { ref: hostRef, id: hostId, className: hostClassName, children: shadowRoot && createPortal(
1167
1238
  /* @__PURE__ */ jsxs(Fragment, { children: [
1168
1239
  /* @__PURE__ */ jsx("style", { children: styles }),
@@ -1356,7 +1427,14 @@ function StreamingText({
1356
1427
  ...props,
1357
1428
  children
1358
1429
  }
1359
- ) : /* @__PURE__ */ jsx("code", { className: `crow-text-gray-200 ${className || ""}`, ...props, children });
1430
+ ) : /* @__PURE__ */ jsx(
1431
+ "code",
1432
+ {
1433
+ className: `crow-text-gray-200 ${className || ""}`,
1434
+ ...props,
1435
+ children
1436
+ }
1437
+ );
1360
1438
  },
1361
1439
  pre: ({ children }) => /* @__PURE__ */ jsx("pre", { className: "crow-bg-gray-800 crow-text-gray-200 crow-p-3 crow-rounded-lg crow-my-2 crow-overflow-x-auto crow-text-sm", children })
1362
1440
  },
@@ -1470,7 +1548,12 @@ function ShimmeringContent({ children }) {
1470
1548
  }
1471
1549
  );
1472
1550
  }
1473
- function ReasoningTrace({ thinking, isComplete, toolCalls = [], isWaiting = false }) {
1551
+ function ReasoningTrace({
1552
+ thinking,
1553
+ isComplete,
1554
+ toolCalls = [],
1555
+ isWaiting = false
1556
+ }) {
1474
1557
  const hasThinking = !!thinking && thinking.trim().length > 0;
1475
1558
  const hasToolCalls = toolCalls.length > 0;
1476
1559
  if (!isWaiting && !hasThinking && !hasToolCalls) return null;
@@ -1486,7 +1569,10 @@ function WaitingIndicator() {
1486
1569
  /* @__PURE__ */ jsx("span", { className: "crow-font-medium", children: /* @__PURE__ */ jsx(ShimmeringContent, { children: getRandomThinkingMessage() }) })
1487
1570
  ] });
1488
1571
  }
1489
- function ThinkingBlock({ thinking, isComplete }) {
1572
+ function ThinkingBlock({
1573
+ thinking,
1574
+ isComplete
1575
+ }) {
1490
1576
  const [isExpanded, setIsExpanded] = useState(!isComplete);
1491
1577
  useLayoutEffect(() => {
1492
1578
  setIsExpanded(!isComplete);
@@ -1680,64 +1766,62 @@ function MessageList({
1680
1766
  msg.id
1681
1767
  )) });
1682
1768
  }
1683
- var MessagesContainer = forwardRef(
1684
- ({ children }, ref) => {
1685
- const styles = useWidgetStyles2();
1686
- const internalRef = useRef(null);
1687
- const lastScrollHeightRef = useRef(0);
1688
- const isUserScrollingRef = useRef(false);
1689
- const containerRef = ref || internalRef;
1690
- const isNearBottom = useCallback(() => {
1691
- const container = containerRef.current;
1692
- if (!container) return true;
1693
- const threshold = 100;
1694
- return container.scrollHeight - container.scrollTop - container.clientHeight < threshold;
1695
- }, [containerRef]);
1696
- const scrollToBottom = useCallback(() => {
1697
- const container = containerRef.current;
1698
- if (!container) return;
1699
- container.scrollTo({
1700
- top: container.scrollHeight,
1701
- behavior: "smooth"
1702
- });
1703
- }, [containerRef]);
1704
- useEffect(() => {
1705
- const container = containerRef.current;
1706
- if (!container) return;
1707
- const handleScroll = () => {
1708
- isUserScrollingRef.current = !isNearBottom();
1709
- };
1710
- container.addEventListener("scroll", handleScroll, { passive: true });
1711
- return () => container.removeEventListener("scroll", handleScroll);
1712
- }, [containerRef, isNearBottom]);
1713
- useEffect(() => {
1714
- const container = containerRef.current;
1715
- if (!container) return;
1716
- const currentHeight = container.scrollHeight;
1717
- const heightChanged = currentHeight !== lastScrollHeightRef.current;
1718
- if (heightChanged) {
1719
- lastScrollHeightRef.current = currentHeight;
1720
- if (!isUserScrollingRef.current || isNearBottom()) {
1721
- scrollToBottom();
1722
- }
1723
- }
1769
+ var MessagesContainer = forwardRef(({ children }, ref) => {
1770
+ const styles = useWidgetStyles2();
1771
+ const internalRef = useRef(null);
1772
+ const lastScrollHeightRef = useRef(0);
1773
+ const isUserScrollingRef = useRef(false);
1774
+ const containerRef = ref || internalRef;
1775
+ const isNearBottom = useCallback(() => {
1776
+ const container = containerRef.current;
1777
+ if (!container) return true;
1778
+ const threshold = 100;
1779
+ return container.scrollHeight - container.scrollTop - container.clientHeight < threshold;
1780
+ }, [containerRef]);
1781
+ const scrollToBottom = useCallback(() => {
1782
+ const container = containerRef.current;
1783
+ if (!container) return;
1784
+ container.scrollTo({
1785
+ top: container.scrollHeight,
1786
+ behavior: "smooth"
1724
1787
  });
1725
- return /* @__PURE__ */ jsx(
1726
- motion.div,
1727
- {
1728
- ref: containerRef,
1729
- id: MESSAGES_CONTAINER_ID,
1730
- initial: { opacity: 0 },
1731
- animate: { opacity: 1 },
1732
- exit: { opacity: 0 },
1733
- transition: { duration: styles.animations.duration },
1734
- 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",
1735
- style: { background: styles.colors.messagesBackground },
1736
- children
1788
+ }, [containerRef]);
1789
+ useEffect(() => {
1790
+ const container = containerRef.current;
1791
+ if (!container) return;
1792
+ const handleScroll = () => {
1793
+ isUserScrollingRef.current = !isNearBottom();
1794
+ };
1795
+ container.addEventListener("scroll", handleScroll, { passive: true });
1796
+ return () => container.removeEventListener("scroll", handleScroll);
1797
+ }, [containerRef, isNearBottom]);
1798
+ useEffect(() => {
1799
+ const container = containerRef.current;
1800
+ if (!container) return;
1801
+ const currentHeight = container.scrollHeight;
1802
+ const heightChanged = currentHeight !== lastScrollHeightRef.current;
1803
+ if (heightChanged) {
1804
+ lastScrollHeightRef.current = currentHeight;
1805
+ if (!isUserScrollingRef.current || isNearBottom()) {
1806
+ scrollToBottom();
1737
1807
  }
1738
- );
1739
- }
1740
- );
1808
+ }
1809
+ });
1810
+ return /* @__PURE__ */ jsx(
1811
+ motion.div,
1812
+ {
1813
+ ref: containerRef,
1814
+ id: MESSAGES_CONTAINER_ID,
1815
+ initial: { opacity: 0 },
1816
+ animate: { opacity: 1 },
1817
+ exit: { opacity: 0 },
1818
+ transition: { duration: styles.animations.duration },
1819
+ 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",
1820
+ style: { background: styles.colors.messagesBackground },
1821
+ children
1822
+ }
1823
+ );
1824
+ });
1741
1825
  MessagesContainer.displayName = "MessagesContainer";
1742
1826
  function ConversationList({
1743
1827
  conversations,
@@ -2009,7 +2093,13 @@ var PromptInput = React3.forwardRef(
2009
2093
  }
2010
2094
  );
2011
2095
  PromptInput.displayName = "PromptInput";
2012
- var PromptInputTextarea = ({ className, onKeyDown, disableAutosize = false, placeholder, ...props }) => {
2096
+ var PromptInputTextarea = ({
2097
+ className,
2098
+ onKeyDown,
2099
+ disableAutosize = false,
2100
+ placeholder,
2101
+ ...props
2102
+ }) => {
2013
2103
  const { value, setValue, maxHeight, onSubmit, disabled } = usePromptInput();
2014
2104
  const textareaRef = React3.useRef(null);
2015
2105
  React3.useEffect(() => {
@@ -2042,7 +2132,14 @@ var PromptInputActions = ({
2042
2132
  children,
2043
2133
  className,
2044
2134
  ...props
2045
- }) => /* @__PURE__ */ jsx("div", { className: cn("crow-flex crow-items-center crow-gap-2", className), ...props, children });
2135
+ }) => /* @__PURE__ */ jsx(
2136
+ "div",
2137
+ {
2138
+ className: cn("crow-flex crow-items-center crow-gap-2", className),
2139
+ ...props,
2140
+ children
2141
+ }
2142
+ );
2046
2143
  var PromptInputAction = ({
2047
2144
  tooltip,
2048
2145
  children,
@@ -2089,7 +2186,13 @@ var PromptInputBox = React3.forwardRef(
2089
2186
  disabled: isLoading,
2090
2187
  ref: ref || promptBoxRef,
2091
2188
  children: [
2092
- /* @__PURE__ */ jsx("div", { className: "crow-transition-all crow-duration-300 crow-opacity-100", children: /* @__PURE__ */ jsx(PromptInputTextarea, { placeholder, className: "crow-text-base" }) }),
2189
+ /* @__PURE__ */ jsx("div", { className: "crow-transition-all crow-duration-300 crow-opacity-100", children: /* @__PURE__ */ jsx(
2190
+ PromptInputTextarea,
2191
+ {
2192
+ placeholder,
2193
+ className: "crow-text-base"
2194
+ }
2195
+ ) }),
2093
2196
  /* @__PURE__ */ jsxs(PromptInputActions, { className: "crow-flex crow-items-center crow-justify-between crow-gap-2 crow-p-0 crow-pt-1", children: [
2094
2197
  /* @__PURE__ */ jsx("div", { className: "crow-flex crow-items-center", children: availableModels.length > 0 && onModelChange && /* @__PURE__ */ jsx(
2095
2198
  ModelSelector,
@@ -2122,10 +2225,21 @@ var PromptInputBox = React3.forwardRef(
2122
2225
  handleSubmit();
2123
2226
  }
2124
2227
  },
2125
- children: isLoading ? /* @__PURE__ */ jsx(Square, { className: "crow-h-3.5 crow-w-3.5 crow-text-white", style: { fill: "white" } }) : /* @__PURE__ */ jsx(ArrowUp, { className: cn(
2126
- "crow-h-3.5 crow-w-3.5",
2127
- hasContent ? "crow-text-white" : "crow-text-gray-400"
2128
- ) })
2228
+ children: isLoading ? /* @__PURE__ */ jsx(
2229
+ Square,
2230
+ {
2231
+ className: "crow-h-3.5 crow-w-3.5 crow-text-white",
2232
+ style: { fill: "white" }
2233
+ }
2234
+ ) : /* @__PURE__ */ jsx(
2235
+ ArrowUp,
2236
+ {
2237
+ className: cn(
2238
+ "crow-h-3.5 crow-w-3.5",
2239
+ hasContent ? "crow-text-white" : "crow-text-gray-400"
2240
+ )
2241
+ }
2242
+ )
2129
2243
  }
2130
2244
  )
2131
2245
  }