Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Library] `Filter chip` Apply high contrast theme to filter chip (selected) ([#494](https://github.com/Orange-OpenSource/ouds-flutter/issues/494))

### Changed
- [DemoApp][Library] `Pin code input` Add optional `keyboardType` parameter (numeric/alphanumeric) ([#733](https://github.com/Orange-OpenSource/ouds-flutter/issues/733))
- [Library] update tokens 1.9.0 - Component Bullet List ([#710](https://github.com/Orange-OpenSource/ouds-flutter/issues/710))
- [Library] update tokens 1.9.0 - Component Alert ([#672](https://github.com/Orange-OpenSource/ouds-flutter/issues/672))

Expand Down
18 changes: 18 additions & 0 deletions app/lib/l10n/gen/ouds_flutter_app_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,24 @@ abstract class AppLocalizations {
/// **'Hidden Password'**
String get app_components_pinCodeInput_hidden_password_label;

/// No description provided for @app_components_pinCodeInput_keyboardType_label.
///
/// In en, this message translates to:
/// **'Keyboard type'**
String get app_components_pinCodeInput_keyboardType_label;

/// No description provided for @app_components_pinCodeInput_keyboardType_numeric_label.
///
/// In en, this message translates to:
/// **'Numeric'**
String get app_components_pinCodeInput_keyboardType_numeric_label;

/// No description provided for @app_components_pinCodeInput_keyboardType_alphanumeric_label.
///
/// In en, this message translates to:
/// **'Alphanumeric'**
String get app_components_pinCodeInput_keyboardType_alphanumeric_label;

/// No description provided for @app_components_navigationBar_label.
///
/// In en, this message translates to:
Expand Down
11 changes: 11 additions & 0 deletions app/lib/l10n/gen/ouds_flutter_app_localizations_ar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,17 @@ class AppLocalizationsAr extends AppLocalizations {
String get app_components_pinCodeInput_hidden_password_label =>
'Hidden Password';

@override
String get app_components_pinCodeInput_keyboardType_label => 'Keyboard type';

@override
String get app_components_pinCodeInput_keyboardType_numeric_label =>
'Numeric';

@override
String get app_components_pinCodeInput_keyboardType_alphanumeric_label =>
'Alphanumeric';

@override
String get app_components_navigationBar_label => 'Bottom Bar';

Expand Down
11 changes: 11 additions & 0 deletions app/lib/l10n/gen/ouds_flutter_app_localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,17 @@ class AppLocalizationsEn extends AppLocalizations {
String get app_components_pinCodeInput_hidden_password_label =>
'Hidden Password';

@override
String get app_components_pinCodeInput_keyboardType_label => 'Keyboard type';

@override
String get app_components_pinCodeInput_keyboardType_numeric_label =>
'Numeric';

@override
String get app_components_pinCodeInput_keyboardType_alphanumeric_label =>
'Alphanumeric';

@override
String get app_components_navigationBar_label => 'Bottom Bar';

Expand Down
11 changes: 11 additions & 0 deletions app/lib/l10n/gen/ouds_flutter_app_localizations_fr.dart
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,17 @@ class AppLocalizationsFr extends AppLocalizations {
String get app_components_pinCodeInput_hidden_password_label =>
'Hidden Password';

@override
String get app_components_pinCodeInput_keyboardType_label => 'Keyboard type';

@override
String get app_components_pinCodeInput_keyboardType_numeric_label =>
'Numeric';

@override
String get app_components_pinCodeInput_keyboardType_alphanumeric_label =>
'Alphanumeric';

@override
String get app_components_navigationBar_label => 'Bottom Bar';

Expand Down
3 changes: 3 additions & 0 deletions app/lib/l10n/ouds_flutter_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,9 @@
"app_components_pinCodeInput_error_label": "Please enter the verification code.",
"app_components_pinCodeInput_verification_error_label": "Verification failed. Check and enter the correct code.",
"app_components_pinCodeInput_hidden_password_label": "Hidden Password",
"app_components_pinCodeInput_keyboardType_label": "Keyboard type",
"app_components_pinCodeInput_keyboardType_numeric_label": "Numeric",
"app_components_pinCodeInput_keyboardType_alphanumeric_label": "Alphanumeric",

"@_components_navigation_bar": {},
"app_components_navigationBar_label": "Bottom Bar",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import 'package:flutter/material.dart';
import 'package:ouds_flutter_demo/ui/components/pin_code_input/pin_code_input_customization.dart';
import 'package:ouds_flutter_demo/ui/components/pin_code_input/pin_code_input_customization_utils.dart';
import 'package:ouds_flutter_demo/ui/components/pin_code_input/pin_code_input_enum.dart';

class PinCodeInputCodeGenerator {
static String updateCode(BuildContext context) {
Expand Down Expand Up @@ -60,6 +61,10 @@ class PinCodeInputCodeGenerator {
props.add(' isOutlined: ${state.hasOutlined},');
}

if (state.selectedKeyboardType != PinCodeKeyboardTypeEnum.numeric) {
props.add(' keyboardType: OudsPinCodeInputKeyboardType.${state.selectedKeyboardType.name},');
}

if (props.isEmpty) {
return "digitInputDecoration: OudsDigitInputDecoration(),";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class PinCodeInputCustomizationState extends CustomizationWidgetState<PinCodeInp
late final PinCodePlaceholderTextState pinCodePlaceholderTextState = PinCodePlaceholderTextState(setState);
late final OutlinedState outlinedState = OutlinedState(setState);
late final ConstrainedMaxWidthState constrainedMaxWidthState = ConstrainedMaxWidthState(setState);
late final PinCodeKeyboardTypeState pinCodeKeyboardTypeState = PinCodeKeyboardTypeState(setState);

// These need context, so they stay as late fields
late final PinCodeHelperTextState pinCodeHelperTextState;
Expand Down Expand Up @@ -102,6 +103,10 @@ class PinCodeInputCustomizationState extends CustomizationWidgetState<PinCodeInp
bool get hasOutlined => outlinedState.value;
set hasOutlined(bool value) => outlinedState.value = value;

// Proxy getters and setters to expose the keyboard type selection.
PinCodeKeyboardTypeEnum get selectedKeyboardType => pinCodeKeyboardTypeState.selected;
set selectedKeyboardType(PinCodeKeyboardTypeEnum value) => pinCodeKeyboardTypeState.selected = value;

@override
Widget build(BuildContext context) {
return _PinCodeInputCustomization(
Expand Down Expand Up @@ -261,3 +266,25 @@ class OutlinedState {
});
}
}

/// Keyboard Type State Management
class PinCodeKeyboardTypeState {
PinCodeKeyboardTypeState(this._setState);

final void Function(void Function()) _setState;

final List<PinCodeKeyboardTypeEnum> _list = [
PinCodeKeyboardTypeEnum.numeric,
PinCodeKeyboardTypeEnum.alphanumeric,
];

List<PinCodeKeyboardTypeEnum> get list => _list;

PinCodeKeyboardTypeEnum _selected = PinCodeKeyboardTypeEnum.numeric;
PinCodeKeyboardTypeEnum get selected => _selected;
set selected(PinCodeKeyboardTypeEnum newValue) {
_setState(() {
_selected = newValue;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,14 @@ class PinCodeInputCustomizationUtils {
final label = customizationState.pinCodeErrorText;
return label.isEmpty ? null : label;
}

/// Maps the demo keyboard-type enum to the public [OudsPinCodeInputKeyboardType].
static OudsPinCodeInputKeyboardType getKeyboardType(PinCodeKeyboardTypeEnum value) {
switch (value) {
case PinCodeKeyboardTypeEnum.numeric:
return OudsPinCodeInputKeyboardType.numeric;
case PinCodeKeyboardTypeEnum.alphanumeric:
return OudsPinCodeInputKeyboardType.alphanumeric;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ class _PinCodeInputDemoState extends State<_PinCodeInputDemo> {
hiddenPassword: customizationState.hasHiddenPassword,
isOutlined: customizationState.hasOutlined,
constrainedMaxWidth: customizationState.hasConstrainedMaxWidth ? true : false,
keyboardType: PinCodeInputCustomizationUtils.getKeyboardType(customizationState.selectedKeyboardType),
),
onEditingComplete: (value) async {
final errorLabel = context.l10n.app_components_pinCodeInput_error_label;
Expand Down Expand Up @@ -280,6 +281,17 @@ class _CustomizationContentState extends State<_CustomizationContent> {
customizationState.hasOutlined = value;
},
),
CustomizableChips<PinCodeKeyboardTypeEnum>(
title: PinCodeKeyboardTypeEnum.enumName(context),
options: customizationState.pinCodeKeyboardTypeState.list,
selectedOption: customizationState.selectedKeyboardType,
getText: (option) => option.stringValue(context),
onSelected: (selectedOption) {
setState(() {
customizationState.selectedKeyboardType = selectedOption;
});
},
),
CustomizableTextField(
title: context.l10n.app_components_common_placeholder_label,
text: customizationState.pinCodePlaceholderText,
Expand Down
23 changes: 23 additions & 0 deletions app/lib/ui/components/pin_code_input/pin_code_input_enum.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,26 @@ extension CustomElementLayout on PinCodeLengthEnum {
}
}

/// Mirrors [OudsPinCodeInputKeyboardType] for the demo customization layer.
enum PinCodeKeyboardTypeEnum {
numeric,
alphanumeric;

const PinCodeKeyboardTypeEnum();

static String enumName(BuildContext context) {
return context.l10n.app_components_pinCodeInput_keyboardType_label;
}
}

extension PinCodeKeyboardTypeLabel on PinCodeKeyboardTypeEnum {
String stringValue(BuildContext context) {
switch (this) {
case PinCodeKeyboardTypeEnum.numeric:
return context.l10n.app_components_pinCodeInput_keyboardType_numeric_label;
case PinCodeKeyboardTypeEnum.alphanumeric:
return context.l10n.app_components_pinCodeInput_keyboardType_alphanumeric_label;
}
}
}

1 change: 1 addition & 0 deletions ouds_core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Library] `Filter chip` Apply high contrast theme to filter chip (selected) ([#494](https://github.com/Orange-OpenSource/ouds-flutter/issues/494))

### Changed
- [Library] `Pin code input` Add optional `keyboardType` parameter (numeric/alphanumeric) ([#733](https://github.com/Orange-OpenSource/ouds-flutter/issues/733))
- [Library] update tokens 1.9.0 - Component Bullet List ([#710](https://github.com/Orange-OpenSource/ouds-flutter/issues/710))
- [Library] update tokens 1.9.0 - Component Alert ([#672](https://github.com/Orange-OpenSource/ouds-flutter/issues/672))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,22 @@ import 'package:ouds_theme_contract/ouds_theme.dart';
/// - [constrainedMaxWidth]: When `true`, the item width is constrained to a maximum value defined by the design system.
/// When `false`, no specific width constraint is applied, allowing the component to size itself or follow external modifiers.
/// Defaults to `false`.
/// - [keyboardType]: Soft keyboard requested when a digit cell is focused. Defaults to [OudsPinCodeInputKeyboardType.numeric].
/// Use [OudsPinCodeInputKeyboardType.alphanumeric] to allow letters in addition to digits.
///
class OudsDigitInputDecoration {
final String? hintText; //placeholder
final bool hiddenPassword;
final bool isOutlined;
final bool constrainedMaxWidth;
final OudsPinCodeInputKeyboardType keyboardType;

const OudsDigitInputDecoration({
this.hintText,
this.hiddenPassword = true,
this.isOutlined = false,
this.constrainedMaxWidth = false,
this.keyboardType = OudsPinCodeInputKeyboardType.numeric,
});
}

Expand Down Expand Up @@ -196,7 +200,12 @@ class _OudsDigitInputState extends State<OudsDigitInput> {
cursorColor: pinCodeInputTextModifier.getPinCodeCursorColor(widget.isError),
controller: widget.controller,
focusNode: widget.focusNode,
keyboardType: TextInputType.number,
keyboardType: widget.digitInputDecoration!.keyboardType == OudsPinCodeInputKeyboardType.numeric
? TextInputType.number
: TextInputType.text,
inputFormatters: widget.digitInputDecoration!.keyboardType == OudsPinCodeInputKeyboardType.numeric
? <TextInputFormatter>[FilteringTextInputFormatter.digitsOnly]
: null,
textAlign: TextAlign.center,
maxLines: 1,
buildCounter: (_, {required currentLength, required isFocused, required maxLength}) => null, // to hide the counter
Expand Down
19 changes: 18 additions & 1 deletion ouds_core/lib/components/pin_code_input/ouds_pin_code_input.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ enum OudsPinCodeInputLength {
const OudsPinCodeInputLength();
}

/// The [OudsPinCodeInputKeyboardType] defines which soft keyboard the digit cells request.
///
/// - [numeric]: numeric keyboard (digits 0–9 only). Non-digit input is filtered out, including paste.
/// - [alphanumeric]: standard text keyboard. Any character is accepted.
///
/// Defaults to [numeric] to match the historical PIN behavior.
enum OudsPinCodeInputKeyboardType {
numeric,
alphanumeric;

const OudsPinCodeInputKeyboardType();
}

/// [OUDS PIN Code Input Design Guidelines](https://r.orange.fr/r/S-ouds-doc-pin-code-input)
///
/// **Reference design version : 1.2.0**
Expand Down Expand Up @@ -215,6 +228,7 @@ class _OudsPinCodeInputState extends State<OudsPinCodeInput> {
hintText: _hintText(index),
hiddenPassword: widget.digitInputDecoration.hiddenPassword,
isOutlined: widget.digitInputDecoration.isOutlined,
keyboardType: widget.digitInputDecoration.keyboardType,
),
focusNode: _focusNodes[index],
isHovered: _isHovered[index],
Expand Down Expand Up @@ -304,7 +318,10 @@ class _OudsPinCodeInputState extends State<OudsPinCodeInput> {
void _handlePaste(String value) {
final totalDigits = widget.length.digits;
final controllers = widget.controllers!;
final digits = value.characters.take(totalDigits).toList();
final sanitized = widget.digitInputDecoration.keyboardType == OudsPinCodeInputKeyboardType.numeric
? value.replaceAll(RegExp(r'\D'), '')
: value;
final digits = sanitized.characters.take(totalDigits).toList();

for (int i = 0; i < digits.length; i++) {
controllers[i].text = digits[i];
Expand Down
Loading