/**
 * 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 { getDevtoolsProps } from "../../global/js/utils/devtools.js";
import React, { forwardRef, useEffect, useRef, useState } from "react";
import PropTypes from "prop-types";
import { IconButton, Toggletip, ToggletipButton, ToggletipContent, usePrefix } from "@carbon/react";
import { Checkmark, Close, Edit, EditOff, WarningFilled } from "@carbon/react/icons";

//#region src/components/EditInPlace/EditInPlace.tsx
/**
* Copyright IBM Corp. 2022, 2025
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
var import_classnames = /* @__PURE__ */ __toESM(require_classnames());
const componentName = "EditInPlace";
const blockClass = `${pkg.prefix}--edit-in-place`;
const defaults = {
	tooltipAlignment: "top",
	size: "sm"
};
const EditInPlace = forwardRef(({ cancelLabel, editAlwaysVisible, editLabel, id, inheritTypography, invalid, invalidLabel: deprecated_invalidLabel = " ", invalidText, labelText, onCancel, onChange, onSave, onBlur, readOnly, readOnlyLabel, readOnlyToggleTipText, saveLabel, size = "sm", toggleTipAlignment, tooltipAlignment, value, placeholder, ...rest }, ref) => {
	const [focused, setFocused] = useState(false);
	const [initialValue, setInitialValue] = useState("");
	const [dirtyInput, setDirtyInput] = useState(false);
	const inputRef = useRef(null);
	const canSave = value !== initialValue && !invalid;
	const escaping = useRef(false);
	const carbonPrefix = usePrefix();
	const tipAlignIsObject = typeof tooltipAlignment === "object";
	const tipAlignments = [
		"edit",
		"save",
		"cancel"
	].reduce((acc, tips) => {
		acc[tips] = (tipAlignIsObject ? tooltipAlignment[tips] : tooltipAlignment) ?? defaults.tooltipAlignment;
		return acc;
	}, {});
	useEffect(() => {
		if (!initialValue && !dirtyInput) setInitialValue(value);
	}, [
		initialValue,
		dirtyInput,
		value
	]);
	const isTargetingChild = ({ currentTarget, relatedTarget }) => currentTarget.contains(relatedTarget);
	const onChangeHandler = ({ target }) => {
		if (!dirtyInput) setDirtyInput(true);
		onChange(target.value);
	};
	const onFocusHandler = (e) => {
		if (!isTargetingChild(e)) {
			inputRef.current?.focus();
			setFocused(true);
		}
	};
	const onSaveHandler = () => {
		setInitialValue(value);
		setDirtyInput(false);
		onSave();
		setFocused(false);
	};
	const onCancelHandler = () => {
		setDirtyInput(false);
		onCancel(initialValue);
	};
	const onBlurHandler = (e) => {
		if (typeof onBlur === "function" && !isTargetingChild(e)) {
			onBlur(initialValue);
			setFocused(false);
		} else {
			if (escaping.current) return;
			if (!isTargetingChild(e)) if (canSave) onSaveHandler();
			else {
				onCancelHandler();
				setFocused(false);
			}
		}
	};
	const returnHandler = () => {
		if (canSave) onSaveHandler();
	};
	const escapeHandler = () => {
		onCancelHandler();
	};
	const removeFocus = () => {
		inputRef.current?.blur();
		setFocused(false);
	};
	const onKeyHandler = (e) => {
		escaping.current = true;
		switch (e.key) {
			case "Escape":
				removeFocus();
				escapeHandler();
				break;
			case "Enter":
				removeFocus();
				returnHandler();
				break;
			default: break;
		}
		escaping.current = false;
	};
	const inputElement = /* @__PURE__ */ React.createElement("input", {
		id,
		className: (0, import_classnames.default)(`${blockClass}__text-input`, `${carbonPrefix}--text-input`, `${carbonPrefix}--text-input--${size}`),
		type: "text",
		placeholder,
		value,
		onChange: onChangeHandler,
		ref: inputRef,
		readOnly,
		onKeyDown: onKeyHandler,
		"aria-label": labelText,
		"aria-invalid": invalid
	});
	const inputContainer = /* @__PURE__ */ React.createElement("div", {
		className: (0, import_classnames.default)(blockClass, `${blockClass}--${size}`, {
			[`${blockClass}--focused`]: focused,
			[`${blockClass}--invalid`]: invalid,
			[`${blockClass}--inherit-type`]: inheritTypography,
			[`${blockClass}--overflows`]: inputRef.current && inputRef.current.scrollWidth > inputRef.current.offsetWidth,
			[`${blockClass}--readonly`]: readOnly
		}),
		onFocus: onFocusHandler,
		onBlur: onBlurHandler
	}, readOnly ? /* @__PURE__ */ React.createElement(Toggletip, {
		align: toggleTipAlignment,
		className: `${blockClass}__toggletip-wrapper`
	}, /* @__PURE__ */ React.createElement(ToggletipButton, { label: readOnlyLabel || "Edit off" }, inputElement), /* @__PURE__ */ React.createElement(ToggletipContent, null, /* @__PURE__ */ React.createElement("p", null, readOnlyToggleTipText || "This field is read-only and cannot be edited"))) : inputElement, /* @__PURE__ */ React.createElement("div", { className: `${blockClass}__toolbar` }, invalid && /* @__PURE__ */ React.createElement(WarningFilled, {
		size: 16,
		className: `${blockClass}__warning-icon`
	}), readOnly ? /* @__PURE__ */ React.createElement(IconButton, {
		className: `${blockClass}__btn-readonly`,
		size,
		label: readOnlyLabel || "Edit off",
		kind: "ghost",
		key: "readonly",
		onClick: onFocusHandler
	}, /* @__PURE__ */ React.createElement(EditOff, { size: 16 })) : focused ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(IconButton, {
		align: tipAlignments.cancel,
		size,
		label: cancelLabel,
		onClick: onCancelHandler,
		kind: "ghost",
		key: "cancel",
		className: `${blockClass}__btn ${blockClass}__btn-cancel`
	}, /* @__PURE__ */ React.createElement(Close, { size: 16 })), /* @__PURE__ */ React.createElement(IconButton, {
		align: tipAlignments.save,
		size,
		label: saveLabel,
		onClick: onSaveHandler,
		kind: "ghost",
		key: "save",
		className: `${blockClass}__btn ${blockClass}__btn-save`,
		disabled: !canSave
	}, /* @__PURE__ */ React.createElement(Checkmark, { size: 16 }))) : /* @__PURE__ */ React.createElement(IconButton, {
		align: tipAlignments.edit,
		className: (0, import_classnames.default)(`${blockClass}__btn`, `${blockClass}__btn-edit`, { [`${blockClass}__btn-edit--always-visible`]: editAlwaysVisible }),
		size,
		label: editLabel,
		onClick: onFocusHandler,
		kind: "ghost",
		key: "edit"
	}, /* @__PURE__ */ React.createElement(Edit, { size: 16 }))));
	return /* @__PURE__ */ React.createElement("div", {
		...rest,
		ref,
		...getDevtoolsProps(componentName)
	}, inputContainer, invalid && /* @__PURE__ */ React.createElement("p", { className: `${blockClass}__warning-text` }, invalidText ?? deprecated_invalidLabel));
});
EditInPlace.displayName = componentName;
const deprecatedProps = { invalidText: PropTypes.string };
const alignPropType = PropTypes.oneOf([
	"top",
	"top-left",
	"top-right",
	"bottom",
	"bottom-left",
	"bottom-right",
	"left",
	"right"
]);
EditInPlace.propTypes = {
	cancelLabel: PropTypes.string.isRequired,
	editAlwaysVisible: PropTypes.bool,
	editLabel: PropTypes.string.isRequired,
	id: PropTypes.string.isRequired,
	inheritTypography: PropTypes.bool,
	invalid: PropTypes.bool,
	invalidText: PropTypes.string,
	labelText: PropTypes.string.isRequired,
	onBlur: PropTypes.func,
	onCancel: PropTypes.func.isRequired,
	onChange: PropTypes.func.isRequired,
	onSave: PropTypes.func.isRequired,
	placeholder: PropTypes.string,
	readOnly: PropTypes.bool,
	readOnlyLabel: PropTypes.string,
	readOnlyToggleTipText: PropTypes.string,
	saveLabel: PropTypes.string.isRequired,
	size: PropTypes.oneOf([
		"sm",
		"md",
		"lg"
	]),
	toggleTipAlignment: alignPropType,
	tooltipAlignment: PropTypes.oneOfType([alignPropType, PropTypes.shape({
		cancel: alignPropType,
		edit: alignPropType,
		save: alignPropType
	})]),
	value: PropTypes.string.isRequired,
	...deprecatedProps
};

//#endregion
export { EditInPlace };