Spaces:
Running
Running
Download src/components/InputPanel.tsx from Orion-zhen/tokenize-it: direct link, hf CLI and curl.
- Browser
- Download file 3.63 kB
-
https://huggingface.co/spaces/Orion-zhen/tokenize-it/resolve/main/src/components/InputPanel.tsx
- Command line
-
hf download hf://spaces/Orion-zhen/tokenize-it/src/components/InputPanel.tsx
-
curl -L -o InputPanel.tsx https://huggingface.co/spaces/Orion-zhen/tokenize-it/resolve/main/src/components/InputPanel.tsx
3.63 kB
| import { Eraser, LoaderCircle, Sparkles, WandSparkles } from "lucide-react"; | |
| const EXAMPLE = "Tokenization turns language into structure. 理解分词,就是理解模型如何阅读世界。"; | |
| interface InputPanelProps { | |
| text: string; | |
| ready: boolean; | |
| loading: boolean; | |
| tokenizing: boolean; | |
| dirtyModel: boolean; | |
| onTextChange: (value: string) => void; | |
| onTokenize: () => void; | |
| } | |
| export function InputPanel({ | |
| text, | |
| ready, | |
| loading, | |
| tokenizing, | |
| dirtyModel, | |
| onTextChange, | |
| onTokenize, | |
| }: InputPanelProps) { | |
| const words = text.trim() ? text.trim().split(/\s+/u).length : 0; | |
| const lines = text ? text.split(/\r?\n/u).length : 0; | |
| const disabled = !ready || loading || tokenizing || !text || dirtyModel; | |
| return ( | |
| <section className="surface p-3" aria-labelledby="input-heading"> | |
| <div className="flex items-center justify-between px-2 pb-2"> | |
| <h1 id="input-heading" className="text-sm font-semibold text-[var(--ink)]"> | |
| 输入 | |
| </h1> | |
| <span className="eyebrow">Local only</span> | |
| </div> | |
| <div className="editor-shell"> | |
| <textarea | |
| className="min-h-48 w-full resize-y bg-transparent px-4 pb-3 pt-4 text-[16px] leading-7 text-[var(--ink)] outline-none placeholder:text-[var(--muted)] sm:min-h-52" | |
| value={text} | |
| maxLength={200000} | |
| onChange={(event) => onTextChange(event.target.value)} | |
| onKeyDown={(event) => { | |
| if ((event.metaKey || event.ctrlKey) && event.key === "Enter") { | |
| event.preventDefault(); | |
| onTokenize(); | |
| } | |
| }} | |
| placeholder="写下或粘贴一段文本……" | |
| aria-label="需要 Tokenize 的文本" | |
| /> | |
| <div className="flex flex-col gap-2 border-t border-[var(--line)] px-3 py-2.5 sm:flex-row sm:items-center sm:justify-between"> | |
| <span className="font-mono text-[10px] text-[var(--muted)]"> | |
| {text.length.toLocaleString()} characters · {words.toLocaleString()} words · {lines} lines | |
| </span> | |
| <div className="flex items-center justify-end gap-1.5"> | |
| <span className="mr-1 hidden text-[9px] text-[var(--muted)] md:inline"> | |
| ⌘ / Ctrl + Enter | |
| </span> | |
| <button | |
| className="mini-icon-button" | |
| type="button" | |
| onClick={() => onTextChange(EXAMPLE)} | |
| aria-label="填入示例文本" | |
| title="示例文本" | |
| > | |
| <WandSparkles size={14} /> | |
| </button> | |
| <button | |
| className="mini-icon-button" | |
| type="button" | |
| onClick={() => onTextChange("")} | |
| aria-label="清空文本" | |
| title="清空" | |
| > | |
| <Eraser size={14} /> | |
| </button> | |
| <button | |
| className="tokenize-button ml-1 min-w-32 justify-center" | |
| type="button" | |
| onClick={onTokenize} | |
| disabled={disabled} | |
| > | |
| {tokenizing ? ( | |
| <LoaderCircle className="animate-spin" size={16} /> | |
| ) : ( | |
| <Sparkles size={16} /> | |
| )} | |
| {dirtyModel | |
| ? "重新加载模型" | |
| : loading | |
| ? "加载中" | |
| : tokenizing | |
| ? "解析中" | |
| : ready | |
| ? "Tokenize" | |
| : "先加载模型"} | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| ); | |
| } | |