TextInput example
TextInput is controlled through a value prop and a text-change event. The
controlled write handshake is shared; the public event name is framework-shaped.
import './NameInput.css';import { useState } from 'react';import { Text, TextInput, View } from '@symbiote-native/react';
export function NameInput() { const [name, setName] = useState('Symbiote');
return ( <View className="root"> <TextInput value={name} onValueChange={setName} className="input" /> <Text>Hello, {name}</Text> </View> );}.root { gap: 12px; }.input { min-width: 220px; padding: 12px; border-width: 1px; }<script setup lang="ts">import { ref } from 'vue';import { Text, TextInput, View } from '@symbiote-native/vue';
const name = ref('Symbiote');</script>
<template> <View class="root"> <TextInput v-model="name" class="input" /> <Text>Hello, {{ name }}</Text> </View></template>
<style scoped>.root { gap: 12px; }.input { min-width: 220px; padding: 12px; border-width: 1px; }</style>v-model="name" is sugar over the same :value/@value-change pair — write
that explicit form instead if you also need the raw native event, which
arrives as @value-change’s second argument: @value-change="(text, event) => …".
import { Component } from '@angular/core';import { Text, TextInput, View } from '@symbiote-native/angular';import './name-input.css';
@Component({ standalone: true, imports: [Text, TextInput, View], template: ` <View class="root"> <TextInput [(value)]="name" class="input" /> <Text>Hello, {{ name }}</Text> </View> `,})export class NameInput { name = 'Symbiote';}.root { gap: 12px; }.input { min-width: 220px; padding: 12px; border-width: 1px; }[(value)]="name" is Angular’s banana-in-a-box two-way binding, sugar over
the same [value]/(valueChange) pair — write that explicit form instead
([value]="name" (valueChange)="setName($event)") if you also need the raw
native event, which arrives on the separate (change) output: an
EventEmitter only carries one value, so (valueChange) stays text-only to
keep [(value)] working, and (change) exists purely for the raw event.
<script lang="ts"> import { Text, TextInput, View } from '@symbiote-native/svelte';
let name = $state('Symbiote');</script>
<View class="root"><TextInput value={name} onValueChange={next => (name = next)} class="input" /><Text>Hello, {name}</Text></View>
<style> .root { gap: 12px; } .input { min-width: 220px; padding: 12px; border-width: 1px; }</style>Svelte’s own element bind:value is explicitly unsupported by this
adapter’s DOM shim — there is no sugar over value/onValueChange here,
same as React. onValueChange’s second argument is the raw native event,
same controlled-write contract every other adapter shares underneath.
API takeaway
Section titled “API takeaway”| Concern | React | Vue | Angular | Svelte |
|---|---|---|---|---|
| Text prop | value |
:valueor v-model |
[value]or [(value)] |
value |
| Text change | onValueChange(text, event) |
@value-changeor v-model |
(valueChange)="handler($event)" (text only) |
onValueChange={(text, event) => …} |
| Native event | (same callback, 2nd arg) | (same emit, 2nd arg) | (change)="handler($event)" (separate output) |
(same callback, 2nd arg) |
| Imperative handle | React ref |
Vue template ref / exposed handle | @ViewChild(TextInput) (the component IS the handle) |
bind:this (a ShimElement) via hostInstance() |
StyleSheet.create works identically to a CSS class if you’d rather keep
style objects inline — see the Styling guide.