@rimori/client 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +13 -0
  2. package/dist/components/MarkdownEditor.js +6 -4
  3. package/dist/components/PluginController.d.ts +21 -0
  4. package/dist/components/PluginController.js +116 -0
  5. package/dist/components/ai/Assistant.js +1 -1
  6. package/dist/components/ai/Avatar.d.ts +5 -3
  7. package/dist/components/ai/Avatar.js +14 -6
  8. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +2 -1
  9. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +35 -14
  10. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +1 -0
  11. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +3 -0
  12. package/dist/components/ai/EmbeddedAssistent/TTS/Player.d.ts +2 -0
  13. package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +5 -0
  14. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +3 -0
  15. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +41 -5
  16. package/dist/components/ai/utils.d.ts +1 -1
  17. package/dist/components.d.ts +1 -0
  18. package/dist/components.js +1 -0
  19. package/dist/controller/AIController.js +2 -1
  20. package/dist/controller/SettingsController.d.ts +18 -10
  21. package/dist/controller/SettingsController.js +28 -31
  22. package/dist/controller/SharedContentController.d.ts +58 -11
  23. package/dist/controller/SharedContentController.js +161 -26
  24. package/dist/controller/SidePluginController.d.ts +1 -12
  25. package/dist/core/components/ContextMenu.d.ts +10 -0
  26. package/dist/core/components/ContextMenu.js +93 -0
  27. package/dist/core.d.ts +2 -0
  28. package/dist/core.js +2 -0
  29. package/dist/hooks/UseChatHook.d.ts +1 -1
  30. package/dist/plugin/AccomplishmentHandler.d.ts +38 -0
  31. package/dist/plugin/AccomplishmentHandler.js +108 -0
  32. package/dist/plugin/ContextMenu.d.ts +17 -0
  33. package/dist/plugin/ContextMenu.js +45 -0
  34. package/dist/plugin/PluginController.js +9 -4
  35. package/dist/plugin/RimoriClient.d.ts +92 -65
  36. package/dist/plugin/RimoriClient.js +105 -75
  37. package/dist/plugin/ThemeSetter.js +4 -4
  38. package/dist/plugin/fromRimori/EventBus.d.ts +6 -3
  39. package/dist/plugin/fromRimori/EventBus.js +15 -9
  40. package/dist/plugin/fromRimori/PluginTypes.d.ts +51 -0
  41. package/dist/plugin/fromRimori/PluginTypes.js +1 -0
  42. package/dist/providers/PluginController.d.ts +21 -0
  43. package/dist/providers/PluginController.js +116 -0
  44. package/dist/providers/PluginProvider.js +26 -73
  45. package/dist/types/Actions.d.ts +4 -0
  46. package/dist/types/Actions.js +1 -0
  47. package/dist/utils/Language.d.ts +66 -0
  48. package/dist/utils/Language.js +67 -0
  49. package/dist/utils/difficultyConverter.d.ts +1 -0
  50. package/dist/utils/difficultyConverter.js +3 -0
  51. package/dist/worker/WorkerSetup.js +5 -4
  52. package/package.json +3 -3
  53. package/src/components/MarkdownEditor.tsx +78 -76
  54. package/src/components/ai/Assistant.tsx +1 -1
  55. package/src/components/ai/Avatar.tsx +65 -48
  56. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +81 -58
  57. package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +4 -0
  58. package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +6 -0
  59. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +51 -8
  60. package/src/components/ai/utils.ts +1 -1
  61. package/src/components.ts +2 -1
  62. package/src/controller/AIController.ts +2 -1
  63. package/src/controller/SettingsController.ts +80 -75
  64. package/src/controller/SharedContentController.ts +214 -53
  65. package/src/controller/SidePluginController.ts +1 -13
  66. package/src/core/components/ContextMenu.tsx +123 -0
  67. package/src/core.ts +3 -1
  68. package/src/hooks/UseChatHook.ts +17 -17
  69. package/src/plugin/AccomplishmentHandler.ts +165 -0
  70. package/src/plugin/PluginController.ts +107 -100
  71. package/src/plugin/RimoriClient.ts +267 -250
  72. package/src/plugin/ThemeSetter.ts +4 -5
  73. package/src/plugin/fromRimori/EventBus.ts +23 -12
  74. package/src/plugin/fromRimori/PluginTypes.ts +67 -0
  75. package/src/providers/PluginProvider.tsx +63 -110
  76. package/src/types/Actions.ts +6 -0
  77. package/src/utils/Language.ts +70 -0
  78. package/src/utils/difficultyConverter.ts +4 -0
  79. package/src/worker/WorkerSetup.ts +5 -4
  80. package/dist/components/avatar/Assistant.d.ts +0 -9
  81. package/dist/components/avatar/Assistant.js +0 -59
  82. package/dist/components/avatar/Avatar.d.ts +0 -12
  83. package/dist/components/avatar/Avatar.js +0 -42
  84. package/dist/components/avatar/EmbeddedAssistent/AudioInputField.d.ts +0 -7
  85. package/dist/components/avatar/EmbeddedAssistent/AudioInputField.js +0 -38
  86. package/dist/components/avatar/EmbeddedAssistent/CircleAudioAvatar.d.ts +0 -7
  87. package/dist/components/avatar/EmbeddedAssistent/CircleAudioAvatar.js +0 -59
  88. package/dist/components/avatar/EmbeddedAssistent/TTS/MessageSender.d.ts +0 -19
  89. package/dist/components/avatar/EmbeddedAssistent/TTS/MessageSender.js +0 -84
  90. package/dist/components/avatar/EmbeddedAssistent/TTS/Player.d.ts +0 -25
  91. package/dist/components/avatar/EmbeddedAssistent/TTS/Player.js +0 -180
  92. package/dist/components/avatar/EmbeddedAssistent/VoiceRecoder.d.ts +0 -7
  93. package/dist/components/avatar/EmbeddedAssistent/VoiceRecoder.js +0 -45
  94. package/dist/components/avatar/utils.d.ts +0 -6
  95. package/dist/components/avatar/utils.js +0 -14
@@ -1,33 +1,34 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { createContext, useContext, useEffect, useState } from 'react';
3
3
  import { PluginController } from '../plugin/PluginController';
4
4
  import { EventBusHandler } from '../plugin/fromRimori/EventBus';
5
- EventBusHandler.getInstance("Plugin EventBus");
5
+ import ContextMenu from '../core/components/ContextMenu';
6
6
  const PluginContext = createContext(null);
7
7
  export const PluginProvider = ({ children, pluginId }) => {
8
8
  const [plugin, setPlugin] = useState(null);
9
- const [contextMenuOnSelect, setContextMenuOnTextSelection] = useState(false);
10
- //route change
9
+ initEventBus(pluginId);
11
10
  useEffect(() => {
12
- let lastHash = window.location.hash;
13
- setInterval(() => {
14
- if (lastHash !== window.location.hash) {
15
- lastHash = window.location.hash;
16
- console.log('url changed:', lastHash);
17
- plugin === null || plugin === void 0 ? void 0 : plugin.event.emit('session.triggerUrlChange', window.location.hash);
18
- }
19
- }, 100);
20
11
  PluginController.getInstance(pluginId).then(setPlugin);
21
- }, []);
22
- //check if context menu opens on text selection
12
+ }, [pluginId]);
13
+ //route change
23
14
  useEffect(() => {
24
15
  if (!plugin)
25
16
  return;
26
- plugin.plugin.getUserInfo().then((userInfo) => {
27
- setContextMenuOnTextSelection(userInfo.contextMenuOnSelect);
28
- }).catch(error => {
29
- console.error('Error fetching settings:', error);
30
- });
17
+ const url = new URL(window.location.href);
18
+ //sidebar pages should not report url changes
19
+ if (url.searchParams.get("applicationMode") === "sidebar")
20
+ return;
21
+ let lastHash = url.hash;
22
+ const emitUrlChange = (url) => plugin.event.emit('session.triggerUrlChange', { url });
23
+ const interval = setInterval(() => {
24
+ if (lastHash === window.location.hash)
25
+ return;
26
+ lastHash = window.location.hash;
27
+ // console.log('url changed:', lastHash);
28
+ emitUrlChange(lastHash);
29
+ }, 1000);
30
+ emitUrlChange(lastHash);
31
+ return () => clearInterval(interval);
31
32
  }, [plugin]);
32
33
  //detect page height change
33
34
  useEffect(() => {
@@ -37,63 +38,10 @@ export const PluginProvider = ({ children, pluginId }) => {
37
38
  handleResize();
38
39
  return () => body.removeEventListener('resize', handleResize);
39
40
  }, [plugin]);
40
- //context menu
41
- useEffect(() => {
42
- let lastMouseX = 0;
43
- let lastMouseY = 0;
44
- let isSelecting = false;
45
- // Track mouse position
46
- const handleMouseMove = (e) => {
47
- lastMouseX = e.clientX;
48
- lastMouseY = e.clientY;
49
- };
50
- const handleContextMenu = (e) => {
51
- var _a;
52
- const selection = (_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.toString().trim();
53
- if (selection) {
54
- e.preventDefault();
55
- // console.log('context menu handled', selection);
56
- plugin === null || plugin === void 0 ? void 0 : plugin.event.emit('global.contextMenu.trigger', { text: selection, x: e.clientX, y: e.clientY, open: true });
57
- }
58
- };
59
- const handleSelectionChange = () => {
60
- var _a;
61
- // if (triggerOnTextSelection) {
62
- const selection = (_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.toString().trim();
63
- const open = !!selection && isSelecting;
64
- // console.log('Selection change, contextMenuOnSelect:', contextMenuOnSelect);
65
- plugin === null || plugin === void 0 ? void 0 : plugin.event.emit('global.contextMenu.trigger', { text: selection, x: lastMouseX, y: lastMouseY, open });
66
- // }
67
- };
68
- const handleMouseUpDown = (e) => {
69
- if (e.type === 'mousedown') {
70
- isSelecting = false;
71
- }
72
- else if (e.type === 'mouseup') {
73
- isSelecting = true;
74
- // console.log('mouseup, contextMenuOnSelect:', contextMenuOnSelect);
75
- if (contextMenuOnSelect) {
76
- handleSelectionChange();
77
- }
78
- }
79
- };
80
- document.addEventListener('contextmenu', handleContextMenu);
81
- document.addEventListener('selectionchange', handleSelectionChange);
82
- document.addEventListener("mousemove", handleMouseMove);
83
- document.addEventListener('mousedown', handleMouseUpDown);
84
- document.addEventListener('mouseup', handleMouseUpDown);
85
- return () => {
86
- document.removeEventListener("mousemove", handleMouseMove);
87
- document.removeEventListener('contextmenu', handleContextMenu);
88
- document.removeEventListener('selectionchange', handleSelectionChange);
89
- document.removeEventListener('mousedown', handleMouseUpDown);
90
- document.removeEventListener('mouseup', handleMouseUpDown);
91
- };
92
- }, [plugin, contextMenuOnSelect]);
93
41
  if (!plugin) {
94
42
  return "";
95
43
  }
96
- return (_jsx(PluginContext.Provider, { value: plugin, children: children }));
44
+ return (_jsxs(PluginContext.Provider, { value: plugin, children: [_jsx(ContextMenu, { client: plugin }), children] }));
97
45
  };
98
46
  export const usePlugin = () => {
99
47
  const context = useContext(PluginContext);
@@ -102,3 +50,8 @@ export const usePlugin = () => {
102
50
  }
103
51
  return context;
104
52
  };
53
+ function initEventBus(pluginId) {
54
+ const url = new URL(window.location.href);
55
+ const isSidebar = url.searchParams.get("applicationMode") === "sidebar";
56
+ EventBusHandler.getInstance("Plugin EventBus " + pluginId + " " + (isSidebar ? "sidebar" : "main"));
57
+ }
@@ -0,0 +1,4 @@
1
+ export type MainPanelAction = {
2
+ pluginId: string;
3
+ actionKey: string;
4
+ } & Record<string, string>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,66 @@
1
+ export declare const languageKeys: {
2
+ readonly sq: "albanian";
3
+ readonly ar: "arabic";
4
+ readonly hy: "armenian";
5
+ readonly az: "azerbaijani";
6
+ readonly bn: "bengali";
7
+ readonly bs: "bosnian";
8
+ readonly bg: "bulgarian";
9
+ readonly ca: "catalan";
10
+ readonly zh: "chinese";
11
+ readonly hr: "croatian";
12
+ readonly cs: "czech";
13
+ readonly da: "danish";
14
+ readonly nl: "dutch";
15
+ readonly en: "english";
16
+ readonly et: "estonian";
17
+ readonly fi: "finnish";
18
+ readonly fr: "french";
19
+ readonly gl: "galician";
20
+ readonly de: "german";
21
+ readonly el: "greek";
22
+ readonly he: "hebrew";
23
+ readonly hi: "hindi";
24
+ readonly hu: "hungarian";
25
+ readonly is: "icelandic";
26
+ readonly id: "indonesian";
27
+ readonly it: "italian";
28
+ readonly ja: "japanese";
29
+ readonly kn: "kannada";
30
+ readonly kk: "kazakh";
31
+ readonly ko: "korean";
32
+ readonly lv: "latvian";
33
+ readonly lt: "lithuanian";
34
+ readonly mk: "macedonian";
35
+ readonly ms: "malay";
36
+ readonly mr: "marathi";
37
+ readonly mi: "maori";
38
+ readonly ne: "nepali";
39
+ readonly no: "norwegian";
40
+ readonly fa: "persian";
41
+ readonly pl: "polish";
42
+ readonly pt: "portuguese";
43
+ readonly ro: "romanian";
44
+ readonly ru: "russian";
45
+ readonly sr: "serbian";
46
+ readonly sk: "slovak";
47
+ readonly sl: "slovenian";
48
+ readonly es: "spanish";
49
+ readonly sw: "swahili";
50
+ readonly sv: "swedish";
51
+ readonly tl: "filipino";
52
+ readonly ta: "tamil";
53
+ readonly th: "thai";
54
+ readonly tr: "turkish";
55
+ readonly uk: "ukrainian";
56
+ readonly ur: "urdu";
57
+ readonly vi: "vietnamese";
58
+ readonly cy: "welsh";
59
+ };
60
+ export type Language = keyof typeof languageKeys;
61
+ /**
62
+ * Get the language name from the language code
63
+ * @param languageCode The code of the language
64
+ * @returns The language name
65
+ */
66
+ export declare function getLanguageName(languageCode: Language): string;
@@ -0,0 +1,67 @@
1
+ export const languageKeys = {
2
+ sq: "albanian",
3
+ ar: "arabic",
4
+ hy: "armenian",
5
+ az: "azerbaijani",
6
+ bn: "bengali",
7
+ bs: "bosnian",
8
+ bg: "bulgarian",
9
+ ca: "catalan",
10
+ zh: "chinese",
11
+ hr: "croatian",
12
+ cs: "czech",
13
+ da: "danish",
14
+ nl: "dutch",
15
+ en: "english",
16
+ et: "estonian",
17
+ fi: "finnish",
18
+ fr: "french",
19
+ gl: "galician",
20
+ de: "german",
21
+ el: "greek",
22
+ he: "hebrew",
23
+ hi: "hindi",
24
+ hu: "hungarian",
25
+ is: "icelandic",
26
+ id: "indonesian",
27
+ it: "italian",
28
+ ja: "japanese",
29
+ kn: "kannada",
30
+ kk: "kazakh",
31
+ ko: "korean",
32
+ lv: "latvian",
33
+ lt: "lithuanian",
34
+ mk: "macedonian",
35
+ ms: "malay",
36
+ mr: "marathi",
37
+ mi: "maori",
38
+ ne: "nepali",
39
+ no: "norwegian",
40
+ fa: "persian",
41
+ pl: "polish",
42
+ pt: "portuguese",
43
+ ro: "romanian",
44
+ ru: "russian",
45
+ sr: "serbian",
46
+ sk: "slovak",
47
+ sl: "slovenian",
48
+ es: "spanish",
49
+ sw: "swahili",
50
+ sv: "swedish",
51
+ tl: "filipino",
52
+ ta: "tamil",
53
+ th: "thai",
54
+ tr: "turkish",
55
+ uk: "ukrainian",
56
+ ur: "urdu",
57
+ vi: "vietnamese",
58
+ cy: "welsh"
59
+ };
60
+ /**
61
+ * Get the language name from the language code
62
+ * @param languageCode The code of the language
63
+ * @returns The language name
64
+ */
65
+ export function getLanguageName(languageCode) {
66
+ return languageKeys[languageCode];
67
+ }
@@ -1,3 +1,4 @@
1
1
  export type LanguageLevel = "Pre-A1" | "A1" | "A2" | "B1" | "B2" | "C1" | "C2" | "Post-C2";
2
2
  export declare function getDifficultyLevel(difficulty: LanguageLevel): number;
3
3
  export declare function getDifficultyLabel(difficulty: number): LanguageLevel;
4
+ export declare function getNeighborDifficultyLevel(difficulty: LanguageLevel, difficultyAdjustment: number): LanguageLevel;
@@ -5,3 +5,6 @@ export function getDifficultyLevel(difficulty) {
5
5
  export function getDifficultyLabel(difficulty) {
6
6
  return codes[difficulty];
7
7
  }
8
+ export function getNeighborDifficultyLevel(difficulty, difficultyAdjustment) {
9
+ return getDifficultyLabel(getDifficultyLevel(difficulty) + difficultyAdjustment);
10
+ }
@@ -19,12 +19,13 @@ let debugEnabled = false;
19
19
  export function setupWorker(init) {
20
20
  // Mock of the window object for the worker context to be able to use the PluginController.
21
21
  const mockWindow = {
22
+ isWorker: true,
22
23
  location: { search: '?secret=123' },
23
24
  parent: {
24
25
  postMessage: (message) => {
25
26
  message.event.sender = "worker." + message.event.sender;
26
27
  checkDebugMode(message.event);
27
- logIfDebug('[Worker] sending event to Rimori', message.event);
28
+ logIfDebug('sending event to Rimori', message.event);
28
29
  self.postMessage(message);
29
30
  }
30
31
  },
@@ -42,16 +43,16 @@ export function setupWorker(init) {
42
43
  // Handle init message from Rimori.
43
44
  self.onmessage = (response) => __awaiter(this, void 0, void 0, function* () {
44
45
  checkDebugMode(response.data);
45
- logIfDebug('[Worker] message received', response.data);
46
+ logIfDebug('Message received', response.data);
46
47
  const event = response.data;
47
48
  if (event.topic === 'global.worker.requestInit') {
48
49
  if (!controller) {
49
50
  mockWindow.APP_CONFIG.SUPABASE_URL = event.data.supabaseUrl;
50
51
  mockWindow.APP_CONFIG.SUPABASE_ANON_KEY = event.data.supabaseAnonKey;
51
52
  controller = yield PluginController.getInstance(event.data.pluginId);
52
- logIfDebug('[Worker] Worker initialized.');
53
+ logIfDebug('Worker initialized.');
53
54
  yield init(controller);
54
- logIfDebug('[Worker] Plugin listeners initialized.');
55
+ logIfDebug('Plugin listeners initialized.');
55
56
  }
56
57
  const initEvent = {
57
58
  timestamp: new Date().toISOString(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rimori/client",
3
- "version": "1.0.4",
3
+ "version": "1.1.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "exports": {
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "scripts": {
21
21
  "build": "tsc && sass src/style.scss:dist/style.css",
22
- "dev": "tsc -w",
22
+ "dev": "tsc -w --preserveWatchOutput",
23
23
  "css-dev": "sass --watch src/style.scss:dist/style.css"
24
24
  },
25
25
  "peerDependencies": {
@@ -30,8 +30,8 @@
30
30
  "@supabase/supabase-js": "^2.48.1",
31
31
  "@tiptap/react": "2.10.3",
32
32
  "@tiptap/starter-kit": "2.10.3",
33
- "uuid": "11.1.0",
34
33
  "react-icons": "^5.4.0",
34
+ "react-markdown": "^10.1.0",
35
35
  "tiptap-markdown": "^0.8.10",
36
36
  "typescript": "^5.7.2"
37
37
  },
@@ -11,101 +11,103 @@ import { FaBold, FaCode, FaItalic, FaParagraph, FaStrikethrough } from "react-ic
11
11
  // This inplementation is rooted in the Tiptap editor basic example https://codesandbox.io/p/devbox/editor-9x9dkd
12
12
 
13
13
  interface EditorButtonProps {
14
- action: string;
15
- isActive?: boolean;
16
- label: string | React.ReactNode;
17
- disabled?: boolean;
14
+ action: string;
15
+ isActive?: boolean;
16
+ label: string | React.ReactNode;
17
+ disabled?: boolean;
18
18
  }
19
19
 
20
20
  const EditorButton = ({ action, isActive, label, disabled }: EditorButtonProps) => {
21
- const { editor } = useCurrentEditor() as any;
21
+ const { editor } = useCurrentEditor() as any;
22
22
 
23
- if (!editor) {
24
- return null;
25
- }
26
-
27
- if (action.includes("heading")) {
28
- const level = parseInt(action[action.length - 1]);
29
- return (
30
- <button
31
- onClick={() => editor.chain().focus().toggleHeading({ level: level }).run()}
32
- className={`pl-2 ${isActive ? "is-active" : ""}`}
33
- >
34
- {label}
35
- </button>
36
- );
37
- }
23
+ if (!editor) {
24
+ return null;
25
+ }
38
26
 
27
+ if (action.includes("heading")) {
28
+ const level = parseInt(action[action.length - 1]);
39
29
  return (
40
- <button
41
- onClick={() => editor.chain().focus()[action]().run()}
42
- disabled={disabled ? !editor.can().chain().focus()[action]().run() : false}
43
- className={`pl-2 ${isActive ? "is-active" : ""}`}
44
- >
45
- {label}
46
- </button>
30
+ <button
31
+ onClick={() => editor.chain().focus().toggleHeading({ level: level }).run()}
32
+ className={`pl-2 ${isActive ? "is-active" : ""}`}
33
+ >
34
+ {label}
35
+ </button>
47
36
  );
37
+ }
38
+
39
+ return (
40
+ <button
41
+ onClick={() => editor.chain().focus()[action]().run()}
42
+ disabled={disabled ? !editor.can().chain().focus()[action]().run() : false}
43
+ className={`pl-2 ${isActive ? "is-active" : ""}`}
44
+ >
45
+ {label}
46
+ </button>
47
+ );
48
48
  };
49
49
 
50
50
  const MenuBar = () => {
51
- const { editor } = useCurrentEditor();
51
+ const { editor } = useCurrentEditor();
52
52
 
53
- if (!editor) {
54
- return null;
55
- }
53
+ if (!editor) {
54
+ return null;
55
+ }
56
56
 
57
- return (
58
- <div className="bg-gray-400 dark:bg-gray-800 dark:text-white text-lg flex flex-row flex-wrap items-center p-1">
59
- <EditorButton action="toggleBold" isActive={editor.isActive("bold")} label={<FaBold />} disabled />
60
- <EditorButton action="toggleItalic" isActive={editor.isActive("italic")} label={<FaItalic />} disabled />
61
- <EditorButton action="toggleStrike" isActive={editor.isActive("strike")} label={<FaStrikethrough />} disabled />
62
- <EditorButton action="toggleCode" isActive={editor.isActive("code")} label={<FaCode />} disabled />
63
- <EditorButton action="setParagraph" isActive={editor.isActive("paragraph")} label={<FaParagraph />} />
64
- <EditorButton action='setHeading1' isActive={editor.isActive("heading", { level: 1 })} label={<LuHeading1 size={"24px"} />} />
65
- <EditorButton action='setHeading2' isActive={editor.isActive("heading", { level: 2 })} label={<LuHeading2 size={"24px"} />} />
66
- <EditorButton action='setHeading3' isActive={editor.isActive("heading", { level: 3 })} label={<LuHeading3 size={"24px"} />} />
67
- <EditorButton action="toggleBulletList" isActive={editor.isActive("bulletList")} label={<AiOutlineUnorderedList size={"24px"} />} />
68
- <EditorButton action="toggleOrderedList" isActive={editor.isActive("orderedList")} label={<GoListOrdered size={"24px"} />} />
69
- <EditorButton action="toggleCodeBlock" isActive={editor.isActive("codeBlock")} label={<PiCodeBlock size={"24px"} />} />
70
- <EditorButton action="toggleBlockquote" isActive={editor.isActive("blockquote")} label={<TbBlockquote size={"24px"} />} />
71
- </div>
72
- );
57
+ return (
58
+ <div className="bg-gray-400 dark:bg-gray-800 dark:text-white text-lg flex flex-row flex-wrap items-center p-1">
59
+ <EditorButton action="toggleBold" isActive={editor.isActive("bold")} label={<FaBold />} disabled />
60
+ <EditorButton action="toggleItalic" isActive={editor.isActive("italic")} label={<FaItalic />} disabled />
61
+ <EditorButton action="toggleStrike" isActive={editor.isActive("strike")} label={<FaStrikethrough />} disabled />
62
+ <EditorButton action="toggleCode" isActive={editor.isActive("code")} label={<FaCode />} disabled />
63
+ <EditorButton action="setParagraph" isActive={editor.isActive("paragraph")} label={<FaParagraph />} />
64
+ <EditorButton action='setHeading1' isActive={editor.isActive("heading", { level: 1 })} label={<LuHeading1 size={"24px"} />} />
65
+ <EditorButton action='setHeading2' isActive={editor.isActive("heading", { level: 2 })} label={<LuHeading2 size={"24px"} />} />
66
+ <EditorButton action='setHeading3' isActive={editor.isActive("heading", { level: 3 })} label={<LuHeading3 size={"24px"} />} />
67
+ <EditorButton action="toggleBulletList" isActive={editor.isActive("bulletList")} label={<AiOutlineUnorderedList size={"24px"} />} />
68
+ <EditorButton action="toggleOrderedList" isActive={editor.isActive("orderedList")} label={<GoListOrdered size={"24px"} />} />
69
+ <EditorButton action="toggleCodeBlock" isActive={editor.isActive("codeBlock")} label={<PiCodeBlock size={"24px"} />} />
70
+ <EditorButton action="toggleBlockquote" isActive={editor.isActive("blockquote")} label={<TbBlockquote size={"24px"} />} />
71
+ </div>
72
+ );
73
73
  };
74
74
 
75
75
  const extensions = [
76
- StarterKit.configure({
77
- bulletList: {
78
- keepMarks: true,
79
- keepAttributes: false,
80
- },
81
- orderedList: {
82
- keepMarks: true,
83
- keepAttributes: false,
84
- },
85
- }),
86
- Markdown,
76
+ StarterKit.configure({
77
+ bulletList: {
78
+ HTMLAttributes: {
79
+ class: "list-disc list-inside dark:text-white p-1 mt-1 [&_li]:mb-1 [&_p]:inline m-0",
80
+ },
81
+ },
82
+ orderedList: {
83
+ HTMLAttributes: {
84
+ className: "list-decimal list-inside dark:text-white p-1 mt-1 [&_li]:mb-1 [&_p]:inline m-0",
85
+ },
86
+ },
87
+ }),
88
+ Markdown,
87
89
  ];
88
90
 
89
91
  interface Props {
90
- content?: string;
91
- editable: boolean;
92
- className?: string;
93
- onUpdate?: (content: string) => void;
92
+ content?: string;
93
+ editable: boolean;
94
+ className?: string;
95
+ onUpdate?: (content: string) => void;
94
96
  }
95
97
 
96
98
  export const MarkdownEditor = (props: Props) => {
97
- return (
98
- <div className={"text-md border border-gray-800 overflow-hidden " + props.className} style={{ borderWidth: props.editable ? 1 : 0 }}>
99
- <EditorProvider
100
- key={(props.editable ? "editable" : "readonly") + props.content}
101
- slotBefore={props.editable ? <MenuBar /> : null}
102
- extensions={extensions}
103
- content={props.content}
104
- editable={props.editable}
105
- onUpdate={(e) => {
106
- props.onUpdate && props.onUpdate(e.editor.storage.markdown.getMarkdown());
107
- }}
108
- ></EditorProvider>
109
- </div>
110
- );
99
+ return (
100
+ <div className={"text-md border border-gray-800 overflow-hidden " + props.className} style={{ borderWidth: props.editable ? 1 : 0 }}>
101
+ <EditorProvider
102
+ key={(props.editable ? "editable" : "readonly") + props.content}
103
+ slotBefore={props.editable ? <MenuBar /> : null}
104
+ extensions={extensions}
105
+ content={props.content}
106
+ editable={props.editable}
107
+ onUpdate={(e) => {
108
+ props.onUpdate && props.onUpdate(e.editor.storage.markdown.getMarkdown());
109
+ }}
110
+ ></EditorProvider>
111
+ </div>
112
+ );
111
113
  };
@@ -23,7 +23,7 @@ export function AssistantChat({ avatarImageUrl, voiceId, onComplete, autoStartCo
23
23
  const lastAssistantMessage = [...messages].filter((m) => m.role === 'assistant').pop()?.content;
24
24
 
25
25
  useEffect(() => {
26
- sender.setOnLoudnessChange((value: number) => event.emit('self.avatar.triggerLoudness', value));
26
+ sender.setOnLoudnessChange((value: number) => event.emit('self.avatar.triggerLoudness', { loudness: value }));
27
27
 
28
28
  if (!autoStartConversation) {
29
29
  return;