/**
 * Shared base functionality for collaboration form components
 * Provides common utilities and rendering logic for input and textarea fields
 */
'use client';
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import React from 'react';
import { IoChatbox, IoEye, IoEyeOff, IoAdd, IoTrash, IoTrashOutline, IoLockClosed, IoLockOpen, IoEllipsisVertical, IoDocumentText, IoPencil } from 'react-icons/io5';
import { BiSkipNextCircle } from 'react-icons/bi';
import { MultiStateRadio } from './multi_state_radio.js';
import { DataOkMultiState } from './data_ok_multi_state.js';
import { cn } from '../utils/cn.js';
import { HiddenBadge, ProtectedBadge, ClarificationLabelBadge, FileErrorLabelBadge } from './status_badges.js';
import { DataOkCheckbox } from './data_ok_checkbox.js';
import { CollabFormFileUpload } from './collab_form_file_upload.js';
import { HazoChat } from 'hazo_chat';
import { createClientLogger } from 'hazo_logs/ui';
import { should_show_border } from './shared/role_utils/index.js';
import { FieldTooltip } from './shared/field_tooltip/index.js';
// Create default logger for HazoChat (required in hazo_chat v4.0+)
const chat_logger = createClientLogger({ packageName: 'hazo_chat' });
/**
 * Default chat status colors (used when no config is provided)
 */
export const DEFAULT_CHAT_STATUS_COLORS = {
    icon_color_unread: 'text-destructive',
    icon_bg_unread: 'bg-red-100',
    icon_border_unread: '',
    icon_color_has_messages: 'text-orange-500',
    icon_bg_has_messages: 'bg-orange-100',
    icon_border_has_messages: '',
    icon_color_none: '',
    icon_bg_none: '',
    icon_border_none: '',
};
/**
 * Control icon size configuration
 * Used for consistent sizing across form fields and summary view
 */
export const CONTROL_SIZE_CONFIG = {
    sm: { button: 'h-7 w-7', icon: 'h-4 w-4' }, // Summary view
    md: { button: 'h-9 w-9', icon: 'h-5 w-5' }, // Form fields (default)
};
/**
 * React context for chat status colors configuration
 * Allows colors to be configured once at the form level and used by all child components
 */
export const ChatStatusColorsContext = React.createContext(DEFAULT_CHAT_STATUS_COLORS);
// ========================================
// Field Columns Context
// ========================================
/**
 * Context that controls how many fields appear per row in the form grid.
 *
 * - `field_columns: 1` (default): each field takes the full row width. The
 *   3-column chat-aligned grid (`1fr minmax(0,1fr) 400px`) is used so that an
 *   open chat panel slides neatly into the third column.
 * - `field_columns: 2` or `3`: fields flow in a multi-column grid. The chat
 *   panel side-by-side layout is suspended (chat panels open inline below the
 *   field instead).
 *
 * Provided by `FormViewProvider` (via the `field_columns` prop on
 * `HazoCollabFormView`) and consumed by `CollabFormFieldContainer` and
 * `HazoCollabFormGroup`.
 */
export const FieldColumnsContext = React.createContext({ field_columns: 1 });
/**
 * Hook to read the current field_columns value from context.
 * Returns 1 when no provider is mounted (single-column, backward-compatible default).
 */
export function useFieldColumns() {
    return React.useContext(FieldColumnsContext).field_columns;
}
/**
 * Hook to access chat status colors from context
 */
export function use_chat_status_colors() {
    const context = React.useContext(ChatStatusColorsContext);
    return {
        ...DEFAULT_CHAT_STATUS_COLORS,
        ...context,
    };
}
// NoteEntry is now imported and re-exported from hazo_notes
/**
 * Convert FormFileAttachment array to ReferenceItem array for HazoChat
 */
function convert_files_to_references(files) {
    return files.map((file) => {
        // Determine reference type from file type
        let reference_type = 'document';
        const mime_type = (file.mime_type || '').toLowerCase();
        if (mime_type.startsWith('image/')) {
            reference_type = 'document';
        }
        else if (mime_type === 'application/pdf' || mime_type.includes('document') || mime_type.includes('text')) {
            reference_type = 'document';
        }
        // Construct file URL
        const file_path = file.file_path || '';
        const file_url = file_path.startsWith('/')
            ? file_path
            : `/api/collab-forms/files/${encodeURIComponent(file_path)}`;
        return {
            id: file.file_id,
            type: reference_type,
            scope: 'field',
            name: file.file_name,
            url: file_url,
            mime_type: file.mime_type,
        };
    });
}
/**
 * Resolve effective chat status from chat_status or deprecated has_chat_messages
 * @param chat_status - New chat status prop
 * @param has_chat_messages - Deprecated boolean prop
 * @returns Resolved ChatStatus value
 */
export function resolve_chat_status(chat_status, has_chat_messages) {
    // New prop takes precedence
    if (chat_status !== undefined) {
        return chat_status;
    }
    // Fall back to deprecated boolean
    if (has_chat_messages === true) {
        return 'has_unread'; // Backward compat: true = red (unread)
    }
    return 'none';
}
/**
 * Get CSS classes for chat status indicator
 * @param status - Chat status
 * @param borderless - Whether button is borderless
 * @param colors - Optional custom colors config (uses defaults if not provided)
 * @returns Object with icon_class, container_class, and border_class
 */
export function get_chat_status_classes(status, borderless = false, colors = DEFAULT_CHAT_STATUS_COLORS) {
    // Merge with defaults to ensure all values are present
    const c = { ...DEFAULT_CHAT_STATUS_COLORS, ...colors };
    switch (status) {
        case 'has_unread':
            return {
                icon_class: c.icon_color_unread,
                container_class: borderless
                    ? c.icon_bg_unread
                    : `${c.icon_bg_unread} ${c.icon_border_unread}`,
                border_class: c.icon_border_unread ? `border-2 ${c.icon_border_unread}` : '',
            };
        case 'has_messages':
            return {
                icon_class: c.icon_color_has_messages,
                container_class: borderless
                    ? c.icon_bg_has_messages
                    : `${c.icon_bg_has_messages} ${c.icon_border_has_messages}`,
                border_class: c.icon_border_has_messages ? `border-2 ${c.icon_border_has_messages}` : '',
            };
        default:
            return {
                icon_class: c.icon_color_none,
                container_class: borderless
                    ? c.icon_bg_none
                    : c.icon_bg_none && c.icon_border_none
                        ? `${c.icon_bg_none} ${c.icon_border_none}`
                        : c.icon_bg_none || '',
                border_class: c.icon_border_none ? `border-2 ${c.icon_border_none}` : '',
            };
    }
}
/**
 * Hook for common collaboration form field functionality
 */
export function use_collab_form_field({ label, field_id, id, field_data_id, field_name, on_chat_click, hazo_chat_group_id, hazo_chat_on_open_change, hazo_chat_is_open, hazo_chat_on_close, }) {
    // Generate field ID if not provided
    const field_id_final = id || field_id || `collab-field-${label.toLowerCase().replace(/\s+/g, '-')}`;
    // Internal state for chat open/close (if not controlled externally)
    const [internal_chat_is_open, set_internal_chat_is_open] = React.useState(false);
    // Use controlled value if provided, otherwise use internal state
    const chat_is_open = hazo_chat_is_open !== undefined ? hazo_chat_is_open : internal_chat_is_open;
    const is_chat_controlled = hazo_chat_is_open !== undefined;
    // Get chat group ID
    const chat_group_id = hazo_chat_group_id;
    // Chat is disabled if no chat_group_id is available (unless on_chat_click is provided as fallback)
    const is_chat_disabled = !chat_group_id && !on_chat_click;
    /**
     * Handle chat icon click - trigger callback or open chat
     */
    const handle_chat_icon_click = React.useCallback(() => {
        // If custom on_chat_click is provided, use it (existing behavior)
        if (field_data_id && on_chat_click) {
            on_chat_click(field_data_id, field_name || label);
            return;
        }
        // If hazo_chat_group_id is provided, open chat internally
        if (chat_group_id) {
            const new_open_state = !chat_is_open;
            if (!is_chat_controlled) {
                set_internal_chat_is_open(new_open_state);
            }
            if (hazo_chat_on_open_change) {
                hazo_chat_on_open_change(new_open_state);
            }
        }
    }, [
        field_data_id,
        field_name,
        label,
        on_chat_click,
        chat_group_id,
        chat_is_open,
        is_chat_controlled,
        hazo_chat_on_open_change,
    ]);
    /**
     * Handle chat close - called when close button is clicked in HazoChat
     */
    const handle_chat_close = React.useCallback(() => {
        // Update internal state if not controlled
        if (!is_chat_controlled) {
            set_internal_chat_is_open(false);
        }
        // Call on_close callback if provided
        if (hazo_chat_on_close) {
            hazo_chat_on_close();
        }
        // Call on_open_change callback if provided
        if (hazo_chat_on_open_change) {
            hazo_chat_on_open_change(false);
        }
    }, [hazo_chat_on_close, hazo_chat_on_open_change, is_chat_controlled]);
    return {
        field_id_final,
        handle_chat_icon_click,
        handle_chat_close,
        chat_is_open,
        is_chat_disabled,
        chat_group_id,
        set_internal_chat_is_open,
    };
}
/**
 * Render the container wrapper with colored border for chat messages and grey background when chat is active
 */
export function CollabFormFieldContainer({ has_chat_messages, chat_status, is_chat_active, chat_background_color = 'bg-muted', is_data_ok_default, container_class_name, row_background_color, confirm_state, force_full_row = false, children, 
// Chat-related props
hazo_chat_is_open, hazo_chat_group_id, hazo_chat_reference_id, hazo_chat_reference_type, hazo_chat_api_base_url, hazo_chat_timezone, hazo_chat_title, hazo_chat_subtitle, hazo_chat_realtime_mode, hazo_chat_polling_interval, hazo_chat_messages_per_page, hazo_chat_class_name, hazo_chat_on_close, hazo_chat_show_sidebar_toggle, hazo_chat_show_delete_button, hazo_chat_bubble_radius, hazo_chat_read_only, hazo_chat_hide_references, hazo_chat_hide_sidebar, hazo_chat_hide_preview, hazo_chat_display_mode, hazo_chat_container_element, hazo_chat_log_polling, field_data_id, field_name, label, files, }) {
    // Get chat group ID
    const chat_group_id = hazo_chat_group_id;
    // Determine if chat should be shown (hazo_chat_is_open is passed from the hook)
    const show_chat = hazo_chat_is_open && chat_group_id;
    // Auto-determine is_chat_active from hazo_chat_is_open if not explicitly provided
    const is_chat_active_final = is_chat_active !== undefined ? is_chat_active : hazo_chat_is_open;
    // Convert files to references
    const additional_references = files ? convert_files_to_references(files) : undefined;
    // Determine chat props
    const chat_reference_id = hazo_chat_reference_id || field_data_id || '';
    const chat_reference_type = hazo_chat_reference_type || 'field';
    const chat_title = hazo_chat_title || field_name || label;
    const chat_subtitle = hazo_chat_subtitle || `Discussing ${field_name || label}`;
    // Get chat status colors from context
    const chat_colors = use_chat_status_colors();
    // Resolve chat status for styling
    const effective_chat_status = resolve_chat_status(chat_status, has_chat_messages);
    const chat_classes = get_chat_status_classes(effective_chat_status, false, chat_colors);
    // Read multi-column context: when field_columns > 1, fields share a row
    // unless force_full_row is explicitly set (e.g. textarea, data table).
    const field_columns = useFieldColumns();
    const use_col_span_full = field_columns === 1 || force_full_row;
    // Container content - spans all columns for full width
    const container = (_jsx("div", { className: cn('cls_collab_field_container space-y-2 rounded-md p-2 transition-colors', use_col_span_full && 'col-span-full', confirm_state && `hcf-confirm-${confirm_state}`, chat_classes.border_class, is_chat_active_final && chat_background_color, is_data_ok_default && 'border border-primary/30', row_background_color, container_class_name), children: children }));
    // Use grid cell positioning: field in column 2, chat in column 3 (same row)
    if (show_chat) {
        return (_jsxs(_Fragment, { children: [container, _jsx("div", { className: "cls_collab_chat_wrapper col-start-3", children: _jsx("div", { className: cn('cls_collab_chat_card flex flex-col min-h-0 rounded-md', chat_background_color), style: { height: '400px' }, children: _jsx("div", { className: "cls_collab_chat_content flex-1 flex flex-col min-h-0", children: _jsx("div", { className: "cls_collab_chat_inner flex-1 min-h-0 w-full", children: _jsx(HazoChat, { ...{
                                        chat_group_id,
                                        logger: chat_logger,
                                        reference_id: chat_reference_id,
                                        reference_type: chat_reference_type,
                                        api_base_url: hazo_chat_api_base_url,
                                        timezone: hazo_chat_timezone,
                                        title: chat_title,
                                        subtitle: chat_subtitle,
                                        on_close: hazo_chat_on_close,
                                        realtime_mode: hazo_chat_realtime_mode,
                                        polling_interval: hazo_chat_polling_interval,
                                        messages_per_page: hazo_chat_messages_per_page,
                                        show_sidebar_toggle: hazo_chat_show_sidebar_toggle,
                                        show_delete_button: hazo_chat_show_delete_button,
                                        bubble_radius: hazo_chat_bubble_radius,
                                        read_only: hazo_chat_read_only,
                                        hide_references: hazo_chat_hide_references,
                                        hide_sidebar: hazo_chat_hide_sidebar,
                                        hide_preview: hazo_chat_hide_preview,
                                        display_mode: hazo_chat_display_mode,
                                        container_element: hazo_chat_container_element,
                                        log_polling: hazo_chat_log_polling ?? false,
                                        className: cn('h-full w-full', hazo_chat_class_name),
                                        additional_references,
                                    } }) }) }) }) })] }));
    }
    // No chat open - just return the container
    return container;
}
/**
 * Render the field label with optional status badges
 */
import { IhelpIcon as IhelpIconLoader } from './shared/ihelp_icon.js';
export function CollabFormFieldLabel({ field_id_final, label, label_class_name, required, visibility, locked, tooltip, ihelp_context_key, label_actions, clarification_count, has_clarification, file_error_count, on_file_error_click, }) {
    const is_hidden = visibility === 'hidden';
    const is_locked = locked === true;
    return (_jsxs("label", { htmlFor: field_id_final, className: cn('cls_collab_field_label text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 inline-flex items-center gap-1.5 flex-wrap', label_class_name), children: [(clarification_count && clarification_count > 0) ? (_jsx(ClarificationLabelBadge, { count: clarification_count })) : (has_clarification && (_jsx(ClarificationLabelBadge, { indicator_only: true }))), _jsx("span", { children: label }), ihelp_context_key && _jsx(IhelpIconLoader, { context_key: ihelp_context_key }), tooltip && _jsx(FieldTooltip, { tooltip: tooltip }), required && _jsx("span", { className: "text-destructive", children: "*" }), !!(file_error_count && file_error_count > 0) && (_jsx(FileErrorLabelBadge, { count: file_error_count, on_click: on_file_error_click })), is_hidden && _jsx(HiddenBadge, {}), is_locked && _jsx(ProtectedBadge, {}), label_actions] }));
}
/**
 * Render the chat icon button
 */
export function CollabFormChatIcon({ label, error, on_click, multi_state_radio, has_chat_messages, chat_status, disabled, button_disabled, borderless = false, size = 'md', }) {
    // Don't render if explicitly disabled (hide completely)
    if (disabled) {
        return null;
    }
    // Button is disabled if button_disabled is true (but icon is still visible)
    const is_button_disabled = button_disabled === true;
    // Get chat status colors from context
    const chat_colors = use_chat_status_colors();
    // Resolve effective chat status
    const effective_status = resolve_chat_status(chat_status, has_chat_messages);
    const chat_has_activity = effective_status !== 'none';
    const chat_classes = get_chat_status_classes(effective_status, borderless, chat_colors);
    const size_config = CONTROL_SIZE_CONFIG[size];
    // Determine title based on status
    const get_title = () => {
        if (is_button_disabled)
            return 'Chat unavailable (chat group not configured)';
        if (effective_status === 'has_unread')
            return 'Has unread messages';
        if (effective_status === 'has_messages')
            return 'Has messages';
        return 'Open chat';
    };
    return (_jsxs("div", { className: "cls_collab_chat_icon_wrapper flex items-center gap-2", children: [multi_state_radio && (_jsx(MultiStateRadio, { data: multi_state_radio.data, value: multi_state_radio.value, onChange: multi_state_radio.onChange, icon_set: multi_state_radio.icon_set, selection: multi_state_radio.selection, bgcolor: multi_state_radio.bgcolor, fgcolor: multi_state_radio.fgcolor, interaction_mode: multi_state_radio.interaction_mode, long_press_ms: multi_state_radio.long_press_ms, size: multi_state_radio.size, "aria-label": `Status for ${label}` })), _jsx("button", { type: "button", onClick: on_click, disabled: is_button_disabled, className: cn('cls_collab_chat_icon flex items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50', size_config.button, !borderless && 'border border-input', !borderless && error && 'border-destructive', effective_status === 'has_unread' && 'bg-red-100', effective_status === 'has_messages' && 'bg-orange-100'), "aria-label": `Chat about ${label}`, title: get_title(), children: _jsx(IoChatbox, { className: cn(size_config.icon, chat_classes.icon_class || 'text-muted-foreground') }) })] }));
}
/**
 * Render the error message
 */
export function CollabFormFieldError({ field_id_final, error, error_class_name, }) {
    if (!error)
        return null;
    return (_jsx("p", { id: `${field_id_final}-error`, className: cn('cls_collab_field_error text-sm text-destructive', error_class_name), role: "alert", children: error }));
}
/**
 * Format reference value for display
 * Handles string, number, and boolean values
 */
function format_reference_value(value) {
    if (value === undefined || value === null) {
        return undefined;
    }
    if (typeof value === 'boolean') {
        return value ? 'Yes' : 'No';
    }
    if (typeof value === 'number') {
        // Format as currency if it's a monetary value (2 decimal places or more than 100)
        if (value >= 100 || value % 1 !== 0) {
            return new Intl.NumberFormat('en-AU', {
                style: 'currency',
                currency: 'AUD',
                minimumFractionDigits: 2,
            }).format(value);
        }
        return value.toString();
    }
    return String(value);
}
/**
 * Render a single reference tag entry
 */
function ReferenceTagEntry({ display_text, background_color = 'bg-muted', on_delete, }) {
    return (_jsxs("div", { className: "group/ref inline-flex items-center gap-1", children: [_jsx("div", { className: cn('cls_collab_field_reference_tag inline-flex items-center px-2 py-0.5 rounded text-xs text-muted-foreground', background_color), children: display_text }), on_delete && (_jsx("button", { type: "button", onClick: on_delete, className: "opacity-0 group-hover/ref:opacity-100 transition-opacity p-0.5 rounded hover:bg-destructive/10", title: "Remove reference", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-muted-foreground hover:text-destructive", children: [_jsx("path", { d: "M3 6h18" }), _jsx("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }), _jsx("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" })] }) }))] }));
}
/**
 * Render the reference tag(s) below the field input
 * Supports both single and multiple reference entries with optional delete
 */
export function CollabFormFieldReferenceTag({ reference_data, reference_value, reference_label, reference_tag_background_color = 'bg-muted', on_reference_delete, }) {
    let entries;
    if (reference_data) {
        entries = Array.isArray(reference_data) ? reference_data : [reference_data];
    }
    else if (reference_value !== undefined || reference_label) {
        entries = [{ value: reference_value, label: reference_label, background_color: reference_tag_background_color }];
    }
    else {
        return null;
    }
    // Filter to entries that have displayable content (exclude array values — rendered by TableReferenceAccordion)
    const displayable = entries.filter(e => {
        if (Array.isArray(e.value))
            return false;
        const fv = format_reference_value(e.value);
        return fv || e.label;
    });
    if (displayable.length === 0)
        return null;
    return (_jsx("div", { className: "flex flex-col gap-1", children: displayable.map((entry, index) => {
            const formatted = format_reference_value(entry.value);
            let display_text;
            if (entry.label && formatted) {
                display_text = `${entry.label}: ${formatted}`;
            }
            else {
                display_text = entry.label || formatted;
            }
            return (_jsx(ReferenceTagEntry, { display_text: display_text, background_color: entry.background_color ?? 'bg-muted', on_delete: on_reference_delete ? () => on_reference_delete(index) : undefined }, entry.id ?? index));
        }) }));
}
/**
 * Render the data OK checkbox or multi-state selector
 * Provides consistent data OK functionality across all form fields
 * Supports both binary checkbox mode and multi-state mode
 */
export function CollabFormDataOkCheckbox({ label, data_ok_checked: controlled_data_ok_checked, on_data_ok_change, data_ok_mode = 'checkbox', data_ok_value: controlled_data_ok_value, on_data_ok_value_change, data_ok_default, data_ok_hidden_states, disabled, editable = false, borderless = false, }) {
    if (disabled) {
        return null;
    }
    // Compute default for checkbox mode
    const checkbox_default = typeof data_ok_default === 'boolean' ? data_ok_default : false;
    // Compute default for multi-state mode
    const multi_state_default = (data_ok_default === 'ok' || data_ok_default === 'not_ok' || data_ok_default === 'pending')
        ? data_ok_default
        : 'not_ok';
    // Internal state for checkbox mode (uncontrolled)
    const [internal_data_ok_checked, set_internal_data_ok_checked] = React.useState(checkbox_default);
    // Internal state for multi-state mode (uncontrolled)
    const [internal_data_ok_value, set_internal_data_ok_value] = React.useState(multi_state_default);
    // Checkbox mode
    if (data_ok_mode === 'checkbox') {
        const data_ok_checked = controlled_data_ok_checked !== undefined
            ? controlled_data_ok_checked
            : internal_data_ok_checked;
        const is_controlled = controlled_data_ok_checked !== undefined;
        const handle_data_ok_change = (checked) => {
            if (!is_controlled) {
                set_internal_data_ok_checked(checked);
            }
            if (on_data_ok_change) {
                on_data_ok_change(checked);
            }
        };
        return (_jsx(DataOkCheckbox, { checked: data_ok_checked, onChange: handle_data_ok_change, "aria-label": `Data OK for ${label}`, disabled: !editable }));
    }
    // Multi-state mode
    const data_ok_value = controlled_data_ok_value !== undefined
        ? controlled_data_ok_value
        : internal_data_ok_value;
    const is_value_controlled = controlled_data_ok_value !== undefined;
    const handle_data_ok_value_change = (value) => {
        if (!is_value_controlled) {
            set_internal_data_ok_value(value);
        }
        if (on_data_ok_value_change) {
            on_data_ok_value_change(value);
        }
    };
    return (_jsx(DataOkMultiState, { value: data_ok_value, onChange: handle_data_ok_value_change, disabled: !editable, "aria-label": `Data validation status for ${label}`, show_border: !borderless, hidden_states: data_ok_hidden_states }));
}
/**
 * Render the file upload component
 * Provides file upload functionality for collaboration form fields
 */
export function CollabFormFileUploadSection({ field_id_final, accept_files_public, accept_files_private, files_dir, default_file_accordion_open, max_size, min_files, max_files, file_accept, file_validator, file_manager, files, on_files_change, 
// Private file props
private_files_permission, can_access_private_files, private_files, on_private_files_change, 
// File status props
show_file_status, allow_reupload, scope_id, uploaded_by, 
// File validation state
validating_file_ids, 
// File error state
error_file_ids, passed_file_ids, error_file_details, 
// Clarification state
clarification_items, clarification_callbacks, 
// Upload suppression
hide_upload_dropzone, 
// Autofill dropzone replacement
autofill_dropzone, }) {
    // Always render wrapper div to maintain consistent DOM structure
    // This prevents hydration mismatches when file settings change between server and client
    if (!file_manager) {
        // Without file_manager, file upload is not functional
        return (_jsx("div", { className: "cls_collab_file_upload_section_wrapper", suppressHydrationWarning: true }));
    }
    return (_jsx("div", { className: "cls_collab_file_upload_section_wrapper", suppressHydrationWarning: true, children: (accept_files_public || accept_files_private) ? (_jsx(CollabFormFileUpload, { field_id_final: field_id_final, accept_files_public: accept_files_public, accept_files_private: accept_files_private, files_dir: files_dir, default_file_accordion_open: default_file_accordion_open, max_size: max_size, min_files: min_files, max_files: max_files, file_accept: file_accept, file_validator: file_validator, file_manager: file_manager, files: files, on_files_change: on_files_change, 
            // Private file props
            private_files_permission: private_files_permission, can_access_private_files: can_access_private_files, private_files: private_files, on_private_files_change: on_private_files_change, 
            // Status props
            show_file_status: show_file_status, allow_reupload: allow_reupload, scope_id: scope_id, uploaded_by: uploaded_by, validating_file_ids: validating_file_ids, error_file_ids: error_file_ids, passed_file_ids: passed_file_ids, error_file_details: error_file_details, clarification_items: clarification_items, clarification_callbacks: clarification_callbacks, hide_upload_dropzone: hide_upload_dropzone, autofill_dropzone: autofill_dropzone })) : null }));
}
/**
 * Render the notes icon button with popover or slide panel
 * Wraps HazoNotesIcon from hazo_notes package (dynamically loaded)
 *
 * **Modes:**
 * - **Uncontrolled mode** (recommended): Don't pass `notes` or `on_notes_change`.
 *   The component will use hazo_notes internal hooks to fetch/persist notes via API.
 *   Requires hazo_notes API routes to be set up in your app.
 *
 * - **Controlled mode**: Pass both `notes` and `on_notes_change` to manage notes
 *   state externally. You are responsible for persisting notes.
 */
export function CollabFormNotesIcon({ label, has_notes, notes, on_notes_change, disabled, current_user, field_data_id, className, icon_size = 28, show_border = true, panel_style, background_color, save_mode, open, onOpenChange, default_open, }) {
    // Determine if we're in controlled mode (notes and on_notes_change both provided)
    const is_controlled = notes !== undefined && on_notes_change !== undefined;
    // State for dynamically loaded HazoNotesIcon
    const [HazoNotesIconComponent, setHazoNotesIconComponent] = React.useState(null);
    // State to track if we should show the popover open (delayed until component is loaded)
    const [should_open, set_should_open] = React.useState(false);
    // Dynamically load HazoNotesIcon from hazo_notes
    React.useEffect(() => {
        const loadComponent = async () => {
            try {
                const hazoNotesModule = await import('hazo_notes');
                if (hazoNotesModule?.HazoNotesIcon) {
                    setHazoNotesIconComponent(() => hazoNotesModule.HazoNotesIcon);
                }
            }
            catch (error) {
                console.warn('[CollabFormNotesIcon] Failed to load HazoNotesIcon from hazo_notes:', error);
            }
        };
        loadComponent();
    }, []);
    // Once component is loaded and open prop is true, trigger the popover to open
    // We use a delay to ensure:
    // 1. The component has fully rendered
    // 2. Any parent dropdown/menu close events have fully propagated
    // Without this delay, clicking "Notes" in a dropdown would cause the notes popover
    // to open and immediately close due to the dropdown's click event being interpreted
    // as a "click outside" by the Radix Popover
    React.useEffect(() => {
        if (HazoNotesIconComponent && (open || default_open)) {
            // Use 150ms delay to ensure dropdown close animations and events are complete
            const timer = setTimeout(() => {
                set_should_open(true);
            }, 150);
            return () => clearTimeout(timer);
        }
    }, [HazoNotesIconComponent, open, default_open]);
    // Handle open state change - propagate to parent and update internal state
    // NOTE: This hook must be called before any early returns to follow React rules of hooks
    const handle_open_change = React.useCallback((new_open) => {
        set_should_open(new_open);
        onOpenChange?.(new_open);
    }, [onOpenChange]);
    // Don't render if explicitly disabled or no field_data_id
    if (disabled || !field_data_id) {
        return null;
    }
    // Show nothing while loading
    if (!HazoNotesIconComponent) {
        return null;
    }
    // Build props conditionally based on controlled vs uncontrolled mode
    const notes_props = is_controlled
        ? {
            notes: notes,
            on_notes_change: on_notes_change,
            has_notes: has_notes ?? (notes?.length ?? 0) > 0,
        }
        : {
            // In uncontrolled mode, HazoNotesIcon uses its internal use_notes hook
            // to fetch notes from the API. has_notes will be auto-detected.
            has_notes: has_notes,
        };
    // When open or default_open is true, use controlled mode with should_open
    // This ensures the popover opens only after the component is fully loaded
    const wants_auto_open = open === true || default_open === true;
    const effective_open = wants_auto_open ? should_open : open;
    return (_jsx(HazoNotesIconComponent, { ref_id: field_data_id, label: label, ...notes_props, current_user: current_user ? {
            id: current_user.id || '',
            name: current_user.name,
            email: current_user.email,
            profile_image: current_user.profile_image,
        } : undefined, disabled: disabled, panel_style: panel_style, background_color: background_color, save_mode: save_mode, className: className, icon_size: icon_size, show_border: show_border, open: effective_open, onOpenChange: handle_open_change }));
}
/**
 * Render the visibility toggle icon button
 * Shows eye icon when visible, eye-off icon when hidden
 * Only renders for users with 'author' role
 */
export function CollabFormVisibilityIcon({ label, visibility = 'visible', on_visibility_change, disabled, user_role = 'responder', borderless = false, size = 'md', editable = true, }) {
    // Don't render if explicitly disabled or user is not an author
    if (disabled || user_role !== 'author') {
        return null;
    }
    const is_visible = visibility === 'visible';
    const is_editable = editable && !!on_visibility_change;
    const size_config = CONTROL_SIZE_CONFIG[size];
    const handle_click = () => {
        if (is_editable && on_visibility_change) {
            on_visibility_change(is_visible ? 'hidden' : 'visible');
        }
    };
    return (_jsx("button", { type: "button", onClick: handle_click, disabled: !is_editable, className: cn('cls_collab_visibility_icon flex items-center justify-center rounded-md bg-transparent text-muted-foreground transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring', size_config.button, !borderless && 'border border-input', is_editable ? 'hover:bg-muted cursor-pointer' : 'cursor-default opacity-60'), "aria-label": is_visible ? `Hide ${label}` : `Show ${label}`, title: is_visible ? 'Hidden from responders' : 'Visible to all', children: is_visible ? (_jsx(IoEye, { className: cn(size_config.icon, 'text-muted-foreground') })) : (_jsx(IoEyeOff, { className: cn(size_config.icon, 'text-muted-foreground') })) }));
}
/**
 * Render the add entry icon button
 * Shows "+" icon to duplicate a field entry
 */
export function CollabFormAddEntryIcon({ label, field_id, on_add_entry, disabled, borderless = false, }) {
    // Don't render if explicitly disabled or no callback
    if (disabled || !on_add_entry) {
        return null;
    }
    const handle_click = () => {
        on_add_entry(field_id);
    };
    return (_jsx("button", { type: "button", onClick: handle_click, className: cn('cls_collab_add_entry_icon flex h-9 w-9 items-center justify-center rounded-md bg-transparent text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring', !borderless && 'border border-input'), "aria-label": `Add another ${label}`, title: `Add another ${label}`, children: _jsx(IoAdd, { className: "h-5 w-5" }) }));
}
/**
 * Render the delete entry icon button
 * Shows trash icon to remove an additional entry
 * Only used for additional entries (not the original)
 */
export function CollabFormDeleteEntryIcon({ label, field_id, on_delete_entry, disabled, borderless = false, }) {
    // Don't render if explicitly disabled or no callback
    if (disabled || !on_delete_entry) {
        return null;
    }
    const handle_click = () => {
        on_delete_entry(field_id);
    };
    return (_jsx("button", { type: "button", onClick: handle_click, className: cn('cls_collab_delete_entry_icon flex h-9 w-9 items-center justify-center rounded-md bg-transparent text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring', !borderless && 'border border-input hover:border-destructive'), "aria-label": `Delete this ${label}`, title: `Delete this ${label}`, children: _jsx(IoTrash, { className: "h-5 w-5" }) }));
}
/**
 * Render the delete field icon button
 * Shows trash outline icon to soft-delete a field
 * Only renders for users with 'author' role
 */
export function CollabFormDeleteFieldIcon({ label, field_id, on_delete, disabled, user_role = 'responder', borderless = false, size = 'md', is_deleted = false, }) {
    // Don't render if explicitly disabled, no callback, or user is not an author
    if (disabled || !on_delete || user_role !== 'author') {
        return null;
    }
    const size_config = CONTROL_SIZE_CONFIG[size];
    const handle_click = () => {
        on_delete(field_id);
    };
    // Show undo option when deleted
    if (is_deleted) {
        return (_jsx("button", { type: "button", onClick: handle_click, className: cn('cls_collab_undo_btn flex items-center justify-center rounded-md hover:bg-muted transition-colors text-blue-600', size_config.button, !borderless && 'border border-input'), title: "Undo delete", children: _jsx("span", { className: "text-xs", children: "Undo" }) }));
    }
    return (_jsx("button", { type: "button", onClick: handle_click, className: cn('cls_collab_delete_field_icon flex items-center justify-center rounded-md bg-transparent text-muted-foreground transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring', size_config.button, !borderless && 'border border-input'), "aria-label": `Delete ${label}`, title: "Delete field", children: _jsx(IoTrashOutline, { className: cn(size_config.icon, 'text-muted-foreground hover:text-red-600') }) }));
}
/**
 * Render the lock icon button
 * Shows lock/unlock icon to toggle field read-only state
 * Only renders for users with 'author' role
 */
export function CollabFormLockIcon({ label, locked = false, on_lock_change, disabled, user_role = 'responder', borderless = false, size = 'md', editable = true, }) {
    // Don't render if explicitly disabled or user is not an author
    if (disabled || user_role !== 'author') {
        return null;
    }
    const is_editable = editable && !!on_lock_change;
    const size_config = CONTROL_SIZE_CONFIG[size];
    const handle_click = () => {
        if (is_editable && on_lock_change) {
            on_lock_change(!locked);
        }
    };
    return (_jsx("button", { type: "button", onClick: handle_click, disabled: !is_editable, className: cn('cls_collab_lock_icon flex items-center justify-center rounded-md bg-transparent text-muted-foreground transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring', size_config.button, !borderless && 'border border-input', is_editable ? 'hover:bg-muted cursor-pointer' : 'cursor-default opacity-60'), "aria-label": locked ? `Unlock ${label}` : `Lock ${label}`, title: locked ? 'Locked (read-only)' : 'Unlocked', children: locked ? (_jsx(IoLockClosed, { className: cn(size_config.icon, 'text-yellow-600') })) : (_jsx(IoLockOpen, { className: cn(size_config.icon, 'text-muted-foreground') })) }));
}
/**
 * Render the skip/not applicable icon button
 * Shows "N/A" text to mark a field as not applicable
 * When skipped, the icon has a filled background
 */
export function CollabFormSkipIcon({ label, skipped = false, on_skip_change, disabled, borderless = false, size = 'md', editable = true, }) {
    // Don't render if explicitly disabled
    if (disabled) {
        return null;
    }
    const is_editable = editable && !!on_skip_change;
    const size_config = CONTROL_SIZE_CONFIG[size];
    const handle_click = () => {
        if (is_editable && on_skip_change) {
            on_skip_change(!skipped);
        }
    };
    return (_jsx("button", { type: "button", onClick: handle_click, disabled: !is_editable, className: cn('cls_collab_skip_icon flex items-center justify-center rounded-md transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring', size_config.button, !borderless && 'border border-input', skipped
            ? 'bg-slate-200 text-slate-700'
            : 'bg-transparent text-muted-foreground', is_editable ? 'hover:bg-muted cursor-pointer' : 'cursor-default opacity-60'), "aria-label": skipped ? `Mark ${label} as applicable` : `Mark ${label} as not applicable`, title: skipped ? 'Not Applicable (N/A)' : 'Mark as N/A', children: _jsx(BiSkipNextCircle, { className: cn(size_config.icon, 'flex-shrink-0') }) }));
}
/**
 * Consolidated edit actions dropdown component
 * Shows ellipsis dropdown when multiple edit actions (lock, visibility, delete, chat, notes) are enabled
 * Shows single icon directly when only one action is enabled
 * Chat and notes can be included via include_chat_in_dropdown and include_notes_in_dropdown props
 * Active chat/notes can be extracted from dropdown via extract_active_chat and extract_active_notes props
 */
export function CollabFormEditActionsDropdown({ label, field_id, user_role = 'responder', enable_lock, disable_lock, locked = false, on_lock_change, enable_visibility_toggle, disable_visibility_toggle, visibility = 'visible', on_visibility_change, enable_delete, disable_delete, on_delete, edit_actions_display = 'auto', borderless = false, size = 'md', 
// Chat consolidation props - default to in dropdown with extraction when active
include_chat_in_dropdown = true, enable_chat, disable_chat, has_chat_messages = false, chat_status, on_chat_click, extract_active_chat = true, 
// Notes consolidation props - default to in dropdown with extraction when active
include_notes_in_dropdown = true, enable_notes, disable_notes, has_notes = false, notes = [], on_notes_change, current_user, field_data_id, extract_active_notes = true, 
// Notes styling props
notes_panel_style, notes_background_color, notes_save_mode, icons_behaviour, }) {
    // State for dynamically loaded dropdown components
    const [DropdownComponents, setDropdownComponents] = React.useState(null);
    // State for notes dialog (when notes is in dropdown)
    const [notes_dialog_open, set_notes_dialog_open] = React.useState(false);
    const [HazoNotesPanelComponent, setHazoNotesPanelComponent] = React.useState(null);
    const [DialogComponents, setDialogComponents] = React.useState(null);
    // Calculate which actions are actually enabled for author controls
    const show_lock = enable_lock && !disable_lock;
    const show_visibility = enable_visibility_toggle && !disable_visibility_toggle;
    const show_delete = enable_delete && !disable_delete;
    // Get chat status colors from context
    const chat_colors = use_chat_status_colors();
    // Resolve chat status
    const effective_chat_status = resolve_chat_status(chat_status, has_chat_messages);
    const chat_has_activity = effective_chat_status !== 'none';
    const chat_classes = get_chat_status_classes(effective_chat_status, borderless, chat_colors);
    // Compute per-icon borders using icons_behaviour (takes precedence over borderless prop)
    // When icons_behaviour is provided, use border_on/border_off arrays to control borders
    // When not provided, fall back to the borderless prop for all icons
    const get_icon_borderless = (control_name) => {
        if (icons_behaviour) {
            // Use should_show_border from role_utils - returns true when border should be shown
            // We need to return borderless (inverse of show_border)
            const has_value = control_name === 'control_chat' ? chat_has_activity :
                control_name === 'control_notes' ? has_notes :
                    control_name === 'control_visibility' ? visibility === 'hidden' :
                        control_name === 'control_lock' ? locked : false;
            return !should_show_border(control_name, icons_behaviour, has_value);
        }
        return borderless;
    };
    const notes_borderless = get_icon_borderless('control_notes');
    const chat_borderless = get_icon_borderless('control_chat');
    const visibility_borderless = get_icon_borderless('control_visibility');
    const lock_borderless = get_icon_borderless('control_lock');
    const delete_borderless = get_icon_borderless('control_delete');
    // Calculate chat/notes in dropdown
    const chat_should_be_in_dropdown = include_chat_in_dropdown && enable_chat && !disable_chat;
    const notes_should_be_in_dropdown = include_notes_in_dropdown && enable_notes && !disable_notes;
    // Extract logic - when active, show outside dropdown
    const chat_is_extracted = chat_should_be_in_dropdown && extract_active_chat && chat_has_activity;
    const notes_is_extracted = notes_should_be_in_dropdown && extract_active_notes && has_notes;
    // Final: what's actually in the dropdown
    const chat_in_dropdown = chat_should_be_in_dropdown && !chat_is_extracted;
    const notes_in_dropdown = notes_should_be_in_dropdown && !notes_is_extracted;
    // Count enabled actions that will be in the dropdown
    // For non-authors, only count chat/notes if included in dropdown
    const author_action_count = user_role === 'author' ? [show_lock, show_visibility, show_delete].filter(Boolean).length : 0;
    const dropdown_items_count = author_action_count + (chat_in_dropdown ? 1 : 0) + (notes_in_dropdown ? 1 : 0);
    // Load dropdown components dynamically - MUST be called before any early returns
    React.useEffect(() => {
        const needs_dropdown = edit_actions_display === 'dropdown' || (edit_actions_display === 'auto' && dropdown_items_count >= 2);
        if (needs_dropdown && !DropdownComponents) {
            const loadComponents = async () => {
                try {
                    const dropdownModule = await import('hazo_ui');
                    if (dropdownModule) {
                        setDropdownComponents({
                            DropdownMenu: dropdownModule.DropdownMenu,
                            DropdownMenuTrigger: dropdownModule.DropdownMenuTrigger,
                            DropdownMenuContent: dropdownModule.DropdownMenuContent,
                            DropdownMenuItem: dropdownModule.DropdownMenuItem,
                            DropdownMenuSeparator: dropdownModule.DropdownMenuSeparator,
                        });
                    }
                }
                catch {
                    // Fallback to inline icons if dropdown-menu not available
                    console.warn('hazo_collab_forms: dropdown-menu component not found, falling back to inline icons');
                }
            };
            loadComponents();
        }
    }, [dropdown_items_count, DropdownComponents, edit_actions_display]);
    // Load HazoNotesPanel for notes dialog - MUST be called before any early returns
    React.useEffect(() => {
        if (notes_in_dropdown && !HazoNotesPanelComponent) {
            const loadNotesComponent = async () => {
                try {
                    const hazoNotesModule = await import('hazo_notes');
                    if (hazoNotesModule?.HazoNotesPanel) {
                        setHazoNotesPanelComponent(() => hazoNotesModule.HazoNotesPanel);
                    }
                }
                catch {
                    console.warn('[CollabFormEditActionsDropdown] Failed to load HazoNotesPanel');
                }
            };
            loadNotesComponent();
        }
    }, [notes_in_dropdown, HazoNotesPanelComponent]);
    // Load Dialog components for notes dialog - MUST be called before any early returns
    React.useEffect(() => {
        if (notes_in_dropdown && !DialogComponents) {
            const loadDialogComponents = async () => {
                try {
                    const dialogModule = await import('hazo_ui');
                    if (dialogModule) {
                        setDialogComponents({
                            Dialog: dialogModule.HazoUiDialogRoot,
                            DialogContent: dialogModule.HazoUiDialogContent,
                            DialogHeader: dialogModule.HazoUiDialogHeader,
                            DialogTitle: dialogModule.HazoUiDialogTitle,
                        });
                    }
                }
                catch {
                    console.warn('[CollabFormEditActionsDropdown] Failed to load Dialog components');
                }
            };
            loadDialogComponents();
        }
    }, [notes_in_dropdown, DialogComponents]);
    // If no actions in dropdown, render nothing
    if (dropdown_items_count === 0) {
        return null;
    }
    // Helper to render inline icons (for fallback and 'separate' mode)
    // Uses shared icon components for consistent styling with summary view
    // Order matches summary: notes, chat, visibility, lock, delete
    const render_inline_icons = () => (_jsxs("div", { className: "cls_collab_edit_actions_inline flex items-center gap-1", children: [notes_in_dropdown && (_jsx(CollabFormNotesIcon, { label: label, has_notes: has_notes, notes: notes, on_notes_change: on_notes_change, current_user: current_user, field_data_id: field_data_id || field_id, show_border: !notes_borderless })), chat_in_dropdown && on_chat_click && (_jsx(CollabFormChatIcon, { label: label, on_click: on_chat_click, chat_status: effective_chat_status, borderless: chat_borderless, size: size })), show_visibility && user_role === 'author' && (_jsx(CollabFormVisibilityIcon, { label: label, visibility: visibility, on_visibility_change: on_visibility_change, user_role: user_role, borderless: visibility_borderless, size: size })), show_lock && user_role === 'author' && (_jsx(CollabFormLockIcon, { label: label, locked: locked, on_lock_change: on_lock_change, user_role: user_role, borderless: lock_borderless, size: size })), show_delete && user_role === 'author' && (_jsx(CollabFormDeleteFieldIcon, { label: label, field_id: field_id, on_delete: on_delete, user_role: user_role, borderless: delete_borderless, size: size }))] }));
    // 'separate' mode: always render individual icons inline
    if (edit_actions_display === 'separate') {
        return render_inline_icons();
    }
    // 'auto' mode with only one action: render single icon directly
    if (edit_actions_display === 'auto' && dropdown_items_count === 1) {
        if (chat_in_dropdown && on_chat_click) {
            return (_jsx(CollabFormChatIcon, { label: label, on_click: on_chat_click, chat_status: effective_chat_status, borderless: chat_borderless, size: size }));
        }
        if (notes_in_dropdown) {
            // For notes, we render the CollabFormNotesIcon directly if it's the only action
            return (_jsx(CollabFormNotesIcon, { label: label, has_notes: has_notes, notes: notes, on_notes_change: on_notes_change, current_user: current_user, field_data_id: field_data_id || field_id, show_border: !notes_borderless }));
        }
        if (show_lock && user_role === 'author') {
            return (_jsx(CollabFormLockIcon, { label: label, locked: locked, on_lock_change: on_lock_change, user_role: user_role, borderless: lock_borderless, size: size }));
        }
        if (show_visibility && user_role === 'author') {
            return (_jsx(CollabFormVisibilityIcon, { label: label, visibility: visibility, on_visibility_change: on_visibility_change, user_role: user_role, borderless: visibility_borderless, size: size }));
        }
        if (show_delete && user_role === 'author') {
            return (_jsx(CollabFormDeleteFieldIcon, { label: label, field_id: field_id, on_delete: on_delete, user_role: user_role, borderless: delete_borderless, size: size }));
        }
    }
    // 'dropdown' mode OR 'auto' mode with multiple actions: use dropdown
    // Fallback: render all icons inline if dropdown not available yet
    if (!DropdownComponents) {
        return render_inline_icons();
    }
    const { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } = DropdownComponents;
    // Determine if any action is in a non-default state (for visual indicator on trigger)
    const has_active_state = locked || visibility === 'hidden' || chat_has_activity || has_notes;
    // Determine trigger icon color based on chat status and notes
    const get_trigger_icon_color = () => {
        if (effective_chat_status === 'has_unread')
            return 'text-destructive'; // red for unread
        if (effective_chat_status === 'has_messages' || has_notes)
            return 'text-orange-500'; // orange for read messages or notes
        return '';
    };
    return (_jsxs(_Fragment, { children: [_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { type: "button", className: cn('cls_collab_edit_actions_trigger flex h-9 w-9 items-center justify-center rounded-md bg-transparent text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring', !borderless && 'border border-input', has_active_state && (borderless ? 'bg-slate-100' : 'bg-slate-100 border-slate-400'), get_trigger_icon_color()), "aria-label": `Actions for ${label}`, title: `Actions for ${label}`, children: _jsx(IoEllipsisVertical, { className: "h-5 w-5" }) }) }), _jsxs(DropdownMenuContent, { align: "end", children: [chat_in_dropdown && (_jsx(DropdownMenuItem, { onClick: on_chat_click, children: _jsxs("span", { className: "flex items-center gap-2", children: [_jsx(IoChatbox, { className: cn('h-4 w-4', chat_classes.icon_class) }), _jsx("span", { children: "Open chat" }), effective_chat_status === 'has_unread' && _jsx("span", { className: "text-xs text-destructive", children: "(unread)" }), effective_chat_status === 'has_messages' && _jsx("span", { className: "text-xs text-orange-500", children: "(messages)" })] }) })), notes_in_dropdown && (_jsx(DropdownMenuItem, { onClick: () => set_notes_dialog_open(true), children: _jsxs("span", { className: "flex items-center gap-2", children: [_jsx(IoDocumentText, { className: cn('h-4 w-4', has_notes && 'text-amber-600') }), _jsx("span", { children: "Notes" }), has_notes && notes.length > 0 && (_jsxs("span", { className: "text-xs text-amber-600", children: ["(", notes.length, ")"] }))] }) })), (chat_in_dropdown || notes_in_dropdown) && author_action_count > 0 && DropdownMenuSeparator && (_jsx(DropdownMenuSeparator, {})), show_lock && user_role === 'author' && (_jsx(DropdownMenuItem, { onClick: () => on_lock_change?.(!locked), children: _jsxs("span", { className: "flex items-center gap-2", children: [locked ? (_jsx(IoLockClosed, { className: "h-4 w-4 text-slate-600" })) : (_jsx(IoLockOpen, { className: "h-4 w-4" })), locked ? 'Unlock field' : 'Lock field'] }) })), show_visibility && user_role === 'author' && (_jsx(DropdownMenuItem, { onClick: () => on_visibility_change?.(visibility === 'visible' ? 'hidden' : 'visible'), children: _jsxs("span", { className: "flex items-center gap-2", children: [visibility === 'visible' ? (_jsx(IoEye, { className: "h-4 w-4" })) : (_jsx(IoEyeOff, { className: "h-4 w-4 text-amber-600" })), visibility === 'visible' ? 'Hide from responders' : 'Show to responders'] }) })), show_delete && user_role === 'author' && (_jsx(DropdownMenuItem, { onClick: () => on_delete?.(field_id), className: "text-destructive focus:text-destructive", children: _jsxs("span", { className: "flex items-center gap-2", children: [_jsx(IoTrashOutline, { className: "h-4 w-4" }), "Delete field"] }) }))] })] }), notes_dialog_open && (_jsx("div", { className: "cls_collab_notes_panel_container mt-2", children: _jsx(CollabFormNotesIcon, { label: label, has_notes: (notes?.length ?? 0) > 0, notes: notes, on_notes_change: on_notes_change, current_user: current_user, field_data_id: field_data_id || field_id, show_border: false, panel_style: notes_panel_style, background_color: notes_background_color, save_mode: notes_save_mode, open: true, onOpenChange: (open) => {
                        if (!open)
                            set_notes_dialog_open(false);
                    } }) }))] }));
}
/**
 * Render the edit field config icon button
 * Shows a pencil icon to edit field properties (label, type, etc.)
 * Used by control_edit_field in icons_behaviour
 */
export function CollabFormEditFieldConfigIcon({ field_id, label, on_click, disabled = false, className, }) {
    // Don't render if explicitly disabled or no callback
    if (!on_click) {
        return null;
    }
    return (_jsx("button", { type: "button", onClick: on_click, disabled: disabled, className: cn('cls_edit_field_config_icon inline-flex items-center justify-center h-7 w-7', 'bg-amber-50 text-amber-500 border border-amber-200', 'rounded transition-colors', disabled
            ? 'opacity-50 cursor-not-allowed'
            : 'hover:bg-amber-100 hover:border-amber-300 hover:text-amber-600 cursor-pointer', className), "aria-label": label ? `Edit ${label}` : `Edit field ${field_id}`, title: "Edit field", children: _jsx(IoPencil, { className: "h-4 w-4" }) }));
}
/**
 * Render the delete field structure icon button
 * Shows a trash icon to remove field from form structure (hard delete)
 * Used by control_delete_field in icons_behaviour
 */
export function CollabFormDeleteFieldStructureIcon({ field_id, label, on_click, disabled = false, className, }) {
    // Don't render if explicitly disabled or no callback
    if (!on_click) {
        return null;
    }
    return (_jsx("button", { type: "button", onClick: on_click, disabled: disabled, className: cn('cls_delete_field_structure_icon inline-flex items-center justify-center h-7 w-7', 'bg-red-50 text-red-400 border border-red-200', 'rounded transition-colors', disabled
            ? 'opacity-50 cursor-not-allowed'
            : 'hover:bg-red-100 hover:border-red-300 hover:text-red-600 cursor-pointer', className), "aria-label": label ? `Remove ${label}` : `Remove field ${field_id}`, title: "Remove field from form", children: _jsx(IoTrash, { className: "h-4 w-4" }) }));
}
/**
 * Render the add field icon button
 * Shows a "+" icon below a field to add a new field after it
 * This is used by control_add_elements in icons_behaviour
 */
export function CollabFormAddFieldIcon({ field_id, on_click, disabled = false, className, variant = 'field', }) {
    // Don't render if explicitly disabled or no callback
    if (!on_click) {
        return null;
    }
    return (_jsx("button", { type: "button", onClick: on_click, disabled: disabled, className: cn('cls_add_field_icon group/add flex items-center justify-center w-full py-0.5 my-1', 
        // Span all columns when inside a grid layout (e.g., group wrapper)
        'col-span-full', 'opacity-0 hover:opacity-100 focus:opacity-100 transition-opacity duration-200', disabled
            ? 'opacity-50 cursor-not-allowed'
            : 'cursor-pointer', className), "aria-label": variant === 'group' ? `Add group after ${field_id}` : `Add field after ${field_id}`, title: variant === 'group' ? 'Add new group' : 'Add new field', children: _jsxs("div", { className: "flex items-center gap-2 w-full", children: [_jsx("div", { className: "flex-1 h-px bg-border" }), _jsx("span", { className: cn('inline-flex items-center justify-center h-5 w-5 rounded-full border transition-colors', variant === 'group'
                        ? 'border-emerald-300 text-emerald-400 group-hover/add:bg-emerald-50'
                        : 'border-blue-300 text-blue-400 group-hover/add:bg-blue-50'), children: _jsx(IoAdd, { className: "h-3 w-3" }) }), _jsx("div", { className: "flex-1 h-px bg-border" })] }) }));
}
//# sourceMappingURL=hazo_collab_form_base.js.map