@flamingo-stack/openframe-frontend-core 0.0.678-snapshot.20260928203735 → 0.0.678

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 (101) hide show
  1. package/dist/{chunk-UAPSU6YW.cjs → chunk-2752B3YY.cjs} +3 -3
  2. package/dist/{chunk-UAPSU6YW.cjs.map → chunk-2752B3YY.cjs.map} +1 -1
  3. package/dist/{chunk-6LN7ZNHT.js → chunk-33HTSSCG.js} +3 -3
  4. package/dist/{chunk-HLMMG6Q7.js → chunk-7IYDTCKE.js} +5 -5
  5. package/dist/{chunk-HA3SBMR2.cjs → chunk-CPJ7QBIV.cjs} +4 -4
  6. package/dist/{chunk-HA3SBMR2.cjs.map → chunk-CPJ7QBIV.cjs.map} +1 -1
  7. package/dist/{chunk-UKZAW4FE.js → chunk-CUGM36ZU.js} +3 -3
  8. package/dist/{chunk-FUBOKAYO.js → chunk-D5FLAQQH.js} +5 -5
  9. package/dist/{chunk-KNPUHPIF.cjs → chunk-DZR47TRO.cjs} +33 -33
  10. package/dist/{chunk-KNPUHPIF.cjs.map → chunk-DZR47TRO.cjs.map} +1 -1
  11. package/dist/{chunk-2YMFBKYR.js → chunk-EPH3FGIF.js} +3 -3
  12. package/dist/{chunk-ZRN244JV.js → chunk-EWNKYH2D.js} +2 -2
  13. package/dist/{chunk-25Y3UR3R.cjs → chunk-EXQPK67M.cjs} +10 -10
  14. package/dist/{chunk-25Y3UR3R.cjs.map → chunk-EXQPK67M.cjs.map} +1 -1
  15. package/dist/{chunk-QU7SDFKO.cjs → chunk-FBQSQRUY.cjs} +71 -71
  16. package/dist/{chunk-QU7SDFKO.cjs.map → chunk-FBQSQRUY.cjs.map} +1 -1
  17. package/dist/{chunk-ZB34GLOZ.cjs → chunk-G4EXCWR4.cjs} +45 -45
  18. package/dist/{chunk-ZB34GLOZ.cjs.map → chunk-G4EXCWR4.cjs.map} +1 -1
  19. package/dist/{chunk-ICGGFQQU.js → chunk-GNOCB662.js} +4 -4
  20. package/dist/{chunk-H27EHTLX.cjs → chunk-GPSL3KFX.cjs} +3 -3
  21. package/dist/{chunk-H27EHTLX.cjs.map → chunk-GPSL3KFX.cjs.map} +1 -1
  22. package/dist/{chunk-FQDHQNSU.js → chunk-HEPOYA2M.js} +10 -31
  23. package/dist/{chunk-FQDHQNSU.js.map → chunk-HEPOYA2M.js.map} +1 -1
  24. package/dist/{chunk-NQCID4VF.js → chunk-J7VFEMTJ.js} +6 -6
  25. package/dist/{chunk-T7GIFC5Y.cjs → chunk-JHSDZI3D.cjs} +10 -31
  26. package/dist/chunk-JHSDZI3D.cjs.map +1 -0
  27. package/dist/{chunk-TKL5JKZS.cjs → chunk-K7YEA2LO.cjs} +10 -10
  28. package/dist/{chunk-TKL5JKZS.cjs.map → chunk-K7YEA2LO.cjs.map} +1 -1
  29. package/dist/{chunk-GZIYE35W.cjs → chunk-L3O2HPOO.cjs} +15 -15
  30. package/dist/{chunk-GZIYE35W.cjs.map → chunk-L3O2HPOO.cjs.map} +1 -1
  31. package/dist/{chunk-4ZKZSWX4.js → chunk-MB5JXDJK.js} +3 -3
  32. package/dist/{chunk-XSSYG7KU.js → chunk-MP2UTOLN.js} +5 -5
  33. package/dist/{chunk-L4NLXAET.js → chunk-N4HJDYMG.js} +2 -2
  34. package/dist/{chunk-HTNUTEXN.cjs → chunk-OAS4JLF4.cjs} +22 -22
  35. package/dist/{chunk-HTNUTEXN.cjs.map → chunk-OAS4JLF4.cjs.map} +1 -1
  36. package/dist/{chunk-RJYYGWJL.cjs → chunk-R5B4T26B.cjs} +22 -22
  37. package/dist/{chunk-RJYYGWJL.cjs.map → chunk-R5B4T26B.cjs.map} +1 -1
  38. package/dist/{chunk-CY3XHQM3.cjs → chunk-RBBFGN6B.cjs} +5 -5
  39. package/dist/{chunk-CY3XHQM3.cjs.map → chunk-RBBFGN6B.cjs.map} +1 -1
  40. package/dist/{chunk-3LW6AJMJ.cjs → chunk-RI44VAGW.cjs} +338 -338
  41. package/dist/{chunk-3LW6AJMJ.cjs.map → chunk-RI44VAGW.cjs.map} +1 -1
  42. package/dist/{chunk-7WGUMITJ.js → chunk-S3NK47ZJ.js} +2 -2
  43. package/dist/{chunk-EEL4RGHX.js → chunk-STVG6WV4.js} +2 -2
  44. package/dist/{chunk-MGSWL3L3.cjs → chunk-THWEZULI.cjs} +26 -26
  45. package/dist/{chunk-MGSWL3L3.cjs.map → chunk-THWEZULI.cjs.map} +1 -1
  46. package/dist/{chunk-CDMZOXS7.js → chunk-UBAXZQKE.js} +3 -3
  47. package/dist/{chunk-IPZCEAAH.js → chunk-X2ORWRBO.js} +2 -2
  48. package/dist/{chunk-CGYFCEHM.cjs → chunk-XZG2NZLL.cjs} +10 -10
  49. package/dist/{chunk-CGYFCEHM.cjs.map → chunk-XZG2NZLL.cjs.map} +1 -1
  50. package/dist/components/case-studies/index.cjs +14 -14
  51. package/dist/components/case-studies/index.js +3 -3
  52. package/dist/components/chat/embeddable-chat.d.ts.map +1 -1
  53. package/dist/components/chat/hooks/use-chat-attachments.d.ts.map +1 -1
  54. package/dist/components/chat/index.cjs +2 -2
  55. package/dist/components/chat/index.js +1 -1
  56. package/dist/components/contact/index.cjs +4 -4
  57. package/dist/components/contact/index.js +3 -3
  58. package/dist/components/docs/index.cjs +7 -7
  59. package/dist/components/docs/index.js +6 -6
  60. package/dist/components/embeds/index.cjs +4 -4
  61. package/dist/components/embeds/index.js +3 -3
  62. package/dist/components/faq/index.cjs +4 -4
  63. package/dist/components/faq/index.js +3 -3
  64. package/dist/components/features/index.cjs +3 -3
  65. package/dist/components/features/index.js +2 -2
  66. package/dist/components/help-center-pages/index.cjs +73 -73
  67. package/dist/components/help-center-pages/index.js +14 -14
  68. package/dist/components/index.cjs +39 -39
  69. package/dist/components/index.js +13 -13
  70. package/dist/components/meeting-scheduler/index.cjs +25 -25
  71. package/dist/components/meeting-scheduler/index.js +2 -2
  72. package/dist/components/navigation/index.cjs +6 -6
  73. package/dist/components/navigation/index.js +5 -5
  74. package/dist/components/onboarding-guides/index.cjs +6 -6
  75. package/dist/components/onboarding-guides/index.js +5 -5
  76. package/dist/components/tickets/index.cjs +7 -7
  77. package/dist/components/tickets/index.js +6 -6
  78. package/dist/components/ui/index.cjs +3 -3
  79. package/dist/components/ui/index.js +2 -2
  80. package/dist/index.cjs +7 -7
  81. package/dist/index.js +6 -6
  82. package/package.json +1 -1
  83. package/src/components/chat/embeddable-chat.tsx +18 -63
  84. package/src/components/chat/hooks/use-chat-attachments.ts +1 -4
  85. package/dist/chunk-T7GIFC5Y.cjs.map +0 -1
  86. package/src/components/chat/__tests__/embeddable-chat-composer-scope.test.tsx +0 -234
  87. /package/dist/{chunk-6LN7ZNHT.js.map → chunk-33HTSSCG.js.map} +0 -0
  88. /package/dist/{chunk-HLMMG6Q7.js.map → chunk-7IYDTCKE.js.map} +0 -0
  89. /package/dist/{chunk-UKZAW4FE.js.map → chunk-CUGM36ZU.js.map} +0 -0
  90. /package/dist/{chunk-FUBOKAYO.js.map → chunk-D5FLAQQH.js.map} +0 -0
  91. /package/dist/{chunk-2YMFBKYR.js.map → chunk-EPH3FGIF.js.map} +0 -0
  92. /package/dist/{chunk-ZRN244JV.js.map → chunk-EWNKYH2D.js.map} +0 -0
  93. /package/dist/{chunk-ICGGFQQU.js.map → chunk-GNOCB662.js.map} +0 -0
  94. /package/dist/{chunk-NQCID4VF.js.map → chunk-J7VFEMTJ.js.map} +0 -0
  95. /package/dist/{chunk-4ZKZSWX4.js.map → chunk-MB5JXDJK.js.map} +0 -0
  96. /package/dist/{chunk-XSSYG7KU.js.map → chunk-MP2UTOLN.js.map} +0 -0
  97. /package/dist/{chunk-L4NLXAET.js.map → chunk-N4HJDYMG.js.map} +0 -0
  98. /package/dist/{chunk-7WGUMITJ.js.map → chunk-S3NK47ZJ.js.map} +0 -0
  99. /package/dist/{chunk-EEL4RGHX.js.map → chunk-STVG6WV4.js.map} +0 -0
  100. /package/dist/{chunk-CDMZOXS7.js.map → chunk-UBAXZQKE.js.map} +0 -0
  101. /package/dist/{chunk-IPZCEAAH.js.map → chunk-X2ORWRBO.js.map} +0 -0
@@ -1,234 +0,0 @@
1
- /**
2
- * The composer belongs to the conversation on screen — pinned.
3
- *
4
- * `ChatInput` is an uncontrolled contenteditable that owns its draft, and the
5
- * slash-command menu is derived from that draft (`/` at the start keeps it
6
- * open). The panel already dropped the staged context chips on a dialog
7
- * change, but the text stayed, so opening another conversation — from the
8
- * list, or from a notification the host resolves straight into the store —
9
- * landed with the previous one's half-typed `/` and its menu still open over
10
- * the new thread. The composer is now keyed on the conversation: leaving one
11
- * remounts it fresh in the same commit.
12
- *
13
- * The one id change that must NOT reset it: a send from the new-chat surface
14
- * creates the dialog, and the id the panel then lands on is this conversation
15
- * being named. The editor stays typable while that first turn streams, so a
16
- * follow-up already being typed has to survive.
17
- */
18
-
19
- import * as DialogPrimitive from '@radix-ui/react-dialog';
20
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
21
- import { act, fireEvent, render, screen } from '@testing-library/react';
22
- import { createRef } from 'react';
23
- import { beforeEach, describe, expect, it, vi } from 'vitest';
24
-
25
- // Identity + every other authed fetch: a promise that never settles keeps the
26
- // panel offline and free of state updates landing outside `act`.
27
- vi.mock('../../../utils/embed-authed-fetch', () => ({
28
- embedAuthedFetch: vi.fn(() => new Promise(() => {})),
29
- }));
30
-
31
- // One canned command, so `/` opens a real suggestions menu.
32
- vi.mock('../hooks/use-slash-commands', async importOriginal => {
33
- const actual = await importOriginal<Record<string, unknown>>();
34
- return {
35
- ...actual,
36
- fetchSlashCommands: vi.fn(() =>
37
- Promise.resolve([
38
- {
39
- id: 'roadmap',
40
- label: 'ClickUp Roadmap',
41
- description: 'Browse the public ClickUp roadmap',
42
- argumentHint: '[task id or name]',
43
- actions: [{ id: 'recent', label: 'Recent' }],
44
- },
45
- ]),
46
- ),
47
- };
48
- });
49
-
50
- import { ChatRuntimeContext, type ChatRuntime } from '../../../contexts/chat-runtime-context';
51
- import { EmbeddableChat, type EmbeddableChatHandle } from '../embeddable-chat';
52
- import type { UnifiedChatState } from '../types/unified-chat-state.types';
53
-
54
- const runtime: ChatRuntime = {
55
- endpoints: {
56
- chatStreamUrl: '/api/docs/chat',
57
- approvalToolUrl: '/api/chat/agent/confirm-tool',
58
- commandsUrl: '/api/docs/commands',
59
- buildListUrl: () => null,
60
- attachmentUploadUrl: '/api/storage/generate-upload-url',
61
- attachmentViewUrlPrefix: '/api/storage/view/chat-attachments/',
62
- identityUrl: '/api/chat/identity',
63
- },
64
- navigation: { mode: 'host' },
65
- };
66
-
67
- const MESSAGE: UnifiedChatState['messages'][number] = {
68
- id: 'm-1',
69
- role: 'user',
70
- content: 'hello',
71
- timestamp: new Date('2026-01-01T00:00:00Z'),
72
- };
73
-
74
- /** The injected-state path (`mingoState`): the panel renders this object and
75
- * opens no transport, so the test drives `activeDialogId` by re-rendering. */
76
- function createState(overrides: Partial<UnifiedChatState>): UnifiedChatState {
77
- const noop = () => {};
78
- const asyncNoop = async () => {};
79
- return {
80
- messages: [],
81
- isLoading: false,
82
- streamingPhase: 'idle',
83
- sendMessage: asyncNoop,
84
- stopMessage: noop,
85
- clearMessages: noop,
86
- discussRef: noop,
87
- displayRef: noop,
88
- currentProvider: 'anthropic',
89
- currentModelLabel: 'Claude',
90
- currentContextWindowMaxTokens: null,
91
- currentInputTokens: null,
92
- currentOutputTokens: null,
93
- currentCacheHitRatePct: null,
94
- currentUsageBreakdown: null,
95
- dialogs: [
96
- { id: 'd-1', title: 'First' },
97
- { id: 'd-2', title: 'Second' },
98
- ],
99
- activeDialogId: null,
100
- selectDialog: noop,
101
- startNewDialog: () => Promise.resolve(null),
102
- deleteDialog: asyncNoop,
103
- renameDialog: asyncNoop,
104
- archiveDialog: asyncNoop,
105
- isDialogsLoading: false,
106
- dialogsError: false,
107
- reloadDialogs: noop,
108
- isMessagesLoading: false,
109
- hasMoreDialogs: false,
110
- loadMoreDialogs: asyncNoop,
111
- hasMoreMessages: false,
112
- loadMoreMessages: asyncNoop,
113
- approveRequest: asyncNoop,
114
- rejectRequest: asyncNoop,
115
- dialogTokenUsage: null,
116
- connectionState: 'connected',
117
- ...overrides,
118
- };
119
- }
120
-
121
- function Harness({ state, handleRef }: { state: UnifiedChatState; handleRef?: React.Ref<EmbeddableChatHandle> }) {
122
- return (
123
- <ChatRuntimeContext.Provider value={runtime}>
124
- <DialogPrimitive.Root open>
125
- <EmbeddableChat
126
- ref={handleRef}
127
- shell="none"
128
- defaultOpen
129
- defaultActiveMode="mingo"
130
- showInternalTrigger={false}
131
- mingoState={state}
132
- mingoDialogCapabilities={{ canRename: true, canArchive: true }}
133
- />
134
- </DialogPrimitive.Root>
135
- </ChatRuntimeContext.Provider>
136
- );
137
- }
138
-
139
- function renderPanel(state: UnifiedChatState, handleRef?: React.Ref<EmbeddableChatHandle>) {
140
- const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
141
- const view = render(
142
- <QueryClientProvider client={client}>
143
- <Harness state={state} handleRef={handleRef} />
144
- </QueryClientProvider>,
145
- );
146
- return {
147
- ...view,
148
- rerender: (next: UnifiedChatState) =>
149
- view.rerender(
150
- <QueryClientProvider client={client}>
151
- <Harness state={next} handleRef={handleRef} />
152
- </QueryClientProvider>,
153
- ),
154
- };
155
- }
156
-
157
- const editor = () => screen.getByRole('textbox', { name: 'Ask a question...' });
158
-
159
- /** Type into the uncontrolled editor the way the browser does: mutate the DOM,
160
- * then fire `input` so the component reads it back. */
161
- function type(text: string) {
162
- const el = editor();
163
- el.textContent = `${el.textContent ?? ''}${text}`;
164
- fireEvent.input(el);
165
- }
166
-
167
- const menu = () => screen.queryByRole('menu', { name: 'Slash command suggestions' });
168
-
169
- beforeEach(() => {
170
- vi.useRealTimers();
171
- });
172
-
173
- describe('EmbeddableChat — the composer belongs to the conversation on screen', () => {
174
- it('opening another dialog drops the draft and the slash menu it kept open', async () => {
175
- const { rerender } = renderPanel(createState({ activeDialogId: 'd-1', messages: [MESSAGE] }));
176
-
177
- type('/');
178
- expect(await screen.findByRole('menu', { name: 'Slash command suggestions' })).toBeInTheDocument();
179
- expect(editor()).toHaveTextContent('/');
180
-
181
- rerender(createState({ activeDialogId: 'd-2', messages: [MESSAGE] }));
182
-
183
- expect(menu()).not.toBeInTheDocument();
184
- expect(editor()).toHaveTextContent('');
185
- });
186
-
187
- it('opening a dialog from the new-chat surface drops the draft typed there', async () => {
188
- const handle = createRef<EmbeddableChatHandle>();
189
- const { rerender } = renderPanel(createState({ activeDialogId: null }), handle);
190
- // Narrow layout: the list has no composer; the compose view does.
191
- act(() => handle.current?.startNewChat());
192
-
193
- type('/');
194
- expect(await screen.findByRole('menu', { name: 'Slash command suggestions' })).toBeInTheDocument();
195
-
196
- rerender(createState({ activeDialogId: 'd-1', messages: [MESSAGE] }));
197
-
198
- expect(menu()).not.toBeInTheDocument();
199
- expect(editor()).toHaveTextContent('');
200
- });
201
-
202
- it('a new chat being named by its first send keeps the follow-up already being typed', async () => {
203
- let settleSend: () => void = () => {};
204
- const sendMessage = vi.fn<UnifiedChatState['sendMessage']>(
205
- () =>
206
- new Promise<void>(resolve => {
207
- settleSend = resolve;
208
- }),
209
- );
210
- const handle = createRef<EmbeddableChatHandle>();
211
- const { rerender } = renderPanel(createState({ activeDialogId: null, sendMessage }), handle);
212
- act(() => handle.current?.startNewChat());
213
-
214
- type('first question');
215
- fireEvent.keyDown(editor(), { key: 'Enter' });
216
- expect(sendMessage.mock.calls[0]?.[0]).toBe('first question');
217
- expect(editor()).toHaveTextContent('');
218
-
219
- // The host is creating the dialog; the user is already typing the next one.
220
- type('and also');
221
- rerender(createState({ activeDialogId: 'd-new', messages: [MESSAGE], sendMessage }));
222
- expect(editor()).toHaveTextContent('and also');
223
-
224
- await act(async () => {
225
- settleSend();
226
- await Promise.resolve();
227
- });
228
- expect(editor()).toHaveTextContent('and also');
229
-
230
- // A real switch afterwards still resets.
231
- rerender(createState({ activeDialogId: 'd-1', messages: [MESSAGE], sendMessage }));
232
- expect(editor()).toHaveTextContent('');
233
- });
234
- });