@opengeni/react 5.0.4 → 5.0.5-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,6 +32,9 @@ Optional `@opengeni/react/connect` exports `useConnect`, `ConnectChooser`,
32
32
  when that scope changes. The controller uses your authenticated backend proxy;
33
33
  never place an organization key in browser props. Import
34
34
  `@opengeni/react/connect.css` for opt-in, scoped styles without Tailwind.
35
+ `DeviceAuthorization` also accepts an optional `render` callback for host presentation;
36
+ it receives shared copy state, the copy action, and the validated verification URL.
37
+ Omitting it preserves the default embedded presentation.
35
38
 
36
39
  ```tsx
37
40
  import { ConnectPanel } from "@opengeni/react/connect";
@@ -137,6 +137,11 @@ export type SandboxWorkspaceProps = ClientOverride & {
137
137
  * omitted the workbench decides from the durable workspace capture. */
138
138
  initialTab?: string | undefined;
139
139
  onActiveTabChange?: ((activeTab: string) => void) | undefined;
140
+ /** Open a built-in or host-injected tab. A new requestId reopens the same tab. */
141
+ openTabRequest?: {
142
+ tab: string;
143
+ requestId: number;
144
+ } | null | undefined;
140
145
  initialFilePath?: string | null | undefined;
141
146
  onFilePathChange?: ((path: string | null) => void) | undefined;
142
147
  /** Presentation-only filter for Files tree nodes and selected-file viewing. */
package/dist/connect.js CHANGED
@@ -534,6 +534,7 @@ function DeviceAuthorization(props) {
534
534
  href = props.verificationUri;
535
535
  } catch {
536
536
  }
537
+ if (props.render) return props.render({ copied, copyError, copy, verificationHref: href });
537
538
  return /* @__PURE__ */ jsxs5("section", { className: `og-connect ${props.className ?? ""}`, "aria-label": "Device authorization", children: [
538
539
  /* @__PURE__ */ jsx5("p", { children: props.description ?? `Enter this code at ${props.providerLabel ?? "the provider"}.` }),
539
540
  /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexWrap: "wrap", gap: "0.5rem", alignItems: "center" }, children: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/connect.ts","../src/connect-setup.tsx","../src/connect-chooser.tsx","../src/connect-accounts.tsx","../src/connect-panel.tsx","../src/device-authorization.tsx","../src/identity-link-consent.tsx","../src/identity-link-accounts.tsx"],"sourcesContent":["// Optional, unstyled React adapter over the shared headless controller.\n// The host owns controller lifetime; unmounting one observer does not cancel an\n// attempt another observer is displaying or a durable backend operation.\nimport { useMemo, useSyncExternalStore } from \"react\";\nimport type { ConnectController } from \"@opengeni/connect\";\nexport { ConnectSetup, type ConnectSetupProps } from \"./connect-setup\";\nexport { ConnectChooser, type ConnectChooserProps } from \"./connect-chooser\";\nexport { ConnectAccounts, type ConnectAccountsProps } from \"./connect-accounts\";\nexport { ConnectPanel, type ConnectPanelProps } from \"./connect-panel\";\nexport { DeviceAuthorization, type DeviceAuthorizationProps } from \"./device-authorization\";\nexport {\n IdentityLinkConsent,\n type IdentityLinkClient,\n type IdentityLinkConsentProps,\n} from \"./identity-link-consent\";\nexport { IdentityLinkAccounts, type IdentityLinkAccountsClient } from \"./identity-link-accounts\";\n\nexport type { ConnectSnapshot } from \"@opengeni/connect\";\nexport type {\n ConnectAccount,\n ConnectAdvance,\n ConnectAttempt,\n ConnectNextAction,\n ConnectOwnership,\n ConnectProvider,\n ConnectResource,\n ConnectTransport,\n} from \"@opengeni/connect\";\n\nexport function useConnect(controller: ConnectController) {\n const snapshot = useSyncExternalStore(\n controller.subscribe,\n controller.getSnapshot,\n controller.getSnapshot,\n );\n const actions = useMemo(\n () => ({\n begin: controller.begin.bind(controller),\n recover: controller.recover.bind(controller),\n refresh: controller.refresh.bind(controller),\n waitForAction: controller.waitForAction.bind(controller),\n advance: controller.advance.bind(controller),\n cancel: controller.cancel.bind(controller),\n }),\n [controller],\n );\n return useMemo(() => ({ ...snapshot, ...actions }), [snapshot, actions]);\n}\n","import { useState, type FormEvent } from \"react\";\nimport type { ConnectAttempt, ConnectController } from \"@opengeni/connect\";\nimport { useConnect } from \"./connect\";\n\nconst setupStatus: Record<ConnectAttempt[\"state\"], string> = {\n ready: \"Ready to connect\",\n requires_user_action: \"Authorize your account\",\n credential_input: \"Enter connection details\",\n provider_wait: \"Waiting for authorization\",\n account_selection: \"Choose an account\",\n resource_selection: \"Choose resources\",\n preview: \"Review available operations\",\n installing: \"Installing selected operations…\",\n connected_but_incomplete: \"Account connected — finish setup\",\n complete: \"Connection ready\",\n cancelled: \"Setup cancelled\",\n expired: \"Setup expired\",\n failed: \"Setup could not finish\",\n uncertain: \"Setup outcome needs checking\",\n};\n\nfunction deviceVerificationUrl(action: ConnectAttempt[\"nextAction\"]): string | null {\n if (action.type !== \"wait\" || !action.verificationUrl) return null;\n try {\n const url = new URL(action.verificationUrl);\n return url.protocol === \"https:\" && !url.username && !url.password\n ? action.verificationUrl\n : null;\n } catch {\n return null;\n }\n}\n\nexport type ConnectSetupProps = {\n controller: ConnectController;\n /** Called synchronously in the click handler so a host can open a popup. */\n onAuthorize: (attempt: ConnectAttempt) => void | Promise<unknown>;\n /** Host pagination must retain selections across pages and submit the final set. */\n onBrowseResources?: (attempt: ConnectAttempt) => void | Promise<unknown>;\n className?: string;\n};\n\n/** Unstyled setup surface. No provider secrets enter React state. Host owns\n * chooser, controller lifetime, navigation and recovery after full redirect. */\nexport function ConnectSetup(props: ConnectSetupProps) {\n // Attempt IDs/revisions are not a substitute for actor scope. A host can\n // recover the same attempt through a replacement controller; never preserve\n // a previous actor's unsent credential DOM or local errors across that swap.\n const [scope, setScope] = useState(props.controller);\n const [generation, setGeneration] = useState(0);\n if (scope !== props.controller) {\n setScope(props.controller);\n setGeneration(generation + 1);\n }\n return <ScopedSetup key={generation} {...props} />;\n}\n\nfunction ScopedSetup({ controller, onAuthorize, onBrowseResources, className }: ConnectSetupProps) {\n const view = useConnect(controller);\n const [localError, setLocalError] = useState(false);\n const invoke = (operation: () => unknown | Promise<unknown>) => {\n setLocalError(false);\n try {\n void Promise.resolve(operation()).catch(() => setLocalError(true));\n } catch {\n setLocalError(true);\n }\n };\n const attempt = view.attempt;\n if (!attempt)\n return (\n <section className={className} aria-label=\"Connection setup\">\n <p role=\"status\">Choose a connection to begin.</p>\n </section>\n );\n const action = attempt.nextAction;\n const verificationUrl = deviceVerificationUrl(action);\n const terminal = [\"complete\", \"cancelled\", \"expired\"].includes(attempt.state);\n const submit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const form = event.currentTarget;\n const data = new FormData(form);\n if (view.busy) return;\n const key = crypto.randomUUID();\n if (action.type === \"credentials\") {\n const values = Object.fromEntries(\n action.fields.map((field, i) => [field.name, String(data.get(`field-${i}`) ?? \"\")]),\n );\n // Clear the DOM before awaiting remote work; controller never retains values.\n form.reset();\n invoke(() => view.advance({ type: \"credentials\", values }, key));\n } else if (action.type === \"select_account\") {\n const accountId = String(data.get(\"account\") ?? \"\");\n if (\n action.accounts.some((account) => account.id === accountId && account.status !== \"disabled\")\n )\n invoke(() => view.advance({ type: \"account\", accountId }, key));\n } else if (action.type === \"select_resources\") {\n if (action.cursor) return;\n const resourceIds = data.getAll(\"resource\").map(String);\n invoke(() => view.advance({ type: \"resources\", resourceIds }, key));\n } else if (action.type === \"preview\") {\n const operationIds = data.getAll(\"operation\").map(String);\n invoke(() =>\n view.advance(\n {\n type: \"install\",\n previewId: action.previewId,\n contentHash: action.contentHash,\n operationIds,\n },\n key,\n ),\n );\n }\n };\n return (\n <section className={className} aria-label=\"Connection setup\" aria-busy={view.busy}>\n <p>Ownership: {attempt.ownership === \"personal\" ? \"Personal\" : \"Workspace\"}</p>\n <p role=\"status\">{setupStatus[attempt.state]}</p>\n {attempt.account && <p>Account: {attempt.account.label}</p>}\n {(localError || view.error || attempt.error) && (\n <p role=\"alert\">\n {attempt.error?.code === \"source_changed\"\n ? \"The integration source changed. Review the new operations before installing.\"\n : \"Connection setup could not continue. Refresh its status before trying again.\"}\n </p>\n )}\n {!terminal && (\n <form key={`${attempt.id}:${attempt.revision}`} onSubmit={submit} autoComplete=\"off\">\n <fieldset disabled={view.busy}>\n <legend>Connection details</legend>\n {attempt.state === \"connected_but_incomplete\" && action.type === \"none\" && (\n <button\n type=\"button\"\n onClick={() => invoke(() => view.advance({ type: \"retry\" }, crypto.randomUUID()))}\n >\n Review integration operations\n </button>\n )}\n {action.type === \"credentials\" &&\n action.fields.map((field, i) => (\n <label key={field.name}>\n {field.label}\n {field.options ? (\n <select name={`field-${i}`} required={field.required} defaultValue=\"\">\n <option value=\"\">\n {field.required ? \"Choose an option\" : \"No account (public service)\"}\n </option>\n {field.options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n ) : (\n <input\n name={`field-${i}`}\n type={field.secret ? \"password\" : \"text\"}\n required={field.required}\n autoComplete=\"off\"\n />\n )}\n </label>\n ))}\n {action.type === \"select_account\" && (\n <label>\n Account\n <select name=\"account\" required defaultValue=\"\">\n <option value=\"\" disabled>\n Choose an account\n </option>\n {action.accounts.map((account) => (\n <option\n key={account.id}\n value={account.id}\n disabled={account.status === \"disabled\"}\n >\n {account.label} — {account.id} ({account.ownership})\n </option>\n ))}\n </select>\n </label>\n )}\n {action.type === \"select_resources\" &&\n action.resources.map((resource) => (\n <label key={resource.id}>\n <input type=\"checkbox\" name=\"resource\" value={resource.id} />\n {resource.label} ({resource.kind})\n </label>\n ))}\n {action.type === \"select_resources\" && action.cursor && (\n <>\n <p>More resources are available. Review all pages before submitting a selection.</p>\n {onBrowseResources && (\n <button\n type=\"button\"\n onClick={() => invoke(() => onBrowseResources(structuredClone(attempt)))}\n >\n Browse all resources\n </button>\n )}\n </>\n )}\n {action.type === \"preview\" && (\n <>\n <p>Select the operations to install.</p>\n {action.operations.map((operation) => (\n <label key={operation.id}>\n <input type=\"checkbox\" name=\"operation\" value={operation.id} />\n {operation.label} ({operation.kind})\n </label>\n ))}\n </>\n )}\n {[\"credentials\", \"select_account\", \"select_resources\", \"preview\"].includes(\n action.type,\n ) && (\n <button\n type=\"submit\"\n disabled={action.type === \"select_resources\" && Boolean(action.cursor)}\n >\n {action.type === \"preview\" ? \"Install selected operations\" : \"Continue\"}\n </button>\n )}\n {action.type === \"authorize\" && (\n <button\n type=\"button\"\n onClick={() => invoke(() => onAuthorize(structuredClone(attempt)))}\n >\n Authorize connection\n </button>\n )}\n {action.type === \"wait\" && (\n <>\n {action.userCode && (\n <p>\n Verification code: <code>{action.userCode}</code>\n </p>\n )}\n <p>Complete provider authorization, then check the connection status.</p>\n {verificationUrl && (\n <a href={verificationUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n Open provider verification page (new tab)\n </a>\n )}\n </>\n )}\n <button type=\"button\" onClick={() => invoke(() => view.refresh())}>\n Check status\n </button>\n <button type=\"button\" onClick={() => invoke(() => view.cancel(crypto.randomUUID()))}>\n Cancel setup\n </button>\n </fieldset>\n </form>\n )}\n </section>\n );\n}\n","import { useEffect, useState, type FormEvent } from \"react\";\nimport type { ConnectController, ConnectProvider } from \"@opengeni/connect\";\nimport { useConnect } from \"./connect\";\n\nexport type ConnectChooserProps = {\n controller: ConnectController;\n /** Exact host return string; no completion parameters are added. */\n returnUrl: string;\n className?: string;\n};\n\n/** Catalog readiness is supplied by the authenticated backend, never inferred\n * from the existence of a provider definition. Host replaces the controller on\n * actor/workspace change. This form does not open OAuth windows itself. */\nexport function ConnectChooser(props: ConnectChooserProps) {\n // Remount scope-local selections synchronously when the controller changes,\n // before effects can expose a previous actor's inventory for one frame.\n const [scope, setScope] = useState(props.controller);\n const [generation, setGeneration] = useState(0);\n if (scope !== props.controller) {\n setScope(props.controller);\n setGeneration(generation + 1);\n }\n return <ScopedChooser key={generation} {...props} />;\n}\n\nfunction ScopedChooser({ controller, returnUrl, className }: ConnectChooserProps) {\n const view = useConnect(controller);\n const [catalog, setCatalog] = useState<ConnectProvider[] | null>(null);\n const [failed, setFailed] = useState(false);\n const [load, setLoad] = useState(0);\n const [providerId, setProviderId] = useState(\"\");\n const [ownership, setOwnership] = useState(\"\");\n useEffect(() => {\n const abort = new AbortController();\n setCatalog(null);\n setFailed(false);\n setProviderId(\"\");\n setOwnership(\"\");\n // Promise boundary also handles a synchronously throwing injected transport.\n void Promise.resolve()\n .then(() => {\n abort.signal.throwIfAborted();\n return controller.transport.catalog(controller.workspaceId, { signal: abort.signal });\n })\n .then((providers) => {\n if (!abort.signal.aborted) setCatalog(structuredClone(providers));\n })\n .catch(() => {\n if (!abort.signal.aborted) setFailed(true);\n });\n return () => abort.abort();\n }, [controller, load]);\n const provider = catalog?.find((entry) => entry.id === providerId);\n const canBegin =\n provider?.readiness === \"available\" &&\n (ownership === \"personal\" || ownership === \"workspace\") &&\n provider.ownership.includes(ownership);\n const submit = (event: FormEvent) => {\n event.preventDefault();\n if (!canBegin || view.busy || (ownership !== \"personal\" && ownership !== \"workspace\")) return;\n setFailed(false);\n try {\n void controller\n .begin({ providerId, ownership, returnUrl, idempotencyKey: crypto.randomUUID() })\n .catch(() => setFailed(true));\n } catch {\n setFailed(true);\n }\n };\n return (\n <section\n className={className}\n aria-label=\"Choose a connection\"\n aria-busy={view.busy || (!catalog && !failed)}\n >\n {failed && (\n <p role=\"alert\">\n Connections could not be loaded or started. Check setup status before retrying.\n </p>\n )}\n {!catalog && !failed && <p role=\"status\">Loading connections…</p>}\n {catalog?.length === 0 && <p role=\"status\">No connections are available.</p>}\n {Boolean(catalog?.length) && (\n <form onSubmit={submit}>\n <fieldset disabled={view.busy}>\n <legend>Provider and ownership</legend>\n <label>\n Provider\n <select\n required\n value={providerId}\n onChange={(event) => {\n setProviderId(event.target.value);\n setOwnership(\"\");\n }}\n >\n <option value=\"\" disabled>\n Choose a provider\n </option>\n {catalog!.map((entry) => (\n <option\n key={entry.id}\n value={entry.id}\n disabled={entry.readiness !== \"available\" || entry.ownership.length === 0}\n >\n {entry.label} — {entry.id} ({entry.readiness.replaceAll(\"_\", \" \")})\n </option>\n ))}\n </select>\n </label>\n {provider && (\n <label>\n Ownership\n <select\n required\n value={ownership}\n onChange={(event) => setOwnership(event.target.value)}\n >\n <option value=\"\" disabled>\n Choose ownership\n </option>\n {provider.ownership.map((choice) => (\n <option key={choice} value={choice}>\n {choice === \"personal\"\n ? \"Personal — owned by you\"\n : \"Workspace — shared connection\"}\n </option>\n ))}\n </select>\n </label>\n )}\n <button type=\"submit\" disabled={!canBegin}>\n Start setup\n </button>\n </fieldset>\n </form>\n )}\n <button type=\"button\" disabled={view.busy} onClick={() => setLoad(load + 1)}>\n Reload providers\n </button>\n </section>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type { ConnectAccount, ConnectController } from \"@opengeni/connect\";\nimport { useConnect } from \"./connect\";\n\nexport type ConnectAccountsProps = {\n controller: ConnectController;\n className?: string;\n /** Enables explicit account-bound reconnect. Host supplies the exact destination. */\n returnUrl?: string;\n};\n\n/** Local credential revocation only. Unknown or changed versions must be\n * refreshed; this component never retries a destructive operation implicitly. */\nexport function ConnectAccounts(props: ConnectAccountsProps) {\n const [scope, setScope] = useState(props.controller);\n const [generation, setGeneration] = useState(0);\n if (scope !== props.controller) {\n setScope(props.controller);\n setGeneration(generation + 1);\n }\n return <ScopedAccounts key={generation} {...props} />;\n}\n\nfunction ScopedAccounts({ controller, className, returnUrl }: ConnectAccountsProps) {\n const view = useConnect(controller);\n const [accounts, setAccounts] = useState<ConnectAccount[] | null>(null);\n const [selected, setSelected] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState(false);\n const [reload, setReload] = useState(0);\n const mutation = useRef<AbortController | null>(null);\n useEffect(() => () => mutation.current?.abort(), []);\n useEffect(() => {\n const abort = new AbortController();\n setAccounts(null);\n setSelected(null);\n setError(false);\n void Promise.resolve()\n .then(() => {\n abort.signal.throwIfAborted();\n return controller.transport.accounts(controller.workspaceId, { signal: abort.signal });\n })\n .then((result) => {\n if (!abort.signal.aborted) setAccounts(structuredClone(result));\n })\n .catch(() => {\n if (!abort.signal.aborted) setError(true);\n });\n return () => abort.abort();\n }, [controller, reload]);\n\n const disconnect = async (account: ConnectAccount) => {\n const expectedVersion = account.version;\n if (\n mutation.current ||\n view.busy ||\n expectedVersion === undefined ||\n !Number.isSafeInteger(expectedVersion) ||\n expectedVersion < 1\n )\n return;\n const abort = new AbortController();\n mutation.current = abort;\n setBusy(true);\n setError(false);\n try {\n await controller.transport.disconnect(controller.workspaceId, account.id, {\n expectedVersion,\n signal: abort.signal,\n });\n if (!abort.signal.aborted) setReload((value) => value + 1);\n } catch {\n if (!abort.signal.aborted) {\n // Outcome may be unknown. Drop the inventory so a second click cannot\n // replay against the stale selection; let the host reload live state.\n setAccounts(null);\n setError(true);\n }\n } finally {\n if (!abort.signal.aborted) {\n mutation.current = null;\n setBusy(false);\n setSelected(null);\n }\n }\n };\n const reconnect = async (account: ConnectAccount) => {\n if (!returnUrl || mutation.current || view.busy) return;\n setError(false);\n try {\n await controller.begin({\n providerId: account.providerId,\n ownership: account.ownership,\n reconnectAccountId: account.id,\n returnUrl,\n idempotencyKey: crypto.randomUUID(),\n });\n } catch {\n setError(true);\n }\n };\n\n return (\n <section\n className={className}\n aria-label=\"Connected accounts\"\n aria-busy={busy || view.busy || (!accounts && !error)}\n >\n {error && (\n <p role=\"alert\">Account state could not be confirmed. Reload before trying again.</p>\n )}\n {!accounts && !error && <p role=\"status\">Loading accounts…</p>}\n {accounts?.length === 0 && <p role=\"status\">No connected accounts.</p>}\n {accounts && accounts.length > 0 && (\n <ul>\n {accounts.map((account) => (\n <li key={`${account.providerId}:${account.id}`}>\n <span>\n {account.label} — {account.providerId} — {account.ownership} —{\" \"}\n {account.status.replaceAll(\"_\", \" \")}\n </span>\n {returnUrl && (\n <button\n type=\"button\"\n disabled={busy || view.busy || account.status === \"disabled\"}\n onClick={() => void reconnect(account)}\n >\n Reconnect {account.label}\n </button>\n )}\n {selected === `${account.providerId}:${account.id}` ? (\n <div role=\"group\" aria-label={`Disconnect ${account.label}`}>\n <p>\n This removes local OpenGeni access. It does not revoke consent at the provider.\n </p>\n <button\n type=\"button\"\n disabled={busy || view.busy}\n onClick={() => void disconnect(account)}\n >\n Confirm disconnect\n </button>\n <button type=\"button\" disabled={busy} onClick={() => setSelected(null)}>\n Keep account\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n disabled={\n busy ||\n view.busy ||\n account.status === \"disabled\" ||\n !Number.isSafeInteger(account.version) ||\n account.version! < 1\n }\n onClick={() => setSelected(`${account.providerId}:${account.id}`)}\n >\n Disconnect {account.label}\n </button>\n )}\n </li>\n ))}\n </ul>\n )}\n <button type=\"button\" disabled={busy} onClick={() => setReload((value) => value + 1)}>\n Reload accounts\n </button>\n </section>\n );\n}\n","import { ConnectAccounts } from \"./connect-accounts\";\nimport { ConnectChooser } from \"./connect-chooser\";\nimport { ConnectSetup, type ConnectSetupProps } from \"./connect-setup\";\n\nexport type ConnectPanelProps = ConnectSetupProps & {\n returnUrl: string;\n title?: string;\n showAccounts?: boolean;\n};\n\n/** Optional composition over the same unstyled surfaces. Import\n * @opengeni/react/connect.css for styling; the host retains navigation,\n * transport, actor admission, and controller lifetime. */\nexport function ConnectPanel({\n returnUrl,\n title = \"Connections\",\n showAccounts = true,\n className,\n ...setup\n}: ConnectPanelProps) {\n return (\n <div className={[\"og-connect\", className].filter(Boolean).join(\" \")}>\n <h2>{title}</h2>\n <ConnectChooser controller={setup.controller} returnUrl={returnUrl} />\n <ConnectSetup {...setup} />\n {showAccounts && <ConnectAccounts controller={setup.controller} returnUrl={returnUrl} />}\n </div>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { copyTextToClipboard } from \"./clipboard\";\n\nexport type DeviceAuthorizationProps = {\n userCode: string;\n verificationUri: string;\n providerLabel?: string;\n description?: string;\n className?: string;\n codeAttributes?: Record<`data-${string}`, string>;\n loadClipboard?: () => Promise<{ copyTextToClipboard(text: string): Promise<boolean> }>;\n onCopyResult?: (copied: boolean) => void;\n};\n\n/** Optional presentation for the existing model-account device APIs. It neither\n * owns provider state nor assumes that opening a verification page completed it. */\nexport function DeviceAuthorization(props: DeviceAuthorizationProps) {\n const [copied, setCopied] = useState(false);\n const [copyError, setCopyError] = useState(false);\n const generation = useRef(0);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => {\n generation.current++;\n setCopied(false);\n setCopyError(false);\n return () => {\n // This is a live async-operation counter, not a captured DOM ref.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n generation.current++;\n if (timer.current) clearTimeout(timer.current);\n };\n }, [props.userCode]);\n async function copy() {\n const revision = ++generation.current;\n if (timer.current) clearTimeout(timer.current);\n setCopied(false);\n setCopyError(false);\n try {\n const clipboard = props.loadClipboard ? await props.loadClipboard() : { copyTextToClipboard };\n if (revision !== generation.current) return;\n const success = await clipboard.copyTextToClipboard(props.userCode);\n if (revision !== generation.current) return;\n setCopied(success);\n setCopyError(!success);\n props.onCopyResult?.(success);\n if (success)\n timer.current = setTimeout(() => {\n if (revision === generation.current) setCopied(false);\n }, 1600);\n } catch {\n if (revision !== generation.current) return;\n setCopyError(true);\n props.onCopyResult?.(false);\n }\n }\n let href: string | undefined;\n try {\n const url = new URL(props.verificationUri);\n if ([\"https:\", \"http:\"].includes(url.protocol) && !url.username && !url.password)\n href = props.verificationUri;\n } catch {\n /* A malformed provider URL must never become an executable link. */\n }\n return (\n <section className={`og-connect ${props.className ?? \"\"}`} aria-label=\"Device authorization\">\n <p>{props.description ?? `Enter this code at ${props.providerLabel ?? \"the provider\"}.`}</p>\n <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: \"0.5rem\", alignItems: \"center\" }}>\n <code {...props.codeAttributes} style={{ overflowWrap: \"anywhere\" }}>\n {props.userCode}\n </code>\n <button\n type=\"button\"\n aria-label={copied ? \"Code copied\" : \"Copy code\"}\n onClick={() => void copy()}\n >\n {copied ? \"Copied\" : \"Copy code\"}\n </button>\n {href ? (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\">\n Open {props.providerLabel ?? \"auth page\"}\n </a>\n ) : (\n <span role=\"alert\">Authorization address unavailable.</span>\n )}\n </div>\n {copyError ? <p role=\"alert\">Couldn't copy the code. Copy it manually instead.</p> : null}\n <p role=\"status\">Waiting for authorization…</p>\n </section>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type {\n ExternalIdentityLink,\n ConfirmExternalIdentityLinkRequest,\n ExternalIdentityLinkPreview,\n} from \"@opengeni/sdk\";\n\nexport type IdentityLinkClient = {\n previewIdentityLink(\n workspaceId: string,\n linkId: string,\n challenge: string,\n ): Promise<ExternalIdentityLinkPreview>;\n confirmIdentityLink(\n workspaceId: string,\n linkId: string,\n input: ConfirmExternalIdentityLinkRequest,\n ): Promise<ExternalIdentityLink>;\n revokeIdentityLink(\n workspaceId: string,\n linkId: string,\n expectedRevision: number,\n ): Promise<ExternalIdentityLink>;\n};\nexport type IdentityLinkConsentProps = {\n client: IdentityLinkClient;\n workspaceId: string;\n linkId: string;\n challenge: string;\n /** Host label is explanatory, never proof of the requesting application. */\n className?: string;\n onComplete?: (link: ExternalIdentityLink) => void;\n};\n\n/** Optional native-login consent. Ordinary Connect does not use this surface.\n * Permission choices only narrow the server's request; no automatic approval. */\nexport function IdentityLinkConsent({\n client,\n workspaceId,\n linkId,\n challenge,\n className,\n onComplete,\n}: IdentityLinkConsentProps) {\n const [link, setLink] = useState<ExternalIdentityLink | null>(null);\n const [preview, setPreview] = useState<ExternalIdentityLinkPreview | null>(null);\n const [selected, setSelected] = useState<ExternalIdentityLink[\"permissions\"]>([]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState(false);\n const [retry, setRetry] = useState(0);\n const generation = useRef(0);\n useEffect(() => {\n const current = ++generation.current;\n setLink(null);\n setPreview(null);\n setSelected([]);\n setBusy(true);\n setError(false);\n void client\n .previewIdentityLink(workspaceId, linkId, challenge)\n .then(\n (result) => {\n if (generation.current !== current) return;\n setPreview(result);\n setLink(result.link);\n setSelected(result.link.permissions);\n },\n () => {\n if (generation.current === current) setError(true);\n },\n )\n .finally(() => {\n if (generation.current === current) setBusy(false);\n });\n return () => {\n // Invalidate live async work, rather than cleaning up a captured DOM node.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n generation.current++;\n };\n }, [client, workspaceId, linkId, challenge, retry]);\n async function mutate(revoke: boolean) {\n if (!link || busy) return;\n const current = generation.current;\n setBusy(true);\n setError(false);\n try {\n const result = revoke\n ? await client.revokeIdentityLink(workspaceId, linkId, link.revision)\n : await client.confirmIdentityLink(workspaceId, linkId, {\n challenge,\n expectedRevision: link.revision,\n permissions: selected,\n });\n if (generation.current !== current) return;\n setLink(result);\n onComplete?.(result);\n } catch {\n if (generation.current === current) setError(true);\n } finally {\n if (generation.current === current) setBusy(false);\n }\n }\n return (\n <section\n className={[\"og-connect og-identity-link\", className].filter(Boolean).join(\" \")}\n aria-label=\"Link your account\"\n aria-busy={busy}\n >\n <h2>Link your OpenGeni account</h2>\n <p>\n Only continue if you started this request in a product you trust. Linking lets that product\n act as your account with the permissions you select. It does not merge accounts or move\n existing work.\n </p>\n {preview && (\n <dl>\n <dt>Organization</dt>\n <dd>{preview.organizationId}</dd>\n <dt>Product user</dt>\n <dd>\n {preview.externalIdentity.externalId} ({preview.externalIdentity.source})\n </dd>\n <dt>Your OpenGeni identity</dt>\n <dd>{preview.nativeSubjectId}</dd>\n </dl>\n )}\n {error && (\n <div role=\"alert\">\n This request could not be completed. It may have expired, changed, or require you to sign\n in to the right organization.\n {!link && (\n <button type=\"button\" disabled={busy} onClick={() => setRetry((value) => value + 1)}>\n Try again\n </button>\n )}\n </div>\n )}\n {!link && busy && <p role=\"status\">Loading the account-link request…</p>}\n {link?.status === \"pending\" && (\n <>\n <p>\n {link.expiresAt\n ? `Access ends ${new Date(link.expiresAt).toLocaleString()}.`\n : \"Access lasts until you or the product revoke this link.\"}{\" \"}\n Your current permissions still apply.\n </p>\n <fieldset disabled={busy}>\n <legend>Allow these permissions</legend>\n {link.permissions.map((permission) => (\n <label key={permission}>\n <input\n type=\"checkbox\"\n checked={selected.includes(permission)}\n onChange={(event) =>\n setSelected((values) =>\n event.target.checked\n ? [...values, permission]\n : values.filter((value) => value !== permission),\n )\n }\n />\n <span>{permission.replaceAll(\":\", \" · \")}</span>\n </label>\n ))}\n </fieldset>\n <button\n type=\"button\"\n disabled={busy || selected.length === 0}\n onClick={() => void mutate(false)}\n >\n {busy ? \"Saving…\" : \"Allow selected access\"}\n </button>\n <p>You can close this page without granting access.</p>\n </>\n )}\n {link?.status === \"active\" && (\n <>\n <p role=\"status\">Account linked. Return to your product to continue.</p>\n <button type=\"button\" disabled={busy} onClick={() => void mutate(true)}>\n Revoke this link\n </button>\n </>\n )}\n {link?.status === \"revoked\" && (\n <p role=\"status\">Link revoked. Your OpenGeni account and existing work are unchanged.</p>\n )}\n {link?.status === \"expired\" && (\n <p role=\"status\">This request has expired. Start a new request from your product.</p>\n )}\n </section>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type { ExternalIdentityLink, ExternalIdentityLinkPage } from \"@opengeni/sdk\";\n\nexport type IdentityLinkAccountsClient = {\n listIdentityLinks(workspaceId: string, cursor?: string): Promise<ExternalIdentityLinkPage>;\n revokeIdentityLink(\n workspaceId: string,\n linkId: string,\n expectedRevision: number,\n ): Promise<ExternalIdentityLink>;\n};\n\n/** Participant-scoped inventory. Revocation never deletes native work or merges\n * identities. The caller remounts this component when the signed-in user changes. */\nexport function IdentityLinkAccounts({\n client,\n workspaceId,\n}: {\n client: IdentityLinkAccountsClient;\n workspaceId: string;\n}) {\n const [links, setLinks] = useState<ExternalIdentityLink[]>([]);\n const [cursor, setCursor] = useState<string | null>(null);\n const [busy, setBusy] = useState(true);\n const [error, setError] = useState(false);\n const [revision, setRevision] = useState(0);\n const generation = useRef(0);\n const inFlight = useRef(false);\n useEffect(() => {\n const current = ++generation.current;\n inFlight.current = true;\n setLinks([]);\n setCursor(null);\n setBusy(true);\n setError(false);\n void client\n .listIdentityLinks(workspaceId)\n .then(\n (page) => {\n if (current !== generation.current) return;\n setLinks(page.links);\n setCursor(page.nextCursor);\n },\n () => {\n if (current === generation.current) setError(true);\n },\n )\n .finally(() => {\n if (current === generation.current) {\n inFlight.current = false;\n setBusy(false);\n }\n });\n return () => {\n // Invalidate live async work, rather than cleaning up a captured DOM node.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n generation.current++;\n };\n }, [client, workspaceId, revision]);\n\n async function act(link?: ExternalIdentityLink) {\n if (inFlight.current || (!link && !cursor)) return;\n const current = generation.current;\n inFlight.current = true;\n setBusy(true);\n setError(false);\n try {\n if (link) {\n const updated = await client.revokeIdentityLink(workspaceId, link.id, link.revision);\n if (current === generation.current)\n setLinks((values) =>\n values.map((value) => (value.id === updated.id ? { ...value, ...updated } : value)),\n );\n } else {\n const page = await client.listIdentityLinks(workspaceId, cursor!);\n if (current === generation.current) {\n setLinks((values) => [\n ...new Map([...values, ...page.links].map((value) => [value.id, value])).values(),\n ]);\n setCursor(page.nextCursor);\n }\n }\n } catch {\n if (current === generation.current) setError(true);\n } finally {\n if (current === generation.current) {\n inFlight.current = false;\n setBusy(false);\n }\n }\n }\n return (\n <section\n className=\"og-connect og-identity-link\"\n aria-label=\"Linked product access\"\n aria-busy={busy}\n >\n <h2>Linked product access</h2>\n <p>\n Manage products allowed to act as your account in this organization. Revoking a link stops\n future linked access; it does not delete your work or undo an operation already started.\n </p>\n {error && (\n <div role=\"alert\">\n Could not update account links. Reload to see current access.\n <button type=\"button\" disabled={busy} onClick={() => setRevision((value) => value + 1)}>\n Reload links\n </button>\n </div>\n )}\n {busy && <p role=\"status\">Loading account links…</p>}\n {!busy && !error && links.length === 0 && (\n <p>No products have linked access to this account.</p>\n )}\n <ul>\n {links.map((link) => (\n <li key={link.id}>\n <p>\n {link.externalIdentity?.source || \"Product identity\"}{\" \"}\n <code>{link.externalIdentity?.externalId ?? link.externalIdentityId}</code>\n </p>\n <p>\n Status: {link.status}.{\" \"}\n {link.expiresAt\n ? `Expires ${new Date(link.expiresAt).toLocaleString()}.`\n : \"No automatic expiry.\"}\n </p>\n <p>{link.permissions.join(\", \")}</p>\n {(link.status === \"active\" || link.status === \"pending\") && (\n <button type=\"button\" disabled={busy} onClick={() => void act(link)}>\n Revoke access\n </button>\n )}\n </li>\n ))}\n </ul>\n {cursor && (\n <button type=\"button\" disabled={busy} onClick={() => void act()}>\n Load more links\n </button>\n )}\n </section>\n );\n}\n"],"mappings":"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","names":["useState","jsx","jsxs","useState","useEffect","useState","jsx","jsxs","useState","useEffect","jsx","jsxs","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","useEffect","useRef","useState","Fragment","jsx","jsxs","useEffect","useRef","useState","jsx","jsxs"]}
1
+ {"version":3,"sources":["../src/connect.ts","../src/connect-setup.tsx","../src/connect-chooser.tsx","../src/connect-accounts.tsx","../src/connect-panel.tsx","../src/device-authorization.tsx","../src/identity-link-consent.tsx","../src/identity-link-accounts.tsx"],"sourcesContent":["// Optional, unstyled React adapter over the shared headless controller.\n// The host owns controller lifetime; unmounting one observer does not cancel an\n// attempt another observer is displaying or a durable backend operation.\nimport { useMemo, useSyncExternalStore } from \"react\";\nimport type { ConnectController } from \"@opengeni/connect\";\nexport { ConnectSetup, type ConnectSetupProps } from \"./connect-setup\";\nexport { ConnectChooser, type ConnectChooserProps } from \"./connect-chooser\";\nexport { ConnectAccounts, type ConnectAccountsProps } from \"./connect-accounts\";\nexport { ConnectPanel, type ConnectPanelProps } from \"./connect-panel\";\nexport { DeviceAuthorization, type DeviceAuthorizationProps } from \"./device-authorization\";\nexport {\n IdentityLinkConsent,\n type IdentityLinkClient,\n type IdentityLinkConsentProps,\n} from \"./identity-link-consent\";\nexport { IdentityLinkAccounts, type IdentityLinkAccountsClient } from \"./identity-link-accounts\";\n\nexport type { ConnectSnapshot } from \"@opengeni/connect\";\nexport type {\n ConnectAccount,\n ConnectAdvance,\n ConnectAttempt,\n ConnectNextAction,\n ConnectOwnership,\n ConnectProvider,\n ConnectResource,\n ConnectTransport,\n} from \"@opengeni/connect\";\n\nexport function useConnect(controller: ConnectController) {\n const snapshot = useSyncExternalStore(\n controller.subscribe,\n controller.getSnapshot,\n controller.getSnapshot,\n );\n const actions = useMemo(\n () => ({\n begin: controller.begin.bind(controller),\n recover: controller.recover.bind(controller),\n refresh: controller.refresh.bind(controller),\n waitForAction: controller.waitForAction.bind(controller),\n advance: controller.advance.bind(controller),\n cancel: controller.cancel.bind(controller),\n }),\n [controller],\n );\n return useMemo(() => ({ ...snapshot, ...actions }), [snapshot, actions]);\n}\n","import { useState, type FormEvent } from \"react\";\nimport type { ConnectAttempt, ConnectController } from \"@opengeni/connect\";\nimport { useConnect } from \"./connect\";\n\nconst setupStatus: Record<ConnectAttempt[\"state\"], string> = {\n ready: \"Ready to connect\",\n requires_user_action: \"Authorize your account\",\n credential_input: \"Enter connection details\",\n provider_wait: \"Waiting for authorization\",\n account_selection: \"Choose an account\",\n resource_selection: \"Choose resources\",\n preview: \"Review available operations\",\n installing: \"Installing selected operations…\",\n connected_but_incomplete: \"Account connected — finish setup\",\n complete: \"Connection ready\",\n cancelled: \"Setup cancelled\",\n expired: \"Setup expired\",\n failed: \"Setup could not finish\",\n uncertain: \"Setup outcome needs checking\",\n};\n\nfunction deviceVerificationUrl(action: ConnectAttempt[\"nextAction\"]): string | null {\n if (action.type !== \"wait\" || !action.verificationUrl) return null;\n try {\n const url = new URL(action.verificationUrl);\n return url.protocol === \"https:\" && !url.username && !url.password\n ? action.verificationUrl\n : null;\n } catch {\n return null;\n }\n}\n\nexport type ConnectSetupProps = {\n controller: ConnectController;\n /** Called synchronously in the click handler so a host can open a popup. */\n onAuthorize: (attempt: ConnectAttempt) => void | Promise<unknown>;\n /** Host pagination must retain selections across pages and submit the final set. */\n onBrowseResources?: (attempt: ConnectAttempt) => void | Promise<unknown>;\n className?: string;\n};\n\n/** Unstyled setup surface. No provider secrets enter React state. Host owns\n * chooser, controller lifetime, navigation and recovery after full redirect. */\nexport function ConnectSetup(props: ConnectSetupProps) {\n // Attempt IDs/revisions are not a substitute for actor scope. A host can\n // recover the same attempt through a replacement controller; never preserve\n // a previous actor's unsent credential DOM or local errors across that swap.\n const [scope, setScope] = useState(props.controller);\n const [generation, setGeneration] = useState(0);\n if (scope !== props.controller) {\n setScope(props.controller);\n setGeneration(generation + 1);\n }\n return <ScopedSetup key={generation} {...props} />;\n}\n\nfunction ScopedSetup({ controller, onAuthorize, onBrowseResources, className }: ConnectSetupProps) {\n const view = useConnect(controller);\n const [localError, setLocalError] = useState(false);\n const invoke = (operation: () => unknown | Promise<unknown>) => {\n setLocalError(false);\n try {\n void Promise.resolve(operation()).catch(() => setLocalError(true));\n } catch {\n setLocalError(true);\n }\n };\n const attempt = view.attempt;\n if (!attempt)\n return (\n <section className={className} aria-label=\"Connection setup\">\n <p role=\"status\">Choose a connection to begin.</p>\n </section>\n );\n const action = attempt.nextAction;\n const verificationUrl = deviceVerificationUrl(action);\n const terminal = [\"complete\", \"cancelled\", \"expired\"].includes(attempt.state);\n const submit = (event: FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n const form = event.currentTarget;\n const data = new FormData(form);\n if (view.busy) return;\n const key = crypto.randomUUID();\n if (action.type === \"credentials\") {\n const values = Object.fromEntries(\n action.fields.map((field, i) => [field.name, String(data.get(`field-${i}`) ?? \"\")]),\n );\n // Clear the DOM before awaiting remote work; controller never retains values.\n form.reset();\n invoke(() => view.advance({ type: \"credentials\", values }, key));\n } else if (action.type === \"select_account\") {\n const accountId = String(data.get(\"account\") ?? \"\");\n if (\n action.accounts.some((account) => account.id === accountId && account.status !== \"disabled\")\n )\n invoke(() => view.advance({ type: \"account\", accountId }, key));\n } else if (action.type === \"select_resources\") {\n if (action.cursor) return;\n const resourceIds = data.getAll(\"resource\").map(String);\n invoke(() => view.advance({ type: \"resources\", resourceIds }, key));\n } else if (action.type === \"preview\") {\n const operationIds = data.getAll(\"operation\").map(String);\n invoke(() =>\n view.advance(\n {\n type: \"install\",\n previewId: action.previewId,\n contentHash: action.contentHash,\n operationIds,\n },\n key,\n ),\n );\n }\n };\n return (\n <section className={className} aria-label=\"Connection setup\" aria-busy={view.busy}>\n <p>Ownership: {attempt.ownership === \"personal\" ? \"Personal\" : \"Workspace\"}</p>\n <p role=\"status\">{setupStatus[attempt.state]}</p>\n {attempt.account && <p>Account: {attempt.account.label}</p>}\n {(localError || view.error || attempt.error) && (\n <p role=\"alert\">\n {attempt.error?.code === \"source_changed\"\n ? \"The integration source changed. Review the new operations before installing.\"\n : \"Connection setup could not continue. Refresh its status before trying again.\"}\n </p>\n )}\n {!terminal && (\n <form key={`${attempt.id}:${attempt.revision}`} onSubmit={submit} autoComplete=\"off\">\n <fieldset disabled={view.busy}>\n <legend>Connection details</legend>\n {attempt.state === \"connected_but_incomplete\" && action.type === \"none\" && (\n <button\n type=\"button\"\n onClick={() => invoke(() => view.advance({ type: \"retry\" }, crypto.randomUUID()))}\n >\n Review integration operations\n </button>\n )}\n {action.type === \"credentials\" &&\n action.fields.map((field, i) => (\n <label key={field.name}>\n {field.label}\n {field.options ? (\n <select name={`field-${i}`} required={field.required} defaultValue=\"\">\n <option value=\"\">\n {field.required ? \"Choose an option\" : \"No account (public service)\"}\n </option>\n {field.options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label}\n </option>\n ))}\n </select>\n ) : (\n <input\n name={`field-${i}`}\n type={field.secret ? \"password\" : \"text\"}\n required={field.required}\n autoComplete=\"off\"\n />\n )}\n </label>\n ))}\n {action.type === \"select_account\" && (\n <label>\n Account\n <select name=\"account\" required defaultValue=\"\">\n <option value=\"\" disabled>\n Choose an account\n </option>\n {action.accounts.map((account) => (\n <option\n key={account.id}\n value={account.id}\n disabled={account.status === \"disabled\"}\n >\n {account.label} — {account.id} ({account.ownership})\n </option>\n ))}\n </select>\n </label>\n )}\n {action.type === \"select_resources\" &&\n action.resources.map((resource) => (\n <label key={resource.id}>\n <input type=\"checkbox\" name=\"resource\" value={resource.id} />\n {resource.label} ({resource.kind})\n </label>\n ))}\n {action.type === \"select_resources\" && action.cursor && (\n <>\n <p>More resources are available. Review all pages before submitting a selection.</p>\n {onBrowseResources && (\n <button\n type=\"button\"\n onClick={() => invoke(() => onBrowseResources(structuredClone(attempt)))}\n >\n Browse all resources\n </button>\n )}\n </>\n )}\n {action.type === \"preview\" && (\n <>\n <p>Select the operations to install.</p>\n {action.operations.map((operation) => (\n <label key={operation.id}>\n <input type=\"checkbox\" name=\"operation\" value={operation.id} />\n {operation.label} ({operation.kind})\n </label>\n ))}\n </>\n )}\n {[\"credentials\", \"select_account\", \"select_resources\", \"preview\"].includes(\n action.type,\n ) && (\n <button\n type=\"submit\"\n disabled={action.type === \"select_resources\" && Boolean(action.cursor)}\n >\n {action.type === \"preview\" ? \"Install selected operations\" : \"Continue\"}\n </button>\n )}\n {action.type === \"authorize\" && (\n <button\n type=\"button\"\n onClick={() => invoke(() => onAuthorize(structuredClone(attempt)))}\n >\n Authorize connection\n </button>\n )}\n {action.type === \"wait\" && (\n <>\n {action.userCode && (\n <p>\n Verification code: <code>{action.userCode}</code>\n </p>\n )}\n <p>Complete provider authorization, then check the connection status.</p>\n {verificationUrl && (\n <a href={verificationUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n Open provider verification page (new tab)\n </a>\n )}\n </>\n )}\n <button type=\"button\" onClick={() => invoke(() => view.refresh())}>\n Check status\n </button>\n <button type=\"button\" onClick={() => invoke(() => view.cancel(crypto.randomUUID()))}>\n Cancel setup\n </button>\n </fieldset>\n </form>\n )}\n </section>\n );\n}\n","import { useEffect, useState, type FormEvent } from \"react\";\nimport type { ConnectController, ConnectProvider } from \"@opengeni/connect\";\nimport { useConnect } from \"./connect\";\n\nexport type ConnectChooserProps = {\n controller: ConnectController;\n /** Exact host return string; no completion parameters are added. */\n returnUrl: string;\n className?: string;\n};\n\n/** Catalog readiness is supplied by the authenticated backend, never inferred\n * from the existence of a provider definition. Host replaces the controller on\n * actor/workspace change. This form does not open OAuth windows itself. */\nexport function ConnectChooser(props: ConnectChooserProps) {\n // Remount scope-local selections synchronously when the controller changes,\n // before effects can expose a previous actor's inventory for one frame.\n const [scope, setScope] = useState(props.controller);\n const [generation, setGeneration] = useState(0);\n if (scope !== props.controller) {\n setScope(props.controller);\n setGeneration(generation + 1);\n }\n return <ScopedChooser key={generation} {...props} />;\n}\n\nfunction ScopedChooser({ controller, returnUrl, className }: ConnectChooserProps) {\n const view = useConnect(controller);\n const [catalog, setCatalog] = useState<ConnectProvider[] | null>(null);\n const [failed, setFailed] = useState(false);\n const [load, setLoad] = useState(0);\n const [providerId, setProviderId] = useState(\"\");\n const [ownership, setOwnership] = useState(\"\");\n useEffect(() => {\n const abort = new AbortController();\n setCatalog(null);\n setFailed(false);\n setProviderId(\"\");\n setOwnership(\"\");\n // Promise boundary also handles a synchronously throwing injected transport.\n void Promise.resolve()\n .then(() => {\n abort.signal.throwIfAborted();\n return controller.transport.catalog(controller.workspaceId, { signal: abort.signal });\n })\n .then((providers) => {\n if (!abort.signal.aborted) setCatalog(structuredClone(providers));\n })\n .catch(() => {\n if (!abort.signal.aborted) setFailed(true);\n });\n return () => abort.abort();\n }, [controller, load]);\n const provider = catalog?.find((entry) => entry.id === providerId);\n const canBegin =\n provider?.readiness === \"available\" &&\n (ownership === \"personal\" || ownership === \"workspace\") &&\n provider.ownership.includes(ownership);\n const submit = (event: FormEvent) => {\n event.preventDefault();\n if (!canBegin || view.busy || (ownership !== \"personal\" && ownership !== \"workspace\")) return;\n setFailed(false);\n try {\n void controller\n .begin({ providerId, ownership, returnUrl, idempotencyKey: crypto.randomUUID() })\n .catch(() => setFailed(true));\n } catch {\n setFailed(true);\n }\n };\n return (\n <section\n className={className}\n aria-label=\"Choose a connection\"\n aria-busy={view.busy || (!catalog && !failed)}\n >\n {failed && (\n <p role=\"alert\">\n Connections could not be loaded or started. Check setup status before retrying.\n </p>\n )}\n {!catalog && !failed && <p role=\"status\">Loading connections…</p>}\n {catalog?.length === 0 && <p role=\"status\">No connections are available.</p>}\n {Boolean(catalog?.length) && (\n <form onSubmit={submit}>\n <fieldset disabled={view.busy}>\n <legend>Provider and ownership</legend>\n <label>\n Provider\n <select\n required\n value={providerId}\n onChange={(event) => {\n setProviderId(event.target.value);\n setOwnership(\"\");\n }}\n >\n <option value=\"\" disabled>\n Choose a provider\n </option>\n {catalog!.map((entry) => (\n <option\n key={entry.id}\n value={entry.id}\n disabled={entry.readiness !== \"available\" || entry.ownership.length === 0}\n >\n {entry.label} — {entry.id} ({entry.readiness.replaceAll(\"_\", \" \")})\n </option>\n ))}\n </select>\n </label>\n {provider && (\n <label>\n Ownership\n <select\n required\n value={ownership}\n onChange={(event) => setOwnership(event.target.value)}\n >\n <option value=\"\" disabled>\n Choose ownership\n </option>\n {provider.ownership.map((choice) => (\n <option key={choice} value={choice}>\n {choice === \"personal\"\n ? \"Personal — owned by you\"\n : \"Workspace — shared connection\"}\n </option>\n ))}\n </select>\n </label>\n )}\n <button type=\"submit\" disabled={!canBegin}>\n Start setup\n </button>\n </fieldset>\n </form>\n )}\n <button type=\"button\" disabled={view.busy} onClick={() => setLoad(load + 1)}>\n Reload providers\n </button>\n </section>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type { ConnectAccount, ConnectController } from \"@opengeni/connect\";\nimport { useConnect } from \"./connect\";\n\nexport type ConnectAccountsProps = {\n controller: ConnectController;\n className?: string;\n /** Enables explicit account-bound reconnect. Host supplies the exact destination. */\n returnUrl?: string;\n};\n\n/** Local credential revocation only. Unknown or changed versions must be\n * refreshed; this component never retries a destructive operation implicitly. */\nexport function ConnectAccounts(props: ConnectAccountsProps) {\n const [scope, setScope] = useState(props.controller);\n const [generation, setGeneration] = useState(0);\n if (scope !== props.controller) {\n setScope(props.controller);\n setGeneration(generation + 1);\n }\n return <ScopedAccounts key={generation} {...props} />;\n}\n\nfunction ScopedAccounts({ controller, className, returnUrl }: ConnectAccountsProps) {\n const view = useConnect(controller);\n const [accounts, setAccounts] = useState<ConnectAccount[] | null>(null);\n const [selected, setSelected] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState(false);\n const [reload, setReload] = useState(0);\n const mutation = useRef<AbortController | null>(null);\n useEffect(() => () => mutation.current?.abort(), []);\n useEffect(() => {\n const abort = new AbortController();\n setAccounts(null);\n setSelected(null);\n setError(false);\n void Promise.resolve()\n .then(() => {\n abort.signal.throwIfAborted();\n return controller.transport.accounts(controller.workspaceId, { signal: abort.signal });\n })\n .then((result) => {\n if (!abort.signal.aborted) setAccounts(structuredClone(result));\n })\n .catch(() => {\n if (!abort.signal.aborted) setError(true);\n });\n return () => abort.abort();\n }, [controller, reload]);\n\n const disconnect = async (account: ConnectAccount) => {\n const expectedVersion = account.version;\n if (\n mutation.current ||\n view.busy ||\n expectedVersion === undefined ||\n !Number.isSafeInteger(expectedVersion) ||\n expectedVersion < 1\n )\n return;\n const abort = new AbortController();\n mutation.current = abort;\n setBusy(true);\n setError(false);\n try {\n await controller.transport.disconnect(controller.workspaceId, account.id, {\n expectedVersion,\n signal: abort.signal,\n });\n if (!abort.signal.aborted) setReload((value) => value + 1);\n } catch {\n if (!abort.signal.aborted) {\n // Outcome may be unknown. Drop the inventory so a second click cannot\n // replay against the stale selection; let the host reload live state.\n setAccounts(null);\n setError(true);\n }\n } finally {\n if (!abort.signal.aborted) {\n mutation.current = null;\n setBusy(false);\n setSelected(null);\n }\n }\n };\n const reconnect = async (account: ConnectAccount) => {\n if (!returnUrl || mutation.current || view.busy) return;\n setError(false);\n try {\n await controller.begin({\n providerId: account.providerId,\n ownership: account.ownership,\n reconnectAccountId: account.id,\n returnUrl,\n idempotencyKey: crypto.randomUUID(),\n });\n } catch {\n setError(true);\n }\n };\n\n return (\n <section\n className={className}\n aria-label=\"Connected accounts\"\n aria-busy={busy || view.busy || (!accounts && !error)}\n >\n {error && (\n <p role=\"alert\">Account state could not be confirmed. Reload before trying again.</p>\n )}\n {!accounts && !error && <p role=\"status\">Loading accounts…</p>}\n {accounts?.length === 0 && <p role=\"status\">No connected accounts.</p>}\n {accounts && accounts.length > 0 && (\n <ul>\n {accounts.map((account) => (\n <li key={`${account.providerId}:${account.id}`}>\n <span>\n {account.label} — {account.providerId} — {account.ownership} —{\" \"}\n {account.status.replaceAll(\"_\", \" \")}\n </span>\n {returnUrl && (\n <button\n type=\"button\"\n disabled={busy || view.busy || account.status === \"disabled\"}\n onClick={() => void reconnect(account)}\n >\n Reconnect {account.label}\n </button>\n )}\n {selected === `${account.providerId}:${account.id}` ? (\n <div role=\"group\" aria-label={`Disconnect ${account.label}`}>\n <p>\n This removes local OpenGeni access. It does not revoke consent at the provider.\n </p>\n <button\n type=\"button\"\n disabled={busy || view.busy}\n onClick={() => void disconnect(account)}\n >\n Confirm disconnect\n </button>\n <button type=\"button\" disabled={busy} onClick={() => setSelected(null)}>\n Keep account\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n disabled={\n busy ||\n view.busy ||\n account.status === \"disabled\" ||\n !Number.isSafeInteger(account.version) ||\n account.version! < 1\n }\n onClick={() => setSelected(`${account.providerId}:${account.id}`)}\n >\n Disconnect {account.label}\n </button>\n )}\n </li>\n ))}\n </ul>\n )}\n <button type=\"button\" disabled={busy} onClick={() => setReload((value) => value + 1)}>\n Reload accounts\n </button>\n </section>\n );\n}\n","import { ConnectAccounts } from \"./connect-accounts\";\nimport { ConnectChooser } from \"./connect-chooser\";\nimport { ConnectSetup, type ConnectSetupProps } from \"./connect-setup\";\n\nexport type ConnectPanelProps = ConnectSetupProps & {\n returnUrl: string;\n title?: string;\n showAccounts?: boolean;\n};\n\n/** Optional composition over the same unstyled surfaces. Import\n * @opengeni/react/connect.css for styling; the host retains navigation,\n * transport, actor admission, and controller lifetime. */\nexport function ConnectPanel({\n returnUrl,\n title = \"Connections\",\n showAccounts = true,\n className,\n ...setup\n}: ConnectPanelProps) {\n return (\n <div className={[\"og-connect\", className].filter(Boolean).join(\" \")}>\n <h2>{title}</h2>\n <ConnectChooser controller={setup.controller} returnUrl={returnUrl} />\n <ConnectSetup {...setup} />\n {showAccounts && <ConnectAccounts controller={setup.controller} returnUrl={returnUrl} />}\n </div>\n );\n}\n","import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport { copyTextToClipboard } from \"./clipboard\";\n\nexport type DeviceAuthorizationProps = {\n userCode: string;\n verificationUri: string;\n providerLabel?: string;\n description?: string;\n className?: string;\n codeAttributes?: Record<`data-${string}`, string>;\n loadClipboard?: () => Promise<{ copyTextToClipboard(text: string): Promise<boolean> }>;\n onCopyResult?: (copied: boolean) => void;\n /** Optional host presentation; clipboard state and URL validation remain shared. */\n render?: (state: {\n copied: boolean;\n copyError: boolean;\n copy: () => Promise<void>;\n verificationHref: string | undefined;\n }) => ReactNode;\n};\n\n/** Optional presentation for the existing model-account device APIs. It neither\n * owns provider state nor assumes that opening a verification page completed it. */\nexport function DeviceAuthorization(props: DeviceAuthorizationProps) {\n const [copied, setCopied] = useState(false);\n const [copyError, setCopyError] = useState(false);\n const generation = useRef(0);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => {\n generation.current++;\n setCopied(false);\n setCopyError(false);\n return () => {\n // This is a live async-operation counter, not a captured DOM ref.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n generation.current++;\n if (timer.current) clearTimeout(timer.current);\n };\n }, [props.userCode]);\n async function copy() {\n const revision = ++generation.current;\n if (timer.current) clearTimeout(timer.current);\n setCopied(false);\n setCopyError(false);\n try {\n const clipboard = props.loadClipboard ? await props.loadClipboard() : { copyTextToClipboard };\n if (revision !== generation.current) return;\n const success = await clipboard.copyTextToClipboard(props.userCode);\n if (revision !== generation.current) return;\n setCopied(success);\n setCopyError(!success);\n props.onCopyResult?.(success);\n if (success)\n timer.current = setTimeout(() => {\n if (revision === generation.current) setCopied(false);\n }, 1600);\n } catch {\n if (revision !== generation.current) return;\n setCopyError(true);\n props.onCopyResult?.(false);\n }\n }\n let href: string | undefined;\n try {\n const url = new URL(props.verificationUri);\n if ([\"https:\", \"http:\"].includes(url.protocol) && !url.username && !url.password)\n href = props.verificationUri;\n } catch {\n /* A malformed provider URL must never become an executable link. */\n }\n if (props.render) return props.render({ copied, copyError, copy, verificationHref: href });\n return (\n <section className={`og-connect ${props.className ?? \"\"}`} aria-label=\"Device authorization\">\n <p>{props.description ?? `Enter this code at ${props.providerLabel ?? \"the provider\"}.`}</p>\n <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: \"0.5rem\", alignItems: \"center\" }}>\n <code {...props.codeAttributes} style={{ overflowWrap: \"anywhere\" }}>\n {props.userCode}\n </code>\n <button\n type=\"button\"\n aria-label={copied ? \"Code copied\" : \"Copy code\"}\n onClick={() => void copy()}\n >\n {copied ? \"Copied\" : \"Copy code\"}\n </button>\n {href ? (\n <a href={href} target=\"_blank\" rel=\"noopener noreferrer\">\n Open {props.providerLabel ?? \"auth page\"}\n </a>\n ) : (\n <span role=\"alert\">Authorization address unavailable.</span>\n )}\n </div>\n {copyError ? <p role=\"alert\">Couldn't copy the code. Copy it manually instead.</p> : null}\n <p role=\"status\">Waiting for authorization…</p>\n </section>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type {\n ExternalIdentityLink,\n ConfirmExternalIdentityLinkRequest,\n ExternalIdentityLinkPreview,\n} from \"@opengeni/sdk\";\n\nexport type IdentityLinkClient = {\n previewIdentityLink(\n workspaceId: string,\n linkId: string,\n challenge: string,\n ): Promise<ExternalIdentityLinkPreview>;\n confirmIdentityLink(\n workspaceId: string,\n linkId: string,\n input: ConfirmExternalIdentityLinkRequest,\n ): Promise<ExternalIdentityLink>;\n revokeIdentityLink(\n workspaceId: string,\n linkId: string,\n expectedRevision: number,\n ): Promise<ExternalIdentityLink>;\n};\nexport type IdentityLinkConsentProps = {\n client: IdentityLinkClient;\n workspaceId: string;\n linkId: string;\n challenge: string;\n /** Host label is explanatory, never proof of the requesting application. */\n className?: string;\n onComplete?: (link: ExternalIdentityLink) => void;\n};\n\n/** Optional native-login consent. Ordinary Connect does not use this surface.\n * Permission choices only narrow the server's request; no automatic approval. */\nexport function IdentityLinkConsent({\n client,\n workspaceId,\n linkId,\n challenge,\n className,\n onComplete,\n}: IdentityLinkConsentProps) {\n const [link, setLink] = useState<ExternalIdentityLink | null>(null);\n const [preview, setPreview] = useState<ExternalIdentityLinkPreview | null>(null);\n const [selected, setSelected] = useState<ExternalIdentityLink[\"permissions\"]>([]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState(false);\n const [retry, setRetry] = useState(0);\n const generation = useRef(0);\n useEffect(() => {\n const current = ++generation.current;\n setLink(null);\n setPreview(null);\n setSelected([]);\n setBusy(true);\n setError(false);\n void client\n .previewIdentityLink(workspaceId, linkId, challenge)\n .then(\n (result) => {\n if (generation.current !== current) return;\n setPreview(result);\n setLink(result.link);\n setSelected(result.link.permissions);\n },\n () => {\n if (generation.current === current) setError(true);\n },\n )\n .finally(() => {\n if (generation.current === current) setBusy(false);\n });\n return () => {\n // Invalidate live async work, rather than cleaning up a captured DOM node.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n generation.current++;\n };\n }, [client, workspaceId, linkId, challenge, retry]);\n async function mutate(revoke: boolean) {\n if (!link || busy) return;\n const current = generation.current;\n setBusy(true);\n setError(false);\n try {\n const result = revoke\n ? await client.revokeIdentityLink(workspaceId, linkId, link.revision)\n : await client.confirmIdentityLink(workspaceId, linkId, {\n challenge,\n expectedRevision: link.revision,\n permissions: selected,\n });\n if (generation.current !== current) return;\n setLink(result);\n onComplete?.(result);\n } catch {\n if (generation.current === current) setError(true);\n } finally {\n if (generation.current === current) setBusy(false);\n }\n }\n return (\n <section\n className={[\"og-connect og-identity-link\", className].filter(Boolean).join(\" \")}\n aria-label=\"Link your account\"\n aria-busy={busy}\n >\n <h2>Link your OpenGeni account</h2>\n <p>\n Only continue if you started this request in a product you trust. Linking lets that product\n act as your account with the permissions you select. It does not merge accounts or move\n existing work.\n </p>\n {preview && (\n <dl>\n <dt>Organization</dt>\n <dd>{preview.organizationId}</dd>\n <dt>Product user</dt>\n <dd>\n {preview.externalIdentity.externalId} ({preview.externalIdentity.source})\n </dd>\n <dt>Your OpenGeni identity</dt>\n <dd>{preview.nativeSubjectId}</dd>\n </dl>\n )}\n {error && (\n <div role=\"alert\">\n This request could not be completed. It may have expired, changed, or require you to sign\n in to the right organization.\n {!link && (\n <button type=\"button\" disabled={busy} onClick={() => setRetry((value) => value + 1)}>\n Try again\n </button>\n )}\n </div>\n )}\n {!link && busy && <p role=\"status\">Loading the account-link request…</p>}\n {link?.status === \"pending\" && (\n <>\n <p>\n {link.expiresAt\n ? `Access ends ${new Date(link.expiresAt).toLocaleString()}.`\n : \"Access lasts until you or the product revoke this link.\"}{\" \"}\n Your current permissions still apply.\n </p>\n <fieldset disabled={busy}>\n <legend>Allow these permissions</legend>\n {link.permissions.map((permission) => (\n <label key={permission}>\n <input\n type=\"checkbox\"\n checked={selected.includes(permission)}\n onChange={(event) =>\n setSelected((values) =>\n event.target.checked\n ? [...values, permission]\n : values.filter((value) => value !== permission),\n )\n }\n />\n <span>{permission.replaceAll(\":\", \" · \")}</span>\n </label>\n ))}\n </fieldset>\n <button\n type=\"button\"\n disabled={busy || selected.length === 0}\n onClick={() => void mutate(false)}\n >\n {busy ? \"Saving…\" : \"Allow selected access\"}\n </button>\n <p>You can close this page without granting access.</p>\n </>\n )}\n {link?.status === \"active\" && (\n <>\n <p role=\"status\">Account linked. Return to your product to continue.</p>\n <button type=\"button\" disabled={busy} onClick={() => void mutate(true)}>\n Revoke this link\n </button>\n </>\n )}\n {link?.status === \"revoked\" && (\n <p role=\"status\">Link revoked. Your OpenGeni account and existing work are unchanged.</p>\n )}\n {link?.status === \"expired\" && (\n <p role=\"status\">This request has expired. Start a new request from your product.</p>\n )}\n </section>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type { ExternalIdentityLink, ExternalIdentityLinkPage } from \"@opengeni/sdk\";\n\nexport type IdentityLinkAccountsClient = {\n listIdentityLinks(workspaceId: string, cursor?: string): Promise<ExternalIdentityLinkPage>;\n revokeIdentityLink(\n workspaceId: string,\n linkId: string,\n expectedRevision: number,\n ): Promise<ExternalIdentityLink>;\n};\n\n/** Participant-scoped inventory. Revocation never deletes native work or merges\n * identities. The caller remounts this component when the signed-in user changes. */\nexport function IdentityLinkAccounts({\n client,\n workspaceId,\n}: {\n client: IdentityLinkAccountsClient;\n workspaceId: string;\n}) {\n const [links, setLinks] = useState<ExternalIdentityLink[]>([]);\n const [cursor, setCursor] = useState<string | null>(null);\n const [busy, setBusy] = useState(true);\n const [error, setError] = useState(false);\n const [revision, setRevision] = useState(0);\n const generation = useRef(0);\n const inFlight = useRef(false);\n useEffect(() => {\n const current = ++generation.current;\n inFlight.current = true;\n setLinks([]);\n setCursor(null);\n setBusy(true);\n setError(false);\n void client\n .listIdentityLinks(workspaceId)\n .then(\n (page) => {\n if (current !== generation.current) return;\n setLinks(page.links);\n setCursor(page.nextCursor);\n },\n () => {\n if (current === generation.current) setError(true);\n },\n )\n .finally(() => {\n if (current === generation.current) {\n inFlight.current = false;\n setBusy(false);\n }\n });\n return () => {\n // Invalidate live async work, rather than cleaning up a captured DOM node.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n generation.current++;\n };\n }, [client, workspaceId, revision]);\n\n async function act(link?: ExternalIdentityLink) {\n if (inFlight.current || (!link && !cursor)) return;\n const current = generation.current;\n inFlight.current = true;\n setBusy(true);\n setError(false);\n try {\n if (link) {\n const updated = await client.revokeIdentityLink(workspaceId, link.id, link.revision);\n if (current === generation.current)\n setLinks((values) =>\n values.map((value) => (value.id === updated.id ? { ...value, ...updated } : value)),\n );\n } else {\n const page = await client.listIdentityLinks(workspaceId, cursor!);\n if (current === generation.current) {\n setLinks((values) => [\n ...new Map([...values, ...page.links].map((value) => [value.id, value])).values(),\n ]);\n setCursor(page.nextCursor);\n }\n }\n } catch {\n if (current === generation.current) setError(true);\n } finally {\n if (current === generation.current) {\n inFlight.current = false;\n setBusy(false);\n }\n }\n }\n return (\n <section\n className=\"og-connect og-identity-link\"\n aria-label=\"Linked product access\"\n aria-busy={busy}\n >\n <h2>Linked product access</h2>\n <p>\n Manage products allowed to act as your account in this organization. Revoking a link stops\n future linked access; it does not delete your work or undo an operation already started.\n </p>\n {error && (\n <div role=\"alert\">\n Could not update account links. Reload to see current access.\n <button type=\"button\" disabled={busy} onClick={() => setRevision((value) => value + 1)}>\n Reload links\n </button>\n </div>\n )}\n {busy && <p role=\"status\">Loading account links…</p>}\n {!busy && !error && links.length === 0 && (\n <p>No products have linked access to this account.</p>\n )}\n <ul>\n {links.map((link) => (\n <li key={link.id}>\n <p>\n {link.externalIdentity?.source || \"Product identity\"}{\" \"}\n <code>{link.externalIdentity?.externalId ?? link.externalIdentityId}</code>\n </p>\n <p>\n Status: {link.status}.{\" \"}\n {link.expiresAt\n ? `Expires ${new Date(link.expiresAt).toLocaleString()}.`\n : \"No automatic expiry.\"}\n </p>\n <p>{link.permissions.join(\", \")}</p>\n {(link.status === \"active\" || link.status === \"pending\") && (\n <button type=\"button\" disabled={busy} onClick={() => void act(link)}>\n Revoke access\n </button>\n )}\n </li>\n ))}\n </ul>\n {cursor && (\n <button type=\"button\" disabled={busy} onClick={() => void act()}>\n Load more links\n </button>\n )}\n </section>\n );\n}\n"],"mappings":"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","names":["useState","jsx","jsxs","useState","useEffect","useState","jsx","jsxs","useState","useEffect","jsx","jsxs","useEffect","useRef","useState","jsx","jsxs","useState","useRef","useEffect","useEffect","useRef","useState","Fragment","jsx","jsxs","useEffect","useRef","useState","jsx","jsxs"]}
@@ -1,3 +1,4 @@
1
+ import { type ReactNode } from "react";
1
2
  export type DeviceAuthorizationProps = {
2
3
  userCode: string;
3
4
  verificationUri: string;
@@ -9,7 +10,14 @@ export type DeviceAuthorizationProps = {
9
10
  copyTextToClipboard(text: string): Promise<boolean>;
10
11
  }>;
11
12
  onCopyResult?: (copied: boolean) => void;
13
+ /** Optional host presentation; clipboard state and URL validation remain shared. */
14
+ render?: (state: {
15
+ copied: boolean;
16
+ copyError: boolean;
17
+ copy: () => Promise<void>;
18
+ verificationHref: string | undefined;
19
+ }) => ReactNode;
12
20
  };
13
21
  /** Optional presentation for the existing model-account device APIs. It neither
14
22
  * owns provider state nor assumes that opening a verification page completed it. */
15
- export declare function DeviceAuthorization(props: DeviceAuthorizationProps): import("react").JSX.Element;
23
+ export declare function DeviceAuthorization(props: DeviceAuthorizationProps): string | number | bigint | boolean | import("react").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | Iterable<ReactNode> | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | import("react").ReactPortal | null | undefined> | null | undefined;
package/dist/index.js CHANGED
@@ -8765,6 +8765,7 @@ function SandboxWorkspace(props) {
8765
8765
  trailingTabs,
8766
8766
  initialTab,
8767
8767
  onActiveTabChange,
8768
+ openTabRequest,
8768
8769
  initialFilePath,
8769
8770
  onFilePathChange,
8770
8771
  isFileNodeVisible,
@@ -8793,6 +8794,27 @@ function SandboxWorkspace(props) {
8793
8794
  const nextFileRequestId = useRef17(0);
8794
8795
  const nextComputerRequestId = useRef17(0);
8795
8796
  const selectedTab = storedSelection?.sessionId === sessionId ? storedSelection.tab : null;
8797
+ const handledTabRequest = useRef17(null);
8798
+ useEffect20(() => {
8799
+ if (!openTabRequest || handledTabRequest.current?.sessionId === sessionId && handledTabRequest.current.requestId === openTabRequest.requestId)
8800
+ return;
8801
+ const available = [...leadingTabs ?? [], ...trailingTabs ?? []].some(
8802
+ (tab) => tab.id === openTabRequest.tab
8803
+ ) || (surfaces ?? WORKBENCH_SURFACES).some((tab) => tab === openTabRequest.tab);
8804
+ if (!available) return;
8805
+ handledTabRequest.current = { sessionId, requestId: openTabRequest.requestId };
8806
+ setStoredSelection({ sessionId, tab: openTabRequest.tab });
8807
+ onActiveTabChange?.(openTabRequest.tab);
8808
+ onCollapsedChange?.(false);
8809
+ }, [
8810
+ openTabRequest,
8811
+ sessionId,
8812
+ leadingTabs,
8813
+ trailingTabs,
8814
+ surfaces,
8815
+ onActiveTabChange,
8816
+ onCollapsedChange
8817
+ ]);
8796
8818
  const activeTabHint = selectedTab ?? initialTab ?? leadingTabs?.[0]?.id ?? null;
8797
8819
  const openFile = useCallback24(
8798
8820
  (path, line) => {