dynim-react 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.
Files changed (47) hide show
  1. package/README.md +447 -0
  2. package/dist/builder/BuilderProvider.d.ts +99 -0
  3. package/dist/builder/BuilderProvider.d.ts.map +1 -0
  4. package/dist/builder/BuilderProvider.js +339 -0
  5. package/dist/builder/ChatContext.d.ts +11 -0
  6. package/dist/builder/ChatContext.d.ts.map +1 -0
  7. package/dist/builder/ChatContext.js +18 -0
  8. package/dist/builder/ChatInput.d.ts +11 -0
  9. package/dist/builder/ChatInput.d.ts.map +1 -0
  10. package/dist/builder/ChatInput.js +20 -0
  11. package/dist/builder/CodeChatPanel.d.ts +24 -0
  12. package/dist/builder/CodeChatPanel.d.ts.map +1 -0
  13. package/dist/builder/CodeChatPanel.js +299 -0
  14. package/dist/builder/EditableZone.d.ts +73 -0
  15. package/dist/builder/EditableZone.d.ts.map +1 -0
  16. package/dist/builder/EditableZone.js +83 -0
  17. package/dist/builder/MessageList.d.ts +14 -0
  18. package/dist/builder/MessageList.d.ts.map +1 -0
  19. package/dist/builder/MessageList.js +23 -0
  20. package/dist/builder/index.d.ts +18 -0
  21. package/dist/builder/index.d.ts.map +1 -0
  22. package/dist/builder/index.js +15 -0
  23. package/dist/builder/useChatbot.d.ts +24 -0
  24. package/dist/builder/useChatbot.d.ts.map +1 -0
  25. package/dist/builder/useChatbot.js +85 -0
  26. package/dist/index.d.ts +14 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +24 -0
  29. package/dist/inference/DynimProvider.d.ts +23 -0
  30. package/dist/inference/DynimProvider.d.ts.map +1 -0
  31. package/dist/inference/DynimProvider.js +231 -0
  32. package/dist/inference/InferenceProvider.d.ts +23 -0
  33. package/dist/inference/InferenceProvider.d.ts.map +1 -0
  34. package/dist/inference/InferenceProvider.js +270 -0
  35. package/dist/inference/createDynimSDK.d.ts +39 -0
  36. package/dist/inference/createDynimSDK.d.ts.map +1 -0
  37. package/dist/inference/createDynimSDK.js +61 -0
  38. package/dist/inference/index.d.ts +7 -0
  39. package/dist/inference/index.d.ts.map +1 -0
  40. package/dist/inference/index.js +7 -0
  41. package/dist/inference/sharedContext.d.ts +39 -0
  42. package/dist/inference/sharedContext.d.ts.map +1 -0
  43. package/dist/inference/sharedContext.js +61 -0
  44. package/dist/inference/types.d.ts +67 -0
  45. package/dist/inference/types.d.ts.map +1 -0
  46. package/dist/inference/types.js +1 -0
  47. package/package.json +30 -0
@@ -0,0 +1,299 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * CodeChatPanel - Self-contained code chat UI component
4
+ *
5
+ * Handles all the complexity internally:
6
+ * - Streaming responses with thinking/text differentiation
7
+ * - Code edit display with accept/reject
8
+ * - Loading states, errors
9
+ *
10
+ * Consuming app just drops this in and it works.
11
+ */
12
+ import { useState, useCallback, useRef, useEffect } from 'react';
13
+ import { useBuilder } from './BuilderProvider';
14
+ // Inline styles to make component self-contained
15
+ const styles = {
16
+ container: {
17
+ display: 'flex',
18
+ flexDirection: 'column',
19
+ height: '100%',
20
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
21
+ fontSize: '14px',
22
+ backgroundColor: '#fafafa',
23
+ borderRadius: '8px',
24
+ overflow: 'hidden',
25
+ },
26
+ messagesArea: {
27
+ flex: 1,
28
+ overflowY: 'auto',
29
+ padding: '16px',
30
+ },
31
+ messageBlock: {
32
+ marginBottom: '16px',
33
+ },
34
+ thinkingSection: {
35
+ marginBottom: '12px',
36
+ },
37
+ thinkingHeader: {
38
+ display: 'flex',
39
+ alignItems: 'center',
40
+ gap: '8px',
41
+ padding: '8px 12px',
42
+ backgroundColor: '#f0f0f0',
43
+ borderRadius: '6px',
44
+ cursor: 'pointer',
45
+ userSelect: 'none',
46
+ fontSize: '13px',
47
+ color: '#666',
48
+ },
49
+ thinkingContent: {
50
+ padding: '12px',
51
+ backgroundColor: '#f8f8f8',
52
+ borderRadius: '0 0 6px 6px',
53
+ borderLeft: '3px solid #ddd',
54
+ marginTop: '-6px',
55
+ fontSize: '13px',
56
+ color: '#555',
57
+ whiteSpace: 'pre-wrap',
58
+ lineHeight: '1.5',
59
+ },
60
+ responseText: {
61
+ padding: '12px 16px',
62
+ backgroundColor: '#fff',
63
+ borderRadius: '8px',
64
+ border: '1px solid #e0e0e0',
65
+ whiteSpace: 'pre-wrap',
66
+ lineHeight: '1.6',
67
+ },
68
+ editsSection: {
69
+ marginTop: '16px',
70
+ },
71
+ editsHeader: {
72
+ display: 'flex',
73
+ alignItems: 'center',
74
+ justifyContent: 'space-between',
75
+ marginBottom: '12px',
76
+ },
77
+ editsTitle: {
78
+ fontWeight: 600,
79
+ color: '#333',
80
+ },
81
+ editsActions: {
82
+ display: 'flex',
83
+ gap: '8px',
84
+ },
85
+ editCard: {
86
+ backgroundColor: '#fff',
87
+ border: '1px solid #e0e0e0',
88
+ borderRadius: '6px',
89
+ marginBottom: '8px',
90
+ overflow: 'hidden',
91
+ },
92
+ editHeader: {
93
+ display: 'flex',
94
+ alignItems: 'center',
95
+ justifyContent: 'space-between',
96
+ padding: '8px 12px',
97
+ backgroundColor: '#f5f5f5',
98
+ borderBottom: '1px solid #e0e0e0',
99
+ },
100
+ editPath: {
101
+ fontFamily: 'monospace',
102
+ fontSize: '12px',
103
+ color: '#666',
104
+ },
105
+ editType: {
106
+ fontSize: '11px',
107
+ padding: '2px 6px',
108
+ borderRadius: '3px',
109
+ fontWeight: 500,
110
+ },
111
+ editTypeCreate: {
112
+ backgroundColor: '#d4edda',
113
+ color: '#155724',
114
+ },
115
+ editTypeReplace: {
116
+ backgroundColor: '#fff3cd',
117
+ color: '#856404',
118
+ },
119
+ editTypeDelete: {
120
+ backgroundColor: '#f8d7da',
121
+ color: '#721c24',
122
+ },
123
+ editContent: {
124
+ padding: '8px 12px',
125
+ fontFamily: 'monospace',
126
+ fontSize: '12px',
127
+ maxHeight: '200px',
128
+ overflowY: 'auto',
129
+ },
130
+ diffLine: {
131
+ padding: '1px 4px',
132
+ whiteSpace: 'pre',
133
+ },
134
+ diffAdd: {
135
+ backgroundColor: '#d4edda',
136
+ color: '#155724',
137
+ },
138
+ diffRemove: {
139
+ backgroundColor: '#f8d7da',
140
+ color: '#721c24',
141
+ },
142
+ button: {
143
+ padding: '6px 12px',
144
+ borderRadius: '4px',
145
+ border: 'none',
146
+ cursor: 'pointer',
147
+ fontSize: '13px',
148
+ fontWeight: 500,
149
+ transition: 'background-color 0.2s',
150
+ },
151
+ buttonPrimary: {
152
+ backgroundColor: '#4CAF50',
153
+ color: '#fff',
154
+ },
155
+ buttonSecondary: {
156
+ backgroundColor: '#f0f0f0',
157
+ color: '#333',
158
+ },
159
+ buttonDisabled: {
160
+ opacity: 0.5,
161
+ cursor: 'not-allowed',
162
+ },
163
+ inputArea: {
164
+ padding: '12px 16px',
165
+ borderTop: '1px solid #e0e0e0',
166
+ backgroundColor: '#fff',
167
+ },
168
+ form: {
169
+ display: 'flex',
170
+ gap: '8px',
171
+ },
172
+ input: {
173
+ flex: 1,
174
+ padding: '10px 14px',
175
+ borderRadius: '6px',
176
+ border: '1px solid #ddd',
177
+ fontSize: '14px',
178
+ outline: 'none',
179
+ },
180
+ statusBar: {
181
+ padding: '8px 16px',
182
+ fontSize: '12px',
183
+ color: '#666',
184
+ backgroundColor: '#f5f5f5',
185
+ borderTop: '1px solid #e0e0e0',
186
+ },
187
+ streamingDot: {
188
+ display: 'inline-block',
189
+ width: '8px',
190
+ height: '8px',
191
+ borderRadius: '50%',
192
+ backgroundColor: '#4CAF50',
193
+ marginRight: '8px',
194
+ animation: 'pulse 1s infinite',
195
+ },
196
+ errorBar: {
197
+ padding: '12px 16px',
198
+ backgroundColor: '#f8d7da',
199
+ color: '#721c24',
200
+ borderTop: '1px solid #f5c6cb',
201
+ },
202
+ emptyState: {
203
+ display: 'flex',
204
+ alignItems: 'center',
205
+ justifyContent: 'center',
206
+ height: '100%',
207
+ color: '#999',
208
+ fontSize: '14px',
209
+ },
210
+ };
211
+ export function CodeChatPanel({ placeholder = 'Ask me to make changes to your code...', className = '', onSave, onAbandon, onError, }) {
212
+ const { sendCode, saveCode, abandonCode, codeMessage } = useBuilder();
213
+ const [inputValue, setInputValue] = useState('');
214
+ const [thinkingExpanded, setThinkingExpanded] = useState(false);
215
+ const [isSaving, setIsSaving] = useState(false);
216
+ const messagesRef = useRef(null);
217
+ const { thinking, text, edits, status, error } = codeMessage;
218
+ // Auto-scroll on new content
219
+ useEffect(() => {
220
+ if (messagesRef.current) {
221
+ messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
222
+ }
223
+ }, [thinking, text, edits]);
224
+ // Notify on errors
225
+ useEffect(() => {
226
+ if (error) {
227
+ onError?.(error);
228
+ }
229
+ }, [error, onError]);
230
+ const handleSubmit = useCallback(async (e) => {
231
+ e.preventDefault();
232
+ const query = inputValue.trim();
233
+ if (!query || status === 'streaming')
234
+ return;
235
+ setInputValue('');
236
+ setThinkingExpanded(false);
237
+ await sendCode(query);
238
+ }, [inputValue, status, sendCode]);
239
+ const handleSave = useCallback(async () => {
240
+ setIsSaving(true);
241
+ try {
242
+ await saveCode();
243
+ onSave?.();
244
+ }
245
+ catch (err) {
246
+ onError?.(err.message);
247
+ }
248
+ finally {
249
+ setIsSaving(false);
250
+ }
251
+ }, [saveCode, onSave, onError]);
252
+ const handleAbandon = useCallback(async () => {
253
+ setIsSaving(true);
254
+ try {
255
+ await abandonCode();
256
+ onAbandon?.();
257
+ }
258
+ catch (err) {
259
+ onError?.(err.message);
260
+ }
261
+ finally {
262
+ setIsSaving(false);
263
+ }
264
+ }, [abandonCode, onAbandon, onError]);
265
+ const isStreaming = status === 'streaming';
266
+ const hasContent = thinking || text || edits.length > 0;
267
+ const hasEdits = edits.length > 0;
268
+ return (_jsxs("div", { style: styles.container, className: className, children: [_jsx("style", { children: `
269
+ @keyframes pulse {
270
+ 0%, 100% { opacity: 1; }
271
+ 50% { opacity: 0.4; }
272
+ }
273
+ ` }), _jsxs("div", { ref: messagesRef, style: styles.messagesArea, children: [!hasContent && status === 'idle' && (_jsx("div", { style: styles.emptyState, children: "Send a message to start editing code" })), hasContent && (_jsxs("div", { style: styles.messageBlock, children: [thinking && (_jsxs("div", { style: styles.thinkingSection, children: [_jsxs("div", { style: styles.thinkingHeader, onClick: () => setThinkingExpanded(!thinkingExpanded), children: [_jsx("span", { children: thinkingExpanded ? '▼' : '▶' }), _jsx("span", { children: "Thinking..." }), _jsxs("span", { style: { marginLeft: 'auto', fontSize: '11px' }, children: [thinking.length, " chars"] })] }), thinkingExpanded && (_jsx("div", { style: styles.thinkingContent, children: thinking }))] })), text && _jsx("div", { style: styles.responseText, children: text }), hasEdits && (_jsxs("div", { style: styles.editsSection, children: [_jsxs("div", { style: styles.editsHeader, children: [_jsxs("span", { style: styles.editsTitle, children: [edits.length, " file", edits.length !== 1 ? 's' : '', " changed"] }), status === 'done' && (_jsxs("div", { style: styles.editsActions, children: [_jsx("button", { style: {
274
+ ...styles.button,
275
+ ...styles.buttonSecondary,
276
+ ...(isSaving ? styles.buttonDisabled : {}),
277
+ }, onClick: handleAbandon, disabled: isSaving, children: "Reject" }), _jsx("button", { style: {
278
+ ...styles.button,
279
+ ...styles.buttonPrimary,
280
+ ...(isSaving ? styles.buttonDisabled : {}),
281
+ }, onClick: handleSave, disabled: isSaving, children: "Accept Changes" })] }))] }), edits.map((edit, index) => (_jsx(EditCard, { edit: edit }, `${edit.file_path}-${index}`)))] }))] }))] }), isStreaming && (_jsxs("div", { style: styles.statusBar, children: [_jsx("span", { style: styles.streamingDot }), "Generating response..."] })), status === 'error' && error && (_jsx("div", { style: styles.errorBar, children: error })), _jsx("div", { style: styles.inputArea, children: _jsxs("form", { style: styles.form, onSubmit: handleSubmit, children: [_jsx("input", { type: "text", style: styles.input, placeholder: placeholder, value: inputValue, onChange: (e) => setInputValue(e.target.value), disabled: isStreaming }), _jsx("button", { type: "submit", style: {
282
+ ...styles.button,
283
+ ...styles.buttonPrimary,
284
+ ...(isStreaming || !inputValue.trim() ? styles.buttonDisabled : {}),
285
+ }, disabled: isStreaming || !inputValue.trim(), children: "Send" })] }) })] }));
286
+ }
287
+ /** Individual edit card component */
288
+ function EditCard({ edit }) {
289
+ const [expanded, setExpanded] = useState(true);
290
+ const typeStyle = {
291
+ ...styles.editType,
292
+ ...(edit.type === 'create'
293
+ ? styles.editTypeCreate
294
+ : edit.type === 'delete'
295
+ ? styles.editTypeDelete
296
+ : styles.editTypeReplace),
297
+ };
298
+ return (_jsxs("div", { style: styles.editCard, children: [_jsxs("div", { style: { ...styles.editHeader, cursor: 'pointer' }, onClick: () => setExpanded(!expanded), children: [_jsxs("span", { style: styles.editPath, children: [expanded ? '▼' : '▶', " ", edit.file_path] }), _jsx("span", { style: typeStyle, children: edit.type })] }), expanded && (_jsxs("div", { style: styles.editContent, children: [edit.type === 'delete' && edit.old_content && (_jsx("div", { children: edit.old_content.split('\n').map((line, i) => (_jsxs("div", { style: { ...styles.diffLine, ...styles.diffRemove }, children: ["- ", line] }, i))) })), edit.type === 'create' && edit.new_content && (_jsx("div", { children: edit.new_content.split('\n').map((line, i) => (_jsxs("div", { style: { ...styles.diffLine, ...styles.diffAdd }, children: ["+ ", line] }, i))) })), edit.type === 'replace' && (_jsxs("div", { children: [edit.old_content?.split('\n').map((line, i) => (_jsxs("div", { style: { ...styles.diffLine, ...styles.diffRemove }, children: ["- ", line] }, `old-${i}`))), edit.new_content?.split('\n').map((line, i) => (_jsxs("div", { style: { ...styles.diffLine, ...styles.diffAdd }, children: ["+ ", line] }, `new-${i}`)))] }))] }))] }));
299
+ }
@@ -0,0 +1,73 @@
1
+ import { type ReactNode, type HTMLAttributes } from 'react';
2
+ /**
3
+ * Props for zone wrapper components
4
+ */
5
+ export interface ZoneProps extends HTMLAttributes<HTMLDivElement> {
6
+ /** Content to wrap */
7
+ children: ReactNode;
8
+ /** HTML tag to render (default: 'div') */
9
+ as?: keyof JSX.IntrinsicElements;
10
+ }
11
+ /**
12
+ * LockedZone - Wraps content to prevent builder customization
13
+ *
14
+ * Elements inside a LockedZone cannot be:
15
+ * - Dragged/moved by the builder
16
+ * - Used as drop targets
17
+ *
18
+ * Use this to protect parts of your UI that should not be editable,
19
+ * like navigation, footers, or critical UI elements.
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * <LockedZone>
24
+ * <Navigation /> {/* Cannot be moved or modified *\/}
25
+ * </LockedZone>
26
+ *
27
+ * <div>
28
+ * {/* This content is editable *\/}
29
+ * </div>
30
+ * ```
31
+ *
32
+ * @example Nested zones
33
+ * ```tsx
34
+ * <LockedZone>
35
+ * <Sidebar>
36
+ * <Logo /> {/* Locked *\/}
37
+ * <EditableZone>
38
+ * <CustomWidgets /> {/* Editable "island" inside locked zone *\/}
39
+ * </EditableZone>
40
+ * </Sidebar>
41
+ * </LockedZone>
42
+ * ```
43
+ */
44
+ export declare const LockedZone: import("react").ForwardRefExoticComponent<ZoneProps & import("react").RefAttributes<HTMLDivElement>>;
45
+ /**
46
+ * EditableZone - Explicitly marks content as editable in the builder
47
+ *
48
+ * Use this to:
49
+ * - Create editable "islands" inside a LockedZone
50
+ * - Explicitly mark content as editable (though content is editable by default)
51
+ *
52
+ * @example Create editable area inside locked zone
53
+ * ```tsx
54
+ * <LockedZone>
55
+ * <Header>
56
+ * <Logo /> {/* Locked *\/}
57
+ * <EditableZone>
58
+ * <UserMenu /> {/* Editable despite being inside LockedZone *\/}
59
+ * </EditableZone>
60
+ * </Header>
61
+ * </LockedZone>
62
+ * ```
63
+ */
64
+ export declare const EditableZone: import("react").ForwardRefExoticComponent<ZoneProps & import("react").RefAttributes<HTMLDivElement>>;
65
+ /**
66
+ * Alias for LockedZone - more explicit naming
67
+ */
68
+ export declare const NonCustomizable: import("react").ForwardRefExoticComponent<ZoneProps & import("react").RefAttributes<HTMLDivElement>>;
69
+ /**
70
+ * Alias for EditableZone - more explicit naming
71
+ */
72
+ export declare const Customizable: import("react").ForwardRefExoticComponent<ZoneProps & import("react").RefAttributes<HTMLDivElement>>;
73
+ //# sourceMappingURL=EditableZone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EditableZone.d.ts","sourceRoot":"","sources":["../../src/builder/EditableZone.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,EAAc,MAAM,OAAO,CAAC;AAGxE;;GAEG;AACH,MAAM,WAAW,SAAU,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC/D,sBAAsB;IACtB,QAAQ,EAAE,SAAS,CAAC;IACpB,0CAA0C;IAC1C,EAAE,CAAC,EAAE,MAAM,GAAG,CAAC,iBAAiB,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,UAAU,sGAYtB,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,YAAY,sGAYxB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,sGAAa,CAAC;AAE1C;;GAEG;AACH,eAAO,MAAM,YAAY,sGAAe,CAAC"}
@@ -0,0 +1,83 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { forwardRef } from 'react';
3
+ import { VISIBILITY_ATTR } from 'dynim-core';
4
+ /**
5
+ * LockedZone - Wraps content to prevent builder customization
6
+ *
7
+ * Elements inside a LockedZone cannot be:
8
+ * - Dragged/moved by the builder
9
+ * - Used as drop targets
10
+ *
11
+ * Use this to protect parts of your UI that should not be editable,
12
+ * like navigation, footers, or critical UI elements.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * <LockedZone>
17
+ * <Navigation /> {/* Cannot be moved or modified *\/}
18
+ * </LockedZone>
19
+ *
20
+ * <div>
21
+ * {/* This content is editable *\/}
22
+ * </div>
23
+ * ```
24
+ *
25
+ * @example Nested zones
26
+ * ```tsx
27
+ * <LockedZone>
28
+ * <Sidebar>
29
+ * <Logo /> {/* Locked *\/}
30
+ * <EditableZone>
31
+ * <CustomWidgets /> {/* Editable "island" inside locked zone *\/}
32
+ * </EditableZone>
33
+ * </Sidebar>
34
+ * </LockedZone>
35
+ * ```
36
+ */
37
+ export const LockedZone = forwardRef(function LockedZone({ children, as: Component = 'div', ...props }, ref) {
38
+ const zoneProps = {
39
+ ...props,
40
+ [VISIBILITY_ATTR]: 'false',
41
+ ref,
42
+ };
43
+ // Use createElement to support dynamic tag
44
+ const Element = Component;
45
+ return _jsx(Element, { ...zoneProps, children: children });
46
+ });
47
+ /**
48
+ * EditableZone - Explicitly marks content as editable in the builder
49
+ *
50
+ * Use this to:
51
+ * - Create editable "islands" inside a LockedZone
52
+ * - Explicitly mark content as editable (though content is editable by default)
53
+ *
54
+ * @example Create editable area inside locked zone
55
+ * ```tsx
56
+ * <LockedZone>
57
+ * <Header>
58
+ * <Logo /> {/* Locked *\/}
59
+ * <EditableZone>
60
+ * <UserMenu /> {/* Editable despite being inside LockedZone *\/}
61
+ * </EditableZone>
62
+ * </Header>
63
+ * </LockedZone>
64
+ * ```
65
+ */
66
+ export const EditableZone = forwardRef(function EditableZone({ children, as: Component = 'div', ...props }, ref) {
67
+ const zoneProps = {
68
+ ...props,
69
+ [VISIBILITY_ATTR]: 'true',
70
+ ref,
71
+ };
72
+ // Use createElement to support dynamic tag
73
+ const Element = Component;
74
+ return _jsx(Element, { ...zoneProps, children: children });
75
+ });
76
+ /**
77
+ * Alias for LockedZone - more explicit naming
78
+ */
79
+ export const NonCustomizable = LockedZone;
80
+ /**
81
+ * Alias for EditableZone - more explicit naming
82
+ */
83
+ export const Customizable = EditableZone;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Message list component
3
+ * Renders messages with optional custom renderer
4
+ */
5
+ import { type ReactNode } from 'react';
6
+ import type { Message } from 'dynim-core';
7
+ export interface MessageListProps {
8
+ className?: string;
9
+ renderMessage?: (message: Message) => ReactNode;
10
+ showAvatars?: boolean;
11
+ showTimestamps?: boolean;
12
+ }
13
+ export declare function MessageList({ className, renderMessage, showAvatars, showTimestamps, }: MessageListProps): JSX.Element;
14
+ //# sourceMappingURL=MessageList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/builder/MessageList.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAE1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,SAAS,CAAC;IAChD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,WAAW,CAAC,EAC1B,SAAc,EACd,aAAa,EACb,WAAkB,EAClB,cAAsB,GACvB,EAAE,gBAAgB,GAAG,GAAG,CAAC,OAAO,CA6ChC"}
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * Message list component
4
+ * Renders messages with optional custom renderer
5
+ */
6
+ import { useRef, useEffect } from 'react';
7
+ import { useChatContext } from './ChatContext';
8
+ export function MessageList({ className = '', renderMessage, showAvatars = true, showTimestamps = false, }) {
9
+ const { messages, isTyping } = useChatContext();
10
+ const containerRef = useRef(null);
11
+ // Auto-scroll to bottom on new messages
12
+ useEffect(() => {
13
+ if (containerRef.current) {
14
+ containerRef.current.scrollTop = containerRef.current.scrollHeight;
15
+ }
16
+ }, [messages]);
17
+ // Default message renderer
18
+ const defaultRenderMessage = (message) => (_jsxs("div", { className: `chatbot-message chatbot-message--${message.role}`, children: [showAvatars && (_jsx("div", { className: "chatbot-avatar", children: message.role === 'user' ? '\u{1F464}' : '\u{1F916}' })), _jsxs("div", { className: "chatbot-bubble", children: [_jsx("div", { className: "chatbot-text", children: message.text }), showTimestamps && (_jsx("div", { className: "chatbot-time", children: new Date(message.timestamp).toLocaleTimeString([], {
19
+ hour: '2-digit',
20
+ minute: '2-digit',
21
+ }) }))] })] }, message.id));
22
+ return (_jsxs("div", { ref: containerRef, className: `chatbot-messages ${className}`, children: [messages.map((message) => renderMessage ? renderMessage(message) : defaultRenderMessage(message)), isTyping && (_jsxs("div", { className: "chatbot-typing", children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] }))] }));
23
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Builder React exports
3
+ */
4
+ export { BuilderProvider, useBuilder } from './BuilderProvider';
5
+ export type { BuilderConfig, BuilderContextValue, BuilderProviderProps } from './BuilderProvider';
6
+ export { ChatProvider, useChatContext } from './ChatContext';
7
+ export type { ChatProviderProps } from './ChatContext';
8
+ export { MessageList } from './MessageList';
9
+ export type { MessageListProps } from './MessageList';
10
+ export { ChatInput } from './ChatInput';
11
+ export type { ChatInputProps } from './ChatInput';
12
+ export { CodeChatPanel } from './CodeChatPanel';
13
+ export type { CodeChatPanelProps } from './CodeChatPanel';
14
+ export { useChatbot } from './useChatbot';
15
+ export type { UseChatbotConfig, UseChatbotReturn } from './useChatbot';
16
+ export { LockedZone, EditableZone, NonCustomizable, Customizable, } from './EditableZone';
17
+ export type { ZoneProps } from './EditableZone';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builder/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAGlG,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGvD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAG1D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGvE,OAAO,EACL,UAAU,EACV,YAAY,EACZ,eAAe,EACf,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Builder React exports
3
+ */
4
+ // Builder provider with capture integration
5
+ export { BuilderProvider, useBuilder } from './BuilderProvider';
6
+ // Chat context and provider
7
+ export { ChatProvider, useChatContext } from './ChatContext';
8
+ // Components
9
+ export { MessageList } from './MessageList';
10
+ export { ChatInput } from './ChatInput';
11
+ export { CodeChatPanel } from './CodeChatPanel';
12
+ // Headless hook for custom UI
13
+ export { useChatbot } from './useChatbot';
14
+ // Zone wrappers for builder customization control
15
+ export { LockedZone, EditableZone, NonCustomizable, Customizable, } from './EditableZone';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Headless hook for full UI control
3
+ * Use this when you want to build your own UI
4
+ */
5
+ import type { Message } from 'dynim-core';
6
+ export interface UseChatbotConfig {
7
+ apiKey?: string;
8
+ endpoint?: string;
9
+ onMessage?: (data: {
10
+ text?: string;
11
+ content?: string;
12
+ }) => void;
13
+ onError?: (error: Error) => void;
14
+ }
15
+ export interface UseChatbotReturn {
16
+ messages: Message[];
17
+ isLoading: boolean;
18
+ isTyping: boolean;
19
+ error: string | null;
20
+ sendMessage: (text: string) => Promise<void>;
21
+ clearMessages: () => void;
22
+ }
23
+ export declare function useChatbot(config?: UseChatbotConfig): UseChatbotReturn;
24
+ //# sourceMappingURL=useChatbot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useChatbot.d.ts","sourceRoot":"","sources":["../../src/builder/useChatbot.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,OAAO,EAA4B,MAAM,YAAY,CAAC;AAEpE,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAChE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAC,MAAM,GAAE,gBAAqB,GAAG,gBAAgB,CAyF1E"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Headless hook for full UI control
3
+ * Use this when you want to build your own UI
4
+ */
5
+ import { useState, useEffect, useCallback, useRef } from 'react';
6
+ import { createState, createClient } from 'dynim-core';
7
+ export function useChatbot(config = {}) {
8
+ const { apiKey, endpoint, onMessage, onError } = config;
9
+ const [messages, setMessages] = useState([]);
10
+ const [isLoading, setIsLoading] = useState(false);
11
+ const [isTyping, setIsTyping] = useState(false);
12
+ const [error, setError] = useState(null);
13
+ const stateRef = useRef(null);
14
+ const clientRef = useRef(null);
15
+ // Initialize on mount
16
+ useEffect(() => {
17
+ const state = createState();
18
+ stateRef.current = state;
19
+ const client = createClient({
20
+ apiKey,
21
+ endpoint,
22
+ onMessage: (data) => {
23
+ const currentMessages = state.getState().messages;
24
+ const lastMessage = currentMessages[currentMessages.length - 1];
25
+ if (lastMessage?.role === 'assistant') {
26
+ const newText = lastMessage.text + (data.text || data.content || '');
27
+ state.updateMessage(lastMessage.id, { text: newText });
28
+ }
29
+ onMessage?.(data);
30
+ },
31
+ onError: (err) => {
32
+ const errorMessage = err instanceof Error ? err.message : 'Unknown error';
33
+ setError(errorMessage);
34
+ if (err instanceof Error) {
35
+ onError?.(err);
36
+ }
37
+ },
38
+ });
39
+ clientRef.current = client;
40
+ // Subscribe to state changes
41
+ const unsubscribe = state.subscribe((newState) => {
42
+ setMessages([...newState.messages]);
43
+ setIsLoading(newState.isLoading);
44
+ setIsTyping(newState.isTyping);
45
+ });
46
+ return () => {
47
+ unsubscribe();
48
+ };
49
+ }, [apiKey, endpoint]);
50
+ // Send message
51
+ const sendMessage = useCallback(async (text) => {
52
+ const state = stateRef.current;
53
+ const client = clientRef.current;
54
+ if (!state || !client)
55
+ return;
56
+ setError(null);
57
+ state.addMessage({ role: 'user', text });
58
+ const botMessage = state.addMessage({ role: 'assistant', text: '' });
59
+ setIsLoading(true);
60
+ setIsTyping(true);
61
+ try {
62
+ await client.send(text);
63
+ }
64
+ catch (err) {
65
+ state.updateMessage(botMessage.id, { text: 'Sorry, something went wrong.' });
66
+ setError(err.message);
67
+ }
68
+ finally {
69
+ setIsLoading(false);
70
+ setIsTyping(false);
71
+ }
72
+ }, []);
73
+ // Clear messages
74
+ const clearMessages = useCallback(() => {
75
+ stateRef.current?.clearMessages();
76
+ }, []);
77
+ return {
78
+ messages,
79
+ isLoading,
80
+ isTyping,
81
+ error,
82
+ sendMessage,
83
+ clearMessages,
84
+ };
85
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * dynim-react - React wrapper for dynim-core
3
+ *
4
+ * This package provides:
5
+ * - Re-exports everything from dynim-core (for convenience)
6
+ * - React components and hooks for the builder
7
+ * - Inference SDK for tenant customization loading
8
+ */
9
+ export * from 'dynim-core';
10
+ export { BuilderProvider, useBuilder, ChatProvider, useChatContext, MessageList, ChatInput, CodeChatPanel, useChatbot, LockedZone, EditableZone, NonCustomizable, Customizable, } from './builder';
11
+ export type { BuilderConfig, BuilderContextValue, BuilderProviderProps, ChatProviderProps, MessageListProps, ChatInputProps, CodeChatPanelProps, UseChatbotConfig, UseChatbotReturn, ZoneProps, } from './builder';
12
+ export { InferenceProvider, InferenceProviderDefault, createSharedContext, getSharedContext, isSharedContextReady, } from './inference';
13
+ export type { DynimSDKConfig, InferenceProviderProps, InferenceState, DynimGlobal, } from './inference';
14
+ //# sourceMappingURL=index.d.ts.map