regex_pattern_text_field 1.1.0 copy "regex_pattern_text_field: ^1.1.0" to clipboard
regex_pattern_text_field: ^1.1.0 copied to clipboard

A custom text editing controller that applies styles to matched patterns in a text field.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:regex_pattern_text_field/regex_pattern_text_field.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Regex Pattern Text Field Demo',
      theme: ThemeData(colorSchemeSeed: Colors.blue, useMaterial3: true),
      home: const RegexPatternDemoPage(),
    );
  }
}

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

  @override
  State<RegexPatternDemoPage> createState() => _RegexPatternDemoPageState();
}

class _RegexPatternDemoPageState extends State<RegexPatternDemoPage> {
  final RegexPatternTextEditingController _controller =
      RegexPatternTextEditingController();

  bool _useDefaultPatterns = true;
  String _lastEvent = 'Type something to see matches.';
  List<RegexPatternMatched<Object?>> _matches = const [];

  static const _customStyles = <RegexPatternTextStyle<Object?>>[
    RegexPatternTextStyle<Object?>(
      type: 'github',
      regexPattern: RegexPatternHelper.github,
      textStyle: TextStyle(color: Colors.redAccent),
    ),
    RegexPatternTextStyle<Object?>(
      type: 'facebook',
      regexPattern: RegexPatternHelper.facebook,
      textStyle: TextStyle(color: Colors.lightGreen),
    ),
    RegexPatternTextStyle<Object?>(
      type: 'twitter',
      regexPattern: RegexPatternHelper.twitter,
      textStyle: TextStyle(color: Colors.deepOrangeAccent),
    ),
    RegexPatternTextStyle<Object?>(
      type: 'instagram',
      regexPattern: RegexPatternHelper.instagram,
      textStyle: TextStyle(color: Colors.brown),
    ),
    RegexPatternTextStyle<Object?>(
      type: 'phone',
      regexPattern: RegexPatternHelper.phone,
      textStyle: TextStyle(color: Colors.amber),
    ),
    RegexPatternTextStyle<Object?>(
      type: 'date',
      regexPattern: RegexPatternHelper.dateTime,
      textStyle: TextStyle(color: Colors.red),
    ),
    RegexPatternTextStyle<Object?>(
      type: 'myRegexPattern',
      regexPattern: r'%+([a-zA-Z]+)',
      textStyle: TextStyle(color: Colors.pink),
    ),
  ];

  @override
  void initState() {
    super.initState();
    _controller.addListener(_syncMatchesFromController);
    _controller.text =
        'Try: #flutter @user user@mail.com https://flutter.dev %token';
  }

  @override
  void dispose() {
    _controller
      ..removeListener(_syncMatchesFromController)
      ..dispose();
    super.dispose();
  }

  void _syncMatchesFromController() {
    setState(() {
      _matches = _controller.regexPatternMatchedList;
    });
  }

  void _applyPatternMode(bool enabled) {
    setState(() {
      _useDefaultPatterns = enabled;
      _lastEvent = enabled
          ? 'Default patterns enabled.'
          : 'Default patterns disabled.';
    });

    _controller.setRegexPatternStyle(_customStyles, _useDefaultPatterns);
    _syncMatchesFromController();
  }

  void _insertSampleText() {
    const sample =
        'Contact @alice via alice@example.com on 08 Jan 2026 and visit https://github.com';
    _controller.value = _controller.value.copyWith(
      text: sample,
      selection: const TextSelection.collapsed(offset: sample.length),
    );
  }

  void _clearText() {
    _controller.clear();
    setState(() {
      _lastEvent = 'Input cleared.';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Regex Pattern Text Field Demo')),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              SwitchListTile(
                contentPadding: EdgeInsets.zero,
                value: _useDefaultPatterns,
                onChanged: _applyPatternMode,
                title: const Text('Use default built-in patterns'),
                subtitle: const Text('email, url, hashtag, mention'),
              ),
              const SizedBox(height: 8),
              Row(
                children: [
                  FilledButton.tonal(
                    onPressed: _insertSampleText,
                    child: const Text('Insert sample'),
                  ),
                  const SizedBox(width: 8),
                  OutlinedButton(
                    onPressed: _clearText,
                    child: const Text('Clear'),
                  ),
                ],
              ),
              const SizedBox(height: 12),
              RegexPatternTextField(
                maxLines: 5,
                regexPatternController: _controller,
                defaultRegexPatternStyles: _useDefaultPatterns,
                regexPatternStyles: _customStyles,
                decoration: const InputDecoration(
                  border: OutlineInputBorder(),
                  hintText:
                      'Type text with @mentions, #tags, emails, urls and %custom.',
                ),
                onChanged: (matches, text) {
                  setState(() {
                    _matches = matches;
                    _lastEvent =
                        'Changed: ${matches.length} match(es) in ${text.length} chars';
                  });
                },
                onSubmitted: (matches, text) {
                  setState(() {
                    _lastEvent =
                        'Submitted: ${matches.length} match(es) in ${text.length} chars';
                  });
                },
                onMatch: (model) {
                  setState(() {
                    _lastEvent =
                        'Match -> text: "${model.text}", type: ${model.type}';
                  });
                },
                onNonMatch: (text) {
                  setState(() {
                    _lastEvent = 'Non-match token: "$text"';
                  });
                },
              ),
              const SizedBox(height: 12),
              Text(
                _lastEvent,
                maxLines: 2,
                overflow: TextOverflow.ellipsis,
                style: Theme.of(context).textTheme.bodySmall,
              ),
              const SizedBox(height: 12),
              Text(
                'Matches (${_matches.length})',
                style: Theme.of(context).textTheme.titleMedium,
              ),
              const SizedBox(height: 8),
              Expanded(
                child: _matches.isEmpty
                    ? const Center(child: Text('No matches yet.'))
                    : ListView.separated(
                        itemCount: _matches.length,
                        separatorBuilder: (_, _) => const Divider(height: 1),
                        itemBuilder: (context, index) {
                          final match = _matches[index];
                          return ListTile(
                            dense: true,
                            title: Text(match.text),
                            subtitle: Text(
                              'type: ${match.type} | range: ${match.start}-${match.end}',
                            ),
                          );
                        },
                      ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
6
likes
150
points
169
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A custom text editing controller that applies styles to matched patterns in a text field.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on regex_pattern_text_field