feat: move away from carbon components and TinyMCE (#597)

* feat: remove tinymce & replace org sidebar

* chore: PR Fixes

* chore: move ui font into src dir

* remove files in vite config

* use google font import for loading font

* remove custom font

* more fonts update

* remove font bold

* more removals of font bold

* fix import

* checkpoint

* chore: checkpoint (add course & lms shadcn sidebar)

* minor css improvements and try out font sans

* chore: replace carbon components with shadcn's

* chore: replace carbon components with shadcn _ v3

* chore: ui fixes & storybook update

* feat: UI cleanup

* fix: quick ui fixes

* chore: update pnpm-lock.yaml with new dependencies and versions; fix output.css formatting

* chore: add isloading to button

* feat: add loading state to button stories

* chore: feedback fixes

* fix: feedback fixes

* chore: remove console

* fix: PR comments

* fix: PR comments

---------

Co-authored-by: Rotimi Best <best@classroomio.com>
This commit is contained in:
Adeyemi Adetunji
2025-11-21 12:18:04 +01:00
committed by GitHub
co-authored by Rotimi Best
parent 2145782385
commit cbf6ae7e63
499 changed files with 19708 additions and 15603 deletions
@@ -1,118 +1,58 @@
<script lang="ts">
import Editor from './TinymceSvelte/index.svelte';
import { globalStore } from '$lib/utils/store/app';
import { addMathPlugin } from '$lib/utils/functions/tinymce/plugins';
import { untrack } from 'svelte';
import { Editor } from '@cio/ui/custom/editor';
import type { Content, TiptapEditor } from '@cio/ui/custom/editor';
interface Props {
id?: string;
value?: string | undefined;
onChange?: any;
height?: number;
placeholder?: string;
editorWindowRef?: Window | undefined;
maxHeight?: number | undefined;
placeholder?: string | ((node: any) => string);
// Content of the editor
content?: Content;
// Whether the toolbar should be visible
showToolBar?: boolean;
// Whether the editor is editable
editable?: boolean;
// Whether to enable localStorage persistence
enablePersistence?: boolean;
// localStorage key for content persistence
contentStorageKey?: string;
// localStorage key for editable state persistence
editableStorageKey?: string;
// CSS class for the editor wrapper
class?: string;
// CSS class for the editor itself
editorClass?: string;
// Callback functions
onChange?: (content: Content) => void;
onReady?: (editor: TiptapEditor) => void;
onEditorDestroy?: () => void;
}
let {
id = '',
value = $bindable(),
onChange = (_html: string) => {},
height = 300,
placeholder = '',
editorWindowRef = $bindable(undefined),
maxHeight = undefined
content,
showToolBar = true,
editable = true,
enablePersistence = false,
contentStorageKey = 'edra-content',
editableStorageKey = 'edra-editable',
class: className = '',
editorClass = '',
placeholder = 'Welcome to ClassroomIO',
onChange,
onReady,
onEditorDestroy
}: Props = $props();
let unmount = $state(false);
let editorChangeHandlerId;
function getTinymce() {
const getSink = () => {
return typeof window !== 'undefined' ? window : global;
};
const sink = getSink();
const res = sink && sink.tinymce ? sink.tinymce : null;
console.log({ res });
return res;
}
// editor configuration
let conf = $state({
plugins: 'lists, link, emoticons, code, media, searchreplace, eqneditor',
toolbar: [
{ name: 'history', items: ['undo', 'redo'] },
{ name: 'styles', items: ['styles'] },
{ name: 'formatting', items: ['bold', 'italic'] },
{ name: 'alignment', items: ['alignleft', 'aligncenter', 'alignright', 'alignjustify'] },
{ name: 'indentation', items: ['outdent', 'indent'] },
{ name: 'list', items: ['numlist', 'bullist'] },
{ name: 'link', items: ['link'] },
{ name: 'insert', items: ['emoticons'] },
{ name: 'code', items: ['code'] },
{ name: 'media', items: ['media'] },
{ name: 'search', items: ['searchreplace'] },
{ name: 'eqneditor', items: ['eqneditor'] }
],
lists_indent_on_tab: false,
min_height: height,
max_height: maxHeight,
placeholder: placeholder,
skin: 'oxide-dark',
content_css: 'dark',
extended_valid_elements: '*[.*]',
license_key: 'gpl',
setup: () => {
addMathPlugin(getTinymce());
},
init_instance_callback: function (editor: any) {
editorWindowRef = editor.iframeElement?.contentWindow;
editor.on('Paste Change input Undo Redo', function () {
clearTimeout(editorChangeHandlerId);
const html = editor.getContent();
editorChangeHandlerId = setTimeout(function () {
if (onChange) {
onChange(html);
}
if (id) {
localStorage.setItem(id, html);
}
}, 1000);
});
}
});
function handleModeChange(isDark: boolean) {
if (isDark) {
conf.content_css = 'dark';
conf.skin = 'oxide-dark';
} else {
conf.content_css = 'light';
conf.skin = 'oxide';
}
untrack(() => {
unmount = true;
setTimeout(() => {
unmount = false;
}, 200);
});
}
$effect(() => {
handleModeChange($globalStore.isDark);
});
</script>
<svelte:head>
<link rel="stylesheet" href="https://unpkg.com/katex@0.12.0/dist/katex.min.css" />
</svelte:head>
<div>
{#if !unmount}
<Editor bind:value bind:conf />
{/if}
</div>
<Editor
content={content || ''}
{showToolBar}
{editable}
{enablePersistence}
{contentStorageKey}
{editableStorageKey}
class={className}
{editorClass}
{placeholder}
onContentChange={onChange}
onEditorReady={onReady}
{onEditorDestroy}
/>