@sybilion/uilib 1.3.86 → 1.3.88
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/agent-glossary/content.generated.ts +4 -6
- package/dist/agent-glossary/content.md +4 -6
- package/dist/agent-glossary/workspace.generated.ts +4 -6
- package/dist/agent-glossary/workspace.md +4 -6
- package/dist/esm/components/ui/Chat/ChatSheet/ChatSheet.js +1 -0
- package/dist/esm/components/ui/Chat/ChatSheet/useChatPanelChromeModel.js +27 -3
- package/dist/esm/components/ui/Sidebar/Sidebar.js +23 -7
- package/dist/esm/types/src/components/ui/Chat/ChatEmptyState/ChatEmptyState.types.d.ts +5 -1
- package/dist/esm/types/src/components/ui/Chat/ChatSheet/ChatSheet.d.ts +2 -0
- package/dist/esm/types/src/components/ui/Chat/ChatSheet/useChatPanelChromeModel.d.ts +2 -0
- package/dist/esm/types/src/components/ui/Chat/index.d.ts +1 -1
- package/dist/esm/types/src/components/ui/Sidebar/Sidebar.d.ts +2 -0
- package/package.json +1 -1
- package/src/components/ui/ChartAreaInteractive/AGENT.md +0 -1
- package/src/components/ui/Chat/ChatEmptyState/ChatEmptyState.types.ts +9 -1
- package/src/components/ui/Chat/ChatSheet/ChatSheet.tsx +3 -0
- package/src/components/ui/Chat/ChatSheet/useChatPanelChromeModel.tsx +41 -4
- package/src/components/ui/Chat/index.ts +1 -0
- package/src/components/ui/Sidebar/Sidebar.tsx +27 -8
- package/src/components/widgets/DriverMap/AGENT.md +1 -1
- package/src/components/widgets/DriversComparisonChart/AGENT.md +2 -2
- package/src/components/widgets/PerformanceChart/AGENT.md +1 -2
|
@@ -180,7 +180,6 @@ Host provides:
|
|
|
180
180
|
- \`chartData\`, \`forecastData\` built from API
|
|
181
181
|
- \`timeRange\` / \`onTimeRangeChange\` or brush-only range
|
|
182
182
|
- Optional \`mode\`: pin | intervals | thresholds + overlay state
|
|
183
|
-
- Analysis selector and fetch outside widget
|
|
184
183
|
|
|
185
184
|
Report tile: \`dataset_card\` — host loads dataset + analysis; chart inside dashboard card.
|
|
186
185
|
|
|
@@ -201,7 +200,7 @@ Host provides:
|
|
|
201
200
|
- Controlled \`selectedDriver\` + \`setSelectedDriver\`
|
|
202
201
|
- \`isLoading\` while fetching drivers
|
|
203
202
|
|
|
204
|
-
Report tile: \`drivers_map\` — tile resolves analysis id, fetches drivers, passes list + selection
|
|
203
|
+
Report tile: \`drivers_map\` — tile resolves analysis id, fetches drivers, passes list + selection.
|
|
205
204
|
|
|
206
205
|
Requires: \`drivers\`; \`isLoading\`; \`selectedDriver\`; \`setSelectedDriver\`.
|
|
207
206
|
|
|
@@ -217,10 +216,9 @@ Not when: simple forecast card or driver backtests — use ChartAreaInteractive
|
|
|
217
216
|
Host provides:
|
|
218
217
|
|
|
219
218
|
- \`performanceData\` (PerformanceChartPayload) and \`historicalData\` from performance API
|
|
220
|
-
- Analysis selection and fetch outside widget
|
|
221
219
|
- Optional \`forecastData\`, \`customPerformanceMatrix\`, \`userSeries\` for spaghetti
|
|
222
220
|
|
|
223
|
-
Report tile: \`performance_chart\` — host loads performance payload + dataset series
|
|
221
|
+
Report tile: \`performance_chart\` — host loads performance payload + dataset series.
|
|
224
222
|
|
|
225
223
|
Requires: \`performanceData\` — model/drift forecasts and metrics; \`historicalData\` — baseline series; \`loading\` / \`chartLoading\` / \`performanceDataLoading\` — spinners; \`runAnalysisHint\` / \`statusHint\` — empty states.
|
|
226
224
|
|
|
@@ -240,9 +238,9 @@ Host provides:
|
|
|
240
238
|
- \`seriesInitKey\` when selected analysis changes
|
|
241
239
|
- \`viewTab\` / \`onViewTabChange\`: \`lagged\` (calendar-aligned, raw dates) or \`overlapped\` (driver series shifted backward by parsed lag months)
|
|
242
240
|
|
|
243
|
-
View tabs: host should render uilib \`Tabs variant="button"\` with **Lagged** / **Overlapped** in the toolbar
|
|
241
|
+
View tabs: host should render uilib \`Tabs variant="button"\` with **Lagged** / **Overlapped** in the toolbar. Chart applies \`applyDriversComparisonViewToPayload\` internally.
|
|
244
242
|
|
|
245
|
-
Report tile: \`drivers_comparison_chart\` — host loads normalized backtests payload + dataset historical
|
|
243
|
+
Report tile: \`drivers_comparison_chart\` — host loads normalized backtests payload + dataset historical.
|
|
246
244
|
|
|
247
245
|
Requires: \`payload\` — target + driver normalized_series; \`loading\` / \`chartLoading\` — spinners; \`seriesInitKey\` — reset visible series on analysis or view tab change; \`runAnalysisHint\` / \`statusHint\` — empty/error text.
|
|
248
246
|
|
|
@@ -179,7 +179,6 @@ Host provides:
|
|
|
179
179
|
- `chartData`, `forecastData` built from API
|
|
180
180
|
- `timeRange` / `onTimeRangeChange` or brush-only range
|
|
181
181
|
- Optional `mode`: pin | intervals | thresholds + overlay state
|
|
182
|
-
- Analysis selector and fetch outside widget
|
|
183
182
|
|
|
184
183
|
Report tile: `dataset_card` — host loads dataset + analysis; chart inside dashboard card.
|
|
185
184
|
|
|
@@ -200,7 +199,7 @@ Host provides:
|
|
|
200
199
|
- Controlled `selectedDriver` + `setSelectedDriver`
|
|
201
200
|
- `isLoading` while fetching drivers
|
|
202
201
|
|
|
203
|
-
Report tile: `drivers_map` — tile resolves analysis id, fetches drivers, passes list + selection
|
|
202
|
+
Report tile: `drivers_map` — tile resolves analysis id, fetches drivers, passes list + selection.
|
|
204
203
|
|
|
205
204
|
Requires: `drivers`; `isLoading`; `selectedDriver`; `setSelectedDriver`.
|
|
206
205
|
|
|
@@ -216,10 +215,9 @@ Not when: simple forecast card or driver backtests — use ChartAreaInteractive
|
|
|
216
215
|
Host provides:
|
|
217
216
|
|
|
218
217
|
- `performanceData` (PerformanceChartPayload) and `historicalData` from performance API
|
|
219
|
-
- Analysis selection and fetch outside widget
|
|
220
218
|
- Optional `forecastData`, `customPerformanceMatrix`, `userSeries` for spaghetti
|
|
221
219
|
|
|
222
|
-
Report tile: `performance_chart` — host loads performance payload + dataset series
|
|
220
|
+
Report tile: `performance_chart` — host loads performance payload + dataset series.
|
|
223
221
|
|
|
224
222
|
Requires: `performanceData` — model/drift forecasts and metrics; `historicalData` — baseline series; `loading` / `chartLoading` / `performanceDataLoading` — spinners; `runAnalysisHint` / `statusHint` — empty states.
|
|
225
223
|
|
|
@@ -239,9 +237,9 @@ Host provides:
|
|
|
239
237
|
- `seriesInitKey` when selected analysis changes
|
|
240
238
|
- `viewTab` / `onViewTabChange`: `lagged` (calendar-aligned, raw dates) or `overlapped` (driver series shifted backward by parsed lag months)
|
|
241
239
|
|
|
242
|
-
View tabs: host should render uilib `Tabs variant="button"` with **Lagged** / **Overlapped** in the toolbar
|
|
240
|
+
View tabs: host should render uilib `Tabs variant="button"` with **Lagged** / **Overlapped** in the toolbar. Chart applies `applyDriversComparisonViewToPayload` internally.
|
|
243
241
|
|
|
244
|
-
Report tile: `drivers_comparison_chart` — host loads normalized backtests payload + dataset historical
|
|
242
|
+
Report tile: `drivers_comparison_chart` — host loads normalized backtests payload + dataset historical.
|
|
245
243
|
|
|
246
244
|
Requires: `payload` — target + driver normalized_series; `loading` / `chartLoading` — spinners; `seriesInitKey` — reset visible series on analysis or view tab change; `runAnalysisHint` / `statusHint` — empty/error text.
|
|
247
245
|
|
|
@@ -199,7 +199,6 @@ Host provides:
|
|
|
199
199
|
- \`chartData\`, \`forecastData\` built from API
|
|
200
200
|
- \`timeRange\` / \`onTimeRangeChange\` or brush-only range
|
|
201
201
|
- Optional \`mode\`: pin | intervals | thresholds + overlay state
|
|
202
|
-
- Analysis selector and fetch outside widget
|
|
203
202
|
|
|
204
203
|
Report tile: \`dataset_card\` — host loads dataset + analysis; chart inside dashboard card.
|
|
205
204
|
|
|
@@ -220,7 +219,7 @@ Host provides:
|
|
|
220
219
|
- Controlled \`selectedDriver\` + \`setSelectedDriver\`
|
|
221
220
|
- \`isLoading\` while fetching drivers
|
|
222
221
|
|
|
223
|
-
Report tile: \`drivers_map\` — tile resolves analysis id, fetches drivers, passes list + selection
|
|
222
|
+
Report tile: \`drivers_map\` — tile resolves analysis id, fetches drivers, passes list + selection.
|
|
224
223
|
|
|
225
224
|
Requires: \`drivers\`; \`isLoading\`; \`selectedDriver\`; \`setSelectedDriver\`.
|
|
226
225
|
|
|
@@ -236,10 +235,9 @@ Not when: simple forecast card or driver backtests — use ChartAreaInteractive
|
|
|
236
235
|
Host provides:
|
|
237
236
|
|
|
238
237
|
- \`performanceData\` (PerformanceChartPayload) and \`historicalData\` from performance API
|
|
239
|
-
- Analysis selection and fetch outside widget
|
|
240
238
|
- Optional \`forecastData\`, \`customPerformanceMatrix\`, \`userSeries\` for spaghetti
|
|
241
239
|
|
|
242
|
-
Report tile: \`performance_chart\` — host loads performance payload + dataset series
|
|
240
|
+
Report tile: \`performance_chart\` — host loads performance payload + dataset series.
|
|
243
241
|
|
|
244
242
|
Requires: \`performanceData\` — model/drift forecasts and metrics; \`historicalData\` — baseline series; \`loading\` / \`chartLoading\` / \`performanceDataLoading\` — spinners; \`runAnalysisHint\` / \`statusHint\` — empty states.
|
|
245
243
|
|
|
@@ -259,9 +257,9 @@ Host provides:
|
|
|
259
257
|
- \`seriesInitKey\` when selected analysis changes
|
|
260
258
|
- \`viewTab\` / \`onViewTabChange\`: \`lagged\` (calendar-aligned, raw dates) or \`overlapped\` (driver series shifted backward by parsed lag months)
|
|
261
259
|
|
|
262
|
-
View tabs: host should render uilib \`Tabs variant="button"\` with **Lagged** / **Overlapped** in the toolbar
|
|
260
|
+
View tabs: host should render uilib \`Tabs variant="button"\` with **Lagged** / **Overlapped** in the toolbar. Chart applies \`applyDriversComparisonViewToPayload\` internally.
|
|
263
261
|
|
|
264
|
-
Report tile: \`drivers_comparison_chart\` — host loads normalized backtests payload + dataset historical
|
|
262
|
+
Report tile: \`drivers_comparison_chart\` — host loads normalized backtests payload + dataset historical.
|
|
265
263
|
|
|
266
264
|
Requires: \`payload\` — target + driver normalized_series; \`loading\` / \`chartLoading\` — spinners; \`seriesInitKey\` — reset visible series on analysis or view tab change; \`runAnalysisHint\` / \`statusHint\` — empty/error text.
|
|
267
265
|
|
|
@@ -198,7 +198,6 @@ Host provides:
|
|
|
198
198
|
- `chartData`, `forecastData` built from API
|
|
199
199
|
- `timeRange` / `onTimeRangeChange` or brush-only range
|
|
200
200
|
- Optional `mode`: pin | intervals | thresholds + overlay state
|
|
201
|
-
- Analysis selector and fetch outside widget
|
|
202
201
|
|
|
203
202
|
Report tile: `dataset_card` — host loads dataset + analysis; chart inside dashboard card.
|
|
204
203
|
|
|
@@ -219,7 +218,7 @@ Host provides:
|
|
|
219
218
|
- Controlled `selectedDriver` + `setSelectedDriver`
|
|
220
219
|
- `isLoading` while fetching drivers
|
|
221
220
|
|
|
222
|
-
Report tile: `drivers_map` — tile resolves analysis id, fetches drivers, passes list + selection
|
|
221
|
+
Report tile: `drivers_map` — tile resolves analysis id, fetches drivers, passes list + selection.
|
|
223
222
|
|
|
224
223
|
Requires: `drivers`; `isLoading`; `selectedDriver`; `setSelectedDriver`.
|
|
225
224
|
|
|
@@ -235,10 +234,9 @@ Not when: simple forecast card or driver backtests — use ChartAreaInteractive
|
|
|
235
234
|
Host provides:
|
|
236
235
|
|
|
237
236
|
- `performanceData` (PerformanceChartPayload) and `historicalData` from performance API
|
|
238
|
-
- Analysis selection and fetch outside widget
|
|
239
237
|
- Optional `forecastData`, `customPerformanceMatrix`, `userSeries` for spaghetti
|
|
240
238
|
|
|
241
|
-
Report tile: `performance_chart` — host loads performance payload + dataset series
|
|
239
|
+
Report tile: `performance_chart` — host loads performance payload + dataset series.
|
|
242
240
|
|
|
243
241
|
Requires: `performanceData` — model/drift forecasts and metrics; `historicalData` — baseline series; `loading` / `chartLoading` / `performanceDataLoading` — spinners; `runAnalysisHint` / `statusHint` — empty states.
|
|
244
242
|
|
|
@@ -258,9 +256,9 @@ Host provides:
|
|
|
258
256
|
- `seriesInitKey` when selected analysis changes
|
|
259
257
|
- `viewTab` / `onViewTabChange`: `lagged` (calendar-aligned, raw dates) or `overlapped` (driver series shifted backward by parsed lag months)
|
|
260
258
|
|
|
261
|
-
View tabs: host should render uilib `Tabs variant="button"` with **Lagged** / **Overlapped** in the toolbar
|
|
259
|
+
View tabs: host should render uilib `Tabs variant="button"` with **Lagged** / **Overlapped** in the toolbar. Chart applies `applyDriversComparisonViewToPayload` internally.
|
|
262
260
|
|
|
263
|
-
Report tile: `drivers_comparison_chart` — host loads normalized backtests payload + dataset historical
|
|
261
|
+
Report tile: `drivers_comparison_chart` — host loads normalized backtests payload + dataset historical.
|
|
264
262
|
|
|
265
263
|
Requires: `payload` — target + driver normalized_series; `loading` / `chartLoading` — spinners; `seriesInitKey` — reset visible series on analysis or view tab change; `runAnalysisHint` / `statusHint` — empty/error text.
|
|
266
264
|
|
|
@@ -40,6 +40,7 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
|
|
|
40
40
|
const [promptLinkPrefill, setPromptLinkPrefill] = useState(null);
|
|
41
41
|
/** Deduplicate Strict Mode double `useEffect` on the same mount. */
|
|
42
42
|
const promptParamHandledInEffectRef = useRef(false);
|
|
43
|
+
const pendingOpenChatAndSubmitRef = useRef(null);
|
|
43
44
|
const prevShellChatPanelOpenRef = useRef(shellChatPanelOpen);
|
|
44
45
|
/** This instance requested shell chat width (ignore other ChatSheet instances on the page). */
|
|
45
46
|
const openedShellChatRef = useRef(false);
|
|
@@ -200,6 +201,18 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
|
|
|
200
201
|
setPromptLinkPrefill(trimmed || null);
|
|
201
202
|
onOpenChange(true);
|
|
202
203
|
}, [startEmptyNewChat, onOpenChange]);
|
|
204
|
+
const openNewChatAndSubmit = useCallback((prompt) => {
|
|
205
|
+
const sessionId = startEmptyNewChat();
|
|
206
|
+
if (sessionId == null) {
|
|
207
|
+
logger.warn('Chat submit: sign in to use the assistant.');
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const trimmed = prompt.trim();
|
|
211
|
+
if (!trimmed)
|
|
212
|
+
return;
|
|
213
|
+
pendingOpenChatAndSubmitRef.current = { sessionId, prompt: trimmed };
|
|
214
|
+
onOpenChange(true);
|
|
215
|
+
}, [startEmptyNewChat, onOpenChange]);
|
|
203
216
|
/**
|
|
204
217
|
* App link: `?prompt=…` — open panel, pre-fill composer, strip param (read once on mount
|
|
205
218
|
* from `location.search`). If the selected session already has messages, `newChat()` first.
|
|
@@ -498,7 +511,14 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
|
|
|
498
511
|
onScriptComplete,
|
|
499
512
|
transformSendPayload,
|
|
500
513
|
]);
|
|
501
|
-
|
|
514
|
+
useEffect(() => {
|
|
515
|
+
const pending = pendingOpenChatAndSubmitRef.current;
|
|
516
|
+
if (!pending || currentChatId !== pending.sessionId)
|
|
517
|
+
return;
|
|
518
|
+
pendingOpenChatAndSubmitRef.current = null;
|
|
519
|
+
void handlePromptSubmit(pending.prompt);
|
|
520
|
+
}, [currentChatId, handlePromptSubmit]);
|
|
521
|
+
const submitPreset = useCallback(async (preset, options) => {
|
|
502
522
|
const script = preset.script;
|
|
503
523
|
const scriptGraph = isPresetScriptGraph(script);
|
|
504
524
|
const hasLinearScript = Array.isArray(script) && script.length > 0;
|
|
@@ -511,7 +531,7 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
|
|
|
511
531
|
if (!currentChatId)
|
|
512
532
|
return;
|
|
513
533
|
endLocalDemoFlow(currentChatId);
|
|
514
|
-
await handlePromptSubmit(preset.text);
|
|
534
|
+
await handlePromptSubmit(options?.message ?? preset.text);
|
|
515
535
|
return;
|
|
516
536
|
}
|
|
517
537
|
setLocalUiBusy(true);
|
|
@@ -798,7 +818,10 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
|
|
|
798
818
|
chatWidthPx,
|
|
799
819
|
})) {
|
|
800
820
|
// Chat open uses `startViewTransition`; nested transition here aborts first → AbortError overlay.
|
|
801
|
-
setSidebarNavOpen(false, {
|
|
821
|
+
setSidebarNavOpen(false, {
|
|
822
|
+
viewTransition: false,
|
|
823
|
+
layoutAutoClose: true,
|
|
824
|
+
});
|
|
802
825
|
}
|
|
803
826
|
};
|
|
804
827
|
collapseNavIfNoSpace();
|
|
@@ -948,6 +971,7 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
|
|
|
948
971
|
toggleOpen,
|
|
949
972
|
newChat: startEmptyNewChat,
|
|
950
973
|
openNewChatWithPrefill,
|
|
974
|
+
openNewChatAndSubmit,
|
|
951
975
|
chatPanelContainer,
|
|
952
976
|
};
|
|
953
977
|
}
|
|
@@ -85,6 +85,8 @@ function SidebarProvider({ defaultOpen = getCookie('isSidebarOpen') ?? true, cla
|
|
|
85
85
|
const [chatPanelOpen, _setChatPanelOpen] = useState(false);
|
|
86
86
|
const sidebarWidthRef = useRef(sidebarWidthPx);
|
|
87
87
|
const chatWidthRef = useRef(chatWidthPx);
|
|
88
|
+
/** Left nav was auto-closed because chat opened on a narrow shell; reopen when chat closes. */
|
|
89
|
+
const sidebarAutoClosedForChatRef = useRef(false);
|
|
88
90
|
sidebarWidthRef.current = sidebarWidthPx;
|
|
89
91
|
chatWidthRef.current = chatWidthPx;
|
|
90
92
|
const mergeWrapperRef = useCallback((el) => {
|
|
@@ -226,10 +228,8 @@ function SidebarProvider({ defaultOpen = getCookie('isSidebarOpen') ?? true, cla
|
|
|
226
228
|
}
|
|
227
229
|
}
|
|
228
230
|
else if (openingChat && isOpen) {
|
|
231
|
+
sidebarAutoClosedForChatRef.current = true;
|
|
229
232
|
setIsOpen(false);
|
|
230
|
-
if (getCookiePreferences(userId)?.functional) {
|
|
231
|
-
setCookie('isSidebarOpen', 'false', 60 * 60 * 24 * 7);
|
|
232
|
-
}
|
|
233
233
|
}
|
|
234
234
|
}, [
|
|
235
235
|
isSidebarSheetLayout,
|
|
@@ -238,18 +238,34 @@ function SidebarProvider({ defaultOpen = getCookie('isSidebarOpen') ?? true, cla
|
|
|
238
238
|
chatPanelOpen,
|
|
239
239
|
sidebarWidthPx,
|
|
240
240
|
chatWidthPx,
|
|
241
|
-
userId,
|
|
242
241
|
]);
|
|
243
242
|
const setChatPanelOpen = useCallback((open) => {
|
|
244
243
|
if (open) {
|
|
245
244
|
closeOppositeSidebarIfNoSpace(false, true);
|
|
245
|
+
_setChatPanelOpen(true);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
_setChatPanelOpen(false);
|
|
249
|
+
if (sidebarAutoClosedForChatRef.current) {
|
|
250
|
+
sidebarAutoClosedForChatRef.current = false;
|
|
251
|
+
setIsOpen(true);
|
|
252
|
+
if (getCookiePreferences(userId)?.functional) {
|
|
253
|
+
setCookie('isSidebarOpen', 'true', 60 * 60 * 24 * 7);
|
|
254
|
+
}
|
|
246
255
|
}
|
|
247
|
-
|
|
248
|
-
}, [closeOppositeSidebarIfNoSpace]);
|
|
256
|
+
}, [closeOppositeSidebarIfNoSpace, userId]);
|
|
249
257
|
const setOpen = useCallback((value, options) => {
|
|
258
|
+
const layoutAutoClose = options?.layoutAutoClose === true;
|
|
250
259
|
if (value) {
|
|
260
|
+
sidebarAutoClosedForChatRef.current = false;
|
|
251
261
|
closeOppositeSidebarIfNoSpace(true, false);
|
|
252
262
|
}
|
|
263
|
+
else if (layoutAutoClose) {
|
|
264
|
+
sidebarAutoClosedForChatRef.current = true;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
sidebarAutoClosedForChatRef.current = false;
|
|
268
|
+
}
|
|
253
269
|
const useViewTransition = options?.viewTransition !== false &&
|
|
254
270
|
!isSidebarSheetLayout &&
|
|
255
271
|
'startViewTransition' in document &&
|
|
@@ -262,7 +278,7 @@ function SidebarProvider({ defaultOpen = getCookie('isSidebarOpen') ?? true, cla
|
|
|
262
278
|
else {
|
|
263
279
|
setIsOpen(value);
|
|
264
280
|
}
|
|
265
|
-
if (getCookiePreferences(userId)?.functional) {
|
|
281
|
+
if (!layoutAutoClose && getCookiePreferences(userId)?.functional) {
|
|
266
282
|
setCookie('isSidebarOpen', value.toString(), 60 * 60 * 24 * 7);
|
|
267
283
|
}
|
|
268
284
|
}, [isSidebarSheetLayout, userId, closeOppositeSidebarIfNoSpace]);
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { ChatPreset } from '#uilib/components/ui/Chat/Chat.types';
|
|
2
|
+
export type SubmitPresetOptions = {
|
|
3
|
+
/** Composer text when preset row includes addon context (e.g. live news URL). */
|
|
4
|
+
message?: string;
|
|
5
|
+
};
|
|
2
6
|
export type ChatEmptyStateContext = {
|
|
3
|
-
submitPreset: (preset: ChatPreset) => void | Promise<void>;
|
|
7
|
+
submitPreset: (preset: ChatPreset, options?: SubmitPresetOptions) => void | Promise<void>;
|
|
4
8
|
};
|
|
5
9
|
export interface ChatEmptyStateProps {
|
|
6
10
|
icon?: React.ReactNode;
|
|
@@ -5,6 +5,8 @@ export type ChatSheetActions = {
|
|
|
5
5
|
openNewChat: () => void;
|
|
6
6
|
/** Starts a new chat, opens the panel, and pre-fills the composer (user sends manually). */
|
|
7
7
|
openNewChatWithPrefill: (prompt: string) => void;
|
|
8
|
+
/** Starts a new chat, opens panel, and sends prompt immediately. */
|
|
9
|
+
openNewChatAndSubmit: (prompt: string) => void;
|
|
8
10
|
};
|
|
9
11
|
export interface ChatSheetProps extends Omit<UseChatPanelChromeModelInput, 'embedAsPage'> {
|
|
10
12
|
title?: string;
|
|
@@ -44,6 +44,8 @@ export type UseChatPanelChromeModelResult = {
|
|
|
44
44
|
newChat: () => void;
|
|
45
45
|
/** New session + open panel + one-shot composer pre-fill (does not send). */
|
|
46
46
|
openNewChatWithPrefill: (prompt: string) => void;
|
|
47
|
+
/** New session + open panel + immediate send. */
|
|
48
|
+
openNewChatAndSubmit: (prompt: string) => void;
|
|
47
49
|
chatPanelContainer: HTMLElement | null;
|
|
48
50
|
};
|
|
49
51
|
export declare function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onScriptComplete, renderMessageChart, renderSystemMessage, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, copyHistoryOnNewChat, transformSendPayload, }: UseChatPanelChromeModelInput): UseChatPanelChromeModelResult;
|
|
@@ -17,7 +17,7 @@ export type { ChatPromptComposerHandle } from './ChatPrompt/ChatPromptComposer';
|
|
|
17
17
|
export { CHAT_PROMPT_COMMAND_CHIP_CLASS, chatPromptChipHtml, createChatPromptComposerHandle, getChatPromptTokenRangeBeforePos, insertChatPromptContentAtCaret, } from './ChatPrompt/chatPromptComposerInsert';
|
|
18
18
|
export type { ChatPromptComposerInsertOptions } from './ChatPrompt/ChatPromptComposer.types';
|
|
19
19
|
export { ChatPresets } from './ChatPresets';
|
|
20
|
-
export type { ChatEmptyStateConfig, ChatEmptyStateContext, ChatEmptyStateProps, } from './ChatEmptyState/ChatEmptyState.types';
|
|
20
|
+
export type { ChatEmptyStateConfig, ChatEmptyStateContext, ChatEmptyStateProps, SubmitPresetOptions, } from './ChatEmptyState/ChatEmptyState.types';
|
|
21
21
|
export type { Chat as ChatType, ChatAttachmentDropItem, ChatMessageClassNames, ChatMessageTextClassNames, ChatMeta, ChatMetaValue, ChatSendMessagePayload, ChatMessageProps, ChatProps, ChatPreset as ChatPresetType, Message, UserTextFileAttachment, } from './Chat.types';
|
|
22
22
|
export { MessageRole } from './Chat.types';
|
|
23
23
|
export type { SlashCommandItem, SlashItemCommandContext, SlashOnItemCommand, } from '#uilib/tiptap/slash-mention/types';
|
|
@@ -12,6 +12,8 @@ type SetPanelWidthOptions = {
|
|
|
12
12
|
/** Pass `viewTransition: false` to avoid nesting `document.startViewTransition` (e.g. chat open already animating). */
|
|
13
13
|
export type SetSidebarOpenOptions = {
|
|
14
14
|
viewTransition?: boolean;
|
|
15
|
+
/** Nav closed for layout (chat/width); restore when chat closes — do not persist closed cookie. */
|
|
16
|
+
layoutAutoClose?: boolean;
|
|
15
17
|
};
|
|
16
18
|
type SidebarContextProps = {
|
|
17
19
|
isOpen: boolean;
|
package/package.json
CHANGED
|
@@ -10,7 +10,6 @@ Host provides:
|
|
|
10
10
|
- `chartData`, `forecastData` built from API
|
|
11
11
|
- `timeRange` / `onTimeRangeChange` or brush-only range
|
|
12
12
|
- Optional `mode`: pin | intervals | thresholds + overlay state
|
|
13
|
-
- Analysis selector and fetch outside widget
|
|
14
13
|
|
|
15
14
|
Report tile: `dataset_card` — host loads dataset + analysis; chart inside dashboard card.
|
|
16
15
|
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import type { ChatPreset } from '#uilib/components/ui/Chat/Chat.types';
|
|
2
2
|
|
|
3
|
+
export type SubmitPresetOptions = {
|
|
4
|
+
/** Composer text when preset row includes addon context (e.g. live news URL). */
|
|
5
|
+
message?: string;
|
|
6
|
+
};
|
|
7
|
+
|
|
3
8
|
export type ChatEmptyStateContext = {
|
|
4
|
-
submitPreset: (
|
|
9
|
+
submitPreset: (
|
|
10
|
+
preset: ChatPreset,
|
|
11
|
+
options?: SubmitPresetOptions,
|
|
12
|
+
) => void | Promise<void>;
|
|
5
13
|
};
|
|
6
14
|
|
|
7
15
|
export interface ChatEmptyStateProps {
|
|
@@ -13,6 +13,8 @@ export type ChatSheetActions = {
|
|
|
13
13
|
openNewChat: () => void;
|
|
14
14
|
/** Starts a new chat, opens the panel, and pre-fills the composer (user sends manually). */
|
|
15
15
|
openNewChatWithPrefill: (prompt: string) => void;
|
|
16
|
+
/** Starts a new chat, opens panel, and sends prompt immediately. */
|
|
17
|
+
openNewChatAndSubmit: (prompt: string) => void;
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
export interface ChatSheetProps extends Omit<
|
|
@@ -79,6 +81,7 @@ export function ChatSheet({
|
|
|
79
81
|
model.onOpenChange(true);
|
|
80
82
|
},
|
|
81
83
|
openNewChatWithPrefill: model.openNewChatWithPrefill,
|
|
84
|
+
openNewChatAndSubmit: model.openNewChatAndSubmit,
|
|
82
85
|
};
|
|
83
86
|
}
|
|
84
87
|
|
|
@@ -51,7 +51,10 @@ import {
|
|
|
51
51
|
} from '../../Sidebar/Sidebar';
|
|
52
52
|
import { Chat } from '../Chat';
|
|
53
53
|
import type { ChatChromeProps } from '../ChatChrome';
|
|
54
|
-
import type {
|
|
54
|
+
import type {
|
|
55
|
+
ChatAttachmentDropItem,
|
|
56
|
+
ChatPresetsRenderOptions,
|
|
57
|
+
} from '../ChatChrome/ChatChrome.types';
|
|
55
58
|
import type { ChatEmptyStateConfig } from '../ChatEmptyState/ChatEmptyState.types';
|
|
56
59
|
import type { ChatEmptyStateProps } from '../ChatEmptyState/ChatEmptyState.types';
|
|
57
60
|
import {
|
|
@@ -118,6 +121,8 @@ export type UseChatPanelChromeModelResult = {
|
|
|
118
121
|
newChat: () => void;
|
|
119
122
|
/** New session + open panel + one-shot composer pre-fill (does not send). */
|
|
120
123
|
openNewChatWithPrefill: (prompt: string) => void;
|
|
124
|
+
/** New session + open panel + immediate send. */
|
|
125
|
+
openNewChatAndSubmit: (prompt: string) => void;
|
|
121
126
|
chatPanelContainer: HTMLElement | null;
|
|
122
127
|
};
|
|
123
128
|
|
|
@@ -209,6 +214,10 @@ export function useChatPanelChromeModel({
|
|
|
209
214
|
);
|
|
210
215
|
/** Deduplicate Strict Mode double `useEffect` on the same mount. */
|
|
211
216
|
const promptParamHandledInEffectRef = useRef(false);
|
|
217
|
+
const pendingOpenChatAndSubmitRef = useRef<{
|
|
218
|
+
sessionId: string;
|
|
219
|
+
prompt: string;
|
|
220
|
+
} | null>(null);
|
|
212
221
|
const prevShellChatPanelOpenRef = useRef(shellChatPanelOpen);
|
|
213
222
|
/** This instance requested shell chat width (ignore other ChatSheet instances on the page). */
|
|
214
223
|
const openedShellChatRef = useRef(false);
|
|
@@ -405,6 +414,23 @@ export function useChatPanelChromeModel({
|
|
|
405
414
|
[startEmptyNewChat, onOpenChange],
|
|
406
415
|
);
|
|
407
416
|
|
|
417
|
+
const openNewChatAndSubmit = useCallback(
|
|
418
|
+
(prompt: string) => {
|
|
419
|
+
const sessionId = startEmptyNewChat();
|
|
420
|
+
if (sessionId == null) {
|
|
421
|
+
logger.warn('Chat submit: sign in to use the assistant.');
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
const trimmed = prompt.trim();
|
|
426
|
+
if (!trimmed) return;
|
|
427
|
+
|
|
428
|
+
pendingOpenChatAndSubmitRef.current = { sessionId, prompt: trimmed };
|
|
429
|
+
onOpenChange(true);
|
|
430
|
+
},
|
|
431
|
+
[startEmptyNewChat, onOpenChange],
|
|
432
|
+
);
|
|
433
|
+
|
|
408
434
|
/**
|
|
409
435
|
* App link: `?prompt=…` — open panel, pre-fill composer, strip param (read once on mount
|
|
410
436
|
* from `location.search`). If the selected session already has messages, `newChat()` first.
|
|
@@ -763,8 +789,15 @@ export function useChatPanelChromeModel({
|
|
|
763
789
|
],
|
|
764
790
|
);
|
|
765
791
|
|
|
792
|
+
useEffect(() => {
|
|
793
|
+
const pending = pendingOpenChatAndSubmitRef.current;
|
|
794
|
+
if (!pending || currentChatId !== pending.sessionId) return;
|
|
795
|
+
pendingOpenChatAndSubmitRef.current = null;
|
|
796
|
+
void handlePromptSubmit(pending.prompt);
|
|
797
|
+
}, [currentChatId, handlePromptSubmit]);
|
|
798
|
+
|
|
766
799
|
const submitPreset = useCallback(
|
|
767
|
-
async (preset: ChatPreset) => {
|
|
800
|
+
async (preset: ChatPreset, options?: { message?: string }) => {
|
|
768
801
|
const script = preset.script;
|
|
769
802
|
const scriptGraph = isPresetScriptGraph(script);
|
|
770
803
|
const hasLinearScript = Array.isArray(script) && script.length > 0;
|
|
@@ -779,7 +812,7 @@ export function useChatPanelChromeModel({
|
|
|
779
812
|
if (!isLocalDemo) {
|
|
780
813
|
if (!currentChatId) return;
|
|
781
814
|
endLocalDemoFlow(currentChatId);
|
|
782
|
-
await handlePromptSubmit(preset.text);
|
|
815
|
+
await handlePromptSubmit(options?.message ?? preset.text);
|
|
783
816
|
return;
|
|
784
817
|
}
|
|
785
818
|
|
|
@@ -1089,7 +1122,10 @@ export function useChatPanelChromeModel({
|
|
|
1089
1122
|
})
|
|
1090
1123
|
) {
|
|
1091
1124
|
// Chat open uses `startViewTransition`; nested transition here aborts first → AbortError overlay.
|
|
1092
|
-
setSidebarNavOpen(false, {
|
|
1125
|
+
setSidebarNavOpen(false, {
|
|
1126
|
+
viewTransition: false,
|
|
1127
|
+
layoutAutoClose: true,
|
|
1128
|
+
});
|
|
1093
1129
|
}
|
|
1094
1130
|
};
|
|
1095
1131
|
|
|
@@ -1301,6 +1337,7 @@ export function useChatPanelChromeModel({
|
|
|
1301
1337
|
toggleOpen,
|
|
1302
1338
|
newChat: startEmptyNewChat,
|
|
1303
1339
|
openNewChatWithPrefill,
|
|
1340
|
+
openNewChatAndSubmit,
|
|
1304
1341
|
chatPanelContainer,
|
|
1305
1342
|
};
|
|
1306
1343
|
}
|
|
@@ -93,7 +93,11 @@ function readInitialChatWidthPx(): number {
|
|
|
93
93
|
type SetPanelWidthOptions = { persist?: boolean };
|
|
94
94
|
|
|
95
95
|
/** Pass `viewTransition: false` to avoid nesting `document.startViewTransition` (e.g. chat open already animating). */
|
|
96
|
-
export type SetSidebarOpenOptions = {
|
|
96
|
+
export type SetSidebarOpenOptions = {
|
|
97
|
+
viewTransition?: boolean;
|
|
98
|
+
/** Nav closed for layout (chat/width); restore when chat closes — do not persist closed cookie. */
|
|
99
|
+
layoutAutoClose?: boolean;
|
|
100
|
+
};
|
|
97
101
|
|
|
98
102
|
type SidebarContextProps = {
|
|
99
103
|
isOpen: boolean;
|
|
@@ -178,6 +182,8 @@ function SidebarProvider({
|
|
|
178
182
|
const [chatPanelOpen, _setChatPanelOpen] = useState(false);
|
|
179
183
|
const sidebarWidthRef = useRef(sidebarWidthPx);
|
|
180
184
|
const chatWidthRef = useRef(chatWidthPx);
|
|
185
|
+
/** Left nav was auto-closed because chat opened on a narrow shell; reopen when chat closes. */
|
|
186
|
+
const sidebarAutoClosedForChatRef = useRef(false);
|
|
181
187
|
sidebarWidthRef.current = sidebarWidthPx;
|
|
182
188
|
chatWidthRef.current = chatWidthPx;
|
|
183
189
|
|
|
@@ -332,10 +338,8 @@ function SidebarProvider({
|
|
|
332
338
|
window.dispatchEvent(new CustomEvent(DISMISS_CHAT_FOR_LAYOUT_EVENT));
|
|
333
339
|
}
|
|
334
340
|
} else if (openingChat && isOpen) {
|
|
341
|
+
sidebarAutoClosedForChatRef.current = true;
|
|
335
342
|
setIsOpen(false);
|
|
336
|
-
if (getCookiePreferences(userId)?.functional) {
|
|
337
|
-
setCookie('isSidebarOpen', 'false', 60 * 60 * 24 * 7);
|
|
338
|
-
}
|
|
339
343
|
}
|
|
340
344
|
},
|
|
341
345
|
[
|
|
@@ -345,7 +349,6 @@ function SidebarProvider({
|
|
|
345
349
|
chatPanelOpen,
|
|
346
350
|
sidebarWidthPx,
|
|
347
351
|
chatWidthPx,
|
|
348
|
-
userId,
|
|
349
352
|
],
|
|
350
353
|
);
|
|
351
354
|
|
|
@@ -353,16 +356,32 @@ function SidebarProvider({
|
|
|
353
356
|
(open: boolean) => {
|
|
354
357
|
if (open) {
|
|
355
358
|
closeOppositeSidebarIfNoSpace(false, true);
|
|
359
|
+
_setChatPanelOpen(true);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
_setChatPanelOpen(false);
|
|
363
|
+
if (sidebarAutoClosedForChatRef.current) {
|
|
364
|
+
sidebarAutoClosedForChatRef.current = false;
|
|
365
|
+
setIsOpen(true);
|
|
366
|
+
if (getCookiePreferences(userId)?.functional) {
|
|
367
|
+
setCookie('isSidebarOpen', 'true', 60 * 60 * 24 * 7);
|
|
368
|
+
}
|
|
356
369
|
}
|
|
357
|
-
_setChatPanelOpen(open);
|
|
358
370
|
},
|
|
359
|
-
[closeOppositeSidebarIfNoSpace],
|
|
371
|
+
[closeOppositeSidebarIfNoSpace, userId],
|
|
360
372
|
);
|
|
361
373
|
|
|
362
374
|
const setOpen = useCallback(
|
|
363
375
|
(value: boolean, options?: SetSidebarOpenOptions) => {
|
|
376
|
+
const layoutAutoClose = options?.layoutAutoClose === true;
|
|
377
|
+
|
|
364
378
|
if (value) {
|
|
379
|
+
sidebarAutoClosedForChatRef.current = false;
|
|
365
380
|
closeOppositeSidebarIfNoSpace(true, false);
|
|
381
|
+
} else if (layoutAutoClose) {
|
|
382
|
+
sidebarAutoClosedForChatRef.current = true;
|
|
383
|
+
} else {
|
|
384
|
+
sidebarAutoClosedForChatRef.current = false;
|
|
366
385
|
}
|
|
367
386
|
|
|
368
387
|
const useViewTransition =
|
|
@@ -379,7 +398,7 @@ function SidebarProvider({
|
|
|
379
398
|
setIsOpen(value);
|
|
380
399
|
}
|
|
381
400
|
|
|
382
|
-
if (getCookiePreferences(userId)?.functional) {
|
|
401
|
+
if (!layoutAutoClose && getCookiePreferences(userId)?.functional) {
|
|
383
402
|
setCookie('isSidebarOpen', value.toString(), 60 * 60 * 24 * 7);
|
|
384
403
|
}
|
|
385
404
|
},
|
|
@@ -11,7 +11,7 @@ Host provides:
|
|
|
11
11
|
- Controlled `selectedDriver` + `setSelectedDriver`
|
|
12
12
|
- `isLoading` while fetching drivers
|
|
13
13
|
|
|
14
|
-
Report tile: `drivers_map` — tile resolves analysis id, fetches drivers, passes list + selection
|
|
14
|
+
Report tile: `drivers_map` — tile resolves analysis id, fetches drivers, passes list + selection.
|
|
15
15
|
|
|
16
16
|
Requires: `drivers`; `isLoading`; `selectedDriver`; `setSelectedDriver`.
|
|
17
17
|
|
|
@@ -12,9 +12,9 @@ Host provides:
|
|
|
12
12
|
- `seriesInitKey` when selected analysis changes
|
|
13
13
|
- `viewTab` / `onViewTabChange`: `lagged` (calendar-aligned, raw dates) or `overlapped` (driver series shifted backward by parsed lag months)
|
|
14
14
|
|
|
15
|
-
View tabs: host should render uilib `Tabs variant="button"` with **Lagged** / **Overlapped** in the toolbar
|
|
15
|
+
View tabs: host should render uilib `Tabs variant="button"` with **Lagged** / **Overlapped** in the toolbar. Chart applies `applyDriversComparisonViewToPayload` internally.
|
|
16
16
|
|
|
17
|
-
Report tile: `drivers_comparison_chart` — host loads normalized backtests payload + dataset historical
|
|
17
|
+
Report tile: `drivers_comparison_chart` — host loads normalized backtests payload + dataset historical.
|
|
18
18
|
|
|
19
19
|
Requires: `payload` — target + driver normalized_series; `loading` / `chartLoading` — spinners; `seriesInitKey` — reset visible series on analysis or view tab change; `runAnalysisHint` / `statusHint` — empty/error text.
|
|
20
20
|
|
|
@@ -8,10 +8,9 @@ Not when: simple forecast card or driver backtests — use ChartAreaInteractive
|
|
|
8
8
|
Host provides:
|
|
9
9
|
|
|
10
10
|
- `performanceData` (PerformanceChartPayload) and `historicalData` from performance API
|
|
11
|
-
- Analysis selection and fetch outside widget
|
|
12
11
|
- Optional `forecastData`, `customPerformanceMatrix`, `userSeries` for spaghetti
|
|
13
12
|
|
|
14
|
-
Report tile: `performance_chart` — host loads performance payload + dataset series
|
|
13
|
+
Report tile: `performance_chart` — host loads performance payload + dataset series.
|
|
15
14
|
|
|
16
15
|
Requires: `performanceData` — model/drift forecasts and metrics; `historicalData` — baseline series; `loading` / `chartLoading` / `performanceDataLoading` — spinners; `runAnalysisHint` / `statusHint` — empty states.
|
|
17
16
|
|