npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kong-ui-public/monaco-editor

v0.22.0

Published

A kong UI Monaco Editor wrapper for Vue 3 with syntax highlighting powered by Shiki.

Readme

@kong-ui-public/monaco-editor

A kong UI Monaco Editor wrapper for Vue 3 with syntax highlighting powered by Shiki.

Features

  • Vue 3 wrapper component for Monaco Editor
  • Syntax highlighting powered by Shiki
  • Two-way data binding with v-model
  • TypeScript support
  • Light and dark themes
  • Customizable toolbar with built-in and custom action buttons
  • Keyboard shortcuts support for actions
  • Configurable context menu integration
  • Customizable editor options
  • Loading and empty states with customizable slots
  • Composable API for advanced use cases
  • Vite plugin for optimized builds

Requirements

  • vue must be initialized in the host application
  • @kong/kongponents must be available as a dependency in the host application (for icons)

Usage

Install

Install the package in your host application

pnpm add @kong-ui-public/monaco-editor

Import the styles in your application:

import '@kong-ui-public/monaco-editor/dist/runtime/style.css'

or if you prefer css

@import "@kong-ui-public/monaco-editor/dist/runtime/style.css";

Register

You can register the MonacoEditor component globally or import it locally in your components.

Global Registration

import { createApp } from 'vue'
import { MonacoEditor } from '@kong-ui-public/monaco-editor'

const app = createApp(App)

app.component('MonacoEditor', MonacoEditor)

Local Registration

<script setup lang="ts">
import { MonacoEditor } from '@kong-ui-public/monaco-editor'
</script>

MonacoEditor Component

Props

appearance

  • type: 'embedded' | 'standalone'
  • required: false
  • default: 'embedded'

The appearance style of the Monaco Editor container.

  • embedded: minimal styling, intended to blend into the surrounding layout.
  • standalone: renders with an input-like border and adds extra editor padding for more comfortable editing.

theme

  • type: 'light' | 'dark'
  • required: false
  • default: 'light'

The theme of the Monaco Editor instance.

language

  • type: string
  • required: false
  • default: 'markdown'

The programming language for syntax highlighting. Supports all languages available in Shiki.

options

  • type: Partial<editor.IStandaloneEditorConstructionOptions>
  • required: false
  • default: undefined

Additional Monaco Editor options to customize the editor further. See Monaco Editor API for available options.

loading

  • type: boolean
  • required: false
  • default: false

Indicates that the editor is waiting for external data in addition to its own internal initialization.

[!WARNING] This prop does not control the Monaco Editor's initialization lifecycle.

The editor manages its own internal loading state while Monaco and syntax highlighting are being initialized. The loading prop is additive, it allows consumers to keep the loading overlay visible if additional async work (such as fetching content) is still in progress after the editor itself is ready.

The loading overlay is shown when either:

  • The editor is still initializing internally, or
  • The loading prop is set to true

showLoadingState

  • type: boolean
  • required: false
  • default: true

Controls whether the loading state overlay is rendered.

[!NOTE] This does not affect editor initialization. When set to false, the editor will still initialize and emit ready, but no loading UI will be displayed.

Useful for constrained layouts where the loading overlay would be visually disruptive.

showEmptyState

  • type: boolean
  • required: false
  • default: true

Controls whether the empty state overlay is rendered when the editor has no content.

[!NOTE] This does not affect editor initialization. When set to false, the editor will still initialize and emit ready, but no empty state UI will be displayed even if the content is empty.

Useful for embedded or compact layouts where the empty state overlay is unnecessary.

toolbar

  • type: MonacoEditorToolbarOptions
  • required: false
  • default: false

Configuration for the editor toolbar, which displays action buttons above the editor. The toolbar supports both built-in actions and custom user-defined actions.

Built-in Actions

The following built-in actions are available:

  • format: Formats the editor content using Monaco's formatter
  • bold: Toggles bold text (**text**) — markdown/mdc only
  • italic: Toggles italic text (_text_) — markdown/mdc only
  • strikethrough: Toggles strikethrough text (~~text~~) — markdown/mdc only
  • inlineCode: Toggles inline code (`code`) — markdown/mdc only
  • link: Inserts a link ([text](url)) — markdown/mdc only
  • image: Inserts an image (![alt](url)) — markdown/mdc only
  • unorderedList: Toggles unordered list prefix (- ) — markdown/mdc only
  • orderedList: Toggles ordered list prefix (1. , 2. , …) — markdown/mdc only
  • taskList: Toggles task list prefix (- [ ] ) — markdown/mdc only
  • search: Toggles the search/find widget
  • fullScreen: Toggles full-screen mode for the editor

You can enable built-in actions by setting them to true or customize them with configuration objects:

interface MonacoEditorToolbarOptions {
  actions?: {
    // Built-in actions
    format?: boolean | MonacoEditorActionConfig
    search?: boolean | MonacoEditorActionConfig
    fullScreen?: boolean | MonacoEditorActionConfig
    
    // Custom actions
    [key: string]: boolean | MonacoEditorActionConfig | undefined
  }
}
Markdown Shortcuts

When the editor language is markdown or mdc, the following keyboard shortcuts are automatically active:

  • List continuation on Enter: Pressing Enter at the end of a list item automatically continues the list on the next line with the appropriate prefix (- , 1. , - [ ] , etc.). Pressing Enter on an empty list item removes the prefix and ends the list.
Action Configuration

Each action can be configured with the following options:

interface MonacoEditorActionConfig {
  /** Unique identifier for the action */
  id: string
  
  /** Display label for the action */
  label?: string
  
  /** Icon component for the action button */
  icon?: Component
  
  /** Keybindings associated with the action (e.g., ['Command', 'Shift', 'F']) */
  keybindings?: string[]
  
  /**
   * The action to execute when the button is clicked.
   * Can be:
   * - A function that receives the editor composable instance
   * - A string ID of a Monaco editor command (e.g., 'editor.action.formatDocument')
   */
  action: string | ((editor: ReturnType<typeof useMonacoEditor>) => void)
  
  /** Where the action should appear in the toolbar */
  placement?: 'left' | 'center' | 'right' // default: 'left'
  
  /** Order of the action within its placement (lower numbers appear first) */
  order?: number // default: 100
  
  /** Group identifier for visual grouping with separators */
  group?: number | string
  
  /** Whether to show this action in the context menu (right-click) */
  showInContextMenu?: boolean // default: true
  
  /** Context menu group identifier */
  contextMenuGroupId?: string // default: 'navigation'
  
  /** Order of the action within its context menu group */
  contextMenuOrder?: number // default: 1
}
Keybindings

Actions can define keyboard shortcuts using the keybindings property. Keybindings are specified as an array of strings representing keys and modifiers.

Supported Modifiers:

  • Command, Cmd, Ctrl, CtrlCmd (maps to Cmd on Mac, Ctrl on Windows/Linux)
  • Shift
  • Alt, Option
  • Win, Meta

Supported Keys:

  • Letters: a-z (case-insensitive)
  • Digits: 0-9
  • Function keys: F1-F12
  • Special keys: Enter, Escape/Esc, Space, Tab, Backspace, Delete, Insert, Home, End, PageUp, PageDown
  • Arrow keys: Up, Down, Left, Right, ArrowUp, ArrowDown, ArrowLeft, ArrowRight

Examples:

keybindings: ['Command', 'S']           // Cmd+S (Mac) or Ctrl+S (Win/Linux)
keybindings: ['Ctrl', 'Shift', 'F']     // Ctrl+Shift+F
keybindings: ['Alt', 'Enter']           // Alt+Enter
keybindings: ['Command', 'K']           // Cmd+K (Mac) or Ctrl+K (Win/Linux)
Example: Basic Toolbar with Built-in Actions
<template>
  <MonacoEditor
    v-model="code"
    language="json"
    :toolbar="{
      actions: {
        format: true,
        search: true,
        fullScreen: true,
      },
    }"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { MonacoEditor } from '@kong-ui-public/monaco-editor'

const code = ref('{"hello": "world"}')
</script>
Example: Customized Built-in Actions
<template>
  <MonacoEditor
    v-model="code"
    language="json"
    :toolbar="{
      actions: {
        format: {
          placement: 'right',
          order: 1,
          keybindings: ['Command', 'Shift', 'F'],
        },
        search: {
          placement: 'right',
          order: 2,
        },
        fullScreen: {
          placement: 'right',
          order: 3,
          group: 'view',
        },
      },
    }"
  />
</template>
Example: Custom Actions
<template>
  <MonacoEditor
    v-model="code"
    language="json"
    :toolbar="{
      actions: {
        format: true,
        
        // Custom action with function
        validate: {
          id: 'validateJson',
          label: 'Validate JSON',
          icon: CheckCircleIcon,
          placement: 'right',
          keybindings: ['Command', 'K'],
          action: (editor) => {
            try {
              JSON.parse(editor.editor.value?.getValue() || '')
              alert('Valid JSON!')
            } catch (error) {
              alert('Invalid JSON: ' + error.message)
            }
          },
        },
        
        // Custom action with Monaco command ID
        copyContent: {
          id: 'copyAllContent',
          label: 'Copy All',
          icon: CopyIcon,
          placement: 'right',
          action: 'editor.action.clipboardCopyAction',
        },
      },
    }"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { MonacoEditor } from '@kong-ui-public/monaco-editor'
import { CheckCircleIcon, CopyIcon } from '@kong/icons'

const code = ref('{"hello": "world"}')
</script>
Example: Advanced Configuration with Groups
<template>
  <MonacoEditor
    v-model="code"
    language="typescript"
    :toolbar="{
      actions: {
        // Edit group on the left
        format: {
          placement: 'left',
          order: 1,
          group: 'edit',
        },
        
        // View group in the center
        search: {
          placement: 'center',
          order: 1,
          group: 'view',
        },
        fullScreen: {
          placement: 'center',
          order: 2,
          group: 'view',
        },
        
        // Custom actions on the right
        runCode: {
          id: 'runCode',
          label: 'Run Code',
          icon: PlayCircleIcon,
          placement: 'right',
          order: 1,
          keybindings: ['Command', 'Enter'],
          action: (editor) => {
            console.log('Running code:', editor.editor.value?.getValue())
          },
        },
      },
    }"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { MonacoEditor } from '@kong-ui-public/monaco-editor'
import { PlayCircleIcon } from '@kong/icons'

const code = ref('console.log("Hello, world!")')
</script>

Events

ready

Emitted when the Monaco editor instance has finished initializing and is ready for interaction.

This event reflects only the editor's internal readiness, not any external loading state controlled by the loading prop.

Payload:

  • editor: The Monaco IStandaloneCodeEditor instance.
Example
<template>
  <MonacoEditor
    v-model="code"
    language="javascript"
    @ready="onEditorReady"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import type { editor } from 'monaco-editor'

const code = ref('// your code here')

function onEditorReady(editorInstance: editor.IStandaloneCodeEditor) {
  // You can now use the Monaco editor instance
  editorInstance.focus()
}
</script>

v-model

The component requires a v-model binding to manage the editor content:

<MonacoEditor v-model="code" />

Slots

state-loading

Slot for customizing the loading state overlay. Receives isLoading as a slot prop.

<MonacoEditor v-model="code">
  <template #state-loading="{ isLoading }">
    <div v-if="isLoading">Custom loading...</div>
  </template>
</MonacoEditor>

state-empty

Slot for customizing the empty state overlay. Receives isEmpty as a slot prop.

<MonacoEditor v-model="code">
  <template #state-empty="{ isEmpty }">
    <div v-if="isEmpty">Custom empty state...</div>
  </template>
</MonacoEditor>

Usage Example

<template>
  <div class="editor-wrapper">
    <MonacoEditor
      v-model="code"
      :theme="isDark ? 'dark' : 'light'"
      appearance="standalone"
      language="json"
      :options="{
        readOnly: false,
        minimap: {
          enabled: false,
        },
      }"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { MonacoEditor } from '@kong-ui-public/monaco-editor'

const code = ref('{\n  "hello": "world"\n}')
const isDark = ref(false)
</script>

<style scoped>
.editor-wrapper {
  height: 500px;
  width: 100%;
}
</style>

MonacoEditorStatusOverlay Component

The MonacoEditorStatusOverlay component displays a centered overlay message within the Monaco Editor, typically used for status messages like loading, empty states, or error messages.

[!NOTE] The MonacoEditor component uses MonacoEditorStatusOverlay internally for two built-in states:

  • Loading state (state-loading slot): Shown while the editor is initializing or when the loading prop is true
  • Empty state (state-empty slot): Shown when the editor is ready but has no content

You can customize these by providing your own content in the respective slots, or use MonacoEditorStatusOverlay with custom props for consistent styling.

Props

title

  • type: string
  • required: true

The title to display in the overlay.

message

  • type: string
  • required: true

The message to display in the overlay.

icon

  • type: Component
  • required: false
  • default: undefined

An optional icon component to display above the title. Can be any Vue component, typically an icon from @kong/icons.

Usage Example

<template>
  <div class="editor-wrapper">
    <MonacoEditor
      v-model="code"
      language="json"
    >
      <template #state-loading>
        <MonacoEditorStatusOverlay
          title="Loading"
          message="Please wait while the editor is initializing..."
          :icon="SpinnerIcon"
        />
      </template>
    </MonacoEditor>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { MonacoEditor, MonacoEditorStatusOverlay } from '@kong-ui-public/monaco-editor'
import { SpinnerIcon } from '@kong/icons'

const code = ref('')
</script>

<style scoped>
.editor-wrapper {
  height: 500px;
  width: 100%;
  position: relative;
}
</style>

You can also use it for custom empty states:

<template>
  <MonacoEditor v-model="code">
    <template #state-empty>
      <MonacoEditorStatusOverlay
        title="No Content"
        message="Start typing to add content to the editor"
        :icon="DocumentIcon"
      />
    </template>
  </MonacoEditor>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { MonacoEditor, MonacoEditorStatusOverlay } from '@kong-ui-public/monaco-editor'
import { DocumentIcon } from '@kong/icons'

const code = ref('')
</script>

useMonacoEditor Composable

For advanced use cases, you can use the useMonacoEditor composable directly:

import { ref } from 'vue'
import { useMonacoEditor } from '@kong-ui-public/monaco-editor'

const editorRef = ref<HTMLElement | null>(null)
const codeRef = ref('// your code here')

const monacoEditor = useMonacoEditor(editorRef, {
  language: 'javascript',
  code: codeRef,
  theme: 'light',
  monacoOptions: {
    readOnly: false,
    minimap: {
      enabled: false,
    },
  },
})

// Access editor states
console.log(monacoEditor.editorStates.hasContent)
console.log(monacoEditor.editorStates.currentLanguage) // e.g. 'javascript'

// Access editor methods
monacoEditor.setContent('new content')
monacoEditor.focus()

Editor States

The editorStates object is a reactive object that provides the current state of the editor instance.

| Property | Type | Default | Description | |---|---|---|---| | editorStatus | 'loading' \| 'ready' | 'loading' | The current status of the editor instance. | | searchBoxIsRevealed | boolean | false | Whether the search box is currently visible. | | hasContent | boolean | false | Whether the editor currently contains any content. | | theme | 'light' \| 'dark' | 'light' | The current theme of the editor. | | currentLanguage | string | '' | The current language ID of the editor model. Reactively updated when the language changes (e.g. via setLanguage()). |

Example with Custom Actions

import { ref } from 'vue'
import { useMonacoEditor } from '@kong-ui-public/monaco-editor'
import type { MonacoEditorActionConfig } from '@kong-ui-public/monaco-editor'

const editorRef = ref<HTMLElement | null>(null)
const codeRef = ref('console.log("Hello")')

// Define custom actions
const customActions: MonacoEditorActionConfig[] = [
  {
    id: 'runCode',
    label: 'Run Code',
    keybindings: ['Command', 'Enter'],
    action: (editor) => {
      const code = editor.editor.value?.getValue()
      console.log('Executing:', code)
      eval(code)
    },
  },
  {
    id: 'clearConsole',
    label: 'Clear Console',
    keybindings: ['Command', 'K'],
    action: () => {
      console.clear()
    },
  },
]

const monacoEditor = useMonacoEditor(editorRef, {
  language: 'javascript',
  code: codeRef,
  actions: customActions,
  onReady: (editor) => {
    console.log('Editor is ready!', editor)
  },
})

// Register additional actions dynamically
setTimeout(() => {
  monacoEditor.registerActions([
    {
      id: 'customFormat',
      label: 'Custom Format',
      action: 'editor.action.formatDocument',
    },
  ])
}, 1000)

Example with Keyboard Commands

import { ref } from 'vue'
import { useMonacoEditor } from '@kong-ui-public/monaco-editor'

const editorRef = ref<HTMLElement | null>(null)
const codeRef = ref('# Markdown content')

const monacoEditor = useMonacoEditor(editorRef, {
  language: 'markdown',
  code: codeRef,
})

// Trigger built-in Monaco commands
function formatDocument() {
  monacoEditor.triggerKeyboardCommand('editor.action.formatDocument')
}

function toggleCommentLine() {
  monacoEditor.triggerKeyboardCommand('editor.action.commentLine')
}

function showSearchWidget() {
  monacoEditor.toggleSearchWidget()
}

Vite Plugin

This package includes a Vite plugin for optimized builds. The plugin reduces bundle size by allowing you to selectively include only the languages and features you need.

import { defineConfig } from 'vite'
import MonacoVitePlugin from '@kong-ui-public/monaco-editor/vite-plugin'

export default defineConfig({
  plugins: [
    MonacoVitePlugin({
      languages: ['json', 'yaml', 'javascript'],
      features: ['bracketMatching', 'comment', 'format'],
      shiki: {
        langs: ['json', 'yaml', 'javascript'],
        themes: ['catppuccin-latte', 'catppuccin-mocha'],
      },
    }),
  ],
})

For more details on configuration options, see the Vite Plugin README.

API Reference

Exported Components

import {
  MonacoEditor,              // Main editor component
  MonacoEditorStatusOverlay, // Status overlay component for loading/empty states
} from '@kong-ui-public/monaco-editor'

Exported Composables

import {
  useMonacoEditor,           // Core editor composable
} from '@kong-ui-public/monaco-editor'

Common Monaco Commands

These command IDs can be used with triggerKeyboardCommand() or as string values for action configurations:

Editing Commands

  • editor.action.formatDocument - Format the entire document
  • editor.action.formatSelection - Format the current selection
  • editor.action.commentLine - Toggle line comment
  • editor.action.addCommentLine - Add line comment
  • editor.action.removeCommentLine - Remove line comment
  • editor.action.blockComment - Toggle block comment
  • editor.action.indentLines - Indent current line(s)
  • editor.action.outdentLines - Outdent current line(s)
  • editor.action.copyLinesUpAction - Copy line up
  • editor.action.copyLinesDownAction - Copy line down
  • editor.action.moveLinesUpAction - Move line up
  • editor.action.moveLinesDownAction - Move line down
  • editor.action.deleteLines - Delete current line(s)

Search & Replace Commands

  • actions.find - Open find widget
  • editor.action.startFindReplaceAction - Open find and replace widget
  • actions.findWithSelection - Find with selection
  • editor.action.nextMatchFindAction - Find next match
  • editor.action.previousMatchFindAction - Find previous match

Selection Commands

  • editor.action.selectAll - Select all
  • editor.action.smartSelect.expand - Expand selection
  • editor.action.smartSelect.shrink - Shrink selection
  • editor.action.selectToBracket - Select to bracket

Clipboard Commands

  • editor.action.clipboardCopyAction - Copy
  • editor.action.clipboardCutAction - Cut
  • editor.action.clipboardPasteAction - Paste

Folding Commands

  • editor.fold - Fold current region
  • editor.unfold - Unfold current region
  • editor.foldAll - Fold all regions
  • editor.unfoldAll - Unfold all regions
  • editor.foldAllBlockComments - Fold all block comments
  • editor.foldAllMarkerRegions - Fold all marker regions

Quick Reference: Toolbar Configuration

Enable all built-in actions:

:toolbar="{ actions: { format: true, search: true, fullScreen: true } }"

Custom action with keyboard shortcut:

:toolbar="{
  actions: {
    myAction: {
      id: 'myAction',
      label: 'My Action',
      icon: MyIcon,
      keybindings: ['Command', 'K'],
      action: (editor) => { /* ... */ }
    }
  }
}"

Action with Monaco command:

:toolbar="{
  actions: {
    format: {
      action: 'editor.action.formatDocument'
    }
  }
}"

Positioning actions:

:toolbar="{
  actions: {
    left: { placement: 'left', order: 1, ... },
    center: { placement: 'center', order: 1, ... },
    right: { placement: 'right', order: 1, ... }
  }
}"

Grouping actions:

:toolbar="{
  actions: {
    action1: { group: 'edit', ... },
    action2: { group: 'edit', ... },
    action3: { group: 'view', ... }
  }
}"

Tips & Best Practices

  1. Use keybindings consistently: Follow platform conventions (Command on Mac, Ctrl on Windows/Linux) by using modifiers like Command, Ctrl, or CtrlCmd.

  2. Group related actions: Use the group property to visually separate different categories of actions in the toolbar.

  3. Provide labels for accessibility: Always include a label for toolbar actions to improve accessibility.

  4. Use built-in commands when possible: Monaco provides many built-in commands that are well-tested and optimized.

  5. Handle editor state: Check editor readiness and content state before performing actions that depend on editor content.

  6. Context menu integration: Set showInContextMenu: false for toolbar-only actions that don't make sense in the right-click context menu.