@vctrl/hooks 0.0.9-3 → 0.0.9

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 (41) hide show
  1. package/.babelrc +12 -0
  2. package/.eslintrc.json +18 -0
  3. package/LICENSE +0 -0
  4. package/README.md +209 -0
  5. package/package.json +1 -1
  6. package/project.json +16 -0
  7. package/src/use-load-model/event-system.ts +29 -0
  8. package/src/use-load-model/file-type-hooks/use-load-binary.ts +74 -0
  9. package/src/use-load-model/file-type-hooks/use-load-gltf.ts +115 -0
  10. package/src/use-load-model/loaders/create-gltf-loader.ts +20 -0
  11. package/{use-load-model/loaders/create-usdz-loader.d.ts → src/use-load-model/loaders/create-usdz-loader.ts} +7 -1
  12. package/src/use-load-model/model-context.tsx +18 -0
  13. package/src/use-load-model/state.ts +33 -0
  14. package/src/use-load-model/types.ts +53 -0
  15. package/src/use-load-model/use-load-model.ts +111 -0
  16. package/src/use-load-model/utils/array-buffer-to-base64.ts +20 -0
  17. package/src/use-load-model/utils/read-directory.ts +31 -0
  18. package/tsconfig.json +21 -0
  19. package/tsconfig.lib.json +25 -0
  20. package/vite.config.ts +59 -0
  21. package/index.cjs.js +0 -1
  22. package/index.es.js +0 -8
  23. package/model-context-ClI5AGc8.js +0 -19136
  24. package/model-context-mPTTbSMx.cjs +0 -3849
  25. package/use-load-model/event-system.d.ts +0 -7
  26. package/use-load-model/file-type-hooks/use-load-binary.d.ts +0 -11
  27. package/use-load-model/file-type-hooks/use-load-gltf.d.ts +0 -5
  28. package/use-load-model/loaders/create-gltf-loader.d.ts +0 -3
  29. package/use-load-model/model-context.d.ts +0 -20
  30. package/use-load-model/state.d.ts +0 -11
  31. package/use-load-model/types.d.ts +0 -48
  32. package/use-load-model/use-load-model.d.ts +0 -11
  33. package/use-load-model/utils/array-buffer-to-base64.d.ts +0 -2
  34. package/use-load-model/utils/read-directory.d.ts +0 -8
  35. package/use-load-model.cjs.js +0 -1
  36. package/use-load-model.es.js +0 -8
  37. /package/{index.d.ts → src/index.ts} +0 -0
  38. /package/{use-load-model/file-type-hooks/index.d.ts → src/use-load-model/file-type-hooks/index.ts} +0 -0
  39. /package/{use-load-model/index.d.ts → src/use-load-model/index.ts} +0 -0
  40. /package/{use-load-model/loaders/index.d.ts → src/use-load-model/loaders/index.ts} +0 -0
  41. /package/{use-load-model/utils/index.d.ts → src/use-load-model/utils/index.ts} +0 -0
package/.babelrc ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "presets": [
3
+ [
4
+ "@nx/react/babel",
5
+ {
6
+ "runtime": "automatic",
7
+ "useBuiltIns": "usage"
8
+ }
9
+ ]
10
+ ],
11
+ "plugins": []
12
+ }
package/.eslintrc.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "extends": ["plugin:@nx/react", "../../.eslintrc.json"],
3
+ "ignorePatterns": ["!**/*"],
4
+ "overrides": [
5
+ {
6
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
7
+ "rules": {}
8
+ },
9
+ {
10
+ "files": ["*.ts", "*.tsx"],
11
+ "rules": {}
12
+ },
13
+ {
14
+ "files": ["*.js", "*.jsx"],
15
+ "rules": {}
16
+ }
17
+ ]
18
+ }
package/LICENSE ADDED
File without changes
package/README.md ADDED
@@ -0,0 +1,209 @@
1
+ # vctrl/hooks
2
+
3
+ [![Version and release packages to NPM](https://img.shields.io/github/actions/workflow/status/vectreal/vectreal-core/version-release.yaml?logo=github&logoColor=%23fc6c18&label=Version%20and%20release%20packages%20to%20NPM&color=%23fc6c18)
4
+ ](https://github.com/Vectreal/vectreal-core/actions/workflows/version-release.yaml)
5
+ [![@vctrl/hooks | NPM Downloads](https://img.shields.io/npm/dm/%40vctrl%2Fhooks?logo=npm&logoColor=%23fc6c18&label=%40vctrl%2Fhooks%20%7C%20NPM%20Downloads&color=%23fc6c18)](https://www.npmjs.com/package/@vctrl/hooks)
6
+
7
+ ## Overview
8
+
9
+ vctrl/hooks is a React hooks package designed to simplify 3D model loading and management within React applications. It's part of the vectreal-core ecosystem and is primarily used in the vctrl/viewer React component and the official website application.
10
+
11
+ The package provides a powerful hook for loading various 3D model file formats, along with a React context for easy state management and an event system for handling different stages of the model loading process.
12
+
13
+ ## Table of contents
14
+
15
+ - [vctrl/hooks](#vctrlhooks)
16
+ - [Overview](#overview)
17
+ - [Table of contents](#table-of-contents)
18
+ - [Features](#features)
19
+ - [Installation](#installation)
20
+ - [Usage](#usage)
21
+ - [API Reference](#api-reference)
22
+ - [useLoadModel](#useloadmodel)
23
+ - [Returns](#returns)
24
+ - [ModelContext](#modelcontext)
25
+ - [Event System](#event-system)
26
+ - [Events](#events)
27
+ - [Supported File Types](#supported-file-types)
28
+ - [File Loading Process](#file-loading-process)
29
+ - [State Management](#state-management)
30
+ - [Integration with Three.js](#integration-with-threejs)
31
+ - [Development](#development)
32
+ - [License](#license)
33
+ - [Contributing](#contributing)
34
+ - [Support](#support)
35
+
36
+ ## Features
37
+
38
+ - Direct 3D model file loading (supports GLTF, GLB, and USDZ formats)
39
+ - React context for state management (ModelContext)
40
+ - Event system for handling loading progress and completion
41
+ - Three.js integration
42
+ - TypeScript support
43
+
44
+ ## Installation
45
+
46
+ To install the package, use npm or yarn:
47
+
48
+ ```bash
49
+ npm install @vctrl/hooks
50
+ # or
51
+ yarn add @vctrl/hooks
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ The main hook exported by this package is `useLoadModel`. Here's a basic example of how to use it:
57
+
58
+ ```jsx
59
+ import React from 'react';
60
+ import { useLoadModel } from '@vctrl/hooks/use-load-model';
61
+
62
+ function ModelLoader() {
63
+ const { handleFileUpload, file, progress, isLoading } = useLoadModel();
64
+
65
+ const onFileChange = (event) => {
66
+ const files = Array.from(event.target.files);
67
+ handleFileUpload(files);
68
+ };
69
+
70
+ return (
71
+ <div>
72
+ <input type="file" onChange={onFileChange} />
73
+ {isLoading && <p>Loading: {progress}%</p>}
74
+ {file && <p>Model loaded: {file.name}</p>}
75
+ </div>
76
+ );
77
+ }
78
+ ```
79
+
80
+ > Multiple files can be handled, e.g. when uploading a `.gltf` model, its `.bin` file and the relavant image texture files as `.jpeg`/`.png` (Other texture file formats have not been tested).
81
+
82
+ ## API Reference
83
+
84
+ ### useLoadModel
85
+
86
+ The main hook for loading and managing 3D model files.
87
+
88
+ #### Returns
89
+
90
+ - `file`: The loaded file object of type `ModelFile | null`.
91
+ - `isLoading`: A boolean indicating whether a file is currently being loaded.
92
+ - `progress`: A number between 0 and 100 representing the loading progress.
93
+ - `handleFileUpload`: A function to handle file upload. It accepts an array of `File` objects or a mixed array of `File` objects and directory entries.
94
+ - `on`: A function to subscribe to events.
95
+ - `off`: A function to unsubscribe from events.
96
+
97
+ ### ModelContext
98
+
99
+ A React context that provides the state and functions from `useLoadModel` to child components. It's implemented in `model-context.tsx`.
100
+
101
+ ```jsx
102
+ import { ModelProvider, useModelContext } from '@vctrl/hooks/use-load-model';
103
+
104
+ function App() {
105
+ return (
106
+ <ModelProvider>
107
+ <ModelConsumer />
108
+ </ModelProvider>
109
+ );
110
+ }
111
+
112
+ function ModelConsumer() {
113
+ const { file, isLoading, progress, handleFileUpload } = useModelContext();
114
+ // Use the context values
115
+ }
116
+ ```
117
+
118
+ > When using the React Context, only load models with the `useModelContext` hook.
119
+
120
+ ### Event System
121
+
122
+ The package includes a custom event system for handling various stages of the model loading process. The event system is implemented in `event-system.ts` and provides three main methods:
123
+
124
+ - `emit<T extends EventTypes>(event: T, data: EventData[T]): void`
125
+ - `on<T extends EventTypes>(event: T, handler: EventHandler<T>): void`
126
+ - `off<T extends EventTypes>(event: T, handler: EventHandler<T>): void`
127
+
128
+ #### Events
129
+
130
+ You can subscribe to these events using the `on` method:
131
+
132
+ - `'UPLOAD_PROGRESS'`: Emitted with the current progress (0-100) during file upload.
133
+ - `'UPLOAD_COMPLETE'`: Emitted with the loaded file object when the upload is complete.
134
+ - `'MULTIPLE_3D_MODELS'`: Emitted if multiple supported 3D model files are detected in the upload.
135
+ - `'UNSUPPORTED_FILE_TYPE'`: Emitted if an unsupported file type is uploaded.
136
+
137
+ Example usage:
138
+
139
+ ```javascript
140
+ const { on, off } = useLoadModel();
141
+
142
+ useEffect(() => {
143
+ const handleProgress = (progress) => {
144
+ console.log(`Upload progress: ${progress}%`);
145
+ };
146
+
147
+ on('UPLOAD_PROGRESS', handleProgress);
148
+
149
+ return () => off('UPLOAD_PROGRESS', handleProgress);
150
+ }, [on, off]);
151
+ ```
152
+
153
+ ## Supported File Types
154
+
155
+ The package currently supports the following 3D model file formats:
156
+
157
+ - GLTF (.gltf)
158
+ - GLB (.glb)
159
+ - USDZ (.usdz)
160
+
161
+ These are defined in the `ModelFileTypes` enum in `types.ts`.
162
+
163
+ ## File Loading Process
164
+
165
+ The file loading process, particularly for GLTF files, is handled by the `useLoadGltf` hook in `use-load-gltf.ts`. This hook performs the following steps:
166
+
167
+ 1. Parses the GLTF file content.
168
+ 2. Embeds external resources (buffers and images) into the GLTF content.
169
+ 3. Uses Three.js GLTFLoader to parse the modified GLTF content.
170
+ 4. Dispatches actions to update the state with the loaded model.
171
+
172
+ The loading process includes progress updates, which are communicated through the event system.
173
+
174
+ ## State Management
175
+
176
+ The package uses a reducer pattern for state management, implemented in `state.ts`. The state includes:
177
+
178
+ - `file`: The currently loaded model file.
179
+ - `isFileLoading`: A boolean indicating if a file is being loaded.
180
+ - `progress`: The current loading progress.
181
+ - `supportedFileTypes`: An array of supported file types.
182
+
183
+ Actions for updating the state are defined in the `Action` type in `types.ts`.
184
+
185
+ ## Integration with Three.js
186
+
187
+ The package integrates with Three.js for handling 3D model rendering. The loaded models are compatible with Three.js scene rendering, with the model stored as a Three.js `Object3D` in the `ModelFile` interface.
188
+
189
+ ## Development
190
+
191
+ This package is part of a monorepo workspace managed with Nx. To contribute or modify the package:
192
+
193
+ 1. Clone the monorepo
194
+ 2. Install dependencies: `npm install` or `yarn install`
195
+ 3. Make your changes
196
+ 4. Build the package: `nx build vctrl/hooks`
197
+ 5. Test your changes: `nx test vctrl/hooks`
198
+
199
+ ## License
200
+
201
+ Please refer to the LICENSE file in the package root for licensing information.
202
+
203
+ ## Contributing
204
+
205
+ Contributions are welcome! Please read the contributing guidelines in the [vectreal-core](https://github.com/vectreal/vectreal-core) monorepo before submitting pull requests.
206
+
207
+ ## Support
208
+
209
+ For issues, feature requests, or questions, please file an issue in the GitHub repository.
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.9-3",
2
+ "version": "0.0.9",
3
3
  "name": "@vctrl/hooks",
4
4
  "description": "vctrl/hooks is a React hooks package designed to simplify 3D model loading and management within React applications. It's part of the vectreal-core ecosystem and is primarily used in the vctrl/viewer React component and the official website application.",
5
5
  "bugs": {
package/project.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "vctrl/hooks",
3
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
4
+ "sourceRoot": "packages/hooks/src",
5
+ "projectType": "library",
6
+ "tags": [],
7
+ "targets": {
8
+ "build": {
9
+ "executor": "@nx/vite:build",
10
+ "options": {
11
+ "outputPath": "dist/packages/vctrl/hooks",
12
+ "configFile": "packages/hooks/vite.config.ts"
13
+ }
14
+ }
15
+ }
16
+ }
@@ -0,0 +1,29 @@
1
+ import { EventData, EventHandler, EventTypes } from './types';
2
+
3
+ const listeners = {} as Record<EventTypes, EventHandler<EventTypes>[]>;
4
+ const eventSystem = {
5
+ emit<T extends EventTypes>(event: T, data: EventData[T]): void {
6
+ const handlers = listeners[event];
7
+ if (handlers) {
8
+ handlers.forEach((handler) => handler(data));
9
+ }
10
+ },
11
+
12
+ on<T extends EventTypes>(event: T, handler: EventHandler<T>): void {
13
+ if (!listeners[event]) {
14
+ listeners[event] = [];
15
+ }
16
+ listeners[event].push(handler as EventHandler<EventTypes>);
17
+ },
18
+
19
+ off<T extends EventTypes>(event: T, handler: EventHandler<T>): void {
20
+ const handlers = listeners[event];
21
+ if (handlers) {
22
+ listeners[event] = handlers.filter(
23
+ (h) => h !== handler,
24
+ ) as EventHandler<EventTypes>[];
25
+ }
26
+ },
27
+ };
28
+
29
+ export default eventSystem;
@@ -0,0 +1,74 @@
1
+ import { useCallback } from 'react';
2
+
3
+ import { Action, ModelFileTypes } from '../types';
4
+ import { createGltfLoader, createUsdzLoader } from '../loaders';
5
+
6
+ /**
7
+ * Hook to load binary files
8
+ *
9
+ * @param dispatch - The dispatch function from the useReducer hook
10
+ * @returns An object containing the loadBinary function
11
+ */
12
+ function useLoadBinary(dispatch: React.Dispatch<Action>) {
13
+ /**
14
+ * Function to read binary files
15
+ *
16
+ * @param file - The binary file to read
17
+ * @param fileType - The type of file to read
18
+ * @param onProgress - The function to call when progress is made
19
+ * @returns {void}
20
+ */
21
+ const loadBinary = useCallback(
22
+ (file: File, fileType: ModelFileTypes, onProgress: () => void) => {
23
+ const reader = new FileReader();
24
+
25
+ reader.onload = async (event: ProgressEvent<FileReader>) => {
26
+ if (event.target?.result) {
27
+ const arrayBuffer = event.target.result as ArrayBuffer;
28
+
29
+ if (fileType === ModelFileTypes.glb) {
30
+ const gltfLoader = createGltfLoader();
31
+
32
+ gltfLoader.parse(arrayBuffer, '', (gltf) => {
33
+ dispatch({
34
+ type: 'SET_FILE',
35
+ payload: {
36
+ model: gltf.scene,
37
+ type: ModelFileTypes.glb,
38
+ name: file.name,
39
+ },
40
+ });
41
+ });
42
+ } else if (fileType === ModelFileTypes.usdz) {
43
+ const usdzLoader = createUsdzLoader();
44
+ const model = usdzLoader.parse(arrayBuffer);
45
+
46
+ dispatch({
47
+ type: 'SET_FILE',
48
+ payload: {
49
+ model: model,
50
+ type: ModelFileTypes.usdz,
51
+ name: file.name,
52
+ },
53
+ });
54
+ }
55
+
56
+ onProgress(); // Call progress callback when binary file is loaded
57
+ dispatch({ type: 'SET_FILE_LOADING', payload: false });
58
+ }
59
+ };
60
+
61
+ reader.onerror = (error) => {
62
+ console.error('Error reading file:', error);
63
+ dispatch({ type: 'SET_FILE_LOADING', payload: false });
64
+ };
65
+
66
+ reader.readAsArrayBuffer(file);
67
+ },
68
+ [dispatch],
69
+ );
70
+
71
+ return { loadBinary };
72
+ }
73
+
74
+ export default useLoadBinary;
@@ -0,0 +1,115 @@
1
+ import { useCallback } from 'react';
2
+
3
+ import { Action, ModelFileTypes, ReducedGltf } from '../types';
4
+ import { arrayBufferToBase64 } from '../utils';
5
+ import { createGltfLoader } from '../loaders';
6
+
7
+ function useLoadGltf(dispatch: React.Dispatch<Action>) {
8
+ const embedExternalResources = useCallback(
9
+ async (
10
+ gltfContent: ReducedGltf,
11
+ otherFiles: File[],
12
+ onProgress: (progress: number) => void,
13
+ ) => {
14
+ const fileMap = new Map(otherFiles.map((file) => [file.name, file]));
15
+ const totalFiles =
16
+ (gltfContent.buffers?.length || 0) + (gltfContent.images?.length || 0);
17
+ let processedFiles = 0;
18
+
19
+ const updateProgress = () => {
20
+ processedFiles++;
21
+ onProgress((processedFiles / totalFiles) * 100);
22
+ };
23
+
24
+ // Embed buffers
25
+ if (gltfContent.buffers) {
26
+ for (let i = 0; i < gltfContent.buffers.length; i++) {
27
+ const buffer = gltfContent.buffers[i];
28
+ if (!buffer.uri || buffer.uri.startsWith('data:')) {
29
+ updateProgress();
30
+ continue;
31
+ }
32
+
33
+ const fileName = buffer.uri.split('/').pop() || '';
34
+ const file = fileMap.get(fileName);
35
+ if (file) {
36
+ const arrayBuffer = await file.arrayBuffer();
37
+ const base64 = await arrayBufferToBase64(arrayBuffer);
38
+ buffer.uri = `data:application/octet-stream;base64,${base64}`;
39
+ }
40
+ updateProgress();
41
+ }
42
+ }
43
+
44
+ // Embed images
45
+ if (gltfContent.images) {
46
+ for (let i = 0; i < gltfContent.images.length; i++) {
47
+ const image = gltfContent.images[i];
48
+ if (!image.uri || image.uri.startsWith('data:')) {
49
+ updateProgress();
50
+ continue;
51
+ }
52
+
53
+ const fileName = image.uri.split('/').pop() || '';
54
+ const file = fileMap.get(fileName);
55
+ if (file) {
56
+ const arrayBuffer = await file.arrayBuffer();
57
+ const base64 = await arrayBufferToBase64(arrayBuffer);
58
+ const mimeType = file.type || 'image/png';
59
+ image.uri = `data:${mimeType};base64,${base64}`;
60
+ }
61
+ updateProgress();
62
+ }
63
+ }
64
+
65
+ return gltfContent;
66
+ },
67
+ [],
68
+ );
69
+
70
+ const loadGltf = useCallback(
71
+ (
72
+ gltfFile: File,
73
+ otherFiles: File[],
74
+ onProgress: (progress: number) => void,
75
+ ) => {
76
+ const reader = new FileReader();
77
+ reader.onload = async (e) => {
78
+ const gltfContent = JSON.parse(e.target?.result as string);
79
+ onProgress(10); // Initial progress after parsing GLTF
80
+
81
+ const modifiedGLTF = await embedExternalResources(
82
+ gltfContent,
83
+ otherFiles,
84
+ (embeddingProgress) => {
85
+ // Map embedding progress to 10-90% range
86
+ onProgress(10 + embeddingProgress * 0.8);
87
+ },
88
+ );
89
+
90
+ const gltfLoader = createGltfLoader();
91
+
92
+ gltfLoader.parse(JSON.stringify(modifiedGLTF), '', (gltf) => {
93
+ dispatch({
94
+ type: 'SET_FILE',
95
+ payload: {
96
+ model: gltf.scene,
97
+ type: ModelFileTypes.gltf,
98
+ name: gltfFile.name,
99
+ },
100
+ });
101
+ });
102
+
103
+ onProgress(100); // Final progress
104
+ dispatch({ type: 'SET_FILE_LOADING', payload: false });
105
+ };
106
+
107
+ reader.readAsText(gltfFile);
108
+ },
109
+ [dispatch, embedExternalResources],
110
+ );
111
+
112
+ return { loadGltf };
113
+ }
114
+
115
+ export default useLoadGltf;
@@ -0,0 +1,20 @@
1
+ import { WebGLRenderer } from 'three';
2
+ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
3
+ import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
4
+ import { KTX2Loader } from 'three/examples/jsm/loaders/KTX2Loader';
5
+
6
+ function createGltfLoader() {
7
+ const dracoLoader = new DRACOLoader();
8
+ dracoLoader.setDecoderPath('/draco/');
9
+
10
+ const ktxLoader = new KTX2Loader();
11
+ ktxLoader.setTranscoderPath('/draco/');
12
+
13
+ const gltfLoader = new GLTFLoader()
14
+ .setDRACOLoader(dracoLoader)
15
+ .setKTX2Loader(ktxLoader.detectSupport(new WebGLRenderer()));
16
+
17
+ return gltfLoader;
18
+ }
19
+
20
+ export default createGltfLoader;
@@ -1,3 +1,9 @@
1
1
  import { USDZLoader } from 'three/examples/jsm/loaders/USDZLoader';
2
- declare function createUsdzLoader(): USDZLoader;
2
+
3
+ function createUsdzLoader() {
4
+ const usdzLoader = new USDZLoader();
5
+
6
+ return usdzLoader;
7
+ }
8
+
3
9
  export default createUsdzLoader;
@@ -0,0 +1,18 @@
1
+ import { createContext, useContext } from 'react';
2
+ import useLoadModel from './use-load-model';
3
+
4
+ const ModelContext = createContext({} as ReturnType<typeof useLoadModel>);
5
+
6
+ const ModelProvider = ({ children }: React.PropsWithChildren) => {
7
+ const value = useLoadModel();
8
+
9
+ return (
10
+ <ModelContext.Provider value={value}>{children}</ModelContext.Provider>
11
+ );
12
+ };
13
+
14
+ const useModelContext = () => {
15
+ return useContext(ModelContext);
16
+ };
17
+
18
+ export { ModelContext, ModelProvider, useModelContext };
@@ -0,0 +1,33 @@
1
+ import { Action, ModelFileTypes, State } from './types';
2
+
3
+ // Initial state
4
+ export const initialState: State = {
5
+ file: null,
6
+ isFileLoading: false,
7
+ progress: 0,
8
+ supportedFileTypes: Object.values(ModelFileTypes),
9
+ };
10
+
11
+ /**
12
+ * Reducer function for the useReadModelFiles hook
13
+ *
14
+ * @param state - The current state of the reducer
15
+ * @param action - The action to be performed
16
+ * @returns The updated state
17
+ */
18
+ function reducer(state: State, action: Action): State {
19
+ switch (action.type) {
20
+ case 'SET_FILE':
21
+ return { ...state, file: action.payload };
22
+ case 'SET_FILE_LOADING':
23
+ return { ...state, isFileLoading: action.payload };
24
+ case 'SET_PROGRESS':
25
+ return { ...state, progress: action.payload };
26
+ case 'RESET_STATE':
27
+ return { ...initialState };
28
+ default:
29
+ return state;
30
+ }
31
+ }
32
+
33
+ export default reducer;
@@ -0,0 +1,53 @@
1
+ import { Object3D } from 'three';
2
+
3
+ export enum ModelFileTypes {
4
+ gltf = 'gltf',
5
+ glb = 'glb',
6
+ usdz = 'usdz',
7
+ }
8
+
9
+ export type InputFileOrDirectory = (File | FileSystemDirectoryHandle)[];
10
+
11
+ export interface ReducedGltf {
12
+ images: { name: string; uri: string }[];
13
+ buffers: { bytelength: string; uri: string }[];
14
+ }
15
+
16
+ export interface ModelFile {
17
+ model: Object3D;
18
+ type: ModelFileTypes;
19
+ name: string;
20
+ }
21
+
22
+ // Updated State interface
23
+ export interface State {
24
+ file: ModelFile | null;
25
+ isFileLoading: boolean;
26
+ progress: number;
27
+ supportedFileTypes: ModelFileTypes[];
28
+ }
29
+
30
+ // Updated Action types
31
+ export type Action =
32
+ | { type: 'SET_FILE'; payload: ModelFile }
33
+ | { type: 'SET_FILE_LOADING'; payload: boolean }
34
+ | { type: 'SET_PROGRESS'; payload: number }
35
+ | { type: 'RESET_STATE' };
36
+
37
+ // Updated Event types
38
+ export type EventTypes =
39
+ | 'MULTIPLE_3D_MODELS'
40
+ | 'UNSUPPORTED_FILE_TYPE'
41
+ | 'UPLOAD_PROGRESS'
42
+ | 'UPLOAD_COMPLETE';
43
+
44
+ // Updated event data types
45
+ export type EventData = {
46
+ MULTIPLE_3D_MODELS: File[];
47
+ UNSUPPORTED_FILE_TYPE: File[];
48
+ UPLOAD_PROGRESS: number;
49
+ UPLOAD_COMPLETE: State['file'];
50
+ };
51
+
52
+ // Updated EventHandler type
53
+ export type EventHandler<T extends EventTypes> = (data: EventData[T]) => void;