import React, { useEffect, useRef, forwardRef, useImperativeHandle } from 'react' import SlimSelectCore from '../index' import type { Config, Option, Optgroup } from '../index' export interface SlimSelectProps { data?: (Partial)[] settings?: Config['settings'] events?: Config['events'] cssClasses?: Config['cssClasses'] value?: string | string[] onChange?: (value: string | string[]) => void children?: React.ReactNode multiple?: boolean } export interface SlimSelectRef { slimSelect: SlimSelectCore | null } const SlimSelect = forwardRef( ({ data, settings, events, cssClasses, value, onChange, children, multiple }, ref) => { const selectRef = useRef(null) const slimSelectRef = useRef(null) const isInitialMount = useRef(true) const currentValueRef = useRef(value) // Expose SlimSelect instance to parent via ref useImperativeHandle(ref, () => ({ slimSelect: slimSelectRef.current })) // Helper to get clean value (similar to Vue's getCleanValue) const getCleanValue = (val: string | string[] | undefined): string | string[] => { // If its multiple and the value is a string, return an array with the string if (typeof val === 'string') { return multiple ? [val] : val } // If its not multiple and the value is an array, return the first item if (Array.isArray(val)) { return multiple ? val : val[0] } return multiple ? [] : '' } // Helper to sync value to SlimSelect (similar to Vue's syncModelValueToSlimSelect) const syncValueToSlimSelect = (val: string | string[] | undefined, runAfterChange: boolean = false) => { if (!slimSelectRef.current) return // Only sync if value is explicitly set (not undefined) // This prevents adding placeholders when value is not provided if (val === undefined) { return } const cleanValue = getCleanValue(val) const data = slimSelectRef.current.getData() // Extract options from data (flatten optgroups if any) const options = data.flatMap((item: Option | Optgroup) => ('label' in item ? item.options : [item])) as Option[] // Check if the value exists in options const valueExists = Array.isArray(cleanValue) ? cleanValue.length > 0 && cleanValue.every((val) => options.some((opt) => opt.value === val)) : cleanValue !== '' && options.some((opt) => opt.value === cleanValue) // If value doesn't exist in options, add a placeholder option if (!valueExists) { // If its not multiple, add a placeholder option if (!Array.isArray(cleanValue)) { // For single select, check if placeholder already exists const hasPlaceholder = options.some((opt) => opt.placeholder) if (!hasPlaceholder) { // Get current data and prepend placeholder option const currentData = slimSelectRef.current.getData() const placeholderOption: Partial