@guuey/chat 0.4.0 → 0.5.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.
- package/dist/native/components.d.ts +94 -0
- package/dist/native/components.d.ts.map +1 -0
- package/dist/native/components.js +292 -0
- package/dist/native/markdown.d.ts +31 -0
- package/dist/native/markdown.d.ts.map +1 -0
- package/dist/native/markdown.js +69 -0
- package/dist/native/theme-native.d.ts +27 -0
- package/dist/native/theme-native.d.ts.map +1 -0
- package/dist/native/theme-native.js +28 -0
- package/dist/native/transcript.d.ts +48 -0
- package/dist/native/transcript.d.ts.map +1 -0
- package/dist/native/transcript.js +86 -0
- package/dist/native.d.ts +26 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +27 -0
- package/package.json +16 -5
- package/src/native/components.tsx +677 -0
- package/src/native/markdown.tsx +205 -0
- package/src/native/theme-native.ts +48 -0
- package/src/native/transcript.tsx +188 -0
- package/src/native.tsx +62 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* `<NativeTranscript>` — the plan walker + the §3.2 renderer obligations,
|
|
4
|
+
* restated over React Native's own mechanics:
|
|
5
|
+
*
|
|
6
|
+
* - **Scroll contract, the inverted way.** The list is an INVERTED
|
|
7
|
+
* FlatList over the reversed plan (the chat-app contract portal's
|
|
8
|
+
* agent-chat screen ratified — guuey#94/#100): content grows at the
|
|
9
|
+
* scroll ORIGIN, so "stick to bottom while streaming" and "never shift
|
|
10
|
+
* the viewport while the reader is up in history" hold by construction
|
|
11
|
+
* — no scrollTo calls during streaming, no re-pin race with content
|
|
12
|
+
* resize (an R6 card growing at the origin cannot move the reader's
|
|
13
|
+
* viewport). "Release on scroll-up" is likewise structural; the kit
|
|
14
|
+
* adds the jump-to-latest affordance when the reader has left the
|
|
15
|
+
* newest turn, and its scroll animation respects the platform
|
|
16
|
+
* reduce-motion setting.
|
|
17
|
+
* - **Windowing** is the list primitive's own virtualization — FlatList
|
|
18
|
+
* windows the DOM-equivalent natively; the plan's stable keys are the
|
|
19
|
+
* `keyExtractor`, so item identity survives streaming updates.
|
|
20
|
+
* - **Accessibility** lives on the item components (`components.tsx`).
|
|
21
|
+
*
|
|
22
|
+
* Platform chrome (keyboard insets, dismiss modes, dock scroll policies)
|
|
23
|
+
* stays HOST-OWNED: `listProps` passes the host's FlatList behavior
|
|
24
|
+
* through, with the kit composing `onScroll` so both the host's policy and
|
|
25
|
+
* the jump affordance see every event. The kit owns data/renderItem/keys/
|
|
26
|
+
* inversion — a host overriding those would be fighting the plan.
|
|
27
|
+
*/
|
|
28
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
29
|
+
import { AccessibilityInfo, FlatList, Pressable, Text, View, } from "react-native";
|
|
30
|
+
import { DEFAULT_CHAT_THEME } from "../theme.js";
|
|
31
|
+
import { defaultChatStrings } from "../strings.js";
|
|
32
|
+
import { nativeTranscriptComponents, renderNativeItem, } from "./components.js";
|
|
33
|
+
import { resolveNativeTheme } from "./theme-native.js";
|
|
34
|
+
/** Offset (px) past which the reader counts as "up in history". */
|
|
35
|
+
const JUMP_THRESHOLD_PX = 160;
|
|
36
|
+
export function NativeTranscript(props) {
|
|
37
|
+
const { plan, components, strings = defaultChatStrings, theme = DEFAULT_CHAT_THEME, mode = "light", listProps, onToggle, onRetry, onPromptAction, onErrorAction, resolvedMounts, onViewPhase, } = props;
|
|
38
|
+
const tokens = useMemo(() => resolveNativeTheme(theme, mode), [theme, mode]);
|
|
39
|
+
const resolvedComponents = useMemo(() => ({ ...nativeTranscriptComponents, ...components }), [components]);
|
|
40
|
+
const ctx = useMemo(() => ({ strings, tokens, onToggle, onRetry, onPromptAction, onErrorAction, resolvedMounts, onViewPhase }), [strings, tokens, onToggle, onRetry, onPromptAction, onErrorAction, resolvedMounts, onViewPhase]);
|
|
41
|
+
// Inverted-list data: reversed plan, newest at index 0 (the visual
|
|
42
|
+
// bottom / scroll origin). Keys are the plan's stable keys.
|
|
43
|
+
const data = useMemo(() => [...plan.items].reverse(), [plan.items]);
|
|
44
|
+
// Reduce motion: the ONE animation the kit owns is the jump scroll.
|
|
45
|
+
const [reduceMotion, setReduceMotion] = useState(false);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
let alive = true;
|
|
48
|
+
void AccessibilityInfo.isReduceMotionEnabled().then((v) => {
|
|
49
|
+
if (alive)
|
|
50
|
+
setReduceMotion(v);
|
|
51
|
+
});
|
|
52
|
+
const sub = AccessibilityInfo.addEventListener("reduceMotionChanged", setReduceMotion);
|
|
53
|
+
return () => {
|
|
54
|
+
alive = false;
|
|
55
|
+
sub.remove();
|
|
56
|
+
};
|
|
57
|
+
}, []);
|
|
58
|
+
const listRef = useRef(null);
|
|
59
|
+
const [showJump, setShowJump] = useState(false);
|
|
60
|
+
const hostOnScroll = listProps?.onScroll;
|
|
61
|
+
const onScroll = useCallback((e) => {
|
|
62
|
+
// Inverted coordinates: offset 0 IS the newest turn.
|
|
63
|
+
setShowJump(e.nativeEvent.contentOffset.y > JUMP_THRESHOLD_PX);
|
|
64
|
+
hostOnScroll?.(e);
|
|
65
|
+
}, [hostOnScroll]);
|
|
66
|
+
const StatusComponent = resolvedComponents.status;
|
|
67
|
+
return (_jsxs(View, { style: { flex: 1, backgroundColor: tokens.palette.canvas }, children: [_jsx(FlatList, { ref: listRef, ...listProps, onScroll: onScroll, scrollEventThrottle: listProps?.scrollEventThrottle ?? 16,
|
|
68
|
+
// Inverted only while non-empty: an inverted ListEmptyComponent
|
|
69
|
+
// renders upside-down (RN gotcha — portal's receipt).
|
|
70
|
+
inverted: data.length > 0, data: data, keyExtractor: (item) => item.key, renderItem: ({ item }) => (_jsx(View, { style: { paddingVertical: tokens.gap / 2 }, children: renderNativeItem(item, resolvedComponents, ctx) })),
|
|
71
|
+
// Inverted list: the header renders at the VISUAL BOTTOM — where
|
|
72
|
+
// the live status line belongs.
|
|
73
|
+
ListHeaderComponent: plan.status !== null ? _jsx(StatusComponent, { item: plan.status, ctx: ctx }) : null }), showJump ? (_jsx(Pressable, { accessibilityRole: "button", onPress: () => {
|
|
74
|
+
setShowJump(false);
|
|
75
|
+
listRef.current?.scrollToOffset({ offset: 0, animated: !reduceMotion });
|
|
76
|
+
}, style: {
|
|
77
|
+
position: "absolute",
|
|
78
|
+
bottom: 12,
|
|
79
|
+
alignSelf: "center",
|
|
80
|
+
backgroundColor: tokens.palette.surface,
|
|
81
|
+
borderRadius: 999,
|
|
82
|
+
paddingHorizontal: 14,
|
|
83
|
+
paddingVertical: 8,
|
|
84
|
+
elevation: 3,
|
|
85
|
+
}, children: _jsx(Text, { style: { color: tokens.palette.ink, fontSize: tokens.fontSize - 2, fontFamily: tokens.fontFamily }, children: strings.jumpToLatest }) })) : null] }));
|
|
86
|
+
}
|
package/dist/native.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Native entry point (`@guuey/chat/native`) — the RN renderer over
|
|
3
|
+
* the SAME headless view-model as `./react` (wave 3c, guuey#135).
|
|
4
|
+
*
|
|
5
|
+
* Zero duplication by construction: the view-model, policies, theme
|
|
6
|
+
* schema, and strings are the root subpath's exports, and the
|
|
7
|
+
* renderer-state hooks (`useTranscript`, `useTranscriptInputs`) are the
|
|
8
|
+
* SAME modules the web kit uses — they are React-generic (no DOM), so both
|
|
9
|
+
* arms share one implementation. Only the walk differs: RN primitives, the
|
|
10
|
+
* inverted-list scroll contract, and the schema's native theme projection
|
|
11
|
+
* (`resolveNativeTheme` — CSS custom properties are the web projection).
|
|
12
|
+
*
|
|
13
|
+
* The R6 default is the documented native default-gap: this tier ships
|
|
14
|
+
* WITHOUT a WebView dependency, so `view` is a required override (a
|
|
15
|
+
* labeled placeholder renders otherwise — never blank). See
|
|
16
|
+
* `native/components.tsx`.
|
|
17
|
+
*
|
|
18
|
+
* `react` and `react-native` are OPTIONAL peers — the root subpath stays
|
|
19
|
+
* importable everywhere; this arm loads only inside an RN runtime.
|
|
20
|
+
*/
|
|
21
|
+
export { NativeTranscript, type NativeTranscriptProps, type NativeTranscriptListProps, } from "./native/transcript.js";
|
|
22
|
+
export { nativeTranscriptComponents, renderNativeItem, NativeUserMessage, NativeText, NativeReasoning, NativeTool, NativeToolGroup, NativeDataResult, NativeView, NativeMedia, NativeCode, NativeCitations, NativePrompt, NativeError, NativeHistoryBoundary, NativeCompaction, NativeUnknown, NativeStatus, type NativeTranscriptComponents, type NativeTranscriptItemContext, } from "./native/components.js";
|
|
23
|
+
export { NativeMarkdown } from "./native/markdown.js";
|
|
24
|
+
export { resolveNativeTheme, type NativeChatTokens, type NativeThemeMode, } from "./native/theme-native.js";
|
|
25
|
+
export { useTranscript, useTranscriptInputs, type UseTranscriptArgs, type UseTranscriptResult, type UseTranscriptInputsResult, } from "./react/use-transcript.js";
|
|
26
|
+
//# sourceMappingURL=native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,GAC/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,0BAA0B,EAC1B,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,UAAU,EACV,eAAe,EACf,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,GACjC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,GAC/B,MAAM,2BAA2B,CAAC"}
|
package/dist/native.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Native entry point (`@guuey/chat/native`) — the RN renderer over
|
|
3
|
+
* the SAME headless view-model as `./react` (wave 3c, guuey#135).
|
|
4
|
+
*
|
|
5
|
+
* Zero duplication by construction: the view-model, policies, theme
|
|
6
|
+
* schema, and strings are the root subpath's exports, and the
|
|
7
|
+
* renderer-state hooks (`useTranscript`, `useTranscriptInputs`) are the
|
|
8
|
+
* SAME modules the web kit uses — they are React-generic (no DOM), so both
|
|
9
|
+
* arms share one implementation. Only the walk differs: RN primitives, the
|
|
10
|
+
* inverted-list scroll contract, and the schema's native theme projection
|
|
11
|
+
* (`resolveNativeTheme` — CSS custom properties are the web projection).
|
|
12
|
+
*
|
|
13
|
+
* The R6 default is the documented native default-gap: this tier ships
|
|
14
|
+
* WITHOUT a WebView dependency, so `view` is a required override (a
|
|
15
|
+
* labeled placeholder renders otherwise — never blank). See
|
|
16
|
+
* `native/components.tsx`.
|
|
17
|
+
*
|
|
18
|
+
* `react` and `react-native` are OPTIONAL peers — the root subpath stays
|
|
19
|
+
* importable everywhere; this arm loads only inside an RN runtime.
|
|
20
|
+
*/
|
|
21
|
+
export { NativeTranscript, } from "./native/transcript.js";
|
|
22
|
+
export { nativeTranscriptComponents, renderNativeItem, NativeUserMessage, NativeText, NativeReasoning, NativeTool, NativeToolGroup, NativeDataResult, NativeView, NativeMedia, NativeCode, NativeCitations, NativePrompt, NativeError, NativeHistoryBoundary, NativeCompaction, NativeUnknown, NativeStatus, } from "./native/components.js";
|
|
23
|
+
export { NativeMarkdown } from "./native/markdown.js";
|
|
24
|
+
export { resolveNativeTheme, } from "./native/theme-native.js";
|
|
25
|
+
// The React-generic renderer-state owner + live assembler — shared with
|
|
26
|
+
// the web kit (one implementation, two walks).
|
|
27
|
+
export { useTranscript, useTranscriptInputs, } from "./react/use-transcript.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guuey/chat",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "The default end-user transcript UI for guuey agents — the headless view-model (planTranscript), calm/debug presets, the GuueyChatTheme token schema, the ChatStrings i18n seam, and (at ./react) the component kit that renders it: per-category components, <Transcript>, the live + history input assemblers, and stick-to-bottom/windowed/accessible transcript behavior.",
|
|
3
|
+
"version": "0.5.0",
|
|
4
|
+
"description": "The default end-user transcript UI for guuey agents — the headless view-model (planTranscript), calm/debug presets, the GuueyChatTheme token schema, the ChatStrings i18n seam, and (at ./react) the component kit that renders it: per-category components, <Transcript>, the live + history input assemblers, and stick-to-bottom/windowed/accessible transcript behavior; at ./native, the React Native renderer over the same view-model.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -27,21 +27,31 @@
|
|
|
27
27
|
"import": "./dist/react.js",
|
|
28
28
|
"default": "./dist/react.js"
|
|
29
29
|
},
|
|
30
|
+
"./native": {
|
|
31
|
+
"react-native": "./src/native.tsx",
|
|
32
|
+
"types": "./dist/native.d.ts",
|
|
33
|
+
"import": "./dist/native.js",
|
|
34
|
+
"default": "./dist/native.js"
|
|
35
|
+
},
|
|
30
36
|
"./styles.css": "./styles.css"
|
|
31
37
|
},
|
|
32
38
|
"dependencies": {
|
|
33
39
|
"@silverprotocol/core": "0.4.1",
|
|
34
40
|
"@silverprotocol/richtext": "0.4.1",
|
|
35
41
|
"zod": "^4.3.6",
|
|
36
|
-
"@guuey/agent-client": "0.
|
|
37
|
-
"@guuey/mcp-apps-host": "0.
|
|
42
|
+
"@guuey/agent-client": "0.5.0",
|
|
43
|
+
"@guuey/mcp-apps-host": "0.5.0"
|
|
38
44
|
},
|
|
39
45
|
"peerDependencies": {
|
|
40
|
-
"react": ">=18"
|
|
46
|
+
"react": ">=18",
|
|
47
|
+
"react-native": ">=0.76"
|
|
41
48
|
},
|
|
42
49
|
"peerDependenciesMeta": {
|
|
43
50
|
"react": {
|
|
44
51
|
"optional": true
|
|
52
|
+
},
|
|
53
|
+
"react-native": {
|
|
54
|
+
"optional": true
|
|
45
55
|
}
|
|
46
56
|
},
|
|
47
57
|
"devDependencies": {
|
|
@@ -52,6 +62,7 @@
|
|
|
52
62
|
"jsdom": "^25.0.1",
|
|
53
63
|
"react": "^19.0.0",
|
|
54
64
|
"react-dom": "^19.0.0",
|
|
65
|
+
"react-native": "0.81.5",
|
|
55
66
|
"typescript": "^5.0.0",
|
|
56
67
|
"vitest": "^3.0.0"
|
|
57
68
|
},
|