एलिमेंट
टेक्स्ट चयन
selectable वाला View अपने अंदर के टेक्स्ट को एक साथ चयनित होने देता है, ठीक वैसे ही जैसे किसी वेब पेज में होता है: एक चयन एक टेक्स्ट के किसी स्थान से दूसरे टेक्स्ट के किसी स्थान तक, व्यूज़, Text एलिमेंट्स और TextView के आर-पार, पढ़ने के क्रम में चलता है। चैट ट्रांसक्रिप्ट को चयन-योग्य बनाएँ, तो चयन एक संदेश में शुरू होकर अगले संदेश में समाप्त हो सकता है; Copy चयनित टेक्स्ट को क्लिपबोर्ड पर रख देता है, जिसमें अगल-बगल के टेक्स्ट टैब से और बाकी टेक्स्ट लाइन ब्रेक से जुड़ते हैं। Rust में इसे view().selectable(true) से सेट किया जाता है, TSX में <View selectable> से; कोई एक टेक्स्ट चयन-योग्य है या नहीं, यह उसकी userSelect स्टाइल तय करती है।
import { mount, Scroll, signal, Text, View } from "nsh";
import { Input } from "nsh/base";
import { TextView } from "nsh/base";
import { platform } from "nsh";
import { field, ui } from "./palette";
const NOTES = "- Sync runs **in the background**\n- Conflicts merge *per field*";
function App() {
const pasted = signal("");
return (
<Scroll style={{ flex: 1, backgroundColor: ui().page }}>
<View style={{ width: "100%", maxWidth: 560, alignSelf: "center", padding: 20, paddingTop: 24, gap: 14 }}>
<Text style={{ fontSize: 22, fontWeight: "700", color: ui().text }}>selectable view</Text>
<Text style={{ color: ui().muted, lineHeight: 20 }}>
{platform.desktop
? "Drag with the mouse from the title into the list: one selection runs across them. Double click a word, triple click a paragraph, Ctrl / Cmd+C copies."
: "Long press a word, then drag the handles across the texts: one selection runs across them. Copy is in the menu."}
</Text>
<View selectable style={{ ...ui().card, borderRadius: 16, padding: 16, gap: 10 }}>
<Text style={{ fontSize: 17, fontWeight: "600", color: ui().text }}>Release notes</Text>
<Text style={{ color: ui().text, lineHeight: 22 }}>Version 2.4 moves the app to offline sync.</Text>
<TextView markdown={NOTES} />
<View style={{ flexDirection: "row", gap: 8 }}>
<Text style={{ userSelect: "none", color: ui().faint }}>
Updated (userSelect none)
</Text>
<Text style={{ color: ui().text }}>October 21</Text>
</View>
</View>
<Text style={{ fontSize: 12, color: ui().muted }}>Paste what you copied: the label marked userSelect none stays out of it.</Text>
<Input
multiline
value={pasted()}
onChange={({ value }) => pasted.set(value)}
placeholder="Paste here"
{...field({ style: { height: 110 } })}
/>
<Text style={{ fontSize: 12, color: ui().muted, fontVariant: ["tabular-nums"] }}>
{pasted().length} characters, {pasted() ? pasted().split("\n").length : 0} lines
</Text>
</View>
</Scroll>
);
}
mount(App);use nsh_base::text_view;
use nsh_core::prelude::*;
fn release_notes(notes: &'static str) -> impl IntoElement {
view()
.selectable(true)
.gap_3()
.p_4()
.child(text("Release notes").font_weight(FontWeight::SEMIBOLD))
.child(text_view().markdown(notes))
.child(
view()
.flex_row()
.gap_2()
.child(text("Updated").select_none().text_color(rgb(0x737373)))
.child(text("October 21")),
)
}import { Text, View } from "nsh";
import { TextView } from "nsh/base";
function ReleaseNotes(props: { notes: string }) {
return (
<View selectable class="gap-3 p-4">
<Text class="font-semibold">Release notes</Text>
<TextView markdown={props.notes} />
<View class="flex-row gap-2">
<Text style={{ userSelect: "none" }} class="text-neutral-500">Updated</Text>
<Text>October 21</Text>
</View>
</View>
);
}व्यू का लेआउट और रूप-रंग ऐप की स्टाइल से तय होते हैं, और उसकी सामग्री उसके चिल्ड्रन होते हैं। चयन स्वयं प्लेटफ़ॉर्म का होता है: व्यू उसके लिए अपना कुछ भी नहीं बनाता।
#चैट ट्रांसक्रिप्ट
एक चयन-योग्य व्यू में रखा ट्रांसक्रिप्ट एक पेज की तरह चयनित होता है: ड्रैग एक उत्तर में शुरू होकर दूसरे में समाप्त हो सकता है, और Copy बीच के हर संदेश का टेक्स्ट ले लेता है।
use nsh_base::text_view;
use nsh_core::prelude::*;
fn transcript(replies: Signal<Vec<SharedString>>) -> impl IntoElement {
scroll().flex_1().child(
view().selectable(true).p_4().gap_4().child(each(
replies,
|reply: &SharedString| reply.clone(),
|reply, _index| text_view().markdown(move || reply.get()),
)),
)
}import { Scroll, View } from "nsh";
import { TextView } from "nsh/base";
<Scroll class="flex-1">
<View selectable class="gap-4 p-4">
<Each of={replies}>{(reply) => <TextView markdown={reply()} />}</Each>
</View>
</Scroll>#चयन कैसे किया जाता है
| प्लेटफ़ॉर्म | चयन कैसे किया जाता है |
|---|---|
| macOS, Windows, Linux, GPUI | टेक्स्ट के आर-पार ड्रैग करें; डबल क्लिक एक शब्द चुनता है, ट्रिपल क्लिक एक अनुच्छेद, और उनके बाद ड्रैग करने पर चयन शब्दों या अनुच्छेदों के हिसाब से आगे बढ़ता है। Shift+क्लिक चयन को बढ़ाता है। Ctrl / Cmd+A व्यू की हर चीज़ चुनता है, Ctrl / Cmd+C कॉपी करता है, Escape या बाहर प्रेस करने पर चयन हट जाता है। |
| iOS, Android | लंबा प्रेस एक शब्द चुनता है; प्लेटफ़ॉर्म के हैंडल उसे बढ़ाते हैं, और उसके एडिट मेन्यू में Copy और Select All होते हैं। |
| Web | ब्राउज़र का अपना चयन, अपने जेस्चर, मेन्यू और शॉर्टकट के साथ। |
#यह क्या चुनता है
- बाहर रहने वाले टेक्स्ट:
userSelect: "none"वाला टेक्स्ट (Rust में.select_none(), क्लासselect-none; जैसे लेबल, बटन का कैप्शन) चयन और उसके जेस्चर के लिए छोड़ दिया जाता है। - नेस्टेड व्यूज़: किसी चयन-योग्य व्यू के अंदर का चयन-योग्य व्यू बाहरी व्यू का हिस्सा होता है, इसलिए एक चयन दोनों को कवर करता है।
- TextView:
selectableवालाTextViewअपने आप में एक इकाई की तरह चयनित होता है: उसके अनुच्छेद, सूची आइटम, सेल और कोड ब्लॉक एक साथ चयनित होते हैं। चयन-योग्य व्यू के अंदर यह बाहरी चयन में शामिल हो जाता है। - एकल टेक्स्ट:
userSelect: "text"वाला टेक्स्ट, जो किसी चयन-योग्य व्यू में नहीं है, अपने आप चयनित होता है, जैसा Text में बताया गया है। - रूप प्रत्येक टेक्स्ट की
selectionColor(selection:text-*) में प्लेटफ़ॉर्म की हाइलाइट होती है। - सूचियाँ: वर्चुअलाइज़्ड List में चयन उन पंक्तियों को कवर करता है जो माउंट हैं; दृश्य से बाहर रीसायकल हुई पंक्तियाँ चयन से बाहर हो जाती हैं।