### Interactive Signals.dart Example Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/index.mdx This is an interactive example demonstrating Signals.dart functionality. It requires no specific setup beyond embedding in a DartPad environment. ```dart import 'package:signals/signals.dart'; void main() { final count = signal(0); final squared = computed(() => count.value * count.value); print('Count: ${count.value}, Squared: ${squared.value}'); batch(() => ( count.value = 1, count.value = 2, count.value = 3, )); print('Count: ${count.value}, Squared: ${squared.value}'); final effect = effect(() => print('Effect: Count is ${count.value}')); count.value = 4; effect.dispose(); } ``` -------------------------------- ### Clean and Get Dependencies Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_lint/README.md After configuring the linter, clean your project and get the updated dependencies. ```sh flutter clean flutter pub get dart run custom_lint ``` -------------------------------- ### Initialize a Signal Connector Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/connect.md Start with a signal and use the `connect` method to create a connector. This sets up the initial connection. ```dart final s = signal(0); final c = connect(s); ``` -------------------------------- ### Starlight Development Commands Source: https://github.com/rodydavis/signals.dart/blob/main/website/README.md Common npm commands for managing your Starlight project. Includes installing dependencies, starting the development server, building for production, and previewing the build. ```bash npm install ``` ```bash npm run dev ``` ```bash npm run build ``` ```bash npm run preview ``` ```bash npm run astro ... ``` ```bash npm run astro -- --help ``` -------------------------------- ### Build and Copy DevTools Extension Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_devtools_extension/README.md This command builds the DevTools extension and copies it to the specified destination directory. Ensure you have run `flutter pub get` before executing. ```bash flutter pub get && dart run devtools_extensions build_and_copy \ --source=. \ --dest=../signals/extension/devtools ``` -------------------------------- ### Run App with Persisted Theme Initialization Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/guides/persisted-signals.md Initializes the AppTheme instance before running the main application widget. This ensures that any persisted theme settings are loaded and applied correctly from the start. ```dart void main() async{ final theme = AppTheme.instance; // We need to init before running the app to prevent the theme from flickering await theme.init(); runApp(MyApp()); } ``` -------------------------------- ### Create a basic signal Source: https://github.com/rodydavis/signals.dart/blob/main/editors/vscode/README.md Use this snippet to quickly generate a mutable signal. No specific setup is required beyond importing the signals library. ```dart signal() ``` -------------------------------- ### Using .watch(context) Extension Method Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals/README.md This example illustrates using the `.watch(context)` extension method directly on a signal within a Text widget. This provides an alternative way to trigger widget rebuilds when the signal's value changes. ```dart final counter = signal(0); ... @override Widget build(BuildContext context) { return Column( children: [ Text('Counter: ${counter.watch(context)}'), ElevatedButton( onPressed: () => counter.value++, child: Text('Increment'), ), ], ); } ``` -------------------------------- ### Basic Example of Signals Hooks Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_hooks/README.md Demonstrates the integration of signals, computed signals, and signal effects within a Flutter HookWidget. All created signals and effects are automatically cleaned up when the widget is unmounted. ```dart import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:signals_hooks/signals_hooks.dart'; class Example extends HookWidget { const Example({super.key}); @override Widget build(BuildContext context) { final count = useSignal(0); final doubleCount = useComputed(() => count.value * 2); useSignalEffect(() { debugPrint('count: $count, double: $doubleCount'); }); return Scaffold( body: Center( child: Text('Count: $count'), ), floatingActionButton: FloatingActionButton( onPressed: () => count.value++, child: const Icon(Icons.add), ), ); } } ``` -------------------------------- ### Counter Widget with Signal Rebuild Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals/README.md This example demonstrates a basic Counter widget that uses a signal for its state. The `Watch` widget ensures that only the Text widget displaying the counter rebuilds when the signal's value is incremented. ```dart import 'package:flutter/material.dart'; import 'package:signals/signals_flutter.dart'; class Counter extends StatefulWidget { @override _CounterState createState() => _CounterState(); } class _CounterState extends State { final counter = signal(0); @override Widget build(BuildContext context) { return Column( children: [ Watch((context) => Text('Counter: $counter')), ElevatedButton( onPressed: () => counter.value++, child: Text('Increment'), ), ], ); } } ``` -------------------------------- ### Run Core Tests with Melos Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_core/test/CONTEXT.md Execute the core test suite for the signals_core package using the Melos command-line tool. Ensure Melos is installed and configured for the project. ```bash melos run test:core ``` -------------------------------- ### Implement ValueNotifierSignalMixin Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/mixins/value-notifier.md Extend Signal and mix in ValueNotifierSignalMixin to create a signal that behaves like a ValueNotifier. This example demonstrates basic usage with listeners. ```dart class MySignal extends Signal with ValueNotifierSignalMixin { MySignal(super.internalValue); } void main() { final signal = MySignal(0); assert(signal is ReadonlySignal); assert(signal is ValueNotifier); final listener = () => print(signal.value); signal.addListener(listener); signal.value = 1; signal.removeListener(listener); signal.value = 2; } ``` -------------------------------- ### Create Custom Signal with ValueListenableSignalMixin Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/flutter/computed.md To create a custom signal that extends `ValueListenable`, use the `ValueListenableSignalMixin`. This example shows how to integrate custom signal logic with Flutter's listening capabilities. ```dart import 'package:signals/signals_flutter.dart'; class MySignal extends Computed with ValueListenableSignalMixin { MySignal(int Function() cb) : super(cb); } ``` -------------------------------- ### Using ListSignalMixin with a custom Signal Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/mixins/list.md Demonstrates how to integrate ListSignalMixin into a custom Signal class. This example shows a Signal> that uses both IterableSignalMixin and ListSignalMixin. It includes setting up an effect to observe signal length changes and performing add, remove, and contains operations. ```dart class MySignal extends Signal> with IterableSignalMixin>, ListSignalMixin> { MySignal(super.internalValue); } void main() { final signal = MySignal([1, 2, 3]); effect(() { print(signal.length); }); signal.add(4); signal.remove(1); print(signal.contains(2)); // true } ``` -------------------------------- ### Custom Signal Extending Signal, ValueNotifier, and Stream Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/guides/value-notifier.md This example demonstrates creating a custom signal that integrates with ValueNotifier and Stream functionalities. It requires the signals_flutter package for the mixins. ```dart import 'package:signals/signals_flutter.dart'; class CustomSignal extends Signal with ValueNotifierSignalMixin, SinkSignalMixin, StreamSignalMixin { CustomSignal(T value) : super(value); } class Counter extends CustomSignal { Counter(int value) : super(value); } void main() { final counter = Counter(0); assert(counter is Signal); assert(counter is ValueNotifier); assert(counter is Stream); // Listen to the stream counter.listen((value) { print('stream: $value'); }); // Subscribe in an effect effect(() { print('effect: $counter'); }); counter.add(1); print(counter.value); // 1 counter.value = 2; print(counter.value); // 2 counter.close(); print(counter.disposed); // true } ``` -------------------------------- ### Flutter Widget with Signals Watch Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/guides/value-notifier.md Shows how to achieve the same reactivity as the ValueNotifier example but with significantly less boilerplate using Signals.dart. It utilizes `watch` for direct value access and `Watch` for declarative UI updates. ```dart import 'package:signals/signals_flutter.dart'; class MyWidget extends ... { final count1 = signal(0); final count2 = signal(0); @override Widget build(BuildContext context) { // If using setState return Text('${count1.watch(context)} - ${count2.watch(context)}'); // Or if you are using with Watch return Watch((context) => Text('$count1 - $count2')); } } ``` -------------------------------- ### Query Documentation with Gemini CLI Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/reference/ai.mdx Create a GEMINI.md file with the documentation URL and then use the Gemini CLI to query the documentation. This allows for interactive questioning of the Signals documentation. ```markdown https://dartsignals.dev/llms.txt ``` ```bash gemini "How do I use signals?" ``` -------------------------------- ### Download Documentation for AI Context Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/reference/ai.mdx Use curl to download the documentation file for local referencing or to provide as context to AI tools. This is a common step for tools like VS Code extensions and Firebase Studio. ```bash curl https://dartsignals.dev/llms.txt > signals.md ``` -------------------------------- ### Get signal value directly with useSignalValue Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_hooks/README.md Use `useSignalValue` to get the current value of a signal directly within a hook widget. The widget will rebuild when the signal's value changes. ```dart class Example extends HookWidget { final Signal count; const Example(this.count, {super.key}); @override Widget build(BuildContext context) { final counter = useSignalValue(count); return Text('Count: $counter'); } } ``` -------------------------------- ### Set LoggingSignalsObserver Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/utilities/observer.md Provide an implementation of SignalsObserver, such as LoggingSignalsObserver, at the start of your application to log signal changes. ```dart void main() { SignalsObserver.instance = LoggingSignalsObserver(); // or custom observer ... } ``` -------------------------------- ### Create Starlight Project with Astro Source: https://github.com/rodydavis/signals.dart/blob/main/website/README.md Use this command to create a new Astro project with the Starlight template. This is the initial step for setting up your documentation site. ```bash npm create astro@latest -- --template starlight ``` -------------------------------- ### Get Current AsyncSignal Error Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/state.md The .error getter returns the current error of the AsyncSignal if it exists, otherwise null. ```dart final s = asyncSignal(AsyncState.error('error', null)); print(s.error); // 'error' or null ``` -------------------------------- ### Accessing FutureSignal Value Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/future.md Explains how to get the `AsyncState` of a FutureSignal and access the actual value if the future completed successfully. ```APIDOC ## .value, .peek() Returns [`AsyncState`](/dart/async/state) for the value and can handle the various states. The `value` getter returns the value of the future if it completed successfully. > .peek() can also be used to not subscribe in an effect ```dart final s = futureSignal(() => Future(() => 1)); final value = s.value.value; // 1 or null ``` ``` -------------------------------- ### Creating FutureSignal Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/future.md Demonstrates two ways to create a FutureSignal: using the `futureSignal` constructor or the `toSignal()` extension method. ```APIDOC ## Creating FutureSignal Future signals can be created by extension or method. ### Using `futureSignal` constructor ```dart final s = futureSignal(() async => 1); ``` ### Using `toSignal()` extension method ```dart final s = Future(() => 1).toSignal(); ``` ``` -------------------------------- ### Get Current AsyncSignal Value Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/state.md The .value getter returns the current value of the AsyncSignal if it exists, otherwise null. ```dart final s = asyncSignal(AsyncState.data(1)); print(s.value); // 1 or null ``` -------------------------------- ### ChangeStackSignal Initialization and Basic Usage Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/value/change-stack.md Demonstrates how to initialize a ChangeStackSignal and perform basic value changes, undo, and redo operations. ```APIDOC ## ChangeStackSignal ### Description Create a signal with undo/redo and replay values. Change stack is a way to track the signal values overtime and undo or redo values. ### Method Constructor ### Endpoint N/A (Dart Class) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```dart final s = ChangeStackSignal(0, limit: 5); s.value = 1; s.value = 2; s.value = 3; print(s.value); // 3 s.undo(); print(s.value); // 2 s.redo(); print(s.value); // 3 ``` ### Response N/A (Dart Class Method) #### Success Response (200) N/A #### Response Example N/A ``` -------------------------------- ### Define and Initialize App Theme with Signals Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/guides/persisted-signals.md Defines an AppTheme class using ColorSignal and EnumSignal to manage theme properties. The init method asynchronously initializes these signals. Ensure init is called before running the app to prevent theme flickering. ```dart class AppTheme { final sourceColor = ColorSignal( Colors.blue, 'sourceColor', ); final themeMode = EnumSignal( ThemeMode.system, 'themeMode', ThemeMode.values, ); static AppTheme instance = AppTheme(); Future init() async { await Future.wait([ sourceColor.init(), themeMode.init(), ]); } } ``` -------------------------------- ### Add signals_lint to Flutter Project Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_lint/README.md Install the signals_lint package as a dev dependency along with custom_lint in your Flutter project. ```sh flutter pub add -d signals_lint custom_lint ``` -------------------------------- ### Get Current AsyncSignal StackTrace Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/state.md The .stackTrace getter returns the current stack trace associated with an error in the AsyncSignal, if it exists. ```dart final s = asyncSignal(AsyncState.error('error', StackTrace(...))); print(s.stackTrace); // StackTrace(...) or null ``` -------------------------------- ### Initialize and Use ChangeStackSignal Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/value/change-stack.md Demonstrates basic usage of ChangeStackSignal, including setting initial value, updating values, and performing undo/redo operations. ```dart final s = ChangeStackSignal(0, limit: 5); s.value = 1; s.value = 2; s.value = 3; print(s.value); // 3 s.undo(); print(s.value); // 2 s.redo(); print(s.value); // 3 ``` -------------------------------- ### Force Unwrap AsyncSignal Value Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/state.md Use .requireValue to get the value from an AsyncSignal, throwing an error if the signal is in an error state or has no value. ```dart final s = asyncSignal(AsyncState.data(1)); print(s.requireValue); // 1 ``` -------------------------------- ### Create a Signal with StreamSignalMixin Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/mixins/stream.md Demonstrates how to create a custom Signal class that extends Signal and mixes in StreamSignalMixin. This makes the signal behave like a Stream. ```dart class MySignal extends Signal with StreamSignalMixin { MySignal(super.internalValue); } void main() { final signal = MySignal(1); assert(signal is Signal); assert(signal is Stream); signal.listen((value) { print(value); }); signal.value = 2; } ``` -------------------------------- ### Build Dart Web App for Production Source: https://github.com/rodydavis/signals.dart/blob/main/examples/html_canvas/README.md Build a production-ready version of the Dart web application. This command optimizes the app for deployment. ```bash webdev build ``` -------------------------------- ### Provide Documentation Context to Claude Code Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/reference/ai.mdx Use the 'claude' command-line tool to directly provide the documentation URL as context for Claude Code. This enables Claude to answer questions based on the Signals documentation. ```bash claude --context https://dartsignals.dev/llms.txt ``` -------------------------------- ### Integrate Signals with GetIt Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/guides/dependency-injection.md Integrate Signals with GetIt for service location. Register the signal as a singleton to make it accessible throughout the application. ```dart import 'package:signals/signals_flutter.dart'; import 'package:get_it/get_it.dart'; import 'package:flutter/material.dart'; void main() { GetIt.I.registerSingleton>(signal(0)); runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { final counter = GetIt.I.get>(); return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Signals with GetIt'), ), body: Center( child: Watch((context) => Text('Value: $signal')), ), floatingActionButton: FloatingActionButton( onPressed: () => counter.value++, child: Icon(Icons.add), ), ), ); } } ``` -------------------------------- ### Basic Signal Usage Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_core/lib/CONTEXT.md Demonstrates the fundamental usage of signals, computed values, and effects. Ensure `signals_core` is imported. ```dart import 'package:signals_core/signals_core.dart'; final count = signal(0); final doubled = computed(() => count() * 2); effect(() { print('Count is: ${count()}, Doubled is: ${doubled()}'); }); count.value++; // Triggers the effect ``` -------------------------------- ### Testing useSignal with flutter_test Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_hooks/README.md This example demonstrates how to test a hook that uses a Signal in a Flutter widget test. It uses `HookBuilder` and `flutter_test` to verify signal state changes and UI updates. ```dart import 'package:flutter/widgets.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:signals_hooks/signals_hooks.dart'; void main() { testWidgets('useSignal', (tester) async { late Signal state; await tester.pumpWidget( HookBuilder(builder: (context) { state = useSignal(42); return GestureDetector( onTap: () => state.value++, child: Text('$state', textDirection: TextDirection.ltr), ); }), ); expect(state.value, 42); expect(find.text('42'), findsOneWidget); // Click text and wait await tester.tap(find.text('42')); await tester.pumpAndSettle(); expect(state.value, 43); expect(find.text('43'), findsOneWidget); }); } ``` -------------------------------- ### StreamSignal Creation Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/stream.md Demonstrates two ways to create a StreamSignal: using the streamSignal constructor directly or by extending a stream with toSignal(). ```APIDOC ## StreamSignal Creation ### Description Creates a signal that contains a stream. This can be done via the `streamSignal` constructor or by extending an existing stream with `toSignal()`. ### Method `streamSignal(() => stream)` or `stream.toSignal()` ### Example ```dart final stream = () async* { yield 1; }; final s1 = streamSignal(() => stream); final s2 = stream.toSignal(); ``` ``` -------------------------------- ### Replacing Builder with Watch.builder Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals/README.md This diff shows how to replace the standard `Builder` widget with `Watch.builder` for more efficient rebuilds tied to signal changes. ```diff - Builder(builder: (context) { + Watch.builder(builder: (context) { return Text('Counter: $counter'); }); ``` -------------------------------- ### Bi-directional Data Flow Causing Infinite Loop Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/guides/bi-directional-data-flow.md This example demonstrates a scenario where two signals are dependent on each other, leading to an infinite loop and an `EffectCycleDetectionError`. Use this to understand the problem before applying solutions. ```dart final a = signal(0); final b = signal(0); effect(() { b.value = a.value + 1; }); effect(() { a.value = b.value + 1; }); ``` -------------------------------- ### Create a Custom Signal Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/core/signal.md Demonstrates how to create a custom signal by extending the `Signal` class. ```dart class MySignal extends Signal { MySignal(int value) : super(value); } ``` -------------------------------- ### Setting a SignalsObserver Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/utilities/observer.md Demonstrates how to set a custom or prebuilt observer to the SignalsObserver instance. ```APIDOC ## Setting a SignalsObserver ### Description To enable signal observation, assign an implementation of `SignalsObserver` to the static `instance` property at the start of your application. ### Usage Override the `SignalsObserver.instance` with your desired observer implementation, such as `LoggingSignalsObserver` or a custom one. ### Code Example ```dart void main() { SignalsObserver.instance = LoggingSignalsObserver(); // or your custom observer // ... rest of your application setup } ``` ### Note Setting an observer incurs a performance cost as all signal updates are tracked. It is recommended to only set the `SignalsObserver.instance` in debug or profile modes. ``` -------------------------------- ### Access AsyncState values and errors Source: https://context7.com/rodydavis/signals.dart/llms.txt Retrieve the current value or error from an `AsyncState` signal. Use `.value` for the nullable value, `.requireValue` to get the value or throw, and `.error` / `.stackTrace` for error details. ```dart print(data.value.value); // T? - current value print(data.value.requireValue); // T - throws if null print(data.value.error); // Object? - current error print(data.value.stackTrace); // StackTrace? - error stack trace ``` -------------------------------- ### Testing Signals with Streams Source: https://context7.com/rodydavis/signals.dart/llms.txt Demonstrates testing signals by converting them to streams and asserting emitted values. Requires `test` and `signals` packages. ```dart import 'package:test/test.dart'; import 'package:signals/signals.dart'; test('signal emits values in order', () { final s = signal(0); final stream = s.toStream(); s.value = 1; s.value = 2; s.value = 3; expect(stream, emitsInOrder([0, 1, 2, 3])); }); test('computed reacts to dependencies', () { final a = signal(0); final b = computed(() => a.value * 2); final stream = b.toStream(); a.value = 1; a.value = 2; a.value = 3; expect(stream, emitsInOrder([0, 2, 4, 6])); }); test('override signal value for testing', () { final s = signal(0).overrideWith(-1); final stream = s.toStream(); s.value = 1; s.value = 2; expect(stream, emitsInOrder([-1, 1, 2])); }); ``` -------------------------------- ### Using IterableSignalMixin with a Custom Signal Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/mixins/iterable.md Demonstrates how to create a custom signal that extends Signal and mixes in IterableSignalMixin. This setup allows reactive operations on an Iterable value. Ensure the signal's value type is compatible with the mixin. ```dart class MySignal extends Signal> with IterableSignalMixin> { MySignal(super.internalValue); } void main() { final signal = MySignal([1, 2, 3]); effect(() { print(signal.length); }); } ``` -------------------------------- ### Run DevTools Extension with Simulated Environment Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_devtools_extension/README.md Use this command to run the DevTools extension in Chrome with a simulated environment enabled. This is useful for development and testing. ```bash flutter run -d chrome --dart-define=use_simulated_environment=true ``` -------------------------------- ### Using TrackedSignalMixin in Dart Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/mixins/tracked.md Demonstrates how to use TrackedSignalMixin to create a signal that tracks its initial and previous values. Ensure values are immutable or copied on change for accurate tracking. ```dart class MySignal extends Signal with TrackedSignalMixin { MySignal(super.internalValue); } void main() { final signal = MySignal(0); signal.value = 1; print(signal.initialValue); // 0 print(signal.previousValue); // null signal.value = 2; print(signal.initialValue); // 0 print(signal.previousValue); // 1 } ``` -------------------------------- ### Computed Signal Updates with Dependencies Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/reference/overview.md Illustrates how computed signals recompute only when their dependencies change. Updates to a signal trigger recomputation in dependent computed signals, and subsequent reads utilize the updated cached values. This example shows minimal updates when dependencies change. ```dart import 'package:signals/signals.dart'; final a = signal(0); final b = signal(0); final c = computed(() => a.value + b.value); final d = computed(() => c.value + 1); final e = computed(() => d.value + 1); // All the callbacks will be called print(e.value); // 2 // None of the callbacks will be called because the // value is cached at each node print(e.value); // 2 // Only the callbacks that need to be updated // will be called b.value = 1; print(e.value); // 3 ``` -------------------------------- ### Starlight Project Structure Source: https://github.com/rodydavis/signals.dart/blob/main/website/README.md An overview of the default directory structure for an Astro + Starlight project. Key directories include `public/` for static assets and `src/content/docs/` for Markdown/MDX files. ```bash . ├── public/ ├── src/ │ ├── assets/ │ ├── content/ │ │ ├── docs/ │ │ └── config.ts │ └── env.d.ts ├── astro.config.mjs ├── package.json └── tsconfig.json ``` -------------------------------- ### Activating and Registering a Command in extension.ts Source: https://github.com/rodydavis/signals.dart/blob/main/editors/vscode/vsc-extension-quickstart.md Implement the `activate` function in `src/extension.ts` to register your extension's command. The command's implementation is passed as the second argument to `registerCommand`. ```typescript import * as vscode from "vscode"; export function activate(context: vscode.ExtensionContext) { console.log('Congratulations, your extension "my-extension" is now active!'); let disposable = vscode.commands.registerCommand('my-extension.helloWorld', () => { vscode.window.showInformationMessage('Hello World from my-extension!'); }); context.subscriptions.push(disposable); } ``` -------------------------------- ### Prevent Effect Cycles with untracked Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals/README.md Mutating a signal within an effect can cause infinite loops. Use `untracked` to read a signal's value without creating a subscription, preventing such cycles. This example demonstrates a potential cycle error if `untracked` is not used. ```dart import 'dart:async'; import 'package:signals/signals.dart'; Future main() async { final completer = Completer(); final age = signal(0); effect(() { print('You are ${age.value} years old'); age.value++; // <-- This will throw a cycle error }); await completer.future; } ``` -------------------------------- ### Create and Update a Signal Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals/README.md Demonstrates how to create a signal with an initial value and how to update its value. Accessing `.value` reads the current value, while assignment updates it. ```dart import 'package:signals/signals.dart'; final counter = signal(0); // Read value from signal, logs: 0 print(counter.value); // Write to a signal counter.value = 1; ``` -------------------------------- ### Add Signals via Command Line (Flutter) Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/reference/install.mdx Execute this command in your Flutter project's root directory to add the signals package. ```sh flutter pub add signals ``` -------------------------------- ### Create a MapSignal using mapSignal Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/value/map.md Initializes a MapSignal with a predefined map. This is a direct way to create a map signal. ```dart final s = mapSignal({'a': 1, 'b': 2, 'c': 3}); ``` -------------------------------- ### Create a ListSignal Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/value/list.md Use the listSignal constructor to create a new ListSignal initialized with a list of values. This is useful for creating reactive lists from scratch. ```dart final s = listSignal([1, 2, 3]); ``` -------------------------------- ### FutureSignal with reactive dependencies Source: https://context7.com/rodydavis/signals.dart/llms.txt Create a `FutureSignal` that automatically refetches when its dependencies change. Provide a list of signals to the `dependencies` parameter. ```dart final userId = signal(1); final user = futureSignal(() async { return await fetchUser(userId.value); }, dependencies: [userId]); userId.value = 2; // Automatically refetches ``` -------------------------------- ### Implement In-Memory KeyValueStore Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/guides/persisted-signals.md An in-memory implementation of KeyValueStore for testing purposes. Does not persist data. ```dart class InMemoryStore implements KeyValueStore { final Map _store = {}; @override Future getItem(String key) async { return _store[key]; } @override Future removeItem(String key) async { _store.remove(key); } @override Future setItem(String key, String value) async { _store[key] = value; } } ``` -------------------------------- ### Using QueueSignalMixin with a Custom Signal Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/mixins/queue.md Demonstrates how to create a custom signal that extends Signal and mixes in QueueSignalMixin. This allows for reactive queue operations on the signal's value. Ensure the signal's value type is Queue. ```dart class MySignal extends Signal> with QueueSignalMixin> { MySignal(super.internalValue); } void main() { final q = Queue(); a.addFirst(1); final signal = MySignal(q); effect(() { print(signal.length); }); signal.addLast(4); } ``` -------------------------------- ### Basic Signal Usage in Pure Dart Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/guides/value-notifier.md This snippet shows how to create and use signals, computed signals, and effects in a standard Dart application. No Flutter-specific imports are needed. ```dart import 'package:signals/signals.dart'; void main() { final count1 = signal(0); final count2 = signal(0); final total = computed(() => count1.value + count2.value); final isEven = computed(() => total.value.isEven); final isOdd = computed(() => total.value.isOdd); effect(() { print('$total even=$isEven odd=$isOdd'); }); } ``` -------------------------------- ### ValueNotifier vs Signal Initialization Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/guides/value-notifier.md Illustrates the basic syntax for initializing a mutable value holder in both ValueNotifier and Signals. ```dart // Value Notifier final count = ValueNotifier(0); // Signals final count = signal(0); ``` -------------------------------- ### Add Signals via Command Line (Dart) Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/reference/install.mdx Run this command in your Dart project's root directory to add the signals package. ```sh dart pub add signals ``` -------------------------------- ### Wrap Widget with Watch Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_lint/README.md Before: A standard StatelessWidget. After: The same widget wrapped with `Watch` to enable automatic rebuilding when signals change. ```dart class Widget extends StatelessWidget { @override Widget build(BuildContext context) { return Text( 'Hello World', style: TextStyle( color: Colors.black, ), ); } } ``` ```dart class Widget extends StatelessWidget { @override Widget build(BuildContext context) { return Watch((context) => Text( 'Hello World', style: TextStyle( color: Colors.black, ), )); } } ``` -------------------------------- ### Initialize AsyncState signal Source: https://context7.com/rodydavis/signals.dart/llms.txt Create an `AsyncState` signal using `asyncSignal` and initialize it with a specific state, such as `AsyncState.loading()`. This provides a type-safe way to manage asynchronous states. ```dart final data = asyncSignal(AsyncState.loading()); ``` -------------------------------- ### FutureSignal Dependencies Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/future.md Illustrates how FutureSignals can depend on other signals, automatically resetting and re-evaluating when dependencies change. ```APIDOC ## Dependencies By default the callback will be called once and the future will be cached unless a signal is read in the callback. ```dart final count = signal(0); final s = futureSignal(() async => count.value); await s.future; // 0 count.value = 1; await s.future; // 1 ``` If there are signals that need to be tracked across an async gap then use the `dependencies` when creating the `futureSignal` to [`reset`](#.reset()) every time any signal in the dependency array changes. ```dart final count = signal(0); final s = futureSignal( () async => count.value, dependencies: [count], ); s.value; // state with count 0 count.value = 1; // resets the future s.value; // state with count 1 ``` ``` -------------------------------- ### Create ListSignal Source: https://context7.com/rodydavis/signals.dart/llms.txt Create a reactive list signal using `listSignal` or the `.toSignal()` extension method on an existing list. List operations trigger reactive updates. ```dart final items = listSignal([1, 2, 3]); // Or from existing list final items2 = [1, 2, 3].toSignal(); ``` -------------------------------- ### Serve Dart Web App Source: https://github.com/rodydavis/signals.dart/blob/main/examples/html_canvas/README.md Run the Dart web application in development mode using webdev serve. This command is used for local testing and development. ```bash webdev serve ``` -------------------------------- ### Create a change stack Source: https://github.com/rodydavis/signals.dart/blob/main/editors/vscode/README.md Use this snippet to initialize a change stack for undo/redo functionality. This is useful for managing mutable state history. ```dart changeStack() ``` -------------------------------- ### Use Watch.builder for reactive UI components Source: https://github.com/rodydavis/signals.dart/blob/main/editors/vscode/README.md Provides a `Watch.builder` constructor for creating reactive UI components. It takes a builder function that receives the build context. ```dart Watch.builder(builder: (context) => ...) ``` -------------------------------- ### Running Extension Tests Source: https://github.com/rodydavis/signals.dart/blob/main/editors/vscode/vsc-extension-quickstart.md Configure and run tests for your VS Code extension. Test files should match the pattern `**.test.ts` and can be organized into subfolders within the `test` directory. ```typescript import * as vscode from "vscode"; import * as path from "path"; it('should activate and show the command palette', async () => { const extension = new vscode.ExtensionContext(); await activate(extension); const command = vscode.commands.executeCommand('my-extension.helloWorld'); await vscode.window.showInformationMessage('Hello World from my-extension!'); }); export const activate = (context: vscode.ExtensionContext) => { // extension.ts }; export const deactivate = () => {}; ``` -------------------------------- ### Basic Counter Widget with useSignal and useSignalEffect Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_hooks/CONTEXT.md Demonstrates a simple counter using `useSignal` for persistent state and `useSignalEffect` for logging. The signal is automatically disposed of when the widget unmounts. ```dart class CounterWidget extends HookWidget { @override Widget build(BuildContext context) { // Persistent signal across rebuilds final count = useSignal(0); // Automatic cleanup useSignalEffect(() => print('Count: ${count.value}')); return IconButton( onPressed: () => count.value++, icon: const Icon(Icons.add), ); } } ``` -------------------------------- ### Reloading FutureSignal Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/future.md Demonstrates how to reload a FutureSignal, setting its state to `AsyncLoading` and providing the new value or error. ```APIDOC ## .reload() Reload the future value by setting the state to `AsyncLoading` and pass in the value or error as data. ```dart final s = futureSignal(() => Future(() => 1)); s.reload(); print(s.value is AsyncLoading); // true ``` ``` -------------------------------- ### Implement SharedPreferencesStore Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/guides/persisted-signals.md A KeyValueStore implementation using SharedPreferences for persistence in Flutter. Initializes SharedPreferences lazily. ```dart class SharedPreferencesStore implements KeyValueStore { SharedPreferencesStore(); SharedPreferences? prefs; Future init() async { prefs ??= await SharedPreferences.getInstance(); return prefs!; } @override Future getItem(String key) async { final prefs = await init(); return prefs.getString(key); } @override Future removeItem(String key) async { final prefs = await init(); prefs.remove(key); } @override Future setItem(String key, String value) async { final prefs = await init(); prefs.setString(key, value); } } ``` -------------------------------- ### Signals with GetIt for DI Source: https://context7.com/rodydavis/signals.dart/llms.txt Integrates signals with the GetIt package for dependency injection. Requires `signals_flutter`, `get_it`, and `flutter/material.dart`. ```dart import 'package:signals/signals_flutter.dart'; import 'package:get_it/get_it.dart'; import 'package:flutter/material.dart'; void main() { GetIt.I.registerSingleton>(signal(0)); runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { final counter = GetIt.I.get>(); return MaterialApp( home: Scaffold( body: Watch((context) => Text('Value: $counter')), floatingActionButton: FloatingActionButton( onPressed: () => counter.value++, child: Icon(Icons.add), ), ), ); } } ``` -------------------------------- ### Isolate Rebuilds with Builder and .watch(context) Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/flutter/watch.md Demonstrates how to use `Builder` with the `.watch(context)` extension to isolate rebuilds for a specific signal. The outer `Column` and `Text('Not rebuilt')` will not rebuild when the signal changes, while the inner `Text('$count')` will. ```dart final signal = signal(10); ... @override Widget build(BuildContext context) { // Called once return Column( children: [ Builder( builder: (context) { // Called every time the signal changes final count = signal.watch(context); return Text('$count'); }, ), Text('Not rebuilt'), ], ); } ``` -------------------------------- ### Create MapSignal Source: https://context7.com/rodydavis/signals.dart/llms.txt Create a reactive map signal using `mapSignal` or the `.toSignal()` extension method on an existing map. Map operations trigger reactive updates. ```dart final settings = mapSignal({'theme': 'dark', 'lang': 'en'}); // Or from existing map final settings2 = {'theme': 'light'}.toSignal(); ``` -------------------------------- ### Use List Signal Hook Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_hooks/lib/src/CONTEXT.md Use `useListSignal` to create a reactive list. Changes to the list (add, remove, update) will trigger rebuilds. ```dart final items = useListSignal(['a', 'b']); ``` -------------------------------- ### Create a Set Signal using toSignal() Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/value/set.md The `toSignal()` extension method provides a concise way to create a Set signal directly from a Dart Set literal. ```dart final s = {1, 2, 3}.toSignal(); ``` -------------------------------- ### Use SignalProvider to manage Counter signal Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/flutter/signal-provider.md Demonstrates how to use SignalProvider to create and provide a Counter signal to the widget tree. Access the signal using SignalProvider.of and update it via a FloatingActionButton. ```dart import 'package:signals/signals_flutter.dart'; import 'package:flutter/material.dart'; class Counter extends FlutterSignal { Counter([super.value = 0]); void increment() => value++; } class Example extends StatelessWidget { const Example({super.key}); @override Widget build(BuildContext context) { return SignalProvider( create: () => Counter(0), child: Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: const Text('Counter'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( 'You have pushed the button this many times:', ), Builder(builder: (context) { final counter = SignalProvider.of(context); return Text( '$counter', style: Theme.of(context).textTheme.headlineMedium, ); }), ], ), ), floatingActionButton: Builder(builder: (context) { final counter = SignalProvider.of(context, listen: false)!; return FloatingActionButton( onPressed: counter.increment, tooltip: 'Increment', child: const Icon(Icons.add), ); }), ), ); } } ``` -------------------------------- ### Use Watch widget for context-based reactivity Source: https://github.com/rodydavis/signals.dart/blob/main/editors/vscode/README.md Generates a `Watch` widget, which rebuilds its child when dependent signals change. It requires a build context. ```dart Watch((context) => ...) ``` -------------------------------- ### Flutter Counter App with Signals.dart Source: https://github.com/rodydavis/signals.dart/blob/main/examples/flutter_counter/README.md This is the main entry point and widget structure for the Flutter counter application. It sets up the MaterialApp, defines themes, and integrates the signals.dart computed signal for theme mode. ```dart import 'package:flutter/material.dart'; import 'package:signals/signals_flutter.dart'; final brightness = signal(Brightness.light); final themeMode = computed(() { if (brightness() == Brightness.dark) { return ThemeMode.dark; } else { return ThemeMode.light; } }); void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', debugShowCheckedModeBanner: false, theme: ThemeData( colorScheme: ColorScheme.fromSeed( seedColor: Colors.deepPurple, brightness: Brightness.light, ), brightness: Brightness.light, useMaterial3: true, ), darkTheme: ThemeData( colorScheme: ColorScheme.fromSeed( seedColor: Colors.deepPurple, brightness: Brightness.dark, ), brightness: Brightness.dark, useMaterial3: true, ), themeMode: themeMode.watch(context), home: const MyHomePage(title: 'Flutter Demo Home Page'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key, required this.title}); final String title; @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { final counter = signal(0); void _incrementCounter() { counter.value++; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), actions: [ Watch((_) { final isDark = brightness() == Brightness.dark; return IconButton( onPressed: () { brightness.value = isDark ? Brightness.light : Brightness.dark; }, icon: Icon(isDark ? Icons.light_mode : Icons.dark_mode), ); }), ], ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( 'You have pushed the button this many times:', ), Watch((context) { return Text( '$counter', style: Theme.of(context).textTheme.headlineMedium!, ); }), ], ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: const Icon(Icons.add), ), ); } } ``` -------------------------------- ### Registering a Command in package.json Source: https://github.com/rodydavis/signals.dart/blob/main/editors/vscode/vsc-extension-quickstart.md Declare an extension command and its properties in the `package.json` manifest. This allows VS Code to display the command in the command palette without needing to load the extension's implementation. ```json { "name": "my-extension", "version": "0.0.1", "engines": { "vscode": "^1.80.0" }, "categories": [ "Other" ], "activationEvents": [ "onCommand:my-extension.helloWorld" ], "main": "./out/extension.js", "contributes": { "commands": [ { "command": "my-extension.helloWorld", "title": "Hello World" } ] }, "scripts": { "vscode:prepublish": "npm run compile", "compile": "tsc -p ./tsconfig.json" }, "devDependencies": { "@types/vscode": "1.80.0", "@types/node": "18.x", "typescript": "5.1.6", "@vscode/test-electron": "2.3.4" } } ``` -------------------------------- ### Use Map Signal Hook Source: https://github.com/rodydavis/signals.dart/blob/main/packages/signals_hooks/lib/src/CONTEXT.md Use `useMapSignal` to create a reactive map. Changes to the map will trigger rebuilds. ```dart final settings = useMapSignal({ 'theme': 'dark', 'fontSize': 14, }); ``` -------------------------------- ### FutureSignal with Dependencies Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/future.md When signals are read within the future's callback, they are automatically tracked. For signals that need to trigger a reset across an async gap, use the `dependencies` parameter. ```dart final count = signal(0); final s = futureSignal(() async => count.value); await s.future; // 0 count.value = 1; await s.future; // 1 ``` -------------------------------- ### Build Material App with Theme Signals Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/guides/persisted-signals.md Constructs the MaterialApp widget, binding its theme properties (colorScheme, themeMode) to the signals managed by AppTheme.instance. The 'watch' method is used to reactively update the UI when signal values change. ```dart class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { final theme = AppTheme.instance; return MaterialApp( theme: ThemeData.light().copyWith( colorScheme: ColorScheme.fromSeed( seedColor: theme.sourceColor.watch(context), brightness: Brightness.light, ), ), darkTheme: ThemeData.dark().copyWith( colorScheme: ColorScheme.fromSeed( seedColor: theme.sourceColor.watch(context), brightness: Brightness.dark, ), ), themeMode: theme.themeMode.watch(context), home: Scaffold( appBar: AppBar( title: Text('Persisted Signals'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () { theme.sourceColor.value = Colors.red; }, child: Text('Change Color'), ), ElevatedButton( onPressed: () { theme.themeMode.value = ThemeMode.dark; }, child: Text('Change Theme'), ), ], ), ), ), ); } } ``` -------------------------------- ### Resetting FutureSignal Source: https://github.com/rodydavis/signals.dart/blob/main/website/src/content/docs/async/future.md Shows how to reset a FutureSignal to its initial state, causing it to re-evaluate on the next access. ```APIDOC ## .reset() The `reset` method resets the future to its initial state to recall on the next evaluation. ```dart final s = futureSignal(() => Future(() => 1)); s.reset(); ``` ```