@we-box/box-components
v0.1.0
Published
Official resource-aware image, audio, video and 3D components for Webox Boxes
Downloads
98
Maintainers
Readme
@we-box/box-components
Official resource-aware Custom Elements for Webox Boxes. Version 0.1.0 is a release candidate in this repository; online use requires npm publication and Package Graph admission in the target environment.
Each Box declares the dependency and imports its required entries; registration happens inside that Box's iframe. The Host injects the SDK, not this component library. Online drafts and uploaded Box Projects use the same package and resource contracts. Development seed snapshots inline workspace code and do not prove registry delivery. See the activation runbook for the release, admission and real Box acceptance requirements.
The published CLI/Builder 0.5.0 cannot build HTML entries containing only component registration imports. Toolchain 0.6.0 contains the required registration-entry fix; workspace tarball validation does not establish compatibility with published 0.5.0. The supported component contract requires renderer 25 or later, including independent native volume under Host mute. Create a new Box version to upgrade an older renderer.
<script type="module">
import '@we-box/box-components/image';
import '@we-box/box-components/audio';
import '@we-box/box-components/video';
import '@we-box/box-components/model';
</script>
<webox-image resource="images/cover.png" alt="Cover"></webox-image>
<webox-audio resource="audio/voice.m4a" controls aria-label="Voice"></webox-audio>
<webox-video resource="videos/demo.mp4" controls aria-label="Demo"></webox-video>
<webox-model resource="models/product.glb" aria-label="Product"></webox-model>Declare "@we-box/box-components": "0.1.0" in runtime dependencies, import
only the entries used, bind the corresponding resources, and declare
resources.box.read. The SDK is injected by the Host; do not install a second
SDK runtime. Framework wrappers are unnecessary: these are standard Custom Elements.
| Element | Attributes and methods |
| --- | --- |
| webox-image | alt (required, empty for decorative images), fit="contain\|cover", loading="lazy\|eager", width, height |
| webox-audio | boolean controls, muted, loop, autoplay; preload="none\|metadata\|auto"; mediaElement, play(), pause(), paused, currentTime |
| webox-video | boolean controls, muted, loop, autoplay; preload="none\|metadata\|auto"; optional poster bound image path; mediaElement, play(), pause(), paused, currentTime |
| webox-model | accessible name; self-contained GLB v2, max 50 MiB; resetView(); pointer orbit, wheel zoom, arrows, +/−, Home |
All accept resource (logical path) or mutually exclusive handle (a viewer
resource handle already obtained with the SDK). handle requires
resources.user.select; mounting never opens a picker or releases your handle.
Audio, video and model require aria-label or aria-labelledby. Boolean attributes
use HTML presence semantics: remove muted to disable it, never muted="false".
poster requires its own image binding and resources.box.read.
All expose retry(), state, data-state (idle, loading, ready, error),
webox-load and webox-error events. Errors contain only {code, retryable};
resource leases are never event payloads. Empty dynamic elements remain idle
until their resource/handle is assigned. Presentation attributes are reactive
and reload the element; use media methods for playback control.
Images defer opening their lease until visible by default (loading="eager" opens immediately). Audio and video use
optional native controls in light DOM so Host mute still applies; autoplay follows
browser policy. Expired media leases reopen once on playback, seeking or error
and restore position, playback intent and media settings. Permission failure
stops playback. Retry is explicit after an error. preload="none" stays loading
until metadata becomes available through playback.
Model rendering pauses outside the viewport or when the Host/document is hidden.
Removal cancels observation/animation and frees model/GPU resources. External
textures and online decoders are unsupported. Image/audio/video entries never import
Three.js. Set size on the custom element; --webox-media-fit controls default
image/video fitting. Controls/errors support English and Chinese from Host locale
or element lang.
/catalog is the machine-readable contract; /authoring validates declarative
HTML, imports, capabilities, resource kinds and accessible names. Dynamic JS
inputs are validated at runtime. Native media/custom rendering remain allowed.
Styling
Media surfaces are transparent by default: no card background, border, shadow or
padding. Transparent pixels in PNG/WebP images and around models show the surrounding
Box. Backgrounds, frames and spacing belong to the calling page and are optional;
the gallery example adds no media backdrop. Size and crop with ordinary CSS on the
custom element, for example style="width:32px;height:32px" for an image in a toolbar.
Native video controls and letterboxing follow the browser. Add controls to show the native audio/video UI.
Omit it to hide native controls and attach an external player to mediaElement after the
webox-load event; the element stays in light DOM so players such as Plyr, Media Chrome or a
custom controller can use the standard HTMLAudioElement or HTMLVideoElement.
The caller owns the player's lifecycle: destroy it before replacing the resource or
unmounting the framework view, and bind the new mediaElement after each webox-load.
When destruction is asynchronous (such as Plyr's callback), wait for it before reloading.
Keep third-party styles and icon sprites local to the Project (see the
toolchain compatibility notes).
Loading uses a small animated ring on a transparent surface, inherits the element's
text color and fits within its dimensions, including small inline images. Localized
loading text remains available to screen readers. Reduced-motion preferences stop the
animation. Loading overlays do not intercept controls; headless audio stays out of the
layout, and preload="none" shows the available player without a waiting animation.
Ready/idle states hide the indicator. Errors use a fine-line icon, compact message and
outlined retry button on the same transparent surface. Narrow elements reduce decoration;
very small images show only the retry icon while keeping accessible text. Buttons inherit
the Box text color, support keyboard focus and respect reduced-motion preferences.
const video = document.querySelector("webox-video");
video?.addEventListener("webox-load", () => {
const media = video.mediaElement;
if (media) attachExternalPlayer(media);
});Local example and checks
The Form & Motion example uses real repository-owned image, audio, video and GLB fixtures. It is nested here so an unpublished npm dependency does not enter workspace installation. Run from the repository root:
pnpm build:box-toolchain
node apps/box-cli/dist/cli.js build packages/box-components/example --json
node apps/box-cli/dist/cli.js preview packages/box-components/example --json
pnpm --filter @we-box/box-components testLocal preview resolves the workspace package. To use the example outside this
repository before publication, pack this package and install that tarball in the
example with npm install --no-save /absolute/path/to/we-box-box-components-0.1.0.tgz.
Keep the manifest's runtime version as 0.1.0; file/workspace dependency requests
are not valid Box upload intent.
Architecture and release prerequisites: Built-in media components.
For audio, import @we-box/box-components/audio and bind an existing MP3/OGG/WAV/M4A resource.
The component uses the resource lease returned by the SDK; it does not transcode or fetch waveform derivatives.
mediaElement is an HTMLAudioElement (available while metadata loads), so a custom control can also call
play() when preload="none". Without controls, audio occupies no player UI space.
Host mute remains authoritative: enable Box sound before listening; changing volume does not override it.
Renderer 25 routes CORS media with native controls through the Host output gain after volume interaction or playback:
native volume and local mute remain adjustable while global sound is off. Hover and focus do not claim a media source.
Audio/video components set anonymous CORS before loading their resource lease. Custom players without native controls
can attach their Web Audio graph before or after playback. When combining native controls and a custom graph,
connect the author source before playback or volume changes; a media element can only bind one source node.
Reading mediaElement.muted returns local mute intent, so renewal during Host mute preserves the player's own setting.
Saved older Boxes need a new version to receive the runtime change.
