react-file-preview-engine 0.1.4 → 0.1.6

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 (3) hide show
  1. package/README.md +72 -19
  2. package/dist/index.js +1 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -184,7 +184,7 @@ This means you can **override** built-in renderers by providing a custom rendere
184
184
 
185
185
  #### Markdown Renderer Example
186
186
 
187
- This example adds support for markdown files. By default, it renders markdown as html, but allows switching to raw text using `additionalContext`.
187
+ This example adds support for markdown files.
188
188
 
189
189
  ```tsx
190
190
  import React, { useEffect, useState } from "react";
@@ -195,12 +195,12 @@ import rehypeRaw from "rehype-raw";
195
195
  import { useRemark } from "react-remarkify";
196
196
  import rehypeSanitize from "rehype-sanitize";
197
197
 
198
- const markdownRenderer: Renderer<{ renderAsHtml?: boolean }> = {
198
+ const markdownRenderer: Renderer = {
199
199
  name: "markdown",
200
200
  canRender({ mimeType }) {
201
201
  return mimeType === "text/markdown";
202
202
  },
203
- Component({ src, onLoad, onError, renderAsHtml = true }) {
203
+ Component({ src, onLoad, onError }) {
204
204
  const [markdown, setMarkdown] = useState("");
205
205
 
206
206
  useEffect(() => {
@@ -224,7 +224,7 @@ const markdownRenderer: Renderer<{ renderAsHtml?: boolean }> = {
224
224
  remarkToRehypeOptions: { allowDangerousHtml: true },
225
225
  });
226
226
 
227
- return renderAsHtml ? <div>{reactContent}</div> : <pre>{markdown}</pre>;
227
+ return <div>{reactContent}</div>;
228
228
  },
229
229
  };
230
230
 
@@ -235,9 +235,62 @@ export default function App() {
235
235
 
236
236
  #### Passing Additional Context
237
237
 
238
+ You can extend renderers with custom configuration using `additionalContext`. This example enhances the markdown renderer to toggle between HTML and raw text rendering.
239
+
240
+ > **Important:** `additionalContext` must remain stable across renders. Use `useMemo` for dynamic values or define it outside your component for static values.
241
+
238
242
  ```tsx
243
+ import React, { useEffect, useMemo, useState } from "react";
244
+ import FilePreviewer from "react-file-preview-engine";
245
+ import type { Renderer } from "react-file-preview-engine/types";
246
+ import remarkGfm from "remark-gfm";
247
+ import rehypeRaw from "rehype-raw";
248
+ import { useRemark } from "react-remarkify";
249
+ import rehypeSanitize from "rehype-sanitize";
250
+
251
+ const markdownRenderer: Renderer<{ renderAsHtml?: boolean }> = {
252
+ name: "markdown",
253
+ canRender({ mimeType }) {
254
+ return mimeType === "text/markdown";
255
+ },
256
+ Component({ src, onLoad, onError, renderAsHtml = true }) {
257
+ const [markdown, setMarkdown] = useState("");
258
+
259
+ useEffect(() => {
260
+ const controller = new AbortController();
261
+
262
+ fetch(src, { signal: controller.signal })
263
+ .then((res) => res.text())
264
+ .then((text) => {
265
+ setMarkdown(text);
266
+ onLoad();
267
+ })
268
+ .catch(onError);
269
+
270
+ return () => controller.abort();
271
+ }, [src]);
272
+
273
+ const reactContent = useRemark({
274
+ markdown,
275
+ remarkPlugins: [remarkGfm],
276
+ rehypePlugins: [rehypeRaw, rehypeSanitize],
277
+ remarkToRehypeOptions: { allowDangerousHtml: true },
278
+ });
279
+
280
+ return renderAsHtml ? <div>{reactContent}</div> : <pre>{markdown}</pre>;
281
+ },
282
+ };
283
+
239
284
  export default function App() {
240
- return <FilePreviewer src="/README.md" fileName="README.md" customRenderers={[markdownRenderer]} additionalContext={{ renderAsHtml: false }} />;
285
+ const [renderAsHtml, setRenderAsHtml] = useState(true);
286
+ const additionalContext = useMemo(() => ({ renderAsHtml }), [renderAsHtml]); // Keep stable across renders
287
+
288
+ return (
289
+ <>
290
+ <button onClick={() => setRenderAsHtml(!renderAsHtml)}>Toggle {renderAsHtml ? "Raw" : "HTML"}</button>
291
+ <FilePreviewer src="/README.md" fileName="README.md" customRenderers={[markdownRenderer]} additionalContext={additionalContext} />
292
+ </>
293
+ );
241
294
  }
242
295
  ```
243
296
 
@@ -251,20 +304,20 @@ You can explore the actual renderer definitions in the [`defaultRenderers` const
251
304
 
252
305
  ### FilePreviewer Props
253
306
 
254
- | Prop | Type | Required | Default | Description |
255
- | ------------------- | ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
256
- | `src` | [`FileSource`](#filesource) | Yes | – | Source URL of the file to preview |
257
- | `mimeType` | `string` | No | inferred | MIME type of the file |
258
- | `fileName` | `string` | No | - | Used for MIME inference and accessibility |
259
- | `autoPlay` | `boolean` | No | `false` | Auto play audio and video |
260
- | `loader` | `ReactNode` | No | [`<Loader />`](https://github.com/SahilAggarwal2004/react-file-preview-engine/blob/main/src/components.tsx) | Shown while the file is loading |
261
- | `customRenderers` | [`Renderer[]`](#renderer) | No | - | Additional or overriding renderers |
262
- | `additionalContext` | `object` | No | - | Extra data passed to renderers, including errorRenderer |
263
- | `errorRenderer` | [`Renderer`](#renderer) | No | [`fallbackRenderer`](https://github.com/SahilAggarwal2004/react-file-preview-engine/blob/main/src/lib/rendererRegistry.tsx) | Renderer used on error |
264
- | `containerProps` | [`DivProps`](#divprops) | No | - | Props applied to preview container |
265
- | `iconProps` | [`DivProps`](#divprops) | No | - | Props applied to fallback icon |
266
- | `onLoad` | [`Eventhandler`](#eventhandler) | No | – | Called when preview is ready |
267
- | `onError` | [`Eventhandler`](#eventhandler) | No | – | Called when preview fails |
307
+ | Prop | Type | Required | Default | Description |
308
+ | ------------------- | ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
309
+ | `src` | [`FileSource`](#filesource) | Yes | – | Source URL of the file to preview |
310
+ | `mimeType` | `string` | No | inferred | MIME type of the file |
311
+ | `fileName` | `string` | No | - | Used for MIME inference and accessibility |
312
+ | `autoPlay` | `boolean` | No | `false` | Auto play audio and video |
313
+ | `loader` | `ReactNode` | No | [`<Loader />`](https://github.com/SahilAggarwal2004/react-file-preview-engine/blob/main/src/components.tsx) | Shown while the file is loading |
314
+ | `customRenderers` | [`Renderer[]`](#renderer) | No | - | Additional or overriding renderers |
315
+ | `additionalContext` | `object` | No | - | Extra data passed to the renderers. Must remain stable across renders |
316
+ | `errorRenderer` | [`Renderer`](#renderer) | No | [`fallbackRenderer`](https://github.com/SahilAggarwal2004/react-file-preview-engine/blob/main/src/lib/rendererRegistry.tsx) | Renderer used on error |
317
+ | `containerProps` | [`DivProps`](#divprops) | No | - | Props applied to preview container |
318
+ | `iconProps` | [`DivProps`](#divprops) | No | - | Props applied to fallback icon |
319
+ | `onLoad` | [`Eventhandler`](#eventhandler) | No | – | Called when preview is ready |
320
+ | `onError` | [`Eventhandler`](#eventhandler) | No | – | Called when preview fails |
268
321
 
269
322
  ## Types
270
323
 
package/dist/index.js CHANGED
@@ -191,7 +191,7 @@ function injectStyle(css) {
191
191
  style.appendChild(document.createTextNode(css));
192
192
  }
193
193
  }
194
- injectStyle("@layer rfpe {\n :where(.rfpe-container) {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n max-width: 100lvw;\n max-width: 100vw;\n }\n :where(.rfpe-icon) {\n width: 50px;\n aspect-ratio: 1;\n }\n}\n.rfpe-audio {\n width: 100%;\n}\n.rfpe-iframe {\n background-color: white;\n}\n.rfpe-iframe,\n.rfpe-image,\n.rfpe-video {\n width: 100%;\n height: 100%;\n}\n.rfpe-image,\n.rfpe-video {\n object-fit: contain;\n}\n.rfpe-text {\n width: 100%;\n height: 100%;\n overflow: auto;\n white-space: pre-wrap;\n}\n.rfpe-loader {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n}\n.rfpe-loader-spinner {\n box-sizing: border-box;\n width: 22px;\n aspect-ratio: 1;\n border-radius: 50%;\n border: 2px solid transparent;\n border-top-color: black;\n border-bottom-color: black;\n animation: rfpe-spin-fast 0.6s ease infinite;\n}\n.rfpe-loader-text {\n font-size: 0.875rem;\n}\n@keyframes rfpe-spin-fast {\n to {\n transform: rotate(360deg);\n }\n}\n");
194
+ injectStyle("@layer rfpe {\n :where(.rfpe-container) {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100%;\n max-width: 100lvw;\n max-width: 100vw;\n }\n :where(.rfpe-icon) {\n width: 50px;\n }\n}\n.rfpe-audio {\n width: 100%;\n}\n.rfpe-iframe {\n background-color: white;\n}\n.rfpe-iframe,\n.rfpe-image,\n.rfpe-video {\n width: 100%;\n height: 100%;\n}\n.rfpe-image,\n.rfpe-video {\n object-fit: contain;\n}\n.rfpe-text {\n width: 100%;\n height: 100%;\n overflow: auto;\n white-space: pre-wrap;\n}\n.rfpe-loader {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n}\n.rfpe-loader-spinner {\n box-sizing: border-box;\n width: 22px;\n aspect-ratio: 1;\n border-radius: 50%;\n border: 2px solid transparent;\n border-top-color: black;\n border-bottom-color: black;\n animation: rfpe-spin-fast 0.6s ease infinite;\n}\n.rfpe-loader-text {\n font-size: 0.875rem;\n}\n@keyframes rfpe-spin-fast {\n to {\n transform: rotate(360deg);\n }\n}\n");
195
195
 
196
196
  // src/index.tsx
197
197
  var { additionalContext: defaultContext, customRenderers: defaultRenderers2, props: defaultProps } = defaults;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-file-preview-engine",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "A renderer-driven React file preview engine with extensible architecture for images, video, audio, pdf, html, and custom formats.",
5
5
  "license": "MIT",
6
6
  "author": "Sahil Aggarwal <aggarwalsahil2004@gmail.com>",