@jini-ai/ui 0.6.16 → 0.6.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/dist/features/charts/catalog-manifests.d.ts +25 -0
- package/dist/features/charts/catalog-manifests.js +73 -0
- package/dist/features/charts/index.d.ts +2 -1
- package/dist/features/charts/index.js +2 -1
- package/dist/features/charts/react.d.ts +10 -6
- package/dist/features/charts/react.js +40 -33
- package/dist/features/charts/wire.d.ts +733 -0
- package/dist/features/charts/wire.js +37 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ar.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.bn.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.de.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.en.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.es.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fa.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.fr.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hi.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.hu.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.id.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.it.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ja.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ko.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pl.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.pt-BR.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ru.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.th.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.tr.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.uk.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.ur.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-CN.js +3 -0
- package/dist/features/i18n/dictionaries/settings-dialog.zh-TW.js +3 -0
- package/dist/features/interactive-ui/index.js +4 -1
- package/dist/features/lexical-rich-text-editor/react/components/RichTextInput.js +2 -1
- package/dist/features/mcp-ui/surfaces/outcome.d.ts +7 -1
- package/dist/features/mcp-ui/surfaces/outcome.js +47 -8
- package/dist/features/sketch-editor/react/hooks/useSketchSaveWorkflow.js +2 -1
- package/dist/react/components/TooltipLayer.js +27 -2
- package/package.json +10 -10
|
@@ -25,6 +25,43 @@ export const rechartsPieChartManifest = {
|
|
|
25
25
|
propsSchema: rechartsPieChartPropsSchema, description: 'Pie chart: named, weighted slices. Uses an enabled chart provider or a styled data table.',
|
|
26
26
|
};
|
|
27
27
|
export const chartWireManifests = [rechartsBarChartManifest, rechartsLineChartManifest, rechartsPieChartManifest];
|
|
28
|
+
/** A series point is a finite number, or null for a gap (a missing month on a line). */
|
|
29
|
+
function isSeriesValue(value) {
|
|
30
|
+
return value === null || (typeof value === 'number' && Number.isFinite(value));
|
|
31
|
+
}
|
|
32
|
+
function isCategoryValue(value) {
|
|
33
|
+
return typeof value === 'string' || (typeof value === 'number' && Number.isFinite(value));
|
|
34
|
+
}
|
|
35
|
+
/** Report the first bad row per key only, so a large table of strings yields one issue, not thousands. */
|
|
36
|
+
function checkColumn({ rows, key, accepts, expected, ctx }, _options = {}) {
|
|
37
|
+
const index = rows.findIndex((row) => !Object.hasOwn(row, key) || !accepts(row[key]));
|
|
38
|
+
if (index < 0)
|
|
39
|
+
return;
|
|
40
|
+
const problem = Object.hasOwn(rows[index], key) ? `is not ${expected}` : 'is missing';
|
|
41
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['data', index, key], message: `Row ${index} "${key}" ${problem}; every row needs it.` });
|
|
42
|
+
}
|
|
43
|
+
/** Rows are the shared x axis: every row carries every series key, so series lengths always match. */
|
|
44
|
+
function checkSeriesShape(spec, ctx) {
|
|
45
|
+
const keys = spec.series.map(({ key }) => key);
|
|
46
|
+
const duplicate = keys.find((key, index) => keys.indexOf(key) !== index);
|
|
47
|
+
if (duplicate !== undefined) {
|
|
48
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, path: ['series'], message: `Series key "${duplicate}" is listed twice.` });
|
|
49
|
+
}
|
|
50
|
+
if (spec.categoryKey !== undefined) {
|
|
51
|
+
checkColumn({ rows: spec.data, key: spec.categoryKey, accepts: isCategoryValue, expected: 'a string or number', ctx });
|
|
52
|
+
}
|
|
53
|
+
for (const key of new Set(keys))
|
|
54
|
+
checkColumn({ rows: spec.data, key, accepts: isSeriesValue, expected: 'a number or null', ctx });
|
|
55
|
+
}
|
|
56
|
+
/** `chart.spec` props: one neutral spec, any kind, one or more series. Stricter than the contract
|
|
57
|
+
* (which also carries converted legacy data) because an agent writes this shape directly.
|
|
58
|
+
*/
|
|
59
|
+
export const chartSpecPropsSchema = z.object({
|
|
60
|
+
spec: chartSpecSchema.extend({
|
|
61
|
+
data: chartSpecSchema.shape.data.min(1),
|
|
62
|
+
series: chartSpecSchema.shape.series.min(1),
|
|
63
|
+
}).superRefine(checkSeriesShape),
|
|
64
|
+
}).passthrough();
|
|
28
65
|
/** Convert validated legacy props to the neutral contract; optional provider overrides stay data.
|
|
29
66
|
* @example legacyChartSpec({ kind: 'pie', props: { data: [{ name: 'A', value: 2 }] } })
|
|
30
67
|
* @throws ZodError for an invalid wire shape or nonserializable row data.
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_AR = {
|
|
2
|
+
"Folders ({count})": "المجلدات ({count})",
|
|
3
|
+
"Copy folder path: {path}": "نسخ مسار المجلد: {path}",
|
|
4
|
+
"Remove folder: {path}": "إزالة المجلد: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "أزلت من رسالتك ما بدا كمفتاح. إن كان حقيقيًا، فاستبدله. استخدم النموذج الآمن لحفظه.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "استخدم النموذج الآمن لحفظ المفاتيح والرموز وكلمات المرور والأسرار. تُرسل إجابات الدردشة إلى المساعد.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# مهارتي\n\n1. اشرح سير العمل.\n2. صف المدخلات والمخرجات.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_BN = {
|
|
2
|
+
"Folders ({count})": "ফোল্ডার ({count})",
|
|
3
|
+
"Copy folder path: {path}": "ফোল্ডারের পাথ কপি করুন: {path}",
|
|
4
|
+
"Remove folder: {path}": "ফোল্ডার সরান: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "আপনার বার্তা থেকে কী বলে মনে হওয়া অংশটি সরিয়ে দিয়েছি। সেটি আসল হলে বদলে ফেলুন। সংরক্ষণ করতে নিরাপদ ফর্ম ব্যবহার করুন।",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "কী, টোকেন, পাসওয়ার্ড ও গোপন তথ্য সংরক্ষণ করতে নিরাপদ ফর্ম ব্যবহার করুন। চ্যাটের উত্তর সহকারীকে পাঠানো হয়।",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# আমার স্কিল\n\n1. ওয়ার্কফ্লো ব্যাখ্যা করুন।\n2. ইনপুট এবং আউটপুট বর্ণনা করুন।',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_DE = {
|
|
2
|
+
"Folders ({count})": "Ordner ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Ordnerpfad kopieren: {path}",
|
|
4
|
+
"Remove folder: {path}": "Ordner entfernen: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Ich habe aus deiner Nachricht entfernt, was wie ein Schlüssel aussah. Falls er echt war, ersetze ihn. Speichere ihn über das sichere Formular.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Speichere Schlüssel, Tokens, Passwörter und Geheimnisse über das sichere Formular. Chatantworten werden an den Assistenten gesendet.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Meine Skill\n\n1. Erkläre den Workflow.\n2. Beschreibe die Eingaben und Ausgaben.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_EN = {
|
|
2
|
+
"Folders ({count})": "Folders ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Copy folder path: {path}",
|
|
4
|
+
"Remove folder: {path}": "Remove folder: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_ES = {
|
|
2
|
+
"Folders ({count})": "Carpetas ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Copiar ruta de carpeta: {path}",
|
|
4
|
+
"Remove folder: {path}": "Quitar carpeta: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "He eliminado de tu mensaje lo que parecía una clave. Si era real, cámbiala. Usa el formulario seguro para guardarla.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Usa el formulario seguro para guardar claves, tokens, contraseñas y secretos. Las respuestas del chat se envían al asistente.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Mi skill\n\n1. Explica el flujo de trabajo.\n2. Describe las entradas y salidas.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_FA = {
|
|
2
|
+
"Folders ({count})": "پوشهها ({count})",
|
|
3
|
+
"Copy folder path: {path}": "کپی مسیر پوشه: {path}",
|
|
4
|
+
"Remove folder: {path}": "حذف پوشه: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "متنی را که شبیه کلید بود از پیامتان حذف کردم. اگر واقعی بود، آن را تعویض کنید. برای ذخیره از فرم امن استفاده کنید.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "برای ذخیره کلیدها، توکنها، گذرواژهها و اطلاعات محرمانه از فرم امن استفاده کنید. پاسخهای گفتگو به دستیار فرستاده میشوند.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# مهارت من\n\n1. گردش کار را توضیح دهید.\n2. ورودیها و خروجیها را شرح دهید.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_FR = {
|
|
2
|
+
"Folders ({count})": "Dossiers ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Copier le chemin du dossier : {path}",
|
|
4
|
+
"Remove folder: {path}": "Retirer le dossier : {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "J’ai supprimé de votre message ce qui ressemblait à une clé. Si elle était réelle, remplacez-la. Utilisez le formulaire sécurisé pour l’enregistrer.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Utilisez le formulaire sécurisé pour enregistrer les clés, jetons, mots de passe et secrets. Les réponses du chat sont envoyées à l’assistant.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Ma compétence\n\n1. Expliquez le déroulement.\n2. Décrivez les entrées et sorties.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_HI = {
|
|
2
|
+
"Folders ({count})": "फ़ोल्डर ({count})",
|
|
3
|
+
"Copy folder path: {path}": "फ़ोल्डर का पथ कॉपी करें: {path}",
|
|
4
|
+
"Remove folder: {path}": "फ़ोल्डर हटाएँ: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "मैंने आपके संदेश से कुंजी जैसा दिखने वाला हिस्सा हटा दिया है। अगर वह असली कुंजी थी, तो उसे बदलें। उसे सहेजने के लिए सुरक्षित फ़ॉर्म का उपयोग करें।",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "कुंजियाँ, टोकन, पासवर्ड और गोपनीय जानकारी सहेजने के लिए सुरक्षित फ़ॉर्म का उपयोग करें। चैट के उत्तर सहायक को भेजे जाते हैं।",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# मेरी स्किल\n\n1. वर्कफ़्लो के बारे में बताएं।\n2. इनपुट और आउटपुट के बारे में बताएं।',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_HU = {
|
|
2
|
+
"Folders ({count})": "Mappák ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Mappa elérési útjának másolása: {path}",
|
|
4
|
+
"Remove folder: {path}": "Mappa eltávolítása: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Eltávolítottam az üzenetedből azt, ami kulcsnak tűnt. Ha valódi volt, cseréld le. A biztonságos űrlapon mentsd el.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "A kulcsokat, tokeneket, jelszavakat és titkokat a biztonságos űrlapon mentsd el. A chatválaszokat elküldjük az asszisztensnek.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Saját képességem\n\n1. Írd le a munkafolyamatot.\n2. Írd le a bemeneteket és a kimeneteket.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_ID = {
|
|
2
|
+
"Folders ({count})": "Folder ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Salin jalur folder: {path}",
|
|
4
|
+
"Remove folder: {path}": "Hapus folder: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Saya menghapus teks yang tampak seperti kunci dari pesan Anda. Jika itu kunci asli, gantilah. Gunakan formulir aman untuk menyimpannya.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Gunakan formulir aman untuk menyimpan kunci, token, kata sandi, dan rahasia. Jawaban chat dikirim ke asisten.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Skill saya\n\n1. Jelaskan alur kerjanya.\n2. Jelaskan input dan outputnya.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_IT = {
|
|
2
|
+
"Folders ({count})": "Cartelle ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Copia percorso cartella: {path}",
|
|
4
|
+
"Remove folder: {path}": "Rimuovi cartella: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Ho rimosso dal messaggio ciò che sembrava una chiave. Se era reale, sostituiscila. Usa il modulo sicuro per salvarla.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Usa il modulo sicuro per salvare chiavi, token, password e segreti. Le risposte nella chat vengono inviate all’assistente.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# La mia competenza\n\n1. Spiega il flusso di lavoro.\n2. Descrivi gli input e gli output.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_JA = {
|
|
2
|
+
"Folders ({count})": "フォルダー({count})",
|
|
3
|
+
"Copy folder path: {path}": "フォルダーのパスをコピー: {path}",
|
|
4
|
+
"Remove folder: {path}": "フォルダーを削除: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "メッセージからキーと思われる文字列を削除しました。本物のキーだった場合は再発行してください。保存には安全なフォームを使ってください。",
|
|
3
6
|
// eslint-disable-next-line sonarjs/no-hardcoded-passwords -- Translation of user-facing credential-safety guidance; the value is prose, not a password.
|
|
4
7
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "キー、トークン、パスワード、シークレットの保存には安全なフォームを使ってください。チャットの回答はアシスタントに送信されます。",
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_KO = {
|
|
2
|
+
"Folders ({count})": "폴더 ({count})",
|
|
3
|
+
"Copy folder path: {path}": "폴더 경로 복사: {path}",
|
|
4
|
+
"Remove folder: {path}": "폴더 제거: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "메시지에서 키로 보이는 내용을 제거했습니다. 실제 키였다면 교체하세요. 저장하려면 보안 양식을 사용하세요.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "키, 토큰, 비밀번호, 비밀 정보를 저장하려면 보안 양식을 사용하세요. 채팅 답변은 어시스턴트에게 전송됩니다.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# 내 스킬\n\n1. 워크플로를 설명하세요.\n2. 입력과 출력을 설명하세요.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_PL = {
|
|
2
|
+
"Folders ({count})": "Foldery ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Kopiuj ścieżkę folderu: {path}",
|
|
4
|
+
"Remove folder: {path}": "Usuń folder: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Usunąłem z wiadomości tekst, który wyglądał jak klucz. Jeśli był prawdziwy, wymień go. Zapisz go za pomocą bezpiecznego formularza.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Użyj bezpiecznego formularza do zapisywania kluczy, tokenów, haseł i sekretów. Odpowiedzi na czacie są wysyłane do asystenta.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Moja umiejętność\n\n1. Opisz przebieg pracy.\n2. Opisz dane wejściowe i wyjściowe.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_PT_BR = {
|
|
2
|
+
"Folders ({count})": "Pastas ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Copiar caminho da pasta: {path}",
|
|
4
|
+
"Remove folder: {path}": "Remover pasta: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Removi da sua mensagem o que parecia ser uma chave. Se era real, substitua-a. Use o formulário seguro para salvá-la.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Use o formulário seguro para salvar chaves, tokens, senhas e segredos. As respostas do chat são enviadas ao assistente.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Minha skill\n\n1. Explique o fluxo de trabalho.\n2. Descreva as entradas e saídas.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_RU = {
|
|
2
|
+
"Folders ({count})": "Папки ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Копировать путь папки: {path}",
|
|
4
|
+
"Remove folder: {path}": "Убрать папку: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Я удалил из сообщения то, что было похоже на ключ. Если он настоящий, замените его. Сохраните его через защищённую форму.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Используйте защищённую форму для сохранения ключей, токенов, паролей и секретов. Ответы в чате отправляются ассистенту.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Мой навык\n\n1. Опишите рабочий процесс.\n2. Опишите входные и выходные данные.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_TH = {
|
|
2
|
+
"Folders ({count})": "โฟลเดอร์ ({count})",
|
|
3
|
+
"Copy folder path: {path}": "คัดลอกพาธโฟลเดอร์: {path}",
|
|
4
|
+
"Remove folder: {path}": "นำโฟลเดอร์ออก: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "ฉันลบข้อความที่ดูเหมือนคีย์ออกจากข้อความของคุณแล้ว หากเป็นคีย์จริง ให้เปลี่ยนคีย์ใหม่ ใช้แบบฟอร์มที่ปลอดภัยเพื่อบันทึก",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "ใช้แบบฟอร์มที่ปลอดภัยเพื่อบันทึกคีย์ โทเค็น รหัสผ่าน และข้อมูลลับ คำตอบในแชตจะถูกส่งไปยังผู้ช่วย",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# ทักษะของฉัน\n\n1. อธิบายขั้นตอนการทำงาน\n2. อธิบายข้อมูลนำเข้าและผลลัพธ์',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_TR = {
|
|
2
|
+
"Folders ({count})": "Klasörler ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Klasör yolunu kopyala: {path}",
|
|
4
|
+
"Remove folder: {path}": "Klasörü kaldır: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Mesajınızdan anahtara benzeyen metni kaldırdım. Gerçekse yenileyin. Kaydetmek için güvenli formu kullanın.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Anahtarları, tokenları, parolaları ve gizli bilgileri kaydetmek için güvenli formu kullanın. Sohbet yanıtları asistana gönderilir.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Becerim\n\n1. İş akışını açıkla.\n2. Girdileri ve çıktıları tanımla.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_UK = {
|
|
2
|
+
"Folders ({count})": "Теки ({count})",
|
|
3
|
+
"Copy folder path: {path}": "Копіювати шлях теки: {path}",
|
|
4
|
+
"Remove folder: {path}": "Прибрати теку: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "Я видалив із повідомлення те, що було схоже на ключ. Якщо він справжній, замініть його. Збережіть його через захищену форму.",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "Використовуйте захищену форму для збереження ключів, токенів, паролів і секретів. Відповіді в чаті надсилаються асистенту.",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# Моя навичка\n\n1. Опишіть робочий процес.\n2. Опишіть вхідні та вихідні дані.',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_UR = {
|
|
2
|
+
"Folders ({count})": "فولڈرز ({count})",
|
|
3
|
+
"Copy folder path: {path}": "فولڈر کا راستہ کاپی کریں: {path}",
|
|
4
|
+
"Remove folder: {path}": "فولڈر ہٹائیں: {path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "میں نے آپ کے پیغام سے وہ متن ہٹا دیا جو کلید جیسا لگ رہا تھا۔ اگر وہ حقیقی تھی تو اسے تبدیل کریں۔ محفوظ کرنے کے لیے محفوظ فارم استعمال کریں۔",
|
|
3
6
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "کلیدیں، ٹوکن، پاس ورڈ اور راز محفوظ کرنے کے لیے محفوظ فارم استعمال کریں۔ چیٹ کے جوابات اسسٹنٹ کو بھیجے جاتے ہیں۔",
|
|
4
7
|
'# My skill\n\n1. Explain the workflow.\n2. Describe the inputs and outputs.': '# میری اسکل\n\n1. ورک فلو کی وضاحت کریں۔\n2. ان پٹس اور آؤٹ پٹس بیان کریں۔',
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_ZH_CN = {
|
|
2
|
+
"Folders ({count})": "文件夹({count})",
|
|
3
|
+
"Copy folder path: {path}": "复制文件夹路径:{path}",
|
|
4
|
+
"Remove folder: {path}": "移除文件夹:{path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "我已从你的消息中移除疑似密钥的内容。如果是真实密钥,请更换它。请使用安全表单保存。",
|
|
3
6
|
// eslint-disable-next-line sonarjs/no-hardcoded-passwords -- Translation of user-facing credential-safety guidance; the value is prose, not a password.
|
|
4
7
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "请使用安全表单保存密钥、令牌、密码和机密信息。聊天回答会发送给助手。",
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export const SETTINGS_DIALOG_ZH_TW = {
|
|
2
|
+
"Folders ({count})": "資料夾({count})",
|
|
3
|
+
"Copy folder path: {path}": "複製資料夾路徑:{path}",
|
|
4
|
+
"Remove folder: {path}": "移除資料夾:{path}",
|
|
2
5
|
"I removed what looked like a key from your message. If it was real, rotate it. Use the secure form to save it.": "我已從你的訊息中移除疑似金鑰的內容。如果是真實金鑰,請更換它。請使用安全表單儲存。",
|
|
3
6
|
// eslint-disable-next-line sonarjs/no-hardcoded-passwords -- Translation of user-facing credential-safety guidance; the value is prose, not a password.
|
|
4
7
|
"Use the secure form to save keys, tokens, passwords, and secrets. Chat answers are sent to the assistant.": "請使用安全表單儲存金鑰、權杖、密碼和機密資訊。聊天回答會傳送給助理。",
|
|
@@ -8,6 +8,7 @@ import { shadcnDataTableManifest, DataTable as ShadcnDataTable, shadcnButtonMani
|
|
|
8
8
|
import { createChartProviderRegistry } from '../charts/registry.js';
|
|
9
9
|
import { createChartInteractiveRegistry } from '../charts/react.js';
|
|
10
10
|
import { chartWireManifests } from '../charts/wire.js';
|
|
11
|
+
import { CHART_SPEC_COMPONENT_ID } from '../charts/catalog-manifests.js';
|
|
11
12
|
/**
|
|
12
13
|
* Every provider currently registered, shadcn preferred over the dependency-free native fallback
|
|
13
14
|
* for `data-table`/`table` — the same order `manifests.ts`'s `ALL_MANIFESTS` declares, so a
|
|
@@ -35,9 +36,11 @@ const nonChartRegistry = new InteractiveUiRegistry({ entries: [
|
|
|
35
36
|
] });
|
|
36
37
|
// Charts retain their wire IDs and validation while an unconfigured host renders the core table.
|
|
37
38
|
// Runtime providers belong to the host's admitted boot snapshot, never to the default registry.
|
|
39
|
+
// `chart.spec` is here too, so a saved multi-series chart still renders (as a table) in a host that
|
|
40
|
+
// has no provider snapshot. It stays out of `ALL_MANIFESTS`: that list is the legacy wire set.
|
|
38
41
|
const chartHosts = createChartInteractiveRegistry({ registry: nonChartRegistry, providers: createChartProviderRegistry({ providers: [] }) });
|
|
39
42
|
export const DEFAULT_INTERACTIVE_UI_REGISTRY = new InteractiveUiRegistry({ entries: [
|
|
40
43
|
...nonChartRegistry.list(),
|
|
41
|
-
...chartWireManifests.map(({ id }) => chartHosts.resolveById({ id })),
|
|
44
|
+
...[...chartWireManifests.map(({ id }) => id), CHART_SPEC_COMPONENT_ID].map((id) => chartHosts.resolveById({ id })),
|
|
42
45
|
] });
|
|
43
46
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { formatErrorForLog } from '@jini-ai/core';
|
|
3
4
|
import { forwardRef, useImperativeHandle, useRef } from 'react';
|
|
4
5
|
import { LexicalComposer } from '@lexical/react/LexicalComposer';
|
|
5
6
|
import { PlainTextPlugin } from '@lexical/react/LexicalPlainTextPlugin';
|
|
@@ -145,7 +146,7 @@ export const RichTextInput = forwardRef(function RichTextInput(props, ref) {
|
|
|
145
146
|
theme: EDITOR_THEME,
|
|
146
147
|
onError(err) {
|
|
147
148
|
if (process.env.NODE_ENV !== 'production') {
|
|
148
|
-
console.error('[rich-text-input]', err);
|
|
149
|
+
console.error('[rich-text-input]', formatErrorForLog({ error: err }));
|
|
149
150
|
}
|
|
150
151
|
},
|
|
151
152
|
// editorState intentionally omitted → empty on first paint (SSR-safe).
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* every call site into "sometimes required, sometimes not" — worse than a small, purpose-built
|
|
34
34
|
* sibling that carries only what a result needs.
|
|
35
35
|
*
|
|
36
|
-
* ## The
|
|
36
|
+
* ## The external link and optional cancellation
|
|
37
37
|
*
|
|
38
38
|
* `openLinkUrl` renders a single button wired to the bridge's existing `openLink` (`ui/open-link`) —
|
|
39
39
|
* no new bridge plumbing: a `<a href>` is dead inside this package's sandboxed `srcdoc` frame (no
|
|
@@ -41,9 +41,13 @@
|
|
|
41
41
|
* all (`bridge.ts`'s own header). The URL is ALSO always rendered as a plain detail row regardless —
|
|
42
42
|
* copyable/selectable text that needs no script to be useful, matching this package's general
|
|
43
43
|
* "the document should say something true even if a caller never runs its script" posture.
|
|
44
|
+
* A partial outcome may also describe external work still waiting on the person. Its optional
|
|
45
|
+
* cancel action answers the caller's existing exchange without confirming an operation or
|
|
46
|
+
* navigating. Ordinary completed outcomes retain their read-only contract.
|
|
44
47
|
*/
|
|
45
48
|
import { type UIResource, type UIResourceUri } from '../resource.js';
|
|
46
49
|
import { type SurfaceDetail } from './document.js';
|
|
50
|
+
import type { ConfirmationToolAction } from './confirmation.js';
|
|
47
51
|
import type { BridgeScriptSpec } from './bridge.js';
|
|
48
52
|
import type { SurfaceTokenName } from './tokens.js';
|
|
49
53
|
export interface SurfaceOutcomeSpec {
|
|
@@ -74,6 +78,8 @@ export interface SurfaceOutcomeSpec {
|
|
|
74
78
|
* Only meaningful alongside `state: 'success'` — a caller should not supply this for a failure. */
|
|
75
79
|
readonly openLinkUrl?: string;
|
|
76
80
|
readonly openLinkLabel?: string;
|
|
81
|
+
/** A pending external action may be skipped through its existing surface exchange. */
|
|
82
|
+
readonly cancel?: ConfirmationToolAction;
|
|
77
83
|
/** Identity reported to the Host in `ui/initialize`. Defaults to a generic one. */
|
|
78
84
|
readonly app?: BridgeScriptSpec;
|
|
79
85
|
readonly lang?: string;
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* every call site into "sometimes required, sometimes not" — worse than a small, purpose-built
|
|
34
34
|
* sibling that carries only what a result needs.
|
|
35
35
|
*
|
|
36
|
-
* ## The
|
|
36
|
+
* ## The external link and optional cancellation
|
|
37
37
|
*
|
|
38
38
|
* `openLinkUrl` renders a single button wired to the bridge's existing `openLink` (`ui/open-link`) —
|
|
39
39
|
* no new bridge plumbing: a `<a href>` is dead inside this package's sandboxed `srcdoc` frame (no
|
|
@@ -41,10 +41,13 @@
|
|
|
41
41
|
* all (`bridge.ts`'s own header). The URL is ALSO always rendered as a plain detail row regardless —
|
|
42
42
|
* copyable/selectable text that needs no script to be useful, matching this package's general
|
|
43
43
|
* "the document should say something true even if a caller never runs its script" posture.
|
|
44
|
+
* A partial outcome may also describe external work still waiting on the person. Its optional
|
|
45
|
+
* cancel action answers the caller's existing exchange without confirming an operation or
|
|
46
|
+
* navigating. Ordinary completed outcomes retain their read-only contract.
|
|
44
47
|
*/
|
|
45
48
|
import { createUIResource } from '../resource.js';
|
|
46
49
|
import { escapeHtml, escapeJsValue } from '../escape.js';
|
|
47
|
-
import { renderActions, renderDetailList, renderSurfaceDocument, renderSurfaceHeader, SURFACE_SCRIPT_PRELUDE, SURFACE_STATUS_ELEMENT_ID, } from './document.js';
|
|
50
|
+
import { DEFAULT_SURFACE_STATUS_TEXT, renderActions, renderDetailList, renderSurfaceDocument, renderSurfaceHeader, SURFACE_SCRIPT_PRELUDE, SURFACE_STATUS_ELEMENT_ID, } from './document.js';
|
|
48
51
|
const DEFAULT_APP = { appName: 'jini-mcp-ui-outcome', appVersion: '1' };
|
|
49
52
|
const DEFAULT_OPEN_LINK_LABEL = 'Open site';
|
|
50
53
|
const OPEN_LINK_ACTION_ID = 'open-link';
|
|
@@ -54,11 +57,45 @@ function statusStateOf(state) {
|
|
|
54
57
|
return 'done';
|
|
55
58
|
return state === 'partial' ? 'partial' : 'failed';
|
|
56
59
|
}
|
|
57
|
-
/**
|
|
60
|
+
/** One action list for the frame and its host mirror. @complexity O(n) in the label length. */
|
|
61
|
+
function outcomeActions(spec) {
|
|
62
|
+
const actions = [];
|
|
63
|
+
if (spec.openLinkUrl !== undefined)
|
|
64
|
+
actions.push({ id: OPEN_LINK_ACTION_ID, label: spec.openLinkLabel ?? DEFAULT_OPEN_LINK_LABEL, variant: spec.state === 'success' ? 'primary' : 'neutral' });
|
|
65
|
+
if (spec.cancel)
|
|
66
|
+
actions.push({ id: 'cancel', label: spec.cancel.label, variant: 'neutral' });
|
|
67
|
+
return actions;
|
|
68
|
+
}
|
|
58
69
|
function renderOpenLinkActions(spec) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
70
|
+
const actions = outcomeActions(spec);
|
|
71
|
+
return actions.length === 0 ? '' : renderActions(actions);
|
|
72
|
+
}
|
|
73
|
+
/** Pending external work keeps its outbound link and answers cancellation through the same bridge.
|
|
74
|
+
* Existing read-only outcomes retain their script and need no exchange. @complexity O(n) rendered bytes. */
|
|
75
|
+
function cancellableOutcomeScript(spec) {
|
|
76
|
+
if (!spec.cancel)
|
|
77
|
+
return outcomeScript(spec.openLinkUrl);
|
|
78
|
+
return `(function () {
|
|
79
|
+
"use strict";
|
|
80
|
+
${SURFACE_SCRIPT_PRELUDE}
|
|
81
|
+
var TEXT = ${escapeJsValue(DEFAULT_SURFACE_STATUS_TEXT)};
|
|
82
|
+
var CANCEL = ${escapeJsValue(spec.cancel)};
|
|
83
|
+
var OPEN_URL = ${escapeJsValue(spec.openLinkUrl ?? null)};
|
|
84
|
+
var locked = false;
|
|
85
|
+
function onClick(event) {
|
|
86
|
+
if (event.isTrusted !== true || locked) return;
|
|
87
|
+
if (event.currentTarget.getAttribute("data-mcpui-action") === "open-link") {
|
|
88
|
+
api.openLink(OPEN_URL);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
locked = true;
|
|
92
|
+
setBusy(true);
|
|
93
|
+
api.callTool(CANCEL.toolName, CANCEL.params).then(function () {
|
|
94
|
+
setStatus(TEXT.dismissed, "dismissed");
|
|
95
|
+
}, function (error) { locked = !reportCallFailure(error); });
|
|
96
|
+
}
|
|
97
|
+
for (var i = 0; i < actionButtons.length; i++) actionButtons[i].addEventListener("click", onClick);
|
|
98
|
+
}());`;
|
|
62
99
|
}
|
|
63
100
|
/** The inline script: wires the open-link button, or nothing at all. @complexity O(n) in the URL length. */
|
|
64
101
|
function outcomeScript(openLinkUrl) {
|
|
@@ -99,7 +136,7 @@ export function renderOutcomeDocument(spec) {
|
|
|
99
136
|
return renderSurfaceDocument({
|
|
100
137
|
title: spec.title,
|
|
101
138
|
bodyHtml,
|
|
102
|
-
script:
|
|
139
|
+
script: cancellableOutcomeScript(spec),
|
|
103
140
|
app: spec.app ?? DEFAULT_APP,
|
|
104
141
|
...(spec.lang === undefined ? {} : { lang: spec.lang }),
|
|
105
142
|
...(spec.tokens === undefined ? {} : { tokens: spec.tokens }),
|
|
@@ -120,10 +157,12 @@ export function buildOutcomeSurface(spec) {
|
|
|
120
157
|
uri: spec.uri,
|
|
121
158
|
htmlString: renderOutcomeDocument(spec),
|
|
122
159
|
...(spec.preferredFrameSize === undefined ? {} : { preferredFrameSize: spec.preferredFrameSize }),
|
|
160
|
+
...(spec.cancel ? { actionPlan: { title: spec.title, actions: outcomeActions(spec) } } : {}),
|
|
123
161
|
// No `actionPlan`: unlike a confirmation, this surface has nothing PENDING for
|
|
124
162
|
// `page.find_elements`'s parent-DOM mirror to describe (`McpUiSurfaceCard`'s own
|
|
125
163
|
// `readActionPlan`/`PendingSurfaceMirror` — that mirror exists for a confirmation a human has not
|
|
126
|
-
// yet answered; a result has already been answered).
|
|
164
|
+
// yet answered; a result has already been answered). A cancellable external wait above is
|
|
165
|
+
// pending, so its mirror uses the same actions its frame renders, with no routing params.
|
|
127
166
|
});
|
|
128
167
|
}
|
|
129
168
|
//# sourceMappingURL=outcome.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { formatErrorForLog } from '@jini-ai/core';
|
|
1
2
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
3
|
import { EXPORTED_IMAGE_MIME_TYPE, SAVED_VISIBLE_MS } from '../../constants.js';
|
|
3
4
|
import { defaultSketchEditorDependencies } from '../../dependencies.js';
|
|
@@ -85,7 +86,7 @@ export function useSketchSaveWorkflow(params) {
|
|
|
85
86
|
});
|
|
86
87
|
}
|
|
87
88
|
catch (err) {
|
|
88
|
-
console.warn('[SketchEditor] export image failed', err);
|
|
89
|
+
console.warn('[SketchEditor] export image failed', formatErrorForLog({ error: err }));
|
|
89
90
|
setToast({ message: tRef.current('Could not export image'), tone: 'error' });
|
|
90
91
|
}
|
|
91
92
|
finally {
|
|
@@ -73,6 +73,12 @@ export function useTooltipLayer() {
|
|
|
73
73
|
const rafRef = useRef(null);
|
|
74
74
|
const lastInputRef = useRef('pointer');
|
|
75
75
|
const suppressedTitleRef = useRef(null);
|
|
76
|
+
// Touch has no hover, and a tap's own pointerdown/click would hide the tip
|
|
77
|
+
// the instant it appeared — so a touch tap on a trigger TOGGLES the tip
|
|
78
|
+
// instead. `touchTapRef` remembers the trigger under the touch pointerdown
|
|
79
|
+
// (and whether its tip was already open) until the matching click.
|
|
80
|
+
const touchTapRef = useRef(null);
|
|
81
|
+
const openTargetRef = useRef(null);
|
|
76
82
|
const [state, setState] = useState(null);
|
|
77
83
|
const restoreNativeTitle = useCallback(() => {
|
|
78
84
|
const suppressed = suppressedTitleRef.current;
|
|
@@ -170,6 +176,7 @@ export function useTooltipLayer() {
|
|
|
170
176
|
});
|
|
171
177
|
}, [updatePosition]);
|
|
172
178
|
useLayoutEffect(() => {
|
|
179
|
+
openTargetRef.current = state?.target ?? null;
|
|
173
180
|
if (!state)
|
|
174
181
|
return;
|
|
175
182
|
updatePosition();
|
|
@@ -209,11 +216,15 @@ export function useTooltipLayer() {
|
|
|
209
216
|
};
|
|
210
217
|
const onPointerOver = (event) => {
|
|
211
218
|
lastInputRef.current = 'pointer';
|
|
219
|
+
if (event.pointerType === 'touch')
|
|
220
|
+
return;
|
|
212
221
|
const target = readTooltipTarget(event.target);
|
|
213
222
|
if (target)
|
|
214
223
|
showTooltip(target);
|
|
215
224
|
};
|
|
216
225
|
const onTargetExit = (event) => {
|
|
226
|
+
if ('pointerType' in event && event.pointerType === 'touch')
|
|
227
|
+
return;
|
|
217
228
|
const target = readTooltipTarget(event.target);
|
|
218
229
|
if (!target)
|
|
219
230
|
return;
|
|
@@ -224,14 +235,28 @@ export function useTooltipLayer() {
|
|
|
224
235
|
};
|
|
225
236
|
const onPointerDown = (event) => {
|
|
226
237
|
lastInputRef.current = 'pointer';
|
|
227
|
-
|
|
238
|
+
const target = readTooltipTarget(event.target);
|
|
239
|
+
touchTapRef.current = null;
|
|
240
|
+
if (event.pointerType === 'touch' && target) {
|
|
241
|
+
touchTapRef.current = { target, wasOpen: openTargetRef.current === target };
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
hideTooltipForActivation(target);
|
|
228
245
|
};
|
|
229
246
|
const onPointerCancel = () => {
|
|
230
247
|
lastInputRef.current = 'pointer';
|
|
248
|
+
touchTapRef.current = null;
|
|
231
249
|
hideTooltip();
|
|
232
250
|
};
|
|
233
251
|
const onClick = (event) => {
|
|
234
|
-
|
|
252
|
+
const target = readTooltipTarget(event.target);
|
|
253
|
+
const touchTap = touchTapRef.current;
|
|
254
|
+
touchTapRef.current = null;
|
|
255
|
+
if (target && touchTap?.target === target && !touchTap.wasOpen) {
|
|
256
|
+
showTooltip(target);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
hideTooltipForActivation(target);
|
|
235
260
|
};
|
|
236
261
|
const onFocusIn = (event) => {
|
|
237
262
|
const target = readTooltipTarget(event.target);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jini-ai/ui",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.19",
|
|
4
4
|
"description": "Generic, product-neutral React UI primitives and feature domains. Framework-free types, decision rules, catalogs, and host port contracts live behind ./core (no React, no DOM). The Excalidraw and Lexical editors live behind ./sketch-editor and ./lexical-rich-text-editor; the GrapesJS-backed inline HTML editor lives behind ./html-editor.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -263,19 +263,19 @@
|
|
|
263
263
|
"shiki": "^1.24.4",
|
|
264
264
|
"tailwind-merge": "^2.6.0",
|
|
265
265
|
"zod": "^3.25.76",
|
|
266
|
-
"@jini-ai/
|
|
267
|
-
"@jini-ai/
|
|
268
|
-
"@jini-ai/
|
|
269
|
-
"@jini-ai/
|
|
270
|
-
"@jini-ai/
|
|
266
|
+
"@jini-ai/integrations": "^0.6.19",
|
|
267
|
+
"@jini-ai/agent-runtime": "^0.6.19",
|
|
268
|
+
"@jini-ai/agentic": "^0.6.19",
|
|
269
|
+
"@jini-ai/core": "^0.6.19",
|
|
270
|
+
"@jini-ai/platform": "^0.6.19"
|
|
271
271
|
},
|
|
272
272
|
"dependencies": {
|
|
273
273
|
"micromark": "^4.0.0",
|
|
274
274
|
"micromark-extension-gfm": "^3.0.0",
|
|
275
|
-
"@jini-ai/ui-kit": "^0.6.
|
|
276
|
-
"@jini-ai/core": "^0.6.
|
|
277
|
-
"@jini-ai/
|
|
278
|
-
"@jini-ai/
|
|
275
|
+
"@jini-ai/ui-kit": "^0.6.19",
|
|
276
|
+
"@jini-ai/core": "^0.6.19",
|
|
277
|
+
"@jini-ai/platform": "^0.6.19",
|
|
278
|
+
"@jini-ai/agentic": "^0.6.19"
|
|
279
279
|
},
|
|
280
280
|
"peerDependencies": {
|
|
281
281
|
"@tanstack/react-query": "^5.0.0",
|