@zephytiju/prism-common-files
v0.1.0
Published
Platform Prism common-files micro-UI (component id "common-files"): the VAULT side panel's pinned-files section — section header (COMMON FILES / PINNED ACROSS WORKSPACES) plus one File Row per pinned IFileEntry record (distinct per-kind icon, name, mono m
Readme
PrismCommonFilesListMicroUI
Platform Prism common-files micro-UI. Component id: common-files.
Published to npm as @zephytiju/prism-common-files.
The VAULT side panel's pinned-files section (independent axiom component — the panel container itself
is composed in the platform prism, never in code): the section header (COMMON FILES /
PINNED ACROSS WORKSPACES — the panel grouping's title header, owned here through configuration
keys) and one File Row per pinned IFileEntry record rendered as same-kind items at app runtime
(design decisions D3/D5): distinct per-kind icon (doc / board / world / folder glyph in the kind's
semantic token), name, mono meta line, and the ok status dot. The pinned records are read through
the EMBEDDED generated IFileEntry client over the Prism Lattice transport (typed per-method
routes; no URLs, clients, or credentials in component code). Render order under the always-present
header: error alert with a Retry button, busy skeletons on first load, guided empty state, then the
row list. Composed applications (for example Guanlan) consume it as-is; the component is
platform-owned.
Configuration keys
| Prop | Meaning |
| --- | --- |
| locale | UI locale for the component-fixed strings: "en" \| "zh-CN" (default "en") — see i18n |
| title | Section header title (defaults to the locale's sectionTitle) |
| subtitle | Section header subtitle (defaults to the locale's sectionSubtitle) |
| scope | Stable IFileEntry.list scope the pinned entries are read from (default "pinned") |
| kindPalette | Kind → semantic color token driving the row icon color (defaults: dossier/evidence/reference → ok, board → warn, world/geovision → signal, folder → accent) |
| meta | (entry) => string mono meta line (defaults to the locale's PINNED • {size} with tiered byte formatting) |
| emptyStateHint | Guidance copy for the no-pinned-files empty state (defaults to the locale's emptyHint) |
| errorTitle | Copy for the error alert title (defaults to the locale's errorTitle) |
Channel contract
| Direction | Kind | Id | Payload |
| --- | --- | --- | --- |
| invokes | Lattice | interfaces/IFileEntry/list | { scope } via the embedded generated client over useLatticeTransport — reads the pinned file entries |
| publishes | state | common-files.selected-file | { id, name, kind, ontologyInterface: "IFileEntry" } on row click |
Channel ids are string literals at every call-site so the build-time channel-graph scanner can
derive the graph. The single publication is setter-only and owned by the item-level FileRow
(which derives its selected highlight from the same shared channel, so every row bound to the
channel reflects the current selection consistently). The Lattice read uses the generated typed
client — no URLs, credentials, or generic invokes.
Audit rule
Listing pinned files is a routine read and is NOT audit-worthy. This component emits NO audit event and NO Prism event whatsoever; the Retry button simply re-runs the embedded read.
Internationalization (i18n)
The component ships en and zh-CN locale bundles — src/locales/en.json / src/locales/zh-CN.json —
and every component-fixed UI string is resolved from them (the section title and subtitle, the
PINNED • {size} default meta, the empty-state title and hint, the Retry button, and the error
title). The component renders no hardcoded copy.
{
"common-files": {
"sectionTitle": "COMMON FILES",
"sectionSubtitle": "PINNED ACROSS WORKSPACES",
"emptyTitle": "No pinned files",
"emptyHint": "Pin dossiers, boards and world views to keep them at hand across every workspace.",
"retry": "Retry",
"errorTitle": "Pinned files failed to load",
"metaDefault": "PINNED • {size}"
}
}locale?: "en" | "zh-CN"prop (default"en") selects the string table per instance.metaDefaultuses a simple{size}placeholder interpolated with the entry's tiered byte size (plain substitution, no regexes —formatMessageis exported from the package entry).- Explicit
title/subtitle/emptyStateHint/errorTitleprops override the locale strings. - Composition-authored strings are localized by the composer; component-fixed strings live in the
locale JSONs. An explicit
titleoverride (and themetacallback) is configuration-authored: a host with a localized header passes its own string per locale. - Locale bundles are namespaced under the component id (
"common-files") so a composer can deep-merge every component's bundle into ONE UI language bundle without collisions:
import { locales as commonFilesLocales } from "@zephytiju/prism-common-files";
// commonFilesLocales["zh-CN"] -> { "common-files": { … } }
const uiBundle = deepMerge(hostStrings, commonFilesLocales["zh-CN"]);The parsed bundles are exported from the package entry (locales, en, zhCN,
stringsForLocale), and the raw JSONs are also served by the ./locales/* exports subpath
(e.g. @zephytiju/prism-common-files/locales/zh-CN.json); files ships both dist and locales.
Theme
No palette is hardcoded. Every color resolves to SEMANTIC theme tokens (ok, accent,
threat, warn, signal, card, card-dark, border, line, muted, text, input,
deep, panel) consumed as CSS variables, plus --mantine-font-family-monospace for the mono
typography — the palette is supplied entirely by the host's MantineProvider. The local demo
ships TWO themes, both defined in src/demo.tsx: vaultTheme (dark), mapping each semantic token
onto the exact :root variables of the VAULT v9 prototype (deep bg, panel black, card, card-dark,
input, border, line, text, muted, mint, blue, red, amber, purple), and the contrasting
latticeLightTheme (light), mapping the SAME semantic token keys onto a different palette — the
component is skinned purely through the surrounding MantineProvider.
Source layout
src/ is strictly two parts:
- Component source (what the package compiles):
CommonFiles.tsx(the section axiom),FileRow.tsx(the per-entry row item — a sub-component library piece rendered by the section through app-runtime same-kind item rendering, never a Prism composition member),fileIcons.tsx(the per-kind icon glyphs and default kind tables),format.ts(tiered byte formatting),index.ts(public entry), andsrc/locales/(en.json,zh-CN.json,index.ts— the i18n string bundles, their resolver, and the{size}interpolation helper). - Demo: exactly ONE file,
src/demo.tsx— the two host themes (VAULT v9 + Lattice Light), the mock host action executor (createDemoExecutor) answeringinterfaces/IFileEntry/list, all demo test data (the six sample pinned entries mirroring the prototype sidebar and their meta configuration), and the demo page rendering TWOCommonFilesinstances side by side behind a global EN | 中文 language switcher (plus per-instance switches) with store buttons for every render branch and a monitor for thecommon-files.selected-filepublication.
The npm package ships dist (compiled component + type declarations + locale JSONs) and the
top-level locales/ directory (the raw JSON bundles, served by the ./locales/* exports
subpath); no demo code is published. scripts/copy-locales.mjs copies the JSON bundles into
both locations during npm run build.
Local development
npm install
npm run typecheck
npm test
npm run dev
npm run shot-demonpm install pulls the platform peers (@zephytiju/prism-react,
@zephytiju/lattice-common-interfaces) from the npm registry, along with the host-side peer
dependencies (react, react-dom, @mantine/core). When consuming the published package,
install it directly (npm install @zephytiju/prism-common-files) and provide those peer
dependencies in the host application.
The demo (npm run dev, entry src/demo.tsx) plays the host: it installs a mock host action
executor answering the embedded client's interfaces/IFileEntry/list route with the six sample
pinned entries and renders TWO CommonFiles instances side by side, each inside its own
MantineProvider with a different theme (VAULT v9 dark left, Lattice Light right). A global
EN | 中文 segmented control switches the locale prop of BOTH instances at once, and each
instance carries its own per-instance control so the two hosts can render DIFFERING locales
simultaneously. Buttons mutate the mock store and remount both instances (Reseed / Empty /
Error) so every render branch can be inspected in the browser — in both themes and both
languages — and the channel monitor shows the common-files.selected-file publication; clicking
a row in EITHER instance highlights the matching row in BOTH hosts via the shared channel.
npm run shot-demo boots the vite dev server, drives the demo in headless Chrome (LEFT
instance en, RIGHT instance zh-CN), clicks a pinned row, and captures the language switcher,
both themed instances with the selection highlight, and the channel monitor in one shot at 2x to
/tmp/guanlan-review/demo-common-files.png.
Design record
Page design: https://qcnwge0wy4s0.feishu.cn/wiki/TLFtwgBgpiW8iWkXT7rcOyKgnAd — decisions D3/D5/D6
(two-layer model, sub-component libraries, independent side-panel axiom components) and the
Common Files sidebar of the v9 interactive HTML prototype (authoritative implementation source).
Grouping doc: https://qcnwge0wy4s0.feishu.cn/wiki/MQfXweoMvirMEykeHuDcCwkhnw9 — common-files
(axiom) pinned-files list section. Visual reference: vault-standalone.html .sidebar /
.sb-head / .frow (sidebar variant).
