Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

playground-elements

google7.8kBSD-3-Clause0.20.0TypeScript support: included

Serverless coding environments for the web

readme

playground-elements


Serverless coding environments for the web.





OverviewGetting StartedProject filesModule resolutionTypeScriptHiding & FoldingCustom layoutsBundlingSandbox securityComponentsStylingSyntax highlightingContributingFAQ

Overview

Playground Elements are a set of components for creating interactive editable coding environments on the web, with live updating previews. You can use Playground Elements to:

  • Embed editable code examples in your documentation.
  • Build interactive tutorials and example galleries.
  • Build full-featured coding sandboxes (think Glitch or JSBin).

🤯 No backend required

Unlike other coding environments, Playground never sends code to a backend server. Instead, Playground uses a Service Worker to create a virtual URL-space that runs 100% within the browser. If you can host static files, you can host a Playground.

TypeScript support

Playground automatically compiles .ts files using TypeScript, and automatically fetches typings for your imports in order to display errors. Compilation happens in a Web Worker on a separate thread, so your page stays responsive.

🧩 Web Components

Playground uses Web Components, so it doesn't require a framework. But it will play nicely with any framework you're already using, like React, Vue, and Angular.

🍱 Mix-and-match for flexible layout

Playground is broken up into small components like an editor, file picker, and preview. Mix-and-match components to create any layout you want, or just use <playground-ide> for an easy out-of-the-box experience.

🎨 Themable

Playground is fully themeable with CSS Custom Properties, down to the color of each kind of syntax-highlighted token. You can import themes from VSCode using the configurator, and it comes with a number of presets too.


Try the demo and configurator!


Getting Started

Install

Install from NPM:

npm i playground-elements
<script
  type="module"
  src="/node_modules/playground-elements/playground-ide.js"
></script>

Hello World

Create a <playground-ide> element in your HTML, and specify your project files inline:

<playground-ide editable-file-system line-numbers resizable>
  <script type="sample/html" filename="index.html">
    <!doctype html>
    <body>
      Hello
      <script type="module" src="./index.js">&lt;/script>
    </body>
  </script>

  <script type="sample/ts" filename="index.ts">
    document.body.appendChild(document.createTextNode("World!"))
  </script>
</playground-ide>

Serve

Use a server like @web/dev-server to handle bare module import resolution automatically:

npm i -D @web/dev-server
npx web-dev-server --node-resolve --watch

Or, use a tool like Rollup to resolve bare module imports to paths at build time. If you need more help with building and serving, check out the Modern Web Guides.

Compatibility

Playground is supported by all modern browsers. It requires support for custom elements, JS modules, service workers, and web workers.

    Supported:   Supported Chrome     Supported Firefox     Supported Safari     Supported Edge

Unsupported:   Unsupported Internet Explorer

Project files

There are 3 ways to specify the files of a playground project:

Option 1: Inline scripts

Add one or more <script> tags as children of your <playground-ide> or <playground-project>, using the following attributes:

Attribute Description
type Required filetype. Options: sample/html, sample/css, sample/js, sample/ts, sample/json, sample/importmap.
filename Required filename.
label Optional label for display in playground-tab-bar. If omitted, the filename is displayed.
hidden If present, the file won't be visible in playground-tab-bar.
selected If present, this file's tab will be selected when the project is loaded. Only one file should have this attribute.
preserve-whitespace Disable the default behavior where leading whitespace that is common to all lines is removed.

Be sure to escape closing </script> tags within your source as &lt;/script>.

<playground-project>
  <script type="sample/html" filename="index.html">
    <!doctype html>
    <head>
      <script type="module" src="javascript.js">&lt;/script>
      <script type="module" src="typescript.js">&lt;/script>
      <link rel="stylesheet" href="styles.css">
    </head>
    <body>
      <p>Hello World!</p>
    </body>
  </script>

  <script type="sample/js" filename="javascript.js">
    console.log('hello from javascript');
  </script>

  <script type="sample/ts" filename="typescript.ts">
    console.log('hello from typescript');
  </script>

  <script type="sample/css" filename="styles.css">
    body { color: blue; }
  </script>
</playground-project>

Option 2: JSON configuration

Set the project-src attribute or projectSrc property to a JSON file with format:

Property Description
files An object mapping filenames to file data.
files.content Optional text content of the file. If omitted, a fetch is made to retrieve the file by filename, relative to the manifest URL.
files.contentType Optional MIME type of the file. If omitted, type is taken from either the fetch response Content-Type header, or inferred from the filename extension when content is set.
files.label Optional label for display in playground-tab-bar. If omitted, the filename is displayed.
files.hidden If true, the file won't be visible in playground-tab-bar.
files.selected If true, this file's tab will be selected when the project is loaded. Only one file should have this field set.
extends Optional URL to another JSON config file to extend from. Configs are deeply merged. URLs are interpreted relative to the URL of each extendee config.
cdnBaseUrl Optional URL for the underlying npm CDN base url. Confirmed tested are htts://unpkg.com and https://cdn.jsdelivr.net/npm
<playground-ide project-src="/path/to/my/project.json"> </playground-ide>
{
  "files": {
    "index.html": {},
    "typescript.ts": {
      "content": "console.log('hello');"
    },
    "javascript.js": {
      "contentType": "text/javascript"
    },
    "styles.css": {
      "label": "Style"
    }
  }
}

Option 3: Config property

In JavaScript, directly set the config property to an object. The format is identical to the JSON config file.

const ide = document.querySelector('playground-ide');
ide.config = {
  files: {
    'index.html': {},
    'typescript.ts': {
      content: "console.log('hello');",
    },
  },
};

If both project-src and config are set, then the one set most recently has precedence. When either are set, inline scripts are ignored.

Module resolution

By default, bare module specifiers in JavaScript and TypeScript files are transformed to special ./node_modules/ URLs, and fetched behind-the-scenes from unpkg.com by default at the latest version.

// What you write:
import {html} from 'lit';

// What playground serves:
import {html} from './node_modules/lit@2.0.2/index.js';

// What playground fetches behind-the-scenes unless you set `cdnBaseUrl`:
// https://unpkg.com/lit@latest

package.json

To customize the version of a module you import, create a file called package.json in your project containing a dependencies map. This works exactly like it does when using NPM locally.

{
  "dependencies": {
    "lit": "^2.0.2"
  }
}

TIP: Use the hidden attribute or property to hide the package.json file from being displayed in the list of project files, if you don't want the end-user to be able to see or modify it.

Export conditions

Playground supports Node-style export conditions when resolving modules in dependencies, and sets the following conditions: module, import, development, and browser.

Import maps

For full control over module resolution, you can configure an import map. You may want to do this to change CDNs or point to a locally served copy of a module:

{
  "files": { ... },
  "importMap": {
    "imports": {
      "lit": "https://cdn.skypack.dev/lit@^2.0.2",
      "lit/": "https://cdn.skypack.dev/lit@^2.0.2/"
    }
  }
}

When using inline project files, you can specify your import map like so:

<playground-ide>
  <script type="sample/importmap">
    {
      "imports": {
        "lit": "https://cdn.skypack.dev/lit@^2.0.2",
        "lit/": "https://cdn.skypack.dev/lit@^2.0.2/"
      }
    }
  </script>
  ...
</playground-ide>

If an import map is defined, but does not contain an entry for a bare module, then playground defaults to the unpkg.com URL unless cdnBaseUrl is set.

TypeScript

Playground automatically compiles .ts, .tsx, and .jsx files using TypeScript.

The following compiler settings are used:

Name Value
target es2021
module esnext
moduleResolution nodenext
experimentalDecorators true
allowJs true
jsx react

Note that when you import from another project module, the import statement should use the .js extension (the same as you would do when running tsc locally):

import './my-other-module.js';

You may also include any Definitely Typed (@types) packages for type checking during compilation by listing it as a dependency in the project's package.json file.

Hiding & folding

If a region of code in a Playground project file is surrounded by playground-hide and playground-hide-end comments, then that region won't be visible or editable by the user, but it will still be compiled and served.

Similarly, if a region is surrounded by playground-fold and playground-fold-end comments, then the region will be replaced with a that expands to reveal the original editable code when clicked.

Use these special regions to help users focus on a particular part of a file, by de-emphasizing boilerplate or unrelated code.

JavaScript fold example

Note that JavaScript // style comments are not supported.

/* playground-fold */
import {html, LitElement} from 'lit';
/* playground-fold-end */

class MyElement extends LitElement {
  render() {
    return html`Hello <slot></slot>!`;
  }
}
/* playground-fold */

customElements.define('my-element', MyElement);

Result:

HTML hide example

<!-- playground-hide -->
<head>
  <title>Boring stuff</title>
  <script type="module" src="./my-element.js"></script>
</head>
<body>
<!-- playground-hide-end -->
<my-element>World</my-element>
<!-- playground-hide -->
</body>
<!-- playground-hide-end -->

Result:

Disabling

Hiding and folding is enabled by default, but can be disabled by setting the pragmas property to "off" (disabled with comments hidden) or "off-visible" (disabled with comments visible). The pragmas property is available on ide, file-editor, and code-editor.

Custom layouts

<playground-ide> provides a complete out-of-the-box experience that's a good start for many use-cases, but you can mix-and-match the various Playground sub-components to make your custom layouts.

For example, say we need a layout with an editor above, a preview below, and only one particular file from the project visible — like this:

To do this, first import just the components you need. The main playground-elements import loads all Playground elements, but when making a custom layout it's a good idea to only load the sub-components you're actually using. This will make your JavaScript bundle smaller.

<script type="module">
  import 'playground-elements/playground-project.js';
  import 'playground-elements/playground-file-editor.js';
  import 'playground-elements/playground-preview.js';
</script>

Next create a <playground-project>, with some inline project files. We could also write our project files separately, and specify them in a JSON manifest. This project element manages the virtual file system, and coordinates with the Playground workers. We give it a unique id, which we'll use to connect up the editor and preview.

<playground-project id="project1">
  <script type="sample/ts" filename="index.ts">
    window.addEventListener('DOMContentLoaded', () => {
      const world = document.createTextNode(' World!');
      document.body.appendChild(world);
    });
  </script>

  <script type="sample/html" filename="index.html">
    <!doctype html>
    <head>
      <script type="module" src="./index.js">&lt;/script>
    </head>
    <body>Hello</body>
  </script>
</playground-project>

Next create an editor and preview. Connect both to the project by setting the property attribute to the project element's id. We could also directly set the project property to the project element, if we were using JavaScript.

By setting the filename attribute on the editor, we've pinned it to one particular file. Since we didn't include a <playground-tab-bar>, there's no way for the user to see or switch to other files in the project.

<div class="example">
  <playground-file-editor
    project="project1"
    filename="index.ts"
  ></playground-file-editor>

  <playground-preview project="project1"> </playground-preview>
</div>

Finally, add a little style:

<style>
  .example {
    width: 500px;
    border: 1px solid #ccc;
  }
  .example > playground-file-editor {
    height: 110px;
  }
  .example > playground-preview {
    height: 100px;
    border-top: 1px solid #ccc;
    --playground-preview-toolbar-background: #eaeaea;
  }
</style>

Bundling

Playground uses a Web Worker to perform TypeScript compilation. If you are bundling or otherwise modifying the layout of the playground-elements NPM package, you may need to add special handling for this file.

Rollup

Use the Rollup @web/rollup-plugin-import-meta-assets plugin to automatically copy the worker script into the correct location. See examples/rollup for an example configuration.

Webpack

Webpack 5+ automatically supports loading Web Workers with no additional plugins. See examples/webpack for an example configuration.

Other

If you are bundling in another way, you'll need to configure your build so that the file node_modules/playground-elements/playground-typescript-worker.js is copied into the same directory as your bundle.

For example, if you bundled playground elements into ./js/app.js, then you should copy the worker module to ./js/playground-typescript-worker.js.

Sandbox security

⚠️ Changing the sandbox base URL from the default can create a security vulnerability for your site if not done carefully. Do not change the default unless you have a specific reason to, and please read this entire section carefully.

The sandboxBaseUrl property and sandbox-base-url attribute can be used to override the origin where untrusted code will execute when displaying Playground previews. The default origin is unpkg.com, which is secure because it is unprivileged and cannot modify the host window.

You may wish to override this default sandbox base URL if you do not want a dependency on unpkg.com, e.g. for isolation from outages, or because your network does not have access to it. Note that Playground currently also uses unpkg.com by default (unless you set cdnBaseUrl) to retrieve imported bare modules that are not otherwise handled by an import map, so to remove the dependency on unpkg, you should also set cdnBaseUrl. See the API docs for more info.

Background

Playground previews work by using a service worker. This service worker takes control over requests to a particular URL space, allowing it to respond to HTTP requests using the files from your local project, instead of from a remote server. The playground preview component contains an <iframe> pointing to the index.html within that URL space.

When JavaScript in this preview <iframe> executes, it does so with the full privileges of whichever origin the service worker was registered on. This means it can access cookies on that origin, make HTTP requests to sensitive URLs on that origin, and directly access the <iframe> parent window if it has the same origin.

The JavaScript in Playground project files should always be considered untrusted and potentially malicious. This is particularly the case if you implement a share feature, because a user can be tricked into executing malicious code simply by visiting a URL.

By default, the sandbox base URL is https://unpkg.com/playground-elements@<version>/playground-projects/. This is a secure default because unpkg.com is unprivileged and cannot modify the host window.

Requirements

If you change the sandbox base URL from the default, ensure that the new URL meets all of the following requirements:

  1. Must be a different origin to the origin hosting the Playground components. This prevents untrusted code from modifying the parent window using window.parent, e.g. to change your sign-in link to a malicious URL.

    NOTE: It is highly recommended to furthermore use either an entirely different site, or to use the Origin-Agent-Cluster header, to improve performance and prevent lockups. See Process isolation for more information.

  2. Must not have access to any sensitive cookies. This prevents untrusted code from e.g. reading and forwarding your user's authentication token.

  3. Must not have access to any sensitive resources or APIs, either through the same-origin policy, or through CORS headers that grant the origin access to resources on other origins. This prevents untrusted code from e.g. making a request to your get_credit_card or change_password APIs.

  4. Must serve the following two pre-minified files from the playground-elements NPM package at the same version as your imported components:

    • playground-service-worker.js
    • playground-service-worker-proxy.html

Process isolation

Some browsers such as Chrome are sometimes able to allocate a separate process or thread for iframes. This is highly desirable for Playground, because it improves responsiveness and prevents full lockups (resulting from e.g. an infinite loop accidentally written by a user).

By default, this iframe process isolation can only occur if the iframe and the parent window are different sites. While an origin is defined by (protocol + subdomain + top-level domain + port), a site is defined only by (protocol + top-level domain). For example, example.com and foo.example.com are different-origin but same-site, whereas example.com and example.net are different-origin and different-site.

Alternatively, if the Origin-Agent-Cluster: ?1 header is set on all server responses from one or the other origins, then iframe process isolation can also occur with different-origin but same-site configurations. Note that this header must truly be set on all responses from the origin, because the browser will remember the setting based on the first response it gets from that origin. See "Requesting performance isolation with the Origin-Agent-Cluster header" for more information about this header.

Components

<playground-ide><playground-project><playground-file-editor><playground-code-editor><playground-preview><playground-tab-bar><playground-file-system-controls>


<playground-ide>

All-in-one project, editor, file switcher, and preview with a horizontal side-by-side layout.

Properties

Name Type Default Description
projectSrc string undefined URL of the project manifest to load
config ProjectManifest undefined Get or set the project configuration and files, (details).
cdnBaseUrl string "" Change the underlying npm CDN base url. Confirmed tested are htts://unpkg.com and https://cdn.jsdelivr.net/npm. Note: Default "" resolves to https://unpkg.com
lineNumbers boolean false Render a gutter with line numbers in the editor
lineWrapping boolean false If true, long lines are wrapped, otherwise the editor will scroll.
editableFileSystem boolean false Allow adding, removing, and renaming files
resizable boolean false Allow dragging the line between editor and preview to change relative sizes
sandboxBaseUrl string module parent directory Base URL for untrusted JavaScript execution (⚠️ use with caution, see sandbox security). Resolved relative to the module containing the definition of <playground-project>.
pragmas "on" | "off" | "off-visible" "on" How to handle playground-hide and playground-fold comments (details).
modified boolean false Whether the user has modified, added, or removed any project files. Resets whenever a new project is loaded.
htmlFile string "index.html" The HTML file used in the preview.
noCompletions boolean false If interactive code completions should be shown. This setting only applies to TypeScript files.

Slots

Name Description
default Inline files (details)

<playground-project>

Invisible element that coordinates the filesystem, build worker, and service worker. Unless you're using <playground-ide>, all Playground layouts need a project element.

Properties

Name Type Default Description
projectSrc string undefined URL of a project files manifest to load.
config ProjectManifest undefined Get or set the project configuration and files, (details).
cdnBaseUrl string "" Change the underlying npm CDN base url. Confirmed tested are htts://unpkg.com and https://cdn.jsdelivr.net/npm. Note: Default "" resolves to https://unpkg.com
sandboxScope string "playground-elements" The service worker scope to register on.
sandboxBaseUrl string module parent directory Base URL for untrusted JavaScript execution (⚠️ use with caution, see sandbox security). Resolved relative to the module containing the definition of <playground-project>.
diagnostics Map<string, lsp.Diagnostic> undefined Map from filename to array of Language Server Protocol diagnostics resulting from the latest compilation.
modified boolean false Whether the user has modified, added, or removed any project files. Resets whenever a new project is loaded.

Methods

Method Description
addFile(filename: string) Create a new file. Type is inferred from filename extension.
deleteFile(filename: string) Delete a file.
renameFile(oldName: string, newName: string) Rename a file.

Slots

Name Description
default Inline files (details)

Events

Event Description
filesChanged A file was added, removed, or renamed.
urlChanged The preview URL has changed
compileStart A build has started.
compileEnd A build has completed.

<playground-tab-bar>

Properties

Property Type Default Description
project string | PlaygroundProject undefined The project this bar is associated with. Either the <playground-project> itself, or its id in the host scope.
editor string | PlaygroundFileEditor undefined The editor this bar controls. Either the <playground-file-editor> itself, or its id in the host scope.
editableFileSystem boolean false Allow adding, removing, and renaming files

<playground-file-editor>

Properties

Name Type Default Description
project string | PlaygroundProject undefined The project that this editor is associated with. Either the <playground-project> node itself, or its id in the host scope.
filename string undefined The name of the project file that is currently being displayed. Set when changing tabs. Does not reflect to attribute.
type "js" | "ts" | "html" | "css" undefined File type.
lineNumbers boolean false Render a gutter with line numbers in the editor
pragmas "on" | "off" | "off-visible" "on" How to handle playground-hide and playground-fold comments (details).
readonly boolean false Do not allow edits
noCompletions boolean false If interactive code completions should be shown. This setting only applies to TypeScript files.

<playground-code-editor>

A pure text editor based on CodeMirror with syntax highlighting for HTML, CSS, JavaScript, and TypeScript.

Properties

Name Type Default Description
value string "" Code as string
type "js" | "ts" | "html" | "css" undefined Language of the file to syntax highlight
readonly boolean false Do not allow edits
lineNumbers boolean false Render a gutter with line numbers in the editor
pragmas "on" | "off" | "off-visible" "on" How to handle playground-hide and playground-fold comments (details).
documentKey object undefined Editor history for undo/redo is isolated per documentKey. Default behavior is a single instance.
noCompletions boolean false If interactive code completions should be shown. This setting only applies to TypeScript files.

Events

Event Description
change User made an edit to the active file

Keyboard shortcuts

The playground code editor extends the CodeMirror default keyboard shortcuts with the following:

Keyboard shortcut Description
Ctrl + Space Trigger code completion when supported
Ctrl + / or Cmd + / Toggle line comments
ESC De-focus the code editor

<playground-preview>

Properties

Name Type Default Description
project string PlaygroundProject undefined The project that this editor is associated with. Either the <playground-project> node itself, or its id in the host scope.
location string ""
htmlFile string "index.html" The HTML file used in the preview.
iframe HTMLIFrameElement | null null A reference to the internal iframe element that is used to render the preview.

<playground-file-system-controls>

Floating controls for adding, deleting, and renaming files.

Properties

Name Type Default Description
state "closed" | "menu" | "rename" | "newfile" "closed" The kind of control to display.

closed: Hidden.
menu: Menu with "Rename" and "Delete" items.
rename: Control for renaming an existing file.
newfile: Control for creating a new file.
filename string undefined When state is menu or newfile, the name of the relevant file.
anchorElement HTMLElement undefined Absolutely position these controls at the bottom-left corner of this element.

Events

Event Detail Description
newFile {filename: string} The specified new file was created through these controls.

Styling

TIP: Use the configurator to quickly experiment with themes and other customizations.

Custom Properties

Name Default Description
--playground-bar-height 40px height of the tab bar and the preview bar
--playground-code-font-family monospace font-family of code in the editor
--playground-code-font-size 14px font-size of code in the editor
--playground-code-line-height 1.4em line-height of code in the editor
--playground-code-TOKEN-color various Color of each kind of TOKEN in syntax highlighted-code. See the syntax highlighting section for details.
--playground-highlight-color #6200EE Color of the active file-picker tab label and indicator, and the preview loading bar
--playground-code-background #FFFFFF background of the code editor
--playground-code-gutter-background var(--playground-code-background, #FFFFFF) background of the line-numbers gutter
--playground-code-gutter-box-shadow none box-shadow of the line-numbers gutter
--playground-code-gutter-border-right none border-right of the line-numbers gutter
--playground-code-linenumber-color #767676 color of line-numbers
--playground-code-cursor-color var(--playground-code-default-color, #000000) color of the cursor
--playground-code-selection-background #D7D4F0 background of selected text
--playground-code-padding 0 padding around the editor code block
--playground-code-line-padding 0 4px padding around each line of code
--playground-tab-bar-background #EAEAEA background of the file-picker tab bar
--playground-tab-bar-active-background transparent background of the active file-picker tab
--playground-tab-bar-foreground-color #000000 Text color of inactive file-picker tabs
--playground-tab-bar-active-color var(--playground-highlight-color, #6200EE) Text color of active file-picker tab
--playground-tab-bar-indicator-color var(--playground-highlight-color, #6200EE) color of active file-picker tab indicator (use transparent to hide)
--playground-tab-bar-font-size 14px font-size of tab titles in the file-picker tab bar
--playground-preview-toolbar-background #FFFFFF background of the preview toolbar
--playground-preview-toolbar-foreground-color #444444 Text color of the preview toolbar
--playground-border 1px solid #DDDDDD Outer and inner border
--playground-floating-controls-highlight-color var(--playground-highlight-color, #6200EE) Highlight color of popup controls buttons and inputs

Shadow Parts

The following CSS shadow parts are exported, which you can style with additional rules not covered by the above CSS custom properties.

Part name Exported by Description
tab-bar ide Tab bar file switcher
editor ide Editor
preview ide Preview
preview-toolbar ide, preview Preview top bar
preview-location ide, preview Preview top bar "Result" heading
preview-reload-button ide, preview Preview top bar reload button
preview-loading-indicator ide, preview Preview top bar horizontal loading indicator
diagnostic-tooltip ide, file-editor, code-editor The tooltip that appears when hovering over a code span that has an error
dialog ide, file-editor, code-editor Dialogs appearing on top of a component (e.g. the editor keyboard help modal that shows on keyboard focus)

Syntax highlighting

Themes

The playground-elements package includes a directory of pre-configured syntax-highlighting themes. To load a theme, import its stylesheet, and apply the corresponding class name to the playground element or one of its ancestors:

<import
  rel="stylesheet"
  src="/node_modules/playground-elements/themes/ayu-mirage.css"
>
  <playground-ide class="playground-theme-ayu-mirage"></playground-ide
></import>

A .js file is also provided for each theme, which exports a Lit CSSResult. You can include this directly in the static styles of your own Lit components, or get a CSSStyleSheet or string representation for other use cases:

import ayuMirageTheme from 'playground-elements/themes/ayu-mirage.css.js';

ayuMirageTheme; // Lit CSSResult
ayuMirageTheme.styleSheet; // CSSStyleSheet
ayuMirageTheme.cssText; // string

Custom syntax highlighting

Each kind of language token is controlled by a CSS custom property with the name --playground-code-TOKEN-color. For example, the keyword token is controlled by --playground-code-keyword-color.

Token Default JS/TS HTML CSS
default #000000 {}[]; <p>foo</p> {}:;
atom #221199 true &amp; bold
attribute #0000CC | <foo bar> @media screen { }
builtin #3300AA | #id { }
callee #000000 func() | calc()
comment #AA5500 // foo <!-- foo --> /* foo */
def #0000FF let foo = bar
/**@param {string} foo*/
| @media
keyword #770088 class | blue
meta #555555 | <!doctype html>
number #116644 4 | 4px
operator #000000 = |
property #000000 class foo { bar; } | color:
qualifier #555555 | .class { }
string #AA1111 "foo" <a b="c"> content: "foo"
string-2 #FF5500 `foo`
/foo/
| zoom: 50% 1
tag #117700 /**@param {string} foo*/ <foo> div { }
type #008855 let foo: string
/**@param {string} foo*/
|
variable #000000 let foo = bar | @keyframes spin { }
variable-2 #0055AA (arg) => { arg } 2 |
variable-3 #008855 | ::hover
local #0000FF (arg) => { }

Notes

  1. In CSS, string-2 is used for "non-standard" properties, but the list is outdated.
  2. In JS/TS, variable-2 is used for function-local variables.

Parsers

Playground uses the google_modes CodeMirror syntax highlighting modes for TS/JS/HTML, because they support highlighting of HTML and CSS within JavaScript tagged template literals.

Contributing

Contributions are very welcome.

For substantial changes, please file an issue first to discuss the changes. For small changes, sending a PR immediately is fine.

Initialize the repo:

git clone git@github.com:google/playground-elements.git
cd playground-elements
npm i
npm run build

Launch the configurator/demo locally and build continuously:

npm run serve --watch

FAQ

How do I save and share a project?

Use the config property of a <playground-ide> or <playground-project> to get or set the current state of the project (details).

How you persist and retrieve serialized project state is up to you. Here are a few ideas:

  • JSON + base64url encode the config, and save it to the URL hash.

    Note that built-in btoa function is not safe for this purpose because it cannot encode non-latin code points, and the + character has a special meaning in URLs. See here for an example safe implementation, and #102 to track adding this implementation to Playground itself.

  • Integrate with a third-party API like GitHub gists.

  • Write to your own datastore.

How do I run custom build steps like JSX or SASS?

Support for build plugins like JSX, SASS, and CSS modules are on the roadmap, but are not yet available. Follow and comment on #66.

Why isn't module resolution working?

There are currently some missing features in module resolution that you might be hitting. Please comment on the issue if it affects you:

  • Imports in HTML files are not transformed (#93)
  • The import map scopes field is not supported (#103)

changelog

Change Log

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

[0.20.0] - 2025-03-31

Added

  • Implement cdnBaseUrl property to allow changing the underlying npm CDN base url. See README for more information.

Fixed

  • Make playground-elements more resilient to 404's from the CDN by not throwing errors when they occur. Instead, log a warning and continue to load the rest of the project.

[0.19.1] - 2024-08-19

Fixed

  • Fix broken import of typescript.js module

[0.19.0] - 2024-08-19

Changed

  • Upgraded to TypeScript 5.2 and Lit 3.0
  • BREAKING Use modules in workers. See caniuse.com's support table for browser support information.
  • Updated comlink, fuse.js, and tslib dependencies.

0.18.1 - 2023-08-10

Fixed

  • Fix tab-to-spaces conversion in the code editor which was resulting in one less space being produced on tab than desired.

0.18.0 - 2023-05-25

Changed

0.17.1 - 2023-04-25

Added

  • Fetch all @types packages listed in the project's package.json file and include them for TypeScript compilation. This allows type-checking packages that do not ship their own types but do have a DefinitelyTyped package available. Note: This does not automatically download the @types package for a package. It must be manually listed in package.json.

0.17.0 - 2022-11-11

Changed

  • Replaced vscode-languageserver dependency with smaller vscode-languageserver-protocol.
  • TypeScript version upgraded from 4.4.4 to 4.8.4.
  • PlaygroundConnectedElement project is now permitted to be undefined according to TypeScript.
  • Upgrade codemirror from 5.63.0 to 5.65.9.
  • BREAKING Switched TypeScript moduleResolution from esnext to nodenext.
  • BREAKING Bumped TypeScript target from es2017 to es2021.
  • BREAKING The local package.json is now passed to TypeScript for compilation, and the default value of the type field is modified to module.

0.16.3 - 2022-08-02

Added

  • Added styntax highlighting for jsx and tsx modules.

0.16.2 - 2022-06-16

Added

  • Added support for compiling jsx and tsx modules.

0.16.1 - 2022-05-17

Changed

  • Upgraded MWC dependencies.

0.16.0 - 2022-05-11

Changed

  • BREAKING Added browser to the set of export conditions used during module resolution.

0.15.5 - 2022-05-06

Added

  • Added lineWrapping property (line-wrapping attribute) to <playground-code-editor>, <playground-file-editor> and <playground-ide> which when enabled wraps long lines, otherwise the editor will scroll. Off by default.

Fixed

  • Fix typo in README. Add missing forward slash in escaped script tag.

0.15.4 - 2022-04-05

Added

  • Add the ability to select a file by setting selected: true in a project config, or by setting the selected attribute on slotted children.

0.15.3 - 2022-03-29

Fixed

  • Fixed the hiding of comments that surround a fold/hide code block from creating invisible readonly regions.

  • Refactored fold/hide marker logic so it doesn't add document history when clearing the prior fold/hide markers.

  • Fix typo and incorrectly documented event name in README. changed event should instead be change.

0.15.2 - 2022-03-24

Added

  • Make hidden code blocks readonly to prevent accidental erasure.

  • Added Ctrl+/ or Cmd+/ hotkey for toggling line comments.

  • Added keyboard shortcut documentation to the playground-code-editor README.

0.15.1 - 2022-03-16

Changed

  • playground-preview now exposes the internal iframe via the iframe property.

0.15.0 - 2022-03-07

Added

  • Added noCompletions property documentation to README.

Fixed

  • Normalize content-type response header to lowercase when matching filetypes.

0.15.0-pre.5 - 2022-02-23

Added

  • More mobile friendly completion items via media query

Fixed

  • Pressing ESC to close completions menu doesn't de-focus the code-editor

  • Word wrapping on long completion item details doesn't extend to multiple lines

  • Elevation on completion items list matches other elevations on project

0.15.0-pre.4 - 2022-02-17

Added

  • Added Ctrl-Space hotkey for triggering interactive code completions.

0.15.0-pre.3 - 2022-02-16

Fixed

  • Fixed syntax highlighting and code folding regressions introduced when using documentKey.

0.15.0-pre.2 - 2022-02-15

Added

  • Added documentKey property to <playground-code-editor> which is used to keep track of individual CodeMirror document instances internally. Default behavior without setting a documentKey is unchanged.

    Use documentKey for fine control over the CodeMirror document instance. For example, to model changing a file.

Fixed

  • Fixed undo history applying across files (#154).

    Previously all files shared the same document instance resulting in files sharing undo/redo history. Now each file has its own isolated internal document instance.

  • Fixed only a single closing script tag unescaping in html files using playground-ide (#251).

0.15.0-pre.1 - 2022-02-04

Added

  • Added interactive code completions for TypeScript files (#243).

    Completions can be disabled by setting the no-completions attribute on <playground-ide>, <playground-file-editor>, or <playground-code-editor> components.

0.14.8 - 2022-01-25

Added

  • Added html-file attribute (htmlFile property) to playground-preview and playground-ide which allows configuring the project HTML file which should be displayed in the preview. Defaults to index.html (which was previously the only possible value)

Fixed

  • Remove nbsp characters from README.

0.14.7 - 2021-12-07

Fixed

  • Fixed missing aria-label attributes on the reload button, file context menu button, and new file button

0.14.6 - 2021-10-18

Fixed

  • Fixed bug where files could not be deleted or renamed using MWC v0.25.2 or above.

0.14.5 - 2021-10-07

Fixed

0.14.4 - 2021-10-06

Fixed

  • Fixed positioning of overlay that displays over previews when service workers are not available so that it is constrained to the preview, rather than the nearest containing positioned ancestor.

0.14.3 - 2021-10-06

Added

  • Added an overlay that will display over the preview when we detect that service workers are not available. One reason this can happen is using Playground in Firefox private browsing mode, which does not support service workers (https://bugzilla.mozilla.org/show_bug.cgi?id=1320796).

  • Added cursorPosition, cursorIndex, and tokenUnderCursor getters to <playground-code-editor>.

Changed

  • Upgraded dependencies, including CodeMirror.

Fixed

  • Fixed a bottleneck that prevented previews from loading until semantic TypeScript errors were computed. This should significantly improve the latency between updating a file and the new preview loading.

  • Fixed bug where parent window history entries were added every time the preview reloaded.

  • Improvements to service worker version updates:

    • The service worker will require less frequent updates going forward. Previously it needed updating for every playground-elements release. Now it only needs updating if the bytes of the service worker have changed between releases.

    • The default service worker scope has changed from <sandboxBaseUrl>/playground-project to <sandboxBaseUrl>/__playground_swfs_<serviceWorkerHash>. This should make service worker updates more reliable because old and new versions of service workers will no longer be in contention to control the same URLs.

    • Misc other small service worker robustness improvements, and additional logging to help debug future issues.

0.14.2 - 2021-09-30

Changed

  • Updated bundled version of TypeScript to 4.4.3.
  • Internal refactoring of language service.

0.14.1 - 2021-09-21

Changed

  • GitHub org changed from PolymerLabs to google.

0.14.0 - 2021-09-20

Changed

  • Upgrade to Lit 2.0.
  • TypeScript files are now compiled incrementally for improved performance

Fixed

  • Fixed bug where the value property of a <playground-code-editor> did not take effect if set before element upgrade.

Added

  • It is now possible to set the value of a <playground-code-editor> using the value HTML attribute.

0.13.0 - 2021-09-14

Changed

  • Node package exports are now supported when resolving dependency modules.

    The module, import, and development conditions are enabled.

    Note this change should not theoretically be BREAKING, but this release is versioned with a major increment because there a risk of breakage in practice due to misconfigured package.json files, differences between prod and dev modes, etc.

Added

  • Added modified property to <playground-project> and <playground-ide> which indicates whether the user has modified, added, or removed any project files. Resets whenever a new project is loaded.

0.12.1 - 2021-08-26

Changed

  • If a file is marked hidden, and the user creates a new file by that name, the file will become visible and editable.

0.12.0 - 2021-08-17

Fixed

  • Fixes duplicate module errors by canonicalizing all import specifiers. Import specifiers are now canonicalized by version number and default module. This applies both to local project files, and throughout the entire external dependency tree.

  • Import maps now apply to modules in external dependencies, not just to local project files.

  • The TypeScript compiler can now deal with multiple versions of the same dependency. Previously, if the import graph included two versions of the same package, only one arbitrary version of the types would be compiled. This caused various errors and missing type issues.

Changed

  • If the project contains a package.json file, then its dependencies field will be used to determine the version of dependencies (just like how NPM works locally).

  • Dependencies are now served from the special "<service-worker-scope>/node_modules/..." path, instead of directly from https://unpkg.com/...?module URLs. Behind-the-scenes, dependencies are still fetched from unpkg, but they are now themselves transformed to ensure correct specifier canonicalization.

  • BREAKING Due to large changes to the way dependencies are handled, there is some risk of breakage due to subtle behavior changes that existing configurations may be relying on. Therefore, this release is versioned with a major increment.

0.11.1 - 2021-08-09

Added

  • Added MIME-type detection for the following project file extensions: gif, ico, jpeg, jpg, mid, midi, mp3, png, svg, weba, webm, webp.

0.11.0 - 2021-07-28

Fixed

  • Playgrounds now ensure that the service worker they are connected to have a matching version. Fixes issues relating to playgrounds being broken for some time after an upgrade.

  • The --playground-tab-bar-font-size CSS custom property now behaves as documented, and defaults to 14px.

  • The --playground-floating-controls-color CSS custom property now behaves as documented.

  • Fix missing .js extension from import in build.js that may have broken Webpack and other builds.

  • The hover effect and touch area for tabs in the tab bar are no longer offset by the height of the active tab indicator.

  • Fix bug that caused failures to load d.ts files and "Could not resolve module specifier" console errors when using import maps.

Changed

  • BREAKING playground-base-url is now resolved relative to the import.meta.url of the module containing the definition of <playground-project>, instead of relative to document.location.href as before. This means that . can now be used to refer to the local playground installation directory.

  • The service worker now sets the Origin-Agent-Cluster: ?1 heading on all responses, to encourage browsers to allocate a separate process or thread for Playground preview iframe under certain conditions. See the Process isolation section of the README for more details.

  • It is now possible to change the font-family of the tab-bar using a ::part(tab-bar) selector.

0.10.1 - 2021-07-14

Changed

  • Bumped MWC dependency versions.

0.10.0 - 2021-07-01

Added

  • Adds --playground-code-padding and --playground-code-line-padding for configuring code editor padding.

  • Bare module specifiers are now transformed in dynamic import() statements.

Changed

  • BREAKING The src/ directory is no longer published to NPM.

  • BREAKING .js files are no longer compiled by TypeScript, so they cannot contain types, decorators, or other TypeScript-specific syntax.

  • Previews will now begin loading immediately, instead of waiting for compilation to completely finish, and each .js file is served as it compiles.

Fixed

  • Query parameters are now ignored when serving files from the virtual file system.

0.9.4 - 2021-05-18

Fixed

  • Fixed timeouts when using the default unpkg.com service worker origin, caused by comlink versions being out-of-sync between local components and remote service worker.

Added

  • Added readonly property to <playground-file-editor>.

0.9.3 - 2021-05-05

Changed

  • Error tooltips now follow --playground-code-font-family.
  • Optimized the UX for fast compile and display by switching to a leading edge debouncer and eliminating the minimum display time for the loading bar.

0.9.2 - 2021-04-26

Changed

  • Playground now executes code on the unpkg.com origin by default, meaning user code execution is now sandboxed by default. The sandbox URL can still be changed with the sandboxBaseUrl property or sandbox-base-url attribute, though it is highly advisable to always use a separate and unprivileged origin.

0.9.1 - 2021-04-19

Changed

  • Tab key now inserts 2 spaces instead of a tab character.

Fixed

  • Fixed missing vertical scrollbars.
  • Fixed transparent region between horizontal and vertical scrollbars.

0.9.0 - 2021-04-13

Changed

  • Focusing the editor using the Tab key no longer activates edit mode immediately. This prevents the Tab key from being trapped, which was an accessibility problem for keyboard users.

    Instead, when the editor is focused, users can now press Enter to begin editing, and Escape to stop editing. A prompt is displayed with these instructions when focused. Focusing the editor with a mouse click continues to activate edit mode immediately, as before.

  • The editor now uses the CodeMirror contenteditable input style, which has much better screen reader support.

  • Line numbers are now annotated with aria-hidden so that they are not voiced by screen readers.

  • Increased default line-height from normal to 1.4em.

  • Added a default padding-left of 1em.

  • Increased width of cursor from 1px to 2px.

  • Increased default tab font-size from 0.75rem to 0.8em;

  • Increased default --playground-bar-height from 35px to `40px.

  • --playground-cursor-color now defaults to the value of --playground-code-default-color.

  • --playground-code-gutter-background now defaults to the value of --playground-code-background.

  • --playground-code-gutter-margin-right default changed from 1px solid #ddd to none.

  • --playground-code-linenumber-color default changed from #999 to #767676.

Added

  • Added playground-styles.css and playground-styles.js which can be imported to apply Playground styles to server-side rendered code.

  • Added dialog CSS shadow part to code-editor, file-editor, and ide for styling modal dialogs that appear over the editor (currently just used for the keyboard help that shows when the editor is focused using the keyboard).

  • Added CSS custom properties:

    • --playground-code-line-height: line-height of code in the editor.
    • --playground-tab-bar-font-size: font-size of tabs in the file picker tab bar.
    • --playground-tab-bar-active-color: Text color of active file-picker tab.
    • --playground-tab-bar-indicator-color: color of the active tab indicator line (use transparent to hide).
    • --playground-tab-bar-active-background: background of the active file-picker tab.
  • Added aria-label attribute to reload, new file, and file context menu buttons.

  • Added title attribute to preview <iframe> element.

  • Added aria-label to the preview loading indicator, and set aria-hidden=true when the preview is not loading.

0.8.0 - 2021-04-02

Added

  • TypeScript type errors are now displayed inline. Previously, only syntax errors were displayed. Type errors may take slightly longer to appear than syntax errors, because they require fetching .d.ts files and running a more expensive compiler pass.

Changed

  • [BREAKING] Removed --playground-error-border property, and updated inline error style from a dashed border to a red squiggle.

0.7.0 - 2021-03-30

Changed

  • [BREAKING] Replaced files getter/setter on <playground-project> and <playground-ide> with config getter/setter. This property has the same type as the JSON config, and can be used to save/restore the state of all files and other configuration.

Fixed

  • TypeScript errors of the form Property '...' does not exist on type and Cannot find name '...' are now suppressed (temporarily until d.ts files are fetched).

0.6.6 - 2021-03-29

Fixed

  • Fixed missing @types/codemirror dependency.

0.6.5 - 2021-03-29

Fixed

  • Fixed missing lib/codemirror.js file in NPM package.

0.6.4 - 2021-03-29

Added

  • TypeScript errors are now displayed in the editor with red underlines. A tooltip displaying the error is shown on hover.

    • Note that only basic/syntactic errors are currently shown, because typings of dependencies are not currently available to compilation.
  • Added CSS property --playground-error-border, the border-bottom of code spans with an error (2px red dashed by default).

  • Added CSS shadow part diagnostic-tooltip for styling the tooltip that appears when hovering over an error.

0.6.3 - 2021-03-24

Added

  • Added optional hidden property/attribute which prevents a file from being displayed in the tab bar.

  • Added support for JSON files with syntax highlighting.

  • Added extends property to JSON config file, an optional URL of another JSON config file to extend from. Useful for setting side-wide defaults.

Fixed

  • Fixed bug where editor did not immediately switch to newly created files.

  • Fixed bug where label was ignored in tab bar.

0.6.2 - 2021-03-02

Added

  • Added content and contentType as optional properties of the JSON manifest.

Changed

  • License headers shortened to concise SPDX style.

Fixed

  • Fixed infinite loop that could occur when switching between two files that both contain code folding/hiding regions.

0.6.1 - 2021-03-01

Added

0.6.0 - 2021-02-19

Changed

  • [BREAKING] Leading whitespace that is common to all lines of slotted <script> files will now be trimmed, along with empty leading/trailing lines. To disable this behavior, add the preserve-whitespace attribute.

Added

  • Added --playground-floating-controls-color to control the highlight color of buttons and text inputs in floating add/remove/rename file controls. Defaults to var(--playground-highlight-color, #6200ee).

Fixed

  • Playground can now be imported from Skypack.

  • Fix bugs where --playground-tab-bar-background and --playground-tab-bar-foreground-color did not apply correctly.

0.5.0 - 2021-01-30

Changed

  • [BREAKING] When both projectSrc and files are set, it is now the most recently set property that wins. Previously, files always won.

  • <playground-preview> now auto-reloads after 300ms, previously 500ms.

Added

  • <playground-project> now emits a compileStart and compileDone event.

Removed

  • [BREAKING] <playground-project> no longer emits a contentChanged event.

0.4.3 - 2021-01-21

Fixed

  • Do not add ?module parameter to import map URLs for bare module specifiers, only to fallback unpkg.com URLs.

  • Prevent z-index issues with CodeMirror scrollbars and other elements by using a separate stacking context.

Changed

  • <playground-preview> now has a default label (called location) of "Result".

0.4.2 - 2021-01-21

Added

  • Import maps are now supported. This allows customizing the URL that a bare module specifier resolves to, e.g. to a specific version, or to a different CDN.

    Note that import maps currently only apply to the immediate imports of project source files, not to external transitive dependencies.

    Also note scopes are not yet supported, only imports.

    See https://github.com/WICG/import-maps and https://wicg.github.io/import-maps/ for more information on import maps.

    Previously, all bare modules resolved to unpkg.com URLs at the latest version. This continues to be the fallback behavior if no import map is provided, or no entry in it matches.

    To specify an import map in a JSON project manifest, add an importMap property:

    {
      "files": {
        "index.html": {},
        "my-element.ts": {}
      },
      "importMap": {
        "imports": {
          "lit-html": "https://unpkg.com/lit-html@next-major",
          "lit-html/": "https://unpkg.com/lit-html@next-major/"
        }
      }
    }

    To specify an import map inline, add a <script type="sample/importmap"> slotted child:

    <playground-ide>
      <script type="sample/importmap">
        {
          "imports": {
            "lit-html": "https://unpkg.com/lit-html@next-major",
            "lit-html/": "https://unpkg.com/lit-html@next-major/"
          }
        }
      </script>
      ...
    </playground-ide>

Fixed

  • Bare module imports in .js files are now resolved in the same way as .ts files.

0.4.1 - 2021-01-15

Fixed

  • Fixed <playground-file-editor> not always displaying initial file.
  • Fixed editable-file-system attribute name (was editableFileSystem).
  • Fixed <playground-ide> not stretching <playground-file-editor> vertically.

0.4.0 - 2021-01-15

Added

  • Added editableFileSystem property (editable-file-system attribute) to <playground-ide>. When true, the user will be able to create, delete, and rename files in the virtual filesystem.

    • To create a new file: click the "+" icon button in the tab bar.
    • To rename a file: click the three-dots menu button on its tab, and select "Rename".
    • To delete a file: click the three-dots menu button on its tab, and select "Delete".
  • Added <playground-file-system-controls> element which displays popup menus/dialogs for creating, deleting, and renaming files.

Changed

  • [BREAKING] The tab bar has been factored into a new standalone element called <playground-tab-bar>. The <playground-file-editor> element no longer integrates the tab bar, and the noFilePicker property has been removed.

  • [BREAKING] The following CSS custom properties have been renamed:

    • --playground-file-picker-background -> --playground-tab-bar-background
    • --playground-file-picker-foreground -> --playground-tab-bar-foreground
  • [BREAKING] The following CSS shadow parts have been renamed:

    • file-picker -> tab-bar

0.3.7 - 2021-01-08

Added

  • Added files property to <playground-ide> and <playground-project>. Use this property to directly get and set the array of project files (e.g. to save/restore the project state).

    Note that directly setting files always takes precedence over setting projectSrc, and both take precedence over slotted children.

Changed

  • It is no longer necessary to load the Material Icons font. The reload button icon is now inlined SVG.

Fixed

  • Fix caret placement issues with some dynamic layouts.

0.3.6 - 2020-12-08

Fixed

  • Fix shifted/hidden code in Safari when line numbers are enabled.

0.3.5 - 2020-12-03

Fixed

  • Fix mwc-tab race condition bug (dependency version bump).

0.3.4 - 2020-12-03

Changed

  • The playground service worker now serves its own 404s when a file is not found, instead of forwarding the request to the server.

Fixed

  • Fix race condition where preview could load too early and 404.
  • Fix race condition where preview could sometimes never load.
  • Fix preview 404 that could occur after leaving page idle for some time.

0.3.3 - 2020-12-01

Fixed

  • Fix Safari scrolling bug by limiting preview max-height.

0.3.2 - 2020-11-30

Fixed

  • Fix installation error relating to missing node_modules/puppeteer directory.

Changed

  • Bumped and un-pinned @material/mwc dependencies.

Removed

  • Removed some unnecessary files from NPM package.

0.3.1 - 2020-11-11

Fixed

  • Remove debugging log statement.
  • Remove unecessary file from NPM package.

0.3.0 - 2020-11-11

Changed

  • [BREAKING] service-worker.js has been renamed to playground-service-worker.js, typescript-worker.js has been renamed to playground-typescript-worker.js, and an additional file called playground-service-worker-proxy.html is now also required. This change may affect bundling configurations.

Added

  • Service Workers and scripts are now able and advised to run on a second origin, in order to isolate arbitrary script execution from sensitive actions or data on the host origin.

    The sandboxBaseUrl property (or sandbox-base-url attribute) has been added <playground-ide> and <playground-project> to control this origin.

    If the default same origin is used, a warning will be logged to the console.

0.2.0 - 2020-10-28

Changed

  • [BREAKING] Replaced theme property with new custom property based theming system (see below).

  • [BREAKING] Renamed CSS custom properties:

    • playground-code-color -> playground-code-default-color
    • playground-file-editor-background-color -> playground-code-background
    • playground-file-picker-background-color -> playground-file-picker-background
    • playground-preview-toolbar-background-color -> playground-preview-toolbar-background

Added

  • Added CSS Custom Properties for configuring the CodeMirror theme.

    Includes broad properties like --playground-code-background and --playground-selection-color, as well as token-specific properties like --playground-code-keyword-color and --playground-code-string-color.

    See the themes/ directory for more examples of what can be customized.

  • Added themes/ directory which includes CSS files and JS modules for each of the standard CodeMirror themes, adapted to use CSS Custom Properties.

    Use the configurator at https://google.github.io/playground-elements/ to try out the available themes.

    To load a theme, load its stylesheet into your document or shadow root scope, and set the corresponding playground-theme-NAME class on any playground element or ancestor.

    In HTML:

    <head>
      <link
        rel="stylesheet"
        href="/node_modules/playground-elements/themes/mbo.css"
      />
    </head>
    
    <body class="playground-theme-mbo">
      <playground-ide></playground-ide>
    </body>

    In a LitElement:

    import mbo from 'playground-elements/themes/mbo.css.js';
    
    class MyElement extends LitElement {
      static styles = [mbo, css`...`];
    
      render() {
        return `
          <playground-ide class="playground-theme-mbo">
          </playground-ide>
        `;
      }
    }

Fixed

  • Fix inconsistent line-number guttter sizing.

0.1.1 - 2020-10-26

Added

  • Added --playground-preview-size CSS custom property to control the initial size of the RHS preview bar in <playground-ide>. The LHS editor will take up all additional space. Defaults to 30%.

  • Added resizable property/attribute which allows users to click and drag in the space between the LHS editor and RHS preview of <playground-ide> to change their relative sizes.

Fixed

  • Invalid module import paths.
  • Reload button icon now respects --playground-preview-toolbar-foreground-color.

Changed

  • TypeScript decorator runtime is now imported from tslib instead of inlined.

0.1.0 - 2020-10-24

  • [BREAKING] NPM package and GitHub repo renamed from code-sample-editor to playground-elements.

  • [BREAKING] Renamed all elements:

    • <code-sample> -> <playground-ide>
    • <code-sample-project> -> <playground-project>
    • <code-sample-editor> -> <playground-file-editor>
    • <codemirror-editor> -> <playground-code-editor>
  • [BREAKING] Renamed all element JS modules:

    • ./lib/code-sample.js -> ./playground-ide.js
    • ./lib/code-sample-project.js -> ./playground-project.js
    • ./lib/code-sample-editor.js -> ./playground-file-editor.js
    • ./lib/codemirror-editor.js -> ./playground-code-editor.js

0.1.0-pre.4 - 2020-10-22

Changed

  • [BREAKING] Major refactor of elements to allow them to be more easily used independently. The new elements are:

    • <code-sample>: A single editor with file-selection bar and preview in side-by-side layout. If a different layout is required, the editor and preview elements can instead be used directly, along with a project element. New equivalent of what used to be <code-sample-editor>.

    • <code-sample-project>: New purely abstract element that coordinates between the service worker, editor elements, and preview elements.

    • <code-sample-editor>: An editor with file-selection bar, tied to a project element. New equivalent to the left-hand-side side of what used to be <code-sample-editor>.

    • <code-sample-preview>: A rendered HTML preview window, tied to a project element. New equivalent to the right-hand-side of what used to be <code-sample-editor-preview>.

    • <codemirror-editor>: A pure CodeMirror editor, mostly unchanged from previous version.

    Example usage without <code-sample>:

    <code-sample-project
      id="myProject"
      project-src="/demo/typescript/project.json"
    ></code-sample-project>
    <code-sample-editor project="myProject"></code-sample-editor>
    <code-sample-preview project="myProject"></code-sample-preview>

    The project property can either be an ID in the host scope (as shown above) or a direct reference to a <code-sample-project> element (which would allow the elements to live in different scopes).

  • Downgraded from CodeMirror v6 to v5 in order to gain support for nested highlighting of HTML and CSS inside JS/TS. See https://github.com/lezer-parser/javascript/issues/3. Will upgrade back to 6 once support is ready.

  • The caret is now only displayed when an editor is on focus (previously it was always displayed).

  • The <code-sample> side-by-side layout is now consistently 70%/30% (widths can be changed using the editor and preview CSS shadow parts).

Added

  • Add syntax highlighting of TypeScript files.

  • Add syntax highlighting of nested HTML and CSS inside JS/TS.

  • Add filename property/attribute to <code-sample-editor> which allows getting and setting the currently selected file.

  • Add noFilePicker property (no-file-picker attribute) to <code-sample-editor> which disables the top file selection tab-bar.

  • Add lineNumbers property (line-numbers attribute) to <code-sample>, <code-sample-editor>, and <codemirror-editor> which enables the left-hand-side gutter with line numbers. Off by default.

  • Add a <slot> to <code-sample-editor> which will be displayed until the file is loaded. This facilitates pre-rendering syntax-highlighted code before both the element has upgraded, and before the project file has been fetched.

  • Add a <slot> to <code-sample-preview> which will be displayed until the preview iframe has loaded for the first time. This facilitates pre-rendering preview HTML both before both the element has upgraded, and before the live preview first renders.

  • Add label property and attribute to project files. When set, the file picker will display this label instead of the filename.

  • An animated progress bar now displays when a preview is loading.

  • Added CSS Shadow Parts:

    • <code-sample-editor>: file-picker
    • <code-sample-preview>: preview-toolbar, preview-location, preview-reload-button, preview-loading-indicator
    • <code-sample>: editor, preview, file-picker, preview-toolbar, preview-location, preview-reload-button, preview-loading-indicator
  • Added CSS Custom Properties:

    • --playground-code-font-family
    • --playground-code-font-size
    • --playground-editor-background-color
    • --playground-file-picker-background-color
    • --playground-file-picker-foreground-color
    • --playground-preview-toolbar-background-color
    • --playground-preview-toolbar-foreground-color
    • --playground-border
    • --playground-highlight-color
    • --playground-bar-height
  • Added theme property to <code-sample>, <code-sample-editor>, and <codemirror-editor>, which sets the theme (currently only default, monokai, ambiance, ayu-mirage are available, but a way to load other themes will follow).

  • Previews will now automatically reload on changes (0.5 second debounce).

  • Added readonly property/attribute to <codemirror-editor> which disables the ability to edit.

Fixed

  • Fix absent CSS syntax highlighting.
  • Fix various styling/layout glitches.
  • Fix service worker and TypeScript worker URLs, which reached up too many parent directories.

0.1.0-pre.3 - 2020-10-05

Fixed

  • Fix missing CodeMirror styles on Firefox and Safari.
  • Fix Safari crashes in <mwc-tab> code.

0.1.0-pre.2 - 2020-09-12

Fixed

  • Fix extra/missing files.

0.1.0-pre.1 - 2020-09-12

  • Initial release.