From 716b38045c2ff43b668e15a29873c61f591fb287 Mon Sep 17 00:00:00 2001
From: Matthias Ngeo <matthiasngeo@gmail.com>
Date: Sat, 7 Dec 2024 12:08:18 +0800
Subject: [PATCH] Add initial rules

---
 docs/pages/docs/form/slider.mdx               |   4 +-
 forui/.gitignore                              |   1 +
 forui/CHANGELOG.md                            |   4 +
 forui/README.md                               |  42 +------
 forui/analysis_options.yaml                   |   4 +-
 forui/example/pubspec.lock                    |  20 ++--
 forui/lib/src/foundation/rendering.dart       |   4 +-
 forui/lib/src/theme/theme.dart                |   6 +-
 .../src/widgets/slider/inherited_data.dart    |   2 +-
 forui/lib/src/widgets/slider/slider.dart      |   8 +-
 forui/lib/src/widgets/slider/slider_mark.dart |   2 +-
 .../widgets/slider/slider_render_object.dart  |  14 +--
 forui/lib/src/widgets/slider/thumb.dart       |  22 ++--
 forui/lib/src/widgets/slider/track.dart       |  30 ++---
 forui/pubspec.yaml                            |   4 +-
 .../widgets/slider/slider_golden_test.dart    |   6 +-
 .../test/src/widgets/slider/slider_test.dart  |  32 ++---
 forui_internal_lints/.gitignore               |  29 +++++
 forui_internal_lints/.metadata                |  10 ++
 forui_internal_lints/CHANGELOG.md             |   3 +
 forui_internal_lints/LICENSE                  |   1 +
 forui_internal_lints/README.md                |  39 ++++++
 forui_internal_lints/analysis_options.yaml    |   9 ++
 .../lib/forui_internal_lints.dart             |  17 +++
 .../lib/src/diagnosticable_styles.dart        |  32 +++++
 ...refer_specific_diagnostics_properties.dart | 112 ++++++++++++++++++
 .../lib/src/prefix_public_types.dart          |  49 ++++++++
 forui_internal_lints/pubspec.yaml             |  65 ++++++++++
 forui_internal_lints/testbed/.gitignore       |  29 +++++
 forui_internal_lints/testbed/.metadata        |  10 ++
 forui_internal_lints/testbed/README.md        |   1 +
 .../testbed/analysis_options.yaml             |   6 +
 .../lib/src/diagnosticable_styles.dart        |  13 ++
 .../lib/src/prefix_public_types/class.dart    |  21 ++++
 .../lib/src/prefix_public_types/enum.dart     |  20 ++++
 .../src/prefix_public_types/extension.dart    |  21 ++++
 .../prefix_public_types/extension_type.dart   |  21 ++++
 .../lib/src/prefix_public_types/mixin.dart    |  21 ++++
 .../src/prefix_public_types/type_alias.dart   |  21 ++++
 forui_internal_lints/testbed/pubspec.yaml     |  59 +++++++++
 samples/lib/widgets/slider.dart               |   2 +-
 41 files changed, 698 insertions(+), 118 deletions(-)
 create mode 100644 forui_internal_lints/.gitignore
 create mode 100644 forui_internal_lints/.metadata
 create mode 100644 forui_internal_lints/CHANGELOG.md
 create mode 100644 forui_internal_lints/LICENSE
 create mode 100644 forui_internal_lints/README.md
 create mode 100644 forui_internal_lints/analysis_options.yaml
 create mode 100644 forui_internal_lints/lib/forui_internal_lints.dart
 create mode 100644 forui_internal_lints/lib/src/diagnosticable_styles.dart
 create mode 100644 forui_internal_lints/lib/src/prefer_specific_diagnostics_properties.dart
 create mode 100644 forui_internal_lints/lib/src/prefix_public_types.dart
 create mode 100644 forui_internal_lints/pubspec.yaml
 create mode 100644 forui_internal_lints/testbed/.gitignore
 create mode 100644 forui_internal_lints/testbed/.metadata
 create mode 100644 forui_internal_lints/testbed/README.md
 create mode 100644 forui_internal_lints/testbed/analysis_options.yaml
 create mode 100644 forui_internal_lints/testbed/lib/src/diagnosticable_styles.dart
 create mode 100644 forui_internal_lints/testbed/lib/src/prefix_public_types/class.dart
 create mode 100644 forui_internal_lints/testbed/lib/src/prefix_public_types/enum.dart
 create mode 100644 forui_internal_lints/testbed/lib/src/prefix_public_types/extension.dart
 create mode 100644 forui_internal_lints/testbed/lib/src/prefix_public_types/extension_type.dart
 create mode 100644 forui_internal_lints/testbed/lib/src/prefix_public_types/mixin.dart
 create mode 100644 forui_internal_lints/testbed/lib/src/prefix_public_types/type_alias.dart
 create mode 100644 forui_internal_lints/testbed/pubspec.yaml

diff --git a/docs/pages/docs/form/slider.mdx b/docs/pages/docs/form/slider.mdx
index c75764f76..fb115b952 100644
--- a/docs/pages/docs/form/slider.mdx
+++ b/docs/pages/docs/form/slider.mdx
@@ -31,7 +31,7 @@ An input where the user selects a value from within a given range.
 
 ```dart
 FSlider(
-  layout: Layout.rtl,
+  layout: FLayout.rtl,
   tooltipBuilder: (style, value) => Text('${(value.toStringAsFixed(2)}%'),
   controller: FContinuousSliderController(
     allowedInteraction: FSliderInteraction.tap,
@@ -231,7 +231,7 @@ describes the mark's value.
         FSlider(
           label: const Text('Volume'),
           description: const Text('Adjust the volume by dragging the slider.'),
-          layout: Layout.btt,
+          layout: FLayout.btt,
           controller: FContinuousSliderController(selection: FSliderSelection(max: 0.35)),
           trackMainAxisExtent: 350,
           marks: const [
diff --git a/forui/.gitignore b/forui/.gitignore
index 4e0566141..efb7b56ef 100644
--- a/forui/.gitignore
+++ b/forui/.gitignore
@@ -32,3 +32,4 @@ build/
 test/golden/failures/
 test/**/*_test.mocks.dart
 /.temp/
+custom_lint.log
diff --git a/forui/CHANGELOG.md b/forui/CHANGELOG.md
index 6505e7c0c..7c9f88a49 100644
--- a/forui/CHANGELOG.md
+++ b/forui/CHANGELOG.md
@@ -38,6 +38,10 @@
 
 * Change `FSelectMenuTile` to be scrollable.
 
+* Change `ThemeBuildContext` to `FThemeBuildContext`.
+
+* **Breaking** Change `Layout` to `FLayout`.
+
 * **Breaking** Change `FTileData.index` to `FTileData.last`.
 
 * **Breaking** Change `FPopoverMenu.controller` to `FPopoverMenu.popoverController`.
diff --git a/forui/README.md b/forui/README.md
index 2ee9c67ef..3287df86f 100644
--- a/forui/README.md
+++ b/forui/README.md
@@ -1,41 +1,3 @@
-<a href="https://forui.dev">
-  <h1 align="center">
-    <img width="400" alt="Forui" src="https://raw.githubusercontent.com/forus-labs/forui/main/docs/public/light_logo.png">
-  </h1>
-</a>
+# Forui Internal Lints
 
-<p align="center">
-  <a href="https://github.com/forus-labs/forui/actions/workflows/forui_build.yaml"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/forus-labs/forui/forui_build.yaml?branch=main&style=flat&logo=github&label=main"></a>
-  <a href="https://pub.dev/packages/forui"><img alt="Pub Version" src="https://img.shields.io/pub/v/forui?style=flat&logo=dart&label=pub.dev&color=00589B"></a>
-  <a href="https://github.com/forus-labs/forui"><img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/forus-labs/forui?style=flat&logo=github&color=8957e5&link=https%3A%2F%2Fgithub.com%2Fforus-labs%2Fforui"></a>
-  <a href="https://github.com/forus-labs/forui"><img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/forus-labs/forui?style=flat&logo=github"></a>
-  <a href="https://discord.gg/jrw3qHksjE"><img alt="Discord" src="https://img.shields.io/discord/1268920771062009886?logo=discord&logoColor=fff&label=discord&color=%237289da"></a>
-</p>
-
-<p align="center">
-  <a href="https://forui.dev/docs">πŸ“š Documentation</a> β€’
-  <a href="https://forui.dev/docs/layout/divider">πŸ–ΌοΈ Widgets</a> β€’
-  <a href="https://pub.dev/documentation/forui">πŸ€“ API Reference</a> β€’
-  <a href="https://github.com/orgs/forus-labs/projects/9">πŸ—ΊοΈ Road Map</a>
-</p>
-
-<p align="center">
-  Forui is a Flutter UI library that provides a set of beautifully designed, minimalistic widgets.
-</p>
-
-<br />
-<div align="center">
- <img width="800" alt="Forui" src="https://raw.githubusercontent.com/forus-labs/forui/main/docs/public/banner-160724.png">
-</div>
-
-## Documentation
-
-Visit [forui.dev/docs](https://forui.dev/docs) to view the documentation.
-
-## Contributing
-
-Please read the [contributing guide](https://github.com/forus-labs/forui/blob/main/CONTRIBUTING.md).
-
-## License
-
-Licensed under the [MIT License](https://github.com/forus-labs/forui/blob/main/forui/LICENSE) and [Open Font License](https://github.com/forus-labs/forui/blob/main/forui/LICENSE).
\ No newline at end of file
+Internal Lints used by the Forui project. Not intended for public use.
\ No newline at end of file
diff --git a/forui/analysis_options.yaml b/forui/analysis_options.yaml
index 61f85845a..5de2367a6 100644
--- a/forui/analysis_options.yaml
+++ b/forui/analysis_options.yaml
@@ -1,9 +1,11 @@
 include: package:flint/analysis_options.flutter.yaml
 analyzer:
+  plugins:
+    - custom_lint
   errors:
     unused_result: ignore
 
 linter:
   rules:
     - use_key_in_widget_constructors
-    - require_trailing_commas
+    - require_trailing_commas
\ No newline at end of file
diff --git a/forui/example/pubspec.lock b/forui/example/pubspec.lock
index 498cffe37..b35981699 100644
--- a/forui/example/pubspec.lock
+++ b/forui/example/pubspec.lock
@@ -236,10 +236,10 @@ packages:
     dependency: transitive
     description:
       name: flutter_svg
-      sha256: "936d9c1c010d3e234d1672574636f3352b4941ca3decaddd3cafaeb9ad49c471"
+      sha256: "54900a1a1243f3c4a5506d853a2b5c2dbc38d5f27e52a52618a8054401431123"
       url: "https://pub.dev"
     source: hosted
-    version: "2.0.15"
+    version: "2.0.16"
   flutter_test:
     dependency: "direct dev"
     description: flutter
@@ -501,18 +501,18 @@ packages:
     dependency: transitive
     description:
       name: path_provider_android
-      sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a
+      sha256: "8c4967f8b7cb46dc914e178daa29813d83ae502e0529d7b0478330616a691ef7"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.12"
+    version: "2.2.14"
   path_provider_foundation:
     dependency: transitive
     description:
       name: path_provider_foundation
-      sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
+      sha256: "4843174df4d288f5e29185bd6e72a6fbdf5a4a4602717eed565497429f179942"
       url: "https://pub.dev"
     source: hosted
-    version: "2.4.0"
+    version: "2.4.1"
   path_provider_linux:
     dependency: transitive
     description:
@@ -714,10 +714,10 @@ packages:
     dependency: transitive
     description:
       name: vector_graphics_compiler
-      sha256: ab9ff38fc771e9ee1139320adbe3d18a60327370c218c60752068ebee4b49ab1
+      sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad"
       url: "https://pub.dev"
     source: hosted
-    version: "1.1.15"
+    version: "1.1.16"
   vector_math:
     dependency: transitive
     description:
@@ -786,10 +786,10 @@ packages:
     dependency: transitive
     description:
       name: win32
-      sha256: "84ba388638ed7a8cb3445a320c8273136ab2631cd5f2c57888335504ddab1bc2"
+      sha256: "8b338d4486ab3fbc0ba0db9f9b4f5239b6697fcee427939a40e720cbb9ee0a69"
       url: "https://pub.dev"
     source: hosted
-    version: "5.8.0"
+    version: "5.9.0"
   xdg_directories:
     dependency: transitive
     description:
diff --git a/forui/lib/src/foundation/rendering.dart b/forui/lib/src/foundation/rendering.dart
index 736256478..62e9e6049 100644
--- a/forui/lib/src/foundation/rendering.dart
+++ b/forui/lib/src/foundation/rendering.dart
@@ -3,7 +3,7 @@ import 'package:flutter/rendering.dart';
 import 'package:meta/meta.dart';
 
 /// Possible way to layout a sequence of items.
-enum Layout {
+enum FLayout {
   /// Lays out the items horizontally from left to right.
   ltr(vertical: false),
 
@@ -19,7 +19,7 @@ enum Layout {
   /// Whether the layout is vertical.
   final bool vertical;
 
-  const Layout({required this.vertical});
+  const FLayout({required this.vertical});
 }
 
 @internal
diff --git a/forui/lib/src/theme/theme.dart b/forui/lib/src/theme/theme.dart
index 66fd7d208..a83df7636 100644
--- a/forui/lib/src/theme/theme.dart
+++ b/forui/lib/src/theme/theme.dart
@@ -8,7 +8,7 @@ import 'package:forui/forui.dart';
 /// Applies a theme to descendant widgets.
 ///
 /// A theme configures the colors and typographic choices of Forui widgets. The actual configuration is stored in
-/// a [FThemeData]. Descendant widgets obtain the current theme's [FThemeData] via either [ThemeBuildContext.theme],
+/// a [FThemeData]. Descendant widgets obtain the current theme's [FThemeData] via either [FThemeBuildContext.theme],
 /// or [FTheme.of]. When a widget uses either, it is automatically rebuilt if the theme later changes.
 ///
 /// ```dart
@@ -35,7 +35,7 @@ import 'package:forui/forui.dart';
 class FTheme extends StatelessWidget {
   /// Returns the current [FThemeData], or `FThemes.zinc.light` if there is no ancestor [FTheme].
   ///
-  /// It is recommended to use the terser [ThemeBuildContext.theme] getter instead.
+  /// It is recommended to use the terser [FThemeBuildContext.theme] getter instead.
   ///
   /// ## Troubleshooting:
   ///
@@ -141,7 +141,7 @@ class _InheritedTheme extends InheritedTheme {
 }
 
 /// Provides functions for accessing the current [FThemeData].
-extension ThemeBuildContext on BuildContext {
+extension FThemeBuildContext on BuildContext {
   /// Returns the current [FThemeData], or `FThemes.zinc.light` if there is no ancestor [FTheme].
   ///
   /// ## Troubleshooting:
diff --git a/forui/lib/src/widgets/slider/inherited_data.dart b/forui/lib/src/widgets/slider/inherited_data.dart
index 533525716..da4cfa686 100644
--- a/forui/lib/src/widgets/slider/inherited_data.dart
+++ b/forui/lib/src/widgets/slider/inherited_data.dart
@@ -15,7 +15,7 @@ final class InheritedData extends InheritedWidget {
   }
 
   final FSliderStyle style;
-  final Layout layout;
+  final FLayout layout;
   final List<FSliderMark> marks;
   final double? trackMainAxisExtent;
   final double? trackHitRegionCrossExtent;
diff --git a/forui/lib/src/widgets/slider/slider.dart b/forui/lib/src/widgets/slider/slider.dart
index f4890e0ce..c90e3cbe2 100644
--- a/forui/lib/src/widgets/slider/slider.dart
+++ b/forui/lib/src/widgets/slider/slider.dart
@@ -40,7 +40,7 @@ class FSlider extends StatelessWidget {
   final FSliderStyle? style;
 
   /// The layout. Defaults to the current [TextDirection].
-  final Layout? layout;
+  final FLayout? layout;
 
   /// The label.
   final Widget? label;
@@ -158,8 +158,8 @@ class FSlider extends StatelessWidget {
     final styles = context.theme.sliderStyles;
     final layout = switch (this.layout) {
       final layout? => layout,
-      _ when Directionality.maybeOf(context) == TextDirection.rtl => Layout.rtl,
-      _ => Layout.ltr,
+      _ when Directionality.maybeOf(context) == TextDirection.rtl => FLayout.rtl,
+      _ => FLayout.ltr,
     };
     final sliderStyle = style ?? (layout.vertical ? styles.verticalStyle : styles.horizontalStyle);
 
@@ -219,7 +219,7 @@ class FSlider extends StatelessWidget {
 class _Slider extends StatefulWidget {
   final FSliderController controller;
   final FSliderStyle style;
-  final Layout layout;
+  final FLayout layout;
   final Widget? label;
   final Widget? description;
   final Widget Function(BuildContext, String) errorBuilder;
diff --git a/forui/lib/src/widgets/slider/slider_mark.dart b/forui/lib/src/widgets/slider/slider_mark.dart
index 797e6f8c3..c1ad73f79 100644
--- a/forui/lib/src/widgets/slider/slider_mark.dart
+++ b/forui/lib/src/widgets/slider/slider_mark.dart
@@ -75,7 +75,7 @@ final class FSliderMarkStyle with Diagnosticable {
   /// The label's offset from the slider, along its cross axis, in logical pixels. The top-left corner is always the
   /// origin, regardless of the layout.
   ///
-  /// For example, if the layout is [Layout.ltr] and the cross axis offset is 3, the label will be 3 pixels below the
+  /// For example, if the layout is [FLayout.ltr] and the cross axis offset is 3, the label will be 3 pixels below the
   /// slider's edge.
   ///
   /// ```
diff --git a/forui/lib/src/widgets/slider/slider_render_object.dart b/forui/lib/src/widgets/slider/slider_render_object.dart
index 24caba26b..95ea4a9cc 100644
--- a/forui/lib/src/widgets/slider/slider_render_object.dart
+++ b/forui/lib/src/widgets/slider/slider_render_object.dart
@@ -175,7 +175,7 @@ abstract class _RenderSlider extends RenderBox
     with ContainerRenderObjectMixin<RenderBox, _Data>, RenderBoxContainerDefaultsMixin<RenderBox, _Data> {
   FSliderStyle _style;
   FSliderStateStyle _stateStyle;
-  Layout _layout;
+  FLayout _layout;
   List<FSliderMark> _marks;
   double? _mainAxisExtent;
   late Rect Function(RenderBox, Size, FSliderMark, FSliderMarkStyle) _positionMark;
@@ -237,22 +237,22 @@ abstract class _RenderSlider extends RenderBox
   Rect Function(RenderBox, Size, FSliderMark, FSliderMarkStyle) get _position {
     final insets = _style.labelLayoutStyle.childPadding;
     return switch (_layout) {
-      Layout.ltr => (track, label, mark, style) {
+      FLayout.ltr => (track, label, mark, style) {
           final extent = track.size.width - insets.left - insets.right;
           final offset = _anchor(extent, mark.value, insets.left, insets.top, style);
           return _rect(label, mark, Offset(offset.$1, offset.$2), style);
         },
-      Layout.rtl => (track, size, mark, style) {
+      FLayout.rtl => (track, size, mark, style) {
           final extent = track.size.width - insets.left - insets.right;
           final offset = _anchor(extent, 1 - mark.value, insets.left, insets.top, style);
           return _rect(size, mark, Offset(offset.$1, offset.$2), style);
         },
-      Layout.ttb => (track, size, mark, style) {
+      FLayout.ttb => (track, size, mark, style) {
           final extent = track.size.height - insets.top - insets.bottom;
           final offset = _anchor(extent, mark.value, insets.top, insets.left, style);
           return _rect(size, mark, Offset(offset.$2, offset.$1), style);
         },
-      Layout.btt => (track, size, mark, style) {
+      FLayout.btt => (track, size, mark, style) {
           final extent = track.size.height - insets.top - insets.bottom;
           final offset = _anchor(extent, 1 - mark.value, insets.top, insets.left, style);
           return _rect(size, mark, Offset(offset.$2, offset.$1), style);
@@ -332,9 +332,9 @@ abstract class _RenderSlider extends RenderBox
     markNeedsLayout();
   }
 
-  Layout get sliderLayout => _layout;
+  FLayout get sliderLayout => _layout;
 
-  set sliderLayout(Layout value) {
+  set sliderLayout(FLayout value) {
     if (_layout == value) {
       return;
     }
diff --git a/forui/lib/src/widgets/slider/thumb.dart b/forui/lib/src/widgets/slider/thumb.dart
index 395e87118..d32131bad 100644
--- a/forui/lib/src/widgets/slider/thumb.dart
+++ b/forui/lib/src/widgets/slider/thumb.dart
@@ -186,26 +186,26 @@ class _ThumbState extends State<Thumb> with SingleTickerProviderStateMixin {
 
   double _offset(FSliderSelection selection) => widget.min ? selection.offset.min : selection.offset.max;
 
-  Map<ShortcutActivator, Intent> _shortcuts(Layout layout) => switch ((layout, widget.min)) {
-        (Layout.ltr, true) || (Layout.rtl, false) => const {
+  Map<ShortcutActivator, Intent> _shortcuts(FLayout layout) => switch ((layout, widget.min)) {
+        (FLayout.ltr, true) || (FLayout.rtl, false) => const {
             SingleActivator(LogicalKeyboardKey.arrowLeft): _ExtendIntent(),
             SingleActivator(LogicalKeyboardKey.arrowRight): _ShrinkIntent(),
           },
-        (Layout.ltr, false) || (Layout.rtl, true) => const {
+        (FLayout.ltr, false) || (FLayout.rtl, true) => const {
             SingleActivator(LogicalKeyboardKey.arrowLeft): _ShrinkIntent(),
             SingleActivator(LogicalKeyboardKey.arrowRight): _ExtendIntent(),
           },
-        (Layout.ttb, true) || (Layout.btt, false) => const {
+        (FLayout.ttb, true) || (FLayout.btt, false) => const {
             SingleActivator(LogicalKeyboardKey.arrowUp): _ExtendIntent(),
             SingleActivator(LogicalKeyboardKey.arrowDown): _ShrinkIntent(),
           },
-        (Layout.ttb, false) || (Layout.btt, true) => const {
+        (FLayout.ttb, false) || (FLayout.btt, true) => const {
             SingleActivator(LogicalKeyboardKey.arrowUp): _ShrinkIntent(),
             SingleActivator(LogicalKeyboardKey.arrowDown): _ExtendIntent(),
           },
       };
 
-  GestureDragUpdateCallback? _drag(FSliderController controller, double thumbSize, Layout layout) {
+  GestureDragUpdateCallback? _drag(FSliderController controller, double thumbSize, FLayout layout) {
     if (controller.allowedInteraction == FSliderInteraction.tap) {
       return null;
     }
@@ -297,11 +297,11 @@ final class FSliderThumbStyle with Diagnosticable {
 }
 
 @internal
-extension Layouts on Layout {
+extension Layouts on FLayout {
   double Function(Offset) translateThumbDrag(double thumbSize) => switch (this) {
-        Layout.ltr => (delta) => delta.dx - thumbSize / 2,
-        Layout.rtl => (delta) => -delta.dx + thumbSize / 2,
-        Layout.ttb => (delta) => delta.dy - thumbSize / 2,
-        Layout.btt => (delta) => -delta.dy + thumbSize / 2,
+        FLayout.ltr => (delta) => delta.dx - thumbSize / 2,
+        FLayout.rtl => (delta) => -delta.dx + thumbSize / 2,
+        FLayout.ttb => (delta) => delta.dy - thumbSize / 2,
+        FLayout.btt => (delta) => -delta.dy + thumbSize / 2,
       };
 }
diff --git a/forui/lib/src/widgets/slider/track.dart b/forui/lib/src/widgets/slider/track.dart
index d56b15fe1..1d6667b1b 100644
--- a/forui/lib/src/widgets/slider/track.dart
+++ b/forui/lib/src/widgets/slider/track.dart
@@ -122,7 +122,7 @@ class _GestureDetectorState extends State<_GestureDetector> {
     }
   }
 
-  GestureTapDownCallback? _tap(FSliderController controller, double thumbSize, Layout layout) {
+  GestureTapDownCallback? _tap(FSliderController controller, double thumbSize, FLayout layout) {
     final translate = layout.translateTrackTap(controller.selection.rawExtent.total, thumbSize);
 
     void down(TapDownDetails details) {
@@ -144,7 +144,7 @@ class _GestureDetectorState extends State<_GestureDetector> {
     return tappable.contains(controller.allowedInteraction) ? down : null;
   }
 
-  GestureDragUpdateCallback? _drag(FSliderController controller, Layout layout) {
+  GestureDragUpdateCallback? _drag(FSliderController controller, FLayout layout) {
     if (controller.allowedInteraction != FSliderInteraction.slide) {
       return null;
     }
@@ -242,25 +242,25 @@ class ActiveTrack extends StatelessWidget {
 }
 
 @internal
-extension Layouts on Layout {
+extension Layouts on FLayout {
   double Function(Offset) translateTrackTap(double extent, double thumbSize) => switch (this) {
-        Layout.ltr => (offset) => offset.dx - thumbSize / 2,
-        Layout.rtl => (offset) => extent - offset.dx + thumbSize / 2,
-        Layout.ttb => (offset) => offset.dy - thumbSize / 2,
-        Layout.btt => (offset) => extent - offset.dy + thumbSize / 2,
+        FLayout.ltr => (offset) => offset.dx - thumbSize / 2,
+        FLayout.rtl => (offset) => extent - offset.dx + thumbSize / 2,
+        FLayout.ttb => (offset) => offset.dy - thumbSize / 2,
+        FLayout.btt => (offset) => extent - offset.dy + thumbSize / 2,
       };
 
   double Function(Offset) translateTrackDrag() => switch (this) {
-        Layout.ltr => (delta) => delta.dx,
-        Layout.rtl => (delta) => -delta.dx,
-        Layout.ttb => (delta) => delta.dy,
-        Layout.btt => (delta) => -delta.dy,
+        FLayout.ltr => (delta) => delta.dx,
+        FLayout.rtl => (delta) => -delta.dx,
+        FLayout.ttb => (delta) => delta.dy,
+        FLayout.btt => (delta) => -delta.dy,
       };
 
   Positioned Function({required double offset, required Widget child}) get position => switch (this) {
-        Layout.ltr => ({required offset, required child}) => Positioned(left: offset, child: child),
-        Layout.rtl => ({required offset, required child}) => Positioned(right: offset, child: child),
-        Layout.ttb => ({required offset, required child}) => Positioned(top: offset, child: child),
-        Layout.btt => ({required offset, required child}) => Positioned(bottom: offset, child: child),
+        FLayout.ltr => ({required offset, required child}) => Positioned(left: offset, child: child),
+        FLayout.rtl => ({required offset, required child}) => Positioned(right: offset, child: child),
+        FLayout.ttb => ({required offset, required child}) => Positioned(top: offset, child: child),
+        FLayout.btt => ({required offset, required child}) => Positioned(bottom: offset, child: child),
       };
 }
diff --git a/forui/pubspec.yaml b/forui/pubspec.yaml
index 140eba6eb..90ed6af70 100644
--- a/forui/pubspec.yaml
+++ b/forui/pubspec.yaml
@@ -28,12 +28,14 @@ dependencies:
   nitrogen_types: ^0.3.0+1
   sugar: ^3.1.0
 
-
 dev_dependencies:
   build_runner: ^2.4.0
+  custom_lint: ^0.6.6
   flint: ^2.8.1
   flutter_test:
     sdk: flutter
+  forui_internal_lints:
+    path: ../forui_internal_lints
   http: ^1.2.2
   mockito: ^5.4.4
 
diff --git a/forui/test/src/widgets/slider/slider_golden_test.dart b/forui/test/src/widgets/slider/slider_golden_test.dart
index 9723ea784..b52ea1856 100644
--- a/forui/test/src/widgets/slider/slider_golden_test.dart
+++ b/forui/test/src/widgets/slider/slider_golden_test.dart
@@ -36,7 +36,7 @@ void main() {
     });
 
     for (final theme in TestScaffold.themes) {
-      for (final layout in Layout.values) {
+      for (final layout in FLayout.values) {
         for (final touch in [true, false]) {
           for (final enabled in [true, false]) {
             testWidgets('${theme.name} - $layout - ${enabled ? 'enabled' : 'disabled'}', (tester) async {
@@ -176,7 +176,7 @@ void main() {
       }
     }
 
-    for (final layout in Layout.values) {
+    for (final layout in FLayout.values) {
       for (final min in [true, false]) {
         testWidgets('single value - $layout - ${min ? 'min' : 'max'}', (tester) async {
           await tester.pumpWidget(
@@ -214,7 +214,7 @@ void main() {
       }
     }
 
-    for (final layout in Layout.values) {
+    for (final layout in FLayout.values) {
       group('label offset - $layout', () {
         late FSliderStyle sliderStyle;
         late Alignment positive;
diff --git a/forui/test/src/widgets/slider/slider_test.dart b/forui/test/src/widgets/slider/slider_test.dart
index 71c8feace..ac5a21fc5 100644
--- a/forui/test/src/widgets/slider/slider_test.dart
+++ b/forui/test/src/widgets/slider/slider_test.dart
@@ -116,7 +116,7 @@ void main() {
     });
   });
 
-  for (final layout in Layout.values) {
+  for (final layout in FLayout.values) {
     Widget slider(FSliderController controller) => TestScaffold.app(
           padded: false,
           child: FSlider(
@@ -343,26 +343,26 @@ void main() {
 }
 
 extension on Rect {
-  Offset min(Layout layout) => switch (layout) {
-        Layout.ltr => centerLeft,
-        Layout.rtl => centerRight,
-        Layout.ttb => topCenter,
-        Layout.btt => bottomCenter,
+  Offset min(FLayout layout) => switch (layout) {
+        FLayout.ltr => centerLeft,
+        FLayout.rtl => centerRight,
+        FLayout.ttb => topCenter,
+        FLayout.btt => bottomCenter,
       };
 
-  Offset max(Layout layout) => switch (layout) {
-        Layout.ltr => centerRight,
-        Layout.rtl => centerLeft,
-        Layout.ttb => bottomCenter,
-        Layout.btt => topCenter,
+  Offset max(FLayout layout) => switch (layout) {
+        FLayout.ltr => centerRight,
+        FLayout.rtl => centerLeft,
+        FLayout.ttb => bottomCenter,
+        FLayout.btt => topCenter,
       };
 }
 
-extension on Layout {
+extension on FLayout {
   Offset directional(double value) => switch (this) {
-        Layout.ltr => Offset(value, 0),
-        Layout.rtl => Offset(-value, 0),
-        Layout.ttb => Offset(0, value),
-        Layout.btt => Offset(0, -value),
+        FLayout.ltr => Offset(value, 0),
+        FLayout.rtl => Offset(-value, 0),
+        FLayout.ttb => Offset(0, value),
+        FLayout.btt => Offset(0, -value),
       };
 }
diff --git a/forui_internal_lints/.gitignore b/forui_internal_lints/.gitignore
new file mode 100644
index 000000000..ac5aa9893
--- /dev/null
+++ b/forui_internal_lints/.gitignore
@@ -0,0 +1,29 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+build/
diff --git a/forui_internal_lints/.metadata b/forui_internal_lints/.metadata
new file mode 100644
index 000000000..7025a6406
--- /dev/null
+++ b/forui_internal_lints/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+  revision: "dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668"
+  channel: "stable"
+
+project_type: package
diff --git a/forui_internal_lints/CHANGELOG.md b/forui_internal_lints/CHANGELOG.md
new file mode 100644
index 000000000..41cc7d819
--- /dev/null
+++ b/forui_internal_lints/CHANGELOG.md
@@ -0,0 +1,3 @@
+## 0.0.1
+
+* TODO: Describe initial release.
diff --git a/forui_internal_lints/LICENSE b/forui_internal_lints/LICENSE
new file mode 100644
index 000000000..ba75c69f7
--- /dev/null
+++ b/forui_internal_lints/LICENSE
@@ -0,0 +1 @@
+TODO: Add your license here.
diff --git a/forui_internal_lints/README.md b/forui_internal_lints/README.md
new file mode 100644
index 000000000..4a260d8d2
--- /dev/null
+++ b/forui_internal_lints/README.md
@@ -0,0 +1,39 @@
+<!--
+This README describes the package. If you publish this package to pub.dev,
+this README's contents appear on the landing page for your package.
+
+For information about how to write a good package README, see the guide for
+[writing package pages](https://dart.dev/tools/pub/writing-package-pages).
+
+For general information about developing packages, see the Dart guide for
+[creating packages](https://dart.dev/guides/libraries/create-packages)
+and the Flutter guide for
+[developing packages and plugins](https://flutter.dev/to/develop-packages).
+-->
+
+TODO: Put a short description of the package here that helps potential users
+know whether this package might be useful for them.
+
+## Features
+
+TODO: List what your package can do. Maybe include images, gifs, or videos.
+
+## Getting started
+
+TODO: List prerequisites and provide or point to information on how to
+start using the package.
+
+## Usage
+
+TODO: Include short and useful examples for package users. Add longer examples
+to `/example` folder.
+
+```dart
+const like = 'sample';
+```
+
+## Additional information
+
+TODO: Tell users more about the package: where to find more information, how to
+contribute to the package, how to file issues, what response they can expect
+from the package authors, and more.
diff --git a/forui_internal_lints/analysis_options.yaml b/forui_internal_lints/analysis_options.yaml
new file mode 100644
index 000000000..61f85845a
--- /dev/null
+++ b/forui_internal_lints/analysis_options.yaml
@@ -0,0 +1,9 @@
+include: package:flint/analysis_options.flutter.yaml
+analyzer:
+  errors:
+    unused_result: ignore
+
+linter:
+  rules:
+    - use_key_in_widget_constructors
+    - require_trailing_commas
diff --git a/forui_internal_lints/lib/forui_internal_lints.dart b/forui_internal_lints/lib/forui_internal_lints.dart
new file mode 100644
index 000000000..948b78472
--- /dev/null
+++ b/forui_internal_lints/lib/forui_internal_lints.dart
@@ -0,0 +1,17 @@
+import 'package:custom_lint_builder/custom_lint_builder.dart';
+
+import 'package:forui_internal_lints/src/diagnosticable_styles.dart';
+import 'package:forui_internal_lints/src/prefer_specific_diagnostics_properties.dart';
+import 'package:forui_internal_lints/src/prefix_public_types.dart';
+
+/// Creates a linter for Forui,
+PluginBase createPlugin() => _ForuiLinter();
+
+class _ForuiLinter extends PluginBase {
+  @override
+  List<LintRule> getLintRules(CustomLintConfigs configs) => const [
+        DiagnosticableStylesRule(),
+        PreferSpecificDiagnosticsProperties(),
+        PrefixPublicTypesRule(),
+      ];
+}
diff --git a/forui_internal_lints/lib/src/diagnosticable_styles.dart b/forui_internal_lints/lib/src/diagnosticable_styles.dart
new file mode 100644
index 000000000..87cafa46b
--- /dev/null
+++ b/forui_internal_lints/lib/src/diagnosticable_styles.dart
@@ -0,0 +1,32 @@
+import 'package:analyzer/error/listener.dart';
+import 'package:custom_lint_builder/custom_lint_builder.dart';
+
+const _code = LintCode(
+  name: 'diagnosticable_styles',
+  problemMessage: 'Style(s) should be assignable to Diagnosticable.',
+);
+
+const _suffixes = {'Style', 'Styles'};
+
+const _checker = TypeChecker.fromName('Diagnosticable', packageName: 'flutter');
+
+/// A lint rule that checks if a class ending with 'Style' or 'Styles' is assignable to Diagnosticable.
+class DiagnosticableStylesRule extends DartLintRule {
+  /// Creates a new [DiagnosticableStylesRule].
+  const DiagnosticableStylesRule() : super(code: _code);
+
+  @override
+  void run(CustomLintResolver resolver, ErrorReporter reporter, CustomLintContext context) {
+    context.registry.addClassDeclaration((node) {
+      final declared = node.declaredElement;
+
+      if (declared?.name case final name? when _suffixes.every((s) => !name.endsWith(s))) {
+        return;
+      }
+
+      if (declared case final declared? when declared.isConstructable && !_checker.isAssignableFrom(declared)) {
+        reporter.atElement(declared, _code);
+      }
+    });
+  }
+}
diff --git a/forui_internal_lints/lib/src/prefer_specific_diagnostics_properties.dart b/forui_internal_lints/lib/src/prefer_specific_diagnostics_properties.dart
new file mode 100644
index 000000000..9f08cec3b
--- /dev/null
+++ b/forui_internal_lints/lib/src/prefer_specific_diagnostics_properties.dart
@@ -0,0 +1,112 @@
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:custom_lint_builder/custom_lint_builder.dart';
+
+const _code = LintCode(
+  name: 'prefer_specific_diagnostics_properties',
+  problemMessage:
+      'Prefer specific diagnostic properties for colors, enums, functions, iterables, primitives and icons.',
+);
+
+const _diagnosticsProperty = TypeChecker.fromName('DiagnosticsProperty', packageName: 'flutter');
+
+const _bool = TypeChecker.fromName('bool');
+const _double = TypeChecker.fromName('double');
+const _iconData = TypeChecker.fromName('IconData', packageName: 'flutter');
+const _int = TypeChecker.fromName('int');
+const _string = TypeChecker.fromName('String');
+
+const _exact = TypeChecker.any([
+  _bool,
+  _double,
+  _iconData,
+  _int,
+  _string,
+]);
+
+const _color = TypeChecker.fromName('Color', packageName: 'flutter');
+const _iterable = TypeChecker.fromName('Iterable');
+
+/// A lint rule that checks if a DiagnosticsProperty is created with a type.
+class PreferSpecificDiagnosticsProperties extends DartLintRule {
+  /// Creates a new [PreferSpecificDiagnosticsProperties].
+  const PreferSpecificDiagnosticsProperties() : super(code: _code);
+
+  @override
+  void run(CustomLintResolver resolver, ErrorReporter reporter, CustomLintContext context) {
+    context.registry.addInstanceCreationExpression((node) {
+      if (node.staticType case final type when type == null || !_diagnosticsProperty.isExactlyType(type)) {
+        return;
+      }
+
+      if (node.argumentList.length < 2) {
+        return;
+      }
+
+      final type = node.argumentList.arguments[1].staticType;
+      if (type == null) {
+        return;
+      }
+
+      if (_exact.isExactlyType(type) ||
+          type.isDartCoreEnum ||
+          type.isDartCoreFunction ||
+          _color.isAssignableFromType(type) ||
+          _iterable.isAssignableFromType(type)) {
+        reporter.atNode(node, _code);
+      }
+    });
+  }
+
+  @override
+  List<DartFix> getFixes() => [_Fix()];
+}
+
+class _Fix extends DartFix {
+  @override
+  void run(
+    CustomLintResolver resolver,
+    ChangeReporter reporter,
+    CustomLintContext context,
+    AnalysisError analysisError,
+    List<AnalysisError> others,
+  ) {
+    context.registry.addInstanceCreationExpression((node) {
+      if (!node.sourceRange.intersects(analysisError.sourceRange)) {
+        return;
+      }
+
+      final type = node.staticType; // DiagnosticsProperty.lazy is not supported.
+      if (type == null || node.constructorName.name != null) {
+        return;
+      }
+
+      reporter
+          .createChangeBuilder(message: 'Use specific DiagnosticsProperties.', priority: 100)
+          .addDartFileEdit((builder) {
+        switch (type) {
+          // FlagProperty (bool) is not supported.
+          case _ when _double.isExactlyType(type):
+            // It may be more appropriate to use a PercentageProperty but there is no simple way to infer that.
+            builder.addSimpleReplacement(node.constructorName.sourceRange, 'DoubleProperty');
+          case _ when _int.isExactlyType(type):
+            builder.addSimpleReplacement(node.constructorName.sourceRange, 'IntProperty');
+          case _ when _string.isExactlyType(type):
+            builder.addSimpleReplacement(node.constructorName.sourceRange, 'StringProperty');
+          case _ when _iconData.isExactlyType(type):
+            builder.addSimpleReplacement(node.constructorName.sourceRange, 'IconDataProperty');
+
+          case _ when type.isDartCoreEnum:
+            builder.addSimpleReplacement(node.constructorName.sourceRange, 'EnumProperty');
+          case _ when type.isDartCoreFunction:
+            builder.addSimpleReplacement(node.constructorName.sourceRange, 'ObjectFlagProperty.has');
+
+          case _ when _color.isAssignableFromType(type):
+            builder.addSimpleReplacement(node.constructorName.sourceRange, 'ColorProperty');
+          case _ when _iterable.isAssignableFromType(type):
+            builder.addSimpleReplacement(node.constructorName.sourceRange, 'IterableProperty');
+        }
+      });
+    });
+  }
+}
diff --git a/forui_internal_lints/lib/src/prefix_public_types.dart b/forui_internal_lints/lib/src/prefix_public_types.dart
new file mode 100644
index 000000000..51c57b30d
--- /dev/null
+++ b/forui_internal_lints/lib/src/prefix_public_types.dart
@@ -0,0 +1,49 @@
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:collection/collection.dart';
+import 'package:custom_lint_builder/custom_lint_builder.dart';
+
+const _code = LintCode(
+  name: 'prefix_public_types',
+  problemMessage: 'Public types should be prefixed with F.',
+);
+
+const _checker = TypeChecker.fromName('internal', packageName: 'meta');
+
+/// A lint rule that checks if a public type is prefixed with F.
+class PrefixPublicTypesRule extends DartLintRule {
+  /// Creates a new [PrefixPublicTypesRule].
+  const PrefixPublicTypesRule() : super(code: _code);
+
+  @override
+  void run(CustomLintResolver resolver, ErrorReporter reporter, CustomLintContext context) {
+    void check(NodeList<Annotation> annotations, Element? element) {
+      if (element?.source?.fullName case final name? when name.contains('test/src')) {
+        return;
+      }
+
+      if (annotations.map((a) => a.element).whereNotNull().any(_checker.isAssignableFrom)) {
+        return;
+      }
+
+      if (element == null || element.isPrivate || element.isSynthetic) {
+        return;
+      }
+
+      if (element.name case final name? when RegExp('^F[A-Z].*').matchAsPrefix(name) != null) {
+        return;
+      }
+
+      reporter.atElement(element, _code);
+    }
+
+    context.registry
+      ..addClassDeclaration((node) => check(node.metadata, node.declaredElement))
+      ..addEnumDeclaration((node) => check(node.metadata, node.declaredElement))
+      ..addMixinDeclaration((node) => check(node.metadata, node.declaredElement))
+      ..addExtensionDeclaration((node) => check(node.metadata, node.declaredElement))
+      ..addExtensionTypeDeclaration((node) => check(node.metadata, node.declaredElement))
+      ..addTypeAlias((node) => check(node.metadata, node.declaredElement));
+  }
+}
diff --git a/forui_internal_lints/pubspec.yaml b/forui_internal_lints/pubspec.yaml
new file mode 100644
index 000000000..847a781e7
--- /dev/null
+++ b/forui_internal_lints/pubspec.yaml
@@ -0,0 +1,65 @@
+name: forui_internal_lints
+description: Internal lints used by Forui. Not intended for public use.
+version: 0.7.0
+homepage: https://forui.dev/
+documentation: https://forui.dev/docs
+repository: https://github.com/forus-labs/forui/tree/main/forui_lints
+issue_tracker: https://github.com/forus-labs/forui/issues
+publish_to: 'none'
+
+environment:
+  sdk: ">=3.5.0 <4.0.0"
+  flutter: ">=3.24.0"
+
+dependencies:
+  analyzer: any
+  analyzer_plugin: any
+  collection: ^1.18.0
+  custom_lint_builder: ^0.6.6
+  flutter:
+    sdk: flutter
+
+dev_dependencies:
+  flint: ^2.8.1
+  flutter_test:
+    sdk: flutter
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+
+  # To add assets to your package, add an assets section, like this:
+  # assets:
+  #   - images/a_dot_burr.jpeg
+  #   - images/a_dot_ham.jpeg
+  #
+  # For details regarding assets in packages, see
+  # https://flutter.dev/to/asset-from-package
+  #
+  # An image asset can refer to one or more resolution-specific "variants", see
+  # https://flutter.dev/to/resolution-aware-images
+
+  # To add custom fonts to your package, add a fonts section here,
+  # in this "flutter" section. Each entry in this list should have a
+  # "family" key with the font family name, and a "fonts" key with a
+  # list giving the asset and other descriptors for the font. For
+  # example:
+  # fonts:
+  #   - family: Schyler
+  #     fonts:
+  #       - asset: fonts/Schyler-Regular.ttf
+  #       - asset: fonts/Schyler-Italic.ttf
+  #         style: italic
+  #   - family: Trajan Pro
+  #     fonts:
+  #       - asset: fonts/TrajanPro.ttf
+  #       - asset: fonts/TrajanPro_Bold.ttf
+  #         weight: 700
+  #
+  # For details regarding fonts in packages, see
+  # https://flutter.dev/to/font-from-package
+
+import_sorter:
+  comments: false
diff --git a/forui_internal_lints/testbed/.gitignore b/forui_internal_lints/testbed/.gitignore
new file mode 100644
index 000000000..ac5aa9893
--- /dev/null
+++ b/forui_internal_lints/testbed/.gitignore
@@ -0,0 +1,29 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
+/pubspec.lock
+**/doc/api/
+.dart_tool/
+build/
diff --git a/forui_internal_lints/testbed/.metadata b/forui_internal_lints/testbed/.metadata
new file mode 100644
index 000000000..7025a6406
--- /dev/null
+++ b/forui_internal_lints/testbed/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+  revision: "dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668"
+  channel: "stable"
+
+project_type: package
diff --git a/forui_internal_lints/testbed/README.md b/forui_internal_lints/testbed/README.md
new file mode 100644
index 000000000..5cfd4fc7c
--- /dev/null
+++ b/forui_internal_lints/testbed/README.md
@@ -0,0 +1 @@
+Tests for the `forui_internal_lints` package.
\ No newline at end of file
diff --git a/forui_internal_lints/testbed/analysis_options.yaml b/forui_internal_lints/testbed/analysis_options.yaml
new file mode 100644
index 000000000..ffc2f9f18
--- /dev/null
+++ b/forui_internal_lints/testbed/analysis_options.yaml
@@ -0,0 +1,6 @@
+analyzer:
+  plugins:
+    - custom_lint
+  errors:
+    unused_result: ignore
+    unused_element: ignore
diff --git a/forui_internal_lints/testbed/lib/src/diagnosticable_styles.dart b/forui_internal_lints/testbed/lib/src/diagnosticable_styles.dart
new file mode 100644
index 000000000..0a321ab0e
--- /dev/null
+++ b/forui_internal_lints/testbed/lib/src/diagnosticable_styles.dart
@@ -0,0 +1,13 @@
+import 'package:flutter/foundation.dart';
+
+class FGood {}
+
+class FGoodStyle with Diagnosticable {}
+
+class FGoodStyles with Diagnosticable {}
+
+// expect_lint: diagnosticable_styles
+class FBadStyle {}
+
+// expect_lint: diagnosticable_styles
+class FBadStyles {}
\ No newline at end of file
diff --git a/forui_internal_lints/testbed/lib/src/prefix_public_types/class.dart b/forui_internal_lints/testbed/lib/src/prefix_public_types/class.dart
new file mode 100644
index 000000000..9987300b8
--- /dev/null
+++ b/forui_internal_lints/testbed/lib/src/prefix_public_types/class.dart
@@ -0,0 +1,21 @@
+// ignore_for_file: unused_element
+
+import 'package:meta/meta.dart';
+
+class _Good {}
+
+@internal
+class GoodSingle {}
+
+@internal
+@visibleForTesting
+class GoodMultiple {}
+
+class FGood {}
+
+// expect_lint: prefix_public_types
+class Bad {}
+
+// expect_lint: prefix_public_types
+class Fbad {}
+
diff --git a/forui_internal_lints/testbed/lib/src/prefix_public_types/enum.dart b/forui_internal_lints/testbed/lib/src/prefix_public_types/enum.dart
new file mode 100644
index 000000000..afb786fa6
--- /dev/null
+++ b/forui_internal_lints/testbed/lib/src/prefix_public_types/enum.dart
@@ -0,0 +1,20 @@
+// ignore_for_file: unused_element, unused_field
+
+import 'package:meta/meta.dart';
+
+enum _Good { foo }
+
+@internal
+enum GoodSingle { foo }
+
+@internal
+@visibleForTesting
+enum GoodMultiple { foo }
+
+enum FGood { foo }
+
+// expect_lint: prefix_public_types
+enum Bad { foo }
+
+// expect_lint: prefix_public_types
+enum Fbad { foo }
diff --git a/forui_internal_lints/testbed/lib/src/prefix_public_types/extension.dart b/forui_internal_lints/testbed/lib/src/prefix_public_types/extension.dart
new file mode 100644
index 000000000..59816aac1
--- /dev/null
+++ b/forui_internal_lints/testbed/lib/src/prefix_public_types/extension.dart
@@ -0,0 +1,21 @@
+// ignore_for_file: unused_element
+
+import 'package:meta/meta.dart';
+
+extension _Good on Never {}
+
+@internal
+extension GoodSingle on Never {}
+
+@internal
+@visibleForTesting
+extension GoodMultiple on Never {}
+
+extension FGood on Never {}
+
+// expect_lint: prefix_public_types
+extension Bad on Never {}
+
+// expect_lint: prefix_public_types
+extension Fbad on Never {}
+
diff --git a/forui_internal_lints/testbed/lib/src/prefix_public_types/extension_type.dart b/forui_internal_lints/testbed/lib/src/prefix_public_types/extension_type.dart
new file mode 100644
index 000000000..f5f01e7ed
--- /dev/null
+++ b/forui_internal_lints/testbed/lib/src/prefix_public_types/extension_type.dart
@@ -0,0 +1,21 @@
+// ignore_for_file: unused_element
+
+import 'package:meta/meta.dart';
+
+extension type _Good(int i) {}
+
+@internal
+extension type GoodSingle(int i) {}
+
+@internal
+@visibleForTesting
+extension type GoodMultiple(int i) {}
+
+extension type FGood(int i) {}
+
+// expect_lint: prefix_public_types
+extension type Bad(int i) {}
+
+// expect_lint: prefix_public_types
+extension type Fbad(int i) {}
+
diff --git a/forui_internal_lints/testbed/lib/src/prefix_public_types/mixin.dart b/forui_internal_lints/testbed/lib/src/prefix_public_types/mixin.dart
new file mode 100644
index 000000000..6f019469f
--- /dev/null
+++ b/forui_internal_lints/testbed/lib/src/prefix_public_types/mixin.dart
@@ -0,0 +1,21 @@
+// ignore_for_file: unused_element
+
+import 'package:meta/meta.dart';
+
+mixin _Good {}
+
+@internal
+mixin GoodSingle {}
+
+@internal
+@visibleForTesting
+mixin GoodMultiple {}
+
+mixin FGood {}
+
+// expect_lint: prefix_public_types
+mixin Bad {}
+
+// expect_lint: prefix_public_types
+mixin Fbad {}
+
diff --git a/forui_internal_lints/testbed/lib/src/prefix_public_types/type_alias.dart b/forui_internal_lints/testbed/lib/src/prefix_public_types/type_alias.dart
new file mode 100644
index 000000000..4d1ac8a07
--- /dev/null
+++ b/forui_internal_lints/testbed/lib/src/prefix_public_types/type_alias.dart
@@ -0,0 +1,21 @@
+// ignore_for_file: unused_element
+
+import 'package:meta/meta.dart';
+
+typedef _Good = String;
+
+@internal
+typedef GoodSingle = String;
+
+@internal
+@visibleForTesting
+typedef GoodMultiple = String;
+
+typedef FGood = String;
+
+// expect_lint: prefix_public_types
+typedef Bad = String;
+
+// expect_lint: prefix_public_types
+typedef Fbad = String;
+
diff --git a/forui_internal_lints/testbed/pubspec.yaml b/forui_internal_lints/testbed/pubspec.yaml
new file mode 100644
index 000000000..7a8f59c3e
--- /dev/null
+++ b/forui_internal_lints/testbed/pubspec.yaml
@@ -0,0 +1,59 @@
+name: testbed
+description: "A new Flutter project."
+version: 0.0.1
+publish_to: 'none'
+
+environment:
+  sdk: ">=3.5.0 <4.0.0"
+  flutter: ">=3.24.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+  meta: ^1.11.0
+
+dev_dependencies:
+  custom_lint: ^0.7.0
+  flutter_test:
+    sdk: flutter
+  forui_internal_lints:
+    path: ../
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter packages.
+flutter:
+
+  # To add assets to your package, add an assets section, like this:
+  # assets:
+  #   - images/a_dot_burr.jpegAct
+  #   - images/a_dot_ham.jpeg
+  #
+  # For details regarding assets in packages, see
+  # https://flutter.dev/to/asset-from-package
+  #
+  # An image asset can refer to one or more resolution-specific "variants", see
+  # https://flutter.dev/to/resolution-aware-images
+
+  # To add custom fonts to your package, add a fonts section here,
+  # in this "flutter" section. Each entry in this list should have a
+  # "family" key with the font family name, and a "fonts" key with a
+  # list giving the asset and other descriptors for the font. For
+  # example:
+  # fonts:
+  #   - family: Schyler
+  #     fonts:
+  #       - asset: fonts/Schyler-Regular.ttf
+  #       - asset: fonts/Schyler-Italic.ttf
+  #         style: italic
+  #   - family: Trajan Pro
+  #     fonts:
+  #       - asset: fonts/TrajanPro.ttf
+  #       - asset: fonts/TrajanPro_Bold.ttf
+  #         weight: 700
+  #
+  # For details regarding fonts in packages, see
+  # https://flutter.dev/to/font-from-package
+import_sorter:
+  comments: false
diff --git a/samples/lib/widgets/slider.dart b/samples/lib/widgets/slider.dart
index bdf79de18..d0f83caa5 100644
--- a/samples/lib/widgets/slider.dart
+++ b/samples/lib/widgets/slider.dart
@@ -128,7 +128,7 @@ class VerticalSliderPage extends Sample {
         child: FSlider(
           label: const Text('Volume'),
           description: const Text('Adjust the volume by dragging the slider.'),
-          layout: Layout.btt,
+          layout: FLayout.btt,
           controller: FContinuousSliderController(selection: FSliderSelection(max: 0.35)),
           trackMainAxisExtent: 350,
           marks: const [