Diese Seite wurde maschinell übersetzt und kann Fehler enthalten. Das englische Original lesen

Elemente

Textauswahl

Eine View mit selectable sorgt dafür, dass die Texte darin gemeinsam ausgewählt werden, wie auf einer Webseite: Eine Auswahl reicht von einer Stelle in einem Text bis zu einer Stelle in einem anderen, über Views, Text-Elemente und TextViews hinweg, in Leserichtung. Macht man ein Chat-Transkript auswählbar, kann eine Auswahl in einer Nachricht beginnen und in der nächsten enden; Kopieren legt den ausgewählten Text in die Zwischenablage, wobei nebeneinanderstehende Texte durch einen Tab und die übrigen durch einen Zeilenumbruch getrennt werden. In Rust wird es mit view().selectable(true) gesetzt, in TSX mit <View selectable>; ob ein einzelner Text ausgewählt werden kann, bestimmt sein Style userSelect.

el-text-selection.tsx
el-text-selection.tsxLive
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")),
        )
}

Layout und Aussehen der View sind Sache der Styles der App, ihr Inhalt sind ihre Children. Die Auswahl selbst gehört der Plattform: Die View zeichnet dafür nichts Eigenes.

#Ein Chat-Transkript

Ein Transkript in einer einzigen auswählbaren View wird wie eine Seite ausgewählt: Ein Ziehen beginnt in einer Antwort und endet in einer anderen, und Kopieren übernimmt den Text jeder Nachricht dazwischen.

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()),
        )),
    )
}

#Wie eine Auswahl erfolgt

Plattform Wie eine Auswahl erfolgt
macOS, Windows, Linux, GPUI Über die Texte ziehen; ein Doppelklick wählt ein Wort aus, ein Dreifachklick einen Absatz, und ein Ziehen danach geht wortweise bzw. absatzweise weiter. Shift+Klick erweitert die Auswahl. Strg / Cmd+A wählt alles in der View aus, Strg / Cmd+C kopiert, Escape oder ein Klick außerhalb hebt die Auswahl auf.
iOS, Android Ein langer Druck wählt ein Wort aus; die Griffe der Plattform erweitern die Auswahl, und ihr Bearbeitungsmenü bietet Kopieren und Alles auswählen.
Web Die eigene Auswahl des Browsers, mit seinen Gesten, seinem Menü und seinen Tastenkürzeln.

#Was ausgewählt wird

  • Texte, die ausgenommen sind: Ein Text mit userSelect: "none" (.select_none() in Rust, die Klasse select-none; ein Label, die Beschriftung eines Buttons) wird von der Auswahl und ihren Gesten übersprungen.
  • Verschachtelte Views: Eine auswählbare View innerhalb einer anderen ist Teil der äußeren, sodass eine Auswahl beide abdeckt.
  • TextView: Eine TextView mit selectable wird als eigene Einheit ausgewählt: Ihre Absätze, Listeneinträge, Zellen und Codeblöcke werden gemeinsam ausgewählt. Innerhalb einer auswählbaren View schließt sie sich der äußeren Auswahl an.
  • Einzelne Texte: Ein Text mit userSelect: "text" in keiner auswählbaren View wird für sich ausgewählt, wie es Text beschreibt.
  • Das Aussehen ist die Hervorhebung der Plattform in der selectionColor (selection:text-*) des jeweiligen Textes.
  • Listen: In einer virtualisierten List umfasst eine Auswahl die Zeilen, die gerade eingebunden sind; Zeilen, die außerhalb des sichtbaren Bereichs recycelt wurden, verlassen die Auswahl.

#Siehe auch

  • View: die Prop selectable.
  • Text: userSelect, selectionColor und die Auswahl eines einzelnen Textes.
  • TextView: Dokumente, deren Blöcke als Einheit ausgewählt werden.