# TextField

> मास्क, EditMode, पासवर्ड मोड, क्लिक करने योग्य आइकन और फ़्लोटिंग caption वाला एक-पंक्ति टेक्स्ट फ़ील्ड।

Source: https://crossfly.dev/hi/docs/ui/widgets/textfield — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# TextField

`TextField` **एक-पंक्ति** टेक्स्ट प्रविष्टि है। आधार [`TextInput`](/docs/ui/widgets/textinput) के ऊपर, यह जोड़ता है: **मास्क** इंजन (तारीख, मुद्रा, कस्टम), **पासवर्ड मोड** (दिखाएँ/छिपाएँ toggle के साथ), बाएँ/दाएँ क्लिक करने योग्य आइकन, क्षैतिज रोलिंग और एक वैकल्पिक **फ़्लोटिंग caption**। प्रविष्टि व्यवहार [`EditMode`](/docs/reference) (NORMAL/DATE/CURRENCY/NUMERIC/TIME/PASSWORD) द्वारा परिभाषित होता है, जो डिफ़ॉल्ट कीबोर्ड भी चुनता है।

> 🟡 · **पैकेज:** `dev.crossfly.ui` · **विस्तार करता है:** `TextInput` · **शैली:** `TextFieldStyle` (default और focused अलग-अलग)

## कब उपयोग करें
- कोई भी **एक-पंक्ति** प्रविष्टि: नाम, ई-मेल, पासवर्ड, संख्यात्मक/मौद्रिक मान, तारीख, समय।
- मास्क वाले फ़ील्ड (CEP, टेलीफ़ोन, तारीख) या क्लिक करने योग्य आइकन वाले (साफ़ करें, खोजें, पासवर्ड आँख)।

## कब उपयोग न करें
- **बहुपंक्ति** टेक्स्ट (टिप्पणियाँ, comments) → [`TextArea`](/docs/ui/widgets/textarea) उपयोग करें।
- स्थिर विकल्पों में से चुनना → `Dropdown` / `Option` उपयोग करें ([`ui/`](/docs/ui) देखें)।

## रूप-रंग
`TextFieldStyle` की पृष्ठभूमि/बॉर्डर वाला बॉक्स, एक पंक्ति में टेक्स्ट, सिरों पर वैकल्पिक आइकन और, वैकल्पिक रूप से, एक **फ़्लोटिंग caption** (`floatingCaption`) जो फ़ोकस या सामग्री होने पर फ़ील्ड के ऊपर उठ जाता है।

``

## पूरा उदाहरण (कॉपी करें, पेस्ट करें और चलाएँ)
```java
package com.exemplo;

import dev.crossfly.ui.*;
import dev.crossfly.ui.layout.*;

/** चलाने योग्य मुख्य स्क्रीन। launcher (classname) की ओर संकेत करें और चलाएँ: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // तैरते caption वाला एक-पंक्ति फ़ील्ड
      TextField nome = new TextField().caption("Nome");
      add(LAY_AUTO, nome);

      // आउटपुट Label
      Label saida = new Label("Digite seu nome e toque em Enviar");
      add(LAY_AUTO, saida);

      // हर कुंजी पर onChange नहीं है: भेजते समय getText() पढ़ें
      Button enviar = new Button("Enviar")
         .onAction(c -> saida.setText("Olá, " + nome.getText() + "!"));
      add(LAY_AUTO, enviar);
   }
}
```

> नीचे के अंश **केवल मूल भाग** दिखाते हैं (जो `onShow()` के अंदर जाता है)। चलाने के लिए, उन्हें ऊपर दिए `MainWindow` कंकाल में रखें।

## बुनियादी उपयोग
```java
TextField nome = new TextField().caption("Nome");
container.add(LAY_AUTO, nome);
// ...
String valor = nome.getText();
```

## Constructors
| Constructor | विवरण |
|---|---|
| `TextField()` | खाली |
| `TextField(String text)` | प्रारंभिक टेक्स्ट के साथ (`null` = खाली) |

## `EditMode` (संपादन मोड)
| `EditMode` | डिफ़ॉल्ट कीबोर्ड | टिप्पणियाँ |
|---|---|---|
| `NORMAL` | `DEFAULT` | सामान्य टेक्स्ट; कस्टम मास्क हो सकता है |
| `DATE` | `DATE` | `DatePicker` खोलता है; तारीख मास्क |
| `CURRENCY` | `CALCULATOR` | मुद्रा/दशमलव, दाएँ से बाएँ मास्क |
| `NUMERIC` | `NUMERIC` | संख्यात्मक (डेस्कटॉप पर `KEYPAD` में बदल जाता है) |
| `TIME` | `TIME` | `TimePicker` खोलता है |
| `PASSWORD` | `DEFAULT` | वर्णों के स्थान पर `passwordChar` दिखाता है |

`setMode(mode)` या `setMode(mode, maskedEdit)` मोड परिभाषित करते हैं; `maskedEdit=true` मास्क द्वारा स्वतः-स्वरूपण सक्षम करता है।

## गुण और अनुकूलन
| गुण / विधि | प्रकार | डिफ़ॉल्ट | क्या करता है |
|---|---|---|---|
| `text(String)` / `setText(String)` | `TextField` / `void` | — | टेक्स्ट सेट करता है (मास्क/मुद्रा सामान्यीकृत करता है; cursor अंत में) |
| `getText()` | `String` | — | प्रदर्शित टेक्स्ट (सक्रिय होने पर मास्क **सहित**) |
| `getTextWithoutMask()` | `String` | — | "साफ़" मान (केवल अंक / स्वरूपित दशमलव) |
| `caption(String)` | `TextField` (fluente) | `null` | फ़्लोटिंग caption / placeholder |
| `setMode(EditMode[, boolean])` | `void` | `NORMAL` | संपादन मोड (+ मास्क) |
| `keyboard(Keyboard)` / `setKeyboard(Keyboard)` | `TextField` / `void` | `EditMode` द्वारा | कीबोर्ड प्रकार |
| `leftIcon(Icon[, Action])` / `rightIcon(Icon[, Action])` | `TextField` (fluente) | `null` | आइकन (वैकल्पिक क्रिया के साथ) |
| `leftIconAction(Action)` / `rightIconAction(Action)` | `TextField` (fluente) | — | आइकन क्रिया (अलग से) |
| `isPassword()` | `boolean` | — | पासवर्ड मोड में है? |
| `clearText()` | `void` | — | टेक्स्ट, मास्क और cache साफ़ करता है |
| शैली `.mask(String)` | `char[]` | — | मास्क (`9`=अंक, बाकी literal): `"99/99/9999"` |
| शैली `.validChars(String)` | `String` | `null` | अनुमत वर्ण |
| शैली `.maxLength(int)` | `int` | `0` (असीमित) | वर्ण सीमा |
| शैली `.passwordToggle(true)` | `boolean` | `false` | दिखाएँ/छिपाएँ "आँख" आइकन बनाता है |
| शैली `.floatingCaption(true)` | `boolean` | — | फ़ोकस/भरने पर caption ऊपर उठता है |
| `getDefaultCurrencyMask(int)` *(static)* | `char[]` | — | मुद्रा मास्क (`LocaleFormats` के विभाजक) |

## Callbacks और घटनाएँ
| Callback | कब ट्रिगर होता है |
|---|---|
| `onAction(Action)` (विरासत में) | `onTouchUp` में, कीबोर्ड खुलने के बाद |
| `onFocus()` / `onBlur()` (विरासत में) | फ़ोकस प्राप्ति / हानि |
| `leftIconAction` / `rightIconAction` | संबंधित आइकन को स्पर्श (और छोड़ने) पर |

कोई समर्पित `onChange` नहीं है — क्रिया के माध्यम से प्रतिक्रिया दें या `getText()`/`getTextWithoutMask()` से पूछें।

## अवस्थाएँ
- **focused:** शैली `textFieldFocused(...)`, cursor झपकता है, स्पर्श पर कीबोर्ड/picker खुलता है; `floatingCaption` हो तो caption ऊपर उठता है।
- **password:** `passwordToggle` के साथ, दायाँ आइकन `PASSWORD`↔`NORMAL` (दिखाएँ/छिपाएँ) बदलता है, default और focused शैलियों को अद्यतन करते हुए।
- **disabled / read-only:** `setEnabled(false)` या `editable=false` संपादन रोकते हैं।

### दिखाएँ/छिपाएँ toggle वाला पासवर्ड फ़ील्ड
```java
TextField senha = new TextField().caption("Senha");
senha.setMode(EditMode.PASSWORD);
senha.style(Styles.theme()
   .field(FieldRole.PASSWORD, State.NORMAL)
   .passwordToggle(true));   // "आँख" आइकन अपने आप बनाता है
container.add(LAY_AUTO, senha);
```

### मास्क + DatePicker वाली तारीख
```java
TextField data = new TextField().caption("Data");
data.setMode(EditMode.DATE, true);          // maskedEdit = true
data.style(Styles.theme()
   .field(FieldRole.NORMAL, State.NORMAL)
   .mask("99/99/9999"));
// छूने पर DatePicker खुलता है; चुनने पर फ़ील्ड भर जाती है।
container.add(LAY_AUTO, data);
```

### सत्यापन और साफ़ करने वाले आइकन के साथ CEP
```java
TextField cep = new TextField().caption("CEP");
cep.style(Styles.theme()
   .field(FieldRole.NORMAL, State.NORMAL)
   .mask("99999-999")
   .validChars("0123456789"));
cep.rightIcon(new MaterialIcon(""), c -> cep.clearText());  // "close"
container.add(LAY_AUTO, cep);

String limpo = cep.getTextWithoutMask();   // सिर्फ़ 8 अंक
```

## अच्छे अभ्यास
- मास्क के लिए, `maskedEdit` सक्षम करें (`setMode(mode, true)`) और शैली में `mask` परिभाषित करें — `maskedEdit` के बिना केवल मास्क परिभाषित करना स्वतः-स्वरूपण नहीं करता।
- persist/सत्यापन के समय `getTextWithoutMask()` (साफ़ अंक) और प्रदर्शन के समय `getText()` उपयोग करें।
- प्रत्येक फ़ील्ड में आदर्श कीबोर्ड खोलने के लिए सही `EditMode`/`Keyboard` को प्राथमिकता दें।

## सामान्य गलतियाँ
- **`mask` परिभाषित करना पर `maskedEdit` भूलना:** टेक्स्ट स्वरूपित नहीं होता। `setMode(mode, true)` उपयोग करें।
- **`getText()` पढ़कर साफ़ अंकों की अपेक्षा करना:** यह विभाजकों **सहित** लौटाता है; `getTextWithoutMask()` उपयोग करें।
- **पासवर्ड मोड के बिना `passwordToggle`:** toggle पहले से डिफ़ॉल्ट रूप से पासवर्ड निहित करता है, पर सही दृश्य के लिए `EditMode.PASSWORD` / `FieldRole.PASSWORD` की पुष्टि करें।

## यह भी देखें
- क्षेत्र गाइड: [`ui/`](/docs/ui) · रेसिपी: [`cookbook/`](/docs/cookbook)
- अवधारणा (मास्क/सत्यापन/फ़ोकस — गहराई से): [`concepts/`](/docs/concepts)
- संबंधित घटक: [`TextInput`](/docs/ui/widgets/textinput) · [`TextArea`](/docs/ui/widgets/textarea) · [`Keypad`](/docs/ui/widgets/keypad)
