@fasl-work/caos-app-shell

中文文档
0.26.0发布于 2026/11/12MITTypeScriptES Module零依赖近 30 天下载 5705

Shared web-app shell, workbench primitives, content primitives, design system and measured gate for the CAOS / Faena public apps (ADR-0016, ADR-0017, ADR-0071).

原始使用文档
文档目录4 节
  1. Install
  2. Use
  3. Exports
  4. Authenticated workbenches

@fasl-work/caos-app-shell

License npm Release

One release, two spellings. npm writes a version in semver (0.19.7); VERSION, the CHANGELOG and the git tag write the same release in the display form X.XX.XXX (0.19.007, tag v0.19.007), because npm forbids leading zeros (ADR-0068). Every version published on npm, its tag and its commit: docs/09_versions.md.

The shared web-app shell, route types, views, drawings, design system and measured gate of the CAOS / Faena public apps, one of the three parts of the CAOS base with the product template (CAOS_PRODUCT_TEMPLATE) and the policy (ADR-0016, ADR-0017, ADR-0071, ADR-0078). The frame, the header, the icons, the tab structure, the viewport, the areas, the text in drawings and the numbers are defined once here; every product composes them, so a fix lands in one place and no product writes them again. Documentation: docs/ (structure, tokens, navigation, views, drawings, icons and numbers, the gate, releasing).

Install

npm i -E @fasl-work/caos-app-shell        # an exact pin: the build you gated is the build you ship
# peer deps (the app provides them):
npm i react react-dom react-router lucide-react katex zustand
# optional: the house chart and the measured gate
npm i uplot && npm i -D playwright

Use

<!-- index.html: apply the stored theme and language before the first frame (THEME_BOOT_SCRIPT, ADR-0011) -->
<script>/* paste THEME_BOOT_SCRIPT here, or inject it at build */</script>
// main.tsx
import "@fasl-work/caos-app-shell/styles.css";
import "@fasl-work/caos-app-shell/chart.css"; // only with the chart entry
import { BrowserRouter, Routes, Route } from "react-router";
import { AppShell, STANDARD_ROUTES, type ShellConfig } from "@fasl-work/caos-app-shell";

const config: ShellConfig = {
  product: { name: "RotorVitals" },
  routes: STANDARD_ROUTES, // App, Introduction, Methodology, Implementation, Experiments, Benchmark
  links: { github: "https://github.com/fsantibanezleal/CAOS_RotorVitals" },
  version: "0.01.000", // X.XX.XXX, checked on mount
  build: import.meta.env.VITE_BUILD_ID, // short commit, shown beside the version
  license: { en: "MIT licence", es: "Licencia MIT" }, // required; no default
  visibility: "public", // "private" hides every source link
  contain: true, // every route is the viewport (ADR-0071 rule 1)
};

<BrowserRouter basename={import.meta.env.BASE_URL}>
  <AppShell config={config}>
    <Routes>{/* / = the workbench; the rest are DocPage routes */}</Routes>
  </AppShell>
</BrowserRouter>
  • Three route types (docs/01): the workbench (CaseWorkbench, a product about cases), the surface (SurfacePage, a hub, an explorer or a console: a head, one row of views, the open view filling the rest), the document (DocPage). Under contain each fills or scrolls inside the viewport; no product writes containment CSS.
  • Land on the tool: / is the App route; the five documentation routes are separate pages.
  • One React, one router: set resolve.dedupe: ['react', 'react-dom', 'react-router'] in Vite. A second copy leaves the shell outside the router context; AppShell reports it with console.error and names the cause.
  • Product metadata: license and visibility are required: the footer shows the product's licence and a private product shows no source link. footer.attribution accepts bilingual text or false.
  • Hub case (Faena): pass routes: [] (or one) and the nav is hidden; header and footer stay identical.
  • The App route: one CaseWorkbench is the whole route: the rail holds the case picker (cases, the CaseSelector props), the variants (variants) and your rail (parameters as Knob and ChipGroup, live values as Readout / Gauge / Verdict); the instrument holds at most six question groups, then the variant comparison and the context. Pickers and numbers live in the rail so the drawing keeps the instrument. Every control writes data-control. PlotCard and Readout take lane, provenance and a dataKey: pass useWorkbenchState().stateKey as captured when the computation started (rail and instrument share it), and a view still showing an earlier selection is overlaid as stale. Anything that loads declares data-state="loading" until it is ready; the gate waits for that, never for the network. A view whose data is absent declares data-state="unavailable" on an element a reader can see (a visible box of 40 by 12 px at least inside the instrument, opaque, its text painted inside the box: not pushed out by text-indent, cut by clip-path or under 8 px) whose rendered text states the reason (12 letters or digits in two words at least) and renders no drawing element; the gate then accepts it under G6, while an unreadable note, a declaration without a reason, or one beside a blank, collapsed or invisible chart still fails. The gate checks that a reason exists, not that it is true.
  • Fill the instrument: <PlotCard fill> takes the height its panel leaves (several fill cards share it, a .caos-views-row puts them side by side), and a Stage or <UPlotChart height="fill"> inside it gets a real size. A table (.caos-table) is sized to its rows: put it above the drawing of the same numbers, never alone.
  • Drawing: put canvas, WebGL and SVG instruments in a Stage (or useStageSize): nothing draws at zero size, and colours come from useThemeTokens() (a canvas cannot read CSS variables).
  • Charts: import { UPlotChart } from "@fasl-work/caos-app-shell/chart": x and y titles with units, series by token colour, marks for what the engine detected (placed inside the plot, haloed), a key of every series when there are two or more, a cursor readout row, theme and language rebuilds, one tick notation per axis. Categories go in BarChart (main entry, no uPlot). A drawing of your own measures its labels with the text kit (textWidth, fitLabel, niceTicks) and declares data-chart (docs/05).
  • Views in the URL: CaseWorkbench and SurfacePage hold the open view in ?view= (and the case selector the case in ?case=), so a view can be shared and survives a reload.
  • Focus mode for the App (0.14.0): <CaseWorkbench focus /> adds a Focus button to the rail head that opens the selected case's open group in the full viewport (FocusShell: the stage is the view, the rail stays), keeps ?focus=1 beside ?case= and ?view=, and returns with Escape or the exit button to the same case, group and sub-view; a product with a simulation must offer it (ADR-0070, caos-shell-gate --require-focus). See docs/04.
  • Small cards and animation (0.14.0): FlipCard and CardDeck for SMALL cards the reader scans by title (a flip card shows its title and turns to its content; a deck is a row up to four cards and a carousel above), used by the executive view for its bearers, roles, approaches and 4 C's; an executive illustration may be an animated SVG with a prefers-reduced-motion block (docs/04, docs/06).
  • Icons: lucide icons are sized by where they sit (svg.lucide); pass no size (docs/06).
  • Numbers: formatNumber(value, lang, opts) or useFormat(); never toFixed in a view. A magnitude below 1e-4 is written in scientific notation (a p-value of 1e-200 is 1E-200, not two hundred zeros); give digits, not decimals, for p-values. A percent and a unit are joined by a no-break space.
  • Documentation routes: DocPage and DocSection (each section ends in its own Refs, or states why it cites nothing), Equation with a caption, CitationsProvider and Cite (every citation has a DOI or URL). Tabs, SubTabs and TabGroups are controllable and render only the open panel inside a PanelBoundary.
  • Architecture modal: five or more tabs, each an inline SVG string (import svg from "./x.svg?raw") that uses only SHELL_TOKENS; validateArchitectureConfig reports anything else on mount.
  • Measure it: npx caos-shell-gate --serve dist --expect-brand "RotorVitals" serves the build as GitHub Pages does (no SPA fallback), or --url https://... measures the deployed origin (needs playwright). It walks every route, tab, sub-tab and case at five sizes, both themes and both languages, and fails on: a wrong subject (G1) or mode (G2), console errors and 4xx/5xx (G3), broken deep links or HTML for an artifact (G4), anything a reader cannot scroll to, see whole or click (G5), blank or underfilled drawings and an instrument under half the viewport (G6), a view that never settles (G7), loops at rest (G8), controls that change nothing (G9), labels cut or overlapping in a drawing, also in a wider fallback font (G10), a decimal point on a Spanish page (G11), a number or percentage broken across lines (G19), a vertical sub-tab list that scrolls away (G12), text under WCAG AA contrast (G13, every language on a documentation page), and a documentation page without the required areas of its kind (ADR-0017.2: executive and technical Introduction, Methodology, Implementation, Experiments, Benchmark; declared with <DocSection area="...">, waived only with a reason of 12 letters or digits in two words through floorWaivers; the executive view opens first, every Introduction section sits in a view, a method cites references, a live control is registered with data-control, and a tab list inside a section belongs to it; docs/04). The report (gate-output/gate-report.json) lists every failure and the smallest margins against each floor; index.html beside it shows every capture (G14). Details: docs/07.
  • Your own CSS: never restyle a class of reserved-classes.json components; a modifiers word (on, active, fill, wide) may be joined to your own class (.my-row.on), never used alone. The template's guard reads that list. Values come from the tokens (var(--rail-w), var(--space-3), docs/02).
  • Animated views: drive every canvas or 3D loop through usePausedViz (default paused, run once, halt on a hidden tab), never call requestAnimationFrame directly.

Exports

AppShell, STANDARD_ROUTES, WorkbenchShell, FocusShell, ArchitectureModal, validateArchitectureConfig, ThemeToggle, LanguageToggle, useThemeStore, applyTheme, readTheme, THEME_BOOT_SCRIPT, THEME_STORAGE_KEY, LANG_STORAGE_KEY, useLangStore, useShellLang, formatNumber, useFormat, NOT_AVAILABLE, SHELL_TOKENS, resolveToken, useThemeTokens, PanelBoundary, usePausedViz, createVizLoop, CaseSelector (and the caseModel helpers), Tabs, MAX_PEER_TABS, SubTabs, TabGroups, Callout, Equation, InlineMath, Figure, CitationsProvider, Cite, Refs, ReferenceList (deprecated), DocPage, DocSection, WorkbenchLayout, CaseWorkbench, MAX_WORKBENCH_GROUPS, VariantBar, LaneBadge, Readout, Gauge, Verdict, PlotCard, Knob, ChipGroup, Stage, useStageSize, makeStateKey, isStale, useWorkbenchState, WorkbenchStateContext, pick; since 0.8.0 SurfacePage, useUrlView, viewParamOf, replaceQueryParam, BREAKPOINTS, BarChart, textWidth, widestLabel, fitLabel, niceTicks, niceStep, fontFamily, formatTicks, NBSP, SCIENTIFIC_BELOW, the type ShellColorToken; since 0.9.0 ViewsRow. Since 0.14.0 FlipCard, CardDeck (with FLIP_LIMITS, FLIP_TEXT, DECK_TEXT, perPageFor, deckWindow, deckPosition), the focus prop of CaseWorkbench (CaseFocusConfig, FOCUS_TEXT, FOCUS_PARAM) and removeQueryParam. Separate entries: /chart (UPlotChart with x.log, parity, onPick; drawMarks, tickSteps, repeatedLabels, seriesStyle, sortOrder, parityRange), /keys (the storage keys, no React), /styles.css, /chart.css, /reserved-classes.json. Bin: caos-shell-gate.

Authenticated workbenches

WorkbenchShell is the shared frame for products whose authenticated UI needs a desktop sidebar and mobile bottom navigation. It renders typed routes and the main landmark while the product supplies its own stateful controls through brand, sidebarFooter, headerLead, headerActions, and overlays. Authentication, account policy, preference persistence, chat, and modal content remain product-owned. The component uses the stable core NavLink contract and supports react-router 6, 7, and 8. Browser applications on 6/7 install the matching react-router-dom, which supplies the core peer; Router 8 applications provide react-router directly. Do not mix different core and DOM majors in one application.

MIT · part of the Faena mining-analytics hub.

版本与发布记录

@fasl-work/caos-app-shell 共发布 63 个版本,首次发布于 2026/06/19;过去 12 个月发布了 63 个版本。

版本发布日期距今
0.26.0latest2026/11/122 天前
0.25.02026/11/085 天前
0.24.02026/11/086 天前
0.23.22026/11/086 天前
0.23.12026/11/086 天前
0.23.02026/11/068 天前

关于 @fasl-work/caos-app-shell 的常见问题

@fasl-work/caos-app-shell 是什么?

Shared web-app shell, workbench primitives, content primitives, design system and measured gate for the CAOS / Faena public apps (ADR-0016, ADR-0017, ADR-0071).

如何安装 @fasl-work/caos-app-shell?

在项目目录运行 npm install @fasl-work/caos-app-shell,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:katex(^0.16.0 || ^0.17.0 || ^0.18.0 || ^0.19.0)、react(^18 || ^19)、zustand(^4 || ^5)、react-dom(^18 || ^19)、lucide-react(>=0.400.0)、react-router(^6 || ^7 || ^8)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。它还提供命令行工具 caos-shell-gate,可以用 npx caos-shell-gate 直接运行。

@fasl-work/caos-app-shell 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@fasl-work/caos-app-shell 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@fasl-work/caos-app-shell 可以商用吗?

@fasl-work/caos-app-shell 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@fasl-work/caos-app-shell 的下载量有多少?

根据 npm 官方下载统计,@fasl-work/caos-app-shell 在 2026/10/15 – 2026/11/13 这 30 天内被下载 5,705 次,日均约 190 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@fasl-work/caos-app-shell 还在维护吗?

最新版本 0.26.0 发布于 2026/11/12(2 天前);至今共发布 63 个版本,其中过去 12 个月发布了 63 个;首次发布于 2026/06/19。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。