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

A customizable Flutter text editing controller for detecting, styling, querying, and serializing semantic text tokens.

example/lib/main.dart

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

void main() => runApp(const ExampleApp());

/// Minimal application demonstrating token-aware editing and suggestions.
class ExampleApp extends StatelessWidget {
  /// Creates the package example application.
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
      ),
      home: const TokenEditorPage(),
    );
  }
}

/// Interactive page containing a token-aware field and rendered preview.
class TokenEditorPage extends StatefulWidget {
  /// Creates the token editor example page.
  const TokenEditorPage({super.key});

  @override
  State<TokenEditorPage> createState() => _TokenEditorPageState();
}

class _TokenEditorPageState extends State<TokenEditorPage> {
  final controller = TokenTextController(
    activeTokens: TokenGroups.assistantChat,
  );
  final focusNode = FocusNode();

  static final suggestions = <TokenKind, List<String>>{
    TokenKind.mention: ['@Luis', '@Andrea', '@FlutterDev'],
    TokenKind.hashtag: ['#Flutter', '#Messaging', '#Community'],
    TokenKind.command: ['/help', '/invite', '/shrug'],
  };

  @override
  void dispose() {
    controller.dispose();
    focusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Token text controller')),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            children: [
              Expanded(
                child: ValueListenableBuilder<TextEditingValue>(
                  valueListenable: controller,
                  builder: (context, value, child) {
                    if (value.text.isEmpty) return const SizedBox.shrink();
                    return Align(
                      alignment: Alignment.topLeft,
                      child: TokenText(
                        value.text,
                        style: Theme.of(context).textTheme.titleMedium,
                      ),
                    );
                  },
                ),
              ),
              ValueListenableBuilder<TokenQuery?>(
                valueListenable: controller.activeQueryListenable,
                builder: (context, query, child) {
                  if (query == null) return const SizedBox.shrink();
                  final matches = (suggestions[query.kind] ?? const <String>[])
                      .where(
                        (value) => value
                            .substring(1)
                            .toLowerCase()
                            .startsWith(query.query.toLowerCase()),
                      )
                      .toList(growable: false);
                  if (matches.isEmpty) return const SizedBox.shrink();

                  return SizedBox(
                    height: 48,
                    child: ListView.separated(
                      scrollDirection: Axis.horizontal,
                      itemCount: matches.length,
                      separatorBuilder: (_, _) => const SizedBox(width: 8),
                      itemBuilder: (context, index) {
                        final value = matches[index];
                        return ActionChip(
                          label: Text(value),
                          onPressed: () => controller.replaceActiveQuery(
                            value,
                            kind: query.kind,
                            data: {'value': value},
                          ),
                        );
                      },
                    ),
                  );
                },
              ),
              TextField(
                controller: controller,
                focusNode: focusNode,
                minLines: 1,
                maxLines: 5,
                decoration: const InputDecoration(
                  hintText: 'Message',
                  border: OutlineInputBorder(),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
1
likes
0
points
254
downloads

Publisher

unverified uploader

Weekly Downloads

A customizable Flutter text editing controller for detecting, styling, querying, and serializing semantic text tokens.

Homepage

Topics

#text-field #text-editing #mentions #hashtags #syntax-highlighting

License

unknown (license)

Dependencies

characters, flutter

More

Packages that depend on token_text_controller