ModalOverlay constructor

ModalOverlay({
  1. required String title,
  2. required int width,
  3. required int height,
  4. required Rect dialogBounds,
  5. required Widget child,
  6. required List<FocusNode> modalFocusNodes,
  7. void onDismiss()?,
  8. Style scrimStyle = const Style(modifiers: Modifier.dim),
  9. FocusScopeNode? focusNode,
  10. Style borderStyle = Style.empty,
  11. Style titleStyle = Style.empty,
  12. Style backgroundStyle = Style.empty,
  13. bool onKeyEvent(
    1. KeyEvent event
    )?,
})

Creates a ModalOverlay widget that traps focus within its bounds.

Implementation

factory ModalOverlay({
  required String title,
  required int width,
  required int height,
  required Rect dialogBounds,
  required Widget child,
  required List<FocusNode> modalFocusNodes,
  void Function()? onDismiss,
  Style scrimStyle = const Style(modifiers: Modifier.dim),
  FocusScopeNode? focusNode,
  Style borderStyle = Style.empty,
  Style titleStyle = Style.empty,
  Style backgroundStyle = Style.empty,
  bool Function(KeyEvent event)? onKeyEvent,
}) {
  final resolvedFocusNode = focusNode ?? FocusScopeNode(id: title);

  bool localHandleKeyEvent(KeyEvent event) {
    if (modalFocusNodes.isEmpty) {
      return onKeyEvent?.call(event) ?? false;
    }

    final isNext =
        event.logicalKey == TermKey.tab ||
        event.type == KeyType.right ||
        event.type == KeyType.down;

    final isPrev =
        event.logicalKey == TermKey.shiftTab ||
        event.type == KeyType.left ||
        event.type == KeyType.up;

    if (isNext) {
      int currentIndex = -1;
      for (var i = 0; i < modalFocusNodes.length; i++) {
        if (modalFocusNodes[i].isFocused) {
          currentIndex = i;
          break;
        }
      }
      final nextIndex = (currentIndex + 1) % modalFocusNodes.length;
      modalFocusNodes[nextIndex].requestFocus();
      return true;
    } else if (isPrev) {
      int currentIndex = -1;
      for (var i = 0; i < modalFocusNodes.length; i++) {
        if (modalFocusNodes[i].isFocused) {
          currentIndex = i;
          break;
        }
      }
      final prevIndex =
          (currentIndex - 1 + modalFocusNodes.length) %
          modalFocusNodes.length;
      modalFocusNodes[prevIndex].requestFocus();
      return true;
    } else {
      return onKeyEvent?.call(event) ?? false;
    }
  }

  return ModalOverlay._(
    title: title,
    width: width,
    height: height,
    dialogBounds: dialogBounds,
    child: FocusScope(
      focusNode: resolvedFocusNode,
      onKeyEvent: localHandleKeyEvent,
      child: child,
    ),
    modalFocusNodes: modalFocusNodes,
    onDismiss: onDismiss,
    scrimStyle: scrimStyle,
    focusNode: resolvedFocusNode,
    borderStyle: borderStyle,
    titleStyle: titleStyle,
    backgroundStyle: backgroundStyle,
    onKeyEvent: onKeyEvent,
  );
}