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

@aehrc/ecl-editor

v1.6.2

Published

Web Component for ECL editing with Monaco

Readme

@aehrc/ecl-editor

Web Component (<ecl-editor>) for editing SNOMED CT Expression Constraint Language (ECL) expressions with Monaco Editor.

Built on ecl-editor-core.

Install

npm install @aehrc/ecl-editor

Peer dependency: monaco-editor >= 0.40.0

Usage

Module

You supply monaco yourself, so you also configure its web worker. Without that, monaco waits on a worker that never loads and formatting takes ~1 s instead of ~15 ms - silently. See Monaco web workers below.

import * as monaco from 'monaco-editor';
import EditorWorker from 'monaco-editor/editor/editor.worker?worker'; // vite
import { defineEclEditor } from '@aehrc/ecl-editor';

self.MonacoEnvironment = {
  getWorker: () => new EditorWorker(),
};

// Assign monaco globally. The element checks `globalThis.monaco` first and
// otherwise polls for it for up to 30 seconds before falling back to a dynamic
// `import('monaco-editor')` - so skipping this costs a 30 s delay before the
// editor appears, even when monaco is already bundled.
(globalThis as any).monaco = monaco;

// Register the custom element (call once)
defineEclEditor();
<ecl-editor
  value="< 404684003 |Clinical finding|"
  fhir-server-url="https://tx.ontoserver.csiro.au/fhir"
  height="400px"
></ecl-editor>

Script Tag

When loaded via <script> (non-module), the element auto-registers as <ecl-editor>.

<script src="monaco-editor/min/vs/loader.js"></script>
<script src="ecl-editor/dist/index.js"></script>

<ecl-editor value="<< 404684003"></ecl-editor>

No worker setup is needed on this path - the AMD loader configures its own.

Monaco web workers

monaco-editor is a peer dependency, so wiring its web worker into your bundler is your responsibility. Skipping it is not fatal but is expensive and silent: on monaco 0.56.0, formatting takes ~1025 ms without the worker versus ~15-150 ms with it.

import EditorWorker from 'monaco-editor/editor/editor.worker?worker'; // vite

self.MonacoEnvironment = {
  getWorker: () => new EditorWorker(),
};

The specifier is monaco-editor/editor/editor.worker on monaco >= 0.56.0 and monaco-editor/esm/vs/editor/editor.worker on <= 0.55.x - 0.56.0 reorganised its ESM entry points. Webpack users can use monaco-editor-webpack-plugin instead, and the AMD loader needs nothing.

Full details, including why it matters, are in @aehrc/ecl-editor-core.

Attributes

| Attribute | Type | Default | Description | | --------------------- | --------- | --------------------------------------- | ------------------------------------------ | | value | string | '' | Editor content | | fhir-server-url | string | 'https://tx.ontoserver.csiro.au/fhir' | FHIR terminology server URL | | snomed-version | string | '' | SNOMED CT edition/version URI | | theme | string | 'vs' | Monaco theme, or 'auto' — see below | | light-theme | string | 'vs' | Theme used by theme="auto" in light mode | | dark-theme | string | 'vs-dark' | Theme used by theme="auto" in dark mode | | height | string | '300px' | Editor height | | width | string | '100%' | Editor width | | read-only | boolean | false | Read-only mode | | minimap | boolean | false | Show minimap | | gutter | string | 'full' | Gutter preset — see below | | line-numbers | string | 'on' | on, off, relative or interval | | glyph-margin | boolean | true | Show the glyph margin | | folding | boolean | true | Show folding controls | | semantic-validation | boolean | true | Enable semantic validation | | cors-proxy | string | | CORS proxy URL prefix |

Dark mode

The theme attribute takes any Monaco theme name (vs, vs-dark, hc-black, hc-light, or one you registered yourself), plus a special value auto:

<ecl-editor theme="auto"></ecl-editor>

auto follows the operating system's prefers-color-scheme and switches live when it changes — no reload or attribute update needed. It picks vs or vs-dark by default; point it at your own themes with light-theme and dark-theme:

<ecl-editor theme="auto" light-theme="my-light" dark-theme="my-dark"></ecl-editor>

The default is still vs, so existing embedders keep a light editor regardless of OS setting. Opt in with auto when you want the editor to follow the page.

The element's own chrome (the shortcut hints bar and resize handle) is recoloured to match, and an ecl-theme-change event fires whenever the resolved theme changes, so you can keep surrounding UI in sync. The current theme is also readable as a property:

document.querySelector('ecl-editor').resolvedTheme; // 'vs-dark'

Note: Monaco applies themes globally, so all editors on a page share one theme. Mixing a light and a dark <ecl-editor> on the same page is a Monaco limitation, not this component's.

Gutter

Monaco's left margin holds line numbers, the glyph margin (where the quick-fix lightbulb appears) and folding controls. For a compact single-expression input that margin is often wasted space, so gutter offers three presets:

| Preset | Line numbers | Glyph margin | Folding | Use for | | --------- | ------------ | ------------ | ------- | -------------------------------------- | | full | yes | yes | yes | Default — a full editing surface | | minimal | no | yes | no | Compact, but quick fixes still visible | | none | no | no | no | No left margin at all |

<ecl-editor gutter="none" height="60px"></ecl-editor>

none zeroes the reserved widths as well as hiding the content — setting line-numbers alone leaves Monaco still reserving the column.

The individual line-numbers, glyph-margin and folding attributes override whichever preset is in effect, so you can start from a preset and adjust one thing:

<!-- No glyph margin or folding, but keep relative line numbers -->
<ecl-editor gutter="none" line-numbers="relative"></ecl-editor>

Note: gutter="none" removes the glyph margin, which is where the quick-fix lightbulb renders. Quick fixes still work via Cmd+. / Ctrl+., but there is no lightbulb to click. Use minimal if you want a compact gutter that keeps it.

All of these attributes can be changed at runtime and take effect immediately.

Events

| Event | Detail | Description | | ------------------ | ----------------------------------- | ------------------------------------- | | ecl-change | { value: string } | Fired when editor content changes | | ecl-diagnostics | { diagnostics: CoreDiagnostic[] } | Fired when diagnostics update | | ecl-theme-change | { theme: string, dark: boolean } | Fired when the resolved theme changes |

document.querySelector('ecl-editor').addEventListener('ecl-change', (e) => {
  console.log('New value:', e.detail.value);
});

Keyboard Shortcuts

| Shortcut | Action | | -------------- | -------------------- | | Ctrl+Space | Autocomplete | | Shift+Alt+F | Format document | | Shift+Alt+T | Toggle display terms | | Cmd+. / Ctrl+. | Quick fix |

Autocomplete is Ctrl+Space on macOS too, not Cmd+Space (Spotlight). Current Monaco also binds Cmd+I / Ctrl+I and, on macOS, Option+Esc — useful when macOS has Ctrl+Space assigned to switching input sources.

Methods

| Method | Returns | Description | | ------------------ | ------------------ | ----------------------- | | format() | void | Format the document | | getDiagnostics() | CoreDiagnostic[] | Get current diagnostics |

Properties

| Property | Type | Description | | --------------- | -------- | ---------------------------------------------------------------- | | value | string | Editor content (get/set) | | resolvedTheme | string | The Monaco theme currently applied, after resolving auto (get) |

Storybook

cd packages/ecl-editor
npm run storybook

License

Copyright 2026 Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230

Apache License 2.0 — see LICENSE.