+ }
+ } else {
+ return setFileList(ev.target.files)}/>
+ }
+}
+
+export default App;
diff --git a/examples/experimental/slpk-in-browser/src/browser-file.ts b/examples/experimental/slpk-in-browser/src/browser-file.ts
new file mode 100644
index 0000000000..0a7cb16b29
--- /dev/null
+++ b/examples/experimental/slpk-in-browser/src/browser-file.ts
@@ -0,0 +1,132 @@
+// loaders.gl
+// SPDX-License-Identifier: MIT
+// Copyright (c) vis.gl contributors
+import {FileProvider} from '@loaders.gl/loader-utils';
+
+/**
+ * Provides file data using node fs library
+ * @deprecated - will be replaced with ReadableFile
+ */
+export class BrowserFile implements FileProvider {
+ /** The File object from which data is provided */
+ private file: File;
+
+ /** Create a new BrowserFile */
+ constructor(file: File) {
+ this.file = file;
+ }
+ /**
+ * returns an ArrayBuffer whose contents are a copy of this file bytes from startOffset, inclusive, up to endOffset, exclusive.
+ * @param start The offset, in byte, from the start of the file where to start reading the data.
+ * @param lenght Length of read data
+ */
+ private async getBytesFromFile(start: number, lenght: number): Promise {
+ let reader = new FileReader();
+ reader.readAsArrayBuffer(this.file.slice(start, start + lenght));
+ return new Promise((res, rej) => {
+ reader.onload = function() {
+ const arrayBuffer = reader.result
+ if (!arrayBuffer || typeof arrayBuffer === 'string') {
+ rej(new Error('something went wrong'));
+ } else {
+ res(arrayBuffer)
+ }
+ }
+ })
+ }
+
+ /**
+ * Truncates the file descriptor.
+ * @param length desired file lenght
+ */
+ async truncate(length: number): Promise {
+ throw new Error("file loaded in browser cannot be changed");
+ }
+
+ /**
+ * Append data to a file.
+ * @param buffer data to append
+ */
+ async append(buffer: Uint8Array): Promise {
+ throw new Error("file loaded in browser cannot be changed");
+ }
+
+ /** Close file */
+ async destroy(): Promise {
+ throw new Error("file loaded in browser cannot be changed");
+ }
+
+ /**
+ * Gets an unsigned 8-bit integer at the specified byte offset from the start of the file.
+ * @param offset The offset, in bytes, from the start of the file where to read the data.
+ */
+ async getUint8(offset: number | bigint): Promise {
+ const arrayBuffer = await this.getBytesFromFile(Number(offset), 1);
+ const val = new Uint8Array(arrayBuffer).at(0);
+ if (val === undefined) {
+ throw new Error('something went wrong');
+ }
+ return val;
+ }
+
+ /**
+ * Gets an unsigned 16-bit integer at the specified byte offset from the start of the file.
+ * @param offset The offset, in bytes, from the start of the file where to read the data.
+ */
+ async getUint16(offset: number | bigint): Promise {
+ const arrayBuffer = await this.getBytesFromFile(Number(offset), 2);
+ const val = new Uint16Array(arrayBuffer).at(0);
+ if (val === undefined) {
+ throw new Error('something went wrong');
+ }
+ return val;
+ }
+
+ /**
+ * Gets an unsigned 32-bit integer at the specified byte offset from the start of the file.
+ * @param offset The offset, in bytes, from the start of the file where to read the data.
+ */
+ async getUint32(offset: number | bigint): Promise {
+ const arrayBuffer = await this.getBytesFromFile(Number(offset), 4);
+ const val = new Uint32Array(arrayBuffer).at(0);
+ if (val === undefined) {
+ throw new Error('something went wrong');
+ }
+ return val;
+ }
+
+ /**
+ * Gets an unsigned 32-bit integer at the specified byte offset from the start of the file.
+ * @param offset The offset, in bytes, from the start of the file where to read the data.
+ */
+ async getBigUint64(offset: number | bigint): Promise {
+ const arrayBuffer = await this.getBytesFromFile(Number(offset), 8);
+ const val = new BigInt64Array(arrayBuffer).at(0);
+ if (val === undefined) {
+ throw new Error('something went wrong');
+ }
+ return val;
+ }
+
+ /**
+ * returns an ArrayBuffer whose contents are a copy of this file bytes from startOffset, inclusive, up to endOffset, exclusive.
+ * @param startOffset The offset, in byte, from the start of the file where to start reading the data.
+ * @param endOffset The offset, in bytes, from the start of the file where to end reading the data.
+ */
+ async slice(startOffset: bigint, endOffset: bigint): Promise {
+ const bigLength = endOffset - startOffset;
+ if (bigLength > Number.MAX_SAFE_INTEGER) {
+ throw new Error('too big slice');
+ }
+ const length = Number(bigLength);
+
+ return await this.getBytesFromFile(Number(startOffset), length);
+ }
+
+ /**
+ * the length (in bytes) of the data.
+ */
+ get length(): bigint {
+ return BigInt(this.file.size);
+ }
+}
diff --git a/examples/experimental/slpk-in-browser/src/index.tsx b/examples/experimental/slpk-in-browser/src/index.tsx
new file mode 100644
index 0000000000..d168d2a340
--- /dev/null
+++ b/examples/experimental/slpk-in-browser/src/index.tsx
@@ -0,0 +1,13 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import App from './App';
+
+const root = ReactDOM.createRoot(
+ document.getElementById('root') as HTMLElement
+);
+root.render(
+
+
+
+);
+
diff --git a/examples/experimental/slpk-in-browser/tsconfig.json b/examples/experimental/slpk-in-browser/tsconfig.json
new file mode 100644
index 0000000000..f00facecf0
--- /dev/null
+++ b/examples/experimental/slpk-in-browser/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "target": "es2020",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "checkJs": false,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noFallthroughCasesInSwitch": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx"
+ },
+ "include": [
+ "src"
+ ]
+}