@ai-matrx/capture
v0.5.40
Published
The AI Matrx capture kit: reusable camera chrome, a production default media engine, injectable host-runtime ports, cloud library integration, and in-browser media review and editing.
Maintainers
Readme
@ai-matrx/capture
The AI Matrx capture kit — the opinionated, iPhone-style camera experience as a reusable React package.
THE CLOUD LAW: cloud integration is WHAT this system does, not an add-on. CameraCapture requires a CaptureCloudPort (recents thumb, library opener, edited-image persistence). The host decides HOW the cloud is reached — never WHETHER.
Drop-in quickstart (any React host)
No media runtime required — the package ships its own engine:
import { useState } from "react";
import {
CameraCapture,
CameraFeed,
useDefaultCaptureEngine,
type CaptureMediaItem,
} from "@ai-matrx/capture/react";
export function Camera() {
const [mode, setMode] = useState<"photo" | "video">("photo");
const [items, setItems] = useState<CaptureMediaItem[]>([]);
const add = (file: File, kind: "photo" | "video") =>
setItems((xs) => [
...xs,
{ key: crypto.randomUUID(), kind, src: URL.createObjectURL(file) },
]);
const engine = useDefaultCaptureEngine({
onPhoto: (f) => add(f, "photo"),
onVideo: (f) => add(f, "video"),
onFiles: (fs) => [...fs].forEach((f) =>
add(f, f.type.startsWith("video/") ? "video" : "photo")),
});
return (
<div style={{ position: "fixed", inset: 0 }}>
<CameraCapture
engine={engine}
preview={<CameraFeed engine={engine} />}
mode={mode}
onModeChange={setMode}
media={{
items,
onDelete: (key) => setItems((xs) => xs.filter((x) => x.key !== key)),
onReplacePhoto: (key, blob) =>
setItems((xs) => xs.map((x) =>
x.key === key
? { ...x, src: URL.createObjectURL(blob) }
: x)),
}}
cloud={{ recentsThumb: null, onOpenLibrary: () => {/* your gallery */} }}
/>
</div>
);
}That is the whole wiring: filmstrip, swipe viewer (tuned gestures + neighbor
preload + resolution caching), crop/rotate editor with replace semantics,
two-tap options grid, timer, torch/zoom (when the hardware reports them),
upload lane and safe-area handling all come from the package. Hosts with
their own camera runtime (AI Matrx) pass a custom CaptureCameraEngine
instead of the default one; persisted items provide resolve() instead of
src and the package caches the resolutions.
What's inside
CameraCapture— the assembled chrome: full-bleed feed under semi-transparent near-black bars; top bar (close · center slot · torch · extras · options); real zoom pills (track capabilities only — nothing faked); VIDEO · PHOTO · UPLOAD mode row (upload is first-class); recents thumb · shutter · flip; honesty chips (recording clock survives hidden chrome).OptionsGridPanel— the two-tap options surface (reveal, then act): Flash (torch), Timer (0/3/10s), Grid, Aspect (full/4:3/1:1/16:9), Exposure (when the hardware reports a range), plus host-injected tiles.ImageEditSheet— instant in-browser editing: crop (free/1:1/4:3/16:9), rotate, flip; canvas re-encode of the original pixels.CaptureSheet— the iOS-style system sheet (content + "busy" transient variant).useTrackControls— honest torch/zoom/exposure overMediaTrackCapabilities.- Slot-based extensibility (
CaptureCameraSlots) — typed slots for domain add-ons (status chips, option tiles, extra modes such as SCAN, rows above the mode selector, overlays). No plugin framework.
What's NOT inside (by design)
- No forced host runtime. The package includes
useDefaultCaptureEngine(its solegetUserMediaimplementation undersrc/engine/) for runtime-less hosts. Apps with an existing cross-feature camera runtime inject aCaptureCameraEngine; AI Matrx does this for lease management, recorder journaling, and diagnostics. - No network, no storage — enforced by
src/laws.test.ts. - Persisted-media rendering (thumbnails, lightboxes, durable refs) — that's
@ai-matrx/media. - Audio-only recording UX —
@ai-matrx/browser-audio. - QR decoding —
@ai-matrx/kit/qr.
Both the default engine and injected host adapters finalize recordings through
finalizeCapturedVideo: emitted/final Blob MIME is authoritative, the filename
extension matches it, and delivered duration is a positive integer.
Usage sketch
import { CameraCapture } from "@ai-matrx/capture/react";
import type { CaptureCameraEngine, CaptureCloudPort } from "@ai-matrx/capture";
<CameraCapture
engine={engine} // host camera runtime adapter
cloud={cloud} // REQUIRED — recents thumb, library, save-edited
mode={mode}
onModeChange={setMode}
preview={<YourLivePreview />}
onClose={close}
blockedSheet={{ body: <p>…</p>, actions: [...] }}
slots={{ optionTiles: [...], statusChips: <...>, extraModes: [{ id: "scan", label: "Scan", onSelect: openScanner }] }}
/>The reference host integration is matrx-frontend features/capture-camera/ (staging source) with the commerce intake surface at /commerce/intake/v2 as the worked domain-extension example.
