import React, { useEffect, useRef } from 'react'; import { hostProps } from '../utils/host-props'; import { useBooleanProperty } from '../utils/use-boolean-prop'; type BuiltinFlavor = 'primary' | 'success' | 'danger' | 'warning' | 'neutral'; type ShadedFlavor = BuiltinFlavor | `${BuiltinFlavor}+` | `${BuiltinFlavor}-`; export interface TySwitchProps extends Omit, 'onChange' | 'onInput'> { /** Checked (on) state */ checked?: boolean; /** Form field value when checked */ value?: string; /** Form field name */ name?: string; /** Disable the switch */ disabled?: boolean; /** Required field */ required?: boolean; /** Switch size */ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'; /** Semantic styling variant */ flavor?: ShadedFlavor | (string & {}); /** * Fires when switch state changes (React convention) * Maps to native 'input' event from ty-switch */ onChange?: (event: CustomEvent) => void; /** * Fires on blur if value changed (native DOM behavior) * Maps to native 'change' event from ty-switch */ onChangeCommit?: (event: CustomEvent) => void; } export interface TySwitchEventDetail { value: boolean; checked: boolean; formValue: string | null; originalEvent: Event; } export const TySwitch = React.forwardRef( ({ checked, value, name, disabled, required, size, flavor, onChange, onChangeCommit, ...props }, ref) => { const elementRef = useRef(null); useEffect(() => { const element = elementRef.current; if (!element) return; const handleInput = (event: Event) => { if (onChange) onChange(event as CustomEvent); }; const handleChangeCommit = (event: Event) => { if (onChangeCommit) onChangeCommit(event as CustomEvent); }; element.addEventListener('input', handleInput); element.addEventListener('change', handleChangeCommit); return () => { element.removeEventListener('input', handleInput); element.removeEventListener('change', handleChangeCommit); }; }, [onChange, onChangeCommit]); useEffect(() => { if (ref && elementRef.current) { if (typeof ref === 'function') { ref(elementRef.current); } else { ref.current = elementRef.current; } } }, [ref]); // Imperative property sync for boolean props (see use-boolean-prop.ts). const isChecked = useBooleanProperty(elementRef, 'checked', checked); const isDisabled = useBooleanProperty(elementRef, 'disabled', disabled); const isRequired = useBooleanProperty(elementRef, 'required', required); const webComponentProps: Record = { ...hostProps(props), ref: elementRef, }; if (isChecked) webComponentProps.checked = ''; if (isDisabled) webComponentProps.disabled = ''; if (isRequired) webComponentProps.required = ''; if (value) webComponentProps.value = value; if (name) webComponentProps.name = name; if (size) webComponentProps.size = size; if (flavor) webComponentProps.flavor = flavor; return React.createElement('ty-switch', webComponentProps); } ); TySwitch.displayName = 'TySwitch';