Skip to content

Latest commit

 

History

History
190 lines (142 loc) · 9.81 KB

File metadata and controls

190 lines (142 loc) · 9.81 KB

API reference

Viewport Lab is a browser library. It has no backend, no framework runtime, and no required CSS import when you use mount() — styles ship inside the bundle and are injected into a shadow root.

Install

npm install github:aneebji/html-editor#v1.1.0

The package is distributed through GitHub. The public npm registry does not currently host it. Import only in a browser environment.

Script tag (no bundler):

<script src="https://aneebji.github.io/html-editor/html-device-preview.umd.js"></script>

jsDelivr (GitHub):

<script src="https://cdn.jsdelivr.net/gh/aneebji/html-editor@main/dist/html-device-preview.umd.js"></script>

mount(target, options?)

Creates the studio inside target (a CSS selector or HTMLElement) and returns a StudioHandle.

import { mount } from "html-device-preview";

const studio = mount("#preview", {
  html: "",
  filename: "Untitled.html",
  height: "820px",
});

Mount options

Option Type Default Description
html string "" Document to edit. Empty shows the welcome state.
theme "light" | "dark" "light" Workspace color scheme.
editorMode "source" | "visual" "source" Initial editor tab.
onChange (html: string) => void none User changes only; setHtml() does not call back.
shareBaseUrl string hosted studio URL URL of a studio that restores #doc= links. Does not change the host page URL.
filename string "Untitled.html" Name used for Download and shown in the topbar.
categories DeviceCategory[] all Limit the mobile catalog (desktop/custom remain available): iphone, ipad, android-phone, android-tablet.
devices string[] popular 12 mobile devices Selected viewport IDs or category names, including desktop and custom. An empty array selects none.
customViewports CustomViewport[] [] Additional instance-local viewports.
compareIds string[] first 3 selected 2–3 distinct selected viewport IDs.
mode "grid" | "focus" | "compare" "grid" Preview layout.
orientation "portrait" | "landscape" "portrait" Device orientation.
zoom "fit" | "50" | "75" | "100" "fit" Preview scale.
showEditor boolean true Show the Visual / Source pane.
showChrome boolean true Show the File / View / Devices topbar. When false, Copy / Share / Download move to the preview bar.
height CSS length host height Applied to the host element.

DeviceCategory is "iphone" | "ipad" | "android-phone" | "android-tablet".

StudioHandle

Method Returns Description
setOptions(options) void Update runtime workspace options without replacing the HTML or editor.
setHtml(html) void Replace the document.
getHtml() string Current source, including <head> when present.
setFilename(name) void Rename the download file (.html is added if missing).
getFilename() string Current filename.
download() void Trigger a file download.
copy() Promise<boolean> Copy source to the clipboard.
shareUrl() Promise<string> URL with the document in #doc=.
destroy() void Unmount and remove listeners.
el HTMLElement Internal studio root inside the host’s shadow root.
document.querySelector("#save").onclick = () => studio.download();
const html = studio.getHtml();

Web component

The bundle registers <html-device-preview> automatically.

<html-device-preview
  height="820px"
  filename="campaign.html"
  devices="iphone,android-phone"
  mode="grid">
</html-device-preview>
<script src="https://aneebji.github.io/html-editor/html-device-preview.umd.js"></script>
Attribute Maps to
html html (also updates the studio when the attribute changes)
filename filename
theme light or dark (live)
editor-mode source or visual (initial)
devices comma-separated category names or ids (live)
mode mode (live)
orientation orientation (live)
zoom zoom (live)
height height
hide-editor showEditor: false (live; removal shows the editor)
hide-chrome showChrome: false

Named exports

import {
  mount,
  defineElement,
  DEVICES,
  DEVICE_COUNT,
  DESKTOP_VIEWPORTS,
  SAMPLE_HTML,
  SAMPLE_TEMPLATES,
  VERSION,
  downloadHtml,
  copyText,
  encodeShare,
  decodeShare,
  readShareHash,
} from "html-device-preview";

On a script tag, the same names live on HtmlDevicePreview.

SAMPLE_HTML is a restaurant landing page you can load with File → Sample templates. It is not mounted by default.

Security

Preview frames use sandbox="allow-scripts allow-forms" and srcdoc. Their opaque origin prevents access to the host DOM and host storage. Documents can still make network requests. Do not add allow-same-origin.

Treat uploaded HTML as untrusted. The studio is an editor and preview, not a sanitizer for publishing to your users.

Share links

shareUrl() / Share compress the document with deflate-raw and encode it as #doc=…. Compression is used when supported, with an uncompressed fallback for encoding. URL limits vary by browser and sharing channel; use Download for larger files. The hosted studio restores share links; mount() does not automatically read the hash. Typing does not rewrite it.

Framework state and lifecycle

const preview = mount(container, {
  html: initialHtml,
  onChange: html => updateFormState(html),
});
// Later, when the framework unmounts the component:
preview.destroy();

Calling mount() again on the same container destroys the previous instance. Editor listeners, preview observers, and pending preview updates are cleaned up.

Web components emit a bubbling, composed html-change event with { html } in event.detail. Subscribe on the custom element or its ancestor. Changes made through setHtml() or the html attribute do not emit this event.

Source changes update the document state immediately, while preview refreshes are debounced by 160 ms. Download and change callbacks always use the latest source.

Visual mode uses DOMPurify to create a basic rich-text editing surface. It excludes scripts, styles, forms, embedded active content, and active attributes. Switching tabs does not rewrite the document. Making a Visual edit replaces its body with the simplified content; use Source to preserve complex layouts. Exported source is not sanitized.

Runtime options

setOptions(patch: RuntimeOptions) accepts theme, devices, mode, orientation, zoom, showEditor, and compareIds. Omitted fields keep their current values. It does not call onChange or emit html-change. Invalid enum values, non-boolean showEditor, or invalid explicit comparisons throw before applying the patch. Unknown device IDs are ignored. Updating devices clears the UI search/family filter so the requested selection is visible.

interface CustomViewport {
  id: string;
  name: string;
  width: number;
  height: number;
}

Custom IDs must be nonempty, unique across the instance and built-in catalog, and contain only letters, numbers, underscores or hyphens. Names must contain 1–80 characters. Width/height are integers between 240 and 3840. Invalid custom definitions cause mount() to throw. Additions made through Catalog use generated instance-local IDs. Custom definitions are mount-time options; setOptions() can select existing custom viewports.

PreviewViewport is the union of the unchanged mobile Device interface and BrowserViewport. Browser viewports use category desktop or custom, os: "browser", notch: "none", and pixelRatio: 1. ViewportCategory includes both new categories; DeviceCategory remains unchanged. The categories option limits the mobile portion of the catalog.

An explicit compareIds must contain 2–3 distinct IDs present in the resulting selected device set (including devices in the same patch). With fewer than two selected viewports, the UI asks the user to select more. Comparison ignores search/family filters and persists across mode changes. Deselecting a compared viewport removes it from the comparison and fills an empty required slot from the remaining selection when possible.

The studio caches instantiated iframe cards within its instance and hides those outside the active view. Zoom, family filters, layout, theme, rotation and resizing reuse the cards; changing HTML reloads their document. Hidden previews may continue running scripts. Destroying the studio removes all cards and the CodeMirror editor, observers and global listeners.

Removing a live custom-element attribute restores its default (theme="light", mode="grid", orientation="portrait", zoom="fit", default 12 devices). Attribute changes affect only the corresponding option. For custom viewport definitions and explicit comparisons, use mount().

Sample templates

SAMPLE_TEMPLATES: SampleTemplate[] contains ten self-contained HTML pages. Each entry has id, name, category, description, and html strings. SampleTemplate is also exported as a TypeScript type. The gallery uses sandboxed thumbnail frames and releases them when closed. Template selection emits a user document change, preserving the current selected viewports and comparison settings. SAMPLE_HTML remains available and refers to Harbor & Rye.

Device cards expose aria-busy="true" and an individual loading overlay while awaiting their iframe's load event. Setting the same source or changing layout/zoom/theme does not restart the loader. A browser resource failure may still produce a completed load; this is a load indicator, not a validator of page correctness.