Skip to content

Latest commit

 

History

History
229 lines (175 loc) · 9.26 KB

ELEMENT.md

File metadata and controls

229 lines (175 loc) · 9.26 KB

Table of Contents

@bigmistqke/repl/element

Exports

<repl-runtime>

Initializes the Repl runtime by dynamically loading the required libraries (Babel and TypeScript) and any Babel presets/plugins defined in the props. Configures and instantiates ReplContext, which sets up FileSystem and TypeRegistry. The component ensures no children are rendered until all dependencies are fully loaded and the optional onSetup-callback has been completed.

It provides access for its children to its internal Runtime through the useRuntime-hook.

type ReplPropsBase = ComponentProps<'div'> &
  Omit<RuntimeConfig, 'transform' | 'transformModulePaths'>
interface ReplProps extends ReplPropsBase {
  /** Required module path transformer, such as `@bigmistqke/transform-module-path/typescript`, to resolve external modules and relative imports. */
  transformModulePaths: TransformModulePaths | Promise<TransformModulePaths>
  /** Required code transformer, such as `@bigmistqke/transform/babel`, for transpiling TypeScript to JavaScript. */
  transform: Transform | Promise<Transform>
}

Usage

import { Repl } from '@bigmistqke/repl'
import { typescriptTransformModulePaths } from '@bigmistqke/repl/transform-module-paths/typescript'
import { babelTransform } from '@bigmistqke/repl/transform/babel'
import { babelSolidReplPlugin } from '@bigmistqke/repl/plugins/babel-solid-repl'

const repl = (
  <Repl
    transformModulePaths={typescriptTransformModulePaths(import('https://esm.sh/typescript'))}
    transform={babelTransform({
      babel: import('https://esm.sh/@babel/standalone'),
      presets: ['babel-preset-solid'],
      plugins: [babelSolidReplPlugin],
    })}
    initialState={{
      files: {
        './index.ts': 'export const sum = (a: number, b: number) => a + b',
      },
    }}
  />
)

<repl-frame>

Manages individual <iframe/> containers for isolated execution environments.

/** Props for the Frame component */
interface FrameProps extends ComponentProps<'iframe'> {
  /** An identifier for the Frame. Defaults to `default`. */
  name?: string
  /** CSS properties as a string or JSX.CSSProperties object to apply to the `<iframe/>` body. */
  bodyStyle?: JSX.CSSProperties | string
}

Usage

import '@bigmistqke/repl/element'
import { Runtime } from '@bigmistqke/repl'

const repl = (
  <repl-runtime runtime={new Runtime(...)}>
    <repl-frame
      style={{ flex: 1 }}
      bodyStyle={{
        padding: '0px',
        margin: '0px',
      }}
    />
    <repl-devtools />
  </repl-runtime>
)

<repl-devtools>

DevTools embeds an iframe to provide a custom Chrome DevTools interface for debugging purposes, provided by chii and chobitus.

This component connects to a Frame with the same name prop to display and interact with the frame's runtime environment, including console outputs, DOM inspections, and network activities. If no name is provided it will default to default.

/** Props for the DevTools component */
interface DevToolsProps extends ComponentProps<'iframe'> {
  /** Unique name used to link the DevTools with a specific Frame. */
  name: string
}

Usage

import '@bigmistqke/repl/element'

// To debug a frame named 'example'
const repl = (
  <repl-runtime>
    <repl-frame name="example" />
    <repl-devtools name="example" />
  </repl-runtime>
)

Editors

The @bigmistqke/repl package offers integrations with various code editors, which are available as separate entry-points within the package. Currently, integrations are provided for two code editors:

  1. monaco-editor
  2. tm-textarea.

@bigmistqke/repl/element/monaco-editor

This package exports both the MonacoEditor and MonacoProvider component.

MonacoEditor embeds a monaco-editor instance for editing files. This editor supports integrated typing assistance, including auto-completions and type-checking, and offers the standard keybindings expected in code editors.

The MonacoProvider component is responsible for initializing Monaco and making it available to descendant components via context. This setup enables multiple instances of MonacoEditor to utilize a single Monaco instance. However, it is also possible to use MonacoEditor outside of a MonacoProvider. In this case, the MonacoEditor will instantiate a new Monaco instance instead of sharing the one provided by MonacoProvider.

You must provide the monaco and theme props to MonacoProvider. This flexibility allows users to import Monaco from a CDN or their own server, either statically or dynamically.

For MonacoEditor, providing monaco and theme is optional because it can function both inside and outside of MonacoProvider. If MonacoEditor is used outside of MonacoProvider, it requires monaco and theme props to be defined and will throw an error if they are missing. If MonacoEditor is used within a MonacoProvider, the provided monaco and theme props will be ignored with a warning.

Note: if you want to automatically import types of external packages you have to enable the importExternalTypes-prop of Repl.

interface MonacoProviderProps {
  /** Required static or dynamic import of `MonacoTheme`. Theme needs to be optimized to make use of TextMate. */
  theme: MonacoTheme | Promise<MonacoTheme>
  /** Required static or dynamic import of `Monaco` */
  monaco: Promise<Monaco> | Monaco
  /** Optional compiler options for typescript */
  tsconfig?: ts.CompilerOptions
}

type MonacoEditorPropsBase = ComponentProps<'div'> & MonacoProviderProps

interface MonacoEditorProps extends MonacoEditorPropsBase {
  /** Required path of the file in the virtual filesystem */
  path: string
  /** Optional callback that is executed when the editor is fully mounted */
  onMount?: (editor: MonacoEditor) => void
  /** Optional arguments to `monaco.editor.create()` */
  editor?: MonacoEditorConfig
}

Usage

If you use MonacoEditor outside of a MonacoProvider, it will instantiate its own Monaco instance. This can be useful for simple applications with only one editor, or when you need isolated Monaco instances.

import { Repl } from '@bigmistqke/repl'
import { MonacoEditor } from '@bigmistqke/repl/element/monaco-editor'
import loader from '@monaco-editor/loader'
import vs_dark from '@bigmistqke/repl/element/monaco-editor/themes/vs_dark_good.json'
import { createSignal } from 'solid-js'

const editor = <repl-monaco-editor path="src/index.tsx" monaco={loader.init()} theme={vs_dark} />

@bigmistqke/repl/element/tm-editor

TmEditor is a tiny, minimal text editor built on the tm-textarea syntax highlighting library, which utilizes TextMate grammar. Internally, it is composed of a standard <textarea/> with syntax-highlighted HTML rendered underneath.

In contrast to the MonacoEditor, TmEditor lacks type-checking and type-information capabilities, and it does not modify any existing key-bindings. As such, it is not ideal for full-featured playgrounds, but is well-suited for simpler applications such as articles and documentation.

interface TmEditorProps extends ComponentProps<'div'> {
  /** The default source code to initialize the editor with. */
  defaultValue?: string
  /** The path of the file in the virtual filesystem. */
  path: string
  /** The theme to apply for syntax highlighting. */
  theme: Theme
  /** The source code to be displayed and edited. */
  value: string
  /** Callback function to handle updates to the source code. */
  onInput?: (source: string) => void
}

Usage

import { Repl } from '@bigmistqke/repl'
import '@bigmistqke/repl/element/tm-editor'

const runtime = new Runtime()

const editor = <repl-tm-editor runtime={runtime()} path={currentPath()} theme="andromeeda" />