/** * Dynamic List Field Component * * A reusable component for managing a dynamic list of items */ import { useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import Select from 'react-select'; import { DynamicListFieldProps, ListItem } from '../types'; const DynamicListField = ({ items = [], onChange, getString, }: DynamicListFieldProps) => { const [selectedItem, setSelectedItem] = useState(''); const [subtitle, setSubtitle] = useState(''); // Custom styles for react-select const selectStyles = { control: (provided: any, state: any) => ({ ...provided, minHeight: '48px', border: state.isFocused ? '1px solid #3b82f6' : '1px solid #d1d5db', borderRadius: '6px', boxShadow: state.isFocused ? '0 0 0 1px #3b82f6' : 'none', '&:hover': { border: '1px solid #3b82f6', }, }), valueContainer: (provided: any) => ({ ...provided, padding: '0 12px', }), input: (provided: any) => ({ ...provided, margin: '0', }), indicatorSeparator: () => ({ display: 'none', }), indicatorsContainer: (provided: any) => ({ ...provided, paddingRight: '12px', }), dropdownIndicator: (provided: any) => ({ ...provided, color: '#6b7280', '&:hover': { color: '#374151', }, }), option: (provided: any, state: any) => ({ ...provided, backgroundColor: state.isSelected ? '#3b82f6' : state.isFocused ? '#f3f4f6' : 'white', color: state.isSelected ? 'white' : '#374151', padding: '12px 16px', '&:hover': { backgroundColor: state.isSelected ? '#3b82f6' : '#f3f4f6', }, }), menu: (provided: any) => ({ ...provided, borderRadius: '6px', border: '1px solid #e5e7eb', boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)', }), }; // Predefined options with non-translatable types and translatable labels const predefinedOptions = [ { type: 'excerpt_tldr', label: getString('dynamic_list', 'excerpt_tldr', 'Excerpt / TL;DR'), }, { type: 'paragraph', label: getString('dynamic_list', 'paragraph', 'Subtopic'), }, { type: 'key_takeaways', label: getString('dynamic_list', 'key_takeaways', 'Key Takeaways'), }, { type: 'faq', label: getString('dynamic_list', 'faq', 'FAQ'), }, { type: 'conclusion_summary', label: getString( 'dynamic_list', 'conclusion_summary', 'Conclusion / summary' ), }, ]; const handleAddItem = (): void => { if (selectedItem) { // Convert string items to ListItem objects for backward compatibility const currentItems = items.map(item => typeof item === 'string' ? { type: item, subtitle: '' } : item ); const newItem: ListItem = { type: selectedItem, // Non-translatable type (e.g., "excerpt_tldr") subtitle: selectedItem === 'paragraph' ? subtitle : undefined, }; onChange([...currentItems, newItem]); setSelectedItem(''); setSubtitle(''); } }; const handleRemoveItem = (index: number): void => { const newItems = items.filter((_, i) => i !== index); onChange(newItems); }; const handleSubtitleChange = (index: number, newSubtitle: string): void => { const currentItems = items.map(item => typeof item === 'string' ? { type: item, subtitle: '' } : item ); const updatedItems = currentItems.map((item, i) => i === index ? { ...item, subtitle: newSubtitle } : item ); onChange(updatedItems); }; // All options are always available (users can select the same item multiple times) const availableOptions = predefinedOptions; return (
{/* Dropdown for selecting new items */}
setSubtitle(e.target.value)} className="cpepai-form-input w-full text-sm sm:text-base" placeholder={getString( 'dynamic_list', 'subtitle_placeholder', 'Enter subtitle for this paragraph section...' )} />
)} {/* List of items */}
{items.map((item, index) => { // Handle backward compatibility: convert string items to objects const itemType = typeof item === 'string' ? item : item.type; const itemSubtitle = typeof item === 'string' ? '' : item.subtitle || ''; // Find the predefined option to get the current label const predefinedOption = predefinedOptions.find( option => option.type === itemType ); const displayLabel = predefinedOption ? predefinedOption.label : itemType; return (
{displayLabel}
{/* Subtitle field for Subtopics */} {itemType === 'paragraph' && ( handleSubtitleChange( index, e.target.value ) } className="cpepai-form-input w-full text-xs sm:text-sm" placeholder={getString( 'dynamic_list', 'subtitle_placeholder', 'Enter subtitle for this paragraph section...' )} /> )}
); })}
{/* Empty state */} {items.length === 0 && (
{getString( 'dynamic_list', 'no_items', 'No items added yet. Choose from the dropdown above to build your structure.' )}
)}
); }; export default DynamicListField;