@particle-academy/fancy-code 0.5.1 → 0.6.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.
- package/README.md +28 -1
- package/dist/index.cjs +115 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +103 -3
- package/dist/index.d.ts +103 -3
- package/dist/index.js +114 -2
- package/dist/index.js.map +1 -1
- package/docs/FileViewer.md +78 -0
- package/package.json +3 -3
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# FileViewer
|
|
2
|
+
|
|
3
|
+
A unified file viewer. Detects whether a file is **text** or **media** and
|
|
4
|
+
renders the right surface:
|
|
5
|
+
|
|
6
|
+
- **text** → a read-only `CodeEditor` with syntax highlighting picked from the
|
|
7
|
+
filename.
|
|
8
|
+
- **media** (image / video / audio / PDF) → react-fancy's [`<MediaViewer>`](https://github.com/Particle-Academy/react-fancy/blob/main/docs/MediaViewer.md),
|
|
9
|
+
always read-only.
|
|
10
|
+
|
|
11
|
+
This solves the "open an image in a code editor and get binary rendered as
|
|
12
|
+
text" problem for apps that show arbitrary files from a tree (e.g. an IDE
|
|
13
|
+
editor panel built on `CodeEditor` + `TreeNav`).
|
|
14
|
+
|
|
15
|
+
## Import
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { FileViewer } from "@particle-academy/fancy-code";
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
> **Peer requirement:** the media path uses `<MediaViewer>` from
|
|
22
|
+
> `@particle-academy/react-fancy` **>= 4.9**.
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
// text → CodeEditor (read-only, language from the filename)
|
|
28
|
+
<FileViewer filename="app.tsx" value={source} />
|
|
29
|
+
|
|
30
|
+
// media → <MediaViewer> (give it the file URL via `src`, and a height)
|
|
31
|
+
<FileViewer filename="diagram.png" src={url} style={{ height: 360 }} />
|
|
32
|
+
|
|
33
|
+
// editable text
|
|
34
|
+
<FileViewer filename="notes.md" value={md} onChange={setMd} readOnly={false} />
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Props
|
|
38
|
+
|
|
39
|
+
| Prop | Type | Default | Description |
|
|
40
|
+
|------|------|---------|-------------|
|
|
41
|
+
| filename | `string` | — | File name / path — drives detection + language, used as label/alt |
|
|
42
|
+
| mime | `string` | — | MIME type — preferred over `filename` for detection |
|
|
43
|
+
| src | `string` | — | Source URL for **media** files (`http(s):` / `data:` / `blob:`) |
|
|
44
|
+
| value | `string` | `""` | Text content for **text** files |
|
|
45
|
+
| onChange | `(value: string) => void` | — | Text change handler (ignored when `readOnly`) |
|
|
46
|
+
| readOnly | `boolean` | `true` | Read-only. Media is always read-only |
|
|
47
|
+
| theme | `string` | `"auto"` | Editor theme for text (`light` / `dark` / `auto` / registered) |
|
|
48
|
+
| fileKind | `FileKind` | — | Force the kind, bypassing detection |
|
|
49
|
+
| lineNumbers | `boolean` | `true` | Line numbers in the text editor |
|
|
50
|
+
| wordWrap | `boolean` | `false` | Wrap long lines in the text editor |
|
|
51
|
+
| minHeight / maxHeight | `number` | — | Editor height bounds (px) |
|
|
52
|
+
| mediaProps | `Partial<MediaViewerProps>` | — | Extra props forwarded to `<MediaViewer>` |
|
|
53
|
+
| className | `string` | — | Classes for the wrapper |
|
|
54
|
+
| style | `CSSProperties` | — | Styles for the wrapper (e.g. a height for media) |
|
|
55
|
+
|
|
56
|
+
The wrapper carries stable handles: `data-fancy-file-viewer`, `data-kind`
|
|
57
|
+
(`"text"` / `"media"`), and `data-media-kind` for media.
|
|
58
|
+
|
|
59
|
+
## `resolveFileKind` / `languageFromFilename`
|
|
60
|
+
|
|
61
|
+
The detection logic is exported so you can branch your own chrome (tabs, save
|
|
62
|
+
buttons, download actions) the same way `FileViewer` does internally.
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { resolveFileKind, languageFromFilename } from "@particle-academy/fancy-code";
|
|
66
|
+
|
|
67
|
+
resolveFileKind({ filename: "logo.png" }); // { kind: "media", mediaKind: "image" }
|
|
68
|
+
resolveFileKind({ filename: "app.tsx" }); // { kind: "text", language: "typescript" }
|
|
69
|
+
resolveFileKind({ mime: "application/pdf" }); // { kind: "media", mediaKind: "pdf" }
|
|
70
|
+
|
|
71
|
+
languageFromFilename("server.go"); // "go"
|
|
72
|
+
languageFromFilename("data.unknown"); // "plaintext"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`FileKind` is `{ kind: "text"; language: string } | { kind: "media"; mediaKind: MediaKind }`.
|
|
76
|
+
MIME wins over the filename when both are given. Text files with no known
|
|
77
|
+
extension resolve to the `"plaintext"` language (no highlighting). SVG resolves
|
|
78
|
+
to a media **image**, not text.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@particle-academy/fancy-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Lightweight embedded code editor with syntax highlighting and extensible language/theme registries",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -39,12 +39,12 @@
|
|
|
39
39
|
"prepublishOnly": "tsup"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@particle-academy/react-fancy": ">=
|
|
42
|
+
"@particle-academy/react-fancy": ">=4.9.0",
|
|
43
43
|
"react": "^18.0.0 || ^19.0.0",
|
|
44
44
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@particle-academy/react-fancy": "^4.
|
|
47
|
+
"@particle-academy/react-fancy": "^4.9.0",
|
|
48
48
|
"@types/react": "^19.0.0",
|
|
49
49
|
"@types/react-dom": "^19.0.0",
|
|
50
50
|
"react": "^19.0.0",
|