headless_textfield 1.0.0
headless_textfield: ^1.0.0 copied to clipboard
Headless TextField component package.
headless_textfield #
Headless RTextField for Flutter.
This package provides text input behavior (controller ownership, focus, keyboard, semantics) and delegates visuals to a renderer capability from your HeadlessThemeProvider.
Quick start (preset) #
import 'package:flutter/material.dart';
import 'package:headless/headless.dart';
import 'package:headless_textfield/headless_textfield.dart';
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String email = '';
@override
Widget build(BuildContext context) {
return RTextField(
value: email,
onChanged: (v) => setState(() => email = v),
label: 'Email',
placeholder: 'Enter your email',
);
}
}
void main() {
runApp(const HeadlessMaterialApp(home: MyApp()));
}
Quick start (custom) #
import 'package:flutter/widgets.dart';
import 'package:headless_contracts/headless_contracts.dart';
import 'package:headless_textfield/headless_textfield.dart';
import 'package:headless_theme/headless_theme.dart';
final class MyTextFieldRenderer implements RTextFieldRenderer {
@override
Widget render(RTextFieldRenderRequest request) => request.input;
}
final class MyTheme extends HeadlessTheme {
@override
T? capability<T>() {
if (T == RTextFieldRenderer) return MyTextFieldRenderer() as T;
return null;
}
}
void main() {
runApp(
HeadlessApp(
theme: MyTheme(),
appBuilder: (overlayBuilder) {
return Directionality(
textDirection: TextDirection.ltr,
child: Builder(
builder: (context) => overlayBuilder(
context,
RTextField(
value: '',
onChanged: (_) {},
),
),
),
);
},
),
);
}
Controller-driven mode #
final c = TextEditingController();
RTextField(
controller: c,
onChanged: (v) {},
)
Do not pass both value and controller (throws ArgumentError).
Simple style sugar #
RTextField(
value: email,
onChanged: (v) => setState(() => email = v),
label: 'Email',
placeholder: 'Enter your email',
style: const RTextFieldStyle(
containerBackgroundColor: Color(0xFFF7F7F7),
containerBorderColor: Color(0xFFCCCCCC),
containerBorderWidth: 1,
containerRadius: 12,
textColor: Color(0xFF111111),
placeholderColor: Color(0xFF888888),
),
)
This is a convenience layer that is internally converted to
RenderOverrides.only(RTextFieldOverrides.tokens(...)).
Priority (strong -> weak):
overrides: RenderOverrides(...)style: RTextFieldStyle(...)- theme/preset defaults
Per-instance overrides (visual only) #
RTextField(
value: '',
onChanged: (_) {},
label: 'Custom',
overrides: RenderOverrides({
RTextFieldOverrides: RTextFieldOverrides.tokens(
containerBorderRadius: BorderRadius.circular(12),
),
}),
)
Requirements (manual wiring) #
- If you don't use
HeadlessMaterialApp/HeadlessCupertinoApp/HeadlessApp, you must provideHeadlessThemeProviderwith a theme that providesRTextFieldRenderer.
Common errors #
MissingThemeException: you forgotHeadlessThemeProvider(debug).MissingCapabilityException: theme exists, but does not provideRTextFieldRenderer(debug).
In release builds, missing theme/capability does not crash the app: the component renders a small diagnostic placeholder and reports the error via FlutterError.reportError.
Conformance #
See CONFORMANCE_REPORT.md and upstream docs:
docs/SPEC_V1.mddocs/CONFORMANCE.md