| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 | 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<T extends ActionItemData> {  List<T> get items;  String get identifier => toString();  double get maxWidth => 162;  double get itemHeight => ActionListSizes.itemHeight;  ListOverlayFooter? get footer;  void Function(dartz.Option<T>) get selectCallback;  FlowyOverlayDelegate? get delegate;  void show(    BuildContext buildContext,    BuildContext anchorContext, {    AnchorDirection anchorDirection = AnchorDirection.bottomRight,    Offset? anchorOffset,  }) {    final widgets = items        .map(          (action) => ActionItem<T>(            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<T extends ActionItemData> 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<AppTheme>();    return FlowyHover(      config: HoverDisplayConfig(hoverColor: theme.hover),      builder: (context, onHover) {        return GestureDetector(          behavior: HitTestBehavior.opaque,          onTap: () => onSelected(action),          child: SizedBox(            height: itemHeight,            child: Row(              crossAxisAlignment: CrossAxisAlignment.center,              children: [                if (action.icon != null) action.icon!,                HSpace(ActionListSizes.itemHPadding),                FlowyText.medium(                  action.name,                  fontSize: 12,                ),              ],            ),          ).padding(            horizontal: ActionListSizes.padding,            vertical: ActionListSizes.padding,          ),        );      },    );  }}
 |