-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #510 from ckeditor/ck/cloud-poc
Feature: Added `useCKEditorCloud` hook for managing asynchronous loading of CKEditor from a CDN. Feature: Added withCKEditorCloud HOC to simplify CKEditor integration with CDN in React components.
- Loading branch information
Showing
67 changed files
with
3,426 additions
and
446 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/** | ||
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md. | ||
*/ | ||
|
||
import React, { StrictMode, useState } from 'react'; | ||
import MultiRootEditorDemo from './MultiRootEditorDemo'; | ||
import MultiRootEditorRichDemo from './MultiRootEditorRichDemo'; | ||
import ContextMultiRootEditorDemo from './ContextMultiRootEditorDemo'; | ||
|
||
type Demo = 'editor' | 'rich' | 'context'; | ||
|
||
const multiRootEditorContent = { | ||
intro: '<h2>Sample</h2><p>This is an instance of the ' + | ||
'<a href="https://ckeditor.com/docs/ckeditor5/latest/builds/guides/overview.html#classic-editor">multi-root editor build</a>.</p>', | ||
content: '<p>It is the custom content</p><figure class="image"><img src="/demos/sample.jpg" alt="CKEditor 5 Sample image."></figure>', | ||
outro: '<p>You can use this sample to validate whether your ' + | ||
'<a href="https://ckeditor.com/docs/ckeditor5/latest/builds/guides/development/custom-builds.html">custom build</a> works fine.</p>' | ||
}; | ||
|
||
const rootsAttributes = { | ||
intro: { | ||
row: '1', | ||
order: 10 | ||
}, | ||
content: { | ||
row: '1', | ||
order: 20 | ||
}, | ||
outro: { | ||
row: '2', | ||
order: 10 | ||
} | ||
}; | ||
|
||
export default function App(): JSX.Element { | ||
const [ demo, setDemo ] = useState<Demo>( 'editor' ); | ||
|
||
const renderDemo = () => { | ||
switch ( demo ) { | ||
case 'context': | ||
return <ContextMultiRootEditorDemo />; | ||
case 'editor': | ||
return <MultiRootEditorDemo data={multiRootEditorContent} rootsAttributes={rootsAttributes} />; | ||
case 'rich': | ||
return <MultiRootEditorRichDemo data={multiRootEditorContent} rootsAttributes={rootsAttributes} />; | ||
} | ||
}; | ||
|
||
return ( | ||
<StrictMode> | ||
<h1>CKEditor 5 – useMultiRootEditor – CDN development sample</h1> | ||
|
||
<div className="buttons" style={ { textAlign: 'center' } }> | ||
<button | ||
onClick={ () => setDemo( 'editor' ) } | ||
disabled={ demo == 'editor' } | ||
> | ||
Editor demo | ||
</button> | ||
|
||
<button | ||
onClick={ () => setDemo( 'rich' ) } | ||
disabled={ demo == 'rich' } | ||
> | ||
Rich integration demo | ||
</button> | ||
|
||
<button | ||
onClick={ () => setDemo( 'context' ) } | ||
disabled={ demo == 'context' } | ||
> | ||
Context demo | ||
</button> | ||
</div> | ||
{ renderDemo() } | ||
</StrictMode> | ||
); | ||
} |
142 changes: 142 additions & 0 deletions
142
demos/cdn-multiroot-react/ContextMultiRootEditorDemo.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
/** | ||
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md. | ||
*/ | ||
|
||
import React from 'react'; | ||
|
||
import { useMultiRootEditor, type MultiRootHookProps, CKEditorContext, withCKEditorCloud } from '../../src/index.js'; | ||
import { useCKCdnMultiRootEditor } from './useCKCdnMultiRootEditor.js'; | ||
|
||
const ContextEditorDemo = ( { editor }: { editor: any } ): JSX.Element => { | ||
const editorProps: Partial<MultiRootHookProps> = { | ||
editor, | ||
|
||
onChange: ( event, editor ) => { | ||
console.log( 'event: onChange', { event, editor } ); | ||
}, | ||
onBlur: ( event, editor ) => { | ||
console.log( 'event: onBlur', { event, editor } ); | ||
}, | ||
onFocus: ( event, editor ) => { | ||
console.log( 'event: onFocus', { event, editor } ); | ||
} | ||
}; | ||
|
||
// First editor initialization. | ||
const { | ||
editor: editor1, editableElements: editableElements1, toolbarElement: toolbarElement1 | ||
} = useMultiRootEditor( { | ||
...editorProps, | ||
data: { | ||
intro: '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>', | ||
content: '<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>' | ||
}, | ||
|
||
onReady: editor => { | ||
window.editor1 = editor; | ||
|
||
console.log( 'event: onChange', { editor } ); | ||
} | ||
} as MultiRootHookProps ); | ||
|
||
// Second editor initialization. | ||
const { | ||
editor: editor2, editableElements: editableElements2, toolbarElement: toolbarElement2 | ||
} = useMultiRootEditor( { | ||
...editorProps, | ||
data: { | ||
notes: '<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>' | ||
}, | ||
|
||
onReady: editor => { | ||
window.editor2 = editor; | ||
|
||
console.log( 'event: onChange', { editor } ); | ||
} | ||
} as MultiRootHookProps ); | ||
|
||
// Function to simulate an error in the editor. | ||
// It is used for testing purposes to trigger the Watchdog to restart the editor. | ||
// Remove it in the actual integration. | ||
const simulateError = ( editor: any ) => { | ||
setTimeout( () => { | ||
const err: any = new Error( 'foo' ); | ||
|
||
err.context = editor; | ||
err.is = () => true; | ||
|
||
throw err; | ||
} ); | ||
}; | ||
|
||
return ( | ||
<> | ||
<h2 className="subtitle">Context Multi-root Editor Demo</h2> | ||
<p className="info"> | ||
This sample demonstrates integration with CKEditorContext.<br /> | ||
</p> | ||
<p className="info">Component's events are logged to the console.</p> | ||
<hr /><br /> | ||
|
||
<div> | ||
<div className="buttons"> | ||
<button | ||
onClick={ () => simulateError( editor1! ) } | ||
disabled={ !editor1 } | ||
> | ||
Simulate an error in first editor | ||
</button> | ||
</div> | ||
|
||
{ toolbarElement1 } | ||
|
||
<div className="flex"> | ||
{ editableElements1 } | ||
</div> | ||
</div> | ||
|
||
<br /> | ||
|
||
<div> | ||
<div className="buttons"> | ||
<button | ||
onClick={ () => simulateError( editor2! ) } | ||
disabled={ !editor2 } | ||
> | ||
Simulate an error in second editor | ||
</button> | ||
</div> | ||
|
||
{ toolbarElement2 } | ||
|
||
<div className="flex"> | ||
{ editableElements2 } | ||
</div> | ||
</div> | ||
</> | ||
); | ||
}; | ||
|
||
const withCKCloud = withCKEditorCloud( { | ||
cloud: { | ||
version: '43.0.0', | ||
languages: [ 'en', 'de' ], | ||
premium: true | ||
} | ||
} ); | ||
|
||
const ContextMultiRootEditorDemo = withCKCloud( ( { cloud } ): JSX.Element => { | ||
const MultiRootEditor = useCKCdnMultiRootEditor( cloud ); | ||
|
||
return ( | ||
<CKEditorContext | ||
context={ MultiRootEditor.Context as any } | ||
contextWatchdog={ MultiRootEditor.ContextWatchdog as any } | ||
> | ||
<ContextEditorDemo editor={MultiRootEditor} /> | ||
</CKEditorContext> | ||
); | ||
} ); | ||
|
||
export default ContextMultiRootEditorDemo; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/** | ||
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved. | ||
* For licensing, see LICENSE.md. | ||
*/ | ||
|
||
import React, { type ReactNode } from 'react'; | ||
|
||
import { useCKCdnMultiRootEditor } from './useCKCdnMultiRootEditor.js'; | ||
import { | ||
useMultiRootEditor, withCKEditorCloud, | ||
type MultiRootHookProps, | ||
type WithCKEditorCloudHocProps | ||
} from '../../src/index.js'; | ||
|
||
type EditorDemoProps = WithCKEditorCloudHocProps & { | ||
data: Record<string, string>; | ||
rootsAttributes: Record<string, Record<string, unknown>>; | ||
}; | ||
|
||
const withCKCloud = withCKEditorCloud( { | ||
cloud: { | ||
version: '43.0.0', | ||
languages: [ 'de' ], | ||
premium: true | ||
} | ||
} ); | ||
|
||
const MultiRootEditorDemo = withCKCloud( ( { data, cloud }: EditorDemoProps ): ReactNode => { | ||
const MultiRootEditor = useCKCdnMultiRootEditor( cloud ); | ||
const editorProps: MultiRootHookProps = { | ||
editor: MultiRootEditor as any, | ||
data | ||
}; | ||
|
||
const { toolbarElement, editableElements } = useMultiRootEditor( editorProps ); | ||
|
||
return ( | ||
<> | ||
<h2 className="subtitle">Multi-root Editor Demo</h2> | ||
<p className="info"> | ||
This sample demonstrates the minimal React application that uses multi-root editor integration.<br /> | ||
You may use it as a starting point for your application. | ||
</p> | ||
<hr /><br /> | ||
|
||
<div> | ||
{ toolbarElement } | ||
|
||
{ editableElements } | ||
</div> | ||
</> | ||
); | ||
} ); | ||
|
||
export default MultiRootEditorDemo; |
Oops, something went wrong.