@workos-inc/widgets 1.16.0-next.1785954585478 → 1.16.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/CHANGELOG.md +7 -1
- package/dist/cjs/lib/elements.cjs +2 -2
- package/dist/cjs/lib/elements.cjs.map +1 -1
- package/dist/cjs/lib/pipes-admin.cjs +7 -8
- package/dist/cjs/lib/pipes-admin.cjs.map +1 -1
- package/dist/cjs/lib/pipes.cjs +462 -133
- package/dist/cjs/lib/pipes.cjs.map +1 -1
- package/dist/cjs/lib/redacted-secret.cjs +33 -0
- package/dist/cjs/lib/redacted-secret.cjs.map +1 -0
- package/dist/cjs/lib/redacted-secret.d.cts +6 -0
- package/dist/esm/lib/elements.js +2 -2
- package/dist/esm/lib/elements.js.map +1 -1
- package/dist/esm/lib/pipes-admin.js +2 -3
- package/dist/esm/lib/pipes-admin.js.map +1 -1
- package/dist/esm/lib/pipes.js +465 -135
- package/dist/esm/lib/pipes.js.map +1 -1
- package/dist/esm/lib/redacted-secret.d.ts +6 -0
- package/dist/esm/lib/redacted-secret.js +8 -0
- package/dist/esm/lib/redacted-secret.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/pipes.tsx"],"sourcesContent":["\"use client\";\nimport { Callout, Card, Flex, Text } from \"@radix-ui/themes\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport * as CardList from \"./card-list.js\";\nimport { DataIntegrationIcon } from \"./data-integration-icon.js\";\nimport { ProviderIcon } from \"./provider-icon.js\";\nimport {\n DotsHorizontalIcon,\n ExternalLinkIcon,\n GlobeIcon,\n LockClosedIcon,\n} from \"@radix-ui/react-icons\";\nimport {\n AlertDialog,\n Button,\n Dialog,\n DropdownMenu,\n IconButton,\n Label,\n PasswordField,\n Skeleton,\n TextField,\n} from \"./elements.js\";\nimport { IconPanel } from \"./icon-panel.js\";\nimport { Status } from \"./status.js\";\nimport {\n DataIntegration,\n DataIntegrationConfigField,\n getMyDataIntegrationsQueryKey,\n useAuthorizeDataIntegrationHook,\n useDeleteDataInstallation,\n useSettings,\n useUpsertDataIntegrationApiKey,\n} from \"../api/endpoint.js\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { GenericError } from \"./generic-error.js\";\nimport { getDomProps, WidgetRootDomProps, WidgetRootState } from \"./utils.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\nimport { ApiError } from \"../api/errors.js\";\n\ninterface PipesProps extends WidgetRootDomProps {\n integrations: DataIntegration[];\n}\n\nconst HANDOFF_INTERVAL_MS = 100;\nconst HANDOFF_MAX_ATTEMPTS = 100; // 10 seconds worth of attempts\n\nconst useOpenDataIntegrationAuthorizeUrl = (integration: DataIntegration) => {\n const authorizeDataIntegration = useAuthorizeDataIntegrationHook();\n const settings = useSettings();\n const baseUrl = settings.data?.authkitOrigin ?? \"\";\n const intervalRef = useRef<ReturnType<typeof setInterval> | undefined>(\n undefined,\n );\n const messageHandlerRef = useRef<((event: MessageEvent) => void) | undefined>(\n undefined,\n );\n\n useEffect(() => {\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n if (messageHandlerRef.current) {\n window.removeEventListener(\"message\", messageHandlerRef.current);\n }\n };\n }, []);\n\n return useCallback(\n async (config?: Record<string, string>) => {\n // Clear any existing interval from a previous invocation\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = undefined;\n }\n // Remove any existing message handler\n if (messageHandlerRef.current) {\n window.removeEventListener(\"message\", messageHandlerRef.current);\n messageHandlerRef.current = undefined;\n }\n\n // need to do this synchronously in the event handler to avoid popup blocker notifications\n const win = window.open(`${baseUrl}/pipes/redirecting`, \"_blank\");\n // A blocked popup yields null; fail loudly (caller catches) instead of\n // authorizing and then discarding the redirect into a phantom success.\n if (!win) {\n throw new Error(\"Unable to open the authorization window.\");\n }\n\n // caller will catch. Close the popup on failure so a network/permission/\n // config error doesn't strand a blank /pipes/redirecting tab.\n let authorization;\n try {\n authorization = await authorizeDataIntegration(integration.slug, {\n requireHandoff: true,\n config,\n });\n } catch (error) {\n win.close();\n throw error;\n }\n const { url, handoffToken, redirectToken } = authorization;\n if (win) {\n win.location = url;\n const parsedUrl = new URL(url);\n const payload = { handoffToken, redirectToken };\n\n const cleanup = () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = undefined;\n }\n if (messageHandlerRef.current) {\n window.removeEventListener(\"message\", messageHandlerRef.current);\n messageHandlerRef.current = undefined;\n }\n };\n\n messageHandlerRef.current = (event: MessageEvent) => {\n if (\n event.origin === parsedUrl.origin &&\n event.data?.redirectToken === redirectToken\n ) {\n cleanup();\n }\n };\n window.addEventListener(\"message\", messageHandlerRef.current);\n\n let attempts = 0;\n intervalRef.current = setInterval(() => {\n attempts += 1;\n\n if (attempts >= HANDOFF_MAX_ATTEMPTS) {\n cleanup();\n return;\n }\n\n if (win && !win.closed) {\n win.postMessage(payload, parsedUrl.origin);\n } else {\n cleanup();\n }\n }, HANDOFF_INTERVAL_MS);\n }\n },\n [authorizeDataIntegration, integration.slug, baseUrl],\n );\n};\n\n/**\n * Returns the provider-declared `installation`-scope config fields that the\n * integration has not pinned a value for, sorted by descriptor `order`. These\n * are the fields the connect flow must prompt for (pin / prompt-if-unset).\n */\nfunction getUnpinnedInstallationFields(\n integration: DataIntegration,\n): DataIntegrationConfigField[] {\n return (integration.configFields ?? [])\n .filter(\n (field) =>\n field.scope === \"installation\" && !integration.config?.[field.key],\n )\n .sort((a, b) => (a.order ?? 0) - (b.order ?? 0));\n}\n\n/** Gray dot separator shown between the logos in the connect-dialog header. */\nfunction LogoSeparator() {\n return (\n <DotsHorizontalIcon\n width=\"20\"\n height=\"20\"\n style={{ color: \"var(--gray-8)\" }}\n />\n );\n}\n\n/**\n * Shared connect-dialog header: the WorkOS → provider icon row and the\n * \"{app} uses WorkOS to connect to {provider}\" title.\n */\nfunction ConnectDialogHeader({\n integration,\n}: {\n integration: DataIntegration;\n}) {\n const settings = useSettings();\n const logo = settings.data?.logoDarkPath ?? settings.data?.logoLightPath;\n const appName = settings.data?.teamName ?? \"This application\";\n\n return (\n <>\n <Flex justify=\"center\" align=\"center\" gap=\"2\" mt=\"2\">\n {logo && (\n <>\n <IconPanel color=\"panel\" style={{ width: \"48px\", height: \"48px\" }}>\n <ProviderIcon\n size=\"2\"\n provider=\"workos\"\n style={{ backgroundImage: `url(${logo})` }}\n />\n </IconPanel>\n <LogoSeparator />\n </>\n )}\n <IconPanel\n color=\"panel\"\n style={{\n ...(logo ? { borderWidth: 0 } : undefined),\n width: \"48px\",\n height: \"48px\",\n }}\n >\n <ProviderIcon size=\"2\" provider=\"workos\" />\n </IconPanel>\n <LogoSeparator />\n <IconPanel color=\"panel\" style={{ width: \"48px\", height: \"48px\" }}>\n <DataIntegrationIcon size=\"2\" integration={integration} />\n </IconPanel>\n </Flex>\n <Dialog.Title size=\"2\" mt=\"5\" mb=\"5\" weight={\"bold\"} align=\"center\">\n <Translation\n defaultMessage=\"{appName} uses WorkOS to connect to {integrationName}.\"\n id=\"ujRDBH\"\n description=\"Dialog title explaining the app connection flow\"\n values={{ appName, integrationName: integration.name }}\n />\n </Dialog.Title>\n </>\n );\n}\n\n/**\n * Shared connect-dialog explainer card: \"you'll be redirected to sign in\" +\n * \"your credentials remain secure\".\n */\nfunction ConnectExplainerCard({\n integration,\n}: {\n integration: DataIntegration;\n}) {\n return (\n <Card>\n <Flex direction=\"column\" gap=\"4\">\n <Flex gap=\"2\" align=\"center\">\n <IconPanel color=\"gray\" style={{ width: \"32px\", height: \"32px\" }}>\n <GlobeIcon />\n </IconPanel>\n <Flex direction=\"column\">\n <Text size=\"1\" weight=\"bold\">\n <Translation\n defaultMessage=\"You'll be redirected to sign in with {integrationName}.\"\n id=\"g+n4aY\"\n description=\"Instruction about redirect to sign in\"\n values={{ integrationName: integration.name }}\n />\n </Text>\n <Text size=\"1\">\n <Translation\n defaultMessage=\"Authorize access to connect your account.\"\n id=\"fxVS34\"\n description=\"Instruction to authorize access\"\n />\n </Text>\n </Flex>\n </Flex>\n <Flex gap=\"2\" align=\"center\">\n <IconPanel color=\"gray\" style={{ width: \"32px\", height: \"32px\" }}>\n <LockClosedIcon />\n </IconPanel>\n <Flex direction=\"column\">\n <Text size=\"1\" weight=\"bold\">\n <Translation\n defaultMessage=\"Your credentials remain secure.\"\n id=\"gM3bot\"\n description=\"Security message about credentials\"\n />\n </Text>\n <Text size=\"1\">\n <Translation\n defaultMessage=\"WorkOS never sees your credentials.\"\n id=\"kC9Fwe\"\n description=\"Security message about WorkOS not seeing credentials\"\n />\n </Text>\n </Flex>\n </Flex>\n </Flex>\n </Card>\n );\n}\n\n/**\n * The single connect dialog for all non-API (OAuth) providers. When the\n * provider declares unpinned `installation`-scope config fields (e.g. a Zendesk\n * subdomain), it opens on a field-collection step (values validated against the\n * descriptor `required` / `pattern`) before the redirect explainer; otherwise\n * it opens directly on the explainer. Collected values are submitted as\n * `config` on the POST authorize call. Controlled so it backs the initial\n * connect flow, the dual-method OAuth option, and reauthorization.\n */\nfunction ConnectDialog({\n integration,\n fields,\n open,\n onOpenChange,\n}: {\n integration: DataIntegration;\n fields: DataIntegrationConfigField[];\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n // Providers without fields to collect skip straight to the explainer.\n const initialStep = fields.length > 0 ? \"fields\" : \"review\";\n const [step, setStep] = useState<\"fields\" | \"review\">(initialStep);\n const [values, setValues] = useState<Record<string, string>>({});\n const [errors, setErrors] = useState<Record<string, string | null>>({});\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const eventHandler = useOpenDataIntegrationAuthorizeUrl(integration);\n const translate = useTranslation();\n\n const requiredMessage = translate({\n defaultMessage: \"This field is required\",\n id: \"B2HvfC\",\n description:\n \"Validation error shown when a required configuration field is left empty\",\n });\n const patternMessage = translate({\n defaultMessage: \"Enter a valid value.\",\n id: \"2XWaGz\",\n description:\n \"Validation error shown when a configuration field value does not match the expected format\",\n });\n const genericConnectError = translate({\n defaultMessage: \"We couldn't start the connection. Please try again.\",\n id: \"zGw1ma\",\n description:\n \"Fallback error shown when starting the connection fails for a non-specific reason\",\n });\n\n const reset = () => {\n setStep(initialStep);\n setValues({});\n setErrors({});\n setSubmitError(null);\n setIsSubmitting(false);\n };\n\n const validateFields = () => {\n const nextErrors: Record<string, string | null> = {};\n let valid = true;\n for (const field of fields) {\n const value = (values[field.key] ?? \"\").trim();\n if (field.required && !value) {\n nextErrors[field.key] = requiredMessage;\n valid = false;\n continue;\n }\n if (value && field.pattern) {\n let matches = true;\n try {\n matches = new RegExp(field.pattern).test(value);\n } catch {\n // Ignore invalid descriptor patterns client-side; the API validates.\n matches = true;\n }\n if (!matches) {\n nextErrors[field.key] = patternMessage;\n valid = false;\n continue;\n }\n }\n nextErrors[field.key] = null;\n }\n setErrors(nextErrors);\n return valid;\n };\n\n const buildConfig = () => {\n const config: Record<string, string> = {};\n for (const field of fields) {\n const value = (values[field.key] ?? \"\").trim();\n if (value) {\n config[field.key] = value;\n }\n }\n return config;\n };\n\n const hasMissingRequired = fields.some(\n (field) => field.required && !(values[field.key] ?? \"\").trim(),\n );\n\n const handleConnect = async () => {\n setSubmitError(null);\n setIsSubmitting(true);\n try {\n // Opens the popup synchronously within this click before awaiting.\n await eventHandler(buildConfig());\n onOpenChange(false);\n } catch (error) {\n // Surface a message for every failure mode (ApiError, network, blocked\n // popup, etc.) so the dialog never fails silently.\n setSubmitError(\n error instanceof ApiError && error.message\n ? error.message\n : genericConnectError,\n );\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n <Dialog.Root\n open={open}\n onOpenChange={(next) => {\n onOpenChange(next);\n if (!next) {\n reset();\n }\n }}\n >\n <Dialog.Content maxWidth=\"430px\">\n <ConnectDialogHeader integration={integration} />\n\n {step === \"fields\" ? (\n <>\n <Card>\n <Flex direction=\"column\" gap=\"4\">\n {fields.map((field) => {\n const fieldId = `pipes-config-${field.key}`;\n const errorId = `${fieldId}-error`;\n const descriptionId = `${fieldId}-description`;\n const error = errors[field.key];\n const Control = field.secret ? PasswordField : TextField;\n const describedBy =\n [\n field.description ? descriptionId : null,\n error ? errorId : null,\n ]\n .filter(Boolean)\n .join(\" \") || undefined;\n return (\n <Flex key={field.key} direction=\"column\" gap=\"1\">\n <Label htmlFor={fieldId}>{field.label}</Label>\n {field.description ? (\n <Text color=\"gray\" size=\"2\" id={descriptionId} mb=\"1\">\n {field.description}\n </Text>\n ) : null}\n <Control\n id={fieldId}\n value={values[field.key] ?? \"\"}\n placeholder={field.example}\n autoComplete=\"off\"\n required={field.required || undefined}\n aria-invalid={!!error || undefined}\n aria-describedby={describedBy}\n onChange={(event) => {\n setValues((prev) => ({\n ...prev,\n [field.key]: event.target.value,\n }));\n if (error) {\n setErrors((prev) => ({\n ...prev,\n [field.key]: null,\n }));\n }\n }}\n />\n {error ? (\n <Text color=\"red\" size=\"2\" id={errorId}>\n {error}\n </Text>\n ) : null}\n </Flex>\n );\n })}\n </Flex>\n </Card>\n <Flex justify=\"end\" gap=\"3\" mt=\"5\">\n <Dialog.Close>\n <Button variant=\"secondary\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Dialog.Close>\n <Button\n type=\"button\"\n disabled={hasMissingRequired}\n onClick={() => {\n if (validateFields()) {\n setStep(\"review\");\n }\n }}\n >\n <Translation\n defaultMessage=\"Next\"\n id=\"L2fmxK\"\n description=\"Button to advance to the next step of the connect flow\"\n />\n </Button>\n </Flex>\n </>\n ) : (\n <>\n {submitError && (\n <Callout.Root mb=\"3\" color=\"red\" role=\"alert\">\n <Callout.Text>{submitError}</Callout.Text>\n </Callout.Root>\n )}\n <ConnectExplainerCard integration={integration} />\n <Flex justify=\"end\" gap=\"3\" mt=\"5\">\n {fields.length > 0 ? (\n <Button\n variant=\"secondary\"\n type=\"button\"\n onClick={() => setStep(\"fields\")}\n >\n <Translation\n defaultMessage=\"Back\"\n id=\"J9MvVP\"\n description=\"Button to return to the previous step of the connect flow\"\n />\n </Button>\n ) : (\n <Dialog.Close>\n <Button variant=\"secondary\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Dialog.Close>\n )}\n <Button\n type=\"button\"\n loading={isSubmitting}\n disabled={isSubmitting}\n onClick={handleConnect}\n >\n <Translation\n defaultMessage=\"Connect\"\n id=\"16WmG0\"\n description=\"Connect button with external link\"\n trailingSpace\n />\n <ExternalLinkIcon aria-hidden />\n </Button>\n </Flex>\n </>\n )}\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\n/**\n * Connect button for a not-yet-connected OAuth provider. Opens the unified\n * {@link ConnectDialog}, which prompts for any unpinned `installation`-scope\n * config fields before the redirect explainer.\n */\nfunction ConnectIntegrationButton({\n integration,\n}: {\n integration: DataIntegration;\n}) {\n const [open, setOpen] = useState(false);\n const fields = getUnpinnedInstallationFields(integration);\n\n return (\n <>\n <ConnectDialog\n integration={integration}\n fields={fields}\n open={open}\n onOpenChange={setOpen}\n />\n <Button variant=\"secondary\" onClick={() => setOpen(true)}>\n <Translation\n defaultMessage=\"Connect\"\n id=\"quvdFp\"\n description=\"Button to connect an integration\"\n />\n </Button>\n </>\n );\n}\n\nconst API_KEY_REDACTED_PREFIX = \"••••\";\n\nfunction ApiKeyDialog({\n integration,\n open,\n onOpenChange,\n}: {\n integration: DataIntegration;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const queryClient = useQueryClient();\n const installation = integration.installation;\n const isRotation =\n installation?.auth_method === \"api_key\" &&\n installation.state === \"connected\";\n const last4 = installation?.api_key_last_4;\n const maskedKey = last4 ? `${API_KEY_REDACTED_PREFIX}${last4}` : \"\";\n\n const [secret, setSecret] = useState(\"\");\n const translate = useTranslation();\n\n const apiKeyPlaceholder = translate({\n defaultMessage: \"Enter your API key\",\n id: \"MzSxEF\",\n description: \"Placeholder for the API key input field\",\n });\n\n const {\n mutate: upsertApiKey,\n error,\n reset,\n isPending,\n } = useUpsertDataIntegrationApiKey({\n mutation: {\n onSuccess: () => {\n onOpenChange(false);\n queryClient.invalidateQueries({\n queryKey: getMyDataIntegrationsQueryKey(),\n });\n },\n },\n });\n\n // The component is only mounted while open (conditional rendering in\n // ApiKeyConnectButton / ProviderStatus), so state resets on mount.\n // We only need to reset the mutation state when the dialog opens in\n // case the same instance was reused.\n useEffect(() => {\n reset();\n }, [reset]);\n\n const errorMessage = (() => {\n if (!error) return null;\n if (error instanceof ApiError && error.message) {\n return error.message;\n }\n return null;\n })();\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Content maxWidth=\"430px\">\n <Dialog.Title size=\"3\" weight=\"bold\">\n {isRotation ? (\n <Translation\n defaultMessage=\"Rotate API key for {integrationName}\"\n id=\"8+NN3t\"\n description=\"Dialog title for rotating an API key\"\n values={{ integrationName: integration.name }}\n />\n ) : (\n <Translation\n defaultMessage=\"Connect {integrationName} with API key\"\n id=\"EyItbA\"\n description=\"Dialog title for connecting with an API key\"\n values={{ integrationName: integration.name }}\n />\n )}\n </Dialog.Title>\n\n {error && (\n <Callout.Root my=\"3\" color=\"red\" role=\"alert\">\n <Callout.Text>\n {errorMessage ?? (\n <Translation\n defaultMessage=\"An error occurred. Please check the value and try again.\"\n id=\"bYLbLL\"\n description=\"Generic error message for API key submission failure\"\n />\n )}\n </Callout.Text>\n </Callout.Root>\n )}\n\n <Flex direction=\"column\" gap=\"4\" mt=\"2\">\n {isRotation && last4 && (\n <Flex direction=\"column\" gap=\"1\">\n <Label>\n <Translation\n defaultMessage=\"Current API key\"\n id=\"+odk8g\"\n description=\"Label for the current masked API key\"\n />\n </Label>\n <Text size=\"2\" color=\"gray\">\n {maskedKey}\n </Text>\n </Flex>\n )}\n\n <Flex direction=\"column\" gap=\"1\">\n <Label>\n {isRotation ? (\n <Translation\n defaultMessage=\"New API key\"\n id=\"L3AmMK\"\n description=\"Label for the new API key input when rotating\"\n />\n ) : (\n <Translation\n defaultMessage=\"API key\"\n id=\"Xnkv+J\"\n description=\"Label for the API key input\"\n />\n )}\n </Label>\n <PasswordField\n value={secret}\n autoComplete=\"off\"\n placeholder={apiKeyPlaceholder}\n onChange={(event) => setSecret(event.target.value)}\n />\n </Flex>\n </Flex>\n\n <Flex justify=\"end\" gap=\"3\" mt=\"5\">\n <Dialog.Close>\n <Button variant=\"secondary\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Dialog.Close>\n <Button\n type=\"button\"\n disabled={isPending || !secret.trim()}\n loading={isPending}\n onClick={() =>\n upsertApiKey({\n slug: integration.slug,\n data: { secret: secret.trim() },\n })\n }\n >\n {isRotation ? (\n <Translation\n defaultMessage=\"Rotate\"\n id=\"LAh+p5\"\n description=\"Button to rotate an API key\"\n />\n ) : (\n <Translation\n defaultMessage=\"Connect\"\n id=\"quvdFp\"\n description=\"Button to connect an integration\"\n />\n )}\n </Button>\n </Flex>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction ApiKeyConnectButton({\n integration,\n}: {\n integration: DataIntegration;\n}) {\n const [open, setOpen] = useState(false);\n\n return (\n <>\n {open && (\n <ApiKeyDialog\n integration={integration}\n open={open}\n onOpenChange={setOpen}\n />\n )}\n <Button variant=\"secondary\" onClick={() => setOpen(true)}>\n <Translation\n defaultMessage=\"Connect\"\n id=\"quvdFp\"\n description=\"Button to connect an integration\"\n />\n </Button>\n </>\n );\n}\n\nfunction DualMethodConnectButton({\n integration,\n}: {\n integration: DataIntegration;\n}) {\n const [apiKeyOpen, setApiKeyOpen] = useState(false);\n const [oauthOpen, setOauthOpen] = useState(false);\n const fields = getUnpinnedInstallationFields(integration);\n\n return (\n <>\n {apiKeyOpen && (\n <ApiKeyDialog\n integration={integration}\n open={apiKeyOpen}\n onOpenChange={setApiKeyOpen}\n />\n )}\n <ConnectDialog\n integration={integration}\n fields={fields}\n open={oauthOpen}\n onOpenChange={setOauthOpen}\n />\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <Button variant=\"secondary\">\n <Translation\n defaultMessage=\"Connect\"\n id=\"quvdFp\"\n description=\"Button to connect an integration\"\n />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n <DropdownMenu.Item onClick={() => setOauthOpen(true)}>\n <Flex gap=\"4\" width=\"100%\" justify=\"between\" align=\"center\">\n <Translation\n defaultMessage=\"Sign in with OAuth\"\n id=\"ssNz+0\"\n description=\"Menu option to connect via OAuth\"\n trailingSpace\n />\n <ExternalLinkIcon aria-hidden />\n </Flex>\n </DropdownMenu.Item>\n <DropdownMenu.Item onClick={() => setApiKeyOpen(true)}>\n <Translation\n defaultMessage=\"Enter API key\"\n id=\"8mq2DA\"\n description=\"Menu option to connect via API key\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </>\n );\n}\n\nfunction ProviderStatus({ integration }: { integration: DataIntegration }) {\n const [disconnectOpen, setDisconnectOpen] = useState(false);\n const [apiKeyOpen, setApiKeyOpen] = useState(false);\n const [reauthConfigOpen, setReauthConfigOpen] = useState(false);\n const authorizeEventHandler = useOpenDataIntegrationAuthorizeUrl(integration);\n const translate = useTranslation();\n\n const pipeActionsTitle = translate({\n defaultMessage: \"Pipe actions\",\n id: \"1uF9ve\",\n description: \"Title for pipe actions dropdown button\",\n });\n\n // Unpinned installation fields must be re-collected on reauthorization too;\n // the authorize endpoint rejects them as missing otherwise.\n const unpinnedFields = getUnpinnedInstallationFields(integration);\n\n if (integration.installation) {\n const connected = integration.installation.state === \"connected\";\n const isApiKeyInstallation =\n integration.installation.auth_method === \"api_key\";\n\n return (\n <>\n <DisconnectAccountDialog\n integrationName={integration.name}\n installationId={integration.installation.id}\n open={disconnectOpen}\n onOpenChange={setDisconnectOpen}\n />\n {apiKeyOpen && (\n <ApiKeyDialog\n integration={integration}\n open={apiKeyOpen}\n onOpenChange={setApiKeyOpen}\n />\n )}\n {unpinnedFields.length > 0 && (\n <ConnectDialog\n integration={integration}\n fields={unpinnedFields}\n open={reauthConfigOpen}\n onOpenChange={setReauthConfigOpen}\n />\n )}\n <Flex align=\"center\" gap=\"4\">\n <Status state={connected ? \"success\" : \"error\"}>\n {connected ? (\n <Translation\n defaultMessage=\"Connected\"\n id=\"i6Hxoz\"\n description=\"Status text for connected integration\"\n />\n ) : (\n <Translation\n defaultMessage=\"Requires reauthorization\"\n id=\"dqczQS\"\n description=\"Status text for integration needing reauthorization\"\n />\n )}\n </Status>\n {connected && isApiKeyInstallation ? (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton title={pipeActionsTitle}>\n <DotsHorizontalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n <DropdownMenu.Item onClick={() => setApiKeyOpen(true)}>\n <Translation\n defaultMessage=\"Rotate API key\"\n id=\"GML+c8\"\n description=\"Menu option to rotate the API key\"\n />\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onClick={() => setDisconnectOpen(true)}\n >\n <Translation\n defaultMessage=\"Disconnect account\"\n id=\"esZQrd\"\n description=\"Menu option to disconnect an account\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n ) : connected ? (\n <Button variant=\"secondary\" onClick={() => setDisconnectOpen(true)}>\n <Translation\n defaultMessage=\"Disconnect\"\n id=\"vMVXQh\"\n description=\"Button to disconnect an account\"\n />\n </Button>\n ) : isApiKeyInstallation ? (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton title={pipeActionsTitle}>\n <DotsHorizontalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n <DropdownMenu.Item onClick={() => setApiKeyOpen(true)}>\n <Translation\n defaultMessage=\"Update API key\"\n id=\"E7pMj/\"\n description=\"Menu option to update the API key for a needs-reauthorization installation\"\n />\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onClick={() => setDisconnectOpen(true)}\n >\n <Translation\n defaultMessage=\"Disconnect account\"\n id=\"esZQrd\"\n description=\"Menu option to disconnect an account\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n ) : (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton title={pipeActionsTitle}>\n <DotsHorizontalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n <DropdownMenu.Item\n onClick={async () => {\n if (unpinnedFields.length > 0) {\n setReauthConfigOpen(true);\n return;\n }\n try {\n await authorizeEventHandler();\n } catch {\n // pass - error displayed in new tab\n }\n }}\n >\n <Flex gap=\"4\" width=\"100%\" justify=\"between\" align=\"center\">\n <Translation\n defaultMessage=\"Reauthorize\"\n id=\"0E29F1\"\n description=\"Menu option to reauthorize an integration\"\n trailingSpace\n />\n <ExternalLinkIcon aria-hidden />\n </Flex>\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onClick={() => setDisconnectOpen(true)}\n >\n <Translation\n defaultMessage=\"Disconnect account\"\n id=\"esZQrd\"\n description=\"Menu option to disconnect an account\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n )}\n </Flex>\n </>\n );\n }\n\n // Not connected: choose the appropriate connect button based on authMethods\n const authMethods = integration.authMethods ?? [];\n const supportsOAuth = authMethods.includes(\"oauth\");\n const supportsApiKey = authMethods.includes(\"api_key\");\n\n // Dual-method: let the user choose\n if (supportsOAuth && supportsApiKey) {\n return (\n <Flex align=\"center\" gap=\"4\">\n <Status state=\"neutral\">\n <Translation\n defaultMessage=\"Not connected\"\n id=\"J7bTZa\"\n description=\"Status text for an integration that is not connected\"\n />\n </Status>\n <DualMethodConnectButton integration={integration} />\n </Flex>\n );\n }\n\n // API-key only\n if (supportsApiKey) {\n return (\n <Flex align=\"center\" gap=\"4\">\n <Status state=\"neutral\">\n <Translation\n defaultMessage=\"Not connected\"\n id=\"J7bTZa\"\n description=\"Status text for an integration that is not connected\"\n />\n </Status>\n <ApiKeyConnectButton integration={integration} />\n </Flex>\n );\n }\n\n // OAuth only: one unified connect dialog regardless of credentials type.\n return (\n <Flex align=\"center\" gap=\"4\">\n <Status state=\"neutral\">\n <Translation\n defaultMessage=\"Not connected\"\n id=\"J7bTZa\"\n description=\"Status text for an integration that is not connected\"\n />\n </Status>\n <ConnectIntegrationButton integration={integration} />\n </Flex>\n );\n}\n\nfunction DisconnectAccountDialog({\n integrationName,\n installationId,\n open,\n onOpenChange,\n}: {\n integrationName: string;\n installationId: string;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const queryClient = useQueryClient();\n const {\n mutate: deleteDataInstallation,\n error,\n reset,\n isPending,\n } = useDeleteDataInstallation({\n mutation: {\n onSuccess: () => {\n onOpenChange(false);\n queryClient.invalidateQueries({\n queryKey: getMyDataIntegrationsQueryKey(),\n });\n },\n },\n });\n\n useEffect(() => {\n if (open) {\n reset();\n }\n }, [open, reset]);\n\n return (\n <AlertDialog.Root open={open} onOpenChange={onOpenChange}>\n <AlertDialog.Content style={{ width: \"80vw\", maxWidth: \"520px\" }}>\n <AlertDialog.Title>\n <Translation\n defaultMessage=\"Disconnect account\"\n id=\"9ABlCr\"\n description=\"Dialog title for disconnecting an account\"\n />\n </AlertDialog.Title>\n {error && (\n <Callout.Root my=\"5\" color=\"red\" role=\"alert\">\n <Callout.Text>\n <Translation\n defaultMessage=\"An error occurred while disconnecting your account. Please refresh the page and try again.\"\n id=\"qKBKF7\"\n description=\"Error message when disconnecting an account fails\"\n />\n </Callout.Text>\n </Callout.Root>\n )}\n <AlertDialog.Description>\n <Translation\n defaultMessage=\"Are you sure you want to disconnect your {integrationName} account?\"\n id=\"eEXeqP\"\n description=\"Confirmation message for disconnecting an account\"\n values={{\n integrationName: (\n <Text as=\"span\" weight=\"bold\">\n {integrationName}\n </Text>\n ),\n }}\n />\n </AlertDialog.Description>\n <Flex gap=\"3\" justify=\"end\" mt=\"5\">\n <AlertDialog.Cancel>\n <Button variant=\"secondary\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </AlertDialog.Cancel>\n <Button\n variant=\"destructive\"\n disabled={isPending}\n loading={isPending}\n onClick={() => deleteDataInstallation({ installationId })}\n >\n <Translation\n defaultMessage=\"Disconnect\"\n id=\"vMVXQh\"\n description=\"Button to disconnect an account\"\n />\n </Button>\n </Flex>\n </AlertDialog.Content>\n </AlertDialog.Root>\n );\n}\n\ninterface PipesLoadingProps extends WidgetRootDomProps {\n count: number;\n}\n\nconst PipesLoading: React.FC<PipesLoadingProps> = ({ count, ...domProps }) => {\n return (\n <CardList.Root {...getWidgetRootDomProps(\"loading\", domProps)}>\n {Array.from({ length: count }).map((_, index) => (\n <CardList.Item key={index}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <Skeleton>\n <IconPanel>\n <ProviderIcon provider=\"google\" />\n </IconPanel>\n </Skeleton>\n <Skeleton>\n <Text size=\"2\" weight=\"bold\">\n <Translation\n defaultMessage=\"Google Drive\"\n id=\"g11OOu\"\n description=\"Placeholder text for loading state\"\n />\n </Text>\n </Skeleton>\n </Flex>\n <Skeleton>\n <Button variant=\"secondary\" disabled>\n <Translation\n defaultMessage=\"Connect\"\n id=\"8TuDfA\"\n description=\"Placeholder button text for loading state\"\n />\n </Button>\n </Skeleton>\n </Flex>\n </CardList.Item>\n ))}\n </CardList.Root>\n );\n};\n\nconst Pipes: React.FC<PipesProps> = ({ integrations, ...domProps }) => {\n return (\n <CardList.Root {...getWidgetRootDomProps(\"resolved\", domProps)}>\n {integrations.map((integration) => (\n <CardList.Item key={integration.id}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <IconPanel color=\"panel\">\n <DataIntegrationIcon integration={integration} />\n </IconPanel>\n <Text size=\"2\" weight=\"bold\">\n {integration.name}\n </Text>\n </Flex>\n <ProviderStatus integration={integration} />\n </Flex>\n </CardList.Item>\n ))}\n </CardList.Root>\n );\n};\n\ninterface PipesErrorProps extends WidgetRootDomProps {\n error: unknown;\n}\n\nconst PipesError: React.FC<PipesErrorProps> = ({ error, ...domProps }) => {\n return (\n <Card size=\"2\" {...getWidgetRootDomProps(\"error\", domProps)}>\n <GenericError error={error} />\n </Card>\n );\n};\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"pipes\",\n widgetState: state,\n });\n}\n\nexport type { PipesProps, PipesLoadingProps, PipesErrorProps };\nexport { Pipes, PipesLoading, PipesError };\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/pipes.tsx"],"sourcesContent":["\"use client\";\nimport { Callout, Card, Flex, Text } from \"@radix-ui/themes\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport * as CardList from \"./card-list.js\";\nimport { DataIntegrationIcon } from \"./data-integration-icon.js\";\nimport { ProviderIcon } from \"./provider-icon.js\";\nimport {\n DotsHorizontalIcon,\n ExternalLinkIcon,\n GlobeIcon,\n LockClosedIcon,\n} from \"@radix-ui/react-icons\";\nimport {\n AlertDialog,\n Button,\n Dialog,\n DropdownMenu,\n IconButton,\n Label,\n PasswordField,\n Skeleton,\n TextField,\n} from \"./elements.js\";\nimport { IconPanel } from \"./icon-panel.js\";\nimport { Status } from \"./status.js\";\nimport {\n DataIntegration,\n DataIntegrationConfigField,\n getMyDataIntegrationsQueryKey,\n useAuthorizeDataIntegrationHook,\n useDeleteDataInstallation,\n useSettings,\n useUpsertDataIntegrationApiKey,\n useUpsertDataIntegrationClientCredentials,\n} from \"../api/endpoint.js\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport { GenericError } from \"./generic-error.js\";\nimport { getDomProps, WidgetRootDomProps, WidgetRootState } from \"./utils.js\";\nimport { Translation } from \"./i18n/translation.js\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\nimport { ApiError } from \"../api/errors.js\";\nimport { buildRedactedSecret, isRedactedSecret } from \"./redacted-secret.js\";\n\ninterface PipesProps extends WidgetRootDomProps {\n integrations: DataIntegration[];\n}\n\nconst HANDOFF_INTERVAL_MS = 100;\nconst HANDOFF_MAX_ATTEMPTS = 100; // 10 seconds worth of attempts\n\ntype DataIntegrationAuthMethod = NonNullable<\n DataIntegration[\"authMethods\"]\n>[number];\n\n/** Supported connect methods, in the order they're offered to the user. */\nconst CONNECT_AUTH_METHODS: DataIntegrationAuthMethod[] = [\n \"oauth\",\n \"client_credentials\",\n \"api_key\",\n];\n\nconst useOpenDataIntegrationAuthorizeUrl = (integration: DataIntegration) => {\n const authorizeDataIntegration = useAuthorizeDataIntegrationHook();\n const settings = useSettings();\n const baseUrl = settings.data?.authkitOrigin ?? \"\";\n const intervalRef = useRef<ReturnType<typeof setInterval> | undefined>(\n undefined,\n );\n const messageHandlerRef = useRef<((event: MessageEvent) => void) | undefined>(\n undefined,\n );\n\n useEffect(() => {\n return () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n }\n if (messageHandlerRef.current) {\n window.removeEventListener(\"message\", messageHandlerRef.current);\n }\n };\n }, []);\n\n return useCallback(\n async (config?: Record<string, string>) => {\n // Clear any existing interval from a previous invocation\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = undefined;\n }\n // Remove any existing message handler\n if (messageHandlerRef.current) {\n window.removeEventListener(\"message\", messageHandlerRef.current);\n messageHandlerRef.current = undefined;\n }\n\n // need to do this synchronously in the event handler to avoid popup blocker notifications\n const win = window.open(`${baseUrl}/pipes/redirecting`, \"_blank\");\n // A blocked popup yields null; fail loudly (caller catches) instead of\n // authorizing and then discarding the redirect into a phantom success.\n if (!win) {\n throw new Error(\"Unable to open the authorization window.\");\n }\n\n // caller will catch. Close the popup on failure so a network/permission/\n // config error doesn't strand a blank /pipes/redirecting tab.\n let authorization;\n try {\n authorization = await authorizeDataIntegration(integration.slug, {\n requireHandoff: true,\n config,\n });\n } catch (error) {\n win.close();\n throw error;\n }\n const { url, handoffToken, redirectToken } = authorization;\n if (win) {\n win.location = url;\n const parsedUrl = new URL(url);\n const payload = { handoffToken, redirectToken };\n\n const cleanup = () => {\n if (intervalRef.current) {\n clearInterval(intervalRef.current);\n intervalRef.current = undefined;\n }\n if (messageHandlerRef.current) {\n window.removeEventListener(\"message\", messageHandlerRef.current);\n messageHandlerRef.current = undefined;\n }\n };\n\n messageHandlerRef.current = (event: MessageEvent) => {\n if (\n event.origin === parsedUrl.origin &&\n event.data?.redirectToken === redirectToken\n ) {\n cleanup();\n }\n };\n window.addEventListener(\"message\", messageHandlerRef.current);\n\n let attempts = 0;\n intervalRef.current = setInterval(() => {\n attempts += 1;\n\n if (attempts >= HANDOFF_MAX_ATTEMPTS) {\n cleanup();\n return;\n }\n\n if (win && !win.closed) {\n win.postMessage(payload, parsedUrl.origin);\n } else {\n cleanup();\n }\n }, HANDOFF_INTERVAL_MS);\n }\n },\n [authorizeDataIntegration, integration.slug, baseUrl],\n );\n};\n\n/**\n * Returns the provider-declared `installation`-scope config fields that the\n * integration has not pinned a value for, sorted by descriptor `order`. These\n * are the fields the connect flow must prompt for (pin / prompt-if-unset).\n */\nfunction getUnpinnedInstallationFields(\n integration: DataIntegration,\n): DataIntegrationConfigField[] {\n return (integration.configFields ?? [])\n .filter(\n (field) =>\n field.scope === \"installation\" && !integration.config?.[field.key],\n )\n .sort((a, b) => (a.order ?? 0) - (b.order ?? 0));\n}\n\n/**\n * Seed values for the descriptors from a stored `config` object, stringifying\n * the scalar values the inputs can round-trip and skipping anything else.\n */\nfunction getInitialConfigValues(\n fields: DataIntegrationConfigField[],\n storedConfig: Record<string, unknown>,\n): Record<string, string> {\n const values: Record<string, string> = {};\n for (const field of fields) {\n const stored = storedConfig[field.key];\n if (\n typeof stored === \"string\" ||\n typeof stored === \"number\" ||\n typeof stored === \"boolean\"\n ) {\n values[field.key] = String(stored);\n }\n }\n return values;\n}\n\n/**\n * Form state for a set of provider-declared config-field descriptors: the\n * collected values, inline validation against `required` / `pattern`, and the\n * `config` payload the connect endpoints accept. Shared by every connect\n * surface so descriptors are rendered and validated in exactly one place.\n *\n * `initialValues` prefills the inputs (e.g. from an existing installation's\n * stored config); `isDirty` reports whether the user actually changed any of\n * them, which callers use to decide whether to send `config` at all.\n */\nfunction useConfigFieldsForm(\n fields: DataIntegrationConfigField[],\n initialValues: Record<string, string> = {},\n) {\n const [values, setValues] = useState<Record<string, string>>(initialValues);\n const [errors, setErrors] = useState<Record<string, string | null>>({});\n const translate = useTranslation();\n\n const requiredMessage = translate({\n defaultMessage: \"This field is required\",\n id: \"B2HvfC\",\n description:\n \"Validation error shown when a required configuration field is left empty\",\n });\n const patternMessage = translate({\n defaultMessage: \"Enter a valid value.\",\n id: \"2XWaGz\",\n description:\n \"Validation error shown when a configuration field value does not match the expected format\",\n });\n\n const setValue = (key: string, value: string) => {\n setValues((prev) => ({ ...prev, [key]: value }));\n setErrors((prev) => (prev[key] ? { ...prev, [key]: null } : prev));\n };\n\n const reset = () => {\n setValues(initialValues);\n setErrors({});\n };\n\n const validate = () => {\n const nextErrors: Record<string, string | null> = {};\n let valid = true;\n for (const field of fields) {\n const value = (values[field.key] ?? \"\").trim();\n if (field.required && !value) {\n nextErrors[field.key] = requiredMessage;\n valid = false;\n continue;\n }\n if (value && field.pattern) {\n let matches = true;\n try {\n matches = new RegExp(field.pattern).test(value);\n } catch {\n // Ignore invalid descriptor patterns client-side; the API validates.\n matches = true;\n }\n if (!matches) {\n nextErrors[field.key] = patternMessage;\n valid = false;\n continue;\n }\n }\n nextErrors[field.key] = null;\n }\n setErrors(nextErrors);\n return valid;\n };\n\n const buildConfig = () => {\n const config: Record<string, string> = {};\n for (const field of fields) {\n const value = (values[field.key] ?? \"\").trim();\n if (value) {\n config[field.key] = value;\n }\n }\n return config;\n };\n\n /**\n * The full `config` object to write, given the config the API returned for\n * the installation. The write is a wholesale replace, so keys the widget\n * never rendered (pinned at the integration level, or unknown to these\n * descriptors) are preserved as received rather than dropped.\n */\n const buildConfigPayload = (storedConfig: Record<string, unknown>) => {\n const payload: Record<string, unknown> = { ...storedConfig };\n for (const field of fields) {\n const value = (values[field.key] ?? \"\").trim();\n if (value) {\n payload[field.key] = value;\n } else {\n delete payload[field.key];\n }\n }\n return payload;\n };\n\n const hasMissingRequired = fields.some(\n (field) => field.required && !(values[field.key] ?? \"\").trim(),\n );\n\n const isDirty = fields.some(\n (field) => (values[field.key] ?? \"\") !== (initialValues[field.key] ?? \"\"),\n );\n\n return {\n values,\n errors,\n setValue,\n reset,\n validate,\n buildConfig,\n buildConfigPayload,\n hasMissingRequired,\n isDirty,\n };\n}\n\n/**\n * Renders config-field descriptors as labelled inputs (secret descriptors get a\n * password field), with the description as help text and inline validation\n * errors wired up via `aria-invalid` / `aria-describedby`.\n */\nfunction ConfigFieldInputs({\n idPrefix,\n fields,\n values,\n errors,\n onChange,\n}: {\n idPrefix: string;\n fields: DataIntegrationConfigField[];\n values: Record<string, string>;\n errors: Record<string, string | null>;\n onChange: (key: string, value: string) => void;\n}) {\n return fields.map((field) => {\n const fieldId = `${idPrefix}-${field.key}`;\n const errorId = `${fieldId}-error`;\n const descriptionId = `${fieldId}-description`;\n const error = errors[field.key];\n const Control = field.secret ? PasswordField : TextField;\n const describedBy =\n [field.description ? descriptionId : null, error ? errorId : null]\n .filter(Boolean)\n .join(\" \") || undefined;\n return (\n <Flex key={field.key} direction=\"column\" gap=\"1\">\n <Label htmlFor={fieldId}>{field.label}</Label>\n {field.description ? (\n <Text color=\"gray\" size=\"2\" id={descriptionId} mb=\"1\">\n {field.description}\n </Text>\n ) : null}\n <Control\n id={fieldId}\n value={values[field.key] ?? \"\"}\n placeholder={field.example}\n autoComplete=\"off\"\n required={field.required || undefined}\n aria-invalid={!!error || undefined}\n aria-describedby={describedBy}\n onChange={(event) => onChange(field.key, event.target.value)}\n />\n {error ? (\n <Text color=\"red\" size=\"2\" id={errorId}>\n {error}\n </Text>\n ) : null}\n </Flex>\n );\n });\n}\n\n/** Gray dot separator shown between the logos in the connect-dialog header. */\nfunction LogoSeparator() {\n return (\n <DotsHorizontalIcon\n width=\"20\"\n height=\"20\"\n style={{ color: \"var(--gray-8)\" }}\n />\n );\n}\n\n/**\n * Shared connect-dialog header: the WorkOS → provider icon row and the\n * \"{app} uses WorkOS to connect to {provider}\" title.\n */\nfunction ConnectDialogHeader({\n integration,\n}: {\n integration: DataIntegration;\n}) {\n const settings = useSettings();\n const logo = settings.data?.logoDarkPath ?? settings.data?.logoLightPath;\n const appName = settings.data?.teamName ?? \"This application\";\n\n return (\n <>\n <Flex justify=\"center\" align=\"center\" gap=\"2\" mt=\"2\">\n {logo && (\n <>\n <IconPanel color=\"panel\" style={{ width: \"48px\", height: \"48px\" }}>\n <ProviderIcon\n size=\"2\"\n provider=\"workos\"\n style={{ backgroundImage: `url(${logo})` }}\n />\n </IconPanel>\n <LogoSeparator />\n </>\n )}\n <IconPanel\n color=\"panel\"\n style={{\n ...(logo ? { borderWidth: 0 } : undefined),\n width: \"48px\",\n height: \"48px\",\n }}\n >\n <ProviderIcon size=\"2\" provider=\"workos\" />\n </IconPanel>\n <LogoSeparator />\n <IconPanel color=\"panel\" style={{ width: \"48px\", height: \"48px\" }}>\n <DataIntegrationIcon size=\"2\" integration={integration} />\n </IconPanel>\n </Flex>\n <Dialog.Title size=\"2\" mt=\"5\" mb=\"5\" weight={\"bold\"} align=\"center\">\n <Translation\n defaultMessage=\"{appName} uses WorkOS to connect to {integrationName}.\"\n id=\"ujRDBH\"\n description=\"Dialog title explaining the app connection flow\"\n values={{ appName, integrationName: integration.name }}\n />\n </Dialog.Title>\n </>\n );\n}\n\n/**\n * Shared connect-dialog explainer card: \"you'll be redirected to sign in\" +\n * \"your credentials remain secure\".\n */\nfunction ConnectExplainerCard({\n integration,\n}: {\n integration: DataIntegration;\n}) {\n return (\n <Card>\n <Flex direction=\"column\" gap=\"4\">\n <Flex gap=\"2\" align=\"center\">\n <IconPanel color=\"gray\" style={{ width: \"32px\", height: \"32px\" }}>\n <GlobeIcon />\n </IconPanel>\n <Flex direction=\"column\">\n <Text size=\"1\" weight=\"bold\">\n <Translation\n defaultMessage=\"You'll be redirected to sign in with {integrationName}.\"\n id=\"g+n4aY\"\n description=\"Instruction about redirect to sign in\"\n values={{ integrationName: integration.name }}\n />\n </Text>\n <Text size=\"1\">\n <Translation\n defaultMessage=\"Authorize access to connect your account.\"\n id=\"fxVS34\"\n description=\"Instruction to authorize access\"\n />\n </Text>\n </Flex>\n </Flex>\n <Flex gap=\"2\" align=\"center\">\n <IconPanel color=\"gray\" style={{ width: \"32px\", height: \"32px\" }}>\n <LockClosedIcon />\n </IconPanel>\n <Flex direction=\"column\">\n <Text size=\"1\" weight=\"bold\">\n <Translation\n defaultMessage=\"Your credentials remain secure.\"\n id=\"gM3bot\"\n description=\"Security message about credentials\"\n />\n </Text>\n <Text size=\"1\">\n <Translation\n defaultMessage=\"WorkOS never sees your credentials.\"\n id=\"kC9Fwe\"\n description=\"Security message about WorkOS not seeing credentials\"\n />\n </Text>\n </Flex>\n </Flex>\n </Flex>\n </Card>\n );\n}\n\n/**\n * The single connect dialog for all non-API (OAuth) providers. When the\n * provider declares unpinned `installation`-scope config fields (e.g. a Zendesk\n * subdomain), it opens on a field-collection step (values validated against the\n * descriptor `required` / `pattern`) before the redirect explainer; otherwise\n * it opens directly on the explainer. Collected values are submitted as\n * `config` on the POST authorize call. Controlled so it backs the initial\n * connect flow, the dual-method OAuth option, and reauthorization.\n */\nfunction ConnectDialog({\n integration,\n fields,\n open,\n onOpenChange,\n}: {\n integration: DataIntegration;\n fields: DataIntegrationConfigField[];\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n // Providers without fields to collect skip straight to the explainer.\n const initialStep = fields.length > 0 ? \"fields\" : \"review\";\n const [step, setStep] = useState<\"fields\" | \"review\">(initialStep);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [isSubmitting, setIsSubmitting] = useState(false);\n const configForm = useConfigFieldsForm(fields);\n const eventHandler = useOpenDataIntegrationAuthorizeUrl(integration);\n const translate = useTranslation();\n\n const genericConnectError = translate({\n defaultMessage: \"We couldn't start the connection. Please try again.\",\n id: \"zGw1ma\",\n description:\n \"Fallback error shown when starting the connection fails for a non-specific reason\",\n });\n\n const reset = () => {\n setStep(initialStep);\n configForm.reset();\n setSubmitError(null);\n setIsSubmitting(false);\n };\n\n const handleConnect = async () => {\n setSubmitError(null);\n setIsSubmitting(true);\n try {\n // Opens the popup synchronously within this click before awaiting.\n await eventHandler(configForm.buildConfig());\n onOpenChange(false);\n } catch (error) {\n // Surface a message for every failure mode (ApiError, network, blocked\n // popup, etc.) so the dialog never fails silently.\n setSubmitError(\n error instanceof ApiError && error.message\n ? error.message\n : genericConnectError,\n );\n } finally {\n setIsSubmitting(false);\n }\n };\n\n return (\n <Dialog.Root\n open={open}\n onOpenChange={(next) => {\n onOpenChange(next);\n if (!next) {\n reset();\n }\n }}\n >\n <Dialog.Content maxWidth=\"430px\">\n <ConnectDialogHeader integration={integration} />\n\n {step === \"fields\" ? (\n <>\n <Card>\n <Flex direction=\"column\" gap=\"4\">\n <ConfigFieldInputs\n idPrefix=\"pipes-config\"\n fields={fields}\n values={configForm.values}\n errors={configForm.errors}\n onChange={configForm.setValue}\n />\n </Flex>\n </Card>\n <Flex justify=\"end\" gap=\"3\" mt=\"5\">\n <Dialog.Close>\n <Button variant=\"secondary\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Dialog.Close>\n <Button\n type=\"button\"\n disabled={configForm.hasMissingRequired}\n onClick={() => {\n if (configForm.validate()) {\n setStep(\"review\");\n }\n }}\n >\n <Translation\n defaultMessage=\"Next\"\n id=\"L2fmxK\"\n description=\"Button to advance to the next step of the connect flow\"\n />\n </Button>\n </Flex>\n </>\n ) : (\n <>\n {submitError && (\n <Callout.Root mb=\"3\" color=\"red\" role=\"alert\">\n <Callout.Text>{submitError}</Callout.Text>\n </Callout.Root>\n )}\n <ConnectExplainerCard integration={integration} />\n <Flex justify=\"end\" gap=\"3\" mt=\"5\">\n {fields.length > 0 ? (\n <Button\n variant=\"secondary\"\n type=\"button\"\n onClick={() => setStep(\"fields\")}\n >\n <Translation\n defaultMessage=\"Back\"\n id=\"J9MvVP\"\n description=\"Button to return to the previous step of the connect flow\"\n />\n </Button>\n ) : (\n <Dialog.Close>\n <Button variant=\"secondary\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Dialog.Close>\n )}\n <Button\n type=\"button\"\n loading={isSubmitting}\n disabled={isSubmitting}\n onClick={handleConnect}\n >\n <Translation\n defaultMessage=\"Connect\"\n id=\"16WmG0\"\n description=\"Connect button with external link\"\n trailingSpace\n />\n <ExternalLinkIcon aria-hidden />\n </Button>\n </Flex>\n </>\n )}\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\n/**\n * Connect button for a not-yet-connected OAuth provider. Opens the unified\n * {@link ConnectDialog}, which prompts for any unpinned `installation`-scope\n * config fields before the redirect explainer.\n */\nfunction ConnectIntegrationButton({\n integration,\n}: {\n integration: DataIntegration;\n}) {\n const [open, setOpen] = useState(false);\n const fields = getUnpinnedInstallationFields(integration);\n\n return (\n <>\n <ConnectDialog\n integration={integration}\n fields={fields}\n open={open}\n onOpenChange={setOpen}\n />\n <Button variant=\"secondary\" onClick={() => setOpen(true)}>\n <Translation\n defaultMessage=\"Connect\"\n id=\"quvdFp\"\n description=\"Button to connect an integration\"\n />\n </Button>\n </>\n );\n}\n\nconst API_KEY_REDACTED_PREFIX = \"••••\";\n\nfunction ApiKeyDialog({\n integration,\n open,\n onOpenChange,\n}: {\n integration: DataIntegration;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const queryClient = useQueryClient();\n const installation = integration.installation;\n const isRotation =\n installation?.auth_method === \"api_key\" &&\n installation.state === \"connected\";\n const last4 = installation?.api_key_last_4;\n const maskedKey = last4 ? `${API_KEY_REDACTED_PREFIX}${last4}` : \"\";\n\n const [secret, setSecret] = useState(\"\");\n const translate = useTranslation();\n\n const apiKeyPlaceholder = translate({\n defaultMessage: \"Enter your API key\",\n id: \"MzSxEF\",\n description: \"Placeholder for the API key input field\",\n });\n\n const {\n mutate: upsertApiKey,\n error,\n reset,\n isPending,\n } = useUpsertDataIntegrationApiKey({\n mutation: {\n onSuccess: () => {\n onOpenChange(false);\n queryClient.invalidateQueries({\n queryKey: getMyDataIntegrationsQueryKey(),\n });\n },\n },\n });\n\n // The component is only mounted while open (conditional rendering in\n // ApiKeyConnectButton / ProviderStatus), so state resets on mount.\n // We only need to reset the mutation state when the dialog opens in\n // case the same instance was reused.\n useEffect(() => {\n reset();\n }, [reset]);\n\n const errorMessage = (() => {\n if (!error) return null;\n if (error instanceof ApiError && error.message) {\n return error.message;\n }\n return null;\n })();\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Content maxWidth=\"430px\">\n <Dialog.Title size=\"3\" weight=\"bold\">\n {isRotation ? (\n <Translation\n defaultMessage=\"Rotate API key for {integrationName}\"\n id=\"8+NN3t\"\n description=\"Dialog title for rotating an API key\"\n values={{ integrationName: integration.name }}\n />\n ) : (\n <Translation\n defaultMessage=\"Connect {integrationName} with API key\"\n id=\"EyItbA\"\n description=\"Dialog title for connecting with an API key\"\n values={{ integrationName: integration.name }}\n />\n )}\n </Dialog.Title>\n\n {error && (\n <Callout.Root my=\"3\" color=\"red\" role=\"alert\">\n <Callout.Text>\n {errorMessage ?? (\n <Translation\n defaultMessage=\"An error occurred. Please check the value and try again.\"\n id=\"bYLbLL\"\n description=\"Generic error message for API key submission failure\"\n />\n )}\n </Callout.Text>\n </Callout.Root>\n )}\n\n <Flex direction=\"column\" gap=\"4\" mt=\"2\">\n {isRotation && last4 && (\n <Flex direction=\"column\" gap=\"1\">\n <Label>\n <Translation\n defaultMessage=\"Current API key\"\n id=\"+odk8g\"\n description=\"Label for the current masked API key\"\n />\n </Label>\n <Text size=\"2\" color=\"gray\">\n {maskedKey}\n </Text>\n </Flex>\n )}\n\n <Flex direction=\"column\" gap=\"1\">\n <Label>\n {isRotation ? (\n <Translation\n defaultMessage=\"New API key\"\n id=\"L3AmMK\"\n description=\"Label for the new API key input when rotating\"\n />\n ) : (\n <Translation\n defaultMessage=\"API key\"\n id=\"Xnkv+J\"\n description=\"Label for the API key input\"\n />\n )}\n </Label>\n <PasswordField\n value={secret}\n autoComplete=\"off\"\n placeholder={apiKeyPlaceholder}\n onChange={(event) => setSecret(event.target.value)}\n />\n </Flex>\n </Flex>\n\n <Flex justify=\"end\" gap=\"3\" mt=\"5\">\n <Dialog.Close>\n <Button variant=\"secondary\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Dialog.Close>\n <Button\n type=\"button\"\n disabled={isPending || !secret.trim()}\n loading={isPending}\n onClick={() =>\n upsertApiKey({\n slug: integration.slug,\n data: { secret: secret.trim() },\n })\n }\n >\n {isRotation ? (\n <Translation\n defaultMessage=\"Rotate\"\n id=\"LAh+p5\"\n description=\"Button to rotate an API key\"\n />\n ) : (\n <Translation\n defaultMessage=\"Connect\"\n id=\"quvdFp\"\n description=\"Button to connect an integration\"\n />\n )}\n </Button>\n </Flex>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction ApiKeyConnectButton({\n integration,\n}: {\n integration: DataIntegration;\n}) {\n const [open, setOpen] = useState(false);\n\n return (\n <>\n {open && (\n <ApiKeyDialog\n integration={integration}\n open={open}\n onOpenChange={setOpen}\n />\n )}\n <Button variant=\"secondary\" onClick={() => setOpen(true)}>\n <Translation\n defaultMessage=\"Connect\"\n id=\"quvdFp\"\n description=\"Button to connect an integration\"\n />\n </Button>\n </>\n );\n}\n\n/**\n * Connect form for the `client_credentials` auth method: the provider's client\n * id and secret plus any unpinned `installation`-scope config fields, rendered\n * generically from the descriptors via {@link ConfigFieldInputs}. Submits to\n * PUT `/DataIntegrations/:slug/client-credentials`, which also handles\n * replacing the credentials of an existing client-credentials installation.\n *\n * For an existing installation the form is prefilled from it: the client id as\n * received, the stored secret as a redacted mask that clears on focus (the\n * real value is never sent to the widget, so a new secret must be re-entered\n * to save), and the config fields from `installation.config`. `config` is only\n * included in the payload when the user edits a config field, since the API\n * keeps the stored config when the key is absent; when it is included it is\n * the full round-tripped object, because the write replaces config wholesale.\n */\nfunction ClientCredentialsDialog({\n integration,\n fields,\n open,\n onOpenChange,\n}: {\n integration: DataIntegration;\n fields: DataIntegrationConfigField[];\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const queryClient = useQueryClient();\n const installation = integration.installation;\n const isUpdate = installation?.auth_method === \"client_credentials\";\n const storedConfig = useMemo(\n () => (isUpdate ? (installation?.config ?? {}) : {}),\n [isUpdate, installation?.config],\n );\n const initialConfigValues = useMemo(\n () => getInitialConfigValues(fields, storedConfig),\n [fields, storedConfig],\n );\n const redactedSecret = buildRedactedSecret(\n isUpdate ? installation?.client_secret_last_4 : null,\n );\n\n const [clientId, setClientId] = useState(\n (isUpdate ? installation?.client_id : null) ?? \"\",\n );\n const [clientSecret, setClientSecret] = useState(redactedSecret);\n const configForm = useConfigFieldsForm(fields, initialConfigValues);\n const translate = useTranslation();\n\n const clientIdPlaceholder = translate({\n defaultMessage: \"Enter your client ID\",\n id: \"5YTAFo\",\n description: \"Placeholder for the client credentials client ID input\",\n });\n const clientSecretPlaceholder = translate({\n defaultMessage: \"Enter your client secret\",\n id: \"53f0B7\",\n description: \"Placeholder for the client credentials client secret input\",\n });\n\n // The widget never holds the real secret, so the prefilled mask can't be\n // submitted: the PUT requires a client secret and re-entry is the only way\n // to supply one.\n const secretMissing = !clientSecret.trim() || isRedactedSecret(clientSecret);\n\n const {\n mutate: upsertClientCredentials,\n error,\n isPending,\n } = useUpsertDataIntegrationClientCredentials({\n mutation: {\n onSuccess: () => {\n onOpenChange(false);\n queryClient.invalidateQueries({\n queryKey: getMyDataIntegrationsQueryKey(),\n });\n },\n },\n });\n\n // Server errors — including the 409 raised when an installation already\n // exists with a different auth method — are surfaced in the banner.\n const errorMessage =\n error instanceof ApiError && error.message ? error.message : null;\n\n const handleSubmit = () => {\n if (!configForm.validate()) {\n return;\n }\n // Untouched config fields mean no `config` key at all: the API preserves\n // the stored config when it's absent, and sending the prefilled object\n // back would make every credential update a config write too.\n const config = configForm.isDirty\n ? configForm.buildConfigPayload(storedConfig)\n : undefined;\n upsertClientCredentials({\n slug: integration.slug,\n data: {\n client_id: clientId.trim(),\n client_secret: clientSecret.trim(),\n ...(config ? { config } : {}),\n },\n });\n };\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Content maxWidth=\"430px\">\n <Dialog.Title size=\"3\" weight=\"bold\">\n {isUpdate ? (\n <Translation\n defaultMessage=\"Update client credentials for {integrationName}\"\n id=\"/D85zF\"\n description=\"Dialog title for updating stored client credentials\"\n values={{ integrationName: integration.name }}\n />\n ) : (\n <Translation\n defaultMessage=\"Connect {integrationName} with client credentials\"\n id=\"x+7tw3\"\n description=\"Dialog title for connecting with client credentials\"\n values={{ integrationName: integration.name }}\n />\n )}\n </Dialog.Title>\n\n {error && (\n <Callout.Root my=\"3\" color=\"red\" role=\"alert\">\n <Callout.Text>\n {errorMessage ?? (\n <Translation\n defaultMessage=\"An error occurred. Please check the value and try again.\"\n id=\"bYLbLL\"\n description=\"Generic error message for API key submission failure\"\n />\n )}\n </Callout.Text>\n </Callout.Root>\n )}\n\n <Flex direction=\"column\" gap=\"4\" mt=\"2\">\n <Flex direction=\"column\" gap=\"1\">\n <Label htmlFor=\"pipes-client-credentials-client-id\">\n <Translation\n defaultMessage=\"Client ID\"\n id=\"/Cv5P1\"\n description=\"Label for the client credentials client ID input\"\n />\n </Label>\n <TextField\n id=\"pipes-client-credentials-client-id\"\n value={clientId}\n autoComplete=\"off\"\n placeholder={clientIdPlaceholder}\n onChange={(event) => setClientId(event.target.value)}\n />\n </Flex>\n\n <Flex direction=\"column\" gap=\"1\">\n <Label htmlFor=\"pipes-client-credentials-client-secret\">\n <Translation\n defaultMessage=\"Client secret\"\n id=\"uScBDj\"\n description=\"Label for the client credentials client secret input\"\n />\n </Label>\n {isUpdate && (\n <Text\n color=\"gray\"\n size=\"2\"\n id=\"pipes-client-credentials-client-secret-description\"\n mb=\"1\"\n >\n <Translation\n defaultMessage=\"Enter the client secret again to save any changes.\"\n id=\"ZrNPCF\"\n description=\"Help text explaining the client secret must be re-entered to save an update\"\n />\n </Text>\n )}\n <PasswordField\n id=\"pipes-client-credentials-client-secret\"\n value={clientSecret}\n autoComplete=\"off\"\n // The mask is what's shown, so render it as text: a password\n // input would re-bullet its last four digits away.\n type={isRedactedSecret(clientSecret) ? \"text\" : undefined}\n placeholder={clientSecretPlaceholder}\n aria-describedby={\n isUpdate\n ? \"pipes-client-credentials-client-secret-description\"\n : undefined\n }\n onChange={(event) => setClientSecret(event.target.value)}\n onFocus={() => {\n if (isRedactedSecret(clientSecret)) {\n setClientSecret(\"\");\n }\n }}\n onBlur={() => {\n if (clientSecret === \"\") {\n setClientSecret(redactedSecret);\n }\n }}\n />\n </Flex>\n\n <ConfigFieldInputs\n idPrefix=\"pipes-client-credentials-config\"\n fields={fields}\n values={configForm.values}\n errors={configForm.errors}\n onChange={configForm.setValue}\n />\n </Flex>\n\n <Flex justify=\"end\" gap=\"3\" mt=\"5\">\n <Dialog.Close>\n <Button variant=\"secondary\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </Dialog.Close>\n <Button\n type=\"button\"\n disabled={\n isPending ||\n !clientId.trim() ||\n secretMissing ||\n configForm.hasMissingRequired\n }\n loading={isPending}\n onClick={handleSubmit}\n >\n {isUpdate ? (\n <Translation\n defaultMessage=\"Save\"\n id=\"RT8KNi\"\n description=\"Save button text\"\n />\n ) : (\n <Translation\n defaultMessage=\"Connect\"\n id=\"quvdFp\"\n description=\"Button to connect an integration\"\n />\n )}\n </Button>\n </Flex>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\nfunction ClientCredentialsConnectButton({\n integration,\n}: {\n integration: DataIntegration;\n}) {\n const [open, setOpen] = useState(false);\n const fields = getUnpinnedInstallationFields(integration);\n\n return (\n <>\n {open && (\n <ClientCredentialsDialog\n integration={integration}\n fields={fields}\n open={open}\n onOpenChange={setOpen}\n />\n )}\n <Button variant=\"secondary\" onClick={() => setOpen(true)}>\n <Translation\n defaultMessage=\"Connect\"\n id=\"quvdFp\"\n description=\"Button to connect an integration\"\n />\n </Button>\n </>\n );\n}\n\n/**\n * Connect entry point for a provider that supports more than one auth method:\n * a menu with one item per method, each opening that method's dialog.\n */\nfunction MultiMethodConnectButton({\n integration,\n methods,\n}: {\n integration: DataIntegration;\n methods: DataIntegrationAuthMethod[];\n}) {\n const [apiKeyOpen, setApiKeyOpen] = useState(false);\n const [oauthOpen, setOauthOpen] = useState(false);\n const [clientCredentialsOpen, setClientCredentialsOpen] = useState(false);\n const fields = getUnpinnedInstallationFields(integration);\n\n return (\n <>\n {apiKeyOpen && (\n <ApiKeyDialog\n integration={integration}\n open={apiKeyOpen}\n onOpenChange={setApiKeyOpen}\n />\n )}\n {clientCredentialsOpen && (\n <ClientCredentialsDialog\n integration={integration}\n fields={fields}\n open={clientCredentialsOpen}\n onOpenChange={setClientCredentialsOpen}\n />\n )}\n {methods.includes(\"oauth\") && (\n <ConnectDialog\n integration={integration}\n fields={fields}\n open={oauthOpen}\n onOpenChange={setOauthOpen}\n />\n )}\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <Button variant=\"secondary\">\n <Translation\n defaultMessage=\"Connect\"\n id=\"quvdFp\"\n description=\"Button to connect an integration\"\n />\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n {methods.includes(\"oauth\") && (\n <DropdownMenu.Item onClick={() => setOauthOpen(true)}>\n <Flex gap=\"4\" width=\"100%\" justify=\"between\" align=\"center\">\n <Translation\n defaultMessage=\"Sign in with OAuth\"\n id=\"ssNz+0\"\n description=\"Menu option to connect via OAuth\"\n trailingSpace\n />\n <ExternalLinkIcon aria-hidden />\n </Flex>\n </DropdownMenu.Item>\n )}\n {methods.includes(\"client_credentials\") && (\n <DropdownMenu.Item onClick={() => setClientCredentialsOpen(true)}>\n <Translation\n defaultMessage=\"Enter client credentials\"\n id=\"Y/87Vt\"\n description=\"Menu option to connect via client credentials\"\n />\n </DropdownMenu.Item>\n )}\n {methods.includes(\"api_key\") && (\n <DropdownMenu.Item onClick={() => setApiKeyOpen(true)}>\n <Translation\n defaultMessage=\"Enter API key\"\n id=\"8mq2DA\"\n description=\"Menu option to connect via API key\"\n />\n </DropdownMenu.Item>\n )}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n </>\n );\n}\n\nfunction ProviderStatus({ integration }: { integration: DataIntegration }) {\n const [disconnectOpen, setDisconnectOpen] = useState(false);\n const [apiKeyOpen, setApiKeyOpen] = useState(false);\n const [clientCredentialsOpen, setClientCredentialsOpen] = useState(false);\n const [reauthConfigOpen, setReauthConfigOpen] = useState(false);\n const authorizeEventHandler = useOpenDataIntegrationAuthorizeUrl(integration);\n const translate = useTranslation();\n\n const pipeActionsTitle = translate({\n defaultMessage: \"Pipe actions\",\n id: \"1uF9ve\",\n description: \"Title for pipe actions dropdown button\",\n });\n\n // Unpinned installation fields must be re-collected on reauthorization too;\n // the authorize endpoint rejects them as missing otherwise.\n const unpinnedFields = getUnpinnedInstallationFields(integration);\n\n if (integration.installation) {\n const connected = integration.installation.state === \"connected\";\n const isApiKeyInstallation =\n integration.installation.auth_method === \"api_key\";\n const isClientCredentialsInstallation =\n integration.installation.auth_method === \"client_credentials\";\n\n return (\n <>\n <DisconnectAccountDialog\n integrationName={integration.name}\n installationId={integration.installation.id}\n open={disconnectOpen}\n onOpenChange={setDisconnectOpen}\n />\n {apiKeyOpen && (\n <ApiKeyDialog\n integration={integration}\n open={apiKeyOpen}\n onOpenChange={setApiKeyOpen}\n />\n )}\n {clientCredentialsOpen && (\n <ClientCredentialsDialog\n integration={integration}\n fields={unpinnedFields}\n open={clientCredentialsOpen}\n onOpenChange={setClientCredentialsOpen}\n />\n )}\n {unpinnedFields.length > 0 && !isClientCredentialsInstallation && (\n <ConnectDialog\n integration={integration}\n fields={unpinnedFields}\n open={reauthConfigOpen}\n onOpenChange={setReauthConfigOpen}\n />\n )}\n <Flex align=\"center\" gap=\"4\">\n <Status state={connected ? \"success\" : \"error\"}>\n {connected ? (\n <Translation\n defaultMessage=\"Connected\"\n id=\"i6Hxoz\"\n description=\"Status text for connected integration\"\n />\n ) : (\n <Translation\n defaultMessage=\"Requires reauthorization\"\n id=\"dqczQS\"\n description=\"Status text for integration needing reauthorization\"\n />\n )}\n </Status>\n {isClientCredentialsInstallation ? (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton title={pipeActionsTitle}>\n <DotsHorizontalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n <DropdownMenu.Item\n onClick={() => setClientCredentialsOpen(true)}\n >\n <Translation\n defaultMessage=\"Update client credentials\"\n id=\"daHKWE\"\n description=\"Menu option to update stored client credentials\"\n />\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onClick={() => setDisconnectOpen(true)}\n >\n <Translation\n defaultMessage=\"Disconnect account\"\n id=\"esZQrd\"\n description=\"Menu option to disconnect an account\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n ) : connected && isApiKeyInstallation ? (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton title={pipeActionsTitle}>\n <DotsHorizontalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n <DropdownMenu.Item onClick={() => setApiKeyOpen(true)}>\n <Translation\n defaultMessage=\"Rotate API key\"\n id=\"GML+c8\"\n description=\"Menu option to rotate the API key\"\n />\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onClick={() => setDisconnectOpen(true)}\n >\n <Translation\n defaultMessage=\"Disconnect account\"\n id=\"esZQrd\"\n description=\"Menu option to disconnect an account\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n ) : connected ? (\n <Button variant=\"secondary\" onClick={() => setDisconnectOpen(true)}>\n <Translation\n defaultMessage=\"Disconnect\"\n id=\"vMVXQh\"\n description=\"Button to disconnect an account\"\n />\n </Button>\n ) : isApiKeyInstallation ? (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton title={pipeActionsTitle}>\n <DotsHorizontalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n <DropdownMenu.Item onClick={() => setApiKeyOpen(true)}>\n <Translation\n defaultMessage=\"Update API key\"\n id=\"E7pMj/\"\n description=\"Menu option to update the API key for a needs-reauthorization installation\"\n />\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onClick={() => setDisconnectOpen(true)}\n >\n <Translation\n defaultMessage=\"Disconnect account\"\n id=\"esZQrd\"\n description=\"Menu option to disconnect an account\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n ) : (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger>\n <IconButton title={pipeActionsTitle}>\n <DotsHorizontalIcon />\n </IconButton>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"end\">\n <DropdownMenu.Item\n onClick={async () => {\n if (unpinnedFields.length > 0) {\n setReauthConfigOpen(true);\n return;\n }\n try {\n await authorizeEventHandler();\n } catch {\n // pass - error displayed in new tab\n }\n }}\n >\n <Flex gap=\"4\" width=\"100%\" justify=\"between\" align=\"center\">\n <Translation\n defaultMessage=\"Reauthorize\"\n id=\"0E29F1\"\n description=\"Menu option to reauthorize an integration\"\n trailingSpace\n />\n <ExternalLinkIcon aria-hidden />\n </Flex>\n </DropdownMenu.Item>\n <DropdownMenu.Item\n variant=\"destructive\"\n onClick={() => setDisconnectOpen(true)}\n >\n <Translation\n defaultMessage=\"Disconnect account\"\n id=\"esZQrd\"\n description=\"Menu option to disconnect an account\"\n />\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n )}\n </Flex>\n </>\n );\n }\n\n // Not connected: choose the connect entry point from the supported methods.\n // More than one: a menu of methods; otherwise that method's own button, with\n // OAuth as the default for a provider that declares nothing.\n const authMethods = integration.authMethods ?? [];\n const methods = CONNECT_AUTH_METHODS.filter((method) =>\n authMethods.includes(method),\n );\n\n return (\n <Flex align=\"center\" gap=\"4\">\n <Status state=\"neutral\">\n <Translation\n defaultMessage=\"Not connected\"\n id=\"J7bTZa\"\n description=\"Status text for an integration that is not connected\"\n />\n </Status>\n {methods.length > 1 ? (\n <MultiMethodConnectButton integration={integration} methods={methods} />\n ) : methods.length === 1 && methods[0] === \"api_key\" ? (\n <ApiKeyConnectButton integration={integration} />\n ) : methods.length === 1 && methods[0] === \"client_credentials\" ? (\n <ClientCredentialsConnectButton integration={integration} />\n ) : (\n <ConnectIntegrationButton integration={integration} />\n )}\n </Flex>\n );\n}\n\nfunction DisconnectAccountDialog({\n integrationName,\n installationId,\n open,\n onOpenChange,\n}: {\n integrationName: string;\n installationId: string;\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}) {\n const queryClient = useQueryClient();\n const {\n mutate: deleteDataInstallation,\n error,\n reset,\n isPending,\n } = useDeleteDataInstallation({\n mutation: {\n onSuccess: () => {\n onOpenChange(false);\n queryClient.invalidateQueries({\n queryKey: getMyDataIntegrationsQueryKey(),\n });\n },\n },\n });\n\n useEffect(() => {\n if (open) {\n reset();\n }\n }, [open, reset]);\n\n return (\n <AlertDialog.Root open={open} onOpenChange={onOpenChange}>\n <AlertDialog.Content style={{ width: \"80vw\", maxWidth: \"520px\" }}>\n <AlertDialog.Title>\n <Translation\n defaultMessage=\"Disconnect account\"\n id=\"9ABlCr\"\n description=\"Dialog title for disconnecting an account\"\n />\n </AlertDialog.Title>\n {error && (\n <Callout.Root my=\"5\" color=\"red\" role=\"alert\">\n <Callout.Text>\n <Translation\n defaultMessage=\"An error occurred while disconnecting your account. Please refresh the page and try again.\"\n id=\"qKBKF7\"\n description=\"Error message when disconnecting an account fails\"\n />\n </Callout.Text>\n </Callout.Root>\n )}\n <AlertDialog.Description>\n <Translation\n defaultMessage=\"Are you sure you want to disconnect your {integrationName} account?\"\n id=\"eEXeqP\"\n description=\"Confirmation message for disconnecting an account\"\n values={{\n integrationName: (\n <Text as=\"span\" weight=\"bold\">\n {integrationName}\n </Text>\n ),\n }}\n />\n </AlertDialog.Description>\n <Flex gap=\"3\" justify=\"end\" mt=\"5\">\n <AlertDialog.Cancel>\n <Button variant=\"secondary\">\n <Translation\n defaultMessage=\"Cancel\"\n id=\"hHNj31\"\n description=\"Cancel button text\"\n />\n </Button>\n </AlertDialog.Cancel>\n <Button\n variant=\"destructive\"\n disabled={isPending}\n loading={isPending}\n onClick={() => deleteDataInstallation({ installationId })}\n >\n <Translation\n defaultMessage=\"Disconnect\"\n id=\"vMVXQh\"\n description=\"Button to disconnect an account\"\n />\n </Button>\n </Flex>\n </AlertDialog.Content>\n </AlertDialog.Root>\n );\n}\n\ninterface PipesLoadingProps extends WidgetRootDomProps {\n count: number;\n}\n\nconst PipesLoading: React.FC<PipesLoadingProps> = ({ count, ...domProps }) => {\n return (\n <CardList.Root {...getWidgetRootDomProps(\"loading\", domProps)}>\n {Array.from({ length: count }).map((_, index) => (\n <CardList.Item key={index}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <Skeleton>\n <IconPanel>\n <ProviderIcon provider=\"google\" />\n </IconPanel>\n </Skeleton>\n <Skeleton>\n <Text size=\"2\" weight=\"bold\">\n <Translation\n defaultMessage=\"Google Drive\"\n id=\"g11OOu\"\n description=\"Placeholder text for loading state\"\n />\n </Text>\n </Skeleton>\n </Flex>\n <Skeleton>\n <Button variant=\"secondary\" disabled>\n <Translation\n defaultMessage=\"Connect\"\n id=\"8TuDfA\"\n description=\"Placeholder button text for loading state\"\n />\n </Button>\n </Skeleton>\n </Flex>\n </CardList.Item>\n ))}\n </CardList.Root>\n );\n};\n\nconst Pipes: React.FC<PipesProps> = ({ integrations, ...domProps }) => {\n return (\n <CardList.Root {...getWidgetRootDomProps(\"resolved\", domProps)}>\n {integrations.map((integration) => (\n <CardList.Item key={integration.id}>\n <Flex direction=\"row\" justify=\"between\" align=\"center\" gap=\"2\">\n <Flex gap=\"4\" align=\"center\">\n <IconPanel color=\"panel\">\n <DataIntegrationIcon integration={integration} />\n </IconPanel>\n <Text size=\"2\" weight=\"bold\">\n {integration.name}\n </Text>\n </Flex>\n <ProviderStatus integration={integration} />\n </Flex>\n </CardList.Item>\n ))}\n </CardList.Root>\n );\n};\n\ninterface PipesErrorProps extends WidgetRootDomProps {\n error: unknown;\n}\n\nconst PipesError: React.FC<PipesErrorProps> = ({ error, ...domProps }) => {\n return (\n <Card size=\"2\" {...getWidgetRootDomProps(\"error\", domProps)}>\n <GenericError error={error} />\n </Card>\n );\n};\n\nfunction getWidgetRootDomProps(\n state: WidgetRootState,\n domProps: WidgetRootDomProps,\n) {\n return getDomProps({\n ...domProps,\n isWidgetRoot: true,\n widgetId: \"pipes\",\n widgetState: state,\n });\n}\n\nexport type { PipesProps, PipesLoadingProps, PipesErrorProps };\nexport { Pipes, PipesLoading, PipesError };\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var redacted_secret_exports = {};
|
|
20
|
+
__export(redacted_secret_exports, {
|
|
21
|
+
buildRedactedSecret: () => buildRedactedSecret,
|
|
22
|
+
isRedactedSecret: () => isRedactedSecret
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(redacted_secret_exports);
|
|
25
|
+
const REDACTED_SECRET_PREFIX = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
|
26
|
+
const buildRedactedSecret = (last4) => last4 ? `${REDACTED_SECRET_PREFIX}${last4}` : "";
|
|
27
|
+
const isRedactedSecret = (value) => value.startsWith(REDACTED_SECRET_PREFIX);
|
|
28
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
29
|
+
0 && (module.exports = {
|
|
30
|
+
buildRedactedSecret,
|
|
31
|
+
isRedactedSecret
|
|
32
|
+
});
|
|
33
|
+
//# sourceMappingURL=redacted-secret.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/redacted-secret.ts"],"sourcesContent":["const REDACTED_SECRET_PREFIX = \"••••••••••••••••\";\n\n/** Masked display value for an existing secret: 16 bullets + the last 4 chars. */\nexport const buildRedactedSecret = (\n last4: string | null | undefined,\n): string => (last4 ? `${REDACTED_SECRET_PREFIX}${last4}` : \"\");\n\n/** True while the field still holds the unmodified redacted placeholder. */\nexport const isRedactedSecret = (value: string): boolean =>\n value.startsWith(REDACTED_SECRET_PREFIX);\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAAM,yBAAyB;AAGxB,MAAM,sBAAsB,CACjC,UACY,QAAQ,GAAG,sBAAsB,GAAG,KAAK,KAAK;AAGrD,MAAM,mBAAmB,CAAC,UAC/B,MAAM,WAAW,sBAAsB;","names":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Masked display value for an existing secret: 16 bullets + the last 4 chars. */
|
|
2
|
+
declare const buildRedactedSecret: (last4: string | null | undefined) => string;
|
|
3
|
+
/** True while the field still holds the unmodified redacted placeholder. */
|
|
4
|
+
declare const isRedactedSecret: (value: string) => boolean;
|
|
5
|
+
|
|
6
|
+
export { buildRedactedSecret, isRedactedSecret };
|
package/dist/esm/lib/elements.js
CHANGED
|
@@ -135,7 +135,7 @@ const TextFieldSlot = React.forwardRef(function TextFieldSlot2({ className, ...p
|
|
|
135
135
|
}
|
|
136
136
|
);
|
|
137
137
|
});
|
|
138
|
-
const PasswordField = React.forwardRef(function PasswordField2({ className, ...props }, ref) {
|
|
138
|
+
const PasswordField = React.forwardRef(function PasswordField2({ className, type, ...props }, ref) {
|
|
139
139
|
const element = useElement("textfield");
|
|
140
140
|
const [showPassword, setShowPassword] = React.useState(false);
|
|
141
141
|
const translate = useTranslation();
|
|
@@ -157,7 +157,7 @@ const PasswordField = React.forwardRef(function PasswordField2({ className, ...p
|
|
|
157
157
|
className: cx(namespaceClassNames("text-field"), className),
|
|
158
158
|
...props,
|
|
159
159
|
...element,
|
|
160
|
-
type: showPassword ? "text" : "password",
|
|
160
|
+
type: type ?? (showPassword ? "text" : "password"),
|
|
161
161
|
children: /* @__PURE__ */ jsx(RadixTextField.Slot, { side: "right", children: /* @__PURE__ */ jsx(
|
|
162
162
|
IconButton,
|
|
163
163
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/lib/elements.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n Avatar as RadixAvatar,\n AvatarProps as RadixAvatarProps,\n Badge as RadixBadge,\n IconButton as RadixIconButton,\n Skeleton as RadixSkeleton,\n Text,\n TextField as RadixTextField,\n type BadgeProps,\n type ButtonProps as RadixButtonProps,\n type IconButtonProps as RadixIconButtonProps,\n type SkeletonProps,\n type TextProps,\n Button as RadixButton,\n} from \"@radix-ui/themes\";\nimport type {\n GetPropDefTypes,\n avatarPropDefs,\n badgePropDefs,\n buttonPropDefs,\n dialogContentPropDefs,\n dropdownMenuContentPropDefs,\n dropdownMenuItemPropDefs,\n iconButtonPropDefs,\n textPropDefs,\n textFieldRootPropDefs,\n selectTriggerPropDefs,\n skeletonPropDefs,\n} from \"@radix-ui/themes/props\";\nimport cx from \"clsx\";\nimport { useElement } from \"./widgets-context.js\";\nimport { getDomProps, namespaceClassNames } from \"./utils.js\";\nimport { EyeClosedIcon, EyeOpenIcon } from \"@radix-ui/react-icons\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\nexport interface ButtonProps extends Omit<\n RadixButtonProps,\n \"variant\" | \"color\"\n> {\n variant?: \"primary\" | \"secondary\" | \"destructive\";\n unsafe_radixVariant?: RadixButtonProps[\"variant\"];\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n { className, variant = \"primary\", unsafe_radixVariant, ...props },\n ref,\n ) {\n const element = useElement(`${variant}Button`);\n\n const themeProps = (() => {\n let props: RadixButtonProps = {};\n if (variant === \"primary\") {\n props = {\n variant: \"solid\",\n } satisfies RadixButtonProps;\n } else if (variant === \"secondary\") {\n props = {\n highContrast: true,\n variant: \"surface\",\n color: \"gray\",\n } satisfies RadixButtonProps;\n } else if (variant === \"destructive\") {\n props = {\n variant: \"solid\",\n color: \"red\",\n } satisfies RadixButtonProps;\n } else {\n variant satisfies never;\n }\n\n if (unsafe_radixVariant) {\n props.variant = unsafe_radixVariant;\n }\n\n return props;\n })();\n\n return (\n <RadixButton\n ref={ref}\n {...getDomProps({\n elementId: `${variant}Button`,\n className: cx(\n className,\n // TODO: Remove BEM-style selector once conventions are standardized\n `button--${variant}`,\n ),\n })}\n {...themeProps}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport interface IconButtonProps extends RadixIconButtonProps {\n title: string;\n}\n\nexport const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(\n function IconButton({ className, ...props }, ref) {\n const element = useElement(\"iconButton\");\n return (\n <RadixIconButton\n ref={ref}\n {...getDomProps({ elementId: \"iconButton\", className })}\n variant=\"ghost\"\n color=\"gray\"\n aria-label={props.title}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport const Skeleton = React.forwardRef<HTMLSpanElement, SkeletonProps>(\n function Skeleton({ className, ...props }, ref) {\n const element = useElement(\"skeleton\");\n return (\n <RadixSkeleton\n ref={ref}\n {...getDomProps({ elementId: \"skeleton\", className })}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport const Label = React.forwardRef<HTMLLabelElement, TextProps>(\n function Label({ children, className, style = {}, ...props }, ref) {\n const element = useElement(\"label\");\n return (\n <Text\n as=\"label\"\n ref={ref}\n weight=\"bold\"\n size=\"2\"\n {...getDomProps({ elementId: \"label\", className })}\n style={{ width: \"fit-content\", ...style }}\n // Text props are a complex union type depending on the `as` prop value,\n // which breaks down when spreading in `element`.\n {...(props as any)}\n {...element}\n >\n {children}\n </Text>\n );\n },\n);\n\nexport const TextField = React.forwardRef<\n HTMLInputElement,\n RadixTextField.RootProps\n>(function TextField({ className, ...props }, ref) {\n const element = useElement(\"textfield\");\n return (\n <RadixTextField.Root\n ref={ref}\n variant=\"surface\"\n className={cx(namespaceClassNames(\"text-field\"), className)}\n {...props}\n {...element}\n />\n );\n});\n\nexport const TextFieldSlot = React.forwardRef<\n HTMLDivElement,\n RadixTextField.SlotProps\n>(function TextFieldSlot({ className, ...props }, ref) {\n return (\n <RadixTextField.Slot\n ref={ref}\n className={cx(namespaceClassNames(\"text-field-slot\"), className)}\n {...props}\n />\n );\n});\n\nexport const PasswordField = React.forwardRef<\n HTMLInputElement,\n RadixTextField.RootProps\n>(function PasswordField({ className, ...props }, ref) {\n const element = useElement(\"textfield\");\n const [showPassword, setShowPassword] = React.useState(false);\n const translate = useTranslation();\n const hidePasswordText = translate({\n defaultMessage: \"Hide password\",\n id: \"Jv4Vps\",\n description: \"Button text to hide password\",\n });\n const showPasswordText = translate({\n defaultMessage: \"Show password\",\n id: \"UIfBSd\",\n description: \"Button text to show password\",\n });\n return (\n <RadixTextField.Root\n ref={ref}\n variant=\"surface\"\n className={cx(namespaceClassNames(\"text-field\"), className)}\n {...props}\n {...element}\n type={showPassword ? \"text\" : \"password\"}\n >\n <RadixTextField.Slot side=\"right\">\n <IconButton\n type=\"button\"\n size=\"1\"\n onClick={() => setShowPassword(!showPassword)}\n title={showPassword ? hidePasswordText : showPasswordText}\n >\n {showPassword ? <EyeOpenIcon /> : <EyeClosedIcon />}\n </IconButton>\n </RadixTextField.Slot>\n </RadixTextField.Root>\n );\n});\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n function Badge({ className, ...props }, ref) {\n const element = useElement(\"badge\");\n return (\n <RadixBadge\n ref={ref}\n {...getDomProps({ elementId: \"badge\", className })}\n {...props}\n {...element}\n />\n );\n },\n);\n\ninterface AvatarProps extends RadixAvatarProps {\n dim?: boolean;\n}\n\nexport const Avatar = React.forwardRef<HTMLImageElement, AvatarProps>(\n function Avatar({ dim, className, ...props }, ref) {\n const element = useElement(\"avatar\");\n return (\n <RadixAvatar\n ref={ref}\n color=\"gray\"\n {...getDomProps({ elementId: \"avatar\", className })}\n {...props}\n {...element}\n // TODO: use CSS var instead of hard-coded value for opacity\n style={dim ? { opacity: 0.6, ...props.style } : props.style}\n />\n );\n },\n);\n\ntype OmitAsChild<T> = {\n [K in keyof T]: T[K] extends undefined\n ? undefined\n : Omit<NonNullable<T[K]>, \"asChild\">;\n};\n\nexport * as Dialog from \"./elements/dialog.js\";\nexport * as AlertDialog from \"./elements/alert-dialog.js\";\nexport * as DropdownMenu from \"./elements/dropdown-menu.js\";\nexport * as Select from \"./elements/select.js\";\n\nexport type Elements = OmitAsChild<{\n dialog?: GetPropDefTypes<typeof dialogContentPropDefs>;\n primaryButton?: GetPropDefTypes<typeof buttonPropDefs>;\n secondaryButton?: GetPropDefTypes<typeof buttonPropDefs>;\n destructiveButton?: GetPropDefTypes<typeof buttonPropDefs>;\n iconButton?: GetPropDefTypes<typeof iconButtonPropDefs>;\n textfield?: GetPropDefTypes<typeof textFieldRootPropDefs>;\n select?: GetPropDefTypes<typeof selectTriggerPropDefs>;\n badge?: GetPropDefTypes<typeof badgePropDefs>;\n dropdown?: GetPropDefTypes<typeof dropdownMenuContentPropDefs>;\n primaryMenuItem?: GetPropDefTypes<typeof dropdownMenuItemPropDefs>;\n destructiveMenuItem?: GetPropDefTypes<typeof dropdownMenuItemPropDefs>;\n avatar?: Omit<GetPropDefTypes<typeof avatarPropDefs>, \"fallback\">;\n label?: GetPropDefTypes<typeof textPropDefs>;\n skeleton?: GetPropDefTypes<typeof skeletonPropDefs>;\n}>;\n"],"mappings":"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","names":["Button","props","IconButton","Skeleton","Label","TextField","TextFieldSlot","PasswordField","Badge","Avatar"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/elements.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n Avatar as RadixAvatar,\n AvatarProps as RadixAvatarProps,\n Badge as RadixBadge,\n IconButton as RadixIconButton,\n Skeleton as RadixSkeleton,\n Text,\n TextField as RadixTextField,\n type BadgeProps,\n type ButtonProps as RadixButtonProps,\n type IconButtonProps as RadixIconButtonProps,\n type SkeletonProps,\n type TextProps,\n Button as RadixButton,\n} from \"@radix-ui/themes\";\nimport type {\n GetPropDefTypes,\n avatarPropDefs,\n badgePropDefs,\n buttonPropDefs,\n dialogContentPropDefs,\n dropdownMenuContentPropDefs,\n dropdownMenuItemPropDefs,\n iconButtonPropDefs,\n textPropDefs,\n textFieldRootPropDefs,\n selectTriggerPropDefs,\n skeletonPropDefs,\n} from \"@radix-ui/themes/props\";\nimport cx from \"clsx\";\nimport { useElement } from \"./widgets-context.js\";\nimport { getDomProps, namespaceClassNames } from \"./utils.js\";\nimport { EyeClosedIcon, EyeOpenIcon } from \"@radix-ui/react-icons\";\nimport { useTranslation } from \"./i18n/use-translation.js\";\n\nexport interface ButtonProps extends Omit<\n RadixButtonProps,\n \"variant\" | \"color\"\n> {\n variant?: \"primary\" | \"secondary\" | \"destructive\";\n unsafe_radixVariant?: RadixButtonProps[\"variant\"];\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n { className, variant = \"primary\", unsafe_radixVariant, ...props },\n ref,\n ) {\n const element = useElement(`${variant}Button`);\n\n const themeProps = (() => {\n let props: RadixButtonProps = {};\n if (variant === \"primary\") {\n props = {\n variant: \"solid\",\n } satisfies RadixButtonProps;\n } else if (variant === \"secondary\") {\n props = {\n highContrast: true,\n variant: \"surface\",\n color: \"gray\",\n } satisfies RadixButtonProps;\n } else if (variant === \"destructive\") {\n props = {\n variant: \"solid\",\n color: \"red\",\n } satisfies RadixButtonProps;\n } else {\n variant satisfies never;\n }\n\n if (unsafe_radixVariant) {\n props.variant = unsafe_radixVariant;\n }\n\n return props;\n })();\n\n return (\n <RadixButton\n ref={ref}\n {...getDomProps({\n elementId: `${variant}Button`,\n className: cx(\n className,\n // TODO: Remove BEM-style selector once conventions are standardized\n `button--${variant}`,\n ),\n })}\n {...themeProps}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport interface IconButtonProps extends RadixIconButtonProps {\n title: string;\n}\n\nexport const IconButton = React.forwardRef<HTMLButtonElement, IconButtonProps>(\n function IconButton({ className, ...props }, ref) {\n const element = useElement(\"iconButton\");\n return (\n <RadixIconButton\n ref={ref}\n {...getDomProps({ elementId: \"iconButton\", className })}\n variant=\"ghost\"\n color=\"gray\"\n aria-label={props.title}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport const Skeleton = React.forwardRef<HTMLSpanElement, SkeletonProps>(\n function Skeleton({ className, ...props }, ref) {\n const element = useElement(\"skeleton\");\n return (\n <RadixSkeleton\n ref={ref}\n {...getDomProps({ elementId: \"skeleton\", className })}\n {...props}\n {...element}\n />\n );\n },\n);\n\nexport const Label = React.forwardRef<HTMLLabelElement, TextProps>(\n function Label({ children, className, style = {}, ...props }, ref) {\n const element = useElement(\"label\");\n return (\n <Text\n as=\"label\"\n ref={ref}\n weight=\"bold\"\n size=\"2\"\n {...getDomProps({ elementId: \"label\", className })}\n style={{ width: \"fit-content\", ...style }}\n // Text props are a complex union type depending on the `as` prop value,\n // which breaks down when spreading in `element`.\n {...(props as any)}\n {...element}\n >\n {children}\n </Text>\n );\n },\n);\n\nexport const TextField = React.forwardRef<\n HTMLInputElement,\n RadixTextField.RootProps\n>(function TextField({ className, ...props }, ref) {\n const element = useElement(\"textfield\");\n return (\n <RadixTextField.Root\n ref={ref}\n variant=\"surface\"\n className={cx(namespaceClassNames(\"text-field\"), className)}\n {...props}\n {...element}\n />\n );\n});\n\nexport const TextFieldSlot = React.forwardRef<\n HTMLDivElement,\n RadixTextField.SlotProps\n>(function TextFieldSlot({ className, ...props }, ref) {\n return (\n <RadixTextField.Slot\n ref={ref}\n className={cx(namespaceClassNames(\"text-field-slot\"), className)}\n {...props}\n />\n );\n});\n\nexport const PasswordField = React.forwardRef<\n HTMLInputElement,\n RadixTextField.RootProps\n>(function PasswordField({ className, type, ...props }, ref) {\n const element = useElement(\"textfield\");\n const [showPassword, setShowPassword] = React.useState(false);\n const translate = useTranslation();\n const hidePasswordText = translate({\n defaultMessage: \"Hide password\",\n id: \"Jv4Vps\",\n description: \"Button text to hide password\",\n });\n const showPasswordText = translate({\n defaultMessage: \"Show password\",\n id: \"UIfBSd\",\n description: \"Button text to show password\",\n });\n return (\n <RadixTextField.Root\n ref={ref}\n variant=\"surface\"\n className={cx(namespaceClassNames(\"text-field\"), className)}\n {...props}\n {...element}\n // An explicit `type` wins, so a caller holding a value that's already\n // redacted (a bullet mask) can render it as plain text.\n type={type ?? (showPassword ? \"text\" : \"password\")}\n >\n <RadixTextField.Slot side=\"right\">\n <IconButton\n type=\"button\"\n size=\"1\"\n onClick={() => setShowPassword(!showPassword)}\n title={showPassword ? hidePasswordText : showPasswordText}\n >\n {showPassword ? <EyeOpenIcon /> : <EyeClosedIcon />}\n </IconButton>\n </RadixTextField.Slot>\n </RadixTextField.Root>\n );\n});\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n function Badge({ className, ...props }, ref) {\n const element = useElement(\"badge\");\n return (\n <RadixBadge\n ref={ref}\n {...getDomProps({ elementId: \"badge\", className })}\n {...props}\n {...element}\n />\n );\n },\n);\n\ninterface AvatarProps extends RadixAvatarProps {\n dim?: boolean;\n}\n\nexport const Avatar = React.forwardRef<HTMLImageElement, AvatarProps>(\n function Avatar({ dim, className, ...props }, ref) {\n const element = useElement(\"avatar\");\n return (\n <RadixAvatar\n ref={ref}\n color=\"gray\"\n {...getDomProps({ elementId: \"avatar\", className })}\n {...props}\n {...element}\n // TODO: use CSS var instead of hard-coded value for opacity\n style={dim ? { opacity: 0.6, ...props.style } : props.style}\n />\n );\n },\n);\n\ntype OmitAsChild<T> = {\n [K in keyof T]: T[K] extends undefined\n ? undefined\n : Omit<NonNullable<T[K]>, \"asChild\">;\n};\n\nexport * as Dialog from \"./elements/dialog.js\";\nexport * as AlertDialog from \"./elements/alert-dialog.js\";\nexport * as DropdownMenu from \"./elements/dropdown-menu.js\";\nexport * as Select from \"./elements/select.js\";\n\nexport type Elements = OmitAsChild<{\n dialog?: GetPropDefTypes<typeof dialogContentPropDefs>;\n primaryButton?: GetPropDefTypes<typeof buttonPropDefs>;\n secondaryButton?: GetPropDefTypes<typeof buttonPropDefs>;\n destructiveButton?: GetPropDefTypes<typeof buttonPropDefs>;\n iconButton?: GetPropDefTypes<typeof iconButtonPropDefs>;\n textfield?: GetPropDefTypes<typeof textFieldRootPropDefs>;\n select?: GetPropDefTypes<typeof selectTriggerPropDefs>;\n badge?: GetPropDefTypes<typeof badgePropDefs>;\n dropdown?: GetPropDefTypes<typeof dropdownMenuContentPropDefs>;\n primaryMenuItem?: GetPropDefTypes<typeof dropdownMenuItemPropDefs>;\n destructiveMenuItem?: GetPropDefTypes<typeof dropdownMenuItemPropDefs>;\n avatar?: Omit<GetPropDefTypes<typeof avatarPropDefs>, \"fallback\">;\n label?: GetPropDefTypes<typeof textPropDefs>;\n skeleton?: GetPropDefTypes<typeof skeletonPropDefs>;\n}>;\n"],"mappings":"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","names":["Button","props","IconButton","Skeleton","Label","TextField","TextFieldSlot","PasswordField","Badge","Avatar"]}
|
|
@@ -30,9 +30,7 @@ import { usePermissions } from "./use-permissions.js";
|
|
|
30
30
|
import { getDomProps } from "./utils.js";
|
|
31
31
|
import { Translation } from "./i18n/translation.js";
|
|
32
32
|
import { useTranslation } from "./i18n/use-translation.js";
|
|
33
|
-
|
|
34
|
-
const buildRedactedSecret = (last4) => last4 ? `${REDACTED_SECRET_PREFIX}${last4}` : "";
|
|
35
|
-
const isRedactedSecret = (value) => value.startsWith(REDACTED_SECRET_PREFIX);
|
|
33
|
+
import { buildRedactedSecret, isRedactedSecret } from "./redacted-secret.js";
|
|
36
34
|
function RedirectUriField({ value }) {
|
|
37
35
|
const translate = useTranslation();
|
|
38
36
|
const copyLabel = translate({
|
|
@@ -415,6 +413,7 @@ function OrgCredentialsDialog({
|
|
|
415
413
|
{
|
|
416
414
|
value: clientSecret,
|
|
417
415
|
autoComplete: "off",
|
|
416
|
+
type: isRedactedSecret(clientSecret) ? "text" : void 0,
|
|
418
417
|
placeholder: clientSecretPlaceholder,
|
|
419
418
|
"aria-invalid": !!clientSecretError || void 0,
|
|
420
419
|
"aria-describedby": clientSecretError ? "pipes-admin-client-secret-error" : void 0,
|