Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add editor options and wrapping component prop #45

Merged
merged 2 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,37 @@ const config: StorybookConfig = {

Use the `Playground` component in [MDX format](https://storybook.js.org/docs/writing-docs/mdx).

```jsx
```mdx
// MyComponent.stories.mdx
import { Playground } from 'storybook-addon-code-editor'

<Playground code="export default () => <h1>Hello</h1>;" />
```

<details>
<summary>Example with a wrapping component and modified editor options</summary>

```mdx
import { Playground } from 'storybook-addon-code-editor';

<Playground code="export default () => <h1>Hello</h1>;"} />
<Playground
defaultEditorOptions={{ minimap: { enabled: false } }}
WrappingComponent={(props) => (
<div style={{ background: '#EEE', padding: '10px' }}>{props.children}</div>
)}
code="export default () => <h1>Hello</h1>;"
/>
```

</details>

<details>
<summary>More advanced example</summary>

```jsx
```mdx
// MyComponent.stories.mdx
import { Playground } from 'storybook-addon-code-editor';
import * as MyLibrary from './index';
import \* as MyLibrary from './index';
import storyCode from './MyStory.source.tsx?raw';

// TypeScript might complain about not finding this import or
Expand All @@ -106,10 +123,10 @@ import MyLibraryTypes from '../dist/types.d.ts?raw';
monaco.editor.setTheme('vs-dark');
monaco.languages.typescript.typescriptDefaults.addExtraLib(
MyLibraryTypes,
'file:///node_modules/my-library/index.d.ts'
'file:///node_modules/my-library/index.d.ts',
);
}}
/>;
/>
```

</details>
Expand Down
33 changes: 33 additions & 0 deletions example/src/intro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,39 @@ ${code}

---

{(() => {
const code = `export default () => (
<h1 style={{ background: "#FFF", borderRadius: "8px", padding: "8px" }}>
Wrapped in a custom component with editor options (no minimap)
</h1>
);`;
const Wrapper = (props) => (
<div style={{ background: '#EEE', padding: '10px' }}>{props.children}</div>
);
return (
<Playground
defaultEditorOptions={{minimap: { enabled: false }}}
WrappingComponent={Wrapper}
code={`
/\* MDX:
import { Playground } from 'storybook-addon-code-editor';
const Wrapper = (props) => (
<div style={{ background: '#EEE', padding: '10px' }}>{props.children}</div>
);
<Playground
defaultEditorOptions={{minimap: { enabled: false }}}
WrappingComponent={Wrapper}
code="${code}"
/>
*/
${code}
`.trim()}
/>
);
})()}

---

{(() => {
const code = `
/\* MDX:
Expand Down
18 changes: 16 additions & 2 deletions src/Editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { getMonacoSetup } from './setupMonaco';

let monacoPromise: Promise<typeof Monaco> | undefined;

export type EditorOptions = Monaco.editor.IEditorOptions;

function loadMonacoEditor() {
const monacoSetup = getMonacoSetup();

Expand Down Expand Up @@ -38,7 +40,12 @@ function loadMonacoEditor() {

let fileCount = 1;

function createEditor(monaco: typeof Monaco, code: string, container: HTMLElement) {
function createEditor(
monaco: typeof Monaco,
code: string,
container: HTMLElement,
defaultEditorOptions?: EditorOptions,
) {
const uri = monaco.Uri.parse(`file:///index${fileCount++}.tsx`);

return monaco.editor.create(container, {
Expand All @@ -47,6 +54,7 @@ function createEditor(monaco: typeof Monaco, code: string, container: HTMLElemen
model: monaco.editor.createModel(code, 'typescript', uri),
overflowWidgetsDomNode: getMonacoOverflowContainer('monacoOverflowContainer'),
tabSize: 2,
...defaultEditorOptions,
});
}

Expand All @@ -55,6 +63,7 @@ interface EditorProps {
value: string;
modifyEditor?: (monaco: typeof Monaco, editor: Monaco.editor.IStandaloneCodeEditor) => any;
parentSize?: string;
defaultEditorOptions?: EditorOptions;
}

interface EditorState {
Expand All @@ -76,7 +85,12 @@ export default function Editor(props: EditorProps) {

Promise.all([containerPromise, loadMonacoEditor()]).then(([editorContainer, monaco]) => {
stateRef.monaco = monaco;
stateRef.editor = createEditor(monaco, props.value, editorContainer);
stateRef.editor = createEditor(
monaco,
props.value,
editorContainer,
props.defaultEditorOptions,
);

stateRef.editor.onDidChangeModelContent(() => {
const currentValue = stateRef.editor?.getValue();
Expand Down
16 changes: 13 additions & 3 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { createStore } from './createStore';
import Editor from './Editor/Editor';
import Editor, { EditorOptions } from './Editor/Editor';
import ErrorBoundary from './ErrorBoundary';
import Preview from './Preview';
export { setupMonaco } from './Editor/setupMonaco';
Expand All @@ -9,6 +9,7 @@ export interface StoryState {
code: string;
availableImports?: Record<string, Record<string, unknown>>;
modifyEditor?: React.ComponentProps<typeof Editor>['modifyEditor'];
defaultEditorOptions?: EditorOptions;
}

const store = createStore<StoryState>();
Expand Down Expand Up @@ -80,8 +81,13 @@ export function Playground({
code,
height = '200px',
id,
WrappingComponent: WrappingComponent,
...editorProps
}: Partial<StoryState> & { height?: string; id?: string }) {
}: Partial<StoryState> & {
height?: string;
id?: string;
WrappingComponent?: React.ComponentType<{ children: React.ReactNode }>;
}) {
let initialCode = code ?? '';
if (id !== undefined) {
savedCode[id] ??= initialCode;
Expand All @@ -93,11 +99,15 @@ export function Playground({
? currentCode
: "import * as React from 'react';" + currentCode;

const preview = (
<Preview availableImports={{ react: React, ...availableImports }} code={fullCode} />
);

return (
<div style={{ border: '1px solid #bebebe' }}>
<div style={{ margin: '16px 16px 0 16px', overflow: 'auto', paddingBottom: '16px' }}>
<ErrorBoundary resetRef={errorBoundaryResetRef}>
<Preview availableImports={{ react: React, ...availableImports }} code={fullCode} />
{WrappingComponent ? <WrappingComponent>{preview}</WrappingComponent> : preview}
</ErrorBoundary>
</div>
<div
Expand Down