@nexbasira/react
Wrapper React em torno de @nexbasira/embed. Duas superfícies — um componente <NexBasiraSession> pronto a usar para o caso comum, mais um hook useNexBasiraSession() para layouts personalizados.
Instalação
npm install @nexbasira/react @nexbasira/embed react react e @nexbasira/embed são peer dependencies — não vêm agrupados neste pacote.
Componente
import { NexBasiraSession } from "@nexbasira/react";
function InspectionPage({ joinUrl }: { joinUrl: string }) {
return (
<NexBasiraSession
sessionUrl={joinUrl}
height="720px"
onSessionComplete={(id) => navigate(`/inspections/${id}`)}
/>
);
} sessionUrl é o URL de uso único que o seu backend recebe de sessions.invite() no SDK Node / Python. O componente monta o iframe no primeiro render e destrói-o de forma limpa ao desmontar.
Acesso imperativo via ref
Use um ref quando os controlos do lado do terreno vivem fora do iframe (toolbar acima do componente, gatilho de modal, etc.):
import { useRef } from "react";
import { NexBasiraSession, type NexBasiraSessionHandle } from "@nexbasira/react";
function Toolbar({ joinUrl }: { joinUrl: string }) {
const session = useRef<NexBasiraSessionHandle>(null);
return (
<>
<button onClick={() => session.current?.requestSnapshot()}>Capture</button>
<button onClick={() => session.current?.openWhiteboard()}>Whiteboard</button>
<button onClick={() => session.current?.endSession()}>End</button>
<NexBasiraSession ref={session} sessionUrl={joinUrl} />
</>
);
} Variante com hook
Quando o <div> do wrapper não se adequa ao seu layout — digamos que quer o iframe num contentor flex com uma sidebar — use o hook + anexe o ref devolvido ao seu próprio elemento anfitrião:
import { useNexBasiraSession } from "@nexbasira/react";
function CustomLayout({ joinUrl }: { joinUrl: string }) {
const [containerRef, widget] = useNexBasiraSession({
sessionUrl: joinUrl,
onSessionComplete: (id) => navigate(`/inspections/${id}`),
});
return (
<div className="grid grid-cols-[1fr_240px] gap-4">
<div ref={containerRef} style={{ minHeight: 600 }} />
<aside>
<button onClick={() => widget.current?.requestSnapshot()}>Snap</button>
</aside>
</div>
);
} Os callbacks de ciclo de vida mantêm-se atualizados entre renders
O widget de embed é criado uma vez por sessionUrl. Para garantir que os seus callbacks veem sempre a closure mais recente (fechando sobre o estado mais recente), o wrapper guarda-os internamente num useRef e relê-os a cada evento. Pode passar funções arrow inline com segurança:
function Page() {
const [count, setCount] = useState(0);
return (
<NexBasiraSession
sessionUrl={joinUrl}
onEvidenceAdded={() => {
// 'count' is always the latest value, not the value at mount
setCount(count + 1);
}}
/>
);
} Quando é que o iframe é reconstruído?
Apenas quando sessionUrl muda. Qualquer outra prop (callbacks, width, height, expectedOrigin) aplica-se no local sem remontar. Isto significa que mudar um callback ou redimensionar o anfitrião não reinicia a sessão em direto — útil quando a sua aplicação faz re-render com frequência.
Props
| Prop | Tipo | Notas |
|---|---|---|
sessionUrl | string | Obrigatório. Emitido pelo seu backend. |
width / height | string | Tamanhos CSS. Por defeito 100% / 600px. |
expectedOrigin | string | Sobrepõe a origem do iframe se alojar num domínio personalizado. |
className | string | Aplicado ao div do wrapper. |
style | CSSProperties | Aplicado ao div do wrapper. |
on* callbacks | function | Mesma superfície que @nexbasira/embed — ver essa página. |
Handle tipado
import type { NexBasiraSessionHandle } from "@nexbasira/react";
const ref = useRef<NexBasiraSessionHandle>(null);
// ref.current has typed methods: requestSnapshot(), openWhiteboard(), etc. O que vem a seguir
- @nexbasira/embed — widget subjacente
- @nexbasira/node — emitir o
sessionUrlno seu backend - Código-fonte no GitHub