/** @license MIT | @cube-dev/ui-kit v0.147.0 | Cube Dev Team */
import { mergeProps as mergeProps$1 } from "../../../utils/react/mergeProps.js";
import { useEvent } from "../../../_internal/hooks/use-event.js";
import { ItemActionProvider } from "../../actions/ItemActionContext.js";
import { ItemAction } from "../../actions/ItemAction/ItemAction.js";
import { InlineInput } from "../../content/InlineInput/InlineInput.js";
import { useI18n } from "../../../i18n/useI18n.js";
import { CloseIcon } from "../../../icons/CloseIcon.js";
import { MoreIcon } from "../../../icons/MoreIcon.js";
import { _MenuTrigger } from "../../actions/Menu/MenuTrigger.js";
import { __Menu } from "../../actions/Menu/Menu.js";
import { useContextMenu } from "../../actions/use-context-menu.js";
import { useBoardDragActive } from "../../layout/Board/board-context.js";
import { createMockDragState } from "../../shared/DraggableCollection.js";
import { TabContainer, TabElement } from "./styled.js";
import { POPOVER_PLACEMENT_BY_TABS_PLACEMENT } from "./popover-placement.js";
import { useTabsContext } from "./TabsContext.js";
import { TabDropIndicator } from "./TabDropIndicator.js";
import { RADIO_SIZE_MAP } from "./types.js";
import { Children, cloneElement, isValidElement, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
import { useDraggableItem, useFocus, useFocusVisible, useHover, useTab } from "react-aria";

//#region src/components/navigation/Tabs/TabButton.tsx
const ACTIONS_EVENT_HANDLERS = {
	onClick: (e) => e.stopPropagation(),
	onPointerDown: (e) => e.stopPropagation(),
	onPointerUp: (e) => e.stopPropagation(),
	onMouseDown: (e) => e.stopPropagation(),
	onMouseUp: (e) => e.stopPropagation(),
	onKeyDown: (e) => {
		if (e.key === "Enter" || e.key === " ") e.stopPropagation();
	}
};
const INLINE_INPUT_STYLES = { cursor: "inherit" };
const SPRING_LOAD_DELAY = 500;
/**
* Extracts the raw key from a React element, stripping the ".$" prefix
* that React adds via Children.map/toArray.
*/
function getRawKey(element) {
	if (element.key == null) return null;
	const keyStr = String(element.key);
	return keyStr.startsWith(".$") ? keyStr.slice(2) : keyStr;
}
/**
* Process menu items for predefined action keys (rename, delete).
* Auto-adds labels and disables items when requirements aren't met.
*/
function processMenuItems(children, effectiveIsEditable, isDeletable) {
	const result = [];
	Children.forEach(children, (child) => {
		if (!isValidElement(child)) {
			result.push(child);
			return;
		}
		const childKey = getRawKey(child);
		const childProps = child.props;
		if (childKey === "rename") {
			result.push(cloneElement(child, {
				children: childProps.children ?? "Rename",
				isDisabled: childProps.isDisabled ?? !effectiveIsEditable
			}));
			return;
		}
		if (childKey === "delete") {
			result.push(cloneElement(child, {
				children: childProps.children ?? "Delete",
				theme: childProps.theme ?? "danger",
				isDisabled: childProps.isDisabled ?? !isDeletable
			}));
			return;
		}
		if (childProps.children && typeof childProps.children !== "string") {
			result.push(cloneElement(child, { children: processMenuItems(childProps.children, effectiveIsEditable, isDeletable) }));
			return;
		}
		result.push(child);
	});
	return result;
}
/**
* Check if menu children is empty (null, undefined, or empty fragment)
*/
function isMenuEmpty(menu) {
	if (menu === null || menu === void 0) return true;
	return Children.toArray(menu).length === 0;
}
/**
* Individual tab button component.
*
* Uses TabsContext to access shared props, dramatically reducing prop drilling.
* Handles:
* - Tab selection and keyboard navigation
* - Inline title editing
* - Menu and context menu
* - Drag-and-drop reordering
* - Focus and hover states
*/
function TabButton({ item, tabData, isLastTab }) {
	const { t } = useI18n();
	const editTabTitleLabel = t("tabs.editTabTitle", "Edit tab title");
	const { state, type, size, placement, autoHideActions: parentAutoHideActions, isEditable: parentIsEditable, menu: parentMenu, menuTriggerProps: parentMenuTriggerProps, menuProps: parentMenuProps, contextMenu: parentContextMenu, onAction: parentOnAction, onDelete, dragState, dropState, editingKey, startEditing, submitEditing, cancelEditing } = useTabsContext();
	const ref = useRef(null);
	const containerRef = useRef(null);
	const actionsRef = useRef(null);
	const inlineInputRef = useRef(null);
	const { tabProps } = useTab({ key: item.key }, state, ref);
	const [actionsWidth, setActionsWidth] = useState(0);
	const isDraggable = !!dragState && !!dropState;
	const mockDragState = useMemo(() => createMockDragState(state.collection, state.selectionManager), [state.collection, state.selectionManager]);
	const dragResult = useDraggableItem({ key: item.key }, dragState ?? mockDragState);
	const effectiveDragProps = isDraggable ? dragResult.dragProps : {};
	const isDragging = isDraggable && dragResult.isDragging;
	const [isMenuOpen, setIsMenuOpen] = useState(false);
	const { hoverProps, isHovered } = useHover({});
	const [isFocused, setIsFocused] = useState(false);
	const { focusProps } = useFocus({ onFocusChange: setIsFocused });
	const { isFocusVisible } = useFocusVisible();
	const [suppressFocusVisible, setSuppressFocusVisible] = useState(false);
	const effectiveFocusVisible = isFocusVisible && !suppressFocusVisible;
	const isActive = state.selectedKey === item.key;
	const isDisabled = state.disabledKeys.has(item.key);
	const isDeletable = !!onDelete;
	const isEditing = editingKey === item.key;
	const isBoardDragActive = useBoardDragActive();
	const [isDropPending, setIsDropPending] = useState(false);
	const springLoadTimerRef = useRef(null);
	const clearSpringLoad = useEvent(() => {
		if (springLoadTimerRef.current != null) {
			clearTimeout(springLoadTimerRef.current);
			springLoadTimerRef.current = null;
		}
		setIsDropPending(false);
	});
	const handleSpringLoadEnter = useEvent(() => {
		if (!isBoardDragActive || isActive || isDisabled) return;
		if (springLoadTimerRef.current != null) return;
		setIsDropPending(true);
		springLoadTimerRef.current = window.setTimeout(() => {
			springLoadTimerRef.current = null;
			setIsDropPending(false);
			state.setSelectedKey(item.key);
		}, SPRING_LOAD_DELAY);
	});
	useEffect(() => {
		if (!isBoardDragActive) clearSpringLoad();
		return clearSpringLoad;
	}, [isBoardDragActive, clearSpringLoad]);
	const effectiveIsEditable = (tabData.isEditable ?? parentIsEditable ?? false) && tabData.title != null;
	const effectiveMenu = tabData.menu === null ? null : tabData.menu ?? parentMenu;
	const effectiveMenuTriggerProps = {
		...parentMenuTriggerProps,
		...tabData.menuTriggerProps
	};
	const effectiveMenuProps = {
		...parentMenuProps,
		...tabData.menuProps
	};
	const effectiveContextMenu = tabData.contextMenu ?? parentContextMenu ?? false;
	const effectiveType = type ?? "default";
	const contextMenuEnabled = effectiveContextMenu === true || effectiveContextMenu === "context-only";
	const contextMenuOnly = effectiveContextMenu === "context-only";
	const showDeleteButton = isDeletable && (isMenuEmpty(effectiveMenu) || contextMenuOnly);
	const processedMenu = effectiveMenu && !isMenuEmpty(effectiveMenu) ? processMenuItems(effectiveMenu, effectiveIsEditable, isDeletable) : null;
	const itemKeyStr = String(item.key);
	const handleDelete = useEvent(() => {
		onDelete?.(itemKeyStr);
	});
	const titleString = typeof tabData.title === "string" ? tabData.title : itemKeyStr;
	const handleStartEditing = useEvent(() => {
		if (!effectiveIsEditable || isDisabled) return;
		startEditing(itemKeyStr, titleString);
	});
	const handleSubmitEditing = useEvent((newTitle) => {
		submitEditing(itemKeyStr, newTitle, tabData.onTitleChange);
		setSuppressFocusVisible(true);
		ref.current?.focus();
	});
	const handleCancelEditing = useEvent(() => {
		cancelEditing();
		setSuppressFocusVisible(true);
		ref.current?.focus();
	});
	const handleEditingChange = useEvent((editing) => {
		if (editing && !isEditing) handleStartEditing();
	});
	const renameInputSelector = `input[aria-label="${editTabTitleLabel.replace(/["\\]/g, "\\$&")}"]`;
	const scheduleRenameRefocus = useEvent(() => {
		let seenEditingInput = false;
		let cancelled = false;
		const timers = [];
		const findEditingInput = () => ref.current?.querySelector(renameInputSelector) ?? null;
		const tick = () => {
			if (cancelled) return;
			const editingInput = findEditingInput();
			if (editingInput) {
				seenEditingInput = true;
				if (document.activeElement !== editingInput) inlineInputRef.current?.focus();
				return;
			}
			if (seenEditingInput) {
				cancelled = true;
				for (const t of timers) clearTimeout(t);
			}
		};
		requestAnimationFrame(tick);
		timers.push(window.setTimeout(tick, 50));
		timers.push(window.setTimeout(tick, 200));
		timers.push(window.setTimeout(tick, 400));
	});
	const handleMenuAction = useEvent((action) => {
		const actionStr = String(action);
		const normalizedAction = actionStr.startsWith(".$") ? actionStr.slice(2) : actionStr;
		if (normalizedAction === "rename" && effectiveIsEditable) {
			inlineInputRef.current?.startEditing();
			scheduleRenameRefocus();
		}
		if (normalizedAction === "delete" && isDeletable) onDelete?.(itemKeyStr);
		tabData.onAction?.(normalizedAction);
		parentOnAction?.(normalizedAction, itemKeyStr);
	});
	const menuElement = processedMenu ? /* @__PURE__ */ jsx(__Menu, {
		...effectiveMenuProps,
		onAction: handleMenuAction,
		children: processedMenu
	}) : null;
	const menuPopoverPlacement = POPOVER_PLACEMENT_BY_TABS_PLACEMENT[placement];
	const contextMenu = useContextMenu(__Menu, { placement: menuPopoverPlacement }, {
		...effectiveMenuProps,
		onAction: handleMenuAction,
		children: processedMenu
	});
	const handleKeyDown = useEvent((e) => {
		if (suppressFocusVisible) setSuppressFocusVisible(false);
		if (e.key === "F2" && effectiveIsEditable && !isDisabled) {
			e.preventDefault();
			e.stopPropagation();
			inlineInputRef.current?.startEditing();
		}
		if (e.key === "F10" && e.shiftKey && processedMenu) {
			e.preventDefault();
			e.stopPropagation();
			if (contextMenuOnly) contextMenu.open();
			else setIsMenuOpen(true);
		}
		if ((e.key === "Delete" || e.key === "Backspace") && isDeletable && !isEditing) {
			e.preventDefault();
			onDelete?.(itemKeyStr);
		}
	});
	const mods = useMemo(() => ({
		type: effectiveType,
		placement,
		active: isActive,
		deletable: isDeletable,
		disabled: isDisabled,
		editing: isEditing,
		hovered: isHovered,
		focused: isFocused,
		"focus-visible": effectiveFocusVisible,
		draggable: isDraggable,
		dragging: isDragging,
		"drop-pending": isDropPending
	}), [
		effectiveType,
		placement,
		isActive,
		isDeletable,
		isDisabled,
		isEditing,
		isHovered,
		isFocused,
		effectiveFocusVisible,
		isDraggable,
		isDragging,
		isDropPending
	]);
	useEffect(() => {
		if (ref.current && isActive) ref.current.scrollIntoView?.({
			block: "nearest",
			inline: "nearest"
		});
	}, [isActive]);
	const menuAction = menuElement && !contextMenuOnly ? /* @__PURE__ */ jsxs(_MenuTrigger, {
		isOpen: isMenuOpen,
		placement: menuPopoverPlacement,
		onOpenChange: setIsMenuOpen,
		children: [/* @__PURE__ */ jsx(ItemAction, {
			tabIndex: -1,
			icon: /* @__PURE__ */ jsx(MoreIcon, {}),
			...effectiveMenuTriggerProps
		}), menuElement]
	}) : null;
	const deleteAction = showDeleteButton ? /* @__PURE__ */ jsx(ItemAction, {
		tabIndex: -1,
		icon: /* @__PURE__ */ jsx(CloseIcon, {}),
		tooltip: t("tabs.close", "Close"),
		onPress: handleDelete
	}) : null;
	const actions = tabData.actions || menuAction || deleteAction ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
		tabData.actions,
		menuAction,
		deleteAction
	] }) : void 0;
	useLayoutEffect(() => {
		if (actions && actionsRef.current) setActionsWidth(Math.round(actionsRef.current.offsetWidth));
	}, [actions]);
	const effectiveSize = tabData.size ?? size ?? "medium";
	const itemSize = effectiveType === "radio" ? RADIO_SIZE_MAP[effectiveSize === "large" ? "large" : "medium"] : effectiveSize;
	const itemType = "clear";
	const itemShape = effectiveType === "file" ? "sharp" : void 0;
	const effectiveAutoHideActions = tabData.autoHideActions ?? parentAutoHideActions;
	const { title: _title, content: _content, key: _key, isDisabled: _isDisabled, prerender: _prerender, keepMounted: _keepMounted, size: _size, actions: _actions, autoHideActions: _autoHideActions, isEditable: _isEditable, onTitleChange: _onTitleChange, menu: _menu, menuTriggerProps: _menuTriggerProps, menuProps: _menuProps, contextMenu: _contextMenu, onAction: _onAction, tooltip: tabTooltip, qa, qaVal, styles, ...itemStyleProps } = tabData;
	const renderTitleDisplay = typeof tabData.title === "string" ? void 0 : () => tabData.title;
	const titleContent = effectiveIsEditable ? /* @__PURE__ */ jsx(InlineInput, {
		ref: inlineInputRef,
		value: titleString,
		isEditing,
		isDisabled,
		keyboardActivation: false,
		"aria-label": editTabTitleLabel,
		styles: INLINE_INPUT_STYLES,
		renderDisplay: renderTitleDisplay,
		tooltip: tabTooltip ?? true,
		onEditingChange: handleEditingChange,
		onSubmit: handleSubmitEditing,
		onCancel: handleCancelEditing
	}) : tabData.title;
	const effectiveContainerRef = contextMenuEnabled && processedMenu ? contextMenu.targetRef : containerRef;
	const ariaProps = processedMenu ? { "aria-haspopup": "menu" } : {};
	const containerMods = {
		...mods,
		"auto-hide-actions": effectiveAutoHideActions
	};
	return /* @__PURE__ */ jsxs(TabContainer, {
		ref: effectiveContainerRef,
		"data-size": itemSize,
		mods: containerMods,
		tokens: { "$actions-width": `${actionsWidth}px` },
		...effectiveDragProps,
		children: [
			isDraggable && dropState && /* @__PURE__ */ jsx(TabDropIndicator, {
				target: {
					type: "item",
					key: item.key,
					dropPosition: "before"
				},
				dropState,
				position: "before"
			}),
			/* @__PURE__ */ jsx(TabElement, {
				preserveActionsSpace: true,
				autoHideActions: effectiveAutoHideActions,
				as: "button",
				...mergeProps$1(tabProps, hoverProps, focusProps, {
					onKeyDown: handleKeyDown,
					onPointerEnter: handleSpringLoadEnter,
					onPointerLeave: clearSpringLoad
				}),
				...ariaProps,
				...itemStyleProps,
				ref,
				qa: qa ?? `Tab-${String(item.key)}`,
				qaVal,
				styles,
				mods,
				isSelected: isActive,
				isDisabled,
				size: itemSize,
				type: itemType,
				shape: itemShape,
				actions: actions ? true : void 0,
				tooltip: effectiveIsEditable ? false : tabTooltip,
				children: titleContent
			}),
			actions && /* @__PURE__ */ jsx("div", {
				ref: actionsRef,
				"data-element": "Actions",
				...ACTIONS_EVENT_HANDLERS,
				children: /* @__PURE__ */ jsx(ItemActionProvider, {
					type: itemType,
					theme: "default",
					isDisabled,
					children: actions
				})
			}),
			contextMenuEnabled && processedMenu && contextMenu.rendered,
			isDraggable && dropState && isLastTab && /* @__PURE__ */ jsx(TabDropIndicator, {
				target: {
					type: "item",
					key: item.key,
					dropPosition: "after"
				},
				dropState,
				position: "after"
			})
		]
	});
}

//#endregion
export { TabButton };
//# sourceMappingURL=TabButton.js.map