NA ŻYWO · ŁAŃCUCH AUDYTU · UE
SYSTEM · 99,99% DOSTĘPNOŚĆ
v 1.0 ↗ WYPRODUKOWANO W UE

@nexbasira/react

Wrapper React wokół @nexbasira/embed. Dwie powierzchnie — gotowy do wstawienia komponent <NexBasiraSession> dla typowego przypadku oraz hook useNexBasiraSession() dla niestandardowych układów.

Instalacja

npm install @nexbasira/react @nexbasira/embed react

react i @nexbasira/embed są zależnościami peer — nie są dołączane do tego pakietu.

Komponent

import { NexBasiraSession } from "@nexbasira/react";

function InspectionPage({ joinUrl }: { joinUrl: string }) {
  return (
    <NexBasiraSession
      sessionUrl={joinUrl}
      height="720px"
      onSessionComplete={(id) => navigate(`/inspections/${id}`)}
    />
  );
}

sessionUrl to jednorazowy URL, który Twój backend otrzymuje z sessions.invite() w SDK Node / Python. Komponent montuje iframe przy pierwszym renderze i czysto go niszczy przy odmontowaniu.

Dostęp imperatywny przez ref

Użyj ref, gdy kontrolki strony terenowej znajdują się poza iframe (pasek narzędzi nad komponentem, wyzwalacz modala itp.):

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} />
    </>
  );
}

Wariant z hookiem

Gdy opakowujący <div> nie pasuje do Twojego układu — powiedzmy, że chcesz iframe w kontenerze flex z panelem bocznym — użyj hooka + podłącz zwrócony ref do własnego elementu hosta:

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>
  );
}

Callbacki cyklu życia pozostają świeże między renderami

Widget embed jest tworzony raz na sessionUrl. Aby zapewnić, że Twoje callbacki zawsze widzą najnowsze domknięcie (obejmujące najnowszy stan), wrapper wewnętrznie przechowuje je w useRef i odczytuje ponownie przy każdym zdarzeniu. Możesz bezpiecznie przekazywać wbudowane funkcje strzałkowe:

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);
      }}
    />
  );
}

Kiedy iframe jest przebudowywany?

Tylko gdy zmieni się sessionUrl. Każdy inny prop (callbacki, szerokość, wysokość, expectedOrigin) stosuje się w miejscu bez ponownego montowania. Oznacza to, że zmiana callbacku lub zmiana rozmiaru hosta nie restartuje sesji na żywo — przydatne, gdy Twoja aplikacja często się renderuje.

Propsy

PropTypUwagi
sessionUrlstringWymagane. Tworzone przez Twój backend.
width / heightstringRozmiary CSS. Domyślnie 100% / 600px.
expectedOriginstringNadpisz origin iframe, jeśli hostujesz na własnej domenie.
classNamestringStosowane do opakowującego diva.
styleCSSPropertiesStosowane do opakowującego diva.
on* callbacksfunctionTa sama powierzchnia co @nexbasira/embed — zobacz tamtą stronę.

Typowany uchwyt

import type { NexBasiraSessionHandle } from "@nexbasira/react";

const ref = useRef<NexBasiraSessionHandle>(null);
// ref.current has typed methods: requestSnapshot(), openWhiteboard(), etc.

Co dalej