words_numbers 0.1.0 copy "words_numbers: ^0.1.0" to clipboard
words_numbers: ^0.1.0 copied to clipboard

High-performance Dart & Flutter library to convert number words to numbers ('five hundred twenty-two' -> 522) and numbers to words, with sentence parsing & currency support.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:words_numbers/words_numbers.dart';

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

/// Root widget for the words_numbers interactive demo application.
class WordsNumbersApp extends StatelessWidget {
  const WordsNumbersApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'WordsNumbers Interactive Playground',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF4F46E5),
          brightness: Brightness.light,
        ),
        useMaterial3: true,
      ),
      darkTheme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF4F46E5),
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: const PlaygroundScreen(),
    );
  }
}

/// The main playground screen featuring Words-to-Numbers and Numbers-to-Words.
class PlaygroundScreen extends StatefulWidget {
  const PlaygroundScreen({super.key});

  @override
  State<PlaygroundScreen> createState() => _PlaygroundScreenState();
}

class _PlaygroundScreenState extends State<PlaygroundScreen> {
  // Controller for Tab 1 (Words to Numbers)
  final TextEditingController _wordsController = TextEditingController(
    text: 'hello world OnE \n How are you two',
  );

  // Controller for Tab 2 (Numbers to Words)
  final TextEditingController _numberController = TextEditingController(
    text: '1250.50',
  );

  bool _includeAnd = true;
  bool _hyphenate = true;
  bool _currencyMode = true;

  @override
  void dispose() {
    _wordsController.dispose();
    _numberController.dispose();
    super.dispose();
  }

  void _copyToClipboard(String text, String label) {
    Clipboard.setData(ClipboardData(text: text));
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('$label copied to clipboard!'),
        behavior: SnackBarBehavior.floating,
        duration: const Duration(seconds: 2),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('WordsNumbers Playground'),
          centerTitle: true,
          bottom: const TabBar(
            tabs: [
              Tab(
                icon: Icon(Icons.text_fields),
                text: 'Words → Numbers',
              ),
              Tab(
                icon: Icon(Icons.numbers),
                text: 'Numbers → Words',
              ),
            ],
          ),
        ),
        body: SafeArea(
          child: TabBarView(
            children: [
              _buildWordsToNumbersTab(),
              _buildNumbersToWordsTab(),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildWordsToNumbersTab() {
    final inputText = _wordsController.text;
    final convertedSentence = WordsNumbers.convertTextNumberToString(inputText);
    final parsedDirect = WordsNumbers.tryParse(inputText);

    return SingleChildScrollView(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          const Text(
            'Speech-to-Text & Sentence Parser',
            style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 4),
          Text(
            'Converts compound phrases and words in sentences to digits.',
            style: TextStyle(color: Theme.of(context).colorScheme.outline),
          ),
          const SizedBox(height: 12),
          Wrap(
            spacing: 8,
            runSpacing: 4,
            children: [
              _buildPresetChip('hello world OnE \n How are you two'),
              _buildPresetChip('five hundred twenty-two'),
              _buildPresetChip(
                'I bought twenty-two apples for five hundred dollars.',
              ),
              _buildPresetChip('The speed was three point one four meters.'),
              _buildPresetChip(
                  'She won first place in the twenty-first event.'),
            ],
          ),
          const SizedBox(height: 16),
          TextField(
            controller: _wordsController,
            maxLines: 4,
            decoration: InputDecoration(
              labelText: 'Input Text / Words',
              alignLabelWithHint: true,
              border: const OutlineInputBorder(),
              suffixIcon: IconButton(
                icon: const Icon(Icons.clear),
                onPressed: () {
                  setState(() {
                    _wordsController.clear();
                  });
                },
              ),
            ),
            onChanged: (_) => setState(() {}),
          ),
          const SizedBox(height: 16),
          Card(
            elevation: 2,
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      const Text(
                        'Converted Output:',
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      IconButton(
                        tooltip: 'Copy Output',
                        icon: const Icon(Icons.copy),
                        onPressed: convertedSentence.isNotEmpty
                            ? () => _copyToClipboard(
                                  convertedSentence,
                                  'Converted output',
                                )
                            : null,
                      ),
                    ],
                  ),
                  const Divider(),
                  const SizedBox(height: 8),
                  SelectableText(
                    convertedSentence.isNotEmpty
                        ? convertedSentence
                        : '(Empty input)',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.w600,
                      color: Theme.of(context).colorScheme.primary,
                    ),
                  ),
                  if (parsedDirect != null) ...[
                    const SizedBox(height: 12),
                    Container(
                      padding: const EdgeInsets.all(8),
                      decoration: BoxDecoration(
                        color: Theme.of(context)
                            .colorScheme
                            .primaryContainer
                            .withValues(alpha: 0.4),
                        borderRadius: BorderRadius.circular(8),
                      ),
                      child: Text(
                        'Direct parsed value: $parsedDirect (${parsedDirect.runtimeType})',
                        style: TextStyle(
                          fontSize: 13,
                          color: Theme.of(context).colorScheme.primary,
                        ),
                      ),
                    ),
                  ],
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildNumbersToWordsTab() {
    final rawNumber = _numberController.text.trim();
    final parsedNum = num.tryParse(rawNumber);

    String convertedOutput;
    if (parsedNum == null) {
      convertedOutput = rawNumber.isEmpty
          ? '(Enter a number above)'
          : 'Please enter a valid numeric value.';
    } else if (_currencyMode) {
      convertedOutput = WordsNumbers.toCurrency(
        parsedNum,
        includeAnd: _includeAnd,
        hyphenate: _hyphenate,
      );
    } else {
      if (parsedNum is int) {
        convertedOutput = WordsNumbers.toWords(
          parsedNum,
          includeAnd: _includeAnd,
          hyphenate: _hyphenate,
        );
      } else {
        // Double without currency: handle dollars/cents or integer conversion
        convertedOutput = WordsNumbers.toCurrency(
          parsedNum,
          currencyWord: 'point',
          centWord: '',
          includeAnd: _includeAnd,
          hyphenate: _hyphenate,
        );
      }
    }

    return SingleChildScrollView(
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          const Text(
            'Number to Words & Currency Engine',
            style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
          ),
          const SizedBox(height: 4),
          Text(
            'Generates English words for invoices, receipts, and checks.',
            style: TextStyle(color: Theme.of(context).colorScheme.outline),
          ),
          const SizedBox(height: 12),
          Wrap(
            spacing: 8,
            runSpacing: 4,
            children: [
              _buildNumberChip('42'),
              _buildNumberChip('105'),
              _buildNumberChip('1250'),
              _buildNumberChip('1250.50'),
              _buildNumberChip('1500000'),
              _buildNumberChip('-42.25'),
            ],
          ),
          const SizedBox(height: 16),
          TextField(
            controller: _numberController,
            keyboardType: const TextInputType.numberWithOptions(
              decimal: true,
              signed: true,
            ),
            decoration: InputDecoration(
              labelText: 'Number Input',
              border: const OutlineInputBorder(),
              suffixIcon: IconButton(
                icon: const Icon(Icons.clear),
                onPressed: () {
                  setState(() {
                    _numberController.clear();
                  });
                },
              ),
            ),
            onChanged: (_) => setState(() {}),
          ),
          const SizedBox(height: 12),
          Wrap(
            spacing: 16,
            children: [
              FilterChip(
                label: const Text('Currency Mode (\$)'),
                selected: _currencyMode,
                onSelected: (val) => setState(() => _currencyMode = val),
              ),
              FilterChip(
                label: const Text('Include "and"'),
                selected: _includeAnd,
                onSelected: (val) => setState(() => _includeAnd = val),
              ),
              FilterChip(
                label: const Text('Hyphenation'),
                selected: _hyphenate,
                onSelected: (val) => setState(() => _hyphenate = val),
              ),
            ],
          ),
          const SizedBox(height: 16),
          Card(
            elevation: 2,
            child: Padding(
              padding: const EdgeInsets.all(16.0),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      const Text(
                        'English Words Result:',
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      IconButton(
                        tooltip: 'Copy Output',
                        icon: const Icon(Icons.copy),
                        onPressed: parsedNum != null
                            ? () => _copyToClipboard(
                                  convertedOutput,
                                  'English words',
                                )
                            : null,
                      ),
                    ],
                  ),
                  const Divider(),
                  const SizedBox(height: 8),
                  SelectableText(
                    convertedOutput,
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.w600,
                      color: Theme.of(context).colorScheme.primary,
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildPresetChip(String text) {
    return ActionChip(
      label: Text(
        text.contains('\n') ? text.split('\n').first : text,
        maxLines: 1,
        overflow: TextOverflow.ellipsis,
      ),
      onPressed: () {
        setState(() {
          _wordsController.text = text;
        });
      },
    );
  }

  Widget _buildNumberChip(String numberStr) {
    return ActionChip(
      label: Text(numberStr),
      onPressed: () {
        setState(() {
          _numberController.text = numberStr;
        });
      },
    );
  }
}
2
likes
160
points
673
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

High-performance Dart & Flutter library to convert number words to numbers ('five hundred twenty-two' -> 522) and numbers to words, with sentence parsing & currency support.

Repository (GitHub)
View/report issues

Topics

#words-to-numbers #number-to-words #converter #speech-to-text #text-processing

License

Apache-2.0 (license)

Dependencies

flutter

More

Packages that depend on words_numbers