@zephytiju/prism-quick-files 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +192 -0
  2. package/dist/DropInModelCard.d.ts +9 -0
  3. package/dist/DropInModelCard.d.ts.map +1 -0
  4. package/dist/DropInModelCard.js +7 -0
  5. package/dist/FileList.d.ts +25 -0
  6. package/dist/FileList.d.ts.map +1 -0
  7. package/dist/FileList.js +23 -0
  8. package/dist/FileRow.d.ts +31 -0
  9. package/dist/FileRow.d.ts.map +1 -0
  10. package/dist/FileRow.js +54 -0
  11. package/dist/PanelHeader.d.ts +17 -0
  12. package/dist/PanelHeader.d.ts.map +1 -0
  13. package/dist/PanelHeader.js +11 -0
  14. package/dist/QuickFiles.d.ts +57 -0
  15. package/dist/QuickFiles.d.ts.map +1 -0
  16. package/dist/QuickFiles.js +75 -0
  17. package/dist/SearchBox.d.ts +13 -0
  18. package/dist/SearchBox.d.ts.map +1 -0
  19. package/dist/SearchBox.js +23 -0
  20. package/dist/SectionLabels.d.ts +9 -0
  21. package/dist/SectionLabels.d.ts.map +1 -0
  22. package/dist/SectionLabels.js +7 -0
  23. package/dist/clients.d.ts +22 -0
  24. package/dist/clients.d.ts.map +1 -0
  25. package/dist/clients.js +13 -0
  26. package/dist/dragState.d.ts +20 -0
  27. package/dist/dragState.d.ts.map +1 -0
  28. package/dist/dragState.js +56 -0
  29. package/dist/icons.d.ts +35 -0
  30. package/dist/icons.d.ts.map +1 -0
  31. package/dist/icons.js +58 -0
  32. package/dist/index.d.ts +11 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +5 -0
  35. package/dist/locales/en.json +20 -0
  36. package/dist/locales/index.d.ts +72 -0
  37. package/dist/locales/index.d.ts.map +1 -0
  38. package/dist/locales/index.js +27 -0
  39. package/dist/locales/zh-CN.json +20 -0
  40. package/dist/tokens.d.ts +19 -0
  41. package/dist/tokens.d.ts.map +1 -0
  42. package/dist/tokens.js +18 -0
  43. package/dist/types.d.ts +88 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +1 -0
  46. package/dist/useQuickFilesEntries.d.ts +16 -0
  47. package/dist/useQuickFilesEntries.d.ts.map +1 -0
  48. package/dist/useQuickFilesEntries.js +40 -0
  49. package/dist/visibleRows.d.ts +12 -0
  50. package/dist/visibleRows.d.ts.map +1 -0
  51. package/dist/visibleRows.js +57 -0
  52. package/locales/en.json +20 -0
  53. package/locales/zh-CN.json +20 -0
  54. package/package.json +65 -0
package/README.md ADDED
@@ -0,0 +1,192 @@
1
+ # PrismQuickFilesMicroUI
2
+
3
+ Platform Prism quick-files micro-UI. Component id: `quick-files`.
4
+ Published to npm as [`@zephytiju/prism-quick-files`](https://www.npmjs.com/package/@zephytiju/prism-quick-files).
5
+
6
+ The Dossier **Quick File Insert** side panel — an axiom component, sibling of the editor viewport
7
+ (not a sub-component of it): the `QUICK FILE INSERT` title header (title, subtitle, trailing meta
8
+ are component configuration keys — Prism has no composed title node), the bordered search box, the
9
+ `FILES ARE THE SHORTCUT` / `RECENT / COMMON FILES` section labels, per-prototype file rows (world
10
+ view / dossier doc / board / folder icons on semantic kind tokens, name + mono meta line, `+`
11
+ insert action) and the `DROP-IN FILE MODEL` info card. Rows are indexed through the `IFileEntry`
12
+ list query via the generated interface client over the host Lattice transport. Composed
13
+ applications (for example Guanlan) consume it as-is; the component is platform-owned.
14
+
15
+ ## D6 — the drag/insert state contract (the heart of this component)
16
+
17
+ The panel **never references any receiving component**. On insert (`+`) or drag-start of a file
18
+ row it publishes ONLY a bounded drag/insert state object carrying file metadata — never a
19
+ component reference — on the `quick-files.drag-state` Prism channel; **ESC and drag-end clear it**
20
+ (drop or cancel alike). Receivers interpret the payload themselves:
21
+
22
+ | Receiver | Interpretation |
23
+ | --- | --- |
24
+ | world view | Geovision Embed block restoring the `IGeoView` snapshot addressed by `snapshotRef` (the drop-in file model) |
25
+ | evidence pack | Evidence Table block |
26
+ | dossier | new paragraph carrying an inline reference link (per D10, links are inline in paragraph text — never standalone blocks) |
27
+ | unknown kind | paragraph with a generic inline file link |
28
+
29
+ Because only state flows between them, the panel and the editor can be composed into different
30
+ side-panel/viewport layouts without either knowing about the other (design decision D6 — this
31
+ component is the reference case).
32
+
33
+ ## Configuration keys
34
+
35
+ | Prop | Meaning |
36
+ | --- | --- |
37
+ | `locale` | UI locale for the component-fixed strings: `"en" \| "zh-CN"` (default `"en"`) — see [i18n](#internationalization-i18n) |
38
+ | `title` | Panel title header (defaults to the locale's `panelTitle`, `"QUICK FILE INSERT"`) |
39
+ | `subtitle` | Mono subtitle under the title (defaults to the locale's `panelSubtitle`) |
40
+ | `trailingMeta` | Trailing header meta (defaults to the locale's `{count} FILES` pattern with the live row count) |
41
+ | `variant` | `"rail"` (default full side panel) or `"popover"` (compact, anchored to a block's `+` control; no info card) |
42
+ | `categoryFilters` | Restrict rendered rows to these `IFileEntry` kinds (world views, dossiers, boards, evidence, folders) |
43
+ | `recencyWindowMs` | Keep rows whose `lastOpenedAt` lies within this window; entries without a timestamp are kept |
44
+ | `kindTokens` | File kind → semantic color token overrides (defaults: world view → `signal`, doc/evidence → `ok`, board → `warn`, folder → `accent`) |
45
+
46
+ ## Channel contract
47
+
48
+ | Direction | Kind | Id | Payload |
49
+ | --- | --- | --- | --- |
50
+ | publishes | state | `quick-files.drag-state` | `{ entryId, kind, name, mime, snapshotRef, sourcePanel: "quick-files" } \| null` — published on `+` insert and on drag-start, cleared (`null`) on drag-end and ESC |
51
+
52
+ Channel ids are string literals at every call-site so the build-time channel-graph scanner can
53
+ derive the graph. The publication is setter-only (`usePrismStateSetter`): the panel never
54
+ re-renders from its own or anyone's publications. The panel also mirrors the payload into the
55
+ HTML5 data transfer (`application/x-prism-quick-file`) on real drags so non-Prism drop targets
56
+ work too. The panel consumes no channels.
57
+
58
+ ## Lattice binding
59
+
60
+ Rows come from the interface-declared `interfaces/IFileEntry/list` query, invoked through the
61
+ generated `createFileEntryClient` from `@zephytiju/lattice-common-interfaces` over
62
+ `useLatticeTransport` — no URLs, clients, or credentials in component code. The generated bundle's
63
+ bounded summary (`id`/`name`/`kind`/`sizeBytes`) is a structural subset of the panel's row
64
+ projection (`mime`, `snapshotRef`, mono meta line, pin, recency); richer hosts return the superset
65
+ on the same route. Missing `mime`/`snapshotRef` fields fall back to bounded defaults (kind mime
66
+ map; the entry id as the snapshot address). The fetch lifecycle (busy skeletons, error alert with
67
+ Retry, guided empty state) is local state only — the panel publishes nothing about its own
68
+ loading.
69
+
70
+ ## Audit rule
71
+
72
+ File browsing and insertion are routine actions and are NOT audit-worthy. This component emits NO
73
+ audit event and NO Prism event of any kind — the single outbound signal is the bounded drag/insert
74
+ state above.
75
+
76
+ ## Internationalization (i18n)
77
+
78
+ The component ships `en` and `zh-CN` locale bundles — `src/locales/en.json` / `src/locales/zh-CN.json` —
79
+ and every component-fixed UI string is resolved from them (the panel title default, subtitle
80
+ default, `{count} FILES` pattern, search placeholder and label, section labels, the DROP-IN FILE
81
+ MODEL card, empty/no-match copy, error title, Retry). The component renders no hardcoded copy.
82
+
83
+ ```json
84
+ {
85
+ "quick-files": {
86
+ "panelTitle": "QUICK FILE INSERT",
87
+ "panelSubtitle": "WORLD VIEWS, DOSSIERS, BOARDS, EVIDENCE",
88
+ "trailingMetaCount": "{count} FILES",
89
+ "searchPlaceholder": "Search recent files and world views",
90
+ "sectionHint": "FILES ARE THE SHORTCUT",
91
+ "sectionRecent": "RECENT / COMMON FILES",
92
+ "infoCardTitle": "DROP-IN FILE MODEL",
93
+ "infoCardBody": "World views are versioned spatial metadata files. …",
94
+ "emptyTitle": "No files yet",
95
+ "retry": "Retry"
96
+ }
97
+ }
98
+ ```
99
+
100
+ - `locale?: "en" | "zh-CN"` prop (default `"en"`) selects the string table per instance.
101
+ - `trailingMetaCount` uses a simple `{count}` placeholder interpolated with the visible row count
102
+ (plain substitution, no regexes — `formatMessage` is exported from the package entry).
103
+ - **Composition-authored strings are localized by the composer; component-fixed strings live in the
104
+ locale JSONs.** An explicit `title` / `subtitle` / `trailingMeta` override is
105
+ configuration-authored: a host with a localized title passes its own string per locale.
106
+ - Locale bundles are namespaced under the component id (`"quick-files"`) so a composer can
107
+ deep-merge every component's bundle into ONE UI language bundle without collisions:
108
+
109
+ ```ts
110
+ import { locales as quickFilesLocales } from "@zephytiju/prism-quick-files";
111
+ // quickFilesLocales["zh-CN"] -> { "quick-files": { … } }
112
+ const uiBundle = deepMerge(hostStrings, quickFilesLocales["zh-CN"]);
113
+ ```
114
+
115
+ The parsed bundles are exported from the package entry (`locales`, `en`, `zhCN`,
116
+ `stringsForLocale`), and the raw JSONs are also served by the `./locales/*` exports subpath
117
+ (e.g. `@zephytiju/prism-quick-files/locales/zh-CN.json`); `files` ships both `dist` and `locales`.
118
+
119
+ ## Theme
120
+
121
+ No palette is hardcoded. Every color resolves to SEMANTIC theme tokens (`ok`, `accent`,
122
+ `threat`, `warn`, `signal`, `card`, `card-dark`, `border`, `line`, `text`, `muted`, `input`,
123
+ `deep`, `panel`) consumed as CSS variables, plus `--mantine-font-family-monospace` for the mono
124
+ typography — the palette is supplied entirely by the host's `MantineProvider`. The prototype's
125
+ kind hues map onto tokens: purple world views → `signal`, mint docs → `ok`, amber boards → `warn`,
126
+ blue folders (and the `+` insert action, search border, subtitle) → `accent`. The local demo ships
127
+ TWO themes, both defined in `src/demo.tsx`: `geovisionTheme` (dark), mapping each semantic token
128
+ onto the exact `:root` variables of the authoritative v9 prototype, and the contrasting
129
+ `latticeLightTheme` (light) mapping the SAME semantic token keys onto a different palette — the
130
+ component is skinned purely through the surrounding `MantineProvider`.
131
+
132
+ ## Source layout
133
+
134
+ `src/` is strictly two parts:
135
+
136
+ - Component source (what the package compiles): `QuickFiles.tsx` (the panel),
137
+ `FileRow.tsx` (item-level row owning the `quick-files.drag-state` publication),
138
+ `icons.tsx` (the prototype's `.fic` glyph set + kind token defaults), `types.ts` (bounded
139
+ channel/route types), `index.ts` (public entry), and `src/locales/` (`en.json`, `zh-CN.json`,
140
+ `index.ts` — the i18n string bundles, their resolver, and the `{count}` interpolation helper).
141
+ - Demo: exactly ONE file, `src/demo.tsx` — the two host themes (GeoVision v9 + Lattice Light),
142
+ the mock host executor answering `interfaces/IFileEntry/list` with the nine prototype rows,
143
+ the demo page rendering THREE `QuickFiles` hosts (dark rail + light rail + light popover with
144
+ category filters) behind a global EN | 中文 switcher (plus per-instance switches), and the D6
145
+ demonstration: a channel monitor reading the published drag state plus a mock receiver (drop
146
+ target) that consumes the SAME channel and interprets each kind its own way.
147
+
148
+ The npm package ships `dist` (compiled component + type declarations + locale JSONs) and the
149
+ top-level `locales/` directory (the raw JSON bundles, served by the `./locales/*` exports
150
+ subpath); no demo code is published. `scripts/copy-locales.mjs` copies the JSON bundles into
151
+ both locations during `npm run build`.
152
+
153
+ ## Local development
154
+
155
+ ```sh
156
+ npm install
157
+ npm run typecheck
158
+ npm test
159
+ npm run dev
160
+ npm run shot-demo
161
+ ```
162
+
163
+ `npm install` pulls the platform peers (`@zephytiju/prism-react`,
164
+ `@zephytiju/lattice-common-interfaces`) from the npm registry, along with the host-side peer
165
+ dependencies (`react`, `react-dom`, `@mantine/core`). When consuming the published package,
166
+ install it directly (`npm install @zephytiju/prism-quick-files`) and provide those peer
167
+ dependencies in the host application.
168
+
169
+ The demo (`npm run dev`, entry `src/demo.tsx`) plays the host: it installs a mock action executor
170
+ answering the interface-declared `IFileEntry` list route with the nine sample rows of the v9
171
+ prototype, then renders three themed `QuickFiles` hosts — GeoVision v9 dark (rail), Lattice
172
+ Light (rail), and a Lattice Light popover host restricted to world views + dossiers. A global
173
+ EN | 中文 segmented control switches the `locale` prop of every instance at once, and each
174
+ instance carries its own per-instance control so the hosts can render DIFFERING locales
175
+ simultaneously. Below the hosts, the D6 demonstration: the `quick-files.drag-state` monitor
176
+ shows the last published `{entryId, kind, name, mime, snapshotRef, sourcePanel}` payload, and the
177
+ mock receiver materializes typed blocks from each payload (world view → Geovision Embed restoring
178
+ the IGeoView snapshot; evidence pack → Evidence Table; dossier → paragraph with an inline link;
179
+ unknown → generic inline file link per D10). Host affordances demonstrate clearing the state
180
+ (same as ESC) and the error + Retry branch. `npm run shot-demo` boots the vite dev server, drives
181
+ the demo in headless Chrome (dark host `en`, light host `zh-CN`), inserts a world view and a
182
+ dossier row, and captures both states to `/tmp/guanlan-review/demo-quick-files-themes.png` and
183
+ `/tmp/guanlan-review/demo-quick-files-insert.png`.
184
+
185
+ ## Design record
186
+
187
+ https://qcnwge0wy4s0.feishu.cn/wiki/B87YwS2PriaGvlkAcOtctKm8nsd — decisions D4 (interface
188
+ binding), D5 (component tiers — this is an axiom component), D6 (cross-component state passing —
189
+ this component is the reference case) and D10 (inline links, embedded block chrome).
190
+ Component doc: https://qcnwge0wy4s0.feishu.cn/wiki/KhFPwrEOIiALwpkvofrcc9KYnEe. Visual reference:
191
+ the authoritative v9 HTML prototype (`dossier-editor-standalone-v9.html`, `.qins` / `.qrow` /
192
+ `.fic`), attached to the design record.
@@ -0,0 +1,9 @@
1
+ export interface QuickFilesDropInModelCardProps {
2
+ /** Locale-resolved card title (DROP-IN FILE MODEL). */
3
+ readonly title: string;
4
+ /** Locale-resolved card body copy. */
5
+ readonly body: string;
6
+ }
7
+ /** The DROP-IN FILE MODEL info card of the rail variant (v9 bottom card). */
8
+ export declare function QuickFilesDropInModelCard({ title, body }: QuickFilesDropInModelCardProps): import("react").JSX.Element;
9
+ //# sourceMappingURL=DropInModelCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DropInModelCard.d.ts","sourceRoot":"","sources":["../src/DropInModelCard.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,8BAA8B;IAC7C,uDAAuD;IACvD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,6EAA6E;AAC7E,wBAAgB,yBAAyB,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,8BAA8B,+BAyBxF"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "@mantine/core";
3
+ import { ACCENT, BORDER, CARD_DARK_BG, MONO, MUTED } from "./tokens.js";
4
+ /** The DROP-IN FILE MODEL info card of the rail variant (v9 bottom card). */
5
+ export function QuickFilesDropInModelCard({ title, body }) {
6
+ return (_jsxs(Box, { p: 10, style: { background: CARD_DARK_BG, border: `1px solid ${BORDER}`, borderRadius: 5 }, "data-testid": "quick-files-info-card", children: [_jsx(Text, { ff: MONO, fz: 9, fw: 500, style: { color: ACCENT, letterSpacing: "0.04em", marginBottom: 6 }, children: title }), _jsx(Text, { ff: MONO, fz: 9, style: { color: MUTED, lineHeight: 1.6 }, "data-testid": "quick-files-info-body", children: body })] }));
7
+ }
@@ -0,0 +1,25 @@
1
+ import type { QuickFilesStrings } from "./locales/index.js";
2
+ import type { QuickFileEntry, QuickFilesStatus } from "./types.js";
3
+ export interface QuickFilesFileListProps {
4
+ /** Lifecycle of the most recent list fetch (busy / error / ready). */
5
+ readonly status: QuickFilesStatus;
6
+ /** The raw fetched entries (null while the first query is in flight). */
7
+ readonly entries: readonly QuickFileEntry[] | null;
8
+ /** Filtered + ordered rows to render (see selectVisibleRows). */
9
+ readonly rows: readonly QuickFileEntry[];
10
+ /** Locale string table for the region's fixed copy. */
11
+ readonly strings: QuickFilesStrings;
12
+ /** File kind → semantic color token overrides (defaults are curated). */
13
+ readonly kindTokens: Readonly<Record<string, string>>;
14
+ /** Re-runs the list query (the error state's Retry action). */
15
+ readonly onRetry: () => void;
16
+ }
17
+ /**
18
+ * The panel's rows region: busy skeletons while the first list query is in
19
+ * flight, an error alert with Retry, a guided empty state, the no-matches
20
+ * notice, and the file rows themselves (kind glyph + semantic token, name,
21
+ * mono meta line, + insert action — each row publishing the bounded drag
22
+ * state itself, per FileRow).
23
+ */
24
+ export declare function QuickFilesFileList({ status, entries, rows, strings, kindTokens, onRetry }: QuickFilesFileListProps): import("react").JSX.Element;
25
+ //# sourceMappingURL=FileList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileList.d.ts","sourceRoot":"","sources":["../src/FileList.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,cAAc,EAAkB,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAInF,MAAM,WAAW,uBAAuB;IACtC,sEAAsE;IACtE,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,GAAG,IAAI,CAAC;IACnD,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,CAAC;IACzC,uDAAuD;IACvD,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACtD,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,uBAAuB,+BA+DlH"}
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Alert, Button, Card, Group, Skeleton, Stack, Text } from "@mantine/core";
3
+ import { FileRow } from "./FileRow.js";
4
+ import { DEFAULT_KIND_GLYPHS, DEFAULT_KIND_TOKENS } from "./icons.js";
5
+ import { buildQuickFileDragState } from "./dragState.js";
6
+ import { formatMessage } from "./locales/index.js";
7
+ import { formatBytes } from "./visibleRows.js";
8
+ import { MUTED } from "./tokens.js";
9
+ /**
10
+ * The panel's rows region: busy skeletons while the first list query is in
11
+ * flight, an error alert with Retry, a guided empty state, the no-matches
12
+ * notice, and the file rows themselves (kind glyph + semantic token, name,
13
+ * mono meta line, + insert action — each row publishing the bounded drag
14
+ * state itself, per FileRow).
15
+ */
16
+ export function QuickFilesFileList({ status, entries, rows, strings, kindTokens, onRetry }) {
17
+ return (_jsx(_Fragment, { children: status.phase === "error" ? (_jsx(Alert, { variant: "light", color: "threat", title: strings.errorTitle, "data-testid": "quick-files-error", children: _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { size: "sm", "data-testid": "quick-files-error-message", children: status.message }), _jsx(Group, { children: _jsx(Button, { variant: "default", "data-testid": "quick-files-retry", onClick: onRetry, children: strings.retry }) })] }) })) : entries === null ? (_jsx(Stack, { gap: 8, "data-testid": "quick-files-loading", "aria-busy": "true", children: [0, 1, 2, 3].map((row) => (_jsx(Skeleton, { height: 58, radius: 5 }, row))) })) : entries.length === 0 ? (_jsx(Card, { withBorder: true, "data-testid": "quick-files-empty", children: _jsxs(Stack, { gap: "xs", children: [_jsx(Text, { fw: 500, children: strings.emptyTitle }), _jsx(Text, { size: "sm", children: strings.emptyHint })] }) })) : rows.length === 0 ? (_jsx(Text, { size: "sm", c: MUTED, "data-testid": "quick-files-no-matches", children: strings.noMatches })) : (_jsx(Stack, { gap: 8, "data-testid": "quick-files-rows", children: rows.map((entry) => {
18
+ const glyph = entry.glyph ?? DEFAULT_KIND_GLYPHS[entry.kind] ?? "doc";
19
+ const token = kindTokens[entry.kind] ?? DEFAULT_KIND_TOKENS[entry.kind] ?? "accent";
20
+ const meta = entry.meta ?? `${entry.kind.toUpperCase()} • ${formatBytes(entry.sizeBytes)}`;
21
+ return (_jsx(FileRow, { entry: entry, dragState: buildQuickFileDragState(entry), glyph: glyph, kindToken: token, insertLabel: formatMessage(strings.insertLabel, { name: entry.name }), dragLabel: formatMessage(strings.dragLabel, { name: entry.name }), meta: meta }, entry.id));
22
+ }) })) }));
23
+ }
@@ -0,0 +1,31 @@
1
+ import type { QuickFileDragState, QuickFileEntry, QuickFileGlyph } from "./types.js";
2
+ export interface FileRowProps {
3
+ /** The IFileEntry projection the row renders. */
4
+ readonly entry: QuickFileEntry;
5
+ /** Bounded drag/insert payload builder output for this row. */
6
+ readonly dragState: QuickFileDragState;
7
+ /** Icon glyph for the row's kind (boards pick workflow vs audit). */
8
+ readonly glyph: QuickFileGlyph;
9
+ /** Semantic color token driving the icon hue (host theme resolves it). */
10
+ readonly kindToken: string;
11
+ /** Accessible label for the + insert action (locale-resolved). */
12
+ readonly insertLabel: string;
13
+ /** Accessible label for the drag handle (locale-resolved). */
14
+ readonly dragLabel: string;
15
+ /** Mono meta line rendered under the name (defaults to kind + size). */
16
+ readonly meta: string;
17
+ }
18
+ /**
19
+ * Per-prototype Quick File Insert row (v9): kind icon, name, mono meta line
20
+ * and the + insert action.
21
+ *
22
+ * The row OWNS the "quick-files.drag-state" channel binding (D6 reference
23
+ * case): the + insert action and a drag-start each publish ONLY the bounded
24
+ * file-metadata state {entryId, kind, name, mime, snapshotRef, sourcePanel}
25
+ * — never a component reference — and drag-end (drop OR cancel) clears it.
26
+ * Any receiver (editor viewport body, block insertion point, another panel)
27
+ * interprets the payload in its own way; the row knows none of them. The
28
+ * setter-only binding means publications never re-render the panel.
29
+ */
30
+ export declare function FileRow({ entry, dragState, glyph, kindToken, insertLabel, dragLabel, meta }: FileRowProps): import("react").JSX.Element;
31
+ //# sourceMappingURL=FileRow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileRow.d.ts","sourceRoot":"","sources":["../src/FileRow.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAErF,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAC;IACvC,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAKD;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,YAAY,+BAkFzG"}
@@ -0,0 +1,54 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback } from "react";
3
+ import { Box, Group, Text, UnstyledButton } from "@mantine/core";
4
+ import { usePrismStateSetter } from "@zephytiju/prism-react";
5
+ import { FileKindIcon } from "./icons.js";
6
+ import { DRAG_STATE_CHANNEL } from "./dragState.js";
7
+ import { ACCENT, BORDER, CARD_BG, MONO, MUTED, TEXT } from "./tokens.js";
8
+ /** MIME type carried in the HTML5 drag data so non-Prism drop targets work too. */
9
+ const DRAG_MIME = "application/x-prism-quick-file";
10
+ /**
11
+ * Per-prototype Quick File Insert row (v9): kind icon, name, mono meta line
12
+ * and the + insert action.
13
+ *
14
+ * The row OWNS the "quick-files.drag-state" channel binding (D6 reference
15
+ * case): the + insert action and a drag-start each publish ONLY the bounded
16
+ * file-metadata state {entryId, kind, name, mime, snapshotRef, sourcePanel}
17
+ * — never a component reference — and drag-end (drop OR cancel) clears it.
18
+ * Any receiver (editor viewport body, block insertion point, another panel)
19
+ * interprets the payload in its own way; the row knows none of them. The
20
+ * setter-only binding means publications never re-render the panel.
21
+ */
22
+ export function FileRow({ entry, dragState, glyph, kindToken, insertLabel, dragLabel, meta }) {
23
+ const publishDragState = usePrismStateSetter(DRAG_STATE_CHANNEL);
24
+ const insert = useCallback(() => {
25
+ publishDragState(dragState);
26
+ }, [dragState, publishDragState]);
27
+ const iconColor = `var(--mantine-color-${kindToken}-filled)`;
28
+ return (_jsxs(Group, { gap: 10, wrap: "nowrap", align: "center", px: 12, style: {
29
+ minHeight: 58,
30
+ background: CARD_BG,
31
+ border: `1px solid ${BORDER}`,
32
+ borderRadius: 5,
33
+ cursor: "grab",
34
+ }, "data-testid": `quick-files-row-${entry.id}`, draggable: true, "aria-label": dragLabel, onDragStart: (event) => {
35
+ publishDragState(dragState);
36
+ // jsdom dispatches synthetic drags without a dataTransfer; real
37
+ // browsers always provide one.
38
+ if (event.dataTransfer) {
39
+ event.dataTransfer.effectAllowed = "copy";
40
+ event.dataTransfer.setData(DRAG_MIME, JSON.stringify(dragState));
41
+ }
42
+ }, onDragEnd: () => {
43
+ // Drop or cancel — the drag session is over either way: clear.
44
+ publishDragState(null);
45
+ }, children: [_jsx(Box, { style: { color: iconColor, flexShrink: 0 }, "data-testid": `quick-files-icon-${entry.id}`, children: _jsx(FileKindIcon, { glyph: glyph }) }), _jsxs(Box, { style: { flex: 1, minWidth: 0 }, children: [_jsx(Text, { fz: 12, fw: 500, style: {
46
+ color: TEXT,
47
+ whiteSpace: "nowrap",
48
+ overflow: "hidden",
49
+ textOverflow: "ellipsis",
50
+ }, "data-testid": `quick-files-name-${entry.id}`, children: entry.name }), _jsx(Text, { ff: MONO, fz: 9, style: { color: MUTED, letterSpacing: "0.03em" }, "data-testid": `quick-files-meta-${entry.id}`, children: meta })] }), _jsx(UnstyledButton, { type: "button", fz: 18, fw: 500, lh: 1, style: { color: ACCENT, flexShrink: 0 }, "aria-label": insertLabel, "data-testid": `quick-files-insert-${entry.id}`, onClick: (event) => {
51
+ event.stopPropagation();
52
+ insert();
53
+ }, children: "+" })] }));
54
+ }
@@ -0,0 +1,17 @@
1
+ export interface QuickFilesPanelHeaderProps {
2
+ /** Rail variant pads the header taller than the popover variant. */
3
+ readonly rail: boolean;
4
+ /** Resolved title — component configuration key with locale default applied. */
5
+ readonly title: string;
6
+ /** Resolved mono subtitle under the title. */
7
+ readonly subtitle: string;
8
+ /** Resolved trailing header meta (e.g. "{count} FILES"). */
9
+ readonly trailingMeta: string;
10
+ }
11
+ /**
12
+ * The panel's title header (v9 QUICK FILE INSERT block): title, mono subtitle
13
+ * and trailing meta — all component configuration keys (Prism has no composed
14
+ * title node), rendered with locale defaults by the composition root.
15
+ */
16
+ export declare function QuickFilesPanelHeader({ rail, title, subtitle, trailingMeta }: QuickFilesPanelHeaderProps): import("react").JSX.Element;
17
+ //# sourceMappingURL=PanelHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PanelHeader.d.ts","sourceRoot":"","sources":["../src/PanelHeader.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,0BAA0B;IACzC,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8CAA8C;IAC9C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,0BAA0B,+BAyCxG"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Group, Stack, Text } from "@mantine/core";
3
+ import { ACCENT, CARD_DARK_BG, MONO, MUTED, TEXT } from "./tokens.js";
4
+ /**
5
+ * The panel's title header (v9 QUICK FILE INSERT block): title, mono subtitle
6
+ * and trailing meta — all component configuration keys (Prism has no composed
7
+ * title node), rendered with locale defaults by the composition root.
8
+ */
9
+ export function QuickFilesPanelHeader({ rail, title, subtitle, trailingMeta }) {
10
+ return (_jsxs(Group, { justify: "space-between", align: "flex-start", wrap: "nowrap", gap: 8, px: 16, pt: rail ? 14 : 10, pb: 10, style: { background: CARD_DARK_BG }, "data-testid": "quick-files-header", children: [_jsxs(Stack, { gap: 4, miw: 0, children: [_jsx(Text, { fz: 13, fw: 600, style: { color: TEXT, letterSpacing: "0.01em" }, "data-testid": "quick-files-title", children: title }), _jsx(Text, { ff: MONO, fz: 9, style: { color: ACCENT, letterSpacing: "0.04em" }, "data-testid": "quick-files-subtitle", children: subtitle })] }), _jsx(Text, { ff: MONO, fz: 9, style: { color: MUTED, letterSpacing: "0.03em", flexShrink: 0, paddingTop: 2 }, "data-testid": "quick-files-trailing-meta", children: trailingMeta })] }));
11
+ }
@@ -0,0 +1,57 @@
1
+ import type { QuickFilesLocale } from "./locales/index.js";
2
+ export interface QuickFilesProps {
3
+ /** Panel title header (component configuration key; defaults to the locale's `panelTitle`). */
4
+ readonly title?: string;
5
+ /** Mono subtitle under the title (defaults to the locale's `panelSubtitle`). */
6
+ readonly subtitle?: string;
7
+ /** Trailing header meta (defaults to the locale's `{count} FILES` pattern). */
8
+ readonly trailingMeta?: string;
9
+ /** Layout variant: "rail" (default full side panel) or "popover" (compact, no info card). */
10
+ readonly variant?: "rail" | "popover";
11
+ /** Category filters — restrict rendered rows to these IFileEntry kinds (config key). */
12
+ readonly categoryFilters?: readonly string[];
13
+ /**
14
+ * Recency window in milliseconds — keep rows whose `lastOpenedAt` lies within
15
+ * the window (entries without a timestamp are kept; config key).
16
+ */
17
+ readonly recencyWindowMs?: number;
18
+ /** File kind → semantic color token overrides (defaults are curated). */
19
+ readonly kindTokens?: Readonly<Record<string, string>>;
20
+ /** UI locale for the component-fixed strings (default "en"). */
21
+ readonly locale?: QuickFilesLocale;
22
+ }
23
+ /**
24
+ * Platform Prism quick-files micro-UI (component id "quick-files"): the
25
+ * Dossier Quick File Insert side panel — an axiom component, sibling of the
26
+ * editor viewport (NOT a sub-component of it).
27
+ *
28
+ * Renders the per-prototype panel of the authoritative v9 HTML prototype: the
29
+ * QUICK FILE INSERT title header (title, subtitle and trailing meta are
30
+ * component configuration keys — Prism has no composed title node), the
31
+ * bordered search box, the FILES ARE THE SHORTCUT / RECENT-COMMON FILES
32
+ * section labels, file rows (world view / dossier doc / board / folder icons
33
+ * with semantic kind tokens, name + mono meta line, + insert action) and the
34
+ * DROP-IN FILE MODEL info card. Rows are indexed through the IFileEntry list
35
+ * query.
36
+ *
37
+ * D6 REFERENCE CASE — the panel NEVER references any receiving component. On
38
+ * insert (+) or drag-start of a file row it publishes ONLY a bounded drag /
39
+ * insert state {entryId, kind, name, mime, snapshotRef, sourcePanel} on the
40
+ * "quick-files.drag-state" Prism channel; receivers interpret it themselves
41
+ * (world view → geovision embed restoring an IGeoView snapshot; evidence pack
42
+ * → evidence table; dossier → paragraph with inline link; unknown → generic
43
+ * inline file link, per D10). ESC and drag-end clear the state. No audit
44
+ * events: file browsing/insertion is routine, not audit-worthy.
45
+ *
46
+ * No palette is hardcoded: every color resolves to semantic theme tokens
47
+ * (ok / accent / warn / signal / card / card-dark / border / line / muted /
48
+ * text …) supplied by the host's MantineProvider.
49
+ *
50
+ * COMPOSITION ROOT of the focused sub-component files: PanelHeader (title
51
+ * header), SearchBox, SectionLabels, FileList (+ FileRow, icons),
52
+ * DropInModelCard, and the hooks/modules clients.ts (Lattice clients),
53
+ * dragState.ts (bounded drag-state publication), useQuickFilesEntries.ts
54
+ * (list lifecycle) and visibleRows.ts (row visibility/ordering rules).
55
+ */
56
+ export declare function QuickFiles({ title, subtitle, trailingMeta, variant, categoryFilters, recencyWindowMs, kindTokens, locale, }: QuickFilesProps): import("react").JSX.Element;
57
+ //# sourceMappingURL=QuickFiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QuickFiles.d.ts","sourceRoot":"","sources":["../src/QuickFiles.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,MAAM,WAAW,eAAe;IAC9B,+FAA+F;IAC/F,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,+EAA+E;IAC/E,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,6FAA6F;IAC7F,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,wFAAwF;IACxF,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,yEAAyE;IACzE,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,gEAAgE;IAChE,QAAQ,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,OAAgB,EAChB,eAAe,EACf,eAAe,EACf,UAAe,EACf,MAAa,GACd,EAAE,eAAe,+BA0EjB"}
@@ -0,0 +1,75 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMemo, useState } from "react";
3
+ import { Stack } from "@mantine/core";
4
+ import { useLatticeTransport } from "@zephytiju/prism-react";
5
+ import { createQuickFilesClients } from "./clients.js";
6
+ import { useQuickFileDragStatePublish } from "./dragState.js";
7
+ import { QuickFilesDropInModelCard } from "./DropInModelCard.js";
8
+ import { QuickFilesFileList } from "./FileList.js";
9
+ import { QuickFilesPanelHeader } from "./PanelHeader.js";
10
+ import { QuickFilesSearchBox } from "./SearchBox.js";
11
+ import { QuickFilesSectionLabels } from "./SectionLabels.js";
12
+ import { CARD_BG, LINE } from "./tokens.js";
13
+ import { useQuickFilesEntries } from "./useQuickFilesEntries.js";
14
+ import { formatMessage, stringsForLocale } from "./locales/index.js";
15
+ import { selectVisibleRows } from "./visibleRows.js";
16
+ /**
17
+ * Platform Prism quick-files micro-UI (component id "quick-files"): the
18
+ * Dossier Quick File Insert side panel — an axiom component, sibling of the
19
+ * editor viewport (NOT a sub-component of it).
20
+ *
21
+ * Renders the per-prototype panel of the authoritative v9 HTML prototype: the
22
+ * QUICK FILE INSERT title header (title, subtitle and trailing meta are
23
+ * component configuration keys — Prism has no composed title node), the
24
+ * bordered search box, the FILES ARE THE SHORTCUT / RECENT-COMMON FILES
25
+ * section labels, file rows (world view / dossier doc / board / folder icons
26
+ * with semantic kind tokens, name + mono meta line, + insert action) and the
27
+ * DROP-IN FILE MODEL info card. Rows are indexed through the IFileEntry list
28
+ * query.
29
+ *
30
+ * D6 REFERENCE CASE — the panel NEVER references any receiving component. On
31
+ * insert (+) or drag-start of a file row it publishes ONLY a bounded drag /
32
+ * insert state {entryId, kind, name, mime, snapshotRef, sourcePanel} on the
33
+ * "quick-files.drag-state" Prism channel; receivers interpret it themselves
34
+ * (world view → geovision embed restoring an IGeoView snapshot; evidence pack
35
+ * → evidence table; dossier → paragraph with inline link; unknown → generic
36
+ * inline file link, per D10). ESC and drag-end clear the state. No audit
37
+ * events: file browsing/insertion is routine, not audit-worthy.
38
+ *
39
+ * No palette is hardcoded: every color resolves to semantic theme tokens
40
+ * (ok / accent / warn / signal / card / card-dark / border / line / muted /
41
+ * text …) supplied by the host's MantineProvider.
42
+ *
43
+ * COMPOSITION ROOT of the focused sub-component files: PanelHeader (title
44
+ * header), SearchBox, SectionLabels, FileList (+ FileRow, icons),
45
+ * DropInModelCard, and the hooks/modules clients.ts (Lattice clients),
46
+ * dragState.ts (bounded drag-state publication), useQuickFilesEntries.ts
47
+ * (list lifecycle) and visibleRows.ts (row visibility/ordering rules).
48
+ */
49
+ export function QuickFiles({ title, subtitle, trailingMeta, variant = "rail", categoryFilters, recencyWindowMs, kindTokens = {}, locale = "en", }) {
50
+ // Every component-fixed UI string comes from the bundled locale JSONs;
51
+ // the title header renders from component configuration keys with locale
52
+ // defaults (composition-authored overrides stay localized by the composer).
53
+ const strings = stringsForLocale(locale);
54
+ const [search, setSearch] = useState("");
55
+ // Setter-only drag-state publication + the ESC cancel listener (D6).
56
+ useQuickFileDragStatePublish();
57
+ const transport = useLatticeTransport();
58
+ const clients = useMemo(() => createQuickFilesClients(transport), [transport]);
59
+ const { entries, status, reload } = useQuickFilesEntries(clients);
60
+ const rows = useMemo(() => (entries === null ? [] : selectVisibleRows(entries, search, categoryFilters, recencyWindowMs)), [entries, search, categoryFilters, recencyWindowMs]);
61
+ const rail = variant === "rail";
62
+ const resolvedTitle = title ?? strings.panelTitle;
63
+ const resolvedSubtitle = subtitle ?? strings.panelSubtitle;
64
+ const resolvedTrailingMeta = trailingMeta ?? formatMessage(strings.trailingMetaCount, { count: rows.length });
65
+ return (_jsxs(Stack, { gap: 8, miw: 0, style: {
66
+ width: rail ? 340 : 300,
67
+ background: CARD_BG,
68
+ borderLeft: `1px solid ${LINE}`,
69
+ borderTopRightRadius: 6,
70
+ borderBottomRightRadius: 6,
71
+ overflow: "hidden",
72
+ }, "data-testid": "quick-files-panel", children: [_jsx(QuickFilesPanelHeader, { rail: rail, title: resolvedTitle, subtitle: resolvedSubtitle, trailingMeta: resolvedTrailingMeta }), _jsxs(Stack, { gap: 12, px: 16, pb: 14, miw: 0, children: [_jsx(QuickFilesSearchBox, { value: search, onChange: setSearch, placeholder: strings.searchPlaceholder, label: strings.searchLabel }), _jsx(QuickFilesSectionLabels, { hint: strings.sectionHint, recent: strings.sectionRecent }), _jsx(QuickFilesFileList, { status: status, entries: entries, rows: rows, strings: strings, kindTokens: kindTokens, onRetry: () => {
73
+ void reload();
74
+ } }), rail && entries !== null && entries.length > 0 ? (_jsx(QuickFilesDropInModelCard, { title: strings.infoCardTitle, body: strings.infoCardBody })) : null] })] }));
75
+ }
@@ -0,0 +1,13 @@
1
+ export interface QuickFilesSearchBoxProps {
2
+ /** Current search text (controlled). */
3
+ readonly value: string;
4
+ /** Reports the raw input value on every keystroke. */
5
+ readonly onChange: (value: string) => void;
6
+ /** Locale-resolved placeholder. */
7
+ readonly placeholder: string;
8
+ /** Locale-resolved accessible label. */
9
+ readonly label: string;
10
+ }
11
+ /** The panel's bordered accent search box on the card-dark surface (v9 ⌕). */
12
+ export declare function QuickFilesSearchBox({ value, onChange, placeholder, label }: QuickFilesSearchBoxProps): import("react").JSX.Element;
13
+ //# sourceMappingURL=SearchBox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchBox.d.ts","sourceRoot":"","sources":["../src/SearchBox.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,wBAAwB;IACvC,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,sDAAsD;IACtD,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,mCAAmC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,wCAAwC;IACxC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,8EAA8E;AAC9E,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,wBAAwB,+BAsCpG"}
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Group, TextInput } from "@mantine/core";
3
+ import { SearchGlyph } from "./icons.js";
4
+ import { ACCENT, INPUT_BG, MONO, MUTED, TEXT } from "./tokens.js";
5
+ /** The panel's bordered accent search box on the card-dark surface (v9 ⌕). */
6
+ export function QuickFilesSearchBox({ value, onChange, placeholder, label }) {
7
+ return (_jsxs(Group, { gap: 10, wrap: "nowrap", align: "center", px: 10, style: {
8
+ height: 40,
9
+ background: INPUT_BG,
10
+ border: `1px solid ${ACCENT}`,
11
+ borderRadius: 5,
12
+ }, "data-testid": "quick-files-search", c: ACCENT, children: [_jsx(SearchGlyph, {}), _jsx(TextInput, { variant: "unstyled", value: value, onChange: (event) => {
13
+ onChange(event.currentTarget.value);
14
+ }, placeholder: placeholder, "aria-label": label, "data-testid": "quick-files-search-input", styles: {
15
+ input: {
16
+ fontFamily: MONO,
17
+ fontSize: 10,
18
+ color: TEXT,
19
+ minHeight: 36,
20
+ "::placeholder": { color: MUTED },
21
+ },
22
+ } })] }));
23
+ }
@@ -0,0 +1,9 @@
1
+ export interface QuickFilesSectionLabelsProps {
2
+ /** Locale-resolved upper section label (FILES ARE THE SHORTCUT). */
3
+ readonly hint: string;
4
+ /** Locale-resolved lower section label (RECENT / COMMON FILES). */
5
+ readonly recent: string;
6
+ }
7
+ /** The panel's two mono section labels (prototype: FILES ARE THE SHORTCUT / RECENT-COMMON). */
8
+ export declare function QuickFilesSectionLabels({ hint, recent }: QuickFilesSectionLabelsProps): import("react").JSX.Element;
9
+ //# sourceMappingURL=SectionLabels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SectionLabels.d.ts","sourceRoot":"","sources":["../src/SectionLabels.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,4BAA4B;IAC3C,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,+FAA+F;AAC/F,wBAAgB,uBAAuB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,4BAA4B,+BAWrF"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Stack, Text } from "@mantine/core";
3
+ import { MONO, MUTED } from "./tokens.js";
4
+ /** The panel's two mono section labels (prototype: FILES ARE THE SHORTCUT / RECENT-COMMON). */
5
+ export function QuickFilesSectionLabels({ hint, recent }) {
6
+ return (_jsxs(Stack, { gap: 5, "data-testid": "quick-files-sections", children: [_jsx(Text, { ff: MONO, fz: 9, fw: 500, style: { color: MUTED, letterSpacing: "0.04em" }, children: hint }), _jsx(Text, { ff: MONO, fz: 9, fw: 500, style: { color: MUTED, letterSpacing: "0.04em" }, children: recent })] }));
7
+ }
@@ -0,0 +1,22 @@
1
+ import type { LatticeTransport } from "@zephytiju/prism-react";
2
+ import type { QuickFileEntryListResult, QuickFileListRequest } from "./types.js";
3
+ /**
4
+ * Lattice clients for the quick-files panel (design record D4).
5
+ *
6
+ * The list query goes through the GENERATED `createFileEntryClient` from
7
+ * @zephytiju/lattice-common-interfaces over the host Lattice transport — no
8
+ * URLs, clients, or credentials in component code. The generated bundle's
9
+ * bounded summary (id/name/kind/sizeBytes) is a structural subset of the
10
+ * panel's row projection; richer hosts return the superset on the same route,
11
+ * which survives the erased generic and is picked up by the widening cast
12
+ * below (bounded fields only — mime, snapshotRef, meta line, pin, recency).
13
+ */
14
+ export interface QuickFilesClients {
15
+ /** `interfaces/IFileEntry/list` — the panel's file index. */
16
+ readonly files: {
17
+ readonly list: (request?: QuickFileListRequest) => Promise<QuickFileEntryListResult>;
18
+ };
19
+ }
20
+ /** Builds the interface clients bound to the host Lattice transport. */
21
+ export declare function createQuickFilesClients(transport: LatticeTransport): QuickFilesClients;
22
+ //# sourceMappingURL=clients.d.ts.map