or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cloud-integration.mdcontext-management.mdindex.mdmulti-root-editor.mdsingle-root-editor.md
tile.json

cloud-integration.mddocs/

Cloud Integration

CKEditor 5 React integration provides cloud-based loading capabilities for dynamically importing CKEditor builds from CDN services, enabling reduced bundle sizes and flexible editor distribution.

Capabilities

useCKEditorCloud Hook

React hook for loading CKEditor bundles from cloud/CDN services with async state management.

/**
 * Hook for loading CKEditor bundles from cloud services
 * Provides async state management for CDN-based editor loading
 */
function useCKEditorCloud<Config extends CKEditorCloudConfig>(
  config: Config
): CKEditorCloudHookResult<Config>;

interface CKEditorCloudConfig {
  /** CKEditor version to load */
  version: string;
  
  /** Array of language codes for translations */
  translations?: string[];
  
  /** Enable premium features */
  premium?: boolean;
  
  /** Additional plugins to load */
  plugins?: string[];
  
  /** CDN base URL override */
  cdnUrl?: string;
}

type CKEditorCloudHookResult<Config extends CKEditorCloudConfig> =
  | {
      /** Loading state */
      status: 'loading';
    }
  | {
      /** Error state */
      status: 'error';
      error: any;
    }
  | ({
      /** Success state with loaded CKEditor modules */
      status: 'success';
    } & CKEditorCloudResult<Config>);

interface CKEditorCloudResult<Config extends CKEditorCloudConfig> {
  /** Core CKEditor modules */
  CKEditor: {
    ClassicEditor: typeof ClassicEditor;
    InlineEditor: typeof InlineEditor; 
    BalloonEditor: typeof BalloonEditor;
    DecoupledEditor: typeof DecoupledEditor;
    MultiRootEditor: typeof MultiRootEditor;
    [key: string]: any;
  };
  
  /** Premium features (if enabled) */
  CKEditorPremiumFeatures?: {
    [key: string]: any;
  };
  
  /** Additional plugins */
  CKPlugins?: {
    [key: string]: any;
  };
}

Usage Examples:

import React from 'react';
import { useCKEditorCloud, CKEditor } from '@ckeditor/ckeditor5-react';

// Basic cloud usage
function BasicCloudEditor() {
  const cloud = useCKEditorCloud({
    version: '42.0.0',
    translations: ['es', 'de']
  });

  if (cloud.status === 'loading') {
    return <div>Loading CKEditor from cloud...</div>;
  }

  if (cloud.status === 'error') {
    return <div>Error loading CKEditor: {cloud.error?.message}</div>;
  }

  const { ClassicEditor } = cloud.CKEditor;

  return (
    <CKEditor
      editor={ClassicEditor}
      data="<p>Editor loaded from cloud!</p>"
      onReady={(editor) => {
        console.log('Cloud editor ready:', editor);
      }}
    />
  );
}

// Advanced cloud configuration
function AdvancedCloudEditor() {
  const cloud = useCKEditorCloud({
    version: '42.0.0',
    translations: ['es', 'fr', 'de'],
    premium: true,
    plugins: ['CustomPlugin', 'SpecialFeature'],
    cdnUrl: 'https://custom-cdn.example.com'
  });

  switch (cloud.status) {
    case 'loading':
      return (
        <div>
          <div>Loading CKEditor...</div>
          <div>Version: 42.0.0</div>
          <div>Premium features: enabled</div>
        </div>
      );

    case 'error':
      return (
        <div style={{ color: 'red' }}>
          <h3>Failed to load CKEditor</h3>
          <p>Error: {cloud.error?.message}</p>
          <p>Please check your network connection and try again.</p>
        </div>
      );

    case 'success':
      const { ClassicEditor, Bold, Italic, Link } = cloud.CKEditor;
      const { PremiumPlugin } = cloud.CKEditorPremiumFeatures || {};
      const { CustomPlugin } = cloud.CKPlugins || {};

      return (
        <div>
          <h3>Cloud Editor Ready</h3>
          <p>Loaded plugins: {Object.keys(cloud.CKEditor).length}</p>
          
          <CKEditor
            editor={ClassicEditor}
            data="<p>Advanced cloud editor with premium features!</p>"
            config={{
              plugins: [Bold, Italic, Link, PremiumPlugin, CustomPlugin].filter(Boolean),
              toolbar: ['bold', 'italic', 'link', 'premiumFeature']
            }}
            onReady={(editor) => {
              console.log('Advanced cloud editor ready with plugins:', 
                editor.plugins.getPluginNames());
            }}
          />
        </div>
      );
  }
}

// Multi-language cloud editor
function MultiLanguageCloudEditor() {
  const [currentLanguage, setCurrentLanguage] = useState('en');
  
  const cloud = useCKEditorCloud({
    version: '42.0.0',
    translations: ['es', 'fr', 'de', 'pl']
  });

  if (cloud.status !== 'success') {
    return <div>Loading editor...</div>;
  }

  const { ClassicEditor } = cloud.CKEditor;

  return (
    <div>
      <div>
        <label>Language: </label>
        <select 
          value={currentLanguage} 
          onChange={(e) => setCurrentLanguage(e.target.value)}
        >
          <option value="en">English</option>
          <option value="es">Español</option>
          <option value="fr">Français</option>
          <option value="de">Deutsch</option>
          <option value="pl">Polski</option>
        </select>
      </div>
      
      <CKEditor
        key={currentLanguage} // Force re-render on language change
        editor={ClassicEditor}
        data="<p>Multi-language editor</p>"
        config={{
          language: currentLanguage,
          toolbar: ['bold', 'italic', 'link']
        }}
      />
    </div>
  );
}

withCKEditorCloud HOC

Higher-order component for injecting CKEditor cloud integration into components.

/**
 * HOC for injecting CKEditor cloud integration into components
 * Provides cloud loading state management and error handling
 */
function withCKEditorCloud<Config extends CKEditorCloudConfig>(
  config: CKEditorCloudHocConfig<Config>
): <P extends object>(
  WrappedComponent: ComponentType<WithCKEditorCloudHocProps<Config> & P>
) => ComponentType<Omit<P, keyof WithCKEditorCloudHocProps<Config>>>;

interface CKEditorCloudHocConfig<Config extends CKEditorCloudConfig> {
  /** Cloud configuration */
  cloud: Config;
  
  /** Component to render while loading */
  renderLoader?: () => ReactNode;
  
  /** Component to render on error */
  renderError?: (error: any) => ReactNode;
}

interface WithCKEditorCloudHocProps<Config extends CKEditorCloudConfig = CKEditorCloudConfig> {
  /** Injected cloud result */
  cloud: CKEditorCloudResult<Config>;
}

HOC Usage Examples:

import React from 'react';
import { withCKEditorCloud, CKEditor } from '@ckeditor/ckeditor5-react';

// Basic HOC usage
const withCKCloud = withCKEditorCloud({
  cloud: {
    version: '42.0.0',
    translations: ['es', 'de'],
    premium: true
  }
});

const MyEditorComponent = withCKCloud(({ cloud, title }) => {
  const { ClassicEditor, Bold, Italic } = cloud.CKEditor;
  const { PremiumFeature } = cloud.CKEditorPremiumFeatures || {};

  return (
    <div>
      <h3>{title}</h3>
      <CKEditor
        editor={ClassicEditor}
        data="<p>Editor with cloud integration via HOC</p>"
        config={{
          plugins: [Bold, Italic, PremiumFeature].filter(Boolean),
          toolbar: ['bold', 'italic', 'premiumFeature']
        }}
      />
    </div>
  );
});

// Usage
function App() {
  return <MyEditorComponent title="My Cloud Editor" />;
}

// Advanced HOC with custom loading and error handling
const withAdvancedCKCloud = withCKEditorCloud({
  cloud: {
    version: '42.0.0',
    premium: true
  },
  renderLoader: () => (
    <div style={{ padding: '20px', textAlign: 'center' }}>
      <div>🔄 Loading CKEditor...</div>
      <div>Please wait while we fetch the editor from our CDN</div>
    </div>
  ),
  renderError: (error) => (
    <div style={{ padding: '20px', color: 'red', border: '1px solid red' }}>
      <h3>❌ CKEditor Load Failed</h3>
      <p>Unable to load CKEditor from cloud service.</p>
      <p>Error: {error?.message}</p>
      <button onClick={() => window.location.reload()}>
        Retry
      </button>
    </div>
  )
});

const AdvancedCloudComponent = withAdvancedCKCloud(({ cloud, config }) => {
  const { ClassicEditor } = cloud.CKEditor;

  return (
    <div>
      <h3>Production Editor</h3>
      <CKEditor
        editor={ClassicEditor}
        data="<p>Production-ready cloud editor</p>"
        config={config}
        onReady={(editor) => {
          console.log('Production editor ready');
        }}
      />
    </div>
  );
});

// Multiple editors with shared cloud HOC
const SharedCloudHOC = withCKEditorCloud({
  cloud: {
    version: '42.0.0',
    translations: ['es', 'fr']
  }
});

const MultiEditorComponent = SharedCloudHOC(({ cloud }) => {
  const { ClassicEditor, InlineEditor } = cloud.CKEditor;

  return (
    <div>
      <div>
        <h4>Classic Editor</h4>
        <CKEditor
          editor={ClassicEditor}
          data="<p>Classic editor content</p>"
        />
      </div>
      
      <div>
        <h4>Inline Editor</h4>
        <CKEditor
          editor={InlineEditor}
          data="<p>Inline editor content</p>"
        />
      </div>
    </div>
  );
});

loadCKEditorCloud Function

Direct function for loading CKEditor from cloud services without React hooks.

/**
 * Loads CKEditor bundles from cloud services
 * Can be used outside of React components
 */
function loadCKEditorCloud<Config extends CKEditorCloudConfig>(
  config: Config
): Promise<CKEditorCloudResult<Config>>;

Direct Loading Usage:

import { loadCKEditorCloud } from '@ckeditor/ckeditor5-react';

// Preload CKEditor outside component
async function preloadCKEditor() {
  try {
    const cloudResult = await loadCKEditorCloud({
      version: '42.0.0',
      translations: ['es', 'fr'],
      premium: true
    });

    console.log('CKEditor preloaded:', cloudResult);
    
    // Store in global state or cache
    window.preloadedCKEditor = cloudResult;
    
    return cloudResult;
  } catch (error) {
    console.error('Failed to preload CKEditor:', error);
    throw error;
  }
}

// Use in application initialization
preloadCKEditor().then(() => {
  console.log('CKEditor ready for use');
});

// Dynamic loading based on user preferences
async function loadEditorForUser(userPreferences) {
  const config = {
    version: '42.0.0',
    translations: [userPreferences.language],
    premium: userPreferences.hasPremium
  };

  try {
    const cloudResult = await loadCKEditorCloud(config);
    return cloudResult;
  } catch (error) {
    console.error('Failed to load personalized editor:', error);
    // Fallback to basic configuration
    return loadCKEditorCloud({ version: '42.0.0' });
  }
}

Error Handling and Recovery

import React, { useState, useCallback } from 'react';
import { useCKEditorCloud, CKEditor } from '@ckeditor/ckeditor5-react';

function RobustCloudEditor() {
  const [retryCount, setRetryCount] = useState(0);
  const [forceReload, setForceReload] = useState(false);

  const cloud = useCKEditorCloud({
    version: '42.0.0',
    premium: true,
    // Add cache busting on retry
    cdnUrl: forceReload ? `https://cdn.ckeditor.com?retry=${retryCount}` : undefined
  });

  const handleRetry = useCallback(() => {
    setRetryCount(prev => prev + 1);
    setForceReload(true);
    setTimeout(() => setForceReload(false), 100);
  }, []);

  if (cloud.status === 'loading') {
    return (
      <div>
        <div>Loading CKEditor from cloud...</div>
        {retryCount > 0 && <div>Retry attempt: {retryCount}</div>}
      </div>
    );
  }

  if (cloud.status === 'error') {
    return (
      <div>
        <h3>Failed to load CKEditor</h3>
        <p>Error: {cloud.error?.message}</p>
        <p>Attempts: {retryCount + 1}</p>
        <button onClick={handleRetry}>
          Retry Loading
        </button>
        {retryCount >= 3 && (
          <div>
            <p>Consider using a local build instead:</p>
            <code>npm install ckeditor5</code>
          </div>
        )}
      </div>
    );
  }

  const { ClassicEditor } = cloud.CKEditor;

  return (
    <div>
      <div>✅ CKEditor loaded successfully</div>
      <CKEditor
        editor={ClassicEditor}
        data="<p>Cloud editor with error recovery</p>"
        onError={(error, details) => {
          console.error('Editor runtime error:', error);
          if (!details.willEditorRestart) {
            // Manual recovery might be needed
            handleRetry();
          }
        }}
      />
    </div>
  );
}