@rimori/client 1.4.10 → 2.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 (136) hide show
  1. package/README.md +140 -1171
  2. package/dist/{core/controller → controller}/AIController.d.ts +1 -1
  3. package/dist/{core/controller → controller}/AIController.js +2 -2
  4. package/dist/{plugin/AccomplishmentHandler.d.ts → controller/AccomplishmentController.d.ts} +1 -1
  5. package/dist/{plugin/AccomplishmentHandler.js → controller/AccomplishmentController.js} +1 -1
  6. package/dist/{core/controller → controller}/ExerciseController.d.ts +8 -6
  7. package/dist/{core/controller → controller}/ExerciseController.js +10 -9
  8. package/dist/{core/controller → controller}/ObjectController.d.ts +1 -1
  9. package/dist/{core/controller → controller}/ObjectController.js +1 -1
  10. package/dist/{core/controller → controller}/SettingsController.d.ts +2 -2
  11. package/dist/{core/controller → controller}/SharedContentController.d.ts +1 -1
  12. package/dist/{core/controller → controller}/VoiceController.d.ts +1 -1
  13. package/dist/index.d.ts +14 -8
  14. package/dist/index.js +7 -7
  15. package/dist/plugin/{PluginController.d.ts → CommunicationHandler.d.ts} +4 -7
  16. package/dist/plugin/{PluginController.js → CommunicationHandler.js} +19 -27
  17. package/dist/plugin/RimoriClient.d.ts +67 -68
  18. package/dist/plugin/RimoriClient.js +101 -43
  19. package/dist/worker/WorkerSetup.js +3 -3
  20. package/example/docs/devdocs.md +1 -1
  21. package/package.json +5 -26
  22. package/src/{core/controller → controller}/AIController.ts +3 -3
  23. package/src/{plugin/AccomplishmentHandler.ts → controller/AccomplishmentController.ts} +1 -1
  24. package/src/{core/controller → controller}/ExerciseController.ts +14 -11
  25. package/src/{core/controller → controller}/ObjectController.ts +2 -2
  26. package/src/{core/controller → controller}/SettingsController.ts +2 -2
  27. package/src/{core/controller → controller}/SharedContentController.ts +1 -1
  28. package/src/{core/controller → controller}/VoiceController.ts +2 -2
  29. package/src/fromRimori/readme.md +1 -1
  30. package/src/index.ts +14 -8
  31. package/src/plugin/{PluginController.ts → CommunicationHandler.ts} +24 -36
  32. package/src/plugin/RimoriClient.ts +127 -118
  33. package/src/worker/WorkerSetup.ts +6 -4
  34. package/tsconfig.json +5 -2
  35. package/dist/cli/scripts/release/release-translation-upload.d.ts +0 -6
  36. package/dist/cli/scripts/release/release-translation-upload.js +0 -87
  37. package/dist/components/CRUDModal.d.ts +0 -17
  38. package/dist/components/CRUDModal.js +0 -24
  39. package/dist/components/MarkdownEditor.d.ts +0 -8
  40. package/dist/components/MarkdownEditor.js +0 -48
  41. package/dist/components/Spinner.d.ts +0 -8
  42. package/dist/components/Spinner.js +0 -4
  43. package/dist/components/ai/Assistant.d.ts +0 -9
  44. package/dist/components/ai/Assistant.js +0 -58
  45. package/dist/components/ai/Avatar.d.ts +0 -14
  46. package/dist/components/ai/Avatar.js +0 -59
  47. package/dist/components/ai/EmbeddedAssistent/AudioInputField.d.ts +0 -7
  48. package/dist/components/ai/EmbeddedAssistent/AudioInputField.js +0 -37
  49. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.d.ts +0 -8
  50. package/dist/components/ai/EmbeddedAssistent/CircleAudioAvatar.js +0 -79
  51. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.d.ts +0 -19
  52. package/dist/components/ai/EmbeddedAssistent/TTS/MessageSender.js +0 -91
  53. package/dist/components/ai/EmbeddedAssistent/TTS/Player.d.ts +0 -27
  54. package/dist/components/ai/EmbeddedAssistent/TTS/Player.js +0 -185
  55. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.d.ts +0 -11
  56. package/dist/components/ai/EmbeddedAssistent/VoiceRecoder.js +0 -95
  57. package/dist/components/ai/utils.d.ts +0 -6
  58. package/dist/components/ai/utils.js +0 -13
  59. package/dist/components/audio/Playbutton.d.ts +0 -15
  60. package/dist/components/audio/Playbutton.js +0 -80
  61. package/dist/components/components/ContextMenu.d.ts +0 -10
  62. package/dist/components/components/ContextMenu.js +0 -135
  63. package/dist/components.d.ts +0 -10
  64. package/dist/components.js +0 -11
  65. package/dist/core/controller/EnhancedUserInfo.d.ts +0 -0
  66. package/dist/core/controller/EnhancedUserInfo.js +0 -1
  67. package/dist/core/core.d.ts +0 -14
  68. package/dist/core/core.js +0 -7
  69. package/dist/hooks/I18nHooks.d.ts +0 -11
  70. package/dist/hooks/I18nHooks.js +0 -25
  71. package/dist/hooks/UseChatHook.d.ts +0 -10
  72. package/dist/hooks/UseChatHook.js +0 -29
  73. package/dist/i18n/I18nHooks.d.ts +0 -11
  74. package/dist/i18n/I18nHooks.js +0 -25
  75. package/dist/i18n/Translator.d.ts +0 -43
  76. package/dist/i18n/Translator.js +0 -118
  77. package/dist/i18n/config.d.ts +0 -7
  78. package/dist/i18n/config.js +0 -20
  79. package/dist/i18n/createI18nInstance.d.ts +0 -7
  80. package/dist/i18n/createI18nInstance.js +0 -31
  81. package/dist/i18n/hooks.d.ts +0 -11
  82. package/dist/i18n/hooks.js +0 -25
  83. package/dist/i18n/index.d.ts +0 -4
  84. package/dist/i18n/index.js +0 -4
  85. package/dist/i18n/types.d.ts +0 -7
  86. package/dist/i18n/types.js +0 -1
  87. package/dist/i18n/useRimoriI18n.d.ts +0 -11
  88. package/dist/i18n/useRimoriI18n.js +0 -41
  89. package/dist/plugin/ThemeSetter.d.ts +0 -2
  90. package/dist/plugin/ThemeSetter.js +0 -19
  91. package/dist/plugin/Translator.d.ts +0 -38
  92. package/dist/plugin/Translator.js +0 -101
  93. package/dist/providers/PluginProvider.d.ts +0 -12
  94. package/dist/providers/PluginProvider.js +0 -152
  95. package/dist/style.css +0 -110
  96. package/dist/style.css.map +0 -1
  97. package/dist/utils/Language.d.ts +0 -67
  98. package/dist/utils/Language.js +0 -69
  99. package/dist/utils/LanguageClass.d.ts +0 -36
  100. package/dist/utils/LanguageClass.example.d.ts +0 -0
  101. package/dist/utils/LanguageClass.example.js +0 -1
  102. package/dist/utils/LanguageClass.js +0 -50
  103. package/dist/utils/LanguageClass.test.d.ts +0 -0
  104. package/dist/utils/LanguageClass.test.js +0 -1
  105. package/dist/utils/PluginUtils.d.ts +0 -2
  106. package/dist/utils/PluginUtils.js +0 -23
  107. package/src/components/CRUDModal.tsx +0 -75
  108. package/src/components/MarkdownEditor.tsx +0 -144
  109. package/src/components/Spinner.tsx +0 -29
  110. package/src/components/ai/Assistant.tsx +0 -96
  111. package/src/components/ai/Avatar.tsx +0 -99
  112. package/src/components/ai/EmbeddedAssistent/AudioInputField.tsx +0 -73
  113. package/src/components/ai/EmbeddedAssistent/CircleAudioAvatar.tsx +0 -107
  114. package/src/components/ai/EmbeddedAssistent/TTS/MessageSender.ts +0 -96
  115. package/src/components/ai/EmbeddedAssistent/TTS/Player.ts +0 -197
  116. package/src/components/ai/EmbeddedAssistent/VoiceRecoder.tsx +0 -129
  117. package/src/components/ai/utils.ts +0 -21
  118. package/src/components/audio/Playbutton.tsx +0 -126
  119. package/src/components/components/ContextMenu.tsx +0 -179
  120. package/src/components.ts +0 -11
  121. package/src/core/core.ts +0 -15
  122. package/src/hooks/I18nHooks.ts +0 -33
  123. package/src/hooks/UseChatHook.ts +0 -38
  124. package/src/plugin/ThemeSetter.ts +0 -23
  125. package/src/providers/PluginProvider.tsx +0 -209
  126. package/src/style.scss +0 -136
  127. package/src/utils/PluginUtils.ts +0 -22
  128. /package/dist/{plugin → controller}/AudioController.d.ts +0 -0
  129. /package/dist/{plugin → controller}/AudioController.js +0 -0
  130. /package/dist/{core/controller → controller}/SettingsController.js +0 -0
  131. /package/dist/{core/controller → controller}/SharedContentController.js +0 -0
  132. /package/dist/{plugin → controller}/TranslationController.d.ts +0 -0
  133. /package/dist/{plugin → controller}/TranslationController.js +0 -0
  134. /package/dist/{core/controller → controller}/VoiceController.js +0 -0
  135. /package/src/{plugin → controller}/AudioController.ts +0 -0
  136. /package/src/{plugin → controller}/TranslationController.ts +0 -0
package/dist/style.css DELETED
@@ -1,110 +0,0 @@
1
- dialog::backdrop {
2
- backdrop-filter: blur(2px);
3
- }
4
-
5
- .dark * dialog::backdrop {
6
- background: transparent;
7
- }
8
-
9
- .tiptap {
10
- padding-top: 5px;
11
- padding-left: 7px;
12
- /* min-height: 300px; */
13
- }
14
- .tiptap:focus-visible {
15
- outline: none;
16
- }
17
- .tiptap h1,
18
- .tiptap h2,
19
- .tiptap h3,
20
- .tiptap h4,
21
- .tiptap h5,
22
- .tiptap h6 {
23
- @apply font-bold;
24
- margin-bottom: 1rem;
25
- }
26
- .tiptap h1 {
27
- @apply text-4xl;
28
- }
29
- .tiptap h2 {
30
- @apply text-3xl;
31
- }
32
- .tiptap h3 {
33
- @apply text-2xl;
34
- }
35
- .tiptap h4 {
36
- @apply text-xl;
37
- }
38
- .tiptap h5 {
39
- @apply text-lg;
40
- }
41
- .tiptap h6 {
42
- @apply text-base;
43
- }
44
- .tiptap p {
45
- @apply mb-4;
46
- }
47
- .tiptap a {
48
- @apply text-blue-600 hover:text-blue-800;
49
- text-decoration: none;
50
- }
51
- .tiptap a:hover {
52
- @apply underline;
53
- }
54
- .tiptap ul {
55
- @apply list-disc pl-8;
56
- }
57
- .tiptap ul li > p {
58
- @apply mb-1;
59
- }
60
- .tiptap ol {
61
- @apply list-decimal pl-7;
62
- }
63
- .tiptap ol li > p {
64
- @apply mb-1;
65
- }
66
- .tiptap blockquote {
67
- @apply border-l-4 pl-4 italic text-gray-600 my-4;
68
- border-color: #ccc;
69
- }
70
- .tiptap code {
71
- font-family: monospace;
72
- }
73
- .tiptap pre {
74
- @apply bg-gray-800 text-gray-500 p-4 rounded-lg overflow-x-auto;
75
- font-family: monospace;
76
- white-space: pre-wrap;
77
- word-wrap: break-word;
78
- }
79
- .tiptap img {
80
- @apply max-w-full h-auto rounded-lg my-4;
81
- }
82
- .tiptap table {
83
- @apply table-auto w-full border-collapse mb-4;
84
- }
85
- .tiptap th,
86
- .tiptap td {
87
- @apply border px-4 py-2 text-left;
88
- }
89
- .tiptap th {
90
- @apply bg-gray-500 font-semibold;
91
- }
92
- .tiptap tr:nth-child(even) {
93
- @apply bg-gray-400;
94
- }
95
- @media (max-width: 768px) {
96
- .tiptap h1 {
97
- @apply text-3xl;
98
- }
99
- .tiptap h2 {
100
- @apply text-2xl;
101
- }
102
- .tiptap p {
103
- @apply text-base;
104
- }
105
- .tiptap img {
106
- @apply max-w-full;
107
- }
108
- }
109
-
110
- /*# sourceMappingURL=style.css.map */
@@ -1 +0,0 @@
1
- {"version":3,"sourceRoot":"","sources":["../src/style.scss"],"names":[],"mappings":"AAAA;EACE;;;AAIF;EACE;;;AAGF;EACE;EACA;AACA;;AAEA;EACE;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;;AAGF;EACE;;AAEA;EACE;;AAIJ;EACE;;AAEA;EACE;;AAIJ;EACE;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;AAAA;EAEE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE","file":"style.css"}
@@ -1,67 +0,0 @@
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
- * @param capitalize Whether to capitalize the first letter of the language name
65
- * @returns The language name
66
- */
67
- export declare function getLanguageName(languageCode: Language, capitalize?: boolean): string;
@@ -1,69 +0,0 @@
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
- * @param capitalize Whether to capitalize the first letter of the language name
64
- * @returns The language name
65
- */
66
- export function getLanguageName(languageCode, capitalize = false) {
67
- const lang = languageKeys[languageCode];
68
- return capitalize ? lang.charAt(0).toUpperCase() + lang.slice(1) : lang;
69
- }
@@ -1,36 +0,0 @@
1
- import { Language } from './Language';
2
- /**
3
- * A class that represents a language with dual functionality:
4
- * - When converted to string, returns the 2-letter language code
5
- * - When used as an object, provides getters for different language representations
6
- */
7
- export declare class LanguageClass {
8
- private readonly languageCode;
9
- constructor(languageCode: Language);
10
- /**
11
- * Returns the 2-letter language code when the object is converted to string
12
- */
13
- toString(): string;
14
- /**
15
- * Returns the 2-letter language code
16
- */
17
- get code(): string;
18
- /**
19
- * Returns the full language name in lowercase
20
- */
21
- get name(): string;
22
- /**
23
- * Returns the full language name with first letter capitalized
24
- */
25
- get capitalized(): string;
26
- /**
27
- * Returns the full language name in uppercase
28
- */
29
- get uppercase(): string;
30
- }
31
- /**
32
- * Creates a LanguageClass instance from a language code
33
- * @param languageCode The 2-letter language code
34
- * @returns A LanguageClass instance
35
- */
36
- export declare function createLanguage(languageCode: Language): LanguageClass;
File without changes
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,50 +0,0 @@
1
- import { languageKeys } from './Language';
2
- /**
3
- * A class that represents a language with dual functionality:
4
- * - When converted to string, returns the 2-letter language code
5
- * - When used as an object, provides getters for different language representations
6
- */
7
- export class LanguageClass {
8
- constructor(languageCode) {
9
- this.languageCode = languageCode;
10
- }
11
- /**
12
- * Returns the 2-letter language code when the object is converted to string
13
- */
14
- toString() {
15
- return this.languageCode;
16
- }
17
- /**
18
- * Returns the 2-letter language code
19
- */
20
- get code() {
21
- return this.languageCode;
22
- }
23
- /**
24
- * Returns the full language name in lowercase
25
- */
26
- get name() {
27
- return languageKeys[this.languageCode];
28
- }
29
- /**
30
- * Returns the full language name with first letter capitalized
31
- */
32
- get capitalized() {
33
- const lang = languageKeys[this.languageCode];
34
- return lang.charAt(0).toUpperCase() + lang.slice(1);
35
- }
36
- /**
37
- * Returns the full language name in uppercase
38
- */
39
- get uppercase() {
40
- return languageKeys[this.languageCode].toUpperCase();
41
- }
42
- }
43
- /**
44
- * Creates a LanguageClass instance from a language code
45
- * @param languageCode The 2-letter language code
46
- * @returns A LanguageClass instance
47
- */
48
- export function createLanguage(languageCode) {
49
- return new LanguageClass(languageCode);
50
- }
File without changes
@@ -1 +0,0 @@
1
- "use strict";
@@ -1,2 +0,0 @@
1
- export declare function isFullscreen(): boolean;
2
- export declare function triggerFullscreen(onStateChange: (isFullscreen: boolean) => void, selector?: string): void;
@@ -1,23 +0,0 @@
1
- export function isFullscreen() {
2
- return !!document.fullscreenElement;
3
- }
4
- export function triggerFullscreen(onStateChange, selector) {
5
- document.addEventListener('fullscreenchange', () => {
6
- onStateChange(isFullscreen());
7
- });
8
- try {
9
- const ref = document.querySelector(selector || '#root');
10
- if (!isFullscreen()) {
11
- // @ts-ignore
12
- ref.requestFullscreen() || ref.webkitRequestFullscreen();
13
- }
14
- else {
15
- // @ts-ignore
16
- document.exitFullscreen() || document.webkitExitFullscreen();
17
- }
18
- }
19
- catch (error) {
20
- console.error('Failed to enter fullscreen', error.message);
21
- }
22
- onStateChange(isFullscreen());
23
- }
@@ -1,75 +0,0 @@
1
- import { useEffect, useRef } from 'react';
2
-
3
- interface Props {
4
- title: string;
5
- show?: boolean;
6
- className?: string;
7
- closeAble?: boolean;
8
- children: React.ReactNode;
9
- actionbuttons: ActionButton[];
10
- buttonText?: string | React.ReactNode;
11
- onClose?: () => void;
12
- }
13
-
14
- interface ActionButton {
15
- text: string;
16
- onClick: () => void;
17
- closeModal?: boolean;
18
- }
19
-
20
- export function CRUDModal({
21
- actionbuttons,
22
- children,
23
- title,
24
- buttonText,
25
- className,
26
- closeAble = true,
27
- show = false,
28
- onClose,
29
- }: Props) {
30
- const dialogRef = useRef<HTMLDialogElement>(null);
31
-
32
- useEffect(() => {
33
- if (show) {
34
- dialogRef.current?.showModal();
35
- } else {
36
- dialogRef.current?.close();
37
- }
38
- }, [show]);
39
-
40
- const handleClose = () => {
41
- dialogRef.current?.close();
42
- onClose?.();
43
- };
44
-
45
- return (
46
- <>
47
- {!!buttonText && (
48
- <button className={className} onClick={() => dialogRef.current?.showModal()}>
49
- {buttonText}
50
- </button>
51
- )}
52
- <dialog ref={dialogRef} className="bg-gray-400 rounded-lg font-normal" onClose={handleClose}>
53
- <div className="bg-gray-500 text-xl flex flex-row justify-between p-3 items-start font-bold">
54
- <h2>{title}</h2>
55
- {closeAble && <button onClick={handleClose}>&times;</button>}
56
- </div>
57
- <div className="modal-body p-2">{children}</div>
58
- <div className="modal-footer px-2 py-2 flex flex-row gap-2 border-t-2">
59
- {actionbuttons.map(({ onClick, text, closeModal = true }, index) => (
60
- <button
61
- key={index}
62
- className="bg-blue-500 hover:bg-blue-600 dark:border-gray-900 rounded-md py-2 px-4 dark:text-white font-bold"
63
- onClick={() => {
64
- if (closeModal) handleClose();
65
- onClick();
66
- }}
67
- >
68
- {text}
69
- </button>
70
- ))}
71
- </div>
72
- </dialog>
73
- </>
74
- );
75
- }
@@ -1,144 +0,0 @@
1
- import { Markdown } from 'tiptap-markdown';
2
- import StarterKit from '@tiptap/starter-kit';
3
- import { PiCodeBlock } from 'react-icons/pi';
4
- import { TbBlockquote } from 'react-icons/tb';
5
- import { GoListOrdered } from 'react-icons/go';
6
- import { AiOutlineUnorderedList } from 'react-icons/ai';
7
- import { EditorProvider, useCurrentEditor } from '@tiptap/react';
8
- import { LuHeading1, LuHeading2, LuHeading3 } from 'react-icons/lu';
9
- import { FaBold, FaCode, FaItalic, FaParagraph, FaStrikethrough } from 'react-icons/fa';
10
-
11
- // This inplementation is rooted in the Tiptap editor basic example https://codesandbox.io/p/devbox/editor-9x9dkd
12
-
13
- interface EditorButtonProps {
14
- action: string;
15
- isActive?: boolean;
16
- label: string | React.ReactNode;
17
- disabled?: boolean;
18
- }
19
-
20
- const EditorButton = ({ action, isActive, label, disabled }: EditorButtonProps) => {
21
- const { editor } = useCurrentEditor() as any;
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
- }
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
- };
49
-
50
- const MenuBar = () => {
51
- const { editor } = useCurrentEditor();
52
-
53
- if (!editor) {
54
- return null;
55
- }
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
65
- action="setHeading1"
66
- isActive={editor.isActive('heading', { level: 1 })}
67
- label={<LuHeading1 size={'24px'} />}
68
- />
69
- <EditorButton
70
- action="setHeading2"
71
- isActive={editor.isActive('heading', { level: 2 })}
72
- label={<LuHeading2 size={'24px'} />}
73
- />
74
- <EditorButton
75
- action="setHeading3"
76
- isActive={editor.isActive('heading', { level: 3 })}
77
- label={<LuHeading3 size={'24px'} />}
78
- />
79
- <EditorButton
80
- action="toggleBulletList"
81
- isActive={editor.isActive('bulletList')}
82
- label={<AiOutlineUnorderedList size={'24px'} />}
83
- />
84
- <EditorButton
85
- action="toggleOrderedList"
86
- isActive={editor.isActive('orderedList')}
87
- label={<GoListOrdered size={'24px'} />}
88
- />
89
- <EditorButton
90
- action="toggleCodeBlock"
91
- isActive={editor.isActive('codeBlock')}
92
- label={<PiCodeBlock size={'24px'} />}
93
- />
94
- <EditorButton
95
- action="toggleBlockquote"
96
- isActive={editor.isActive('blockquote')}
97
- label={<TbBlockquote size={'24px'} />}
98
- />
99
- </div>
100
- );
101
- };
102
-
103
- const extensions = [
104
- StarterKit.configure({
105
- bulletList: {
106
- HTMLAttributes: {
107
- class: 'list-disc list-inside dark:text-white p-1 mt-1 [&_li]:mb-1 [&_p]:inline m-0',
108
- },
109
- },
110
- orderedList: {
111
- HTMLAttributes: {
112
- className: 'list-decimal list-inside dark:text-white p-1 mt-1 [&_li]:mb-1 [&_p]:inline m-0',
113
- },
114
- },
115
- }),
116
- Markdown,
117
- ];
118
-
119
- interface Props {
120
- content?: string;
121
- editable: boolean;
122
- className?: string;
123
- onUpdate?: (content: string) => void;
124
- }
125
-
126
- export const MarkdownEditor = (props: Props) => {
127
- return (
128
- <div
129
- className={'text-md border border-gray-800 overflow-hidden ' + props.className}
130
- style={{ borderWidth: props.editable ? 1 : 0 }}
131
- >
132
- <EditorProvider
133
- key={(props.editable ? 'editable' : 'readonly') + props.content}
134
- slotBefore={props.editable ? <MenuBar /> : null}
135
- extensions={extensions}
136
- content={props.content}
137
- editable={props.editable}
138
- onUpdate={(e) => {
139
- props.onUpdate && props.onUpdate(e.editor.storage.markdown.getMarkdown());
140
- }}
141
- ></EditorProvider>
142
- </div>
143
- );
144
- };
@@ -1,29 +0,0 @@
1
- import React from 'react';
2
-
3
- interface SpinnerProps {
4
- text?: string;
5
- size?: string;
6
- className?: string;
7
- }
8
-
9
- export const Spinner: React.FC<SpinnerProps> = ({ text, className, size = '30px' }) => {
10
- return (
11
- <div className={'flex items-center space-x-2 ' + className}>
12
- <svg
13
- style={{ width: size, height: size }}
14
- className="animate-spin -ml-1 mr-3 h-5 w-5 text-white"
15
- xmlns="http://www.w3.org/2000/svg"
16
- fill="none"
17
- viewBox="0 0 24 24"
18
- >
19
- <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
20
- <path
21
- className="opacity-75"
22
- fill="currentColor"
23
- d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
24
- ></path>
25
- </svg>
26
- {text && <span className="">{text}</span>}
27
- </div>
28
- );
29
- };