← בלוג

⁦Text.js 0.1⁩

⁦Text.js 0.1⁩ מביא מנגנון התאמה של ⁦React 19⁩, layout של Yoga ו-⁦App Router⁩ מבוסס מערכת קבצים לאפליקציות שמרנדרות במסוף של DevTools.

Adam

⁦Text.js 0.1⁩ קיבלה תג גרסה. זו הגרסה הראשונה עם כל שלוש השכבות: @textjs/core מציירת פריימים במסוף, @textjs/react מרנדרת ⁦React 19⁩ לתוך הפריימים האלה, ו-textjs מוסיפה ⁦App Router⁩ וממשק שורת פקודה.

App Router

נתיבים הם תיקיות בתוך app/, בהתאם למוסכמות של ⁦App Router⁩ ב-Next.js. זו התבנית dashboard מתוך create-text-app:

app/├── layout.tsx├── page.tsx├── not-found.tsx├── deployments/│   └── [id]/│       └── page.tsx└── api/    └── metrics/        └── route.ts

⁦layout⁩ עוטף כל עמוד שמתחתיו ושומר על המצב שלו במהלך הניווט. <Link> מקבל shortcut, כך שלחיצה על מקש יחיד פותחת את הקישור, ו-activeClassName מעצב את הקישור לנתיב הנוכחי:

app/layout.tsxtsx
import type { ReactNode } from "react";import { Box, KeyHint, Text, useTheme, type Metadata } from "textjs";import Link from "textjs/link";export const metadata: Metadata = { title: { default: "Acme", template: "%s · Acme" } };export default function RootLayout({ children }: { children?: ReactNode }): ReactNode {  const theme = useTheme();  return (    <Box className="flex-col w-full h-full">      <Box className="flex-row h-1 px-1 gap-3 bg-surface shrink-0">        <Text bold color={theme.fg} wrap="nowrap">          ▼ Acme        </Text>        <Link href="/" shortcut="1" className="text-muted no-underline" activeClassName="text-fg bold">          1 Metrics        </Link>        <Link href="/deployments/dpl_a1" shortcut="2" className="text-muted no-underline" activeClassName="text-fg bold">          2 Latest deploy        </Link>      </Box>      <Box className="grow flex-col px-2 pt-1">{children}</Box>      <Box className="flex-row h-1 gap-2 pl-6 shrink-0 bg-surface">        <KeyHint keys="1-2" label="navigate" />        <KeyHint keys="tab" label="focus" />        <KeyHint keys="F2" label="devtools" />      </Box>    </Box>  );}

מקטעים דינמיים פועלים כמו ב-Next.js. [id] הופך לפרמטר, [...slug] לוכד את שאר הנתיב ו-[[...slug]] מתאים גם להורה. מקטעים סטטיים מקבלים עדיפות על פני מקטעים דינמיים, וקבוצות נתיבים כמו (marketing) מארגנות קבצים בלי להוסיף דבר לכתובת ה-URL.

app/deployments/[id]/page.tsxtsx
import { Box, Text, useInput } from "textjs";import { notFound, useParams, useRouter } from "textjs/navigation";import { DEPLOYMENTS } from "../../../lib/data";export default function DeploymentPage() {  const router = useRouter();  const { id } = useParams<{ id: string }>();  const deployment = DEPLOYMENTS.find((d) => d.id === id);  useInput((e) => {    if (e.key === "escape") router.back();  });  if (!deployment) notFound();  return (    <Box className="flex-col gap-1">      <Text bold>{deployment.id}</Text>      <Text>{deployment.branch}</Text>    </Box>  );}

loading.tsx ו-error.tsx עוטפים מקטע בגבול Suspense ובגבול שגיאה. רכיב השגיאה מקבל את השגיאה ופונקציית reset:

app/deployments/error.tsxtsx
import { Box, Text, useInput, type ErrorComponentProps } from "textjs";export default function DeploymentsError({ error, reset }: ErrorComponentProps) {  useInput((e) => {    if (e.key === "r") reset();  });  return (    <Box className="flex-col grow items-center justify-center gap-1">      <Text bold>Something went wrong loading deployments.</Text>      <Text>{error.message}</Text>    </Box>  );}

מטפלי נתיבים נמצאים בתוך app/api ומחזירים Response תקני:

app/api/metrics/route.tsts
export function GET(): Response {  return Response.json({ cpu: Math.random(), memory: Math.random(), at: new Date().toISOString() });}

הנתב שומר על הסנכרון של window.location באמצעות history.pushState, כך שחזרה, מעבר קדימה וקישורים עמוקים פועלים, ו-metadata.title נכתב אל document.title. האפליקציה מציירת במסוף, והעמוד מארח משטח מיקוד שאוסף קלט.

ממשק שורת הפקודה

  • text dev מפעילה את Vite עם ⁦React Fast Refresh⁩. שמירת קובץ מעדכנת את המסוף במקום.
  • text build כותבת תוצר בנייה לסביבת ייצור של האפליקציה ומטפלי הנתיבים שלה.
  • text start מגישה את תוצר הבנייה ואת מטפלי הנתיבים.

create-text-app יוצרת שלד פרויקט מהתבנית starter או dashboard.

כלי הבדיקה

כדי לפתוח את כלי הבדיקה [▼] בתוך המסוף, יש ללחוץ על Ctrl+` או על F2 באפליקציה פועלת. הוא מציג את הנתיב התואם והפרמטרים שלו, את גודל הפריים, מספר ה-span וזמני השלבים, ואת מספר הפריימים שמנגנון בדיקת השינויים דילג עליהם. W מצייר את ה-layout של Yoga כשלד קווי.

עוד ב-0.1

@textjs/react כוללת רכיבים בשמות PascalCase (Box, Text, ScrollBox, Input, Textarea, Select, Tabs, Code, Markdown, Diff, Modal, Spinner), כלי עזר של className בסגנון Tailwind שפועלים בתאים, וערכות נושא. חישוב ה-layout מתבצע באמצעות Yoga ב-WebAssembly.

הרשימה המלאה מופיעה ביומן השינויים.