beacon_widget 0.2.0 copy "beacon_widget: ^0.2.0" to clipboard
beacon_widget: ^0.2.0 copied to clipboard

Tap a widget in your running Flutter app and get its file:line, theme properties and geometry on your clipboard, ready to paste into an AI coding agent.

example/lib/main.dart

// Test harness: exercises the real `beacon` package — including the Phase 4
// select-mode overlay — against a wide matrix of widget shapes (PLAN.md
// §3.2 asks for ~15). Tap the FAB to enter select mode, then tap anything
// below; long-press the FAB to broadcast everything selected since the
// last broadcast as one combined reference (PLAN.md §6).
import 'package:beacon_widget/beacon_widget.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const BeaconTestApp());
}

class BeaconTestApp extends StatelessWidget {
  const BeaconTestApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Beacon Widget Matrix',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      builder: (context, child) => Beacon.attach(child!),
      home: const WidgetMatrixScreen(),
    );
  }
}

class WidgetMatrixScreen extends StatefulWidget {
  const WidgetMatrixScreen({super.key});

  @override
  State<WidgetMatrixScreen> createState() => _WidgetMatrixScreenState();
}

class _WidgetMatrixScreenState extends State<WidgetMatrixScreen> {
  bool _switchValue = false;
  bool? _checkboxValue = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Beacon Widget Matrix'),
        actions: const [_BeaconVisibilityToggle(), SizedBox(width: 8)],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: const Icon(Icons.add),
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          const _Section('1. Custom widget'),
          const BeaconCard(label: 'Custom widget (BeaconCard)'),
          const SizedBox(height: 16),

          const _Section('2. Material buttons'),
          Wrap(
            spacing: 12,
            runSpacing: 12,
            children: [
              ElevatedButton(onPressed: () {}, child: const Text('Elevated')),
              OutlinedButton(onPressed: () {}, child: const Text('Outlined')),
              TextButton(onPressed: () {}, child: const Text('Text')),
              IconButton(onPressed: () {}, icon: const Icon(Icons.favorite)),
            ],
          ),
          const SizedBox(height: 16),

          const _Section('3. Button wrapped in framework noise'),
          Semantics(
            label: 'wrapped button',
            child: RepaintBoundary(
              child: AnimatedBuilder(
                animation: const AlwaysStoppedAnimation(0),
                builder: (context, child) => child!,
                child: const WrappedButton(),
              ),
            ),
          ),
          const SizedBox(height: 16),

          const _Section('4. Text inside a standard ListTile'),
          const Card(
            child: ListTile(
              leading: Icon(Icons.info_outline),
              title: Text('Text inside ListTile'),
              subtitle: Text('tap the title, subtitle, or leading icon'),
            ),
          ),
          const SizedBox(height: 16),

          const _Section('5. Widget behind a Stack'),
          SizedBox(
            height: 80,
            child: Stack(
              children: [
                Positioned(
                  left: 0,
                  top: 0,
                  child: Container(
                    width: 100,
                    height: 80,
                    color: Colors.grey.shade300,
                  ),
                ),
                const Positioned(
                  left: 20,
                  top: 20,
                  child: BeaconCard(label: 'Behind Stack'),
                ),
              ],
            ),
          ),
          const SizedBox(height: 16),

          const _Section('6. Items inside ListView.builder'),
          SizedBox(
            height: 150,
            child: ListView.builder(
              itemCount: 3,
              itemBuilder: (context, index) => ProductRow(index: index),
            ),
          ),
          const SizedBox(height: 16),

          const _Section('7. Form controls'),
          Row(
            children: [
              Checkbox(
                value: _checkboxValue,
                onChanged: (v) => setState(() => _checkboxValue = v),
              ),
              Switch(
                value: _switchValue,
                onChanged: (v) => setState(() => _switchValue = v),
              ),
              const SizedBox(width: 12),
              Chip(label: const Text('A chip')),
            ],
          ),
          const SizedBox(height: 12),
          const TextField(
            decoration: InputDecoration(
              labelText: 'A text field',
              border: OutlineInputBorder(),
            ),
          ),
          const SizedBox(height: 16),

          const _Section('8. Deeply nested custom widget'),
          const Padding(
            padding: EdgeInsets.all(4),
            child: Center(
              child: BeaconCard(label: 'Nested in Padding > Center'),
            ),
          ),
          const SizedBox(height: 16),

          const _Section('9. Theme-literal color (no token match expected)'),
          Container(
            padding: const EdgeInsets.all(12),
            color: const Color(0xFF123456),
            child: const Text('Literal color container'),
          ),
        ],
      ),
    );
  }
}

/// A debug settings toggle for `Beacon.visible` (`Beacon.hide`/`.show`) — a
/// developer wires this into whatever settings UI their own app already
/// has; this is just the example app's version of that. Rebuilds only
/// itself off `Beacon.visible`, not the whole screen.
class _BeaconVisibilityToggle extends StatelessWidget {
  const _BeaconVisibilityToggle();

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<bool>(
      valueListenable: Beacon.visible,
      builder: (context, visible, _) {
        return Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Text('Beacon'),
            Switch(value: visible, onChanged: Beacon.setVisible),
          ],
        );
      },
    );
  }
}

class _Section extends StatelessWidget {
  const _Section(this.label);

  final String label;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 8),
      child: Text(label, style: Theme.of(context).textTheme.labelLarge),
    );
  }
}

/// Custom widget the resolver should land on exactly, at the line below.
class BeaconCard extends StatelessWidget {
  const BeaconCard({super.key, required this.label});

  final String label;

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.all(12),
      decoration: BoxDecoration(
        color: Theme.of(context).colorScheme.primaryContainer,
        borderRadius: BorderRadius.circular(8),
      ),
      child: Text(label),
    );
  }
}

class WrappedButton extends StatelessWidget {
  const WrappedButton({super.key});

  @override
  Widget build(BuildContext context) {
    return OutlinedButton(
      onPressed: () {},
      child: const Text('Wrapped in Semantics/RepaintBoundary'),
    );
  }
}

class ProductRow extends StatelessWidget {
  const ProductRow({super.key, required this.index});

  final int index;

  @override
  Widget build(BuildContext context) {
    return ListTile(
      leading: const Icon(Icons.inventory_2_outlined),
      title: Text('Product #$index'),
    );
  }
}
2
likes
0
points
357
downloads

Publisher

unverified uploader

Weekly Downloads

Tap a widget in your running Flutter app and get its file:line, theme properties and geometry on your clipboard, ready to paste into an AI coding agent.

Repository (GitHub)
View/report issues

Topics

#devtools #debugging #developer-tools #ai

License

unknown (license)

Dependencies

flutter, meta, no_screenshot, path, vm_service

More

Packages that depend on beacon_widget