Other frameworks

React-Native

import * as React from "react";
import { View, StyleSheet, Image, Text } from "react-native";
import { useState } from "react";

const arabicToEnglish = (string) => {
  // removing non numeric characters
  const number = string.replace(/[^0-9Ù -Ù©.,]+/g, "");
  // replacing arabic numbers with english numbers
  return number.replace(/[\u0660-\u0669]/g, (digit) =>
    "٠١٢٣٤٥٦٧٨٩".indexOf(digit)
  );
};

export default function MyComponent(props) {
  const [number, setNumber] = useState(() => "");

  return (
    <>
      <View>
        <Text>This input changes arabic numbers to english numbers! </Text>
      </View>

      <View />

      <View
        value={number}
        onInput={(event) => setNumber(arabicToEnglish(event.target.value))}
        inputMode={props.inputMode ?? "numeric"}
      />
    </>
  );
}

Qwik

// GENERATED BY MITOSIS

import { Fragment, component$, h, useStore } from "@builder.io/qwik";
const arabicToEnglish = (string) => {
  // removing non numeric characters
  const number = string.replace(/[^0-9Ù -Ù©.,]+/g, "");
  // replacing arabic numbers with english numbers
  return number.replace(/[\u0660-\u0669]/g, (digit) =>
    "٠١٢٣٤٥٦٧٨٩".indexOf(digit)
  );
};
export const MyComponent = component$((props) => {
  const state = useStore({ number: "" });
  return (
    <Fragment>
      <label>This input changes arabic numbers to english numbers! </label>
      <br></br>
      <input
        value={state.number}
        onInput$={(event) =>
          (state.number = arabicToEnglish(event.target.value))
        }
        inputMode={props.inputMode ?? "numeric"}
      ></input>
    </Fragment>
  );
});
export default MyComponent;

Web Components

export interface MyComponentProps {
  inputMode?: "numeric" | "tel" | "decimal";
}

const arabicToEnglish = (string) => {
  // removing non numeric characters
  const number = string.replace(/[^0-9Ù -Ù©.,]+/g, "");
  // replacing arabic numbers with english numbers
  return number.replace(/[\u0660-\u0669]/g, (digit) =>
    "٠١٢٣٤٥٦٧٨٩".indexOf(digit)
  );
};

/**
 * Usage:
 *
 *  <my-component></my-component>
 *
 */
class MyComponent extends HTMLElement {
  get _root() {
    return this.shadowRoot || this;
  }

  constructor() {
    super();
    const self = this;

    this.state = { number: "" };
    if (!this.props) {
      this.props = {};
    }

    this.componentProps = ["inputMode"];

    // used to keep track of all nodes created by show/for
    this.nodesToDestroy = [];
    // batch updates
    this.pendingUpdate = false;

    // Event handler for 'input' event on input-my-component-1
    this.onInputMyComponent1Input = (event) => {
      this.state.number = arabicToEnglish(event.target.value);
      this.update();
    };

    if (undefined) {
      this.attachShadow({ mode: "open" });
    }
  }

  destroyAnyNodes() {
    // destroy current view template refs before rendering again
    this.nodesToDestroy.forEach((el) => el.remove());
    this.nodesToDestroy = [];
  }

  connectedCallback() {
    this.getAttributeNames().forEach((attr) => {
      const jsVar = attr.replace(/-/g, "");
      const regexp = new RegExp(jsVar, "i");
      this.componentProps.forEach((prop) => {
        if (regexp.test(prop)) {
          const attrValue = this.getAttribute(attr);
          if (this.props[prop] !== attrValue) {
            this.props[prop] = attrValue;
          }
        }
      });
    });

    this._root.innerHTML = `
      <label>This input changes arabic numbers to english numbers!</label>
      
      <br />
      
      <input
        data-el="input-my-component-1"
        data-dom-state="MyComponent-input-my-component-1"
      />`;
    this.pendingUpdate = true;

    this.render();
    this.onMount();
    this.pendingUpdate = false;
    this.update();
  }

  onMount() {}

  onUpdate() {}

  update() {
    if (this.pendingUpdate === true) {
      return;
    }
    this.pendingUpdate = true;
    this.render();
    this.onUpdate();
    this.pendingUpdate = false;
  }

  render() {
    // grab previous input state
    const preStateful = this.getStateful(this._root);
    const preValues = this.prepareHydrate(preStateful);

    // re-rendering needs to ensure that all nodes generated by for/show are refreshed
    this.destroyAnyNodes();
    this.updateBindings();

    // hydrate input state
    if (preValues.length) {
      const nextStateful = this.getStateful(this._root);
      this.hydrateDom(preValues, nextStateful);
    }
  }

  getStateful(el) {
    const stateful = el.querySelectorAll("[data-dom-state]");
    return stateful ? Array.from(stateful) : [];
  }
  prepareHydrate(stateful) {
    return stateful.map((el) => {
      return {
        id: el.dataset.domState,
        value: el.value,
        active: document.activeElement === el,
        selectionStart: el.selectionStart,
      };
    });
  }
  hydrateDom(preValues, stateful) {
    return stateful.map((el, index) => {
      const prev = preValues.find((prev) => el.dataset.domState === prev.id);
      if (prev) {
        el.value = prev.value;
        if (prev.active) {
          el.focus();
          el.selectionStart = prev.selectionStart;
        }
      }
    });
  }

  updateBindings() {
    this._root
      .querySelectorAll("[data-el='input-my-component-1']")
      .forEach((el) => {
        el.value = this.state.number;

        el.removeEventListener("input", this.onInputMyComponent1Input);
        el.addEventListener("input", this.onInputMyComponent1Input);

        el.setAttribute("inputMode", this.props.inputMode ?? "numeric");
      });
  }

  // Helper to render content
  renderTextNode(el, text) {
    const textNode = document.createTextNode(text);
    if (el?.scope) {
      textNode.scope = el.scope;
    }
    if (el?.context) {
      textNode.context = el.context;
    }
    el.after(textNode);
    this.nodesToDestroy.push(el.nextSibling);
  }
}
customElements.define("my-component", MyComponent);

Angular

import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";

import { Component, Input } from "@angular/core";

export interface MyComponentProps {
  inputMode?: "numeric" | "decimal" | "tel";
}

const arabicToEnglish = (string) => {
  // removing non numeric characters
  const number = string.replace(/[^0-9Ù -Ù©.,]+/g, "");
  // replacing arabic numbers with english numbers
  return number.replace(/[\u0660-\u0669]/g, (digit) =>
    "٠١٢٣٤٥٦٧٨٩".indexOf(digit)
  );
};

@Component({
  selector: "my-component, MyComponent",
  template: `
    <ng-container>
      <label>This input changes arabic numbers to english numbers!</label>

      <br />

      <input
        [attr.value]="number"
        (input)="number = arabicToEnglish($event.target.value)"
        [attr.inputMode]='inputMode ?? "numeric"'
      />
    </ng-container>
  `,
})
export class MyComponent {
  arabicToEnglish = arabicToEnglish;

  @Input() inputMode: MyComponentProps["inputMode"];

  number = "";
}

@NgModule({
  declarations: [MyComponent],
  imports: [CommonModule],
  exports: [MyComponent],
})
export class MyComponentModule {}

Swift

import SwiftUI
import JavaScriptCore

final class UpdateTracker: ObservableObject {
  @Published var value = 0;

  func update() {
    value += 1
  }
}

struct MyComponent: View {
  @ObservedObject var updateTracker = UpdateTracker()
  private var jsContext = JSContext()

  @State private var input1: String = ""

  func eval(code: String) -> JSValue! {
    return jsContext?.evaluateScript(code)
  }

  func setComputedState() {
    input1 = eval(code: "state.number").toString()!
  }

  init() {
    let jsSource = """
    const state = new Proxy(
      { number: "" },
      {
        set: (target, key, value) => {
          const returnVal = Reflect.set(target, key, value);
          update();
          return returnVal;
        },
      }
    );
    """
    jsContext?.exceptionHandler = { context, exception in
      print("JS Error: \(exception!)")
    }

    let updateRef = updateTracker.update
    let updateFn : @convention(block) () -> Void = { updateRef() }
    jsContext?.setObject(updateFn, forKeyedSubscript: "update" as NSString)

    jsContext?.evaluateScript(jsSource)
  }

  var body: some View {
    VStack {

      VStack() {Text("This input changes arabic numbers to english numbers!")}

      VStack() {}

      TextField("", text: $input1)

      }
      .onAppear {
        setComputedState()
      }

      }
    }

Flutter

import 'package:flutter/material.dart';

class MyComponent extends StatefulWidget {
  const MyComponent({Key? key}) : super(key: key);

  @override
  State<MyComponent> createState() => _MyComponentState();
}

class _MyComponentState extends State<MyComponent> {

  String arabicToEnglish(String input) {
    final numericValue = input.replaceAll(RegExp(r'[^Ù -Ù©0-9.,]+'), "");

    return numericValue.replaceAllMapped(RegExp(r'[\u0660-\u0669]'),
            (match) => "٠١٢٣٤٥٦٧٨٩".indexOf(match[0].toString()).toString());
  }

  final TextEditingController _controller = TextEditingController();

//  ٠١٢٣٤٥٦٧٨٩0123456

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: SizedBox(
            width: MediaQuery.of(context).size.width / 3,
            child: TextField(
              controller: _controller,
              onChanged: (val) {
                final newInput = arabicToEnglish(_controller.text);
                _controller.value = _controller.value.copyWith(
                  text: newInput,
                  selection: TextSelection.collapsed(offset: newInput.length),
                );
              },
              decoration: const InputDecoration(
                border: OutlineInputBorder(),
                hintText: 'Enter a search term'
              ),
            ),
          ),
        ),
      ),
    );
  }
}