@nice2dev/ui-3d 1.1.10 → 1.2.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +11 -15
  3. package/dist/cjs/core/threeCompat.js +52 -0
  4. package/dist/cjs/dance/PoseDetector.js +112 -62
  5. package/dist/cjs/index.js +0 -3
  6. package/dist/cjs/model/ModelEditor.js +0 -3
  7. package/dist/cjs/model/ModelViewer.js +0 -3
  8. package/dist/cjs/model/NiceArmatureEditor.js +2 -2
  9. package/dist/cjs/model/NicePhysicsSimulation.js +1 -1
  10. package/dist/cjs/model/NiceTerrainEditor.js +2 -2
  11. package/dist/cjs/model/NiceWeightPainter.js +2 -2
  12. package/dist/cjs/model/NiceXRPreview.js +3 -3
  13. package/dist/cjs/model/useModelEditor.js +8 -3
  14. package/dist/cjs/model/useModelViewer.js +13 -9
  15. package/dist/cjs/rendering/NiceRenderExport.js +2 -2
  16. package/dist/cjs/rendering/NiceWebGPURenderer.js +3 -2
  17. package/dist/esm/core/threeCompat.js +30 -0
  18. package/dist/esm/dance/PoseDetector.js +114 -63
  19. package/dist/esm/index.js +3 -3
  20. package/dist/esm/model/ModelEditor.js +1 -3
  21. package/dist/esm/model/ModelViewer.js +1 -3
  22. package/dist/esm/model/NiceArmatureEditor.js +3 -3
  23. package/dist/esm/model/NicePhysicsSimulation.js +1 -1
  24. package/dist/esm/model/NiceTerrainEditor.js +2 -2
  25. package/dist/esm/model/NiceWeightPainter.js +2 -2
  26. package/dist/esm/model/NiceXRPreview.js +3 -3
  27. package/dist/esm/model/useModelEditor.js +8 -3
  28. package/dist/esm/model/useModelViewer.js +13 -9
  29. package/dist/esm/rendering/NiceRenderExport.js +2 -2
  30. package/dist/esm/rendering/NiceWebGPURenderer.js +3 -2
  31. package/dist/types/core/threeCompat.d.ts +14 -0
  32. package/dist/types/dance/PoseDetector.d.ts +14 -13
  33. package/dist/types/index.d.ts +4 -4
  34. package/dist/types/model/ModelEditor.d.ts +0 -4
  35. package/dist/types/model/ModelViewer.d.ts +0 -4
  36. package/package.json +2 -2
@@ -21,6 +21,7 @@ import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js';
21
21
  import { SVGLoader } from 'three/examples/jsm/loaders/SVGLoader.js';
22
22
  import { TDSLoader } from 'three/examples/jsm/loaders/TDSLoader.js';
23
23
  import { VTKLoader } from 'three/examples/jsm/loaders/VTKLoader.js';
24
+ import { createFrameClock, SOFT_SHADOW_MAP } from '../core/threeCompat.js';
24
25
  import { SUPPORTED_EXTENSIONS, pose3dToClip } from './modelEditorTypes.js';
25
26
  import { UndoRedoStack, createMaterialFromPreset, generateLOD, convertToInstanced, applyHDRIPreset, snapMulti, HDRI_PRESETS, PBR_PRESETS } from './modelEditorUtils.js';
26
27
 
@@ -52,6 +53,7 @@ function findNodeById(nodes, id) {
52
53
  Hook
53
54
  ═══════════════════════════════════════════ */
54
55
  function useModelEditor({ onSaveToLibrary, onAIPoseVideo, }) {
56
+ var _a;
55
57
  /* ── refs ── */
56
58
  const mountRef = useRef(null);
57
59
  const rendererRef = useRef(null);
@@ -59,7 +61,9 @@ function useModelEditor({ onSaveToLibrary, onAIPoseVideo, }) {
59
61
  const cameraRef = useRef(new THREE.PerspectiveCamera(50, 1, 0.01, 10000));
60
62
  const orbitRef = useRef(null);
61
63
  const transformRef = useRef(null);
62
- const clockRef = useRef(new THREE.Clock());
64
+ // Created once: useRef's argument runs on every render, and three r183 warns per Clock.
65
+ const clockRef = useRef(null);
66
+ (_a = clockRef.current) !== null && _a !== void 0 ? _a : (clockRef.current = createFrameClock());
63
67
  const mixerRef = useRef(null);
64
68
  const rafRef = useRef(0);
65
69
  const fileInputRef = useRef(null);
@@ -139,7 +143,7 @@ function useModelEditor({ onSaveToLibrary, onAIPoseVideo, }) {
139
143
  const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: false });
140
144
  renderer.setPixelRatio(window.devicePixelRatio);
141
145
  renderer.shadowMap.enabled = true;
142
- renderer.shadowMap.type = THREE.PCFSoftShadowMap;
146
+ renderer.shadowMap.type = SOFT_SHADOW_MAP;
143
147
  renderer.toneMapping = THREE.ACESFilmicToneMapping;
144
148
  renderer.toneMappingExposure = 1.2;
145
149
  renderer.outputColorSpace = THREE.SRGBColorSpace;
@@ -222,8 +226,9 @@ function useModelEditor({ onSaveToLibrary, onAIPoseVideo, }) {
222
226
  onResize();
223
227
  // Animation loop
224
228
  const animate = () => {
229
+ var _a, _b;
225
230
  rafRef.current = requestAnimationFrame(animate);
226
- const dt = clockRef.current.getDelta();
231
+ const dt = (_b = (_a = clockRef.current) === null || _a === void 0 ? void 0 : _a.getDelta()) !== null && _b !== void 0 ? _b : 0;
227
232
  orbit.update();
228
233
  // Update mixer
229
234
  if (mixerRef.current && isPlayingRef.current) {
@@ -8,6 +8,7 @@ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
8
8
  import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
9
9
  import { PLYLoader } from 'three/examples/jsm/loaders/PLYLoader.js';
10
10
  import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js';
11
+ import { createFrameClock, SOFT_SHADOW_MAP } from '../core/threeCompat.js';
11
12
 
12
13
  /**
13
14
  * useModelViewer — lightweight hook for the view-only 3D model viewer.
@@ -39,6 +40,7 @@ const TONE_MAP = {
39
40
  Hook
40
41
  ═══════════════════════════════════════════ */
41
42
  function useModelViewer(props = {}) {
43
+ var _a;
42
44
  const { src, format, navigationMode: initNavMode = 'orbit', quality = 'high', autoRotateSpeed: initAutoRotate = 0, backgroundColor = 'var(--nice-bg, #1a1a2e)', showGrid: initShowGrid = true, shadows = true, gamepad = false, cameraPresets: _cameraPresets = [], annotations: _annotations = [], hotspots: _hotspots = [], floorPlans: _floorPlans = [], onHotspotClick: _onHotspotClick, onAnnotationClick: _onAnnotationClick, onLoadProgress, onLoad, onError, clippingPlanes = [], measureMode: initMeasureMode = false, measurements: _measurements = [], onMeasure: _onMeasure, minDistance = 0.1, maxDistance = 1000, fov = 50, vr: _vr = false, walkSpeed = 5, ambientIntensity = 0.5, directionalIntensity = 0.8, antiAlias = true, toneMapping = 'aces', exposure = 1, } = props;
43
45
  /* ── refs ── */
44
46
  const mountRef = useRef(null);
@@ -46,7 +48,9 @@ function useModelViewer(props = {}) {
46
48
  const sceneRef = useRef(new THREE.Scene());
47
49
  const cameraRef = useRef(new THREE.PerspectiveCamera(fov, 1, 0.01, 10000));
48
50
  const orbitRef = useRef(null);
49
- const clockRef = useRef(new THREE.Clock());
51
+ // Created once: useRef's argument runs on every render, and three r183 warns per Clock.
52
+ const clockRef = useRef(null);
53
+ (_a = clockRef.current) !== null && _a !== void 0 ? _a : (clockRef.current = createFrameClock());
50
54
  const mixerRef = useRef(null);
51
55
  const rafRef = useRef(0);
52
56
  const rootRef = useRef(null);
@@ -102,7 +106,7 @@ function useModelViewer(props = {}) {
102
106
  renderer.outputColorSpace = THREE.SRGBColorSpace;
103
107
  if (shadows) {
104
108
  renderer.shadowMap.enabled = true;
105
- renderer.shadowMap.type = THREE.PCFSoftShadowMap;
109
+ renderer.shadowMap.type = SOFT_SHADOW_MAP;
106
110
  }
107
111
  mount.appendChild(renderer.domElement);
108
112
  rendererRef.current = renderer;
@@ -156,20 +160,20 @@ function useModelViewer(props = {}) {
156
160
  ro.observe(mount);
157
161
  // Animation loop
158
162
  const animate = () => {
159
- var _a, _b, _c, _d, _e;
163
+ var _a, _b, _c, _d, _e, _f, _g;
160
164
  if (disposeRef.current) {
161
165
  return;
162
166
  }
163
167
  rafRef.current = requestAnimationFrame(animate);
164
- const dt = clockRef.current.getDelta();
168
+ const dt = (_b = (_a = clockRef.current) === null || _a === void 0 ? void 0 : _a.getDelta()) !== null && _b !== void 0 ? _b : 0;
165
169
  // Gamepad FPS-style nav
166
170
  if (gamepad && navMode === 'fps') {
167
- const pads = (_a = navigator.getGamepads) === null || _a === void 0 ? void 0 : _a.call(navigator);
168
- const gp = (_b = pads === null || pads === void 0 ? void 0 : pads[0]) !== null && _b !== void 0 ? _b : null;
171
+ const pads = (_c = navigator.getGamepads) === null || _c === void 0 ? void 0 : _c.call(navigator);
172
+ const gp = (_d = pads === null || pads === void 0 ? void 0 : pads[0]) !== null && _d !== void 0 ? _d : null;
169
173
  if (gp) {
170
- const lx = (_c = gp.axes[0]) !== null && _c !== void 0 ? _c : 0;
171
- const ly = (_d = gp.axes[1]) !== null && _d !== void 0 ? _d : 0;
172
- const rx = (_e = gp.axes[2]) !== null && _e !== void 0 ? _e : 0;
174
+ const lx = (_e = gp.axes[0]) !== null && _e !== void 0 ? _e : 0;
175
+ const ly = (_f = gp.axes[1]) !== null && _f !== void 0 ? _f : 0;
176
+ const rx = (_g = gp.axes[2]) !== null && _g !== void 0 ? _g : 0;
173
177
  const fwd = new THREE.Vector3();
174
178
  camera.getWorldDirection(fwd);
175
179
  fwd.y = 0;
@@ -320,13 +320,13 @@ const NiceRenderExport = ({ renderer, scene, camera, className = '', }) => {
320
320
  ? 'var(--nice-color-accent, #6366f1)'
321
321
  : 'transparent',
322
322
  color: config.width === p.width && config.height === p.height
323
- ? 'var(--nice-text-on-primary, #fff)'
323
+ ? 'var(--nice-color-white, #fff)'
324
324
  : 'inherit',
325
325
  }, children: p.label }, p.label))) }), jsxs("div", { style: { display: 'flex', gap: 4, alignItems: 'center' }, children: [jsx("input", { type: "number", value: config.width, min: 1, max: 8192, onChange: (e) => setConfig({ width: parseInt(e.target.value, 10) || 1 }), style: { width: 70, padding: '3px 6px' } }), jsx("span", { children: "\u00D7" }), jsx("input", { type: "number", value: config.height, min: 1, max: 8192, onChange: (e) => setConfig({ height: parseInt(e.target.value, 10) || 1 }), style: { width: 70, padding: '3px 6px' } })] }), jsxs("label", { children: ["Format:", jsxs("select", { value: config.format, onChange: (e) => setConfig({ format: e.target.value }), style: { width: '100%', marginTop: 2 }, children: [jsx("option", { value: "png", children: "PNG (lossless + alpha)" }), jsx("option", { value: "jpeg", children: "JPEG (lossy, no alpha)" }), jsx("option", { value: "exr", children: "EXR (HDR float)" })] })] }), jsxs("label", { children: ["Background:", jsxs("select", { value: config.backgroundMode, onChange: (e) => setConfig({ backgroundMode: e.target.value }), style: { width: '100%', marginTop: 2 }, children: [jsx("option", { value: "transparent", children: "Transparent" }), jsx("option", { value: "color", children: "Solid Color" }), jsx("option", { value: "scene", children: "Scene Background" })] })] }), config.backgroundMode === 'color' && (jsxs("label", { style: { display: 'flex', alignItems: 'center', gap: 6 }, children: ["Color:", jsx("input", { type: "color", value: config.backgroundColor, onChange: (e) => setConfig({ backgroundColor: e.target.value }) })] })), jsxs("label", { children: ["Supersampling: ", config.samples, "x", jsxs("select", { value: config.samples, onChange: (e) => setConfig({ samples: parseInt(e.target.value, 10) }), style: { width: '100%', marginTop: 2 }, children: [jsx("option", { value: 1, children: "1x (none)" }), jsx("option", { value: 2, children: "2x" }), jsx("option", { value: 4, children: "4x (best quality)" })] })] }), jsx("button", { type: "button", onClick: handleRender, disabled: isRendering, style: {
326
326
  background: isRendering
327
327
  ? 'var(--nice-bg-tertiary, #94a3b8)'
328
328
  : 'var(--nice-color-accent, #6366f1)',
329
- color: 'var(--nice-text-on-primary, #fff)',
329
+ color: 'var(--nice-color-white, #fff)',
330
330
  border: 'none',
331
331
  borderRadius: 4,
332
332
  padding: '8px 12px',
@@ -2,6 +2,7 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
2
  import { NiceIcon } from '@nice2dev/ui';
3
3
  import { useState, useRef, useEffect, useCallback } from 'react';
4
4
  import * as THREE from 'three';
5
+ import { SOFT_SHADOW_MAP } from '../core/threeCompat.js';
5
6
 
6
7
  /* ── WebGPU detection ── */
7
8
  async function detectWebGPU() {
@@ -116,7 +117,7 @@ function useWebGPURenderer(canvas, scene, camera, width = 800, height = 600, onR
116
117
  r.toneMappingExposure = toneMappingExposure;
117
118
  r.outputColorSpace = outputColorSpace;
118
119
  r.shadowMap.enabled = true;
119
- r.shadowMap.type = THREE.PCFSoftShadowMap;
120
+ r.shadowMap.type = SOFT_SHADOW_MAP;
120
121
  rendererRef.current = r;
121
122
  setRenderer(r);
122
123
  setIsWebGPU(usingWebGPU);
@@ -214,7 +215,7 @@ const NiceWebGPURenderer = ({ canvas, scene, camera, width, height, onRendererRe
214
215
  padding: '2px 6px',
215
216
  borderRadius: 4,
216
217
  background: isWebGPU ? 'var(--nice-success, #22c55e)' : 'var(--nice-warning, #f59e0b)',
217
- color: 'var(--nice-text-on-primary, #fff)',
218
+ color: 'var(--nice-color-white, #fff)',
218
219
  }, children: isWebGPU ? 'WebGPU' : 'WebGL' })] }), !isReady && jsx("div", { style: { opacity: 0.6, fontSize: 11 }, children: "Initializing\u2026" }), capabilities && (jsxs("div", { style: { fontSize: 10, opacity: 0.7, lineHeight: 1.5 }, children: ["GPU: ", capabilities.adapterName, jsx("br", {}), "Vendor: ", capabilities.vendor, jsx("br", {}), "Max Texture: ", capabilities.maxTextureDimension2D, "px", capabilities.features.length > 0 && (jsxs(Fragment, { children: [jsx("br", {}), "Features: ", capabilities.features.length] }))] })), jsxs("label", { children: ["Tone Mapping:", jsx("select", { value: toneMapping, onChange: (e) => setToneMapping(parseInt(e.target.value, 10)), style: { width: '100%', marginTop: 2 }, children: TONE_MAPPINGS.map((tm) => (jsx("option", { value: tm.value, children: tm.label }, tm.value))) })] }), jsxs("label", { children: ["Exposure: ", toneMappingExposure.toFixed(2), jsx("input", { type: "range", min: 0.1, max: 3, step: 0.05, value: toneMappingExposure, onChange: (e) => setToneMappingExposure(parseFloat(e.target.value)), style: { width: '100%' } })] }), jsxs("label", { children: ["Output Color Space:", jsxs("select", { value: outputColorSpace, onChange: (e) => setOutputColorSpace(e.target.value), style: { width: '100%', marginTop: 2 }, children: [jsx("option", { value: THREE.SRGBColorSpace, children: "sRGB" }), jsx("option", { value: THREE.LinearSRGBColorSpace, children: "Linear sRGB" })] })] }), jsxs("label", { children: ["Pixel Ratio: ", pixelRatio.toFixed(1), jsx("input", { type: "range", min: 0.5, max: 3, step: 0.5, value: pixelRatio, onChange: (e) => setPixelRatio(parseFloat(e.target.value)), style: { width: '100%' } })] })] }));
219
220
  };
220
221
 
@@ -0,0 +1,14 @@
1
+ /**
2
+ * three.js r183 deprecated `Clock` (for `Timer`) and folds `PCFSoftShadowMap` into
3
+ * `PCFShadowMap`; both log a console warning there. The peer range starts at r150, which has
4
+ * neither `Timer` in its core nor the softer `PCFShadowMap`, so the choice follows the revision.
5
+ */
6
+ import * as THREE from 'three';
7
+ /** Soft shadows without the r183 deprecation warning; older three keeps `PCFSoftShadowMap`. */
8
+ export declare const SOFT_SHADOW_MAP: THREE.ShadowMapType;
9
+ /** Seconds since the previous call — what an animation loop feeds its mixer. */
10
+ export interface FrameClock {
11
+ getDelta(): number;
12
+ }
13
+ /** `Timer` where three has deprecated `Clock`, `Clock` before. */
14
+ export declare function createFrameClock(): FrameClock;
@@ -1,8 +1,17 @@
1
1
  import React from 'react';
2
- import type { Pose3DFrame } from '../model/modelEditorTypes';
2
+ import type { PosePerson3D, Pose3DFrame } from '../model/modelEditorTypes';
3
3
  export type PoseBackend = 'mediapipe' | 'tfjs';
4
+ /**
5
+ * Finds the people in one video frame; the model is yours — TF.js pose-detection (MoveNet,
6
+ * BlazePose), MediaPipe Pose Landmarker… Return keypoints in video pixels, named as in COCO-17
7
+ * (`nose`, `left_shoulder`, `right_ankle`, …): the overlay connects them by name. It may be
8
+ * async; the next detection waits for it.
9
+ */
10
+ export type NicePoseDetectorFn = (video: HTMLVideoElement, timestampMs: number) => PosePerson3D[] | Promise<PosePerson3D[]>;
4
11
  export interface NicePoseDetectorConfig {
5
- /** Detection backend */
12
+ /** Finds the poses in each frame. Without it the camera runs, but nothing is detected. */
13
+ detector?: NicePoseDetectorFn;
14
+ /** Which backend your `detector` uses — informational; the component loads no model. */
6
15
  backend?: PoseBackend;
7
16
  /** Maximum number of persons to track */
8
17
  maxPersons?: number;
@@ -17,8 +26,6 @@ export interface NicePoseDetectorConfig {
17
26
  /** Show confidence dots on keypoints */
18
27
  showConfidence?: boolean;
19
28
  }
20
- /** @deprecated Use NicePoseDetectorConfig */
21
- export type PoseDetectorConfig = NicePoseDetectorConfig;
22
29
  export interface NicePoseDetectorHandle {
23
30
  /** Start detection */
24
31
  start(): void;
@@ -29,8 +36,6 @@ export interface NicePoseDetectorHandle {
29
36
  /** Check if actively detecting */
30
37
  readonly isDetecting: boolean;
31
38
  }
32
- /** @deprecated Use NicePoseDetectorHandle */
33
- export type PoseDetectorHandle = NicePoseDetectorHandle;
34
39
  export interface NicePoseDetectorProps extends NicePoseDetectorConfig {
35
40
  /** Called each frame with detected poses */
36
41
  onFrame?: (frame: Pose3DFrame) => void;
@@ -38,7 +43,7 @@ export interface NicePoseDetectorProps extends NicePoseDetectorConfig {
38
43
  onStart?: () => void;
39
44
  /** Called when detection stops */
40
45
  onStop?: () => void;
41
- /** Called on error */
46
+ /** Called when the camera cannot start or the detector fails (detection then stops) */
42
47
  onError?: (error: Error) => void;
43
48
  /** CSS class for the container */
44
49
  className?: string;
@@ -49,14 +54,10 @@ export interface NicePoseDetectorProps extends NicePoseDetectorConfig {
49
54
  /** Height of the video feed */
50
55
  height?: number;
51
56
  }
52
- /** @deprecated Use NicePoseDetectorProps */
53
- export type PoseDetectorProps = NicePoseDetectorProps;
54
- export declare function usePoseDetection(config?: PoseDetectorConfig): {
55
- start: (video: HTMLVideoElement, onFrame?: (frame: Pose3DFrame) => void) => Promise<void>;
57
+ export declare function usePoseDetection(config?: NicePoseDetectorConfig): {
58
+ start: (video: HTMLVideoElement, onFrame?: (frame: Pose3DFrame) => void, onError?: (error: Error) => void) => Promise<void>;
56
59
  stop: () => void;
57
60
  isDetecting: boolean;
58
61
  getLatestFrame: () => Pose3DFrame | null;
59
62
  };
60
63
  export declare const NicePoseDetector: React.ForwardRefExoticComponent<NicePoseDetectorProps & React.RefAttributes<NicePoseDetectorHandle>>;
61
- /** @deprecated Use NicePoseDetector */
62
- export declare const PoseDetector: React.ForwardRefExoticComponent<NicePoseDetectorProps & React.RefAttributes<NicePoseDetectorHandle>>;
@@ -2,11 +2,11 @@
2
2
  * @nice2dev/ui-3d — Public API
3
3
  *
4
4
  * Tree-shakeable exports. Import only what you need:
5
- * import { ModelEditor } from '@nice2dev/ui-3d';
5
+ * import { NiceModelEditor } from '@nice2dev/ui-3d';
6
6
  * import { NiceI18nProvider } from '@nice2dev/ui-3d';
7
7
  */
8
- export { NiceModelEditor, ModelEditor, type NiceModelEditorProps, type ModelEditorProps, } from './model/ModelEditor';
9
- export { NiceModelViewer, ModelViewer, type NiceModelViewerProps, type ModelViewerProps, } from './model/ModelViewer';
8
+ export { NiceModelEditor, type NiceModelEditorProps } from './model/ModelEditor';
9
+ export { NiceModelViewer, type NiceModelViewerProps } from './model/ModelViewer';
10
10
  export { type CADTool, type CADSnapMode, type CADUnit, type CADGridConfig, type WallSegment, type WallOpening, type FloorPlan, type RoomDefinition, type RoomType, type StairConfig, type Annotation, type CADSettings, type DXFEntity, DEFAULT_CAD_SETTINGS, UNIT_SCALES, ROOM_COLORS, WALL_MATERIALS, FLOOR_MATERIALS, createCADGrid, snapToCADGrid, } from './model/cadModeUtils';
11
11
  export { type FurnitureCategory, type FurnitureItem, type PlacedFurniture, type RoomLayout, type SimsTool, type SimsState, FURNITURE_CATALOG, FURNITURE_CATEGORIES, ROOM_PRESETS, createFurnitureMesh, placeFurnitureInScene, removeFurnitureFromScene, rotatePlacedItem, resizePlacedItem, createDragPreview, getFloorIntersection, checkFurnitureCollision, applyRoomLayout, calculateBudget, } from './model/simsModeUtils';
12
12
  export { useModelEditor } from './model/useModelEditor';
@@ -15,7 +15,7 @@ export { NiceI18nProvider, useNiceTranslation, type NiceTranslateFn, type NiceI1
15
15
  export { UndoRedoStack, type UndoAction, PBR_PRESETS, type PBRPreset, applyPBRPreset, createMaterialFromPreset, generateLOD, type LODLevel, convertToInstanced, countTriangles, computeSceneBounds, measureDistance, measureAngle, type Measurement, HDRI_PRESETS, type HDRIPreset, applyHDRIPreset, snapToGrid, snapToVertex, snapToEdge, snapMulti, type SnapTarget, type SnapResult, evaluateTrack, setKeyframe, removeKeyframe, toThreeKeyframeTrack, createAnimationClip, type Keyframe, type KeyframeTrack, downloadBlob, exportSceneGLTF, exportSceneUSDZ, type ExportOptions, crossfadeAnimations, makeAdditiveAction, blendAnimations, subclip, type AnimationBlendConfig, solveIKChain, type IKChain, createViewportCamera, renderMultiViewport, QUAD_VIEWPORT, type ViewportPreset, type ViewportConfig, } from './model/modelEditorUtils';
16
16
  export { EditorShortcutManager, type EditorShortcut, type EditorShortcutBinding, type EditorShortcutConfig, } from './model/editorShortcuts';
17
17
  export type { Pose3DSequenceResult, Pose3DFrame, PosePerson3D, PoseKeypoint3D, SceneNode, AnimClip, TransformMode, ShadingMode, EditorMode, } from './model/modelEditorTypes';
18
- export { NicePoseDetector, PoseDetector, usePoseDetection, type NicePoseDetectorProps, type NicePoseDetectorHandle, type NicePoseDetectorConfig, type PoseDetectorProps, type PoseDetectorHandle, type PoseDetectorConfig, type PoseBackend, } from './dance/PoseDetector';
18
+ export { NicePoseDetector, usePoseDetection, type NicePoseDetectorProps, type NicePoseDetectorHandle, type NicePoseDetectorConfig, type NicePoseDetectorFn, type PoseBackend, } from './dance/PoseDetector';
19
19
  export { DanceScoreEngine, useDanceScore, type DanceScoreConfig, type FrameScore, type DanceSessionResult, type HitRating, type KeypointScore, } from './dance/DanceScoreEngine';
20
20
  export { DanceBridge, useDanceBridge, rhythmToBeatSync, type DanceBridgeConfig, type DanceBridgeCallbacks, type DanceBridgeHandle, type DanceSessionState, type BeatSync, } from './dance/DanceBridge';
21
21
  export { NiceUVEditor, type NiceUVEditorProps } from './uv/NiceUVEditor';
@@ -13,9 +13,5 @@ export interface NiceModelEditorProps {
13
13
  /** Optional AI pose-from-video callback. If omitted the AI video button is hidden. */
14
14
  onAIPoseVideo?: (file: File) => Promise<import('./modelEditorTypes').Pose3DSequenceResult>;
15
15
  }
16
- /** @deprecated Use NiceModelEditorProps */
17
- export type ModelEditorProps = NiceModelEditorProps;
18
16
  export declare const NiceModelEditor: React.FC<NiceModelEditorProps>;
19
- /** @deprecated Use NiceModelEditor */
20
- export declare const ModelEditor: React.FC<NiceModelEditorProps>;
21
17
  export default NiceModelEditor;
@@ -23,9 +23,5 @@ export interface NiceModelViewerProps extends UseModelViewerProps {
23
23
  /** Render prop — exposes the full API. */
24
24
  children?: (api: ModelViewerAPI) => React.ReactNode;
25
25
  }
26
- /** @deprecated Use NiceModelViewerProps */
27
- export type ModelViewerProps = NiceModelViewerProps;
28
26
  export declare const NiceModelViewer: React.FC<NiceModelViewerProps>;
29
- /** @deprecated Use NiceModelViewer */
30
- export declare const ModelViewer: React.FC<NiceModelViewerProps>;
31
27
  export default NiceModelViewer;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nice2dev/ui-3d",
3
- "version": "1.1.10",
3
+ "version": "1.2.0",
4
4
  "description": "Nice2Dev 3D Editor — Blender-style 3D model editor component for React, powered by Three.js",
5
5
  "author": "NiceToDev <contact@nicetodev.com>",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -65,7 +65,7 @@
65
65
  "three": ">=0.150.0"
66
66
  },
67
67
  "devDependencies": {
68
- "@nice2dev/ui": "^1.1.10",
68
+ "@nice2dev/ui": "^1.2.0",
69
69
  "@rollup/plugin-commonjs": "^29.0.3",
70
70
  "@rollup/plugin-node-resolve": "^16.0.3",
71
71
  "@rollup/plugin-typescript": "^12.3.0",