@vctrl/hooks 0.0.9 → 0.1.1

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/LICENSE.md +650 -0
  2. package/index.cjs.js +1 -0
  3. package/index.es.js +8 -0
  4. package/model-context-ClI5AGc8.js +19136 -0
  5. package/model-context-mPTTbSMx.cjs +3849 -0
  6. package/package.json +1 -1
  7. package/use-load-model/event-system.d.ts +7 -0
  8. package/use-load-model/file-type-hooks/use-load-binary.d.ts +11 -0
  9. package/use-load-model/file-type-hooks/use-load-gltf.d.ts +5 -0
  10. package/use-load-model/loaders/create-gltf-loader.d.ts +3 -0
  11. package/{src/use-load-model/loaders/create-usdz-loader.ts → use-load-model/loaders/create-usdz-loader.d.ts} +1 -7
  12. package/use-load-model/model-context.d.ts +20 -0
  13. package/use-load-model/state.d.ts +11 -0
  14. package/use-load-model/types.d.ts +48 -0
  15. package/use-load-model/use-load-model.d.ts +11 -0
  16. package/use-load-model/utils/array-buffer-to-base64.d.ts +2 -0
  17. package/use-load-model/utils/read-directory.d.ts +8 -0
  18. package/use-load-model.cjs.js +1 -0
  19. package/use-load-model.es.js +8 -0
  20. package/.babelrc +0 -12
  21. package/.eslintrc.json +0 -18
  22. package/LICENSE +0 -0
  23. package/project.json +0 -16
  24. package/src/use-load-model/event-system.ts +0 -29
  25. package/src/use-load-model/file-type-hooks/use-load-binary.ts +0 -74
  26. package/src/use-load-model/file-type-hooks/use-load-gltf.ts +0 -115
  27. package/src/use-load-model/loaders/create-gltf-loader.ts +0 -20
  28. package/src/use-load-model/model-context.tsx +0 -18
  29. package/src/use-load-model/state.ts +0 -33
  30. package/src/use-load-model/types.ts +0 -53
  31. package/src/use-load-model/use-load-model.ts +0 -111
  32. package/src/use-load-model/utils/array-buffer-to-base64.ts +0 -20
  33. package/src/use-load-model/utils/read-directory.ts +0 -31
  34. package/tsconfig.json +0 -21
  35. package/tsconfig.lib.json +0 -25
  36. package/vite.config.ts +0 -59
  37. /package/{src/index.ts → index.d.ts} +0 -0
  38. /package/{src/use-load-model/file-type-hooks/index.ts → use-load-model/file-type-hooks/index.d.ts} +0 -0
  39. /package/{src/use-load-model/index.ts → use-load-model/index.d.ts} +0 -0
  40. /package/{src/use-load-model/loaders/index.ts → use-load-model/loaders/index.d.ts} +0 -0
  41. /package/{src/use-load-model/utils/index.ts → use-load-model/utils/index.d.ts} +0 -0
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.0.9",
2
+ "version": "0.1.1",
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": {
@@ -0,0 +1,7 @@
1
+ import { EventData, EventHandler, EventTypes } from './types';
2
+ declare const eventSystem: {
3
+ emit<T extends EventTypes>(event: T, data: EventData[T]): void;
4
+ on<T extends EventTypes>(event: T, handler: EventHandler<T>): void;
5
+ off<T extends EventTypes>(event: T, handler: EventHandler<T>): void;
6
+ };
7
+ export default eventSystem;
@@ -0,0 +1,11 @@
1
+ import { Action, ModelFileTypes } from '../types';
2
+ /**
3
+ * Hook to load binary files
4
+ *
5
+ * @param dispatch - The dispatch function from the useReducer hook
6
+ * @returns An object containing the loadBinary function
7
+ */
8
+ declare function useLoadBinary(dispatch: React.Dispatch<Action>): {
9
+ loadBinary: (file: File, fileType: ModelFileTypes, onProgress: () => void) => void;
10
+ };
11
+ export default useLoadBinary;
@@ -0,0 +1,5 @@
1
+ import { Action } from '../types';
2
+ declare function useLoadGltf(dispatch: React.Dispatch<Action>): {
3
+ loadGltf: (gltfFile: File, otherFiles: File[], onProgress: (progress: number) => void) => void;
4
+ };
5
+ export default useLoadGltf;
@@ -0,0 +1,3 @@
1
+ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
2
+ declare function createGltfLoader(): GLTFLoader;
3
+ export default createGltfLoader;
@@ -1,9 +1,3 @@
1
1
  import { USDZLoader } from 'three/examples/jsm/loaders/USDZLoader';
2
-
3
- function createUsdzLoader() {
4
- const usdzLoader = new USDZLoader();
5
-
6
- return usdzLoader;
7
- }
8
-
2
+ declare function createUsdzLoader(): USDZLoader;
9
3
  export default createUsdzLoader;
@@ -0,0 +1,20 @@
1
+ declare const ModelContext: import('react').Context<{
2
+ on: <T extends import('./types').EventTypes>(event: T, handler: import('./types').EventHandler<T>) => void;
3
+ off: <T extends import('./types').EventTypes>(event: T, handler: import('./types').EventHandler<T>) => void;
4
+ handleFileUpload: (filesOrDirectories: import('./types').InputFileOrDirectory) => Promise<void>;
5
+ file: import('./types').ModelFile | null;
6
+ isFileLoading: boolean;
7
+ progress: number;
8
+ supportedFileTypes: import('./types').ModelFileTypes[];
9
+ }>;
10
+ declare const ModelProvider: ({ children }: React.PropsWithChildren) => import("react/jsx-runtime").JSX.Element;
11
+ declare const useModelContext: () => {
12
+ on: <T extends import('./types').EventTypes>(event: T, handler: import('./types').EventHandler<T>) => void;
13
+ off: <T extends import('./types').EventTypes>(event: T, handler: import('./types').EventHandler<T>) => void;
14
+ handleFileUpload: (filesOrDirectories: import('./types').InputFileOrDirectory) => Promise<void>;
15
+ file: import('./types').ModelFile | null;
16
+ isFileLoading: boolean;
17
+ progress: number;
18
+ supportedFileTypes: import('./types').ModelFileTypes[];
19
+ };
20
+ export { ModelContext, ModelProvider, useModelContext };
@@ -0,0 +1,11 @@
1
+ import { Action, State } from './types';
2
+ export declare const initialState: State;
3
+ /**
4
+ * Reducer function for the useReadModelFiles hook
5
+ *
6
+ * @param state - The current state of the reducer
7
+ * @param action - The action to be performed
8
+ * @returns The updated state
9
+ */
10
+ declare function reducer(state: State, action: Action): State;
11
+ export default reducer;
@@ -0,0 +1,48 @@
1
+ import { Object3D } from 'three';
2
+ export declare enum ModelFileTypes {
3
+ gltf = "gltf",
4
+ glb = "glb",
5
+ usdz = "usdz"
6
+ }
7
+ export type InputFileOrDirectory = (File | FileSystemDirectoryHandle)[];
8
+ export interface ReducedGltf {
9
+ images: {
10
+ name: string;
11
+ uri: string;
12
+ }[];
13
+ buffers: {
14
+ bytelength: string;
15
+ uri: string;
16
+ }[];
17
+ }
18
+ export interface ModelFile {
19
+ model: Object3D;
20
+ type: ModelFileTypes;
21
+ name: string;
22
+ }
23
+ export interface State {
24
+ file: ModelFile | null;
25
+ isFileLoading: boolean;
26
+ progress: number;
27
+ supportedFileTypes: ModelFileTypes[];
28
+ }
29
+ export type Action = {
30
+ type: 'SET_FILE';
31
+ payload: ModelFile;
32
+ } | {
33
+ type: 'SET_FILE_LOADING';
34
+ payload: boolean;
35
+ } | {
36
+ type: 'SET_PROGRESS';
37
+ payload: number;
38
+ } | {
39
+ type: 'RESET_STATE';
40
+ };
41
+ export type EventTypes = 'MULTIPLE_3D_MODELS' | 'UNSUPPORTED_FILE_TYPE' | 'UPLOAD_PROGRESS' | 'UPLOAD_COMPLETE';
42
+ export type EventData = {
43
+ MULTIPLE_3D_MODELS: File[];
44
+ UNSUPPORTED_FILE_TYPE: File[];
45
+ UPLOAD_PROGRESS: number;
46
+ UPLOAD_COMPLETE: State['file'];
47
+ };
48
+ export type EventHandler<T extends EventTypes> = (data: EventData[T]) => void;
@@ -0,0 +1,11 @@
1
+ import { ModelFileTypes, InputFileOrDirectory } from './types';
2
+ declare function useLoadModel(): {
3
+ on: <T extends import('./types').EventTypes>(event: T, handler: import('./types').EventHandler<T>) => void;
4
+ off: <T extends import('./types').EventTypes>(event: T, handler: import('./types').EventHandler<T>) => void;
5
+ handleFileUpload: (filesOrDirectories: InputFileOrDirectory) => Promise<void>;
6
+ file: import('./types').ModelFile | null;
7
+ isFileLoading: boolean;
8
+ progress: number;
9
+ supportedFileTypes: ModelFileTypes[];
10
+ };
11
+ export default useLoadModel;
@@ -0,0 +1,2 @@
1
+ declare function arrayBufferToBase64(arrayBuffer: ArrayBuffer): Promise<unknown>;
2
+ export default arrayBufferToBase64;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Recursively reads a directory
3
+ *
4
+ * @param directoryHandle - The directory handle to read
5
+ * @returns - An array of file objects
6
+ */
7
+ declare function readDirectory(directoryHandle: FileSystemDirectoryHandle): Promise<File[]>;
8
+ export default readDirectory;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./model-context-mPTTbSMx.cjs");exports.ModelContext=e.ModelContext;exports.ModelFileTypes=e.ModelFileTypes;exports.ModelProvider=e.ModelProvider;exports.useLoadModel=e.useLoadModel;exports.useModelContext=e.useModelContext;
@@ -0,0 +1,8 @@
1
+ import { a as s, M as a, b as d, u as l, c as M } from "./model-context-ClI5AGc8.js";
2
+ export {
3
+ s as ModelContext,
4
+ a as ModelFileTypes,
5
+ d as ModelProvider,
6
+ l as useLoadModel,
7
+ M as useModelContext
8
+ };
package/.babelrc DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "presets": [
3
- [
4
- "@nx/react/babel",
5
- {
6
- "runtime": "automatic",
7
- "useBuiltIns": "usage"
8
- }
9
- ]
10
- ],
11
- "plugins": []
12
- }
package/.eslintrc.json DELETED
@@ -1,18 +0,0 @@
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 DELETED
File without changes
package/project.json DELETED
@@ -1,16 +0,0 @@
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
- }
@@ -1,29 +0,0 @@
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;
@@ -1,74 +0,0 @@
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;
@@ -1,115 +0,0 @@
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;
@@ -1,20 +0,0 @@
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,18 +0,0 @@
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 };
@@ -1,33 +0,0 @@
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;
@@ -1,53 +0,0 @@
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;