import { component, type Define } from '@sigx/lynx'; import { Pressable } from '@sigx/lynx-gestures'; import { PRESSED_SCALE, PRESSED_OPACITY, type ColorVariant, type SizeScale, type WithAccessibility } from '@sigx/lynx-zero'; export type ToggleColor = Exclude; export type ToggleSize = Extract; export type ToggleProps = & Define.Prop<'checked', boolean, false> & Define.Prop<'color', ToggleColor, false> & Define.Prop<'size', ToggleSize, false> & Define.Prop<'disabled', boolean, false> & Define.Prop<'class', string, false> & WithAccessibility // Two-way binding (the sigx way): `model={() => state.on}`. When a model is // bound it drives the on/off state and the press writes back to it; the // static `checked` prop + `change` event still work when no model is bound. & Define.Model & Define.Event<'change', boolean>; // Track-width minus thumb-width minus padding, per size — how far the thumb // travels when checked (kept in sync with the dimensions in toggle.css). const thumbOffsetMap: Record = { sm: 16, md: 20, lg: 24, }; const sizeClasses: Record = { sm: 'hero-toggle-sm', md: '', lg: 'hero-toggle-lg', }; export const Toggle = component(({ props, emit }) => { const isChecked = () => (props.model ? !!props.model.value : !!props.checked); const getClasses = () => { const c = ['hero-toggle']; if (props.size) { const s = sizeClasses[props.size]; if (s) c.push(s); } if (props.color) c.push(`hero-toggle-${props.color}`); if (isChecked()) c.push('hero-toggle-checked'); if (props.disabled) c.push('hero-toggle-disabled'); if (props.class) c.push(props.class); return c.join(' '); }; return () => { const checked = isChecked(); const offset = checked ? thumbOffsetMap[props.size ?? 'md'] : 0; return ( { if (props.disabled) return; const next = !checked; if (props.model) props.model.value = next; emit('change', next); }} > ); }; });