@messenger-box/tailwind-ui-inbox 10.0.3-alpha.143 → 10.0.3-alpha.154
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/CHANGELOG.md +32 -0
- package/lib/components/InboxMessage/RightSidebarAi.d.ts +6 -0
- package/lib/components/InboxMessage/RightSidebarAi.d.ts.map +1 -1
- package/lib/components/InboxMessage/RightSidebarAi.js.map +1 -1
- package/lib/components/slot-fill/right-sidebar-filler.d.ts.map +1 -1
- package/lib/components/slot-fill/right-sidebar-filler.js.map +1 -1
- package/lib/container/InboxContainer.d.ts +5 -0
- package/lib/container/InboxContainer.d.ts.map +1 -1
- package/lib/container/InboxContainer.js.map +1 -1
- package/lib/container/InboxWithAiLoader.d.ts +5 -0
- package/lib/container/InboxWithAiLoader.d.ts.map +1 -1
- package/lib/container/InboxWithAiLoader.js +6 -2
- package/lib/container/InboxWithAiLoader.js.map +1 -1
- package/lib/container/TestInboxWithAiLoader.d.ts.map +1 -1
- package/lib/container/TestInboxWithAiLoader.js +2 -1
- package/lib/container/TestInboxWithAiLoader.js.map +1 -1
- package/lib/templates/InboxWithAi.d.ts +5 -0
- package/lib/templates/InboxWithAi.d.ts.map +1 -1
- package/lib/templates/InboxWithAi.js +52 -2
- package/lib/templates/InboxWithAi.js.map +1 -1
- package/lib/templates/InboxWithAi.tsx +70 -0
- package/lib/xstate/rightSidebar.machine.d.ts.map +1 -1
- package/lib/xstate/rightSidebar.machine.js +172 -21
- package/lib/xstate/rightSidebar.machine.js.map +1 -1
- package/lib/xstate/rightSidebar.types.d.ts +6 -1
- package/lib/xstate/rightSidebar.types.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/components/InboxMessage/RightSidebarAi.tsx +3 -0
- package/src/components/slot-fill/right-sidebar-filler.tsx +3 -0
- package/src/container/InboxContainer.tsx +2 -0
- package/src/container/InboxWithAiLoader.tsx +6 -0
- package/src/container/TestInboxWithAiLoader.tsx +1 -0
- package/src/templates/InboxWithAi.tsx +70 -0
- package/src/xstate/rightSidebar.machine.ts +187 -22
- package/src/xstate/rightSidebar.types.ts +5 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {createMachine,assign,fromPromise}from'xstate'
|
|
1
|
+
import {createMachine,assign,fromPromise}from'xstate';// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
const rightSidebarMachine = createMachine({
|
|
2
3
|
id: 'rightSidebar',
|
|
3
4
|
types: {},
|
|
4
5
|
context: ({
|
|
@@ -28,7 +29,6 @@ import {createMachine,assign,fromPromise}from'xstate';const rightSidebarMachine
|
|
|
28
29
|
}))
|
|
29
30
|
},
|
|
30
31
|
SET_FRAGMENT: {
|
|
31
|
-
target: 'probing',
|
|
32
32
|
actions: assign(({
|
|
33
33
|
context,
|
|
34
34
|
event
|
|
@@ -37,9 +37,8 @@ import {createMachine,assign,fromPromise}from'xstate';const rightSidebarMachine
|
|
|
37
37
|
activeFragment: event.fragment,
|
|
38
38
|
currentFiles: event.fragment?.files || context.currentFiles,
|
|
39
39
|
canvasLayers: event.fragment?.canvasLayers || context.canvasLayers,
|
|
40
|
-
previewStatus
|
|
41
|
-
|
|
42
|
-
} : null
|
|
40
|
+
// Don't set previewStatus to 'checking' automatically - only probe when explicitly needed
|
|
41
|
+
previewStatus: null
|
|
43
42
|
}))
|
|
44
43
|
},
|
|
45
44
|
PROBE: 'probing',
|
|
@@ -52,7 +51,52 @@ import {createMachine,assign,fromPromise}from'xstate';const rightSidebarMachine
|
|
|
52
51
|
isLoading: event.isLoading
|
|
53
52
|
}))
|
|
54
53
|
},
|
|
55
|
-
|
|
54
|
+
CLEAR_PREVIEW_STATUS: {
|
|
55
|
+
actions: assign(({
|
|
56
|
+
context
|
|
57
|
+
}) => ({
|
|
58
|
+
...context,
|
|
59
|
+
previewStatus: null
|
|
60
|
+
}))
|
|
61
|
+
},
|
|
62
|
+
RECREATE_SANDBOX: [{
|
|
63
|
+
// Only transition if we're not already recreating
|
|
64
|
+
guard: ({
|
|
65
|
+
context
|
|
66
|
+
}) => {
|
|
67
|
+
// Check if we have a fragment ID to recreate
|
|
68
|
+
const hasFragmentId = !!context.activeFragment?.id;
|
|
69
|
+
if (!hasFragmentId) {
|
|
70
|
+
console.log('🚫 RECREATE_SANDBOX: No fragment ID, ignoring');
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
return true;
|
|
74
|
+
},
|
|
75
|
+
target: 'recreating',
|
|
76
|
+
actions: assign(({
|
|
77
|
+
context,
|
|
78
|
+
event
|
|
79
|
+
}) => {
|
|
80
|
+
const recreateEvent = event;
|
|
81
|
+
console.log('🎯 RECREATE_SANDBOX event received and accepted:', {
|
|
82
|
+
id: recreateEvent.id,
|
|
83
|
+
fragmentId: context.activeFragment?.id
|
|
84
|
+
});
|
|
85
|
+
return context;
|
|
86
|
+
})
|
|
87
|
+
}, {
|
|
88
|
+
// If guard fails or already recreating, just log and stay in current state
|
|
89
|
+
actions: ({
|
|
90
|
+
context,
|
|
91
|
+
event
|
|
92
|
+
}) => {
|
|
93
|
+
const recreateEvent = event;
|
|
94
|
+
console.log('⏭️ RECREATE_SANDBOX ignored (already recreating or no fragment):', {
|
|
95
|
+
id: recreateEvent.id,
|
|
96
|
+
fragmentId: context.activeFragment?.id
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}]
|
|
56
100
|
}
|
|
57
101
|
},
|
|
58
102
|
probing: {
|
|
@@ -62,10 +106,13 @@ import {createMachine,assign,fromPromise}from'xstate';const rightSidebarMachine
|
|
|
62
106
|
input: ({
|
|
63
107
|
context,
|
|
64
108
|
event
|
|
65
|
-
}) =>
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
109
|
+
}) => {
|
|
110
|
+
const probeEvent = event;
|
|
111
|
+
return {
|
|
112
|
+
url: probeEvent.url ?? context.activeFragment?.sandboxUrl,
|
|
113
|
+
fragmentId: probeEvent.fragmentId ?? context.activeFragment?.id
|
|
114
|
+
};
|
|
115
|
+
},
|
|
69
116
|
onDone: {
|
|
70
117
|
target: 'idle',
|
|
71
118
|
actions: assign(({
|
|
@@ -76,7 +123,52 @@ import {createMachine,assign,fromPromise}from'xstate';const rightSidebarMachine
|
|
|
76
123
|
isLoading: false
|
|
77
124
|
}))
|
|
78
125
|
},
|
|
79
|
-
onError: {
|
|
126
|
+
onError: [{
|
|
127
|
+
// Only recreate if we have a fragment ID AND the error suggests the sandbox is truly unavailable
|
|
128
|
+
// Don't recreate on transient network errors (timeouts, CORS, etc.)
|
|
129
|
+
guard: ({
|
|
130
|
+
context,
|
|
131
|
+
event
|
|
132
|
+
}) => {
|
|
133
|
+
if (!context.activeFragment?.id) {
|
|
134
|
+
console.log('🚫 Guard: No fragment ID, skipping recreation');
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
const errorMessage = event.error instanceof Error ? event.error.message : String(event.error);
|
|
138
|
+
// Check for explicit HTTP status codes (4xx, 5xx)
|
|
139
|
+
const isServerError = /^[45]\d{2}/.test(errorMessage);
|
|
140
|
+
// Also check for CORS/network errors that likely indicate expired sandbox (502)
|
|
141
|
+
// CORS errors on sandbox URLs usually mean the sandbox is expired/down
|
|
142
|
+
const isCorsNetworkError = errorMessage.includes('502 CORS/Network Error') || errorMessage.includes('Failed to fetch') || errorMessage.includes('CORS') || errorMessage.includes('NetworkError') || errorMessage.includes('Network request failed');
|
|
143
|
+
const willRecreate = isServerError || isCorsNetworkError;
|
|
144
|
+
console.log('🔍 Guard check:', {
|
|
145
|
+
errorMessage,
|
|
146
|
+
isServerError,
|
|
147
|
+
isCorsNetworkError,
|
|
148
|
+
willRecreate
|
|
149
|
+
});
|
|
150
|
+
return willRecreate;
|
|
151
|
+
},
|
|
152
|
+
target: 'recreating',
|
|
153
|
+
actions: assign(({
|
|
154
|
+
context,
|
|
155
|
+
event
|
|
156
|
+
}) => {
|
|
157
|
+
console.log('🔄 Transitioning to recreating state:', {
|
|
158
|
+
fragmentId: context.activeFragment?.id,
|
|
159
|
+
error: event.error instanceof Error ? event.error.message : String(event.error)
|
|
160
|
+
});
|
|
161
|
+
return {
|
|
162
|
+
...context,
|
|
163
|
+
previewStatus: {
|
|
164
|
+
status: 'error',
|
|
165
|
+
message: event.error instanceof Error ? event.error.message : 'Network error'
|
|
166
|
+
},
|
|
167
|
+
isLoading: true
|
|
168
|
+
};
|
|
169
|
+
})
|
|
170
|
+
}, {
|
|
171
|
+
// For other errors (network, CORS, timeout), just show error but don't recreate
|
|
80
172
|
target: 'idle',
|
|
81
173
|
actions: assign(({
|
|
82
174
|
context,
|
|
@@ -89,7 +181,7 @@ import {createMachine,assign,fromPromise}from'xstate';const rightSidebarMachine
|
|
|
89
181
|
},
|
|
90
182
|
isLoading: false
|
|
91
183
|
}))
|
|
92
|
-
}
|
|
184
|
+
}]
|
|
93
185
|
}
|
|
94
186
|
},
|
|
95
187
|
recreating: {
|
|
@@ -97,17 +189,31 @@ import {createMachine,assign,fromPromise}from'xstate';const rightSidebarMachine
|
|
|
97
189
|
id: 'recreateSandbox',
|
|
98
190
|
src: 'recreateSandbox',
|
|
99
191
|
input: ({
|
|
192
|
+
context,
|
|
100
193
|
event
|
|
101
|
-
}) =>
|
|
102
|
-
|
|
103
|
-
|
|
194
|
+
}) => {
|
|
195
|
+
const recreateEvent = event;
|
|
196
|
+
const id = recreateEvent.id ?? context.activeFragment?.id ?? '';
|
|
197
|
+
console.log('📥 recreateSandbox input:', {
|
|
198
|
+
id,
|
|
199
|
+
hasRecreateEventId: !!recreateEvent.id,
|
|
200
|
+
hasActiveFragmentId: !!context.activeFragment?.id,
|
|
201
|
+
activeFragmentId: context.activeFragment?.id
|
|
202
|
+
});
|
|
203
|
+
return {
|
|
204
|
+
id
|
|
205
|
+
};
|
|
206
|
+
},
|
|
104
207
|
onDone: {
|
|
105
208
|
target: 'idle',
|
|
106
209
|
actions: assign(({
|
|
107
210
|
context
|
|
108
211
|
}) => ({
|
|
109
212
|
...context,
|
|
110
|
-
isLoading: false
|
|
213
|
+
isLoading: false,
|
|
214
|
+
previewStatus: {
|
|
215
|
+
status: 'checking'
|
|
216
|
+
}
|
|
111
217
|
}))
|
|
112
218
|
},
|
|
113
219
|
onError: {
|
|
@@ -124,6 +230,18 @@ import {createMachine,assign,fromPromise}from'xstate';const rightSidebarMachine
|
|
|
124
230
|
}
|
|
125
231
|
}))
|
|
126
232
|
}
|
|
233
|
+
},
|
|
234
|
+
on: {
|
|
235
|
+
COMPLETE_RECREATION: {
|
|
236
|
+
target: 'idle',
|
|
237
|
+
actions: assign(({
|
|
238
|
+
context
|
|
239
|
+
}) => ({
|
|
240
|
+
...context,
|
|
241
|
+
isLoading: false,
|
|
242
|
+
previewStatus: null
|
|
243
|
+
}))
|
|
244
|
+
}
|
|
127
245
|
}
|
|
128
246
|
}
|
|
129
247
|
}
|
|
@@ -135,12 +253,14 @@ import {createMachine,assign,fromPromise}from'xstate';const rightSidebarMachine
|
|
|
135
253
|
const {
|
|
136
254
|
url
|
|
137
255
|
} = input;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
256
|
+
console.log('🔍 probeUrl actor called with URL:', url);
|
|
257
|
+
if (!url) {
|
|
258
|
+
throw new Error('No URL provided for probing');
|
|
259
|
+
}
|
|
141
260
|
const controller = new AbortController();
|
|
142
261
|
const timeoutId = setTimeout(() => controller.abort(), 10000);
|
|
143
262
|
try {
|
|
263
|
+
console.log('📡 Fetching URL to probe:', url);
|
|
144
264
|
const res = await fetch(url, {
|
|
145
265
|
method: 'GET',
|
|
146
266
|
mode: 'cors',
|
|
@@ -148,14 +268,45 @@ import {createMachine,assign,fromPromise}from'xstate';const rightSidebarMachine
|
|
|
148
268
|
signal: controller.signal
|
|
149
269
|
});
|
|
150
270
|
clearTimeout(timeoutId);
|
|
271
|
+
console.log('📊 Probe response status:', res.status, res.statusText);
|
|
272
|
+
// Check for HTTP error status codes (4xx, 5xx)
|
|
151
273
|
if (!res.ok) {
|
|
152
|
-
|
|
274
|
+
const statusCode = res.status;
|
|
275
|
+
const statusText = res.statusText || 'Unknown Error';
|
|
276
|
+
const errorMessage = `${statusCode} ${statusText}`;
|
|
277
|
+
console.log('❌ Probe detected error:', errorMessage);
|
|
278
|
+
// Throw error with status code format that matches the guard regex: /^[45]\d{2}/
|
|
279
|
+
throw new Error(errorMessage);
|
|
153
280
|
}
|
|
281
|
+
console.log('✅ Probe successful - URL is accessible');
|
|
154
282
|
return {
|
|
155
283
|
ok: true
|
|
156
284
|
};
|
|
157
|
-
}
|
|
285
|
+
} catch (error) {
|
|
158
286
|
clearTimeout(timeoutId);
|
|
287
|
+
// If it's an abort (timeout), don't treat as server error
|
|
288
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
289
|
+
throw new Error('TIMEOUT Request timeout');
|
|
290
|
+
}
|
|
291
|
+
// If it's already a formatted error (from res.ok check), rethrow it
|
|
292
|
+
if (error instanceof Error && /^\d{3}/.test(error.message)) {
|
|
293
|
+
throw error;
|
|
294
|
+
}
|
|
295
|
+
// Handle CORS/network errors - these often mask 502 errors from expired sandboxes
|
|
296
|
+
// When we get a CORS error or "Failed to fetch", it's likely because:
|
|
297
|
+
// 1. The sandbox is expired (502) and the server isn't responding properly
|
|
298
|
+
// 2. The sandbox is down and can't set CORS headers
|
|
299
|
+
// We'll throw a special error that the guard can recognize
|
|
300
|
+
if (error instanceof Error) {
|
|
301
|
+
const isCorsError = error.message.includes('Failed to fetch') || error.message.includes('CORS') || error.message.includes('NetworkError') || error.message.includes('Network request failed');
|
|
302
|
+
if (isCorsError) {
|
|
303
|
+
console.log('⚠️ CORS/Network error detected - likely expired sandbox (502):', error.message);
|
|
304
|
+
// Throw as 502 error so guard will match it
|
|
305
|
+
throw new Error('502 CORS/Network Error - Sandbox likely expired');
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// For other network errors, throw as-is and let guard decide
|
|
309
|
+
throw error;
|
|
159
310
|
}
|
|
160
311
|
}),
|
|
161
312
|
recreateSandbox: fromPromise(async ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rightSidebar.machine.js","sources":["../../src/xstate/rightSidebar.machine.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rightSidebar.machine.js","sources":["../../src/xstate/rightSidebar.machine.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,7 @@ export type ActiveFragment = {
|
|
|
15
15
|
canvasLayers?: unknown[];
|
|
16
16
|
summary?: unknown;
|
|
17
17
|
isError?: boolean;
|
|
18
|
+
isCreatingSandbox?: boolean;
|
|
18
19
|
} | null;
|
|
19
20
|
export type RightSidebarContext = {
|
|
20
21
|
channelId: string;
|
|
@@ -47,6 +48,10 @@ export type RecreateSandboxEvent = {
|
|
|
47
48
|
export type MachineEvent = UpdateEvent | SetFragmentEvent | ProbeEvent | RecreateSandboxEvent | {
|
|
48
49
|
type: 'SET_LOADING';
|
|
49
50
|
isLoading: boolean;
|
|
51
|
+
} | {
|
|
52
|
+
type: 'CLEAR_PREVIEW_STATUS';
|
|
53
|
+
} | {
|
|
54
|
+
type: 'COMPLETE_RECREATION';
|
|
50
55
|
};
|
|
51
|
-
export type SubmitOrganizationActor = ActorRefFrom<
|
|
56
|
+
export type SubmitOrganizationActor = ActorRefFrom<unknown>;
|
|
52
57
|
//# sourceMappingURL=rightSidebar.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rightSidebar.types.d.ts","sourceRoot":"","sources":["../../src/xstate/rightSidebar.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE3C,MAAM,MAAM,aAAa,GAAG;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;CACjC,GAAG,IAAI,CAAC;AAET,MAAM,MAAM,cAAc,GAAG;IACzB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"rightSidebar.types.d.ts","sourceRoot":"","sources":["../../src/xstate/rightSidebar.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE3C,MAAM,MAAM,aAAa,GAAG;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;CACjC,GAAG,IAAI,CAAC;AAET,MAAM,MAAM,cAAc,GAAG;IACzB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC/B,GAAG,IAAI,CAAC;AAET,MAAM,MAAM,mBAAmB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,YAAY,EAAE,OAAO,EAAE,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACtB,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9E,MAAM,MAAM,oBAAoB,GAAG;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E,MAAM,MAAM,YAAY,GAClB,WAAW,GACX,gBAAgB,GAChB,UAAU,GACV,oBAAoB,GACpB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,sBAAsB,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,qBAAqB,CAAA;CAAE,CAAC;AAEtC,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@messenger-box/tailwind-ui-inbox",
|
|
3
|
-
"version": "10.0.3-alpha.
|
|
3
|
+
"version": "10.0.3-alpha.154",
|
|
4
4
|
"description": "Inbox UI components built with TailwindCSS",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "CDMBase LLC",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"watch": "npm run build:lib:watch"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@messenger-box/core": "10.0.3-alpha.
|
|
25
|
-
"@messenger-box/platform-client": "10.0.3-alpha.
|
|
24
|
+
"@messenger-box/core": "10.0.3-alpha.154",
|
|
25
|
+
"@messenger-box/platform-client": "10.0.3-alpha.154",
|
|
26
26
|
"@monaco-editor/react": "^4.7.0",
|
|
27
27
|
"date-fns": "^4.1.0",
|
|
28
28
|
"date-fns-tz": "^3.2.0",
|
|
@@ -58,5 +58,5 @@
|
|
|
58
58
|
"typescript": {
|
|
59
59
|
"definition": "lib/index.d.ts"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "ed2e0f3b207c3d6da21b73baacc00bce93be80db"
|
|
62
62
|
}
|
|
@@ -21,6 +21,9 @@ export interface IRightSidebarAi extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
21
21
|
isLoading?: boolean;
|
|
22
22
|
messages?: any[];
|
|
23
23
|
selectedPost?: any;
|
|
24
|
+
contextData?: any;
|
|
25
|
+
showContextTab?: boolean;
|
|
26
|
+
ContextTabComponent?: React.ComponentType<{ context: any; selectedPost?: any }>;
|
|
24
27
|
handleSendMessage?: (createChannelInput: ICreateChannelInput) => void;
|
|
25
28
|
isMinimized?: boolean;
|
|
26
29
|
handleRecreateSandbox?: (messageId: string) => void | Promise<any>;
|
|
@@ -19,6 +19,9 @@ type RightSidebarProps = {
|
|
|
19
19
|
windowHeight: number;
|
|
20
20
|
activeTab?: string;
|
|
21
21
|
selectedPost?: any;
|
|
22
|
+
contextData?: any;
|
|
23
|
+
showContextTab?: boolean;
|
|
24
|
+
ContextTabComponent?: React.ComponentType<{ context: any; selectedPost?: any }>;
|
|
22
25
|
messages?: any[];
|
|
23
26
|
setIsLoading?: (isLoading: boolean) => void;
|
|
24
27
|
handleSendMessage?: (createChannelInput: ICreateChannelInput) => void;
|
|
@@ -9,6 +9,8 @@ interface InboxContainerProps {
|
|
|
9
9
|
orgName?: string;
|
|
10
10
|
handleRecreateSandbox?: (messageId: string) => void | Promise<any>;
|
|
11
11
|
isShowOnlyInbox?: boolean;
|
|
12
|
+
showContextTab?: boolean;
|
|
13
|
+
ContextTabComponent?: React.ComponentType<{ context: any; selectedPost?: any }>;
|
|
12
14
|
[key: string]: any;
|
|
13
15
|
}
|
|
14
16
|
|
|
@@ -42,6 +42,8 @@ interface InboxWithAiLoaderProps {
|
|
|
42
42
|
isShowAiLanding?: boolean;
|
|
43
43
|
showModelToolbarProjectSettings?: boolean;
|
|
44
44
|
isShowMeta?: boolean;
|
|
45
|
+
showContextTab?: boolean;
|
|
46
|
+
ContextTabComponent?: React.ComponentType<{ context: any; selectedPost?: any }>;
|
|
45
47
|
[key: string]: any;
|
|
46
48
|
}
|
|
47
49
|
|
|
@@ -52,6 +54,8 @@ const InboxWithAiLoader = (props: InboxWithAiLoaderProps) => {
|
|
|
52
54
|
isShowAiLanding = false,
|
|
53
55
|
showModelToolbarProjectSettings = false,
|
|
54
56
|
isShowMeta = false,
|
|
57
|
+
showContextTab = true,
|
|
58
|
+
ContextTabComponent = null,
|
|
55
59
|
} = props;
|
|
56
60
|
const { orgName, channelRole: channelRoleParam } = useParams();
|
|
57
61
|
const location = useLocation();
|
|
@@ -64,6 +68,8 @@ const InboxWithAiLoader = (props: InboxWithAiLoaderProps) => {
|
|
|
64
68
|
pathPrefix: pathPrefix || '',
|
|
65
69
|
handleRecreateSandbox: props.handleRecreateSandbox,
|
|
66
70
|
isShowOnlyInbox: props?.isShowOnlyInbox || false,
|
|
71
|
+
showContextTab: showContextTab,
|
|
72
|
+
ContextTabComponent: ContextTabComponent,
|
|
67
73
|
}),
|
|
68
74
|
[props, orgName, pathPrefix],
|
|
69
75
|
);
|
|
@@ -34,6 +34,8 @@ export interface InboxProps {
|
|
|
34
34
|
orgName?: string;
|
|
35
35
|
handleRecreateSandbox?: (messageId: string) => void | Promise<any>;
|
|
36
36
|
isShowOnlyInbox?: boolean;
|
|
37
|
+
showContextTab?: boolean;
|
|
38
|
+
ContextTabComponent?: React.ComponentType<{ context: any; selectedPost?: any }>;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
// Static utility hooks and components
|
|
@@ -92,6 +94,22 @@ const EmptyState = React.memo(() => (
|
|
|
92
94
|
</div>
|
|
93
95
|
));
|
|
94
96
|
|
|
97
|
+
const DefaultContextTab = ({ context }: { context: any }) => {
|
|
98
|
+
const isString = typeof context === 'string';
|
|
99
|
+
const content = isString ? context : JSON.stringify(context ?? {}, null, 2);
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<div className="h-full w-full bg-gray-50 text-gray-800 overflow-auto">
|
|
103
|
+
<div className="p-4">
|
|
104
|
+
<h3 className="text-sm font-semibold text-gray-700 mb-2">Context</h3>
|
|
105
|
+
<pre className="text-sm whitespace-pre-wrap break-words font-mono bg-white border border-gray-200 rounded-md p-3 shadow-sm">
|
|
106
|
+
{content || 'No context available.'}
|
|
107
|
+
</pre>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
};
|
|
112
|
+
|
|
95
113
|
const InboxWithAi = (props: InboxProps) => {
|
|
96
114
|
const [activeTab, setActiveTab] = React.useState('preview');
|
|
97
115
|
|
|
@@ -117,9 +135,26 @@ const InboxWithAiInternal = (props: InboxProps) => {
|
|
|
117
135
|
const [errorData, setError] = useState<string | null>(null);
|
|
118
136
|
const [sendMessageInput, handleSendMessage] = useState<ICreateChannelInput | null>(null);
|
|
119
137
|
const [isMinimized, setIsMinimized] = useState(false);
|
|
138
|
+
const showContextTab = props.showContextTab ?? true;
|
|
139
|
+
const contextData = useMemo(() => {
|
|
140
|
+
const cfg = selectedPost?.propsConfiguration;
|
|
141
|
+
return (
|
|
142
|
+
cfg?.contents?.fragment?.context ||
|
|
143
|
+
cfg?.content?.fragment?.context ||
|
|
144
|
+
cfg?.fragment?.context ||
|
|
145
|
+
null
|
|
146
|
+
);
|
|
147
|
+
}, [selectedPost]);
|
|
120
148
|
// Extract channelId from query parameters (priority) or path parameters (fallback)
|
|
121
149
|
const channelId = urlParams?.get('id') || pathChannelId;
|
|
122
150
|
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
// If context tab is disabled via props, fall back to preview
|
|
153
|
+
if (activeTab === 'context' && !showContextTab) {
|
|
154
|
+
setActiveTab('preview');
|
|
155
|
+
}
|
|
156
|
+
}, [activeTab, showContextTab, setActiveTab]);
|
|
157
|
+
|
|
123
158
|
const recreateSandboxForFragment = useCallback(
|
|
124
159
|
async (messageId: string) => {
|
|
125
160
|
if (!channelId || !messageId) {
|
|
@@ -261,6 +296,38 @@ const InboxWithAiInternal = (props: InboxProps) => {
|
|
|
261
296
|
</svg>
|
|
262
297
|
<span>Code</span>
|
|
263
298
|
</button>
|
|
299
|
+
{showContextTab && (
|
|
300
|
+
<button
|
|
301
|
+
onClick={() => setActiveTab('context')}
|
|
302
|
+
className={`flex items-center space-x-2 px-4 py-2 text-xs font-medium transition-all duration-200 ${
|
|
303
|
+
activeTab === 'context'
|
|
304
|
+
? 'bg-blue-500 text-white shadow-sm'
|
|
305
|
+
: 'text-gray-600 hover:text-gray-900'
|
|
306
|
+
}`}
|
|
307
|
+
style={{ borderRadius: '10px' }}
|
|
308
|
+
>
|
|
309
|
+
<svg
|
|
310
|
+
className="w-4 h-4"
|
|
311
|
+
fill="none"
|
|
312
|
+
stroke="currentColor"
|
|
313
|
+
viewBox="0 0 24 24"
|
|
314
|
+
>
|
|
315
|
+
<path
|
|
316
|
+
strokeLinecap="round"
|
|
317
|
+
strokeLinejoin="round"
|
|
318
|
+
strokeWidth={2}
|
|
319
|
+
d="M12 8c-1.657 0-3 1.343-3 3s1.343 3 3 3 3-1.343 3-3-1.343-3-3-3z"
|
|
320
|
+
/>
|
|
321
|
+
<path
|
|
322
|
+
strokeLinecap="round"
|
|
323
|
+
strokeLinejoin="round"
|
|
324
|
+
strokeWidth={2}
|
|
325
|
+
d="M21 12c0 4.97-4.03 9-9 9s-9-4.03-9-9 4.03-9 9-9 9 4.03 9 9z"
|
|
326
|
+
/>
|
|
327
|
+
</svg>
|
|
328
|
+
<span>Context</span>
|
|
329
|
+
</button>
|
|
330
|
+
)}
|
|
264
331
|
</div>
|
|
265
332
|
)}
|
|
266
333
|
</div>
|
|
@@ -384,6 +451,8 @@ const InboxWithAiInternal = (props: InboxProps) => {
|
|
|
384
451
|
channelId={channelId}
|
|
385
452
|
messages={messages}
|
|
386
453
|
selectedPost={selectedPost}
|
|
454
|
+
contextData={contextData}
|
|
455
|
+
showContextTab={showContextTab}
|
|
387
456
|
setIsLoading={setIsLoading}
|
|
388
457
|
setIsCreatingSandbox={setIsCreatingSandbox}
|
|
389
458
|
isCreatingSandbox={isCreatingSandbox}
|
|
@@ -391,6 +460,7 @@ const InboxWithAiInternal = (props: InboxProps) => {
|
|
|
391
460
|
handleSendMessage={handleSendMessage}
|
|
392
461
|
handleRecreateSandbox={props?.handleRecreateSandbox || null}
|
|
393
462
|
isMinimized={isMinimized}
|
|
463
|
+
ContextTabComponent={props?.ContextTabComponent ?? DefaultContextTab}
|
|
394
464
|
{...props}
|
|
395
465
|
/>
|
|
396
466
|
</div>
|