Repository: StacDev/stac
Pull request #241: feat: add support for inkwell widget
Author: login: AbhijithKonnayil
Created: 2025-05-08T21:48:53Z | Merged: 2025-05-11T05:28:30Z

## Description

Add support for Inkwell

## Related Issues https://github.com/StacDev/stac/issues/238


## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x] New feature (non-breaking change which adds functionality)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] Code refactor
- [ ] Build configuration change
- [x] Documentation
- [ ] Chore



Diff:
diff --git a/examples/stac_gallery/assets/json/home_screen.json b/examples/stac_gallery/assets/json/home_screen.json
index e91c50af3..7170a9780 100644
--- a/examples/stac_gallery/assets/json/home_screen.json
+++ b/examples/stac_gallery/assets/json/home_screen.json
@@ -375,6 +375,29 @@
       }
     }
   },
+  {
+    "type": "listTile",
+    "leading": {
+      "type": "icon",
+      "iconType": "cupertino",
+      "icon": "hand_draw"
+    },
+    "title": {
+      "type": "text",
+      "data": "Stac InkWell"
+    },
+    "subtitle": {
+      "type": "text",
+      "data": "Creates an Inkwell effect when tapped"
+    },
+    "onTap": {
+      "actionType": "navigate",
+      "widgetJson": {
+        "type": "exampleScreen",
+        "assetPath": "assets/json/inkwell_example.json"
+      }
+    }
+  },
   {
     "type": "listTile",
     "leading": {
diff --git a/examples/stac_gallery/assets/json/inkwell_example.json b/examples/stac_gallery/assets/json/inkwell_example.json
new file mode 100644
index 000000000..5192b532b
--- /dev/null
+++ b/examples/stac_gallery/assets/json/inkwell_example.json
@@ -0,0 +1,57 @@
+{
+    "type": "scaffold",
+    "appBar": {
+        "type": "appBar",
+        "title": {
+            "type": "text",
+            "data": "InkWell"
+        }
+    },
+    "body": {
+        "type": "listView",
+        "shrinkWrap": true,
+        "children": [
+            {
+                "type": "center",
+                "child": {
+                    "type": "inkWell",
+                    "child": {
+                        "type": "padding",
+                        "padding": {
+                            "top": 20,
+                            "bottom": 20,
+                            "right": 20,
+                            "left": 20
+                        },
+                        "child": {
+                            "type": "text",
+                            "data": "Hello, World! from Inkwell",
+                            "textAlign": "center"
+                        }
+                    },
+                    "splashColor": "#E1BEE7",
+                    "borderRadius": {
+                        "topLeft": 20,
+                        "topRight": 20,
+                        "bottomLeft": 20,
+                        "bottomRight": 20
+                    },
+                    "radius": 20,
+                    "hoverDuration": {
+                        "seconds": 10
+                    },
+                    "onTap": {
+                        "actionType": "showDialog",
+                        "widget": {
+                            "type": "alertDialog",
+                            "title": {
+                                "type": "text",
+                                "data": "On Tap Successful"
+                            }
+                        }
+                    }
+                }
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/packages/stac/lib/src/framework/stac.dart b/packages/stac/lib/src/framework/stac.dart
index f35159f3b..029ab39f8 100644
--- a/packages/stac/lib/src/framework/stac.dart
+++ b/packages/stac/lib/src/framework/stac.dart
@@ -7,6 +7,7 @@ import 'package:flutter/services.dart';
 import 'package:stac/src/framework/stac_registry.dart';
 import 'package:stac/src/parsers/actions/stac_network_request/stac_network_request_parser.dart';
 import 'package:stac/src/parsers/parsers.dart';
+import 'package:stac/src/parsers/widgets/stac_inkwell/stac_inkwell_parser.dart';
 import 'package:stac/src/services/stac_network_service.dart';
 import 'package:stac/src/utils/log.dart';
 import 'package:stac_framework/stac_framework.dart';
@@ -100,6 +101,7 @@ class Stac {
     const StacClipRRectParser(),
     const StacClipOvalParser(),
     const StacGestureDetectorParser(),
+    const StacInkwellParser(),
   ];
 
   static final _actionParsers = <StacActionParser>[
diff --git a/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell.dart b/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell.dart
new file mode 100644
index 000000000..8be952727
--- /dev/null
+++ b/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell.dart
@@ -0,0 +1,46 @@
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'package:stac/src/parsers/widgets/stac_mouse_cursor/stac_mouse_cursor.dart';
+import 'package:stac/stac.dart';
+
+part 'stac_inkwell.freezed.dart';
+part 'stac_inkwell.g.dart';
+
+@freezed
+abstract class StacInkWell with _$StacInkWell {
+  const factory StacInkWell({
+    Map<String, dynamic>? child,
+    Map<String, dynamic>? onTap,
+    Map<String, dynamic>? onDoubleTap,
+    Map<String, dynamic>? onLongPress,
+    Map<String, dynamic>? onTapDown,
+    Map<String, dynamic>? onTapUp,
+    Map<String, dynamic>? onTapCancel,
+    Map<String, dynamic>? onSecondaryTap,
+    Map<String, dynamic>? onSecondaryTapUp,
+    Map<String, dynamic>? onSecondaryTapDown,
+    Map<String, dynamic>? onSecondaryTapCancel,
+    Map<String, dynamic>? onHighlightChanged,
+    Map<String, dynamic>? onHover,
+    StacMouseCursor? mouseCursor,
+    String? focusColor,
+    String? hoverColor,
+    String? highlightColor,
+    String? overlayColor,
+    String? splashColor,
+    Map<String, dynamic>? splashFactory,
+    double? radius,
+    StacBorderRadius? borderRadius,
+    StacBorder? customBorder,
+    @Default(true) bool enableFeedback,
+    @Default(false) bool excludeFromSemantics,
+    Map<String, dynamic>? focusNode,
+    @Default(true) bool canRequestFocus,
+    Map<String, dynamic>? onFocusChange,
+    @Default(false) bool autofocus,
+    Map<String, dynamic>? statesController,
+    StacDuration? hoverDuration,
+  }) = _StacInkWell;
+
+  factory StacInkWell.fromJson(Map<String, dynamic> json) =>
+      _$StacInkWellFromJson(json);
+}
diff --git a/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell.freezed.dart b/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell.freezed.dart
new file mode 100644
index 000000000..82c4631b7
--- /dev/null
+++ b/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell.freezed.dart
@@ -0,0 +1,1071 @@
+// dart format width=80
+// coverage:ignore-file
+// GENERATED CODE - DO NOT MODIFY BY HAND
+// ignore_for_file: type=lint
+// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
+
+part of 'stac_inkwell.dart';
+
+// **************************************************************************
+// FreezedGenerator
+// **************************************************************************
+
+// dart format off
+T _$identity<T>(T value) => value;
+
+/// @nodoc
+mixin _$StacInkWell {
+  Map<String, dynamic>? get child;
+  Map<String, dynamic>? get onTap;
+  Map<String, dynamic>? get onDoubleTap;
+  Map<String, dynamic>? get onLongPress;
+  Map<String, dynamic>? get onTapDown;
+  Map<String, dynamic>? get onTapUp;
+  Map<String, dynamic>? get onTapCancel;
+  Map<String, dynamic>? get onSecondaryTap;
+  Map<String, dynamic>? get onSecondaryTapUp;
+  Map<String, dynamic>? get onSecondaryTapDown;
+  Map<String, dynamic>? get onSecondaryTapCancel;
+  Map<String, dynamic>? get onHighlightChanged;
+  Map<String, dynamic>? get onHover;
+  StacMouseCursor? get mouseCursor;
+  String? get focusColor;
+  String? get hoverColor;
+  String? get highlightColor;
+  String? get overlayColor;
+  String? get splashColor;
+  Map<String, dynamic>? get splashFactory;
+  double? get radius;
+  StacBorderRadius? get borderRadius;
+  StacBorder? get customBorder;
+  bool get enableFeedback;
+  bool get excludeFromSemantics;
+  Map<String, dynamic>? get focusNode;
+  bool get canRequestFocus;
+  Map<String, dynamic>? get onFocusChange;
+  bool get autofocus;
+  Map<String, dynamic>? get statesController;
+  StacDuration? get hoverDuration;
+
+  /// Create a copy of StacInkWell
+  /// with the given fields replaced by the non-null parameter values.
+  @JsonKey(includeFromJson: false, includeToJson: false)
+  @pragma('vm:prefer-inline')
+  $StacInkWellCopyWith<StacInkWell> get copyWith =>
+      _$StacInkWellCopyWithImpl<StacInkWell>(this as StacInkWell, _$identity);
+
+  /// Serializes this StacInkWell to a JSON map.
+  Map<String, dynamic> toJson();
+
+  @override
+  bool operator ==(Object other) {
+    return identical(this, other) ||
+        (other.runtimeType == runtimeType &&
+            other is StacInkWell &&
+            const DeepCollectionEquality().equals(other.child, child) &&
+            const DeepCollectionEquality().equals(other.onTap, onTap) &&
+            const DeepCollectionEquality()
+                .equals(other.onDoubleTap, onDoubleTap) &&
+            const DeepCollectionEquality()
+                .equals(other.onLongPress, onLongPress) &&
+            const DeepCollectionEquality().equals(other.onTapDown, onTapDown) &&
+            const DeepCollectionEquality().equals(other.onTapUp, onTapUp) &&
+            const DeepCollectionEquality()
+                .equals(other.onTapCancel, onTapCancel) &&
+            const DeepCollectionEquality()
+                .equals(other.onSecondaryTap, onSecondaryTap) &&
+            const DeepCollectionEquality()
+                .equals(other.onSecondaryTapUp, onSecondaryTapUp) &&
+            const DeepCollectionEquality()
+                .equals(other.onSecondaryTapDown, onSecondaryTapDown) &&
+            const DeepCollectionEquality()
+                .equals(other.onSecondaryTapCancel, onSecondaryTapCancel) &&
+            const DeepCollectionEquality()
+                .equals(other.onHighlightChanged, onHighlightChanged) &&
+            const DeepCollectionEquality().equals(other.onHover, onHover) &&
+            (identical(other.mouseCursor, mouseCursor) ||
+                other.mouseCursor == mouseCursor) &&
+            (identical(other.focusColor, focusColor) ||
+                other.focusColor == focusColor) &&
+            (identical(other.hoverColor, hoverColor) ||
+                other.hoverColor == hoverColor) &&
+            (identical(other.highlightColor, highlightColor) ||
+                other.highlightColor == highlightColor) &&
+            (identical(other.overlayColor, overlayColor) ||
+                other.overlayColor == overlayColor) &&
+            (identical(other.splashColor, splashColor) ||
+                other.splashColor == splashColor) &&
+            const DeepCollectionEquality()
+                .equals(other.splashFactory, splashFactory) &&
+            (identical(other.radius, radius) || other.radius == radius) &&
+            (identical(other.borderRadius, borderRadius) ||
+                other.borderRadius == borderRadius) &&
+            (identical(other.customBorder, customBorder) ||
+                other.customBorder == customBorder) &&
+            (identical(other.enableFeedback, enableFeedback) ||
+                other.enableFeedback == enableFeedback) &&
+            (identical(other.excludeFromSemantics, excludeFromSemantics) ||
+                other.excludeFromSemantics == excludeFromSemantics) &&
+            const DeepCollectionEquality().equals(other.focusNode, focusNode) &&
+            (identical(other.canRequestFocus, canRequestFocus) ||
+                other.canRequestFocus == canRequestFocus) &&
+            const DeepCollectionEquality()
+                .equals(other.onFocusChange, onFocusChange) &&
+            (identical(other.autofocus, autofocus) ||
+                other.autofocus == autofocus) &&
+            const DeepCollectionEquality()
+                .equals(other.statesController, statesController) &&
+            (identical(other.hoverDuration, hoverDuration) ||
+                other.hoverDuration == hoverDuration));
+  }
+
+  @JsonKey(includeFromJson: false, includeToJson: false)
+  @override
+  int get hashCode => Object.hashAll([
+        runtimeType,
+        const DeepCollectionEquality().hash(child),
+        const DeepCollectionEquality().hash(onTap),
+        const DeepCollectionEquality().hash(onDoubleTap),
+        const DeepCollectionEquality().hash(onLongPress),
+        const DeepCollectionEquality().hash(onTapDown),
+        const DeepCollectionEquality().hash(onTapUp),
+        const DeepCollectionEquality().hash(onTapCancel),
+        const DeepCollectionEquality().hash(onSecondaryTap),
+        const DeepCollectionEquality().hash(onSecondaryTapUp),
+        const DeepCollectionEquality().hash(onSecondaryTapDown),
+        const DeepCollectionEquality().hash(onSecondaryTapCancel),
+        const DeepCollectionEquality().hash(onHighlightChanged),
+        const DeepCollectionEquality().hash(onHover),
+        mouseCursor,
+        focusColor,
+        hoverColor,
+        highlightColor,
+        overlayColor,
+        splashColor,
+        const DeepCollectionEquality().hash(splashFactory),
+        radius,
+        borderRadius,
+        customBorder,
+        enableFeedback,
+        excludeFromSemantics,
+        const DeepCollectionEquality().hash(focusNode),
+        canRequestFocus,
+        const DeepCollectionEquality().hash(onFocusChange),
+        autofocus,
+        const DeepCollectionEquality().hash(statesController),
+        hoverDuration
+      ]);
+
+  @override
+  String toString() {
+    return 'StacInkWell(child: $child, onTap: $onTap, onDoubleTap: $onDoubleTap, onLongPress: $onLongPress, onTapDown: $onTapDown, onTapUp: $onTapUp, onTapCancel: $onTapCancel, onSecondaryTap: $onSecondaryTap, onSecondaryTapUp: $onSecondaryTapUp, onSecondaryTapDown: $onSecondaryTapDown, onSecondaryTapCancel: $onSecondaryTapCancel, onHighlightChanged: $onHighlightChanged, onHover: $onHover, mouseCursor: $mouseCursor, focusColor: $focusColor, hoverColor: $hoverColor, highlightColor: $highlightColor, overlayColor: $overlayColor, splashColor: $splashColor, splashFactory: $splashFactory, radius: $radius, borderRadius: $borderRadius, customBorder: $customBorder, enableFeedback: $enableFeedback, excludeFromSemantics: $excludeFromSemantics, focusNode: $focusNode, canRequestFocus: $canRequestFocus, onFocusChange: $onFocusChange, autofocus: $autofocus, statesController: $statesController, hoverDuration: $hoverDuration)';
+  }
+}
+
+/// @nodoc
+abstract mixin class $StacInkWellCopyWith<$Res> {
+  factory $StacInkWellCopyWith(
+          StacInkWell value, $Res Function(StacInkWell) _then) =
+      _$StacInkWellCopyWithImpl;
+  @useResult
+  $Res call(
+      {Map<String, dynamic>? child,
+      Map<String, dynamic>? onTap,
+      Map<String, dynamic>? onDoubleTap,
+      Map<String, dynamic>? onLongPress,
+      Map<String, dynamic>? onTapDown,
+      Map<String, dynamic>? onTapUp,
+      Map<String, dynamic>? onTapCancel,
+      Map<String, dynamic>? onSecondaryTap,
+      Map<String, dynamic>? onSecondaryTapUp,
+      Map<String, dynamic>? onSecondaryTapDown,
+      Map<String, dynamic>? onSecondaryTapCancel,
+      Map<String, dynamic>? onHighlightChanged,
+      Map<String, dynamic>? onHover,
+      StacMouseCursor? mouseCursor,
+      String? focusColor,
+      String? hoverColor,
+      String? highlightColor,
+      String? overlayColor,
+      String? splashColor,
+      Map<String, dynamic>? splashFactory,
+      double? radius,
+      StacBorderRadius? borderRadius,
+      StacBorder? customBorder,
+      bool enableFeedback,
+      bool excludeFromSemantics,
+      Map<String, dynamic>? focusNode,
+      bool canRequestFocus,
+      Map<String, dynamic>? onFocusChange,
+      bool autofocus,
+      Map<String, dynamic>? statesController,
+      StacDuration? hoverDuration});
+
+  $StacBorderRadiusCopyWith<$Res>? get borderRadius;
+  $StacBorderCopyWith<$Res>? get customBorder;
+  $StacDurationCopyWith<$Res>? get hoverDuration;
+}
+
+/// @nodoc
+class _$StacInkWellCopyWithImpl<$Res> implements $StacInkWellCopyWith<$Res> {
+  _$StacInkWellCopyWithImpl(this._self, this._then);
+
+  final StacInkWell _self;
+  final $Res Function(StacInkWell) _then;
+
+  /// Create a copy of StacInkWell
+  /// with the given fields replaced by the non-null parameter values.
+  @pragma('vm:prefer-inline')
+  @override
+  $Res call({
+    Object? child = freezed,
+    Object? onTap = freezed,
+    Object? onDoubleTap = freezed,
+    Object? onLongPress = freezed,
+    Object? onTapDown = freezed,
+    Object? onTapUp = freezed,
+    Object? onTapCancel = freezed,
+    Object? onSecondaryTap = freezed,
+    Object? onSecondaryTapUp = freezed,
+    Object? onSecondaryTapDown = freezed,
+    Object? onSecondaryTapCancel = freezed,
+    Object? onHighlightChanged = freezed,
+    Object? onHover = freezed,
+    Object? mouseCursor = freezed,
+    Object? focusColor = freezed,
+    Object? hoverColor = freezed,
+    Object? highlightColor = freezed,
+    Object? overlayColor = freezed,
+    Object? splashColor = freezed,
+    Object? splashFactory = freezed,
+    Object? radius = freezed,
+    Object? borderRadius = freezed,
+    Object? customBorder = freezed,
+    Object? enableFeedback = null,
+    Object? excludeFromSemantics = null,
+    Object? focusNode = freezed,
+    Object? canRequestFocus = null,
+    Object? onFocusChange = freezed,
+    Object? autofocus = null,
+    Object? statesController = freezed,
+    Object? hoverDuration = freezed,
+  }) {
+    return _then(_self.copyWith(
+      child: freezed == child
+          ? _self.child
+          : child // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onTap: freezed == onTap
+          ? _self.onTap
+          : onTap // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onDoubleTap: freezed == onDoubleTap
+          ? _self.onDoubleTap
+          : onDoubleTap // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onLongPress: freezed == onLongPress
+          ? _self.onLongPress
+          : onLongPress // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onTapDown: freezed == onTapDown
+          ? _self.onTapDown
+          : onTapDown // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onTapUp: freezed == onTapUp
+          ? _self.onTapUp
+          : onTapUp // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onTapCancel: freezed == onTapCancel
+          ? _self.onTapCancel
+          : onTapCancel // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onSecondaryTap: freezed == onSecondaryTap
+          ? _self.onSecondaryTap
+          : onSecondaryTap // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onSecondaryTapUp: freezed == onSecondaryTapUp
+          ? _self.onSecondaryTapUp
+          : onSecondaryTapUp // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onSecondaryTapDown: freezed == onSecondaryTapDown
+          ? _self.onSecondaryTapDown
+          : onSecondaryTapDown // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onSecondaryTapCancel: freezed == onSecondaryTapCancel
+          ? _self.onSecondaryTapCancel
+          : onSecondaryTapCancel // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onHighlightChanged: freezed == onHighlightChanged
+          ? _self.onHighlightChanged
+          : onHighlightChanged // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onHover: freezed == onHover
+          ? _self.onHover
+          : onHover // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      mouseCursor: freezed == mouseCursor
+          ? _self.mouseCursor
+          : mouseCursor // ignore: cast_nullable_to_non_nullable
+              as StacMouseCursor?,
+      focusColor: freezed == focusColor
+          ? _self.focusColor
+          : focusColor // ignore: cast_nullable_to_non_nullable
+              as String?,
+      hoverColor: freezed == hoverColor
+          ? _self.hoverColor
+          : hoverColor // ignore: cast_nullable_to_non_nullable
+              as String?,
+      highlightColor: freezed == highlightColor
+          ? _self.highlightColor
+          : highlightColor // ignore: cast_nullable_to_non_nullable
+              as String?,
+      overlayColor: freezed == overlayColor
+          ? _self.overlayColor
+          : overlayColor // ignore: cast_nullable_to_non_nullable
+              as String?,
+      splashColor: freezed == splashColor
+          ? _self.splashColor
+          : splashColor // ignore: cast_nullable_to_non_nullable
+              as String?,
+      splashFactory: freezed == splashFactory
+          ? _self.splashFactory
+          : splashFactory // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      radius: freezed == radius
+          ? _self.radius
+          : radius // ignore: cast_nullable_to_non_nullable
+              as double?,
+      borderRadius: freezed == borderRadius
+          ? _self.borderRadius
+          : borderRadius // ignore: cast_nullable_to_non_nullable
+              as StacBorderRadius?,
+      customBorder: freezed == customBorder
+          ? _self.customBorder
+          : customBorder // ignore: cast_nullable_to_non_nullable
+              as StacBorder?,
+      enableFeedback: null == enableFeedback
+          ? _self.enableFeedback
+          : enableFeedback // ignore: cast_nullable_to_non_nullable
+              as bool,
+      excludeFromSemantics: null == excludeFromSemantics
+          ? _self.excludeFromSemantics
+          : excludeFromSemantics // ignore: cast_nullable_to_non_nullable
+              as bool,
+      focusNode: freezed == focusNode
+          ? _self.focusNode
+          : focusNode // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      canRequestFocus: null == canRequestFocus
+          ? _self.canRequestFocus
+          : canRequestFocus // ignore: cast_nullable_to_non_nullable
+              as bool,
+      onFocusChange: freezed == onFocusChange
+          ? _self.onFocusChange
+          : onFocusChange // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      autofocus: null == autofocus
+          ? _self.autofocus
+          : autofocus // ignore: cast_nullable_to_non_nullable
+              as bool,
+      statesController: freezed == statesController
+          ? _self.statesController
+          : statesController // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      hoverDuration: freezed == hoverDuration
+          ? _self.hoverDuration
+          : hoverDuration // ignore: cast_nullable_to_non_nullable
+              as StacDuration?,
+    ));
+  }
+
+  /// Create a copy of StacInkWell
+  /// with the given fields replaced by the non-null parameter values.
+  @override
+  @pragma('vm:prefer-inline')
+  $StacBorderRadiusCopyWith<$Res>? get borderRadius {
+    if (_self.borderRadius == null) {
+      return null;
+    }
+
+    return $StacBorderRadiusCopyWith<$Res>(_self.borderRadius!, (value) {
+      return _then(_self.copyWith(borderRadius: value));
+    });
+  }
+
+  /// Create a copy of StacInkWell
+  /// with the given fields replaced by the non-null parameter values.
+  @override
+  @pragma('vm:prefer-inline')
+  $StacBorderCopyWith<$Res>? get customBorder {
+    if (_self.customBorder == null) {
+      return null;
+    }
+
+    return $StacBorderCopyWith<$Res>(_self.customBorder!, (value) {
+      return _then(_self.copyWith(customBorder: value));
+    });
+  }
+
+  /// Create a copy of StacInkWell
+  /// with the given fields replaced by the non-null parameter values.
+  @override
+  @pragma('vm:prefer-inline')
+  $StacDurationCopyWith<$Res>? get hoverDuration {
+    if (_self.hoverDuration == null) {
+      return null;
+    }
+
+    return $StacDurationCopyWith<$Res>(_self.hoverDuration!, (value) {
+      return _then(_self.copyWith(hoverDuration: value));
+    });
+  }
+}
+
+/// @nodoc
+@JsonSerializable()
+class _StacInkWell implements StacInkWell {
+  const _StacInkWell(
+      {final Map<String, dynamic>? child,
+      final Map<String, dynamic>? onTap,
+      final Map<String, dynamic>? onDoubleTap,
+      final Map<String, dynamic>? onLongPress,
+      final Map<String, dynamic>? onTapDown,
+      final Map<String, dynamic>? onTapUp,
+      final Map<String, dynamic>? onTapCancel,
+      final Map<String, dynamic>? onSecondaryTap,
+      final Map<String, dynamic>? onSecondaryTapUp,
+      final Map<String, dynamic>? onSecondaryTapDown,
+      final Map<String, dynamic>? onSecondaryTapCancel,
+      final Map<String, dynamic>? onHighlightChanged,
+      final Map<String, dynamic>? onHover,
+      this.mouseCursor,
+      this.focusColor,
+      this.hoverColor,
+      this.highlightColor,
+      this.overlayColor,
+      this.splashColor,
+      final Map<String, dynamic>? splashFactory,
+      this.radius,
+      this.borderRadius,
+      this.customBorder,
+      this.enableFeedback = true,
+      this.excludeFromSemantics = false,
+      final Map<String, dynamic>? focusNode,
+      this.canRequestFocus = true,
+      final Map<String, dynamic>? onFocusChange,
+      this.autofocus = false,
+      final Map<String, dynamic>? statesController,
+      this.hoverDuration})
+      : _child = child,
+        _onTap = onTap,
+        _onDoubleTap = onDoubleTap,
+        _onLongPress = onLongPress,
+        _onTapDown = onTapDown,
+        _onTapUp = onTapUp,
+        _onTapCancel = onTapCancel,
+        _onSecondaryTap = onSecondaryTap,
+        _onSecondaryTapUp = onSecondaryTapUp,
+        _onSecondaryTapDown = onSecondaryTapDown,
+        _onSecondaryTapCancel = onSecondaryTapCancel,
+        _onHighlightChanged = onHighlightChanged,
+        _onHover = onHover,
+        _splashFactory = splashFactory,
+        _focusNode = focusNode,
+        _onFocusChange = onFocusChange,
+        _statesController = statesController;
+  factory _StacInkWell.fromJson(Map<String, dynamic> json) =>
+      _$StacInkWellFromJson(json);
+
+  final Map<String, dynamic>? _child;
+  @override
+  Map<String, dynamic>? get child {
+    final value = _child;
+    if (value == null) return null;
+    if (_child is EqualUnmodifiableMapView) return _child;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onTap;
+  @override
+  Map<String, dynamic>? get onTap {
+    final value = _onTap;
+    if (value == null) return null;
+    if (_onTap is EqualUnmodifiableMapView) return _onTap;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onDoubleTap;
+  @override
+  Map<String, dynamic>? get onDoubleTap {
+    final value = _onDoubleTap;
+    if (value == null) return null;
+    if (_onDoubleTap is EqualUnmodifiableMapView) return _onDoubleTap;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onLongPress;
+  @override
+  Map<String, dynamic>? get onLongPress {
+    final value = _onLongPress;
+    if (value == null) return null;
+    if (_onLongPress is EqualUnmodifiableMapView) return _onLongPress;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onTapDown;
+  @override
+  Map<String, dynamic>? get onTapDown {
+    final value = _onTapDown;
+    if (value == null) return null;
+    if (_onTapDown is EqualUnmodifiableMapView) return _onTapDown;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onTapUp;
+  @override
+  Map<String, dynamic>? get onTapUp {
+    final value = _onTapUp;
+    if (value == null) return null;
+    if (_onTapUp is EqualUnmodifiableMapView) return _onTapUp;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onTapCancel;
+  @override
+  Map<String, dynamic>? get onTapCancel {
+    final value = _onTapCancel;
+    if (value == null) return null;
+    if (_onTapCancel is EqualUnmodifiableMapView) return _onTapCancel;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onSecondaryTap;
+  @override
+  Map<String, dynamic>? get onSecondaryTap {
+    final value = _onSecondaryTap;
+    if (value == null) return null;
+    if (_onSecondaryTap is EqualUnmodifiableMapView) return _onSecondaryTap;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onSecondaryTapUp;
+  @override
+  Map<String, dynamic>? get onSecondaryTapUp {
+    final value = _onSecondaryTapUp;
+    if (value == null) return null;
+    if (_onSecondaryTapUp is EqualUnmodifiableMapView) return _onSecondaryTapUp;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onSecondaryTapDown;
+  @override
+  Map<String, dynamic>? get onSecondaryTapDown {
+    final value = _onSecondaryTapDown;
+    if (value == null) return null;
+    if (_onSecondaryTapDown is EqualUnmodifiableMapView)
+      return _onSecondaryTapDown;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onSecondaryTapCancel;
+  @override
+  Map<String, dynamic>? get onSecondaryTapCancel {
+    final value = _onSecondaryTapCancel;
+    if (value == null) return null;
+    if (_onSecondaryTapCancel is EqualUnmodifiableMapView)
+      return _onSecondaryTapCancel;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onHighlightChanged;
+  @override
+  Map<String, dynamic>? get onHighlightChanged {
+    final value = _onHighlightChanged;
+    if (value == null) return null;
+    if (_onHighlightChanged is EqualUnmodifiableMapView)
+      return _onHighlightChanged;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  final Map<String, dynamic>? _onHover;
+  @override
+  Map<String, dynamic>? get onHover {
+    final value = _onHover;
+    if (value == null) return null;
+    if (_onHover is EqualUnmodifiableMapView) return _onHover;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  @override
+  final StacMouseCursor? mouseCursor;
+  @override
+  final String? focusColor;
+  @override
+  final String? hoverColor;
+  @override
+  final String? highlightColor;
+  @override
+  final String? overlayColor;
+  @override
+  final String? splashColor;
+  final Map<String, dynamic>? _splashFactory;
+  @override
+  Map<String, dynamic>? get splashFactory {
+    final value = _splashFactory;
+    if (value == null) return null;
+    if (_splashFactory is EqualUnmodifiableMapView) return _splashFactory;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  @override
+  final double? radius;
+  @override
+  final StacBorderRadius? borderRadius;
+  @override
+  final StacBorder? customBorder;
+  @override
+  @JsonKey()
+  final bool enableFeedback;
+  @override
+  @JsonKey()
+  final bool excludeFromSemantics;
+  final Map<String, dynamic>? _focusNode;
+  @override
+  Map<String, dynamic>? get focusNode {
+    final value = _focusNode;
+    if (value == null) return null;
+    if (_focusNode is EqualUnmodifiableMapView) return _focusNode;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  @override
+  @JsonKey()
+  final bool canRequestFocus;
+  final Map<String, dynamic>? _onFocusChange;
+  @override
+  Map<String, dynamic>? get onFocusChange {
+    final value = _onFocusChange;
+    if (value == null) return null;
+    if (_onFocusChange is EqualUnmodifiableMapView) return _onFocusChange;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  @override
+  @JsonKey()
+  final bool autofocus;
+  final Map<String, dynamic>? _statesController;
+  @override
+  Map<String, dynamic>? get statesController {
+    final value = _statesController;
+    if (value == null) return null;
+    if (_statesController is EqualUnmodifiableMapView) return _statesController;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  @override
+  final StacDuration? hoverDuration;
+
+  /// Create a copy of StacInkWell
+  /// with the given fields replaced by the non-null parameter values.
+  @override
+  @JsonKey(includeFromJson: false, includeToJson: false)
+  @pragma('vm:prefer-inline')
+  _$StacInkWellCopyWith<_StacInkWell> get copyWith =>
+      __$StacInkWellCopyWithImpl<_StacInkWell>(this, _$identity);
+
+  @override
+  Map<String, dynamic> toJson() {
+    return _$StacInkWellToJson(
+      this,
+    );
+  }
+
+  @override
+  bool operator ==(Object other) {
+    return identical(this, other) ||
+        (other.runtimeType == runtimeType &&
+            other is _StacInkWell &&
+            const DeepCollectionEquality().equals(other._child, _child) &&
+            const DeepCollectionEquality().equals(other._onTap, _onTap) &&
+            const DeepCollectionEquality()
+                .equals(other._onDoubleTap, _onDoubleTap) &&
+            const DeepCollectionEquality()
+                .equals(other._onLongPress, _onLongPress) &&
+            const DeepCollectionEquality()
+                .equals(other._onTapDown, _onTapDown) &&
+            const DeepCollectionEquality().equals(other._onTapUp, _onTapUp) &&
+            const DeepCollectionEquality()
+                .equals(other._onTapCancel, _onTapCancel) &&
+            const DeepCollectionEquality()
+                .equals(other._onSecondaryTap, _onSecondaryTap) &&
+            const DeepCollectionEquality()
+                .equals(other._onSecondaryTapUp, _onSecondaryTapUp) &&
+            const DeepCollectionEquality()
+                .equals(other._onSecondaryTapDown, _onSecondaryTapDown) &&
+            const DeepCollectionEquality()
+                .equals(other._onSecondaryTapCancel, _onSecondaryTapCancel) &&
+            const DeepCollectionEquality()
+                .equals(other._onHighlightChanged, _onHighlightChanged) &&
+            const DeepCollectionEquality().equals(other._onHover, _onHover) &&
+            (identical(other.mouseCursor, mouseCursor) ||
+                other.mouseCursor == mouseCursor) &&
+            (identical(other.focusColor, focusColor) ||
+                other.focusColor == focusColor) &&
+            (identical(other.hoverColor, hoverColor) ||
+                other.hoverColor == hoverColor) &&
+            (identical(other.highlightColor, highlightColor) ||
+                other.highlightColor == highlightColor) &&
+            (identical(other.overlayColor, overlayColor) ||
+                other.overlayColor == overlayColor) &&
+            (identical(other.splashColor, splashColor) ||
+                other.splashColor == splashColor) &&
+            const DeepCollectionEquality()
+                .equals(other._splashFactory, _splashFactory) &&
+            (identical(other.radius, radius) || other.radius == radius) &&
+            (identical(other.borderRadius, borderRadius) ||
+                other.borderRadius == borderRadius) &&
+            (identical(other.customBorder, customBorder) ||
+                other.customBorder == customBorder) &&
+            (identical(other.enableFeedback, enableFeedback) ||
+                other.enableFeedback == enableFeedback) &&
+            (identical(other.excludeFromSemantics, excludeFromSemantics) ||
+                other.excludeFromSemantics == excludeFromSemantics) &&
+            const DeepCollectionEquality()
+                .equals(other._focusNode, _focusNode) &&
+            (identical(other.canRequestFocus, canRequestFocus) ||
+                other.canRequestFocus == canRequestFocus) &&
+            const DeepCollectionEquality()
+                .equals(other._onFocusChange, _onFocusChange) &&
+            (identical(other.autofocus, autofocus) ||
+                other.autofocus == autofocus) &&
+            const DeepCollectionEquality()
+                .equals(other._statesController, _statesController) &&
+            (identical(other.hoverDuration, hoverDuration) ||
+                other.hoverDuration == hoverDuration));
+  }
+
+  @JsonKey(includeFromJson: false, includeToJson: false)
+  @override
+  int get hashCode => Object.hashAll([
+        runtimeType,
+        const DeepCollectionEquality().hash(_child),
+        const DeepCollectionEquality().hash(_onTap),
+        const DeepCollectionEquality().hash(_onDoubleTap),
+        const DeepCollectionEquality().hash(_onLongPress),
+        const DeepCollectionEquality().hash(_onTapDown),
+        const DeepCollectionEquality().hash(_onTapUp),
+        const DeepCollectionEquality().hash(_onTapCancel),
+        const DeepCollectionEquality().hash(_onSecondaryTap),
+        const DeepCollectionEquality().hash(_onSecondaryTapUp),
+        const DeepCollectionEquality().hash(_onSecondaryTapDown),
+        const DeepCollectionEquality().hash(_onSecondaryTapCancel),
+        const DeepCollectionEquality().hash(_onHighlightChanged),
+        const DeepCollectionEquality().hash(_onHover),
+        mouseCursor,
+        focusColor,
+        hoverColor,
+        highlightColor,
+        overlayColor,
+        splashColor,
+        const DeepCollectionEquality().hash(_splashFactory),
+        radius,
+        borderRadius,
+        customBorder,
+        enableFeedback,
+        excludeFromSemantics,
+        const DeepCollectionEquality().hash(_focusNode),
+        canRequestFocus,
+        const DeepCollectionEquality().hash(_onFocusChange),
+        autofocus,
+        const DeepCollectionEquality().hash(_statesController),
+        hoverDuration
+      ]);
+
+  @override
+  String toString() {
+    return 'StacInkWell(child: $child, onTap: $onTap, onDoubleTap: $onDoubleTap, onLongPress: $onLongPress, onTapDown: $onTapDown, onTapUp: $onTapUp, onTapCancel: $onTapCancel, onSecondaryTap: $onSecondaryTap, onSecondaryTapUp: $onSecondaryTapUp, onSecondaryTapDown: $onSecondaryTapDown, onSecondaryTapCancel: $onSecondaryTapCancel, onHighlightChanged: $onHighlightChanged, onHover: $onHover, mouseCursor: $mouseCursor, focusColor: $focusColor, hoverColor: $hoverColor, highlightColor: $highlightColor, overlayColor: $overlayColor, splashColor: $splashColor, splashFactory: $splashFactory, radius: $radius, borderRadius: $borderRadius, customBorder: $customBorder, enableFeedback: $enableFeedback, excludeFromSemantics: $excludeFromSemantics, focusNode: $focusNode, canRequestFocus: $canRequestFocus, onFocusChange: $onFocusChange, autofocus: $autofocus, statesController: $statesController, hoverDuration: $hoverDuration)';
+  }
+}
+
+/// @nodoc
+abstract mixin class _$StacInkWellCopyWith<$Res>
+    implements $StacInkWellCopyWith<$Res> {
+  factory _$StacInkWellCopyWith(
+          _StacInkWell value, $Res Function(_StacInkWell) _then) =
+      __$StacInkWellCopyWithImpl;
+  @override
+  @useResult
+  $Res call(
+      {Map<String, dynamic>? child,
+      Map<String, dynamic>? onTap,
+      Map<String, dynamic>? onDoubleTap,
+      Map<String, dynamic>? onLongPress,
+      Map<String, dynamic>? onTapDown,
+      Map<String, dynamic>? onTapUp,
+      Map<String, dynamic>? onTapCancel,
+      Map<String, dynamic>? onSecondaryTap,
+      Map<String, dynamic>? onSecondaryTapUp,
+      Map<String, dynamic>? onSecondaryTapDown,
+      Map<String, dynamic>? onSecondaryTapCancel,
+      Map<String, dynamic>? onHighlightChanged,
+      Map<String, dynamic>? onHover,
+      StacMouseCursor? mouseCursor,
+      String? focusColor,
+      String? hoverColor,
+      String? highlightColor,
+      String? overlayColor,
+      String? splashColor,
+      Map<String, dynamic>? splashFactory,
+      double? radius,
+      StacBorderRadius? borderRadius,
+      StacBorder? customBorder,
+      bool enableFeedback,
+      bool excludeFromSemantics,
+      Map<String, dynamic>? focusNode,
+      bool canRequestFocus,
+      Map<String, dynamic>? onFocusChange,
+      bool autofocus,
+      Map<String, dynamic>? statesController,
+      StacDuration? hoverDuration});
+
+  @override
+  $StacBorderRadiusCopyWith<$Res>? get borderRadius;
+  @override
+  $StacBorderCopyWith<$Res>? get customBorder;
+  @override
+  $StacDurationCopyWith<$Res>? get hoverDuration;
+}
+
+/// @nodoc
+class __$StacInkWellCopyWithImpl<$Res> implements _$StacInkWellCopyWith<$Res> {
+  __$StacInkWellCopyWithImpl(this._self, this._then);
+
+  final _StacInkWell _self;
+  final $Res Function(_StacInkWell) _then;
+
+  /// Create a copy of StacInkWell
+  /// with the given fields replaced by the non-null parameter values.
+  @override
+  @pragma('vm:prefer-inline')
+  $Res call({
+    Object? child = freezed,
+    Object? onTap = freezed,
+    Object? onDoubleTap = freezed,
+    Object? onLongPress = freezed,
+    Object? onTapDown = freezed,
+    Object? onTapUp = freezed,
+    Object? onTapCancel = freezed,
+    Object? onSecondaryTap = freezed,
+    Object? onSecondaryTapUp = freezed,
+    Object? onSecondaryTapDown = freezed,
+    Object? onSecondaryTapCancel = freezed,
+    Object? onHighlightChanged = freezed,
+    Object? onHover = freezed,
+    Object? mouseCursor = freezed,
+    Object? focusColor = freezed,
+    Object? hoverColor = freezed,
+    Object? highlightColor = freezed,
+    Object? overlayColor = freezed,
+    Object? splashColor = freezed,
+    Object? splashFactory = freezed,
+    Object? radius = freezed,
+    Object? borderRadius = freezed,
+    Object? customBorder = freezed,
+    Object? enableFeedback = null,
+    Object? excludeFromSemantics = null,
+    Object? focusNode = freezed,
+    Object? canRequestFocus = null,
+    Object? onFocusChange = freezed,
+    Object? autofocus = null,
+    Object? statesController = freezed,
+    Object? hoverDuration = freezed,
+  }) {
+    return _then(_StacInkWell(
+      child: freezed == child
+          ? _self._child
+          : child // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onTap: freezed == onTap
+          ? _self._onTap
+          : onTap // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onDoubleTap: freezed == onDoubleTap
+          ? _self._onDoubleTap
+          : onDoubleTap // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onLongPress: freezed == onLongPress
+          ? _self._onLongPress
+          : onLongPress // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onTapDown: freezed == onTapDown
+          ? _self._onTapDown
+          : onTapDown // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onTapUp: freezed == onTapUp
+          ? _self._onTapUp
+          : onTapUp // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onTapCancel: freezed == onTapCancel
+          ? _self._onTapCancel
+          : onTapCancel // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onSecondaryTap: freezed == onSecondaryTap
+          ? _self._onSecondaryTap
+          : onSecondaryTap // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onSecondaryTapUp: freezed == onSecondaryTapUp
+          ? _self._onSecondaryTapUp
+          : onSecondaryTapUp // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onSecondaryTapDown: freezed == onSecondaryTapDown
+          ? _self._onSecondaryTapDown
+          : onSecondaryTapDown // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onSecondaryTapCancel: freezed == onSecondaryTapCancel
+          ? _self._onSecondaryTapCancel
+          : onSecondaryTapCancel // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onHighlightChanged: freezed == onHighlightChanged
+          ? _self._onHighlightChanged
+          : onHighlightChanged // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      onHover: freezed == onHover
+          ? _self._onHover
+          : onHover // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      mouseCursor: freezed == mouseCursor
+          ? _self.mouseCursor
+          : mouseCursor // ignore: cast_nullable_to_non_nullable
+              as StacMouseCursor?,
+      focusColor: freezed == focusColor
+          ? _self.focusColor
+          : focusColor // ignore: cast_nullable_to_non_nullable
+              as String?,
+      hoverColor: freezed == hoverColor
+          ? _self.hoverColor
+          : hoverColor // ignore: cast_nullable_to_non_nullable
+              as String?,
+      highlightColor: freezed == highlightColor
+          ? _self.highlightColor
+          : highlightColor // ignore: cast_nullable_to_non_nullable
+              as String?,
+      overlayColor: freezed == overlayColor
+          ? _self.overlayColor
+          : overlayColor // ignore: cast_nullable_to_non_nullable
+              as String?,
+      splashColor: freezed == splashColor
+          ? _self.splashColor
+          : splashColor // ignore: cast_nullable_to_non_nullable
+              as String?,
+      splashFactory: freezed == splashFactory
+          ? _self._splashFactory
+          : splashFactory // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      radius: freezed == radius
+          ? _self.radius
+          : radius // ignore: cast_nullable_to_non_nullable
+              as double?,
+      borderRadius: freezed == borderRadius
+          ? _self.borderRadius
+          : borderRadius // ignore: cast_nullable_to_non_nullable
+              as StacBorderRadius?,
+      customBorder: freezed == customBorder
+          ? _self.customBorder
+          : customBorder // ignore: cast_nullable_to_non_nullable
+              as StacBorder?,
+      enableFeedback: null == enableFeedback
+          ? _self.enableFeedback
+          : enableFeedback // ignore: cast_nullable_to_non_nullable
+              as bool,
+      excludeFromSemantics: null == excludeFromSemantics
+          ? _self.excludeFromSemantics
+          : excludeFromSemantics // ignore: cast_nullable_to_non_nullable
+              as bool,
+      focusNode: freezed == focusNode
+          ? _self._focusNode
+          : focusNode // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      canRequestFocus: null == canRequestFocus
+          ? _self.canRequestFocus
+          : canRequestFocus // ignore: cast_nullable_to_non_nullable
+              as bool,
+      onFocusChange: freezed == onFocusChange
+          ? _self._onFocusChange
+          : onFocusChange // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      autofocus: null == autofocus
+          ? _self.autofocus
+          : autofocus // ignore: cast_nullable_to_non_nullable
+              as bool,
+      statesController: freezed == statesController
+          ? _self._statesController
+          : statesController // ignore: cast_nullable_to_non_nullable
+              as Map<String, dynamic>?,
+      hoverDuration: freezed == hoverDuration
+          ? _self.hoverDuration
+          : hoverDuration // ignore: cast_nullable_to_non_nullable
+              as StacDuration?,
+    ));
+  }
+
+  /// Create a copy of StacInkWell
+  /// with the given fields replaced by the non-null parameter values.
+  @override
+  @pragma('vm:prefer-inline')
+  $StacBorderRadiusCopyWith<$Res>? get borderRadius {
+    if (_self.borderRadius == null) {
+      return null;
+    }
+
+    return $StacBorderRadiusCopyWith<$Res>(_self.borderRadius!, (value) {
+      return _then(_self.copyWith(borderRadius: value));
+    });
+  }
+
+  /// Create a copy of StacInkWell
+  /// with the given fields replaced by the non-null parameter values.
+  @override
+  @pragma('vm:prefer-inline')
+  $StacBorderCopyWith<$Res>? get customBorder {
+    if (_self.customBorder == null) {
+      return null;
+    }
+
+    return $StacBorderCopyWith<$Res>(_self.customBorder!, (value) {
+      return _then(_self.copyWith(customBorder: value));
+    });
+  }
+
+  /// Create a copy of StacInkWell
+  /// with the given fields replaced by the non-null parameter values.
+  @override
+  @pragma('vm:prefer-inline')
+  $StacDurationCopyWith<$Res>? get hoverDuration {
+    if (_self.hoverDuration == null) {
+      return null;
+    }
+
+    return $StacDurationCopyWith<$Res>(_self.hoverDuration!, (value) {
+      return _then(_self.copyWith(hoverDuration: value));
+    });
+  }
+}
+
+// dart format on
diff --git a/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell.g.dart b/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell.g.dart
new file mode 100644
index 000000000..1c9348a1c
--- /dev/null
+++ b/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell.g.dart
@@ -0,0 +1,124 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'stac_inkwell.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+_StacInkWell _$StacInkWellFromJson(Map<String, dynamic> json) => _StacInkWell(
+      child: json['child'] as Map<String, dynamic>?,
+      onTap: json['onTap'] as Map<String, dynamic>?,
+      onDoubleTap: json['onDoubleTap'] as Map<String, dynamic>?,
+      onLongPress: json['onLongPress'] as Map<String, dynamic>?,
+      onTapDown: json['onTapDown'] as Map<String, dynamic>?,
+      onTapUp: json['onTapUp'] as Map<String, dynamic>?,
+      onTapCancel: json['onTapCancel'] as Map<String, dynamic>?,
+      onSecondaryTap: json['onSecondaryTap'] as Map<String, dynamic>?,
+      onSecondaryTapUp: json['onSecondaryTapUp'] as Map<String, dynamic>?,
+      onSecondaryTapDown: json['onSecondaryTapDown'] as Map<String, dynamic>?,
+      onSecondaryTapCancel:
+          json['onSecondaryTapCancel'] as Map<String, dynamic>?,
+      onHighlightChanged: json['onHighlightChanged'] as Map<String, dynamic>?,
+      onHover: json['onHover'] as Map<String, dynamic>?,
+      mouseCursor:
+          $enumDecodeNullable(_$StacMouseCursorEnumMap, json['mouseCursor']),
+      focusColor: json['focusColor'] as String?,
+      hoverColor: json['hoverColor'] as String?,
+      highlightColor: json['highlightColor'] as String?,
+      overlayColor: json['overlayColor'] as String?,
+      splashColor: json['splashColor'] as String?,
+      splashFactory: json['splashFactory'] as Map<String, dynamic>?,
+      radius: (json['radius'] as num?)?.toDouble(),
+      borderRadius: json['borderRadius'] == null
+          ? null
+          : StacBorderRadius.fromJson(json['borderRadius']),
+      customBorder: json['customBorder'] == null
+          ? null
+          : StacBorder.fromJson(json['customBorder'] as Map<String, dynamic>),
+      enableFeedback: json['enableFeedback'] as bool? ?? true,
+      excludeFromSemantics: json['excludeFromSemantics'] as bool? ?? false,
+      focusNode: json['focusNode'] as Map<String, dynamic>?,
+      canRequestFocus: json['canRequestFocus'] as bool? ?? true,
+      onFocusChange: json['onFocusChange'] as Map<String, dynamic>?,
+      autofocus: json['autofocus'] as bool? ?? false,
+      statesController: json['statesController'] as Map<String, dynamic>?,
+      hoverDuration: json['hoverDuration'] == null
+          ? null
+          : StacDuration.fromJson(
+              json['hoverDuration'] as Map<String, dynamic>),
+    );
+
+Map<String, dynamic> _$StacInkWellToJson(_StacInkWell instance) =>
+    <String, dynamic>{
+      'child': instance.child,
+      'onTap': instance.onTap,
+      'onDoubleTap': instance.onDoubleTap,
+      'onLongPress': instance.onLongPress,
+      'onTapDown': instance.onTapDown,
+      'onTapUp': instance.onTapUp,
+      'onTapCancel': instance.onTapCancel,
+      'onSecondaryTap': instance.onSecondaryTap,
+      'onSecondaryTapUp': instance.onSecondaryTapUp,
+      'onSecondaryTapDown': instance.onSecondaryTapDown,
+      'onSecondaryTapCancel': instance.onSecondaryTapCancel,
+      'onHighlightChanged': instance.onHighlightChanged,
+      'onHover': instance.onHover,
+      'mouseCursor': _$StacMouseCursorEnumMap[instance.mouseCursor],
+      'focusColor': instance.focusColor,
+      'hoverColor': instance.hoverColor,
+      'highlightColor': instance.highlightColor,
+      'overlayColor': instance.overlayColor,
+      'splashColor': instance.splashColor,
+      'splashFactory': instance.splashFactory,
+      'radius': instance.radius,
+      'borderRadius': instance.borderRadius,
+      'customBorder': instance.customBorder,
+      'enableFeedback': instance.enableFeedback,
+      'excludeFromSemantics': instance.excludeFromSemantics,
+      'focusNode': instance.focusNode,
+      'canRequestFocus': instance.canRequestFocus,
+      'onFocusChange': instance.onFocusChange,
+      'autofocus': instance.autofocus,
+      'statesController': instance.statesController,
+      'hoverDuration': instance.hoverDuration,
+    };
+
+const _$StacMouseCursorEnumMap = {
+  StacMouseCursor.none: 'none',
+  StacMouseCursor.basic: 'basic',
+  StacMouseCursor.click: 'click',
+  StacMouseCursor.forbidden: 'forbidden',
+  StacMouseCursor.wait: 'wait',
+  StacMouseCursor.progress: 'progress',
+  StacMouseCursor.contextMenu: 'contextMenu',
+  StacMouseCursor.help: 'help',
+  StacMouseCursor.text: 'text',
+  StacMouseCursor.verticalText: 'verticalText',
+  StacMouseCursor.cell: 'cell',
+  StacMouseCursor.precise: 'precise',
+  StacMouseCursor.move: 'move',
+  StacMouseCursor.grab: 'grab',
+  StacMouseCursor.grabbing: 'grabbing',
+  StacMouseCursor.noDrop: 'noDrop',
+  StacMouseCursor.alias: 'alias',
+  StacMouseCursor.copy: 'copy',
+  StacMouseCursor.disappearing: 'disappearing',
+  StacMouseCursor.allScroll: 'allScroll',
+  StacMouseCursor.resizeLeftRight: 'resizeLeftRight',
+  StacMouseCursor.resizeUpDown: 'resizeUpDown',
+  StacMouseCursor.resizeUpLeftDownRight: 'resizeUpLeftDownRight',
+  StacMouseCursor.resizeUpRightDownLeft: 'resizeUpRightDownLeft',
+  StacMouseCursor.resizeUp: 'resizeUp',
+  StacMouseCursor.resizeDown: 'resizeDown',
+  StacMouseCursor.resizeLeft: 'resizeLeft',
+  StacMouseCursor.resizeRight: 'resizeRight',
+  StacMouseCursor.resizeUpLeft: 'resizeUpLeft',
+  StacMouseCursor.resizeUpRight: 'resizeUpRight',
+  StacMouseCursor.resizeDownLeft: 'resizeDownLeft',
+  StacMouseCursor.resizeDownRight: 'resizeDownRight',
+  StacMouseCursor.resizeColumn: 'resizeColumn',
+  StacMouseCursor.resizeRow: 'resizeRow',
+  StacMouseCursor.zoomIn: 'zoomIn',
+  StacMouseCursor.zoomOut: 'zoomOut',
+};
diff --git a/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell_parser.dart b/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell_parser.dart
new file mode 100644
index 000000000..2c66a6f51
--- /dev/null
+++ b/packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell_parser.dart
@@ -0,0 +1,80 @@
+import 'package:flutter/material.dart';
+import 'package:stac/src/parsers/widgets/stac_inkwell/stac_inkwell.dart';
+import 'package:stac/src/utils/widget_type.dart';
+import 'package:stac/stac.dart';
+
+class StacInkwellParser extends StacParser<StacInkWell> {
+  const StacInkwellParser();
+
+  @override
+  String get type => WidgetType.inkWell.name;
+
+  @override
+  StacInkWell getModel(Map<String, dynamic> json) {
+    return StacInkWell.fromJson(json);
+  }
+
+  @override
+  Widget parse(BuildContext context, StacInkWell model) {
+    return InkWell(
+      child: Stac.fromJson(model.child, context),
+      onTap: model.onTap == null
+          ? null
+          : () => Stac.onCallFromJson(model.onTap, context),
+      onDoubleTap: model.onDoubleTap == null
+          ? null
+          : () => Stac.onCallFromJson(model.onDoubleTap, context),
+      onLongPress: model.onLongPress == null
+          ? null
+          : () => Stac.onCallFromJson(model.onLongPress, context),
+      onTapDown: model.onTapDown == null
+          ? null
+          : (_) => Stac.onCallFromJson(model.onTapDown, context),
+      onTapUp: model.onTapUp == null
+          ? null
+          : (_) => Stac.onCallFromJson(model.onTapUp, context),
+      onTapCancel: model.onTapCancel == null
+          ? null
+          : () => Stac.onCallFromJson(model.onTapCancel, context),
+      onSecondaryTap: model.onSecondaryTap == null
+          ? null
+          : () => Stac.onCallFromJson(model.onSecondaryTap, context),
+      onSecondaryTapUp: model.onSecondaryTapUp == null
+          ? null
+          : (_) => Stac.onCallFromJson(model.onSecondaryTapUp, context),
+      onSecondaryTapDown: model.onSecondaryTapDown == null
+          ? null
+          : (_) => Stac.onCallFromJson(model.onSecondaryTapDown, context),
+      onSecondaryTapCancel: model.onSecondaryTapCancel == null
+          ? null
+          : () => Stac.onCallFromJson(model.onSecondaryTapCancel, context),
+      onHighlightChanged: model.onHighlightChanged == null
+          ? null
+          : (_) => Stac.onCallFromJson(model.onHighlightChanged, context),
+      onHover: model.onHover == null
+          ? null
+          : (_) => Stac.onCallFromJson(model.onHover, context),
+      mouseCursor: model.mouseCursor?.value,
+      focusColor: model.focusColor.toColor(context),
+      hoverColor: model.hoverColor.toColor(context),
+      highlightColor: model.highlightColor.toColor(context),
+      overlayColor:
+          WidgetStateProperty.all(model.overlayColor?.toColor(context)),
+      splashColor: model.splashColor.toColor(context),
+      radius: model.radius,
+      borderRadius: model.borderRadius.parse,
+      customBorder: model.customBorder?.parse(context),
+      enableFeedback: model.enableFeedback,
+      excludeFromSemantics: model.excludeFromSemantics,
+      canRequestFocus: model.canRequestFocus,
+      onFocusChange: (_) => Stac.onCallFromJson(model.onFocusChange, context),
+      autofocus: model.autofocus,
+      hoverDuration: model.hoverDuration?.parse,
+
+      ///TODO : need to add support for
+      ///focusNode
+      ///splashFactory
+      ///statesController
+    );
+  }
+}
diff --git a/packages/stac/lib/src/utils/widget_type.dart b/packages/stac/lib/src/utils/widget_type.dart
index 6c2408b7b..80994d5fb 100644
--- a/packages/stac/lib/src/utils/widget_type.dart
+++ b/packages/stac/lib/src/utils/widget_type.dart
@@ -39,6 +39,7 @@ enum WidgetType {
   icon,
   iconButton,
   image,
+  inkWell,
   limitedBox,
   linearProgressIndicator,
   listTile,
diff --git a/website/docs/widgets/ink_well.md b/website/docs/widgets/ink_well.md
new file mode 100644
index 000000000..769c61f68
--- /dev/null
+++ b/website/docs/widgets/ink_well.md
@@ -0,0 +1,71 @@
+# InkWell
+
+**Stac InkWell** allows you to build the Flutter `InkWell` widget using JSON.  
+To learn more about the `InkWell` widget in Flutter, refer to the [official documentation](https://api.flutter.dev/flutter/material/InkWell-class.html).
+
+
+## Properties
+| Property                | Type                         | Description                                                                 |
+|-------------------------|------------------------------|-----------------------------------------------------------------------------|
+| `child`                 | `Map<String, dynamic>?`      | The widget below this InkWell.     |
+| `onTap`                 | `Map<String, dynamic>?`      | Called when the user taps the InkWell.                                     |
+| `onDoubleTap`           | `Map<String, dynamic>?`      | Called when the user double taps the InkWell.                              |
+| `onLongPress`           | `Map<String, dynamic>?`      | Called when the user presses and holds for a long duration.                |
+| `onTapDown`             | `Map<String, dynamic>?`      | Called when a tap gesture starts.                                          |
+| `onTapUp`               | `Map<String, dynamic>?`      | Called when a tap gesture is lifted.                                       |
+| `onTapCancel`           | `Map<String, dynamic>?`      | Called when a tap gesture is aborted.                                      |
+| `onSecondaryTap`        | `Map<String, dynamic>?`      | Called for a secondary tap (e.g., right-click on desktop).                 |
+| `onSecondaryTapUp`      | `Map<String, dynamic>?`      | Called when a secondary tap is lifted.                                     |
+| `onSecondaryTapDown`    | `Map<String, dynamic>?`      | Called when a secondary tap gesture starts.                                |
+| `onSecondaryTapCancel`  | `Map<String, dynamic>?`      | Called when a secondary tap gesture is aborted.                            |
+| `onHighlightChanged`    | `Map<String, dynamic>?`      | Called when the InkWell highlight changes (pressed state).                 |
+| `onHover`               | `Map<String, dynamic>?`      | Called when a pointer enters or exits the widget area.                     |
+| `mouseCursor`           | `StacMouseCursor?`           | Defines the mouse cursor when it hovers over the InkWell.                  |
+| `focusColor`            | `String?`                    | Color of the focus highlight.                                              |
+| `hoverColor`            | `String?`                    | Color when a pointer hovers over the InkWell.                              |
+| `highlightColor`        | `String?`                    | Color when the InkWell is pressed.                                         |
+| `overlayColor`          | `String?`                    | Ripple effect color over the child.                                        |
+| `splashColor`           | `String?`                    | The splash color of the ripple.                                            |
+| `radius`                | `double?`                    | Defines the splash radius.                                                 |
+| `borderRadius`          | `StacBorderRadius?`          | Sets rounded corners for the ripple effect.                                |
+| `customBorder`          | `StacBorder?`                | Custom border shape for clipping and ripple.                               |
+| `enableFeedback`        | `@Default(true) bool`        | Whether to play feedback (e.g., sound, vibration) on tap.                  |
+| `excludeFromSemantics`  | `@Default(false) bool`       | Whether to exclude from accessibility tools like screen readers.           |
+| `canRequestFocus`       | `@Default(true) bool`        | Whether this widget can request focus.                                     |
+| `onFocusChange`         | `Map<String, dynamic>?`      | Callback for when the focus changes.                                       |
+| `autofocus`             | `@Default(false) bool`       | Automatically focuses when the widget is built.                            |
+| `hoverDuration`         | `StacDuration?`              | Duration for the hover animation effect.                                   |
+
+## Example JSON
+
+```json
+{
+    "type": "inkWell",
+    "child": {
+        "type": "padding",
+        "padding": {
+            "top": 20,
+            "bottom": 20,
+            "right": 20,
+            "left": 20
+        },
+        "child": {
+            "type": "text",
+            "data": "Hello, World! from Inkwell",
+            "textAlign": "center"
+        }
+    },
+    "splashColor": "#E1BEE7",
+    "borderRadius": {
+        "topLeft": 20,
+        "topRight": 20,
+        "bottomLeft": 20,
+        "bottomRight": 20
+    },
+    "radius": 20,
+    "hoverDuration": {
+        "seconds": 10
+    },
+    "onTap": {}
+}
+```


Reviews:
user: login: divyanshub024
body: Thanks for the PR @AbhijithKonnayil 💯 
Please check my suggestions. 
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-09T07:46:28Z
user: login: divyanshub024
body: Thank you for your contribution @AbhijithKonnayil 🥇 
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-11T05:28:23Z

Review comments:
diff_hunk: @@ -1,4 +1,27 @@
 [
+  {
+    "type": "listTile",
+    "leading": {
+      "type": "icon",
+      "iconType": "cupertino",
+      "icon": "hand_draw"
+    },
+    "title": {
+      "type": "text",
+      "data": "Stac InkWell"
+    },
+    "subtitle": {
+      "type": "text",
+      "data": "Creates an Inkwell effect when tapped"
+    },
+    "onTap": {
+      "actionType": "navigate",
+      "widgetJson": {
+        "type": "exampleScreen",
+        "assetPath": "assets/json/inkwell_example.json"
+      }
+    }
+  },
path: examples/stac_gallery/assets/json/home_screen.json
user: login: divyanshub024
body: Can we move this in alphabetical order? 
created_at: 2025-05-09T07:34:12Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,48 @@
+{
+    "type": "scaffold",
+    "appBar": {
+        "type": "appBar",
+        "title": {
+            "type": "text",
+            "data": "InkWell"
+        }
+    },
+    "body": {
+        "type": "listView",
+        "shrinkWrap": true,
+        "children": [
+            {
+                "type": "center",
+                "child": {
+                    "type": "inkWell",
+                    "child": {
+                        "type": "padding",
+                        "padding": {
+                            "top": 20,
+                            "bottom": 20,
+                            "right": 20,
+                            "left": 20
+                        },
+                        "child": {
+                            "type": "text",
+                            "data": "Hello, World! from Inkwell",
+                            "textAlign": "center"
+                        }
+                    },
+                    "splashColor": "#E1BEE7",
+                    "borderRadius_": {
+                        "topLeft": 20,
+                        "topRight": 20,
+                        "bottomLeft": 20,
+                        "bottomRight": 20
+                    },
+                    "radius": 20,
+                    "hoverDuration": {
+                        "seconds": 10
+                    },
+                    "onTap": {}
path: examples/stac_gallery/assets/json/inkwell_example.json
user: login: divyanshub024
body: Can we show some action in "onTap"? 
created_at: 2025-05-09T07:34:53Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,78 @@
+import 'package:flutter/material.dart';
+import 'package:stac/src/parsers/widgets/stac_inkwell/stac_inkwell.dart';
+import 'package:stac/src/utils/widget_type.dart';
+import 'package:stac/stac.dart';
+
+class StacInkwellParser extends StacParser<StacInkWell> {
+  const StacInkwellParser();
+  @override
path: packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell_parser.dart
user: login: divyanshub024
body: Please add an empty line before this line for better readability. 
created_at: 2025-05-09T07:44:36Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,78 @@
+import 'package:flutter/material.dart';
+import 'package:stac/src/parsers/widgets/stac_inkwell/stac_inkwell.dart';
+import 'package:stac/src/utils/widget_type.dart';
+import 'package:stac/stac.dart';
+
+class StacInkwellParser extends StacParser<StacInkWell> {
+  const StacInkwellParser();
+  @override
+  String get type => WidgetType.inkWell.name;
+  @override
path: packages/stac/lib/src/parsers/widgets/stac_inkwell/stac_inkwell_parser.dart
user: login: divyanshub024
body: Please add an empty line before this line for better readability.
created_at: 2025-05-09T07:44:54Z
author_association: MEMBER

PR comments:
user: login: CLAassistant
created_at: 2025-05-08T21:48:59Z
body: [![CLA assistant check](https://cla-assistant.io/pull/badge/signed)](https://cla-assistant.io/StacDev/stac?pullRequest=241) <br/>All committers have signed the CLA.
author_association: NONE
user: login: AbhijithKonnayil
created_at: 2025-05-09T12:50:35Z
body: > Thanks for the PR @AbhijithKonnayil 💯 Please check my suggestions.

updated the PR with your suggestions. Please cheak
author_association: CONTRIBUTOR
user: login: divyanshub024
created_at: 2025-05-10T06:17:52Z
body: Hey @AbhijithKonnayil!! Looks like PR format check is failing. Can you please check?
author_association: MEMBER