@wingmanjs/react 0.1.1 → 1.0.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.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Hook that auto-scrolls a container to the bottom as new content streams in.
3
+ *
4
+ * Works with both shadcn ScrollArea (data-slot="scroll-area-viewport") and
5
+ * plain scrollable divs. Respects the user's scroll position — if they've
6
+ * scrolled up to read history, auto-scroll pauses until they scroll back
7
+ * near the bottom.
8
+ *
9
+ * @param deps - Reactive values that trigger a scroll check (e.g., messages, streaming content)
10
+ * @param threshold - Pixels from bottom to consider "at bottom" (default: 80)
11
+ * @returns ref to attach to the scroll container (or its wrapper)
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * const scrollRef = useAutoScroll([messages, streamingContent], 80);
16
+ * return <ScrollArea ref={scrollRef}>...</ScrollArea>;
17
+ * ```
18
+ */
19
+ export declare function useAutoScroll<T extends HTMLElement = HTMLDivElement>(deps: unknown[], threshold?: number): import("react").RefObject<T | null>;
20
+ //# sourceMappingURL=use-auto-scroll.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-auto-scroll.d.ts","sourceRoot":"","sources":["../../src/hooks/use-auto-scroll.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,WAAW,GAAG,cAAc,EAClE,IAAI,EAAE,OAAO,EAAE,EACf,SAAS,SAAK,uCA0Cf"}
@@ -0,0 +1,58 @@
1
+ import { useEffect, useRef, useCallback } from 'react';
2
+ /**
3
+ * Hook that auto-scrolls a container to the bottom as new content streams in.
4
+ *
5
+ * Works with both shadcn ScrollArea (data-slot="scroll-area-viewport") and
6
+ * plain scrollable divs. Respects the user's scroll position — if they've
7
+ * scrolled up to read history, auto-scroll pauses until they scroll back
8
+ * near the bottom.
9
+ *
10
+ * @param deps - Reactive values that trigger a scroll check (e.g., messages, streaming content)
11
+ * @param threshold - Pixels from bottom to consider "at bottom" (default: 80)
12
+ * @returns ref to attach to the scroll container (or its wrapper)
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * const scrollRef = useAutoScroll([messages, streamingContent], 80);
17
+ * return <ScrollArea ref={scrollRef}>...</ScrollArea>;
18
+ * ```
19
+ */
20
+ export function useAutoScroll(deps, threshold = 80) {
21
+ const containerRef = useRef(null);
22
+ const isUserScrolledUp = useRef(false);
23
+ // Resolve the actual scrollable element (handles shadcn ScrollArea wrapper)
24
+ const getScrollEl = useCallback(() => {
25
+ const el = containerRef.current;
26
+ if (!el)
27
+ return null;
28
+ // shadcn ScrollArea wraps the viewport in [data-slot="scroll-area-viewport"]
29
+ return el.querySelector('[data-slot="scroll-area-viewport"]') ?? el;
30
+ }, []);
31
+ // Track whether the user has scrolled away from the bottom
32
+ useEffect(() => {
33
+ const scrollEl = getScrollEl();
34
+ if (!scrollEl)
35
+ return;
36
+ const handleScroll = () => {
37
+ const { scrollTop, scrollHeight, clientHeight } = scrollEl;
38
+ const distanceFromBottom = scrollHeight - scrollTop - clientHeight;
39
+ isUserScrolledUp.current = distanceFromBottom > threshold;
40
+ };
41
+ scrollEl.addEventListener('scroll', handleScroll, { passive: true });
42
+ return () => scrollEl.removeEventListener('scroll', handleScroll);
43
+ }, [getScrollEl, threshold]);
44
+ // Auto-scroll when deps change, unless user has scrolled up
45
+ useEffect(() => {
46
+ if (isUserScrolledUp.current)
47
+ return;
48
+ const scrollEl = getScrollEl();
49
+ if (!scrollEl)
50
+ return;
51
+ // Use requestAnimationFrame for scroll after DOM paint
52
+ requestAnimationFrame(() => {
53
+ scrollEl.scrollTop = scrollEl.scrollHeight;
54
+ });
55
+ }, deps); // eslint-disable-line react-hooks/exhaustive-deps
56
+ return containerRef;
57
+ }
58
+ //# sourceMappingURL=use-auto-scroll.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-auto-scroll.js","sourceRoot":"","sources":["../../src/hooks/use-auto-scroll.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEvD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAe,EACf,SAAS,GAAG,EAAE;IAEd,MAAM,YAAY,GAAG,MAAM,CAAI,IAAI,CAAC,CAAC;IACrC,MAAM,gBAAgB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAEvC,4EAA4E;IAC5E,MAAM,WAAW,GAAG,WAAW,CAAC,GAAuB,EAAE;QACvD,MAAM,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC;QAChC,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACrB,6EAA6E;QAC7E,OAAO,EAAE,CAAC,aAAa,CAAc,oCAAoC,CAAC,IAAI,EAAE,CAAC;IACnF,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,2DAA2D;IAC3D,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,MAAM,YAAY,GAAG,GAAG,EAAE;YACxB,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAC;YAC3D,MAAM,kBAAkB,GAAG,YAAY,GAAG,SAAS,GAAG,YAAY,CAAC;YACnE,gBAAgB,CAAC,OAAO,GAAG,kBAAkB,GAAG,SAAS,CAAC;QAC5D,CAAC,CAAC;QAEF,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACpE,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;IAE7B,4DAA4D;IAC5D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,gBAAgB,CAAC,OAAO;YAAE,OAAO;QAErC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,uDAAuD;QACvD,qBAAqB,CAAC,GAAG,EAAE;YACzB,QAAQ,CAAC,SAAS,GAAG,QAAQ,CAAC,YAAY,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,kDAAkD;IAE5D,OAAO,YAAY,CAAC;AACtB,CAAC"}
package/dist/index.d.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  */
7
7
  export { ChatProvider, useChat } from './providers/chat-provider.js';
8
8
  export type { ChatProviderProps, ChatState, ChatContextValue } from './providers/chat-provider.js';
9
+ export { useAutoScroll } from './hooks/use-auto-scroll.js';
9
10
  export { ThemeProvider, useTheme } from './providers/theme-provider.js';
10
11
  export type { ThemeProviderProps, ThemeContextValue, WingmanTheme, WingmanThemeColors, } from './providers/theme-provider.js';
11
12
  export { ChatMessage } from './components/chat-message.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACrE,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEnG,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACxE,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,GACnB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,YAAY,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGzE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAQ/E,eAAO,MAAM,OAAO,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AACrE,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEnG,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACxE,YAAY,EACV,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,GACnB,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,YAAY,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,YAAY,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAGzE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAEvE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAQ/E,eAAO,MAAM,OAAO,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@
6
6
  */
7
7
  // Provider + hooks
8
8
  export { ChatProvider, useChat } from './providers/chat-provider.js';
9
+ export { useAutoScroll } from './hooks/use-auto-scroll.js';
9
10
  export { ThemeProvider, useTheme } from './providers/theme-provider.js';
10
11
  // Components
11
12
  export { ChatMessage } from './components/chat-message.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAGrE,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAQxE,aAAa;AACb,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG3D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGzD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAG/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAGrE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAG/D,qBAAqB;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGzD,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGzD,qCAAqC;AACrC,kEAAkE;AAClE,wDAAwD;AACxD,0DAA0D;AAC1D,wEAAwE;AAExE,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,mBAAmB;AACnB,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAGrE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAQxE,aAAa;AACb,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG3D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGzD,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAG/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAGrE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAG/D,qBAAqB;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGzD,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAGzD,qCAAqC;AACrC,kEAAkE;AAClE,wDAAwD;AACxD,0DAA0D;AAC1D,wEAAwE;AAExE,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wingmanjs/react",
3
- "version": "0.1.1",
3
+ "version": "1.0.0",
4
4
  "description": "React hooks and components for Wingman chat",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -30,6 +30,15 @@
30
30
  ],
31
31
  "author": "Eric Hansen",
32
32
  "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/ericchansen/wingman.git",
36
+ "directory": "packages/react"
37
+ },
38
+ "homepage": "https://github.com/ericchansen/wingman#readme",
39
+ "bugs": {
40
+ "url": "https://github.com/ericchansen/wingman/issues"
41
+ },
33
42
  "engines": {
34
43
  "node": ">=20.11.0"
35
44
  },
@@ -40,7 +49,7 @@
40
49
  "peerDependencies": {
41
50
  "react": "^19.0.0",
42
51
  "react-dom": "^19.0.0",
43
- "@wingmanjs/core": "0.1.1"
52
+ "@wingmanjs/core": "0.2.0"
44
53
  },
45
54
  "devDependencies": {
46
55
  "@types/react": "^19.0.0",