New features: - HLS video encoding/streaming (hls routes, hls-encoder) and a media transcripts pipeline (transcripts route + media-transcript queries) - AI assistant chat vs. run model: agent-course-generation worker/queue, run-monitor pane, chat-changes card, content ask-ai bar - Per-theme course-page previews across org landing-page themes (bold, classic, corporate, editorial, etc.) with a shared course token/component set - View-as-student mode and login-link / link-invite invite flows Refactor: - Extract packages/core consolidating config (env, storage, dashboard-url), services and utils previously duplicated under apps/api/src/config - Remove legacy agent service modules (chat-tools, chat-context, context-window, document, fetch-url, lesson-content) - Relax Cross-Origin-Resource-Policy to allow cross-origin media embedding - Add format script to tenant-router so turbo run format covers it
66 lines
1.8 KiB
Svelte
66 lines
1.8 KiB
Svelte
<script module lang="ts">
|
|
// Module-level singleton: one Promise shared across all mounted instances.
|
|
// Dynamic imports are already cached by the JS engine after the first load,
|
|
// but reusing the same Promise avoids redundant microtask chains on remounts.
|
|
let pending: Promise<typeof import('@cio/ui/custom/editor')> | null = null;
|
|
|
|
function loadEditor() {
|
|
pending ??= import('@cio/ui/custom/editor');
|
|
return pending;
|
|
}
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
// Type-only imports are erased at build time — no static TipTap dependency.
|
|
import type { HTMLContent, TiptapEditor } from '@cio/ui/custom/editor';
|
|
|
|
interface Props {
|
|
placeholder?: string | ((node: any) => string);
|
|
content?: HTMLContent;
|
|
showToolBar?: boolean;
|
|
editable?: boolean;
|
|
enablePersistence?: boolean;
|
|
contentStorageKey?: string;
|
|
editableStorageKey?: string;
|
|
class?: string;
|
|
editorClass?: string;
|
|
onChange?: (content: HTMLContent) => void;
|
|
onReady?: (editor: TiptapEditor) => void;
|
|
onEditorDestroy?: () => void;
|
|
}
|
|
|
|
let {
|
|
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();
|
|
</script>
|
|
|
|
{#await loadEditor()}
|
|
<div class="ui:animate-pulse ui:rounded-md ui:bg-muted ui:h-32 ui:w-full" />
|
|
{:then { Editor }}
|
|
<Editor
|
|
{content}
|
|
{showToolBar}
|
|
{editable}
|
|
{enablePersistence}
|
|
{contentStorageKey}
|
|
{editableStorageKey}
|
|
class={className}
|
|
{editorClass}
|
|
{placeholder}
|
|
onContentChange={onChange}
|
|
onEditorReady={onReady}
|
|
{onEditorDestroy}
|
|
/>
|
|
{/await}
|