@smartspace/chat-ui 1.14.4-dev.65f646d → 1.14.4-dev.b35149c
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/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +147 -1
- package/dist/index.js +1188 -486
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import MuiButton from '@mui/material/Button';
|
|
2
|
-
import
|
|
3
|
-
import { Loader2,
|
|
4
|
-
import * as
|
|
5
|
-
import { createContext, forwardRef, useImperativeHandle, useRef, useState, useEffect, useMemo, useCallback, useContext, useSyncExternalStore } from 'react';
|
|
2
|
+
import IconButton2 from '@mui/material/IconButton';
|
|
3
|
+
import { Loader2, ChevronDown, Check, Cpu, SlidersHorizontal, X, Globe, Zap, Square, Mic, Paperclip, Send, Minimize2, AlertTriangle, FileImage, FileVideo, FileAudio, FileArchive, FileCode, FileSpreadsheet, Presentation, FileText, ChevronUp, ExternalLink, Download, ShieldAlert, Copy } from 'lucide-react';
|
|
4
|
+
import * as React9 from 'react';
|
|
5
|
+
import React9__default, { createContext, forwardRef, useImperativeHandle, useRef, useState, useEffect, useMemo, useCallback, useContext, useSyncExternalStore } from 'react';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
|
-
import { useQuery, queryOptions, useQueryClient, useMutation
|
|
8
|
+
import { useQuery, queryOptions, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
9
9
|
import { toast } from 'sonner';
|
|
10
10
|
import { ChatZod } from '@smartspace/api-client';
|
|
11
11
|
import { z } from 'zod';
|
|
@@ -17,14 +17,13 @@ import { codeBlockSchema, commonmark } from '@milkdown/preset-commonmark';
|
|
|
17
17
|
import { Slice, NodeType } from '@milkdown/prose/model';
|
|
18
18
|
import { MilkdownProvider, useEditor, Milkdown } from '@milkdown/react';
|
|
19
19
|
import { PluginKey, Plugin } from '@milkdown/prose/state';
|
|
20
|
-
import {
|
|
20
|
+
import { DecorationSet, Decoration } from '@milkdown/prose/view';
|
|
21
21
|
import 'crypto';
|
|
22
22
|
import '@milkdown/prose';
|
|
23
23
|
import '@milkdown/prose/inputrules';
|
|
24
24
|
import { withJsonFormsControlProps, withJsonFormsLayoutProps, JsonForms, ResolvedJsonFormsDispatch } from '@jsonforms/react';
|
|
25
25
|
import { rankWith, uiTypeIs, createAjv } from '@jsonforms/core';
|
|
26
26
|
import { vanillaRenderers, vanillaCells } from '@jsonforms/vanilla-renderers';
|
|
27
|
-
import { FormControl, InputLabel, Select, MenuItem, useTheme, Box, Skeleton as Skeleton$1 } from '@mui/material';
|
|
28
27
|
import 'ace-builds/src-noconflict/ace';
|
|
29
28
|
import 'ace-builds/src-noconflict/ext-language_tools';
|
|
30
29
|
import 'ace-builds/src-noconflict/mode-json';
|
|
@@ -57,6 +56,7 @@ import relativeTime from 'dayjs/plugin/relativeTime';
|
|
|
57
56
|
import utc from 'dayjs/plugin/utc';
|
|
58
57
|
import { Slot } from '@radix-ui/react-slot';
|
|
59
58
|
import { cva } from 'class-variance-authority';
|
|
59
|
+
import { useTheme, Box, Skeleton as Skeleton$1 } from '@mui/material';
|
|
60
60
|
|
|
61
61
|
var __defProp = Object.defineProperty;
|
|
62
62
|
var __export = (target, all5) => {
|
|
@@ -600,9 +600,14 @@ var useThread = ({
|
|
|
600
600
|
};
|
|
601
601
|
var useThreadIsRunning = (workspaceId, threadId) => {
|
|
602
602
|
const queryClient = useQueryClient();
|
|
603
|
+
const service = useChatService();
|
|
603
604
|
const { data: detailThread } = useQuery({
|
|
604
|
-
|
|
605
|
-
|
|
605
|
+
...threadDetailOptions({
|
|
606
|
+
service,
|
|
607
|
+
workspaceId: workspaceId ?? "",
|
|
608
|
+
threadId: threadId ?? ""
|
|
609
|
+
}),
|
|
610
|
+
enabled: false
|
|
606
611
|
});
|
|
607
612
|
const listThread = workspaceId && threadId ? getThreadPlaceholderFromListCache(queryClient, workspaceId, threadId) : void 0;
|
|
608
613
|
const { data: optimistic } = useQuery({
|
|
@@ -837,6 +842,37 @@ function useMessages(threadId) {
|
|
|
837
842
|
});
|
|
838
843
|
}
|
|
839
844
|
|
|
845
|
+
// src/domains/speech/queryKeys.ts
|
|
846
|
+
var speechKeys = {
|
|
847
|
+
all: ["speech"],
|
|
848
|
+
config: () => [...speechKeys.all, "config"]
|
|
849
|
+
};
|
|
850
|
+
|
|
851
|
+
// src/domains/speech/queries.ts
|
|
852
|
+
var unavailable = { enabled: false, defaultLocale: "en-US" };
|
|
853
|
+
var isNotFound = (error) => error?.type === "NotFound" || error?.response?.status === 404;
|
|
854
|
+
function useSpeechConfig() {
|
|
855
|
+
const service = useChatService();
|
|
856
|
+
const supported = !!service.getSpeechConfig && !!service.getSpeechToken;
|
|
857
|
+
return useQuery({
|
|
858
|
+
...queryOptions({
|
|
859
|
+
queryKey: speechKeys.config(),
|
|
860
|
+
queryFn: async () => {
|
|
861
|
+
try {
|
|
862
|
+
return await service.getSpeechConfig?.() ?? unavailable;
|
|
863
|
+
} catch (error) {
|
|
864
|
+
if (isNotFound(error)) return unavailable;
|
|
865
|
+
throw error;
|
|
866
|
+
}
|
|
867
|
+
},
|
|
868
|
+
staleTime: Infinity,
|
|
869
|
+
retry: (failureCount) => failureCount < 2,
|
|
870
|
+
retryDelay: 1e3
|
|
871
|
+
}),
|
|
872
|
+
enabled: supported
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
|
|
840
876
|
// ../../node_modules/.pnpm/@milkdown+exception@7.20.0/node_modules/@milkdown/exception/lib/index.js
|
|
841
877
|
var ErrorCode = /* @__PURE__ */ (function(ErrorCode2) {
|
|
842
878
|
ErrorCode2["docTypeError"] = "docTypeError";
|
|
@@ -970,6 +1006,75 @@ var autolink = $prose(() => {
|
|
|
970
1006
|
}
|
|
971
1007
|
});
|
|
972
1008
|
});
|
|
1009
|
+
var dictationGhostKey = new PluginKey("dictationGhost");
|
|
1010
|
+
function buildDecorations2(state, text6) {
|
|
1011
|
+
const doc = state.doc;
|
|
1012
|
+
const from = state.selection.head;
|
|
1013
|
+
const before = from > 0 ? doc.textBetween(from - 1, from, " ") : "";
|
|
1014
|
+
const display = before !== "" && !/\s/.test(before) ? ` ${text6}` : text6;
|
|
1015
|
+
const widget = Decoration.widget(
|
|
1016
|
+
from,
|
|
1017
|
+
() => {
|
|
1018
|
+
const span = document.createElement("span");
|
|
1019
|
+
span.className = "md-editor__dictation-ghost";
|
|
1020
|
+
span.setAttribute("aria-hidden", "true");
|
|
1021
|
+
span.appendChild(document.createTextNode(display));
|
|
1022
|
+
const dots = document.createElement("span");
|
|
1023
|
+
dots.className = "md-editor__dictation-dots";
|
|
1024
|
+
for (let i = 0; i < 3; i += 1)
|
|
1025
|
+
dots.appendChild(document.createElement("span"));
|
|
1026
|
+
span.appendChild(dots);
|
|
1027
|
+
return span;
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
// Render after the caret so typing still lands where the user expects.
|
|
1031
|
+
side: 1,
|
|
1032
|
+
// Keyed by content so ProseMirror reuses the node between renders instead
|
|
1033
|
+
// of tearing it down on every interim result.
|
|
1034
|
+
key: `dictation-ghost:${display}`
|
|
1035
|
+
}
|
|
1036
|
+
);
|
|
1037
|
+
const decorations = [widget];
|
|
1038
|
+
const $head = state.selection.$head;
|
|
1039
|
+
if ($head.depth > 0) {
|
|
1040
|
+
decorations.push(
|
|
1041
|
+
Decoration.node($head.before(), $head.after(), {
|
|
1042
|
+
class: "md-editor__has-dictation-ghost"
|
|
1043
|
+
})
|
|
1044
|
+
);
|
|
1045
|
+
}
|
|
1046
|
+
return DecorationSet.create(doc, decorations);
|
|
1047
|
+
}
|
|
1048
|
+
var dictationGhost = $prose(() => {
|
|
1049
|
+
return new Plugin({
|
|
1050
|
+
key: dictationGhostKey,
|
|
1051
|
+
state: {
|
|
1052
|
+
init: () => "",
|
|
1053
|
+
apply(tr, previous2) {
|
|
1054
|
+
const meta = tr.getMeta(dictationGhostKey);
|
|
1055
|
+
if (meta) return meta.text;
|
|
1056
|
+
if (tr.docChanged || tr.selectionSet) return "";
|
|
1057
|
+
return previous2;
|
|
1058
|
+
}
|
|
1059
|
+
},
|
|
1060
|
+
props: {
|
|
1061
|
+
decorations(state) {
|
|
1062
|
+
const text6 = dictationGhostKey.getState(state) ?? "";
|
|
1063
|
+
if (!text6) return DecorationSet.empty;
|
|
1064
|
+
return buildDecorations2(state, text6);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
});
|
|
1068
|
+
});
|
|
1069
|
+
function setDictationGhost(view, text6) {
|
|
1070
|
+
const current = dictationGhostKey.getState(view.state) ?? "";
|
|
1071
|
+
if (current === text6) return;
|
|
1072
|
+
const tr = view.state.tr.setMeta(dictationGhostKey, {
|
|
1073
|
+
text: text6
|
|
1074
|
+
});
|
|
1075
|
+
tr.setMeta("addToHistory", false);
|
|
1076
|
+
view.dispatch(tr);
|
|
1077
|
+
}
|
|
973
1078
|
|
|
974
1079
|
// src/shared/markdown/extensions/fileTag.ts
|
|
975
1080
|
var fileTag = $node("fileTag", () => ({
|
|
@@ -1879,7 +1984,7 @@ function EditorInner({
|
|
|
1879
1984
|
} catch {
|
|
1880
1985
|
}
|
|
1881
1986
|
});
|
|
1882
|
-
}).use(commonmark).use(history).use(clipboard).use(listener).use(autolink).use(fileTag).use(ssImageNode).use(ssImageView).use(htmlPreviewView).use(enableMentions ? mention : fileTag);
|
|
1987
|
+
}).use(commonmark).use(history).use(clipboard).use(listener).use(autolink).use(dictationGhost).use(fileTag).use(ssImageNode).use(ssImageView).use(htmlPreviewView).use(enableMentions ? mention : fileTag);
|
|
1883
1988
|
},
|
|
1884
1989
|
[isEditable]
|
|
1885
1990
|
);
|
|
@@ -2089,6 +2194,25 @@ function EditorInner({
|
|
|
2089
2194
|
return value ?? "";
|
|
2090
2195
|
}
|
|
2091
2196
|
},
|
|
2197
|
+
insertText: (text6) => {
|
|
2198
|
+
const view = viewRef.current;
|
|
2199
|
+
if (!view || !isEditable || !text6) return;
|
|
2200
|
+
try {
|
|
2201
|
+
const { from } = view.state.selection;
|
|
2202
|
+
const before = from > 0 ? view.state.doc.textBetween(from - 1, from, " ") : "";
|
|
2203
|
+
const needsSpace = before !== "" && !/\s/.test(before);
|
|
2204
|
+
insertTextAtSelection(view, (needsSpace ? " " : "") + text6);
|
|
2205
|
+
} catch {
|
|
2206
|
+
}
|
|
2207
|
+
},
|
|
2208
|
+
setDictationGhost: (text6) => {
|
|
2209
|
+
const view = viewRef.current;
|
|
2210
|
+
if (!view || !isEditable) return;
|
|
2211
|
+
try {
|
|
2212
|
+
setDictationGhost(view, text6);
|
|
2213
|
+
} catch {
|
|
2214
|
+
}
|
|
2215
|
+
},
|
|
2092
2216
|
clear: () => {
|
|
2093
2217
|
const view = viewRef.current;
|
|
2094
2218
|
if (!view) return;
|
|
@@ -2432,6 +2556,326 @@ var MarkdownEditor = forwardRef((props, ref) => {
|
|
|
2432
2556
|
return /* @__PURE__ */ jsx(MilkdownProvider, { children: /* @__PURE__ */ jsx(EditorInner, { ...props, editorHandleRef: ref }) });
|
|
2433
2557
|
});
|
|
2434
2558
|
MarkdownEditor.displayName = "MarkdownEditor";
|
|
2559
|
+
var TOKEN_EXPIRY_MARGIN_MS = 15e3;
|
|
2560
|
+
var noLevelMonitor = () => void 0;
|
|
2561
|
+
var SILENCE_HINT_MS = 6e3;
|
|
2562
|
+
var SILENCE_LEVEL = 3;
|
|
2563
|
+
function monitorInputLevel(stream, onSilent, onSound) {
|
|
2564
|
+
let context;
|
|
2565
|
+
let source;
|
|
2566
|
+
let analyser;
|
|
2567
|
+
try {
|
|
2568
|
+
context = new AudioContext();
|
|
2569
|
+
source = context.createMediaStreamSource(stream);
|
|
2570
|
+
analyser = context.createAnalyser();
|
|
2571
|
+
analyser.fftSize = 512;
|
|
2572
|
+
source.connect(analyser);
|
|
2573
|
+
} catch {
|
|
2574
|
+
return () => void 0;
|
|
2575
|
+
}
|
|
2576
|
+
if (context.state === "suspended")
|
|
2577
|
+
void context.resume().catch(() => void 0);
|
|
2578
|
+
const samples = new Uint8Array(analyser.fftSize);
|
|
2579
|
+
let lastSound = Date.now();
|
|
2580
|
+
let silent = false;
|
|
2581
|
+
let stopped = false;
|
|
2582
|
+
const poll = window.setInterval(() => {
|
|
2583
|
+
if (context.state !== "running") return;
|
|
2584
|
+
analyser.getByteTimeDomainData(samples);
|
|
2585
|
+
let peak = 0;
|
|
2586
|
+
for (const sample of samples) peak = Math.max(peak, Math.abs(sample - 128));
|
|
2587
|
+
if (peak > SILENCE_LEVEL) {
|
|
2588
|
+
lastSound = Date.now();
|
|
2589
|
+
if (silent) {
|
|
2590
|
+
silent = false;
|
|
2591
|
+
onSound();
|
|
2592
|
+
}
|
|
2593
|
+
} else if (!silent && Date.now() - lastSound > SILENCE_HINT_MS) {
|
|
2594
|
+
silent = true;
|
|
2595
|
+
onSilent();
|
|
2596
|
+
}
|
|
2597
|
+
}, 250);
|
|
2598
|
+
return () => {
|
|
2599
|
+
if (stopped) return;
|
|
2600
|
+
stopped = true;
|
|
2601
|
+
window.clearInterval(poll);
|
|
2602
|
+
try {
|
|
2603
|
+
source.disconnect();
|
|
2604
|
+
void context.close().catch(() => void 0);
|
|
2605
|
+
} catch {
|
|
2606
|
+
}
|
|
2607
|
+
};
|
|
2608
|
+
}
|
|
2609
|
+
var STALE_TOKEN_FLOOR_MS = 6e4;
|
|
2610
|
+
function kickOff(fn) {
|
|
2611
|
+
let promise;
|
|
2612
|
+
try {
|
|
2613
|
+
promise = Promise.resolve(fn());
|
|
2614
|
+
} catch (e) {
|
|
2615
|
+
promise = Promise.reject(e);
|
|
2616
|
+
}
|
|
2617
|
+
promise.catch(() => void 0);
|
|
2618
|
+
return promise;
|
|
2619
|
+
}
|
|
2620
|
+
var isSupported = () => typeof window !== "undefined" && window.isSecureContext && !!navigator.mediaDevices?.getUserMedia;
|
|
2621
|
+
function classifyTokenFailure(error) {
|
|
2622
|
+
const code3 = error?.code;
|
|
2623
|
+
if (code3 === "SP500") return "unavailable";
|
|
2624
|
+
if (error?.type === "NotFound") {
|
|
2625
|
+
return "unavailable";
|
|
2626
|
+
}
|
|
2627
|
+
return "unavailable-temporarily";
|
|
2628
|
+
}
|
|
2629
|
+
function useDictation({
|
|
2630
|
+
region,
|
|
2631
|
+
locale,
|
|
2632
|
+
getToken,
|
|
2633
|
+
onPhrase,
|
|
2634
|
+
onInterim,
|
|
2635
|
+
maxDurationMs = 18e4,
|
|
2636
|
+
idleTimeoutMs = 2e4
|
|
2637
|
+
}) {
|
|
2638
|
+
const [state, setState] = useState("idle");
|
|
2639
|
+
const [error, setError] = useState(null);
|
|
2640
|
+
const [deviceLabel, setDeviceLabel] = useState("");
|
|
2641
|
+
const [silent, setSilent] = useState(false);
|
|
2642
|
+
const sessionRef = useRef(null);
|
|
2643
|
+
const generationRef = useRef(0);
|
|
2644
|
+
const onPhraseRef = useRef(onPhrase);
|
|
2645
|
+
const onInterimRef = useRef(onInterim);
|
|
2646
|
+
useEffect(() => {
|
|
2647
|
+
onPhraseRef.current = onPhrase;
|
|
2648
|
+
onInterimRef.current = onInterim;
|
|
2649
|
+
});
|
|
2650
|
+
const clearInterim = useCallback(() => onInterimRef.current?.(""), []);
|
|
2651
|
+
const supported = isSupported();
|
|
2652
|
+
const available = supported && !!region && !!getToken;
|
|
2653
|
+
useEffect(() => {
|
|
2654
|
+
if (!available) return;
|
|
2655
|
+
const nav = navigator;
|
|
2656
|
+
if (nav.connection?.saveData) return;
|
|
2657
|
+
const warm = () => void kickOff(() => import('microsoft-cognitiveservices-speech-sdk'));
|
|
2658
|
+
if (typeof window.requestIdleCallback === "function") {
|
|
2659
|
+
const id2 = window.requestIdleCallback(warm, { timeout: 2e3 });
|
|
2660
|
+
return () => window.cancelIdleCallback(id2);
|
|
2661
|
+
}
|
|
2662
|
+
const id = window.setTimeout(warm, 1500);
|
|
2663
|
+
return () => window.clearTimeout(id);
|
|
2664
|
+
}, [available]);
|
|
2665
|
+
const stop = useCallback(() => {
|
|
2666
|
+
generationRef.current += 1;
|
|
2667
|
+
const session = sessionRef.current;
|
|
2668
|
+
sessionRef.current = null;
|
|
2669
|
+
clearInterim();
|
|
2670
|
+
setState("idle");
|
|
2671
|
+
setSilent(false);
|
|
2672
|
+
setDeviceLabel("");
|
|
2673
|
+
if (!session) return;
|
|
2674
|
+
window.clearTimeout(session.timers.idle);
|
|
2675
|
+
window.clearTimeout(session.timers.max);
|
|
2676
|
+
session.stopLevelMonitor();
|
|
2677
|
+
session.stream.getTracks().forEach((t) => t.stop());
|
|
2678
|
+
session.recognizer.stopContinuousRecognitionAsync(
|
|
2679
|
+
() => session.recognizer.close(),
|
|
2680
|
+
() => session.recognizer.close()
|
|
2681
|
+
);
|
|
2682
|
+
}, [clearInterim]);
|
|
2683
|
+
const start = useCallback(async () => {
|
|
2684
|
+
if (!available || sessionRef.current) return;
|
|
2685
|
+
const generation = ++generationRef.current;
|
|
2686
|
+
const superseded = () => generationRef.current !== generation;
|
|
2687
|
+
setError(null);
|
|
2688
|
+
setSilent(false);
|
|
2689
|
+
setState("starting");
|
|
2690
|
+
const streamPromise = kickOff(
|
|
2691
|
+
() => navigator.mediaDevices.getUserMedia({
|
|
2692
|
+
audio: {
|
|
2693
|
+
echoCancellation: true,
|
|
2694
|
+
noiseSuppression: true,
|
|
2695
|
+
autoGainControl: true
|
|
2696
|
+
}
|
|
2697
|
+
})
|
|
2698
|
+
);
|
|
2699
|
+
const tokenPromise = kickOff(getToken);
|
|
2700
|
+
const sdkPromise = kickOff(
|
|
2701
|
+
() => import('microsoft-cognitiveservices-speech-sdk')
|
|
2702
|
+
);
|
|
2703
|
+
let stream;
|
|
2704
|
+
try {
|
|
2705
|
+
stream = await streamPromise;
|
|
2706
|
+
} catch (e) {
|
|
2707
|
+
if (superseded()) return;
|
|
2708
|
+
const name = e?.name;
|
|
2709
|
+
setError(
|
|
2710
|
+
name === "NotAllowedError" || name === "SecurityError" ? "permission-denied" : name === "NotFoundError" || name === "OverconstrainedError" ? "no-microphone" : "unknown"
|
|
2711
|
+
);
|
|
2712
|
+
setState("idle");
|
|
2713
|
+
return;
|
|
2714
|
+
}
|
|
2715
|
+
if (superseded()) {
|
|
2716
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
2717
|
+
return;
|
|
2718
|
+
}
|
|
2719
|
+
let token;
|
|
2720
|
+
try {
|
|
2721
|
+
token = await tokenPromise;
|
|
2722
|
+
if (Date.parse(token.expiresOn) - Date.now() < STALE_TOKEN_FLOOR_MS) {
|
|
2723
|
+
token = await getToken();
|
|
2724
|
+
}
|
|
2725
|
+
} catch (e) {
|
|
2726
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
2727
|
+
if (superseded()) return;
|
|
2728
|
+
setError(classifyTokenFailure(e));
|
|
2729
|
+
setState("idle");
|
|
2730
|
+
return;
|
|
2731
|
+
}
|
|
2732
|
+
if (superseded()) {
|
|
2733
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
2734
|
+
return;
|
|
2735
|
+
}
|
|
2736
|
+
let recognizer = null;
|
|
2737
|
+
let published = null;
|
|
2738
|
+
try {
|
|
2739
|
+
const sdk = await sdkPromise;
|
|
2740
|
+
if (superseded()) {
|
|
2741
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
2742
|
+
return;
|
|
2743
|
+
}
|
|
2744
|
+
const speechConfig = sdk.SpeechConfig.fromAuthorizationToken(
|
|
2745
|
+
token.token,
|
|
2746
|
+
region
|
|
2747
|
+
);
|
|
2748
|
+
speechConfig.speechRecognitionLanguage = locale;
|
|
2749
|
+
speechConfig.setProfanity(sdk.ProfanityOption.Raw);
|
|
2750
|
+
speechConfig.setProperty(
|
|
2751
|
+
sdk.PropertyId.Speech_SegmentationSilenceTimeoutMs,
|
|
2752
|
+
"700"
|
|
2753
|
+
);
|
|
2754
|
+
recognizer = new sdk.SpeechRecognizer(
|
|
2755
|
+
speechConfig,
|
|
2756
|
+
sdk.AudioConfig.fromStreamInput(stream)
|
|
2757
|
+
);
|
|
2758
|
+
const untilExpiry = Date.parse(token.expiresOn) - Date.now() - TOKEN_EXPIRY_MARGIN_MS;
|
|
2759
|
+
const sessionCapMs = Number.isFinite(untilExpiry) && untilExpiry > 0 ? Math.min(maxDurationMs, untilExpiry) : maxDurationMs;
|
|
2760
|
+
const session = {
|
|
2761
|
+
recognizer,
|
|
2762
|
+
stream,
|
|
2763
|
+
timers: {},
|
|
2764
|
+
stopLevelMonitor: noLevelMonitor
|
|
2765
|
+
};
|
|
2766
|
+
const armIdle = () => {
|
|
2767
|
+
window.clearTimeout(session.timers.idle);
|
|
2768
|
+
session.timers.idle = window.setTimeout(stop, idleTimeoutMs);
|
|
2769
|
+
};
|
|
2770
|
+
const isLive = () => sessionRef.current === session;
|
|
2771
|
+
sessionRef.current = session;
|
|
2772
|
+
published = session;
|
|
2773
|
+
const goLive = () => {
|
|
2774
|
+
if (!isLive()) return;
|
|
2775
|
+
session.timers.max ??= window.setTimeout(stop, sessionCapMs);
|
|
2776
|
+
if (session.stopLevelMonitor === noLevelMonitor) {
|
|
2777
|
+
try {
|
|
2778
|
+
setDeviceLabel(stream.getAudioTracks()[0]?.label ?? "");
|
|
2779
|
+
session.stopLevelMonitor = monitorInputLevel(
|
|
2780
|
+
stream,
|
|
2781
|
+
() => {
|
|
2782
|
+
if (isLive()) setSilent(true);
|
|
2783
|
+
},
|
|
2784
|
+
() => {
|
|
2785
|
+
if (isLive()) setSilent(false);
|
|
2786
|
+
}
|
|
2787
|
+
);
|
|
2788
|
+
} catch {
|
|
2789
|
+
session.stopLevelMonitor = noLevelMonitor;
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
armIdle();
|
|
2793
|
+
setState("listening");
|
|
2794
|
+
};
|
|
2795
|
+
recognizer.sessionStarted = () => goLive();
|
|
2796
|
+
recognizer.recognizing = (_sender, event) => {
|
|
2797
|
+
if (!isLive()) return;
|
|
2798
|
+
onInterimRef.current?.(event.result.text ?? "");
|
|
2799
|
+
armIdle();
|
|
2800
|
+
};
|
|
2801
|
+
recognizer.recognized = (_sender, event) => {
|
|
2802
|
+
if (!isLive()) return;
|
|
2803
|
+
const text6 = event.result.text?.trim();
|
|
2804
|
+
clearInterim();
|
|
2805
|
+
if (event.result.reason === sdk.ResultReason.RecognizedSpeech && text6) {
|
|
2806
|
+
onPhraseRef.current(text6);
|
|
2807
|
+
}
|
|
2808
|
+
armIdle();
|
|
2809
|
+
};
|
|
2810
|
+
recognizer.canceled = (_sender, event) => {
|
|
2811
|
+
if (!isLive()) return;
|
|
2812
|
+
if (event.reason === sdk.CancellationReason.Error) {
|
|
2813
|
+
console.warn("[dictation] cancelled, errorCode:", event.errorCode);
|
|
2814
|
+
setError(
|
|
2815
|
+
event.errorCode === sdk.CancellationErrorCode.ConnectionFailure ? "network" : event.errorCode === sdk.CancellationErrorCode.AuthenticationFailure ? "unavailable-temporarily" : "unknown"
|
|
2816
|
+
);
|
|
2817
|
+
}
|
|
2818
|
+
stop();
|
|
2819
|
+
};
|
|
2820
|
+
recognizer.sessionStopped = () => {
|
|
2821
|
+
if (isLive()) stop();
|
|
2822
|
+
};
|
|
2823
|
+
try {
|
|
2824
|
+
const connection = sdk.Connection.fromRecognizer(recognizer);
|
|
2825
|
+
connection.connected = () => goLive();
|
|
2826
|
+
connection.openConnection();
|
|
2827
|
+
} catch {
|
|
2828
|
+
}
|
|
2829
|
+
await new Promise(
|
|
2830
|
+
(resolve, reject) => session.recognizer.startContinuousRecognitionAsync(resolve, reject)
|
|
2831
|
+
);
|
|
2832
|
+
goLive();
|
|
2833
|
+
} catch (e) {
|
|
2834
|
+
stream.getTracks().forEach((t) => t.stop());
|
|
2835
|
+
try {
|
|
2836
|
+
recognizer?.close();
|
|
2837
|
+
} catch {
|
|
2838
|
+
}
|
|
2839
|
+
if (published) {
|
|
2840
|
+
window.clearTimeout(published.timers.idle);
|
|
2841
|
+
window.clearTimeout(published.timers.max);
|
|
2842
|
+
published.stopLevelMonitor();
|
|
2843
|
+
if (sessionRef.current === published) sessionRef.current = null;
|
|
2844
|
+
}
|
|
2845
|
+
if (superseded()) return;
|
|
2846
|
+
console.warn("[dictation] failed to start:", e);
|
|
2847
|
+
setError((prev) => prev ?? "unavailable-temporarily");
|
|
2848
|
+
setState("idle");
|
|
2849
|
+
}
|
|
2850
|
+
}, [
|
|
2851
|
+
available,
|
|
2852
|
+
clearInterim,
|
|
2853
|
+
getToken,
|
|
2854
|
+
idleTimeoutMs,
|
|
2855
|
+
locale,
|
|
2856
|
+
maxDurationMs,
|
|
2857
|
+
region,
|
|
2858
|
+
stop
|
|
2859
|
+
]);
|
|
2860
|
+
useEffect(() => stop, [stop]);
|
|
2861
|
+
const toggle = useCallback(() => {
|
|
2862
|
+
if (state === "idle") void start();
|
|
2863
|
+
else stop();
|
|
2864
|
+
}, [start, state, stop]);
|
|
2865
|
+
return {
|
|
2866
|
+
supported,
|
|
2867
|
+
available,
|
|
2868
|
+
state,
|
|
2869
|
+
error,
|
|
2870
|
+
/** Name of the microphone in use, once a session is live. May be ''. */
|
|
2871
|
+
deviceLabel,
|
|
2872
|
+
/** Listening, but the microphone has produced no sound for a while. */
|
|
2873
|
+
silent,
|
|
2874
|
+
start,
|
|
2875
|
+
stop,
|
|
2876
|
+
toggle
|
|
2877
|
+
};
|
|
2878
|
+
}
|
|
2435
2879
|
function useFlowRunVariables(flowRunId) {
|
|
2436
2880
|
const service = useChatService();
|
|
2437
2881
|
return useQuery({
|
|
@@ -2443,6 +2887,31 @@ function useFlowRunVariables(flowRunId) {
|
|
|
2443
2887
|
enabled: !!flowRunId
|
|
2444
2888
|
});
|
|
2445
2889
|
}
|
|
2890
|
+
|
|
2891
|
+
// src/chat-variables/renders/fieldStyles.ts
|
|
2892
|
+
var scaleFor = (surface) => surface === "form" ? "comfortable" : "dense";
|
|
2893
|
+
var fieldLabelClass = (scale) => `block truncate font-medium text-muted-foreground ${scale === "dense" ? "mb-1 text-xs" : "mb-1.5 text-sm"}`;
|
|
2894
|
+
var CONTROL_BASE = "rounded-md border bg-background text-foreground transition-colors placeholder:text-muted-foreground ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-60";
|
|
2895
|
+
var borderClass = (hasError) => hasError ? "border-destructive" : "border-input";
|
|
2896
|
+
var fieldControlClass = (scale, hasError) => `w-full ${CONTROL_BASE} ${borderClass(hasError)} ${scale === "dense" ? "px-2.5 py-1.5 text-xs" : "px-3 py-2 text-sm"}`;
|
|
2897
|
+
var fieldTriggerClass = (scale, hasError) => `w-full ${CONTROL_BASE} ${borderClass(
|
|
2898
|
+
hasError
|
|
2899
|
+
)} flex items-center justify-between gap-2 text-left ${scale === "dense" ? "h-8 px-2.5 text-xs" : "h-10 px-3 text-sm"}`;
|
|
2900
|
+
var fieldNumberClass = (scale, hasError) => `${CONTROL_BASE} ${borderClass(hasError)} tabular-nums ${scale === "dense" ? "h-8 w-20 px-2 text-xs" : "h-10 w-24 px-2.5 text-sm"}`;
|
|
2901
|
+
var fieldHintClass = "mt-1 text-xs text-muted-foreground";
|
|
2902
|
+
var fieldErrorClass = "mt-1 text-xs text-destructive";
|
|
2903
|
+
var fieldRowClass = "flex items-center justify-between gap-3";
|
|
2904
|
+
var fieldRowLabelClass = (scale) => `min-w-0 flex-1 truncate font-medium text-muted-foreground ${scale === "dense" ? "text-xs" : "text-sm"}`;
|
|
2905
|
+
var pillClass = (opts) => `flex h-8 shrink-0 items-center gap-1.5 rounded-full border px-2.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary ${opts.active ? "border-primary/30 bg-primary/10 text-primary" : "border-border/70 bg-transparent text-muted-foreground hover:bg-secondary"} ${opts.hasError ? "border-destructive text-destructive" : ""} ${opts.disabled ? "cursor-not-allowed opacity-60" : ""}`;
|
|
2906
|
+
var pillLabelClass = "max-w-[9rem] truncate";
|
|
2907
|
+
var pillValueClass = "max-w-[9rem] truncate text-foreground";
|
|
2908
|
+
var switchTrackClass = (on, disabled) => `peer inline-flex h-6 w-11 shrink-0 items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background ${on ? "bg-primary" : "bg-input"} ${disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"}`;
|
|
2909
|
+
var switchThumbClass = (on) => `pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform ${on ? "translate-x-5" : "translate-x-0"}`;
|
|
2910
|
+
var POPOVER_WIDTH_PX = 288;
|
|
2911
|
+
var POPOVER_MAX_HEIGHT_PX = 288;
|
|
2912
|
+
var popoverClass = "flex flex-col overflow-hidden rounded-xl border border-border bg-popover shadow-lg";
|
|
2913
|
+
var popoverRowClass = "flex w-full items-center gap-2.5 px-3 py-2 text-left transition-colors hover:bg-secondary/60";
|
|
2914
|
+
var popoverHeadingClass = "text-[10px] font-semibold uppercase tracking-wide text-muted-foreground";
|
|
2446
2915
|
function iconFor(label) {
|
|
2447
2916
|
const name = (label ?? "").toLowerCase();
|
|
2448
2917
|
if (/search|web|browse|internet/.test(name)) return Globe;
|
|
@@ -2458,7 +2927,8 @@ var BooleanRenderer = ({
|
|
|
2458
2927
|
errors,
|
|
2459
2928
|
uischema,
|
|
2460
2929
|
visible,
|
|
2461
|
-
enabled
|
|
2930
|
+
enabled,
|
|
2931
|
+
config
|
|
2462
2932
|
}) => {
|
|
2463
2933
|
const onToggle = useCallback(() => {
|
|
2464
2934
|
handleChange(path2, !data);
|
|
@@ -2469,13 +2939,17 @@ var BooleanRenderer = ({
|
|
|
2469
2939
|
const hasError = !!errors && errors.length > 0;
|
|
2470
2940
|
const isChecked = Boolean(data);
|
|
2471
2941
|
const Icon = iconFor(label);
|
|
2942
|
+
const surface = (config ?? {}).surface ?? "form";
|
|
2943
|
+
const scale = scaleFor(surface);
|
|
2472
2944
|
const tooltip = [label, description, hasError ? errors : null].filter(Boolean).join(" \u2014 ");
|
|
2473
|
-
|
|
2945
|
+
const toggle = /* @__PURE__ */ jsx(
|
|
2474
2946
|
"button",
|
|
2475
2947
|
{
|
|
2476
2948
|
id: `toggle-${path2}`,
|
|
2477
2949
|
type: "button",
|
|
2478
|
-
"
|
|
2950
|
+
role: surface === "bar" ? void 0 : "switch",
|
|
2951
|
+
"aria-pressed": surface === "bar" ? isChecked : void 0,
|
|
2952
|
+
"aria-checked": surface === "bar" ? void 0 : isChecked,
|
|
2479
2953
|
"aria-label": label,
|
|
2480
2954
|
title: tooltip || void 0,
|
|
2481
2955
|
onClick: onToggle,
|
|
@@ -2485,16 +2959,28 @@ var BooleanRenderer = ({
|
|
|
2485
2959
|
e.currentTarget.blur();
|
|
2486
2960
|
}
|
|
2487
2961
|
},
|
|
2488
|
-
className:
|
|
2489
|
-
|
|
2962
|
+
className: surface === "bar" ? `boolean-switch ${pillClass({
|
|
2963
|
+
active: isChecked,
|
|
2964
|
+
hasError,
|
|
2965
|
+
disabled: isDisabled
|
|
2966
|
+
})}` : switchTrackClass(isChecked, isDisabled),
|
|
2967
|
+
children: surface === "bar" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2490
2968
|
/* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
2491
2969
|
label && // Desktop-first: the app and the package each ship a full Tailwind
|
|
2492
|
-
// build, so a base `hidden` can out-order `sm:inline`.
|
|
2493
|
-
// is the form that survives both cascades.
|
|
2494
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
2495
|
-
]
|
|
2970
|
+
// build, so a base `hidden` can out-order `sm:inline`.
|
|
2971
|
+
// `max-sm:hidden` is the form that survives both cascades.
|
|
2972
|
+
/* @__PURE__ */ jsx("span", { className: `inline ${pillLabelClass} max-sm:hidden`, children: label })
|
|
2973
|
+
] }) : /* @__PURE__ */ jsx("span", { className: switchThumbClass(isChecked) })
|
|
2496
2974
|
}
|
|
2497
2975
|
);
|
|
2976
|
+
if (surface === "bar") return toggle;
|
|
2977
|
+
return /* @__PURE__ */ jsxs("div", { className: "ss-jsonforms-field ss-jsonforms-boolean", children: [
|
|
2978
|
+
/* @__PURE__ */ jsxs("div", { className: fieldRowClass, children: [
|
|
2979
|
+
/* @__PURE__ */ jsx("label", { htmlFor: `toggle-${path2}`, className: fieldRowLabelClass(scale), children: label }),
|
|
2980
|
+
toggle
|
|
2981
|
+
] }),
|
|
2982
|
+
hasError && /* @__PURE__ */ jsx("div", { className: fieldErrorClass, children: errors })
|
|
2983
|
+
] });
|
|
2498
2984
|
};
|
|
2499
2985
|
var booleanRendererTester = rankWith(40, (uischema, schema) => {
|
|
2500
2986
|
if (uischema.type !== "Control") return false;
|
|
@@ -2504,6 +2990,104 @@ var booleanRendererTester = rankWith(40, (uischema, schema) => {
|
|
|
2504
2990
|
return fieldSchema?.type === "boolean";
|
|
2505
2991
|
});
|
|
2506
2992
|
var BooleanRendererControl = withJsonFormsControlProps(BooleanRenderer);
|
|
2993
|
+
var GAP_PX = 8;
|
|
2994
|
+
var MIN_TRIGGER_WIDTH_PX = 224;
|
|
2995
|
+
var MIN_PANEL_HEIGHT_PX = 180;
|
|
2996
|
+
var NestedPopoverContext = React9__default.createContext(null);
|
|
2997
|
+
function useAnchoredPopover({
|
|
2998
|
+
trigger,
|
|
2999
|
+
popover,
|
|
3000
|
+
width,
|
|
3001
|
+
maxHeight,
|
|
3002
|
+
role,
|
|
3003
|
+
label
|
|
3004
|
+
}) {
|
|
3005
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
3006
|
+
const parentRegistry = useContext(NestedPopoverContext);
|
|
3007
|
+
const descendants = useRef(/* @__PURE__ */ new Set());
|
|
3008
|
+
const close = useCallback(() => setIsOpen(false), []);
|
|
3009
|
+
const toggle = useCallback(() => setIsOpen((open) => !open), []);
|
|
3010
|
+
const registry = useMemo(
|
|
3011
|
+
() => ({
|
|
3012
|
+
register: (el) => {
|
|
3013
|
+
descendants.current.add(el);
|
|
3014
|
+
parentRegistry?.register(el);
|
|
3015
|
+
},
|
|
3016
|
+
unregister: (el) => {
|
|
3017
|
+
descendants.current.delete(el);
|
|
3018
|
+
parentRegistry?.unregister(el);
|
|
3019
|
+
}
|
|
3020
|
+
}),
|
|
3021
|
+
[parentRegistry]
|
|
3022
|
+
);
|
|
3023
|
+
useEffect(() => {
|
|
3024
|
+
if (!isOpen || !parentRegistry) return;
|
|
3025
|
+
const el = popover.current;
|
|
3026
|
+
if (!el) return;
|
|
3027
|
+
parentRegistry.register(el);
|
|
3028
|
+
return () => parentRegistry.unregister(el);
|
|
3029
|
+
}, [isOpen, parentRegistry, popover]);
|
|
3030
|
+
useEffect(() => {
|
|
3031
|
+
if (!isOpen) return;
|
|
3032
|
+
const onPointerDown = (event) => {
|
|
3033
|
+
const target = event.target;
|
|
3034
|
+
if (trigger.current?.contains(target)) return;
|
|
3035
|
+
if (popover.current?.contains(target)) return;
|
|
3036
|
+
for (const el of descendants.current) {
|
|
3037
|
+
if (el.contains(target)) return;
|
|
3038
|
+
}
|
|
3039
|
+
close();
|
|
3040
|
+
};
|
|
3041
|
+
const onKeyDown = (event) => {
|
|
3042
|
+
if (event.key === "Escape") close();
|
|
3043
|
+
};
|
|
3044
|
+
document.addEventListener("mousedown", onPointerDown);
|
|
3045
|
+
document.addEventListener("keydown", onKeyDown);
|
|
3046
|
+
window.addEventListener("resize", close);
|
|
3047
|
+
return () => {
|
|
3048
|
+
document.removeEventListener("mousedown", onPointerDown);
|
|
3049
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
3050
|
+
window.removeEventListener("resize", close);
|
|
3051
|
+
};
|
|
3052
|
+
}, [isOpen, close, trigger, popover]);
|
|
3053
|
+
const renderPopover = (children2) => {
|
|
3054
|
+
if (!isOpen) return null;
|
|
3055
|
+
const anchor = trigger.current?.getBoundingClientRect();
|
|
3056
|
+
if (!anchor) return null;
|
|
3057
|
+
const panelWidth = width === "trigger" ? Math.max(anchor.width, MIN_TRIGGER_WIDTH_PX) : width;
|
|
3058
|
+
const spaceAbove = anchor.top - GAP_PX * 2;
|
|
3059
|
+
const spaceBelow = window.innerHeight - anchor.bottom - GAP_PX * 2;
|
|
3060
|
+
const openAbove = spaceAbove >= MIN_PANEL_HEIGHT_PX || spaceAbove >= spaceBelow;
|
|
3061
|
+
const panelMaxHeight = Math.max(
|
|
3062
|
+
0,
|
|
3063
|
+
Math.min(maxHeight, openAbove ? spaceAbove : spaceBelow)
|
|
3064
|
+
);
|
|
3065
|
+
return createPortal(
|
|
3066
|
+
/* @__PURE__ */ jsx(
|
|
3067
|
+
"div",
|
|
3068
|
+
{
|
|
3069
|
+
ref: popover,
|
|
3070
|
+
role,
|
|
3071
|
+
"aria-label": label,
|
|
3072
|
+
className: `fixed z-50 ${popoverClass}`,
|
|
3073
|
+
style: {
|
|
3074
|
+
width: panelWidth,
|
|
3075
|
+
maxWidth: `calc(100vw - ${GAP_PX * 4}px)`,
|
|
3076
|
+
left: Math.max(
|
|
3077
|
+
GAP_PX,
|
|
3078
|
+
Math.min(anchor.left, window.innerWidth - panelWidth - GAP_PX)
|
|
3079
|
+
),
|
|
3080
|
+
...openAbove ? { bottom: window.innerHeight - anchor.top + GAP_PX } : { top: anchor.bottom + GAP_PX },
|
|
3081
|
+
maxHeight: panelMaxHeight
|
|
3082
|
+
},
|
|
3083
|
+
children: /* @__PURE__ */ jsx(NestedPopoverContext.Provider, { value: registry, children: children2 })
|
|
3084
|
+
}
|
|
3085
|
+
),
|
|
3086
|
+
document.body
|
|
3087
|
+
);
|
|
3088
|
+
};
|
|
3089
|
+
return { isOpen, close, toggle, renderPopover };
|
|
3090
|
+
}
|
|
2507
3091
|
function hasConst(x) {
|
|
2508
3092
|
return !!x && typeof x === "object" && "const" in x;
|
|
2509
3093
|
}
|
|
@@ -2542,185 +3126,109 @@ var DropdownRenderer = ({
|
|
|
2542
3126
|
label,
|
|
2543
3127
|
description,
|
|
2544
3128
|
errors,
|
|
2545
|
-
|
|
3129
|
+
config,
|
|
3130
|
+
uischema,
|
|
3131
|
+
visible
|
|
2546
3132
|
}) => {
|
|
3133
|
+
const triggerRef = useRef(null);
|
|
3134
|
+
const listRef = useRef(null);
|
|
3135
|
+
const surface = (config ?? {}).surface ?? "form";
|
|
3136
|
+
const scale = scaleFor(surface);
|
|
3137
|
+
const { isOpen, close, toggle, renderPopover } = useAnchoredPopover({
|
|
3138
|
+
trigger: triggerRef,
|
|
3139
|
+
popover: listRef,
|
|
3140
|
+
// A select's list lines up with its own control.
|
|
3141
|
+
width: "trigger",
|
|
3142
|
+
maxHeight: POPOVER_MAX_HEIGHT_PX,
|
|
3143
|
+
role: "listbox",
|
|
3144
|
+
label: label || "Options"
|
|
3145
|
+
});
|
|
2547
3146
|
const options = toOptions(schema);
|
|
2548
|
-
const
|
|
2549
|
-
(
|
|
2550
|
-
handleChange(path2,
|
|
3147
|
+
const select = useCallback(
|
|
3148
|
+
(value) => {
|
|
3149
|
+
handleChange(path2, value);
|
|
3150
|
+
close();
|
|
2551
3151
|
},
|
|
2552
|
-
[handleChange, path2]
|
|
3152
|
+
[handleChange, path2, close]
|
|
2553
3153
|
);
|
|
2554
|
-
|
|
3154
|
+
if (!visible) return null;
|
|
2555
3155
|
const readOnly = uischema?.access === "Read";
|
|
2556
3156
|
const isDisabled = !enabled || readOnly;
|
|
2557
|
-
|
|
2558
|
-
|
|
3157
|
+
const hasError = !!errors;
|
|
3158
|
+
const selected = options.find((option) => option.const === data);
|
|
3159
|
+
const valueText = selected ? selected.title ?? String(selected.const) : data != null && data !== "" ? String(data) : "";
|
|
3160
|
+
const triggerId = `${path2}-trigger`;
|
|
3161
|
+
const isBar = surface === "bar";
|
|
3162
|
+
const placeholder = `Select ${(label || "value").toLowerCase()}\u2026`;
|
|
3163
|
+
const trigger = /* @__PURE__ */ jsxs(
|
|
3164
|
+
"button",
|
|
2559
3165
|
{
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
error: !!errors,
|
|
3166
|
+
id: triggerId,
|
|
3167
|
+
ref: triggerRef,
|
|
3168
|
+
type: "button",
|
|
2564
3169
|
disabled: isDisabled,
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
3170
|
+
onClick: toggle,
|
|
3171
|
+
"aria-haspopup": "listbox",
|
|
3172
|
+
"aria-expanded": isOpen,
|
|
3173
|
+
"aria-label": label,
|
|
3174
|
+
title: [label, valueText, hasError ? errors : null].filter(Boolean).join(" \u2014 ") || void 0,
|
|
3175
|
+
className: isBar ? `ss-jsonforms-select-trigger ${pillClass({
|
|
3176
|
+
active: isOpen,
|
|
3177
|
+
hasError,
|
|
3178
|
+
disabled: isDisabled
|
|
3179
|
+
})}` : `ss-jsonforms-select-trigger ${fieldTriggerClass(scale, hasError)}`,
|
|
2569
3180
|
children: [
|
|
3181
|
+
isBar && label && /* @__PURE__ */ jsx("span", { className: `inline ${pillLabelClass} max-sm:hidden`, children: label }),
|
|
2570
3182
|
/* @__PURE__ */ jsx(
|
|
2571
|
-
|
|
3183
|
+
"span",
|
|
2572
3184
|
{
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
color: "#6b7280",
|
|
2576
|
-
fontSize: "0.875rem",
|
|
2577
|
-
fontWeight: 500,
|
|
2578
|
-
"&.Mui-focused": {
|
|
2579
|
-
color: "#6366f1"
|
|
2580
|
-
},
|
|
2581
|
-
"&.Mui-error": {
|
|
2582
|
-
color: "#ef4444"
|
|
2583
|
-
}
|
|
2584
|
-
},
|
|
2585
|
-
children: label
|
|
3185
|
+
className: isBar ? pillValueClass : `min-w-0 flex-1 truncate ${valueText ? "" : "text-muted-foreground"}`,
|
|
3186
|
+
children: valueText || (isBar ? "\u2014" : placeholder)
|
|
2586
3187
|
}
|
|
2587
3188
|
),
|
|
2588
3189
|
/* @__PURE__ */ jsx(
|
|
2589
|
-
|
|
2590
|
-
{
|
|
2591
|
-
labelId: `${path2}-label`,
|
|
2592
|
-
value: displayValue,
|
|
2593
|
-
onChange: handleSelectionChange,
|
|
2594
|
-
label,
|
|
2595
|
-
sx: {
|
|
2596
|
-
"& .MuiOutlinedInput-root": {
|
|
2597
|
-
backgroundColor: "#fafafa",
|
|
2598
|
-
borderRadius: "8px",
|
|
2599
|
-
transition: "all 0.2s ease-in-out",
|
|
2600
|
-
height: "40px",
|
|
2601
|
-
// Same height as model dropdown
|
|
2602
|
-
"& fieldset": {
|
|
2603
|
-
borderColor: "#e5e7eb",
|
|
2604
|
-
borderWidth: "1px"
|
|
2605
|
-
},
|
|
2606
|
-
"&:hover": {
|
|
2607
|
-
backgroundColor: "#ffffff",
|
|
2608
|
-
"& fieldset": {
|
|
2609
|
-
borderColor: "#9ca3af"
|
|
2610
|
-
}
|
|
2611
|
-
},
|
|
2612
|
-
"&.Mui-focused": {
|
|
2613
|
-
backgroundColor: "#ffffff",
|
|
2614
|
-
"& fieldset": {
|
|
2615
|
-
borderColor: "#6366f1",
|
|
2616
|
-
borderWidth: "2px"
|
|
2617
|
-
}
|
|
2618
|
-
},
|
|
2619
|
-
"&.Mui-error": {
|
|
2620
|
-
"& fieldset": {
|
|
2621
|
-
borderColor: "#ef4444"
|
|
2622
|
-
}
|
|
2623
|
-
}
|
|
2624
|
-
},
|
|
2625
|
-
"& .MuiSelect-select": {
|
|
2626
|
-
backgroundColor: "#fafafa",
|
|
2627
|
-
borderRadius: "8px",
|
|
2628
|
-
transition: "all 0.2s ease-in-out",
|
|
2629
|
-
height: "40px",
|
|
2630
|
-
display: "flex",
|
|
2631
|
-
alignItems: "center",
|
|
2632
|
-
paddingRight: "32px !important",
|
|
2633
|
-
"&:hover": {
|
|
2634
|
-
backgroundColor: "#ffffff"
|
|
2635
|
-
},
|
|
2636
|
-
"&.Mui-focused": {
|
|
2637
|
-
backgroundColor: "#ffffff"
|
|
2638
|
-
}
|
|
2639
|
-
},
|
|
2640
|
-
"& .MuiOutlinedInput-notchedOutline": {
|
|
2641
|
-
borderColor: "#e5e7eb",
|
|
2642
|
-
borderWidth: "1px",
|
|
2643
|
-
borderRadius: "8px"
|
|
2644
|
-
},
|
|
2645
|
-
"&:hover .MuiOutlinedInput-notchedOutline": {
|
|
2646
|
-
borderColor: "#9ca3af"
|
|
2647
|
-
},
|
|
2648
|
-
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
|
|
2649
|
-
borderColor: "#6366f1",
|
|
2650
|
-
borderWidth: "2px"
|
|
2651
|
-
},
|
|
2652
|
-
"&.Mui-error .MuiOutlinedInput-notchedOutline": {
|
|
2653
|
-
borderColor: "#ef4444"
|
|
2654
|
-
},
|
|
2655
|
-
"& .MuiSelect-icon": {
|
|
2656
|
-
color: "#9ca3af",
|
|
2657
|
-
"&:hover": {
|
|
2658
|
-
color: "#6b7280"
|
|
2659
|
-
}
|
|
2660
|
-
}
|
|
2661
|
-
},
|
|
2662
|
-
MenuProps: {
|
|
2663
|
-
PaperProps: {
|
|
2664
|
-
sx: {
|
|
2665
|
-
borderRadius: "8px",
|
|
2666
|
-
boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
|
|
2667
|
-
border: "1px solid #e5e7eb",
|
|
2668
|
-
marginTop: "4px",
|
|
2669
|
-
maxHeight: "280px"
|
|
2670
|
-
}
|
|
2671
|
-
},
|
|
2672
|
-
MenuListProps: {
|
|
2673
|
-
sx: {
|
|
2674
|
-
padding: 0
|
|
2675
|
-
}
|
|
2676
|
-
}
|
|
2677
|
-
},
|
|
2678
|
-
children: options.map((option, index) => {
|
|
2679
|
-
const raw2 = option.const;
|
|
2680
|
-
const key = typeof raw2 === "string" || typeof raw2 === "number" ? String(raw2) : String(index);
|
|
2681
|
-
const value = typeof raw2 === "string" || typeof raw2 === "number" ? raw2 : String(raw2 ?? index);
|
|
2682
|
-
return /* @__PURE__ */ jsx(
|
|
2683
|
-
MenuItem,
|
|
2684
|
-
{
|
|
2685
|
-
value,
|
|
2686
|
-
sx: {
|
|
2687
|
-
padding: "12px 16px",
|
|
2688
|
-
fontSize: "0.875rem",
|
|
2689
|
-
borderBottom: "1px solid #f3f4f6",
|
|
2690
|
-
"&:last-child": {
|
|
2691
|
-
borderBottom: "none"
|
|
2692
|
-
},
|
|
2693
|
-
"&:hover": {
|
|
2694
|
-
backgroundColor: "#f8fafc"
|
|
2695
|
-
},
|
|
2696
|
-
"&.Mui-selected": {
|
|
2697
|
-
backgroundColor: "#eff6ff",
|
|
2698
|
-
"&:hover": {
|
|
2699
|
-
backgroundColor: "#dbeafe"
|
|
2700
|
-
}
|
|
2701
|
-
}
|
|
2702
|
-
},
|
|
2703
|
-
children: option.title ?? String(raw2)
|
|
2704
|
-
},
|
|
2705
|
-
key
|
|
2706
|
-
);
|
|
2707
|
-
})
|
|
2708
|
-
}
|
|
2709
|
-
),
|
|
2710
|
-
(description || errors) && /* @__PURE__ */ jsx(
|
|
2711
|
-
"div",
|
|
3190
|
+
ChevronDown,
|
|
2712
3191
|
{
|
|
2713
|
-
|
|
2714
|
-
fontSize: "0.75rem",
|
|
2715
|
-
marginTop: "4px",
|
|
2716
|
-
color: errors ? "#ef4444" : "#6b7280"
|
|
2717
|
-
},
|
|
2718
|
-
children: errors || description
|
|
3192
|
+
className: `shrink-0 opacity-50 ${isBar ? "h-3 w-3" : "h-4 w-4"}`
|
|
2719
3193
|
}
|
|
2720
3194
|
)
|
|
2721
3195
|
]
|
|
2722
3196
|
}
|
|
2723
3197
|
);
|
|
3198
|
+
return /* @__PURE__ */ jsxs("div", { className: "ss-jsonforms-field ss-jsonforms-select compact-field", children: [
|
|
3199
|
+
!isBar && label && /* @__PURE__ */ jsx("label", { htmlFor: triggerId, className: fieldLabelClass(scale), children: label }),
|
|
3200
|
+
trigger,
|
|
3201
|
+
!isBar && (errors || description) && /* @__PURE__ */ jsx("div", { className: errors ? fieldErrorClass : fieldHintClass, children: errors || description }),
|
|
3202
|
+
renderPopover(
|
|
3203
|
+
/* @__PURE__ */ jsxs("div", { className: "min-h-0 overflow-y-auto py-1", children: [
|
|
3204
|
+
options.length === 0 && /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-muted-foreground", children: "No options available" }),
|
|
3205
|
+
options.map((option, index) => {
|
|
3206
|
+
const active = option.const === data;
|
|
3207
|
+
const text6 = option.title ?? String(option.const);
|
|
3208
|
+
return /* @__PURE__ */ jsxs(
|
|
3209
|
+
"button",
|
|
3210
|
+
{
|
|
3211
|
+
type: "button",
|
|
3212
|
+
role: "option",
|
|
3213
|
+
"aria-selected": active,
|
|
3214
|
+
onClick: () => select(option.const),
|
|
3215
|
+
className: popoverRowClass,
|
|
3216
|
+
children: [
|
|
3217
|
+
/* @__PURE__ */ jsx(
|
|
3218
|
+
Check,
|
|
3219
|
+
{
|
|
3220
|
+
className: `h-3.5 w-3.5 shrink-0 ${active ? "text-primary" : "opacity-0"}`
|
|
3221
|
+
}
|
|
3222
|
+
),
|
|
3223
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm text-foreground", children: text6 })
|
|
3224
|
+
]
|
|
3225
|
+
},
|
|
3226
|
+
typeof option.const === "string" || typeof option.const === "number" ? String(option.const) : `option-${index}`
|
|
3227
|
+
);
|
|
3228
|
+
})
|
|
3229
|
+
] })
|
|
3230
|
+
)
|
|
3231
|
+
] });
|
|
2724
3232
|
};
|
|
2725
3233
|
var dropdownRendererTester = rankWith(
|
|
2726
3234
|
90,
|
|
@@ -2738,8 +3246,8 @@ var dropdownRendererTester = rankWith(
|
|
|
2738
3246
|
return false;
|
|
2739
3247
|
}
|
|
2740
3248
|
const hasDropdownOptions = !!(fieldSchema.oneOf || fieldSchema.anyOf || fieldSchema.enum && Array.isArray(fieldSchema.enum));
|
|
2741
|
-
const
|
|
2742
|
-
return hasDropdownOptions && !
|
|
3249
|
+
const isModelSelector2 = typeof fieldSchema === "object" && fieldSchema && fieldSchema["x-model-selector"] === true || fieldSchema.title === "ModelId" || fieldSchema.format === "uuid";
|
|
3250
|
+
return hasDropdownOptions && !isModelSelector2;
|
|
2743
3251
|
}
|
|
2744
3252
|
);
|
|
2745
3253
|
var DropdownRendererControl = withJsonFormsControlProps(DropdownRenderer);
|
|
@@ -2774,7 +3282,8 @@ var JsonEditorRenderer = ({
|
|
|
2774
3282
|
uischema,
|
|
2775
3283
|
visible,
|
|
2776
3284
|
enabled,
|
|
2777
|
-
required
|
|
3285
|
+
required,
|
|
3286
|
+
config
|
|
2778
3287
|
}) => {
|
|
2779
3288
|
const [jsonValue, setJsonValue] = useState("");
|
|
2780
3289
|
const [displayedParseError, setDisplayedParseError] = useState(
|
|
@@ -2828,43 +3337,19 @@ var JsonEditorRenderer = ({
|
|
|
2828
3337
|
}
|
|
2829
3338
|
const readOnly = uischema?.access === "Read";
|
|
2830
3339
|
const isDisabled = !enabled || readOnly;
|
|
3340
|
+
const scale = scaleFor(
|
|
3341
|
+
(config ?? {}).surface ?? "form"
|
|
3342
|
+
);
|
|
2831
3343
|
return /* @__PURE__ */ jsxs("div", { style: { marginBottom: "1rem" }, children: [
|
|
2832
|
-
label && /* @__PURE__ */ jsxs(
|
|
2833
|
-
|
|
2834
|
-
{
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
color: "#475569",
|
|
2838
|
-
fontSize: "0.875rem",
|
|
2839
|
-
fontWeight: 500,
|
|
2840
|
-
marginBottom: "0.375rem"
|
|
2841
|
-
},
|
|
2842
|
-
children: [
|
|
2843
|
-
label,
|
|
2844
|
-
required && /* @__PURE__ */ jsx("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
|
|
2845
|
-
]
|
|
2846
|
-
}
|
|
2847
|
-
),
|
|
2848
|
-
description && /* @__PURE__ */ jsx(
|
|
2849
|
-
"div",
|
|
2850
|
-
{
|
|
2851
|
-
style: {
|
|
2852
|
-
color: "#6b7280",
|
|
2853
|
-
fontSize: "0.75rem",
|
|
2854
|
-
marginBottom: "0.5rem"
|
|
2855
|
-
},
|
|
2856
|
-
children: description
|
|
2857
|
-
}
|
|
2858
|
-
),
|
|
3344
|
+
label && /* @__PURE__ */ jsxs("label", { className: fieldLabelClass(scale), children: [
|
|
3345
|
+
label,
|
|
3346
|
+
required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-destructive", children: "*" })
|
|
3347
|
+
] }),
|
|
3348
|
+
description && /* @__PURE__ */ jsx("div", { className: fieldHintClass, children: description }),
|
|
2859
3349
|
/* @__PURE__ */ jsx(
|
|
2860
3350
|
"div",
|
|
2861
3351
|
{
|
|
2862
|
-
|
|
2863
|
-
border: errors || displayedParseError ? "1px solid #ef4444" : "1px solid #d1d5db",
|
|
2864
|
-
borderRadius: "6px",
|
|
2865
|
-
overflow: "hidden",
|
|
2866
|
-
opacity: isDisabled ? 0.6 : 1
|
|
2867
|
-
},
|
|
3352
|
+
className: `overflow-hidden rounded-md border ${errors || displayedParseError ? "border-destructive" : "border-input"} ${isDisabled ? "opacity-60" : ""}`,
|
|
2868
3353
|
children: /* @__PURE__ */ jsx(
|
|
2869
3354
|
AceEditor,
|
|
2870
3355
|
{
|
|
@@ -2897,28 +3382,8 @@ var JsonEditorRenderer = ({
|
|
|
2897
3382
|
)
|
|
2898
3383
|
}
|
|
2899
3384
|
),
|
|
2900
|
-
displayedParseError && /* @__PURE__ */ jsx(
|
|
2901
|
-
|
|
2902
|
-
{
|
|
2903
|
-
style: {
|
|
2904
|
-
color: "#ef4444",
|
|
2905
|
-
fontSize: "0.75rem",
|
|
2906
|
-
marginTop: "0.25rem"
|
|
2907
|
-
},
|
|
2908
|
-
children: displayedParseError
|
|
2909
|
-
}
|
|
2910
|
-
),
|
|
2911
|
-
errors && /* @__PURE__ */ jsx(
|
|
2912
|
-
"div",
|
|
2913
|
-
{
|
|
2914
|
-
style: {
|
|
2915
|
-
color: "#ef4444",
|
|
2916
|
-
fontSize: "0.75rem",
|
|
2917
|
-
marginTop: "0.25rem"
|
|
2918
|
-
},
|
|
2919
|
-
children: errors
|
|
2920
|
-
}
|
|
2921
|
-
)
|
|
3385
|
+
displayedParseError && /* @__PURE__ */ jsx("div", { className: fieldErrorClass, children: displayedParseError }),
|
|
3386
|
+
errors && /* @__PURE__ */ jsx("div", { className: fieldErrorClass, children: errors })
|
|
2922
3387
|
] });
|
|
2923
3388
|
};
|
|
2924
3389
|
var jsonEditorTester = rankWith(
|
|
@@ -3009,14 +3474,31 @@ var ModelIdRenderer = ({
|
|
|
3009
3474
|
description,
|
|
3010
3475
|
errors,
|
|
3011
3476
|
uischema,
|
|
3012
|
-
visible
|
|
3477
|
+
visible,
|
|
3478
|
+
config
|
|
3013
3479
|
}) => {
|
|
3014
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
3015
3480
|
const [searchValue, setSearchValue] = useState("");
|
|
3016
3481
|
const [debouncedSearchValue, setDebouncedSearchValue] = useState("");
|
|
3017
|
-
const
|
|
3482
|
+
const triggerRef = useRef(null);
|
|
3018
3483
|
const menuRef = useRef(null);
|
|
3019
3484
|
const searchRef = useRef(null);
|
|
3485
|
+
const surface = (config ?? {}).surface ?? "bar";
|
|
3486
|
+
const scale = scaleFor(surface);
|
|
3487
|
+
const isBar = surface === "bar";
|
|
3488
|
+
const {
|
|
3489
|
+
isOpen,
|
|
3490
|
+
close: closeMenu,
|
|
3491
|
+
toggle,
|
|
3492
|
+
renderPopover
|
|
3493
|
+
} = useAnchoredPopover({
|
|
3494
|
+
trigger: triggerRef,
|
|
3495
|
+
popover: menuRef,
|
|
3496
|
+
// Wide enough for a provider glyph, a model name and its id underneath.
|
|
3497
|
+
width: POPOVER_WIDTH_PX,
|
|
3498
|
+
maxHeight: POPOVER_MAX_HEIGHT_PX,
|
|
3499
|
+
role: "listbox",
|
|
3500
|
+
label: "Models"
|
|
3501
|
+
});
|
|
3020
3502
|
const debounceTimerRef = useRef(
|
|
3021
3503
|
void 0
|
|
3022
3504
|
);
|
|
@@ -3055,35 +3537,13 @@ var ModelIdRenderer = ({
|
|
|
3055
3537
|
handleChange(path2, model.id);
|
|
3056
3538
|
setSearchValue("");
|
|
3057
3539
|
setDebouncedSearchValue("");
|
|
3058
|
-
|
|
3540
|
+
closeMenu();
|
|
3059
3541
|
},
|
|
3060
|
-
[handleChange, path2]
|
|
3542
|
+
[handleChange, path2, closeMenu]
|
|
3061
3543
|
);
|
|
3062
|
-
const close = useCallback(() => {
|
|
3063
|
-
setIsOpen(false);
|
|
3064
|
-
setSearchValue("");
|
|
3065
|
-
}, []);
|
|
3066
3544
|
useEffect(() => {
|
|
3067
|
-
if (!isOpen)
|
|
3068
|
-
|
|
3069
|
-
const target = event.target;
|
|
3070
|
-
if (containerRef.current && !containerRef.current.contains(target) && !(menuRef.current && menuRef.current.contains(target))) {
|
|
3071
|
-
close();
|
|
3072
|
-
}
|
|
3073
|
-
};
|
|
3074
|
-
const onKeyDown = (event) => {
|
|
3075
|
-
if (event.key === "Escape") close();
|
|
3076
|
-
};
|
|
3077
|
-
const onResize = () => close();
|
|
3078
|
-
document.addEventListener("mousedown", onPointerDown);
|
|
3079
|
-
document.addEventListener("keydown", onKeyDown);
|
|
3080
|
-
window.addEventListener("resize", onResize);
|
|
3081
|
-
return () => {
|
|
3082
|
-
document.removeEventListener("mousedown", onPointerDown);
|
|
3083
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
3084
|
-
window.removeEventListener("resize", onResize);
|
|
3085
|
-
};
|
|
3086
|
-
}, [isOpen, close]);
|
|
3545
|
+
if (!isOpen) setSearchValue("");
|
|
3546
|
+
}, [isOpen]);
|
|
3087
3547
|
useEffect(() => {
|
|
3088
3548
|
if (isOpen) searchRef.current?.focus();
|
|
3089
3549
|
}, [isOpen]);
|
|
@@ -3092,53 +3552,58 @@ var ModelIdRenderer = ({
|
|
|
3092
3552
|
const isDisabled = !enabled || readOnly;
|
|
3093
3553
|
const hasError = !!errors && errors.length > 0;
|
|
3094
3554
|
const selectedName = selectedModel ? selectedModel.displayName || selectedModel.name || "" : "";
|
|
3095
|
-
const triggerText = selectedName ||
|
|
3555
|
+
const triggerText = selectedName || "Select model";
|
|
3096
3556
|
const iconSrc = getModelIcon(selectedModel);
|
|
3097
3557
|
const tooltip = [selectedName || label, description, hasError ? errors : null].filter(Boolean).join(" \u2014 ");
|
|
3098
|
-
const
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3558
|
+
const triggerLabel = !label || label === "ModelId" ? "Model" : label;
|
|
3559
|
+
const trigger = /* @__PURE__ */ jsxs(
|
|
3560
|
+
"button",
|
|
3561
|
+
{
|
|
3562
|
+
ref: triggerRef,
|
|
3563
|
+
id: `${path2}-trigger`,
|
|
3564
|
+
type: "button",
|
|
3565
|
+
onClick: toggle,
|
|
3566
|
+
disabled: isDisabled,
|
|
3567
|
+
"aria-expanded": isOpen,
|
|
3568
|
+
"aria-haspopup": "listbox",
|
|
3569
|
+
"aria-label": triggerLabel,
|
|
3570
|
+
title: tooltip || void 0,
|
|
3571
|
+
className: isBar ? pillClass({ active: isOpen, hasError, disabled: isDisabled }) : fieldTriggerClass(scale, hasError),
|
|
3572
|
+
children: [
|
|
3573
|
+
iconSrc ? /* @__PURE__ */ jsx(
|
|
3574
|
+
"img",
|
|
3575
|
+
{
|
|
3576
|
+
src: iconSrc,
|
|
3577
|
+
alt: "",
|
|
3578
|
+
className: "h-3.5 w-3.5 shrink-0 object-contain"
|
|
3579
|
+
}
|
|
3580
|
+
) : /* @__PURE__ */ jsx(Cpu, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
3581
|
+
/* @__PURE__ */ jsx(
|
|
3582
|
+
"span",
|
|
3583
|
+
{
|
|
3584
|
+
className: isBar ? `inline ${pillValueClass} max-sm:hidden` : "min-w-0 flex-1 truncate",
|
|
3585
|
+
children: triggerText
|
|
3586
|
+
}
|
|
3587
|
+
),
|
|
3588
|
+
/* @__PURE__ */ jsx(
|
|
3589
|
+
ChevronDown,
|
|
3590
|
+
{
|
|
3591
|
+
className: `shrink-0 opacity-60 ${isBar ? "h-3 w-3" : "h-4 w-4"}`
|
|
3592
|
+
}
|
|
3593
|
+
)
|
|
3594
|
+
]
|
|
3595
|
+
}
|
|
3596
|
+
);
|
|
3597
|
+
return /* @__PURE__ */ jsxs(
|
|
3598
|
+
"div",
|
|
3599
|
+
{
|
|
3600
|
+
className: isBar ? "ss-jsonforms-field ss-jsonforms-model relative shrink-0" : "ss-jsonforms-field ss-jsonforms-model compact-field",
|
|
3601
|
+
children: [
|
|
3602
|
+
!isBar && /* @__PURE__ */ jsx("label", { htmlFor: `${path2}-trigger`, className: fieldLabelClass(scale), children: triggerLabel }),
|
|
3603
|
+
trigger,
|
|
3604
|
+
renderPopover(
|
|
3605
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3606
|
+
/* @__PURE__ */ jsx("div", { className: "shrink-0 border-b border-border p-2", children: /* @__PURE__ */ jsx(
|
|
3142
3607
|
"input",
|
|
3143
3608
|
{
|
|
3144
3609
|
ref: searchRef,
|
|
@@ -3150,7 +3615,7 @@ var ModelIdRenderer = ({
|
|
|
3150
3615
|
className: "h-8 w-full rounded-md border border-border bg-background px-2 text-xs text-foreground outline-none placeholder:text-muted-foreground focus:border-primary/40"
|
|
3151
3616
|
}
|
|
3152
3617
|
) }),
|
|
3153
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
3618
|
+
/* @__PURE__ */ jsxs("div", { className: "min-h-0 overflow-y-auto", children: [
|
|
3154
3619
|
isLoading && listModels.length === 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin text-primary" }) }),
|
|
3155
3620
|
!isLoading && listModels.length === 0 && /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-center text-xs text-muted-foreground", children: searchValue ? "No models found" : "No models available" }),
|
|
3156
3621
|
listModels.map((model) => {
|
|
@@ -3163,7 +3628,7 @@ var ModelIdRenderer = ({
|
|
|
3163
3628
|
role: "option",
|
|
3164
3629
|
"aria-selected": active,
|
|
3165
3630
|
onClick: () => handleSelect(model),
|
|
3166
|
-
className:
|
|
3631
|
+
className: popoverRowClass,
|
|
3167
3632
|
children: [
|
|
3168
3633
|
/* @__PURE__ */ jsx(
|
|
3169
3634
|
Check,
|
|
@@ -3189,12 +3654,11 @@ var ModelIdRenderer = ({
|
|
|
3189
3654
|
);
|
|
3190
3655
|
})
|
|
3191
3656
|
] })
|
|
3192
|
-
]
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
] });
|
|
3657
|
+
] })
|
|
3658
|
+
)
|
|
3659
|
+
]
|
|
3660
|
+
}
|
|
3661
|
+
);
|
|
3198
3662
|
};
|
|
3199
3663
|
var modelIdRendererTester = rankWith(
|
|
3200
3664
|
100,
|
|
@@ -3229,6 +3693,7 @@ var NumberRenderer = ({
|
|
|
3229
3693
|
uischema,
|
|
3230
3694
|
visible,
|
|
3231
3695
|
enabled,
|
|
3696
|
+
config,
|
|
3232
3697
|
required
|
|
3233
3698
|
}) => {
|
|
3234
3699
|
const isInteger = schema?.type === "integer";
|
|
@@ -3257,40 +3722,58 @@ var NumberRenderer = ({
|
|
|
3257
3722
|
const max = fieldSchema?.maximum;
|
|
3258
3723
|
const step = isInteger ? 1 : fieldSchema?.multipleOf ?? "any";
|
|
3259
3724
|
const tooltip = [label, description, hasError ? errors : null].filter(Boolean).join(" \u2014 ");
|
|
3260
|
-
|
|
3261
|
-
|
|
3725
|
+
const surface = (config ?? {}).surface ?? "form";
|
|
3726
|
+
const scale = scaleFor(surface);
|
|
3727
|
+
const input = /* @__PURE__ */ jsx(
|
|
3728
|
+
"input",
|
|
3262
3729
|
{
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
label,
|
|
3273
|
-
required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-destructive", children: "*" })
|
|
3274
|
-
]
|
|
3275
|
-
}
|
|
3276
|
-
),
|
|
3277
|
-
/* @__PURE__ */ jsx(
|
|
3278
|
-
"input",
|
|
3279
|
-
{
|
|
3280
|
-
id: `number-${path2}`,
|
|
3281
|
-
type: "number",
|
|
3282
|
-
value: data ?? "",
|
|
3283
|
-
onChange: handleInputChange,
|
|
3284
|
-
disabled: isDisabled,
|
|
3285
|
-
min,
|
|
3286
|
-
max,
|
|
3287
|
-
step,
|
|
3288
|
-
className: "w-14 border-0 bg-transparent p-0 text-xs font-medium tabular-nums text-foreground outline-none disabled:cursor-not-allowed"
|
|
3289
|
-
}
|
|
3290
|
-
)
|
|
3291
|
-
]
|
|
3730
|
+
id: `number-${path2}`,
|
|
3731
|
+
type: "number",
|
|
3732
|
+
value: data ?? "",
|
|
3733
|
+
onChange: handleInputChange,
|
|
3734
|
+
disabled: isDisabled,
|
|
3735
|
+
min,
|
|
3736
|
+
max,
|
|
3737
|
+
step,
|
|
3738
|
+
className: surface === "bar" ? "w-14 border-0 bg-transparent p-0 text-xs font-medium tabular-nums text-foreground outline-none disabled:cursor-not-allowed" : fieldNumberClass(scale, hasError)
|
|
3292
3739
|
}
|
|
3293
3740
|
);
|
|
3741
|
+
if (surface === "bar") {
|
|
3742
|
+
return /* @__PURE__ */ jsxs(
|
|
3743
|
+
"div",
|
|
3744
|
+
{
|
|
3745
|
+
className: `ss-jsonforms-field ss-jsonforms-number ${pillClass({
|
|
3746
|
+
hasError,
|
|
3747
|
+
disabled: isDisabled
|
|
3748
|
+
})}`,
|
|
3749
|
+
title: tooltip || void 0,
|
|
3750
|
+
children: [
|
|
3751
|
+
label && /* @__PURE__ */ jsxs(
|
|
3752
|
+
"label",
|
|
3753
|
+
{
|
|
3754
|
+
htmlFor: `number-${path2}`,
|
|
3755
|
+
className: `${pillLabelClass} whitespace-nowrap ${hasError ? "text-destructive" : "text-muted-foreground"}`,
|
|
3756
|
+
children: [
|
|
3757
|
+
label,
|
|
3758
|
+
required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-destructive", children: "*" })
|
|
3759
|
+
]
|
|
3760
|
+
}
|
|
3761
|
+
),
|
|
3762
|
+
input
|
|
3763
|
+
]
|
|
3764
|
+
}
|
|
3765
|
+
);
|
|
3766
|
+
}
|
|
3767
|
+
return /* @__PURE__ */ jsxs("div", { className: "ss-jsonforms-field ss-jsonforms-number", children: [
|
|
3768
|
+
/* @__PURE__ */ jsxs("div", { className: fieldRowClass, children: [
|
|
3769
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: `number-${path2}`, className: fieldRowLabelClass(scale), children: [
|
|
3770
|
+
label,
|
|
3771
|
+
required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-destructive", children: "*" })
|
|
3772
|
+
] }),
|
|
3773
|
+
input
|
|
3774
|
+
] }),
|
|
3775
|
+
hasError && /* @__PURE__ */ jsx("div", { className: fieldErrorClass, children: errors })
|
|
3776
|
+
] });
|
|
3294
3777
|
};
|
|
3295
3778
|
var numberRendererTester = rankWith(
|
|
3296
3779
|
40,
|
|
@@ -3306,6 +3789,14 @@ var numberRendererTester = rankWith(
|
|
|
3306
3789
|
}
|
|
3307
3790
|
);
|
|
3308
3791
|
var NumberRendererControl = withJsonFormsControlProps(NumberRenderer);
|
|
3792
|
+
var SCALE = {
|
|
3793
|
+
comfortable: { lineHeight: 20, padding: 8 },
|
|
3794
|
+
dense: { lineHeight: 16, padding: 6 }
|
|
3795
|
+
};
|
|
3796
|
+
var rowsToPx = (rows, scale) => rows * scale.lineHeight + scale.padding * 2 + 2;
|
|
3797
|
+
var MAX_VIEWPORT_SHARE = 0.5;
|
|
3798
|
+
var DEFAULT_MIN_ROWS = 3;
|
|
3799
|
+
var DEFAULT_MAX_ROWS = 9;
|
|
3309
3800
|
var TextareaRenderer = ({
|
|
3310
3801
|
data,
|
|
3311
3802
|
handleChange,
|
|
@@ -3317,28 +3808,49 @@ var TextareaRenderer = ({
|
|
|
3317
3808
|
uischema,
|
|
3318
3809
|
visible,
|
|
3319
3810
|
enabled,
|
|
3320
|
-
required
|
|
3811
|
+
required,
|
|
3812
|
+
config
|
|
3321
3813
|
}) => {
|
|
3322
3814
|
const textareaRef = useRef(null);
|
|
3815
|
+
const textareaOptions = schema["ui:textarea"] ?? {};
|
|
3816
|
+
const formConfig = config ?? {};
|
|
3817
|
+
const scaleName = scaleFor(formConfig.surface ?? "form");
|
|
3818
|
+
const scale = SCALE[scaleName];
|
|
3819
|
+
const minRows = textareaOptions.minRows ?? formConfig.minRows ?? DEFAULT_MIN_ROWS;
|
|
3820
|
+
const maxRows = Math.max(
|
|
3821
|
+
minRows,
|
|
3822
|
+
textareaOptions.maxRows ?? formConfig.maxRows ?? DEFAULT_MAX_ROWS
|
|
3823
|
+
);
|
|
3824
|
+
const minHeight = rowsToPx(minRows, scale);
|
|
3825
|
+
const maxHeight = rowsToPx(maxRows, scale);
|
|
3826
|
+
const [viewportCap, setViewportCap] = useState(
|
|
3827
|
+
() => typeof window === "undefined" ? Number.POSITIVE_INFINITY : Math.round(window.innerHeight * MAX_VIEWPORT_SHARE)
|
|
3828
|
+
);
|
|
3829
|
+
const ceiling = Math.max(minHeight, Math.min(maxHeight, viewportCap));
|
|
3323
3830
|
const autoResize = useCallback(() => {
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
}
|
|
3333
|
-
}, []);
|
|
3831
|
+
const el = textareaRef.current;
|
|
3832
|
+
if (!el) return;
|
|
3833
|
+
el.style.height = "auto";
|
|
3834
|
+
el.style.height = `${Math.min(
|
|
3835
|
+
Math.max(el.scrollHeight, minHeight),
|
|
3836
|
+
ceiling
|
|
3837
|
+
)}px`;
|
|
3838
|
+
}, [minHeight, ceiling]);
|
|
3334
3839
|
useEffect(() => {
|
|
3335
3840
|
autoResize();
|
|
3336
3841
|
}, [data, autoResize]);
|
|
3842
|
+
useEffect(() => {
|
|
3843
|
+
const onResize = () => {
|
|
3844
|
+
setViewportCap(Math.round(window.innerHeight * MAX_VIEWPORT_SHARE));
|
|
3845
|
+
autoResize();
|
|
3846
|
+
};
|
|
3847
|
+
window.addEventListener("resize", onResize);
|
|
3848
|
+
return () => window.removeEventListener("resize", onResize);
|
|
3849
|
+
}, [autoResize]);
|
|
3337
3850
|
const handleInputChange = useCallback(
|
|
3338
3851
|
(event) => {
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
setTimeout(autoResize, 0);
|
|
3852
|
+
handleChange(path2, event.target.value);
|
|
3853
|
+
autoResize();
|
|
3342
3854
|
},
|
|
3343
3855
|
[handleChange, path2, autoResize]
|
|
3344
3856
|
);
|
|
@@ -3348,89 +3860,34 @@ var TextareaRenderer = ({
|
|
|
3348
3860
|
const readOnly = uischema?.access === "Read";
|
|
3349
3861
|
const isDisabled = !enabled || readOnly;
|
|
3350
3862
|
const hasError = errors && errors.length > 0;
|
|
3351
|
-
const textareaOptions = schema["ui:textarea"] ?? {};
|
|
3352
3863
|
const placeholder = textareaOptions.placeholder || schema?.description || `Enter ${label?.toLowerCase() || "text"}...`;
|
|
3353
|
-
const minRows = textareaOptions.minRows || 3;
|
|
3354
3864
|
return /* @__PURE__ */ jsxs("div", { className: "ss-jsonforms-field ss-jsonforms-textarea", children: [
|
|
3355
|
-
label && /* @__PURE__ */ jsxs(
|
|
3356
|
-
|
|
3357
|
-
{
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
color: hasError ? "#ef4444" : "#475569",
|
|
3361
|
-
fontSize: "0.875rem",
|
|
3362
|
-
fontWeight: 500,
|
|
3363
|
-
marginBottom: "0.375rem"
|
|
3364
|
-
},
|
|
3365
|
-
children: [
|
|
3366
|
-
label,
|
|
3367
|
-
required && /* @__PURE__ */ jsx("span", { style: { color: "#ef4444", marginLeft: "0.25rem" }, children: "*" })
|
|
3368
|
-
]
|
|
3369
|
-
}
|
|
3370
|
-
),
|
|
3371
|
-
description && /* @__PURE__ */ jsx(
|
|
3372
|
-
"div",
|
|
3373
|
-
{
|
|
3374
|
-
style: {
|
|
3375
|
-
color: "#6b7280",
|
|
3376
|
-
fontSize: "0.75rem",
|
|
3377
|
-
marginBottom: "0.5rem"
|
|
3378
|
-
},
|
|
3379
|
-
children: description
|
|
3380
|
-
}
|
|
3381
|
-
),
|
|
3865
|
+
label && /* @__PURE__ */ jsxs("label", { htmlFor: path2, className: fieldLabelClass(scaleName), children: [
|
|
3866
|
+
label,
|
|
3867
|
+
required && /* @__PURE__ */ jsx("span", { className: "ml-1 text-destructive", children: "*" })
|
|
3868
|
+
] }),
|
|
3869
|
+
description && /* @__PURE__ */ jsx("div", { className: fieldHintClass, children: description }),
|
|
3382
3870
|
/* @__PURE__ */ jsx(
|
|
3383
3871
|
"textarea",
|
|
3384
3872
|
{
|
|
3873
|
+
id: path2,
|
|
3385
3874
|
ref: textareaRef,
|
|
3386
3875
|
value: data || "",
|
|
3387
3876
|
onChange: handleInputChange,
|
|
3388
3877
|
placeholder,
|
|
3389
3878
|
disabled: isDisabled,
|
|
3390
3879
|
rows: minRows,
|
|
3880
|
+
className: `resize-y ${fieldControlClass(scaleName, !!hasError)}`,
|
|
3391
3881
|
style: {
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
padding: "0.75rem",
|
|
3397
|
-
border: hasError ? "2px solid #ef4444" : "1px solid #d1d5db",
|
|
3398
|
-
borderRadius: "6px",
|
|
3399
|
-
fontSize: "16px",
|
|
3400
|
-
lineHeight: "1.5",
|
|
3401
|
-
fontFamily: "inherit",
|
|
3402
|
-
backgroundColor: isDisabled ? "#f9fafb" : "#ffffff",
|
|
3403
|
-
color: isDisabled ? "#9ca3af" : "#111827",
|
|
3404
|
-
outline: "none",
|
|
3405
|
-
transition: "border-color 0.2s ease-in-out, box-shadow 0.2s ease-in-out",
|
|
3406
|
-
boxShadow: hasError ? "0 0 0 1px #ef4444" : "none",
|
|
3882
|
+
minHeight: `${minHeight}px`,
|
|
3883
|
+
maxHeight: `${ceiling}px`,
|
|
3884
|
+
// iOS zooms a focused control under 16px; the design's fields are
|
|
3885
|
+
// 14px, so opt out of the adjustment rather than the design.
|
|
3407
3886
|
WebkitTextSizeAdjust: "100%"
|
|
3408
|
-
},
|
|
3409
|
-
onFocus: (e) => {
|
|
3410
|
-
if (!hasError) {
|
|
3411
|
-
e.target.style.borderColor = "#6366f1";
|
|
3412
|
-
e.target.style.boxShadow = "0 0 0 1px #6366f1";
|
|
3413
|
-
}
|
|
3414
|
-
},
|
|
3415
|
-
onBlur: (e) => {
|
|
3416
|
-
if (!hasError) {
|
|
3417
|
-
e.target.style.borderColor = "#d1d5db";
|
|
3418
|
-
e.target.style.boxShadow = "none";
|
|
3419
|
-
}
|
|
3420
3887
|
}
|
|
3421
3888
|
}
|
|
3422
3889
|
),
|
|
3423
|
-
hasError && /* @__PURE__ */ jsx(
|
|
3424
|
-
"div",
|
|
3425
|
-
{
|
|
3426
|
-
style: {
|
|
3427
|
-
color: "#ef4444",
|
|
3428
|
-
fontSize: "0.75rem",
|
|
3429
|
-
marginTop: "0.25rem"
|
|
3430
|
-
},
|
|
3431
|
-
children: errors
|
|
3432
|
-
}
|
|
3433
|
-
)
|
|
3890
|
+
hasError && /* @__PURE__ */ jsx("div", { className: fieldErrorClass, children: errors })
|
|
3434
3891
|
] });
|
|
3435
3892
|
};
|
|
3436
3893
|
var textareaRendererTester = rankWith(
|
|
@@ -3482,10 +3939,25 @@ var renderers = [
|
|
|
3482
3939
|
];
|
|
3483
3940
|
|
|
3484
3941
|
// src/chat-variables/VariablesForm.vm.ts
|
|
3942
|
+
var MAX_INLINE_VARIABLES = 3;
|
|
3943
|
+
var isModelSelector = (schema) => schema.title === "ModelId" || schema["x-model-selector"] === true;
|
|
3944
|
+
function rowLayout(controls) {
|
|
3945
|
+
const innerRow = {
|
|
3946
|
+
type: "HorizontalLayout",
|
|
3947
|
+
elements: controls,
|
|
3948
|
+
options: { gap: "12px", alignItems: "flex-start" }
|
|
3949
|
+
};
|
|
3950
|
+
const ui = {
|
|
3951
|
+
type: "VerticalLayout",
|
|
3952
|
+
elements: [innerRow]
|
|
3953
|
+
};
|
|
3954
|
+
return ui;
|
|
3955
|
+
}
|
|
3485
3956
|
function buildSimpleSchemaAndUi(vars, threadVars, useDefaults) {
|
|
3486
3957
|
const names = Object.keys(vars || {});
|
|
3487
3958
|
const properties2 = {};
|
|
3488
3959
|
const controls = [];
|
|
3960
|
+
const inlineOnly = [];
|
|
3489
3961
|
const initialData = {};
|
|
3490
3962
|
const $defs = {};
|
|
3491
3963
|
for (const name of names) {
|
|
@@ -3505,19 +3977,24 @@ function buildSimpleSchemaAndUi(vars, threadVars, useDefaults) {
|
|
|
3505
3977
|
control.enabled = false;
|
|
3506
3978
|
}
|
|
3507
3979
|
controls.push(control);
|
|
3980
|
+
if (isModelSelector(properties2[name])) inlineOnly.push(control);
|
|
3508
3981
|
}
|
|
3509
3982
|
const schema = { type: "object", properties: properties2 };
|
|
3510
3983
|
if (Object.keys($defs).length > 0) schema.$defs = $defs;
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3984
|
+
if (controls.length <= MAX_INLINE_VARIABLES) {
|
|
3985
|
+
return {
|
|
3986
|
+
schema,
|
|
3987
|
+
inlineControls: controls,
|
|
3988
|
+
overflowControls: [],
|
|
3989
|
+
initialData
|
|
3990
|
+
};
|
|
3991
|
+
}
|
|
3992
|
+
return {
|
|
3993
|
+
schema,
|
|
3994
|
+
inlineControls: inlineOnly,
|
|
3995
|
+
overflowControls: controls.filter((c) => !inlineOnly.includes(c)),
|
|
3996
|
+
initialData
|
|
3519
3997
|
};
|
|
3520
|
-
return { schema, uiSchema: ui, initialData };
|
|
3521
3998
|
}
|
|
3522
3999
|
function useChatVariablesFormVm({
|
|
3523
4000
|
workspace,
|
|
@@ -3532,26 +4009,26 @@ function useChatVariablesFormVm({
|
|
|
3532
4009
|
const { mutate: updateVariableMutation } = useUpdateFlowRunVariable();
|
|
3533
4010
|
const querySettled = !isLoading && (threadVars !== void 0 || isError);
|
|
3534
4011
|
const shouldUseDefaults = isError || threadVars && Object.keys(threadVars).length === 0;
|
|
3535
|
-
const built =
|
|
4012
|
+
const built = React9.useMemo(() => {
|
|
3536
4013
|
return buildSimpleSchemaAndUi(
|
|
3537
4014
|
workspace.variables,
|
|
3538
4015
|
threadVars,
|
|
3539
4016
|
shouldUseDefaults ?? false
|
|
3540
4017
|
);
|
|
3541
4018
|
}, [workspace.variables, threadVars, shouldUseDefaults]);
|
|
3542
|
-
const [data, setData] =
|
|
3543
|
-
|
|
4019
|
+
const [data, setData] = React9.useState(null);
|
|
4020
|
+
React9.useEffect(() => {
|
|
3544
4021
|
if (querySettled) {
|
|
3545
4022
|
setData(built.initialData);
|
|
3546
4023
|
setVariables(built.initialData);
|
|
3547
4024
|
}
|
|
3548
4025
|
}, [querySettled, built.initialData, setVariables]);
|
|
3549
|
-
const ajv =
|
|
3550
|
-
const prevRef =
|
|
3551
|
-
|
|
4026
|
+
const ajv = React9.useMemo(() => createAjv({ useDefaults: false }), []);
|
|
4027
|
+
const prevRef = React9.useRef(null);
|
|
4028
|
+
React9.useEffect(() => {
|
|
3552
4029
|
prevRef.current = data;
|
|
3553
4030
|
}, [data]);
|
|
3554
|
-
const onChange =
|
|
4031
|
+
const onChange = React9.useCallback(
|
|
3555
4032
|
({ data: next2 }) => {
|
|
3556
4033
|
if (prevRef.current && !isDraftThreadId(threadId)) {
|
|
3557
4034
|
const keys2 = Object.keys(workspace.variables || {});
|
|
@@ -3572,29 +4049,96 @@ function useChatVariablesFormVm({
|
|
|
3572
4049
|
},
|
|
3573
4050
|
[workspace.variables, setVariables, updateVariableMutation, threadId]
|
|
3574
4051
|
);
|
|
3575
|
-
const
|
|
4052
|
+
const barConfig = React9.useMemo(
|
|
3576
4053
|
() => ({
|
|
3577
4054
|
restrict: true,
|
|
3578
4055
|
trim: false,
|
|
3579
4056
|
showUnfocusedDescription: true,
|
|
3580
|
-
hideRequiredAsterisk: true
|
|
4057
|
+
hideRequiredAsterisk: true,
|
|
4058
|
+
surface: "bar",
|
|
4059
|
+
minRows: 1,
|
|
4060
|
+
maxRows: 6
|
|
3581
4061
|
}),
|
|
3582
4062
|
[]
|
|
3583
4063
|
);
|
|
4064
|
+
const panelConfig = React9.useMemo(
|
|
4065
|
+
() => ({ ...barConfig, surface: "panel" }),
|
|
4066
|
+
[barConfig]
|
|
4067
|
+
);
|
|
4068
|
+
const inlineUiSchema = React9.useMemo(
|
|
4069
|
+
() => built.inlineControls.length ? rowLayout(built.inlineControls) : null,
|
|
4070
|
+
[built.inlineControls]
|
|
4071
|
+
);
|
|
4072
|
+
const overflowUiSchema = React9.useMemo(
|
|
4073
|
+
() => built.overflowControls.length ? rowLayout(built.overflowControls) : null,
|
|
4074
|
+
[built.overflowControls]
|
|
4075
|
+
);
|
|
3584
4076
|
return {
|
|
3585
4077
|
schema: built.schema,
|
|
3586
|
-
|
|
4078
|
+
inlineUiSchema,
|
|
4079
|
+
overflowUiSchema,
|
|
4080
|
+
overflowCount: built.overflowControls.length,
|
|
3587
4081
|
data,
|
|
3588
4082
|
renderers,
|
|
3589
4083
|
cells,
|
|
3590
4084
|
ajv,
|
|
3591
4085
|
onChange,
|
|
3592
|
-
|
|
4086
|
+
barConfig,
|
|
4087
|
+
panelConfig,
|
|
3593
4088
|
isLoading,
|
|
3594
4089
|
isReady: querySettled,
|
|
3595
4090
|
isHydrated: data !== null
|
|
3596
4091
|
};
|
|
3597
4092
|
}
|
|
4093
|
+
function VariablesOverflowPanel({ count, children: children2 }) {
|
|
4094
|
+
const triggerRef = useRef(null);
|
|
4095
|
+
const panelRef = useRef(null);
|
|
4096
|
+
const { isOpen, close, toggle, renderPopover } = useAnchoredPopover({
|
|
4097
|
+
trigger: triggerRef,
|
|
4098
|
+
popover: panelRef,
|
|
4099
|
+
width: POPOVER_WIDTH_PX,
|
|
4100
|
+
maxHeight: POPOVER_MAX_HEIGHT_PX,
|
|
4101
|
+
role: "dialog",
|
|
4102
|
+
label: "Workspace variables"
|
|
4103
|
+
});
|
|
4104
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4105
|
+
/* @__PURE__ */ jsxs(
|
|
4106
|
+
"button",
|
|
4107
|
+
{
|
|
4108
|
+
ref: triggerRef,
|
|
4109
|
+
type: "button",
|
|
4110
|
+
onClick: toggle,
|
|
4111
|
+
"aria-expanded": isOpen,
|
|
4112
|
+
"aria-haspopup": "dialog",
|
|
4113
|
+
"aria-label": `Variables (${count})`,
|
|
4114
|
+
className: `flex h-8 shrink-0 items-center gap-1.5 rounded-full border px-2.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary ${isOpen ? "border-primary/30 bg-primary/10 text-primary" : "border-border/70 bg-transparent text-muted-foreground hover:bg-secondary"}`,
|
|
4115
|
+
children: [
|
|
4116
|
+
/* @__PURE__ */ jsx(SlidersHorizontal, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
4117
|
+
/* @__PURE__ */ jsx("span", { className: "inline max-sm:hidden", children: "Variables" }),
|
|
4118
|
+
/* @__PURE__ */ jsx("span", { className: "rounded-full bg-secondary px-1.5 text-[10px] leading-4 tabular-nums", children: count })
|
|
4119
|
+
]
|
|
4120
|
+
}
|
|
4121
|
+
),
|
|
4122
|
+
renderPopover(
|
|
4123
|
+
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4124
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center justify-between border-b border-border px-3 py-2", children: [
|
|
4125
|
+
/* @__PURE__ */ jsx("span", { className: popoverHeadingClass, children: "Variables" }),
|
|
4126
|
+
/* @__PURE__ */ jsx(
|
|
4127
|
+
"button",
|
|
4128
|
+
{
|
|
4129
|
+
type: "button",
|
|
4130
|
+
onClick: close,
|
|
4131
|
+
"aria-label": "Close variables",
|
|
4132
|
+
className: "inline-flex h-5 w-5 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground",
|
|
4133
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
|
|
4134
|
+
}
|
|
4135
|
+
)
|
|
4136
|
+
] }),
|
|
4137
|
+
/* @__PURE__ */ jsx("div", { className: "ss-variables-panel min-h-0 overflow-y-auto p-3", children: children2 })
|
|
4138
|
+
] })
|
|
4139
|
+
)
|
|
4140
|
+
] });
|
|
4141
|
+
}
|
|
3598
4142
|
var ChatVariablesForm = forwardRef(({ workspace, threadId, setVariables }, ref) => {
|
|
3599
4143
|
const vm = useChatVariablesFormVm({ workspace, threadId, setVariables });
|
|
3600
4144
|
useImperativeHandle(ref, () => ({
|
|
@@ -3610,20 +4154,85 @@ var ChatVariablesForm = forwardRef(({ workspace, threadId, setVariables }, ref)
|
|
|
3610
4154
|
if (!vm.isHydrated) {
|
|
3611
4155
|
return /* @__PURE__ */ jsx("div", { className: "flex justify-center items-center w-full h-8", children: /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin text-primary" }) });
|
|
3612
4156
|
}
|
|
3613
|
-
|
|
3614
|
-
|
|
4157
|
+
const formProps = {
|
|
4158
|
+
schema: vm.schema,
|
|
4159
|
+
data: vm.data,
|
|
4160
|
+
renderers: vm.renderers,
|
|
4161
|
+
cells: vm.cells,
|
|
4162
|
+
ajv: vm.ajv,
|
|
4163
|
+
onChange: vm.onChange
|
|
4164
|
+
};
|
|
4165
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex w-full min-w-0 items-center gap-1", children: [
|
|
4166
|
+
vm.inlineUiSchema && /* @__PURE__ */ jsx("div", { className: "min-w-0 jsonforms-compact", children: /* @__PURE__ */ jsx(
|
|
4167
|
+
JsonForms,
|
|
4168
|
+
{
|
|
4169
|
+
...formProps,
|
|
4170
|
+
uischema: vm.inlineUiSchema,
|
|
4171
|
+
config: vm.barConfig
|
|
4172
|
+
}
|
|
4173
|
+
) }),
|
|
4174
|
+
vm.overflowUiSchema && /* @__PURE__ */ jsx(VariablesOverflowPanel, { count: vm.overflowCount, children: /* @__PURE__ */ jsx("div", { className: "jsonforms-compact", children: /* @__PURE__ */ jsx(
|
|
4175
|
+
JsonForms,
|
|
4176
|
+
{
|
|
4177
|
+
...formProps,
|
|
4178
|
+
uischema: vm.overflowUiSchema,
|
|
4179
|
+
config: vm.panelConfig
|
|
4180
|
+
}
|
|
4181
|
+
) }) })
|
|
4182
|
+
] });
|
|
4183
|
+
});
|
|
4184
|
+
var dictationErrorMessages = {
|
|
4185
|
+
"permission-denied": "Microphone access is blocked \u2014 allow it in your browser settings and try again",
|
|
4186
|
+
"no-microphone": "No microphone was found",
|
|
4187
|
+
network: "Could not reach the speech service \u2014 try again",
|
|
4188
|
+
"unavailable-temporarily": "Dictation is starting up \u2014 try again in a moment",
|
|
4189
|
+
unavailable: "Dictation is not available on this workspace",
|
|
4190
|
+
unknown: "Dictation stopped unexpectedly \u2014 try again"
|
|
4191
|
+
};
|
|
4192
|
+
function DictationButton({
|
|
4193
|
+
state,
|
|
4194
|
+
error,
|
|
4195
|
+
disabled,
|
|
4196
|
+
onToggle,
|
|
4197
|
+
deviceLabel,
|
|
4198
|
+
size = "sm"
|
|
4199
|
+
}) {
|
|
4200
|
+
const listening = state === "listening";
|
|
4201
|
+
const starting = state === "starting";
|
|
4202
|
+
const label = listening ? "Stop dictation" : "Dictate a message";
|
|
4203
|
+
const hint = listening && deviceLabel ? `${label} \u2014 ${deviceLabel}` : label;
|
|
4204
|
+
const dims = size === "sm" ? "h-8 w-8" : "h-9 w-9";
|
|
4205
|
+
const icon = size === "sm" ? "h-4 w-4" : "h-5 w-5";
|
|
4206
|
+
return /* @__PURE__ */ jsxs(
|
|
4207
|
+
IconButton2,
|
|
3615
4208
|
{
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
4209
|
+
type: "button",
|
|
4210
|
+
onClick: onToggle,
|
|
4211
|
+
disabled,
|
|
4212
|
+
"aria-pressed": listening,
|
|
4213
|
+
"aria-label": label,
|
|
4214
|
+
title: error ? dictationErrorMessages[error] : hint,
|
|
4215
|
+
className: `relative ${dims} rounded-full transition-colors ${listening ? "bg-destructive text-destructive-foreground hover:bg-destructive/90" : "text-muted-foreground hover:bg-secondary"}`,
|
|
4216
|
+
children: [
|
|
4217
|
+
starting && /* @__PURE__ */ jsx(
|
|
4218
|
+
"span",
|
|
4219
|
+
{
|
|
4220
|
+
"aria-hidden": "true",
|
|
4221
|
+
className: "absolute inset-0 animate-spin rounded-full border-2 border-transparent border-t-current opacity-70"
|
|
4222
|
+
}
|
|
4223
|
+
),
|
|
4224
|
+
listening && /* @__PURE__ */ jsx(
|
|
4225
|
+
"span",
|
|
4226
|
+
{
|
|
4227
|
+
"aria-hidden": "true",
|
|
4228
|
+
className: "absolute inset-0 animate-ping rounded-full bg-destructive/30"
|
|
4229
|
+
}
|
|
4230
|
+
),
|
|
4231
|
+
listening ? /* @__PURE__ */ jsx(Square, { className: `relative ${icon} fill-current` }) : /* @__PURE__ */ jsx(Mic, { className: `relative ${icon}` })
|
|
4232
|
+
]
|
|
3624
4233
|
}
|
|
3625
|
-
)
|
|
3626
|
-
}
|
|
4234
|
+
);
|
|
4235
|
+
}
|
|
3627
4236
|
|
|
3628
4237
|
// src/domains/workspaces/queryKeys.ts
|
|
3629
4238
|
var workspaceKeys = {
|
|
@@ -3856,6 +4465,40 @@ function MessageComposer(_props = {}) {
|
|
|
3856
4465
|
cancelReset();
|
|
3857
4466
|
}
|
|
3858
4467
|
}, [isSending, cancelAccepted, cancelErrored, cancelReset]);
|
|
4468
|
+
const attachEditor = useCallback(
|
|
4469
|
+
(handle2) => {
|
|
4470
|
+
if (handle2) editorRef.current = handle2;
|
|
4471
|
+
},
|
|
4472
|
+
// Both flags matter: the portal mounts on `isMobile && isFullscreen`, and
|
|
4473
|
+
// nothing resets isFullscreen when the breakpoint flips, so crossing it
|
|
4474
|
+
// while fullscreen would unmount the portal editor without re-attaching the
|
|
4475
|
+
// inline one — leaving a destroyed handle and silently swallowing phrases.
|
|
4476
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
4477
|
+
[isFullscreen, isMobile]
|
|
4478
|
+
);
|
|
4479
|
+
const { data: speechConfig, isFetching: speechConfigLoading } = useSpeechConfig();
|
|
4480
|
+
const getSpeechToken = useMemo(
|
|
4481
|
+
() => chatService.getSpeechToken?.bind(chatService),
|
|
4482
|
+
[chatService]
|
|
4483
|
+
);
|
|
4484
|
+
const dictation = useDictation({
|
|
4485
|
+
region: speechConfig?.enabled ? speechConfig.region : null,
|
|
4486
|
+
locale: speechConfig?.defaultLocale ?? "en-US",
|
|
4487
|
+
getToken: getSpeechToken,
|
|
4488
|
+
// Final phrases become real text; provisional ones render as greyed ghost
|
|
4489
|
+
// text at the caret and never enter the document.
|
|
4490
|
+
onPhrase: (text6) => editorRef.current?.insertText(`${text6} `),
|
|
4491
|
+
onInterim: (text6) => editorRef.current?.setDictationGhost(text6)
|
|
4492
|
+
});
|
|
4493
|
+
const { stop: stopDictation } = dictation;
|
|
4494
|
+
const dictationUnavailableReason = speechConfigLoading ? "Checking whether dictation is available" : dictation.supported ? "Dictation is not enabled for this workspace" : "Dictation is not available in this browser";
|
|
4495
|
+
const handleDictationToggle = () => {
|
|
4496
|
+
if (dictation.state === "idle") editorRef.current?.focus();
|
|
4497
|
+
dictation.toggle();
|
|
4498
|
+
};
|
|
4499
|
+
useEffect(() => {
|
|
4500
|
+
if (disabled) stopDictation();
|
|
4501
|
+
}, [disabled, stopDictation]);
|
|
3859
4502
|
useEffect(() => {
|
|
3860
4503
|
if (typeof window === "undefined") return;
|
|
3861
4504
|
window.__ssDownloadFile = (id) => getFileBlobUrl(id);
|
|
@@ -3975,6 +4618,7 @@ function MessageComposer(_props = {}) {
|
|
|
3975
4618
|
const latestText = editorRef.current?.getMarkdown() ?? newMessage;
|
|
3976
4619
|
const sent = handleSendMessage(latestText, uploadedAttachments);
|
|
3977
4620
|
if (!sent) return;
|
|
4621
|
+
stopDictation();
|
|
3978
4622
|
handleClearAttachments();
|
|
3979
4623
|
setEditorKey((k) => k + 1);
|
|
3980
4624
|
};
|
|
@@ -4081,7 +4725,7 @@ function MessageComposer(_props = {}) {
|
|
|
4081
4725
|
/* @__PURE__ */ jsx("div", { className: "max-h-[400px] w-full overflow-y-auto", children: /* @__PURE__ */ jsx(
|
|
4082
4726
|
MarkdownEditor,
|
|
4083
4727
|
{
|
|
4084
|
-
ref:
|
|
4728
|
+
ref: attachEditor,
|
|
4085
4729
|
value: newMessage,
|
|
4086
4730
|
onChange: (md) => setNewMessage(md),
|
|
4087
4731
|
onKeyDown: handleComposerKeyDown,
|
|
@@ -4094,14 +4738,22 @@ function MessageComposer(_props = {}) {
|
|
|
4094
4738
|
disabled,
|
|
4095
4739
|
placeholder: "What would you like to do?",
|
|
4096
4740
|
className: "md-editor--bare px-5 pb-3 pt-4 text-sm",
|
|
4097
|
-
minHeight:
|
|
4741
|
+
minHeight: 24
|
|
4098
4742
|
},
|
|
4099
4743
|
`composer-md-${editorKey}`
|
|
4100
4744
|
) }),
|
|
4745
|
+
/* @__PURE__ */ jsx("div", { role: "status", className: "sr-only", children: dictation.state === "listening" ? dictation.silent ? `Listening, but not hearing anything from ${dictation.deviceLabel || "your microphone"}` : "Listening" : dictation.state === "starting" ? "Starting dictation" : "" }),
|
|
4746
|
+
dictation.state === "listening" && dictation.silent && /* @__PURE__ */ jsxs("div", { className: "px-5 pb-1 text-xs text-muted-foreground", children: [
|
|
4747
|
+
"Not hearing anything from",
|
|
4748
|
+
" ",
|
|
4749
|
+
dictation.deviceLabel || "your microphone",
|
|
4750
|
+
"."
|
|
4751
|
+
] }),
|
|
4752
|
+
dictation.error && /* @__PURE__ */ jsx("div", { role: "alert", className: "px-5 pb-1 text-xs text-destructive", children: dictationErrorMessages[dictation.error] }),
|
|
4101
4753
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 px-3 pb-3", children: [
|
|
4102
4754
|
/* @__PURE__ */ jsxs("div", { className: "ss-composer__actions flex min-w-0 flex-1 items-center gap-1", children: [
|
|
4103
4755
|
supportsFiles && /* @__PURE__ */ jsx(
|
|
4104
|
-
|
|
4756
|
+
IconButton2,
|
|
4105
4757
|
{
|
|
4106
4758
|
type: "button",
|
|
4107
4759
|
onClick: handlePickFilesClick,
|
|
@@ -4122,19 +4774,39 @@ function MessageComposer(_props = {}) {
|
|
|
4122
4774
|
)
|
|
4123
4775
|
] }),
|
|
4124
4776
|
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1.5", children: [
|
|
4125
|
-
/* @__PURE__ */ jsx(
|
|
4126
|
-
|
|
4777
|
+
dictation.available ? /* @__PURE__ */ jsx(
|
|
4778
|
+
DictationButton,
|
|
4127
4779
|
{
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
children: /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" })
|
|
4780
|
+
state: dictation.state,
|
|
4781
|
+
error: dictation.error,
|
|
4782
|
+
disabled,
|
|
4783
|
+
onToggle: handleDictationToggle,
|
|
4784
|
+
deviceLabel: dictation.deviceLabel
|
|
4134
4785
|
}
|
|
4786
|
+
) : (
|
|
4787
|
+
// A disabled button receives no pointer events, so its own
|
|
4788
|
+
// `title` never renders a tooltip. The wrapper is what the user
|
|
4789
|
+
// actually hovers.
|
|
4790
|
+
/* @__PURE__ */ jsx(
|
|
4791
|
+
"span",
|
|
4792
|
+
{
|
|
4793
|
+
title: dictationUnavailableReason,
|
|
4794
|
+
className: "inline-flex cursor-not-allowed",
|
|
4795
|
+
children: /* @__PURE__ */ jsx(
|
|
4796
|
+
IconButton2,
|
|
4797
|
+
{
|
|
4798
|
+
type: "button",
|
|
4799
|
+
disabled: true,
|
|
4800
|
+
"aria-label": `Dictate a message. ${dictationUnavailableReason}`,
|
|
4801
|
+
className: "h-8 w-8 rounded-full text-muted-foreground",
|
|
4802
|
+
children: /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" })
|
|
4803
|
+
}
|
|
4804
|
+
)
|
|
4805
|
+
}
|
|
4806
|
+
)
|
|
4135
4807
|
),
|
|
4136
4808
|
canStop ? /* @__PURE__ */ jsx(
|
|
4137
|
-
|
|
4809
|
+
IconButton2,
|
|
4138
4810
|
{
|
|
4139
4811
|
onClick: handleStopRun,
|
|
4140
4812
|
className: "chat-send h-8 w-8 rounded-full",
|
|
@@ -4148,7 +4820,7 @@ function MessageComposer(_props = {}) {
|
|
|
4148
4820
|
)
|
|
4149
4821
|
}
|
|
4150
4822
|
) : /* @__PURE__ */ jsx(
|
|
4151
|
-
|
|
4823
|
+
IconButton2,
|
|
4152
4824
|
{
|
|
4153
4825
|
onClick: handleSendMessageAndClear,
|
|
4154
4826
|
className: `chat-send h-8 w-8 rounded-full ${sendDisabled ? "cursor-not-allowed" : ""}`,
|
|
@@ -4177,7 +4849,7 @@ function MessageComposer(_props = {}) {
|
|
|
4177
4849
|
},
|
|
4178
4850
|
children: /* @__PURE__ */ jsxs("div", { className: "relative h-full w-full bg-background border shadow-lg", children: [
|
|
4179
4851
|
/* @__PURE__ */ jsx(
|
|
4180
|
-
|
|
4852
|
+
IconButton2,
|
|
4181
4853
|
{
|
|
4182
4854
|
type: "button",
|
|
4183
4855
|
size: "small",
|
|
@@ -4195,7 +4867,7 @@ function MessageComposer(_props = {}) {
|
|
|
4195
4867
|
/* @__PURE__ */ jsx("div", { className: "flex-1 p-4", children: /* @__PURE__ */ jsx(
|
|
4196
4868
|
MarkdownEditor,
|
|
4197
4869
|
{
|
|
4198
|
-
ref:
|
|
4870
|
+
ref: attachEditor,
|
|
4199
4871
|
value: newMessage,
|
|
4200
4872
|
onChange: (md) => setNewMessage(md),
|
|
4201
4873
|
onKeyDown: handleComposerKeyDown,
|
|
@@ -4210,10 +4882,18 @@ function MessageComposer(_props = {}) {
|
|
|
4210
4882
|
},
|
|
4211
4883
|
`composer-md-${editorKey}`
|
|
4212
4884
|
) }),
|
|
4885
|
+
dictation.error && /* @__PURE__ */ jsx(
|
|
4886
|
+
"div",
|
|
4887
|
+
{
|
|
4888
|
+
"aria-hidden": "true",
|
|
4889
|
+
className: "px-4 pb-1 text-xs text-destructive",
|
|
4890
|
+
children: dictationErrorMessages[dictation.error]
|
|
4891
|
+
}
|
|
4892
|
+
),
|
|
4213
4893
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-t bg-background", children: [
|
|
4214
4894
|
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
4215
4895
|
supportsFiles && /* @__PURE__ */ jsx(
|
|
4216
|
-
|
|
4896
|
+
IconButton2,
|
|
4217
4897
|
{
|
|
4218
4898
|
type: "button",
|
|
4219
4899
|
onClick: handlePickFilesClick,
|
|
@@ -4228,8 +4908,19 @@ function MessageComposer(_props = {}) {
|
|
|
4228
4908
|
)
|
|
4229
4909
|
}
|
|
4230
4910
|
),
|
|
4911
|
+
dictation.available && /* @__PURE__ */ jsx(
|
|
4912
|
+
DictationButton,
|
|
4913
|
+
{
|
|
4914
|
+
size: "md",
|
|
4915
|
+
state: dictation.state,
|
|
4916
|
+
error: dictation.error,
|
|
4917
|
+
disabled,
|
|
4918
|
+
onToggle: handleDictationToggle,
|
|
4919
|
+
deviceLabel: dictation.deviceLabel
|
|
4920
|
+
}
|
|
4921
|
+
),
|
|
4231
4922
|
canStop ? /* @__PURE__ */ jsx(
|
|
4232
|
-
|
|
4923
|
+
IconButton2,
|
|
4233
4924
|
{
|
|
4234
4925
|
onClick: handleStopRun,
|
|
4235
4926
|
className: "chat-send h-9 w-9 rounded-full",
|
|
@@ -4243,7 +4934,7 @@ function MessageComposer(_props = {}) {
|
|
|
4243
4934
|
)
|
|
4244
4935
|
}
|
|
4245
4936
|
) : /* @__PURE__ */ jsx(
|
|
4246
|
-
|
|
4937
|
+
IconButton2,
|
|
4247
4938
|
{
|
|
4248
4939
|
onClick: handleSendMessageAndClear,
|
|
4249
4940
|
className: `chat-send h-9 w-9 rounded-full ${sendDisabled ? "cursor-not-allowed" : ""}`,
|
|
@@ -19173,7 +19864,7 @@ var buttonVariants = cva(
|
|
|
19173
19864
|
}
|
|
19174
19865
|
}
|
|
19175
19866
|
);
|
|
19176
|
-
var Button =
|
|
19867
|
+
var Button = React9.forwardRef(
|
|
19177
19868
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
19178
19869
|
const Comp = asChild ? Slot : "button";
|
|
19179
19870
|
return /* @__PURE__ */ jsx(
|
|
@@ -19724,6 +20415,7 @@ function ChatMessageSources({
|
|
|
19724
20415
|
] })
|
|
19725
20416
|
] });
|
|
19726
20417
|
}
|
|
20418
|
+
var USER_FORM_CONFIG = { surface: "form", minRows: 6, maxRows: 20 };
|
|
19727
20419
|
var REVEAL_ON_HOVER = "opacity-100 focus-visible:opacity-100 [@media(hover:hover)]:opacity-0 [@media(hover:hover)]:group-hover:opacity-100";
|
|
19728
20420
|
var MessageBubble = (props) => {
|
|
19729
20421
|
const {
|
|
@@ -19777,7 +20469,7 @@ var MessageBubble = (props) => {
|
|
|
19777
20469
|
);
|
|
19778
20470
|
})
|
|
19779
20471
|
] }),
|
|
19780
|
-
showForm && /* @__PURE__ */ jsxs("div", { className: "mt-4 border-t border-border pt-4", children: [
|
|
20472
|
+
showForm && /* @__PURE__ */ jsxs("div", { className: "ss-chat-message__user-form mt-4 border-t border-border pt-4", children: [
|
|
19781
20473
|
/* @__PURE__ */ jsx(
|
|
19782
20474
|
JsonForms,
|
|
19783
20475
|
{
|
|
@@ -19786,6 +20478,7 @@ var MessageBubble = (props) => {
|
|
|
19786
20478
|
renderers,
|
|
19787
20479
|
cells,
|
|
19788
20480
|
readonly: userInput !== void 0,
|
|
20481
|
+
config: USER_FORM_CONFIG,
|
|
19789
20482
|
onChange: ({ data, errors }) => {
|
|
19790
20483
|
setResponseFormData(data);
|
|
19791
20484
|
setResponseFormValid(!errors?.length);
|
|
@@ -19930,14 +20623,14 @@ var MessageItem = ({
|
|
|
19930
20623
|
const { data: workspace } = useWorkspace(workspaceId);
|
|
19931
20624
|
const chatbotName = getChatbotName(workspace?.name);
|
|
19932
20625
|
const { addInputToMessageMutation } = useAddInputToMessage();
|
|
19933
|
-
const onSubmitUserForm = (messageId) => (name, value) => {
|
|
20626
|
+
const onSubmitUserForm = (messageId, channels = {}) => (name, value) => {
|
|
19934
20627
|
if (!threadId || !messageId) return;
|
|
19935
20628
|
addInputToMessageMutation.mutate({
|
|
19936
20629
|
threadId,
|
|
19937
20630
|
messageId,
|
|
19938
20631
|
name,
|
|
19939
20632
|
value,
|
|
19940
|
-
channels
|
|
20633
|
+
channels
|
|
19941
20634
|
});
|
|
19942
20635
|
};
|
|
19943
20636
|
const safeTime = (d) => {
|
|
@@ -20068,7 +20761,7 @@ var MessageItem = ({
|
|
|
20068
20761
|
userOutput: v.value && typeof v.value === "object" ? v.value : null,
|
|
20069
20762
|
chatbotName,
|
|
20070
20763
|
userInput: userInput?.value,
|
|
20071
|
-
onSubmitUserForm: onSubmitUserForm(message.id ?? "")
|
|
20764
|
+
onSubmitUserForm: onSubmitUserForm(message.id ?? "", v.channels)
|
|
20072
20765
|
},
|
|
20073
20766
|
`user-${message.id ?? "msg"}-${keyCounter++}`
|
|
20074
20767
|
)
|
|
@@ -20264,6 +20957,7 @@ function MessageList({
|
|
|
20264
20957
|
] }) });
|
|
20265
20958
|
}
|
|
20266
20959
|
if (safeMessages.length === 0 && !hadMessagesBefore) {
|
|
20960
|
+
const descriptionParagraphs = (activeWorkspace?.summary ?? "").split(/\n+/).map((paragraph2) => paragraph2.trim()).filter(Boolean);
|
|
20267
20961
|
return (
|
|
20268
20962
|
// A new thread opens the way the design does: the greeting and the
|
|
20269
20963
|
// composer travel together as one narrower block centred in the canvas.
|
|
@@ -20276,6 +20970,14 @@ function MessageList({
|
|
|
20276
20970
|
"data-ss-layer": "message-list",
|
|
20277
20971
|
children: /* @__PURE__ */ jsxs("div", { className: "mx-auto mb-6 w-full max-w-2xl px-4 text-center", children: [
|
|
20278
20972
|
/* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold text-foreground", children: "What\u2019s on the agenda today?" }),
|
|
20973
|
+
descriptionParagraphs.length > 0 && /* @__PURE__ */ jsx(
|
|
20974
|
+
"div",
|
|
20975
|
+
{
|
|
20976
|
+
className: "mx-auto mt-2 max-w-lg space-y-1.5 text-sm text-muted-foreground",
|
|
20977
|
+
"data-ss-layer": "workspace-description",
|
|
20978
|
+
children: descriptionParagraphs.map((paragraph2, index) => /* @__PURE__ */ jsx("p", { children: paragraph2 }, index))
|
|
20979
|
+
}
|
|
20980
|
+
),
|
|
20279
20981
|
activeWorkspace?.firstPrompt && /* @__PURE__ */ jsx("div", { className: "chat-prose mt-3 text-center", children: /* @__PURE__ */ jsx(MessageMarkdown, { value: activeWorkspace.firstPrompt }) })
|
|
20280
20982
|
] })
|
|
20281
20983
|
}
|
|
@@ -20567,6 +21269,6 @@ function getUserPhotoUrl(userId) {
|
|
|
20567
21269
|
return `${base2}/users/${userId}/photo`;
|
|
20568
21270
|
}
|
|
20569
21271
|
|
|
20570
|
-
export { ChatProvider, ChatVariablesForm, DRAFT_THREAD_PREFIX, DateFromApi, MarkdownEditor, MessageComposer, MessageList, MessageListSkeleton, MessageMarkdown, MessageValueType, NEW_THREAD_ID, THREAD_LIST_PAGE_SIZE, applyDeltaToMessage, applyThreadToCache, createDraftThreadId, createThreadId, downloadFileBlobOptions, filesKeys, flowRunsKeys, getMessageErrorText, getModelIcon, getRetryStatusText, getThreadPlaceholderFromListCache, getUserPhotoUrl, invalidateWorkspaceThreadLists, isDraftThreadId, mapFileInfoDtoToModel, mapMentionUserDtoToModel, mapMessageDtoToModel, mapMessageErrorDtoToModel, mapMessageValueDtoToModel, mapMessagesDtoToModels, mapSignalRThreadSummaryToModel, mapThreadDtoToModel, mapThreadsResponseDtoToModel, mapWorkspaceDtoToModel, mapWorkspacesDtoToModels, markDraftThreadId, messagesKeys, messagesListOptions, messagesMutationsKeys, modelsKeys, parseDateTime, parseDateTimeHuman, parseRetryStatus, randomUUID, setThreadOptimisticRunning, setThreadRunningInLists, taggableUsersOptions, threadDetailOptions, threadsKeys, unmarkDraftThreadId, useAddInputToMessage, useChatContext, useChatIdentity, useChatService, useDownloadFileBlobQuery, useFileMutations, useFlowRunVariables, useIsDraftThreadId, useMessages, useModels, useSendMessage, useTaggableWorkspaceUsers, useThread, useThreadIsRunning, useUpdateFlowRunVariable, useWorkspace, utcDate, workspaceDetailOptions, workspaceKeys };
|
|
21272
|
+
export { ChatProvider, ChatVariablesForm, DRAFT_THREAD_PREFIX, DateFromApi, DictationButton, MarkdownEditor, MessageComposer, MessageList, MessageListSkeleton, MessageMarkdown, MessageValueType, NEW_THREAD_ID, THREAD_LIST_PAGE_SIZE, applyDeltaToMessage, applyThreadToCache, createDraftThreadId, createThreadId, downloadFileBlobOptions, filesKeys, flowRunsKeys, getMessageErrorText, getModelIcon, getRetryStatusText, getThreadPlaceholderFromListCache, getUserPhotoUrl, invalidateWorkspaceThreadLists, isDraftThreadId, mapFileInfoDtoToModel, mapMentionUserDtoToModel, mapMessageDtoToModel, mapMessageErrorDtoToModel, mapMessageValueDtoToModel, mapMessagesDtoToModels, mapSignalRThreadSummaryToModel, mapThreadDtoToModel, mapThreadsResponseDtoToModel, mapWorkspaceDtoToModel, mapWorkspacesDtoToModels, markDraftThreadId, messagesKeys, messagesListOptions, messagesMutationsKeys, modelsKeys, parseDateTime, parseDateTimeHuman, parseRetryStatus, randomUUID, setThreadOptimisticRunning, setThreadRunningInLists, speechKeys, taggableUsersOptions, threadDetailOptions, threadsKeys, unmarkDraftThreadId, useAddInputToMessage, useChatContext, useChatIdentity, useChatService, useDictation, useDownloadFileBlobQuery, useFileMutations, useFlowRunVariables, useIsDraftThreadId, useMessages, useModels, useSendMessage, useSpeechConfig, useTaggableWorkspaceUsers, useThread, useThreadIsRunning, useUpdateFlowRunVariable, useWorkspace, utcDate, workspaceDetailOptions, workspaceKeys };
|
|
20571
21273
|
//# sourceMappingURL=index.js.map
|
|
20572
21274
|
//# sourceMappingURL=index.js.map
|