/**
 * Copyright IBM Corp. 2020, 2026
 *
 * This source code is licensed under the Apache-2.0 license found in the
 * LICENSE file in the root directory of this source tree.
 */

import { __toESM } from "../../_virtual/_rolldown/runtime.js";
import { require_classnames } from "../../node_modules/classnames/index.js";
import { pkg } from "../../settings.js";
import { usePreviousValue } from "../../global/js/hooks/usePreviousValue.js";
import { useFocus } from "../../global/js/hooks/useFocus.js";
import { getDevtoolsProps } from "../../global/js/utils/devtools.js";
import { usePortalTarget } from "../../global/js/hooks/usePortalTarget.js";
import uuidv4 from "../../global/js/utils/uuidv4.js";
import { APIKeyDownloader } from "./APIKeyDownloader.js";
import React, { forwardRef, useEffect, useRef, useState } from "react";
import PropTypes from "prop-types";
import { Button, ComposedModal, Form, InlineLoading, ModalBody, ModalFooter, ModalHeader, PasswordInput, TextInput, unstable_FeatureFlags } from "@carbon/react";
import { CheckmarkFilled, Copy, ErrorFilled, InformationFilled } from "@carbon/react/icons";
//#region src/components/APIKeyModal/APIKeyModal.tsx
var import_classnames = /* @__PURE__ */ __toESM(require_classnames());
const componentName = "APIKeyModal";
const defaults = {
	apiKeyName: "",
	customSteps: []
};
const APIKeyModal = forwardRef(({ apiKey, apiKeyLabel, apiKeyName = defaults.apiKeyName, body, className, closeButtonText, copyButtonText, copyErrorText, copyIconDescription, customSteps = defaults.customSteps, downloadBodyText, downloadFileName, downloadFileType, downloadLinkText, downloadLinkLabel = downloadLinkText, editButtonText, editSuccess, editSuccessTitle, editSuccessMessage, editing, error, errorText, generateButtonText, generateSuccessBody, generateSuccessTitle, generateSuccessMessage, generateTitle, hasAPIKeyVisibilityToggle, hasDownloadLink, hideAPIKeyLabel, launcherButtonRef, loading, loadingText, modalLabel, nameHelperText, nameLabel, namePlaceholder, nameRequired, nextStepButtonText, onClose, onCopy, onRequestEdit, onRequestGenerate, open, portalTarget: portalTargetIn, previousStepButtonText, showAPIKeyLabel, helperText, ...rest }, ref) => {
	const [title, setTitle] = useState(null);
	const [successMessage, setSuccessMessage] = useState(null);
	const [copyError, setCopyError] = useState(false);
	const [name, setName] = useState(apiKeyName);
	const [currentStep, setCurrentStep] = useState(0);
	const copyRef = useRef(void 0);
	const apiKeyInputId = useRef(uuidv4());
	const nameInputId = useRef(uuidv4());
	const renderPortalUse = usePortalTarget(portalTargetIn);
	const hasSteps = Boolean(customSteps.length);
	const apiKeyLoaded = apiKey && !loading;
	const hasNextStep = hasSteps && currentStep < customSteps.length - 1;
	const hasPreviousStep = hasSteps && currentStep !== 0;
	const copyButtonProps = {
		renderIcon: (props) => /* @__PURE__ */ React.createElement(Copy, {
			size: 16,
			...props
		}),
		iconDescription: copyIconDescription,
		ref: copyRef
	};
	const blockClass = `${pkg.prefix}--apikey-modal`;
	const localRef = useRef(void 0);
	const PasswordInputRef = useRef(null);
	const modalRef = ref || localRef;
	const { firstElement, keyDownListener, claimFocus } = useFocus(modalRef);
	const prevOpen = usePreviousValue(open);
	useEffect(() => {
		if (copyRef.current && open && apiKeyLoaded) copyRef.current.focus();
		if (PasswordInputRef?.current) PasswordInputRef?.current.setAttribute("readOnly", "true");
	}, [open, apiKeyLoaded]);
	useEffect(() => {
		if (open) setTimeout(() => claimFocus(), 0);
	}, [
		modalRef,
		open,
		firstElement
	]);
	useEffect(() => {
		if (prevOpen && !open && launcherButtonRef) setTimeout(() => {
			launcherButtonRef.current.focus();
		}, 0);
	}, [
		launcherButtonRef,
		open,
		prevOpen
	]);
	const isPrimaryButtonDisabled = () => {
		if (loading) return true;
		if (hasSteps && "valid" in (customSteps?.[currentStep] || [])) return !customSteps[currentStep]?.valid;
		if (!hasSteps && nameRequired && !name) return true;
		return false;
	};
	const getPrimaryButtonText = () => {
		if (hasNextStep) return nextStepButtonText;
		if (apiKeyLoaded) return copyButtonText;
		if (editing) return editButtonText;
		return generateButtonText;
	};
	const getSecondaryButtonText = () => {
		if (hasPreviousStep && !apiKeyLoaded) return previousStepButtonText;
		return closeButtonText;
	};
	useEffect(() => {
		if (editing && editSuccess) {
			setTitle(generateTitle);
			setSuccessMessage(editSuccessMessage ?? editSuccessTitle);
		} else if (apiKeyLoaded) {
			setTitle(generateTitle);
			setSuccessMessage(generateSuccessMessage ?? generateSuccessTitle);
		} else if (hasSteps) setTitle(customSteps[currentStep]?.title);
		else setTitle(generateTitle);
	}, [
		apiKeyLoaded,
		loading,
		editing,
		editSuccess,
		editSuccessTitle,
		editSuccessMessage,
		hasSteps,
		generateSuccessTitle,
		generateSuccessMessage,
		generateTitle,
		currentStep,
		customSteps
	]);
	const setNameHandler = (evt) => {
		setName(evt.target.value);
	};
	const onCloseHandler = () => {
		setName("");
		setCurrentStep(0);
		onClose?.();
	};
	const submitHandler = async (e) => {
		e.preventDefault();
		if (hasNextStep) setCurrentStep(currentStep + 1);
		else if (apiKeyLoaded) if (onCopy) onCopy(apiKey);
		else try {
			await navigator.clipboard.writeText(apiKey);
		} catch (e) {
			console.error(e);
			setCopyError(true);
		}
		else if (editing) onRequestEdit?.(name);
		else onRequestGenerate?.(name);
	};
	const onBackHandler = () => {
		if (hasPreviousStep && !apiKeyLoaded) setCurrentStep(currentStep - 1);
		else onCloseHandler();
	};
	return renderPortalUse(/* @__PURE__ */ React.createElement(unstable_FeatureFlags, { enableExperimentalFocusWrapWithoutSentinels: true }, /* @__PURE__ */ React.createElement(ComposedModal, {
		...rest,
		open,
		...getDevtoolsProps(componentName),
		ref: modalRef,
		onKeyDown: keyDownListener,
		className: (0, import_classnames.default)(className, blockClass),
		onClose: onCloseHandler,
		size: "sm",
		"aria-label": modalLabel,
		preventCloseOnClickOutside: true
	}, /* @__PURE__ */ React.createElement(ModalHeader, {
		className: `${blockClass}__header`,
		title,
		label: modalLabel
	}), /* @__PURE__ */ React.createElement(ModalBody, { className: `${blockClass}__body-container` }, hasSteps && !apiKeyLoaded ? customSteps[currentStep]?.content : /* @__PURE__ */ React.createElement(React.Fragment, null, body && /* @__PURE__ */ React.createElement("p", { className: `${blockClass}__body` }, body), !editing && apiKey && hasAPIKeyVisibilityToggle && /* @__PURE__ */ React.createElement(PasswordInput, {
		value: apiKey,
		labelText: apiKeyLabel,
		id: apiKeyInputId.current,
		showPasswordLabel: showAPIKeyLabel,
		hidePasswordLabel: hideAPIKeyLabel,
		tooltipPosition: "left",
		helperText,
		ref: PasswordInputRef
	}), !editing && apiKey && !hasAPIKeyVisibilityToggle && /* @__PURE__ */ React.createElement(TextInput, {
		value: apiKey,
		labelText: apiKeyLabel,
		id: apiKeyInputId.current
	}), (editing || !apiKeyLoaded && nameRequired) && /* @__PURE__ */ React.createElement(Form, {
		onSubmit: submitHandler,
		"aria-label": title ?? void 0
	}, /* @__PURE__ */ React.createElement(TextInput, {
		helperText: nameHelperText,
		placeholder: namePlaceholder,
		labelText: nameLabel,
		onChange: setNameHandler,
		value: name,
		id: nameInputId.current,
		disabled: loading,
		required: nameRequired,
		"data-modal-primary-focus": true
	})), loading && /* @__PURE__ */ React.createElement(InlineLoading, {
		description: loadingText,
		className: `${blockClass}__loader`
	}), (copyError || error) && /* @__PURE__ */ React.createElement("div", { className: `${blockClass}__messaging` }, /* @__PURE__ */ React.createElement("div", { className: `${blockClass}__error-icon` }, /* @__PURE__ */ React.createElement(ErrorFilled, { size: 16 })), /* @__PURE__ */ React.createElement("p", {
		className: `${blockClass}__messaging-text`,
		role: "alert",
		"aria-live": "assertive"
	}, copyError ? copyErrorText : errorText)), apiKeyLoaded && /* @__PURE__ */ React.createElement("div", { className: `${blockClass}__messaging` }, /* @__PURE__ */ React.createElement(InformationFilled, { size: 16 }), hasDownloadLink ? /* @__PURE__ */ React.createElement(APIKeyDownloader, {
		apiKey,
		body: downloadBodyText,
		fileName: downloadFileName,
		linkText: downloadLinkText,
		fileType: downloadFileType,
		downloadLinkLabel
	}) : /* @__PURE__ */ React.createElement("div", {
		className: `${blockClass}__messaging-text`,
		role: "alert",
		"aria-live": "assertive"
	}, generateSuccessBody)), (editSuccess || apiKeyLoaded && successMessage) && /* @__PURE__ */ React.createElement("div", { className: `${blockClass}__messaging` }, /* @__PURE__ */ React.createElement(CheckmarkFilled, {
		size: 16,
		className: `${blockClass}__checkmark-icon`
	}), /* @__PURE__ */ React.createElement("p", {
		className: `${blockClass}__messaging-text`,
		role: "alert",
		"aria-live": "assertive"
	}, successMessage)))), /* @__PURE__ */ React.createElement(ModalFooter, { className: `${blockClass}__footer` }, /* @__PURE__ */ React.createElement(Button, {
		type: "button",
		kind: "secondary",
		onClick: onBackHandler
	}, getSecondaryButtonText()), /* @__PURE__ */ React.createElement(Button, {
		...apiKeyLoaded && copyButtonProps,
		type: "submit",
		kind: "primary",
		onClick: submitHandler,
		disabled: isPrimaryButtonDisabled()
	}, getPrimaryButtonText())))));
});
const deprecatedProps = {
	/**
	* deprecated
	* title for a successful edit
	*/
	editSuccessTitle: PropTypes.string,
	/**
	* deprecated
	* title for a successful key generation
	*/
	generateSuccessTitle: PropTypes.string
};
APIKeyModal.propTypes = {
	/**
	* the api key that's displayed to the user when a request to create is fulfilled.
	*/
	apiKey: PropTypes.string,
	/**
	* label for the text input that holds the api key.
	*/
	apiKeyLabel: PropTypes.string,
	/**
	* the name of the api key. should only be supplied in edit mode.
	*/
	apiKeyName: PropTypes.string,
	/**
	* body content for the modal
	*/
	body: PropTypes.string,
	/**
	* optional class name
	*/
	className: PropTypes.string,
	/**
	* text for the close button
	*/
	closeButtonText: PropTypes.string,
	/**
	* text for the copy button
	*/
	copyButtonText: PropTypes.string,
	/**
	* Error message for when the copy function fails
	*/
	copyErrorText: PropTypes.string,
	/**
	* text description for the copy button icon
	*/
	copyIconDescription: PropTypes.string,
	/**
	* if you need more options for key creation beyond just the name use custom steps to obtain whatever data is required.
	*/
	/**@ts-ignore*/
	customSteps: PropTypes.arrayOf(PropTypes.shape({
		/**
		* designates if the step has passed whatever validation rules are in place.
		*/
		valid: PropTypes.bool,
		/**
		* designates content is the JSX that holds whatever inputs you need
		*/
		content: PropTypes.node,
		/**
		* designates the title that's displayed at the top of the modal for each step
		*/
		title: PropTypes.string
	})),
	/**
	* the content that appears that indicates the key is downloadable
	*/
	downloadBodyText: PropTypes.string,
	/**
	* designates the name of downloadable json file with the key. if not specified will default to 'apikey'
	*/
	downloadFileName: PropTypes.string,
	/**
	* designates the file type for the downloadable key
	*/
	downloadFileType: PropTypes.oneOf(["txt", "json"]),
	/**
	* aria-label for the download link
	*/
	downloadLinkLabel: PropTypes.string,
	/**
	* anchor text for the download link
	*/
	downloadLinkText: PropTypes.string,
	/**
	* text for the edit button
	*/
	editButtonText: PropTypes.string,
	/**
	* designates if the edit request was successful
	*/
	editSuccess: PropTypes.bool,
	/**
	* title for a successful edit
	*/
	editSuccessMessage: PropTypes.string,
	/**
	* designates if the modal is in the edit mode
	*/
	editing: PropTypes.bool,
	/**
	* designates if an error has occurred in a request
	*/
	error: PropTypes.bool,
	/**
	* text to display if an error has occurred
	*/
	errorText: PropTypes.string,
	/**
	* default primary button text for modal in assumed default mode create or generate.
	* in create mode this is the button text prior to supplying an api key, which then
	* uses copyButtonText
	*/
	generateButtonText: PropTypes.string,
	/**
	* content to display if generate request was successful
	*/
	generateSuccessBody: PropTypes.node,
	/**
	* title for a successful key generation
	*/
	generateSuccessMessage: PropTypes.string,
	/**
	* default title for the modal in generate key mode
	*/
	generateTitle: PropTypes.string,
	/**
	* designates if the api input has the visibility toggle enabled
	*/
	hasAPIKeyVisibilityToggle: PropTypes.bool,
	/**
	* designates if user is able to download the api key
	*/
	hasDownloadLink: PropTypes.bool,
	/**
	* helper text for password input
	*/
	helperText: PropTypes.string,
	/**
	* label text that's displayed when hovering over visibility toggler to hide key
	*/
	hideAPIKeyLabel: PropTypes.string,
	/**
	* Provide a ref to return focus to once the tearsheet is closed.
	*/
	/**@ts-ignore */
	launcherButtonRef: PropTypes.any,
	/**
	* designates if the modal is in a loading state via a request or some other in progress operation
	*/
	loading: PropTypes.bool,
	/**
	* text that displays while modal is in the loading state
	*/
	loadingText: PropTypes.string,
	/**
	* general label text for modal
	*/
	modalLabel: PropTypes.string,
	/**
	* helper text for name input
	*/
	nameHelperText: PropTypes.string,
	/**
	* label for api key name input
	*/
	nameLabel: PropTypes.string,
	/**
	* placeholder text for api key name input
	*/
	namePlaceholder: PropTypes.string,
	/**
	* designates if a name is required or not for key generation. NOTE- if using custom steps set this to false since you will be using your own validation
	*/
	nameRequired: PropTypes.bool,
	/**
	* text that displays in the primary button when using custom steps to indicate to the user that there is a next step
	*/
	nextStepButtonText: PropTypes.string,
	/**
	* handler for on modal close
	*/
	onClose: PropTypes.func,
	/**
	* Optional callback if you want to use your own copy function instead of the build in one
	* onCopy(apiKey)
	*/
	onCopy: PropTypes.func,
	/**
	* handler for api key edit
	*/
	onRequestEdit: PropTypes.func,
	/**
	* handler for api key generation
	*/
	onRequestGenerate: PropTypes.func,
	/**
	* designates if modal is open or closed
	*/
	open: PropTypes.bool.isRequired,
	/**
	* The DOM node the tearsheet should be rendered within. Defaults to document.body.
	*/
	portalTarget: PropTypes.node,
	/**
	* text that displays in the secondary button when using custom steps to indicate to the user that there is a previous step
	*/
	previousStepButtonText: PropTypes.string,
	/**
	* label text that's displayed when hovering over visibility toggler to show key
	*/
	showAPIKeyLabel: PropTypes.string,
	...deprecatedProps
};
APIKeyModal.displayName = componentName;
//#endregion
export { APIKeyModal };
