import 'package:flutter/material.dart'; import 'package:forui/forui.dart'; const _kRowLabelStyle = TextStyle(color: Colors.white70, fontSize: 13); const _kRowValueStyle = TextStyle( color: Colors.white, fontSize: 13, fontWeight: FontWeight.w500, ); const _kPanelSliderTheme = SliderThemeData( trackHeight: 3, thumbShape: RoundSliderThumbShape(enabledThumbRadius: 7), overlayShape: RoundSliderOverlayShape(overlayRadius: 14), activeTrackColor: Colors.white, inactiveTrackColor: Colors.white24, thumbColor: Colors.white, overlayColor: Colors.white10, ); class PanelGroupHeader extends StatelessWidget { final String title; const PanelGroupHeader({super.key, required this.title}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.only(bottom: 4, left: 2), child: Text( title, style: const TextStyle( color: Colors.white54, fontSize: 12, fontWeight: FontWeight.w600, ), ), ); } } class PanelSliderRow extends StatelessWidget { final String label; final double value; final double min; final double max; final double step; final String display; final ValueChanged onChanged; const PanelSliderRow({ super.key, required this.label, required this.value, required this.min, required this.max, required this.step, required this.display, required this.onChanged, }); @override Widget build(BuildContext context) { final divisions = ((max - min) / step).round(); return Padding( padding: const EdgeInsets.symmetric(vertical: 2), child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( children: [ Expanded(child: Text(label, style: _kRowLabelStyle)), Text(display, style: _kRowValueStyle), ], ), SizedBox( height: 28, child: SliderTheme( data: _kPanelSliderTheme, child: Slider( value: value.clamp(min, max), min: min, max: max, divisions: divisions, padding: EdgeInsets.zero, onChanged: onChanged, ), ), ), ], ), ); } } class PanelToggleRow extends StatelessWidget { final String label; final bool value; final ValueChanged onChanged; const PanelToggleRow({ super.key, required this.label, required this.value, required this.onChanged, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 6), child: Row( children: [ Expanded(child: Text(label, style: _kRowLabelStyle)), FSwitch( value: value, onChange: onChanged, style: FSwitchStyleDelta.delta( trackColor: FVariantsValueDelta.delta([ FVariantValueDeltaOperation.all(Colors.white12), FVariantValueDeltaOperation.exact({ FSwitchVariantConstraint.selected, }, Colors.white38), ]), thumbColor: FVariantsValueDelta.delta([ FVariantValueDeltaOperation.all(Colors.white38), FVariantValueDeltaOperation.exact({ FSwitchVariantConstraint.selected, }, Colors.white), ]), ), ), ], ), ); } } class PanelStepperRow extends StatelessWidget { final String label; final String display; final VoidCallback? onDecrement; final VoidCallback? onIncrement; const PanelStepperRow({ super.key, required this.label, required this.display, this.onDecrement, this.onIncrement, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 6), child: Row( children: [ Expanded(child: Text(label, style: _kRowLabelStyle)), _StepButton(icon: Icons.remove, onPressed: onDecrement), Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: SizedBox( width: 46, child: Text( display, style: _kRowValueStyle, textAlign: TextAlign.center, ), ), ), _StepButton(icon: Icons.add, onPressed: onIncrement), ], ), ); } } class _StepButton extends StatelessWidget { final IconData icon; final VoidCallback? onPressed; const _StepButton({required this.icon, required this.onPressed}); @override Widget build(BuildContext context) { return SizedBox.square( dimension: 28, child: FButton.icon( variant: FButtonVariant.ghost, size: FButtonSizeVariant.xs, onPress: onPressed, child: Icon( icon, size: 14, color: onPressed != null ? Colors.white70 : Colors.white24, ), ), ); } }