Esta página foi traduzida automaticamente e pode conter erros. Ler o original em inglês

Elementos

Seleção de texto

Uma View com selectable faz os textos dentro dela serem selecionados em conjunto, como os de uma página web: uma única seleção vai de um ponto em um texto até um ponto em outro, entre views, elementos Text e TextViews, na ordem de leitura. Torne a transcrição de um chat selecionável e uma seleção poderá começar em uma mensagem e terminar na seguinte; Copiar coloca o texto selecionado na área de transferência, com textos lado a lado separados por uma tabulação e os demais por uma quebra de linha. No Rust, ela é definida com view().selectable(true); no TSX, com <View selectable>; se um texto isolado pode ser selecionado é determinado pelo estilo 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")),
        )
}

O layout e a aparência da view são os estilos do app, e seu conteúdo são seus filhos. A seleção em si é da plataforma: a view não desenha nada próprio para ela.

#Uma transcrição de chat

Uma transcrição em uma única view selecionável é selecionada como uma só página: um arrasto começa em uma resposta e termina em outra, e Copiar leva o texto de todas as mensagens entre elas.

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

#Como uma seleção é feita

Plataforma Como uma seleção é feita
macOS, Windows, Linux, GPUI Arraste sobre os textos; um clique duplo seleciona uma palavra, um clique triplo seleciona um parágrafo, e um arrasto depois deles continua por palavras ou parágrafos. Shift+clique estende a seleção. Ctrl / Cmd+A seleciona tudo na view, Ctrl / Cmd+C copia, Escape ou um toque fora limpa a seleção.
iOS, Android Um toque longo seleciona uma palavra; as alças da plataforma a estendem, e o menu de edição da plataforma tem Copiar e Selecionar tudo.
Web A seleção do próprio navegador, com seus gestos, menu e atalhos.

#O que ela seleciona

  • Textos que ficam de fora: um texto com userSelect: "none" (.select_none() no Rust, a classe select-none; um rótulo, o título de um botão) é ignorado pela seleção e por seus gestos.
  • Views aninhadas: uma view selecionável dentro de outra faz parte da externa, então uma única seleção cobre ambas.
  • TextView: uma TextView com selectable é selecionada como uma unidade própria: seus parágrafos, itens de lista, células e blocos de código são selecionados em conjunto. Dentro de uma view selecionável, ela se junta à seleção externa.
  • Textos isolados: um texto com userSelect: "text" fora de qualquer view selecionável é selecionado por conta própria, como descrito em Text.
  • A aparência é o destaque da plataforma na selectionColor de cada texto (selection:text-*).
  • Listas: em uma List virtualizada, a seleção cobre as linhas que estão montadas; as linhas recicladas fora da área visível saem dela.

#Relacionados

  • View: a prop selectable.
  • Text: userSelect, selectionColor e a seleção de um texto isolado.
  • TextView: documentos cujos blocos são selecionados como um só.