Skip to main content

The light-viewer element

This is a live <light-viewer> showing a track light's IES file. Drag to orbit, scroll to zoom, use the gear for viewer settings, and switch tabs for charts.

Use the custom element in any browser application, independently of React. The quickest way is to load the self-contained bundle from jsDelivr:

<script type="module" src="https://cdn.jsdelivr.net/npm/@ies-tools/viewer/dist/light-viewer.js"></script>
<light-viewer src="/lights/luminaire.ies" exposure="1" style="height: 600px"></light-viewer>

This URL always serves the latest release; add a version such as @ies-tools/[email protected] to pin one. To self-host instead, copy @ies-tools/viewer/dist/light-viewer.js to your application's public assets and point the script at it, or import '@ies-tools/viewer/element' in a bundler. To script the element:

import 'https://cdn.jsdelivr.net/npm/@ies-tools/viewer/dist/light-viewer.js';

const viewer = document.querySelector('light-viewer');
viewer.addEventListener('load', (event) => console.log(event.detail.profile));
viewer.addEventListener('error', (event) => console.error(event.detail.message));
viewer.iesText = await file.text();

photometryText accepts raw IES or LDT source text. data and iesText are compatibility aliases for that property, avoiding the need to host an uploaded file. Attach listeners before setting a source. Fetched URLs must be accessible to your page under normal browser CORS rules.

src changes cancel previous requests; removing the element cancels loading and releases GPU resources. Reinserting the element recreates its viewer. exposure controls display brightness and must be a finite nonnegative number. The element defaults to a 480-pixel height and black background.

The load event carries { profile, document, sourceFormat }; the existing profile field remains available. The error event carries { message, error }, and the component also displays the message. Both events bubble across the shadow boundary. A hardware WebGL2 context and Type C profile are required for rendering.

Imperative Three.js API​

import { createLightViewer } from '@ies-tools/viewer';

const viewer = createLightViewer(document.querySelector('#viewport'), { height: 2, exposure: 1 });
viewer.load(iesOrLdtText);
viewer.setExposure(2);
// When the host view is destroyed:
viewer.dispose();

height is the luminaire's distance above the floor in meters; size the host element with CSS. setProfile(profile) accepts a previously parsed compatible profile. setDocument(document) accepts a shared native-source document directly. The returned renderer exposes the Three.js WebGLRenderer for integrations and hardware diagnostics.

Three.js's IESLoader is also exported by @ies-tools/viewer for applications that use its native photometric textures. Its texture representation differs from the viewer's calibrated candela table; consult the Three.js loader contract when integrating it with Three.js lighting.

The currently pinned Three.js loader has known texture layout limitations for some bilateral and full-azimuth files. The shared viewer uses its own validated candela sampler, and tests verify finite receiver textures for every bundled fixture. The native loader export is provided for interoperability, not as a substitute for core validation.

EULUMDAT and source hints​

<script type="module" src="https://cdn.jsdelivr.net/npm/@ies-tools/viewer/dist/light-viewer.js"></script>
<light-viewer src="/lights/luminaire.ldt" format="ldt" lamp-set-index="1"></light-viewer>

format optionally forces ies or ldt; without it, file content is detected. lamp-set-index is a zero-based LDT configuration index and must be supplied for files containing multiple alternative lamp sets. It is not a lamp count or a brightness multiplier. Single-set files need no index. Invalid formats and indices produce the normal error event and visible status message.

import { parsePhotometry } from '@ies-tools/core';
viewer.photometryText = ldtText; // automatically detected
viewer.photometry = parsePhotometry(ldtText, 'ldt', { lampSetIndex: 1 });
viewer.addEventListener('load', (event) => {
console.log(event.detail.sourceFormat, event.detail.document.source);
});

The photometry property accepts a shared in-memory document and preserves its source geometry and metadata without converting to an IES string. Assigning raw text replaces that document input; changing src replaces both explicit text and document inputs. Source changes cancel older fetches, and stale responses cannot replace a newer selection. Removing the element cancels loading and disposes the controller; reconnecting recreates it with the selected input.

The imperative controller keeps its original load(text) return value, a compatible IESProfile, while accepting either source format. Use loadDocument(text, format?, { lampSetIndex? }) to receive the complete native-source document, or read the controller's document after loading. load(text, format?, { lampSetIndex? }) accepts the same optional input hint and zero-based selection.

Viewer options​

The gear button opens a built-in overlay, shared by browser embeds and VS Code. It controls the back wall, the helper, wall distance, floor distance (light mounting height), tone mapping, and exposure. Distances are in meters. Changing a source preserves these settings.

<script type="module" src="https://cdn.jsdelivr.net/npm/@ies-tools/viewer/dist/light-viewer.js"></script>
<light-viewer
src="/lights/luminaire.ies"
settings-panel="open"
show-wall="true"
wall-distance="2"
floor-distance="2"
tone-mapping="aces"
exposure="1"
helper="true"
></light-viewer>

helper draws blue beam-extent lines and is on by default; helper="false" hides it. A downward beam (intensity cut off below 80° from nadir) shows its ground circle, just above the floor, with four lines to the light; wider distributions show three axis circles at half the mounting height with axis lines through the light.

settings-panel is closed by default (gear visible), open, or hidden (no controls, useful for image export). Escape, the close button, and clicking outside dismiss the overlay. A missing show-wall attribute enables the wall; use show-wall="false" to hide it. Distances accept 0.1–100 meters. Exposure accepts any finite nonnegative value, including zero. Tone mapping accepts aces (default), agx, neutral, reinhard, cineon, linear, and none.

viewer.settings = { showWall: false, floorDistance: 3, toneMapping: 'agx', exposure: 2 };
viewer.addEventListener('settingschange', (event) => console.log(event.detail.settings));

The settings property returns a copy. Assigning a partial settings object validates it atomically, reflects the attributes and updates the controls. The bubbling, composed settingschange event supplies { settings, previousSettings } once per effective change. Removing and reinserting the element preserves settings. The imperative controller offers getSettings(), setSettings(patch) and settingschange listeners. Its existing height option remains an alias for floorDistance, and setExposure() remains supported. Floor distance changes move the fixture above the fixed ground; wall distance moves the receiver behind it. The camera preserves its orbit direction while fitting distance changes.

Chart tabs​

Add charts="true" to show a tab bar: the 3D view first, then polar, Cartesian, topology, isolux, cone, luminance and intensity-table charts of the loaded light. The isolux chart uses the floor distance as mounting height. The cone tab shows centre illuminance and beam/field diameters at 1–5 m, the luminance tab shows glare-angle average luminance over the declared luminous opening, and the intensity-table tab shows the measured candela grid; wide tables scroll. See Photometric graphs. The options overlay applies to the 3D tab only.

<script type="module" src="https://cdn.jsdelivr.net/npm/@ies-tools/viewer/dist/light-viewer.js"></script>
<light-viewer src="/lights/luminaire.ies" charts="true"></light-viewer>

Shared React and Tailwind styling​

The options overlay uses the shared React ViewerSettingsPanel, styled by the same Tailwind utilities and tokens as the extension and React viewer. The standalone light-viewer.js bundle contains React and its compiled stylesheet; it fetches no UI scripts, styles or fonts. Bundler users importing @ies-tools/viewer/element must supply the React and React DOM peer dependencies, but do not need a CSS loader: the built element imports an SSR-safe stylesheet string module.

UI colors inherit host custom properties such as --popover, --popover-foreground, --foreground, --input, --border and --ring. Unspecified values use dark standalone fallbacks. These properties pass through the shadow boundary, so VS Code themes update the controls without rebuilding them. The rendering background stays black. See Styling and themes.