import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:dartz/dartz.dart' as dartz; abstract class ActionList { List get items; String get identifier => toString(); double get maxWidth => 162; double get itemHeight => ActionListSizes.itemHeight; ListOverlayFooter? get footer; void Function(dartz.Option) get selectCallback; FlowyOverlayDelegate? get delegate; void show( BuildContext buildContext, BuildContext anchorContext, { AnchorDirection anchorDirection = AnchorDirection.bottomRight, Offset? anchorOffset, }) { final widgets = items .map( (action) => ActionItem( action: action, itemHeight: itemHeight, onSelected: (action) { FlowyOverlay.of(buildContext).remove(identifier); selectCallback(dartz.some(action)); }, ), ) .toList(); ListOverlay.showWithAnchor( buildContext, identifier: identifier, itemCount: widgets.length, itemBuilder: (context, index) => widgets[index], anchorContext: anchorContext, anchorDirection: anchorDirection, width: maxWidth, height: widgets.length * (itemHeight + ActionListSizes.padding * 2), delegate: delegate, anchorOffset: anchorOffset, footer: footer, ); } } abstract class ActionItemData { Widget? get icon; String get name; } class ActionListSizes { static double itemHPadding = 10; static double itemHeight = 16; static double padding = 6; } class ActionItem extends StatelessWidget { final T action; final Function(T) onSelected; final double itemHeight; const ActionItem({ Key? key, required this.action, required this.onSelected, required this.itemHeight, }) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); return FlowyHover( config: HoverDisplayConfig(hoverColor: theme.hover), builder: (context, onHover) { return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => onSelected(action), child: SizedBox( height: itemHeight, child: Row( children: [ if (action.icon != null) action.icon!, HSpace(ActionListSizes.itemHPadding), FlowyText.medium( action.name, fontSize: 12, ), ], ), ).padding( horizontal: ActionListSizes.padding, vertical: ActionListSizes.padding, ), ); }, ); } }