@nice2dev/ui-3d 1.0.4 → 1.0.5

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 (43) hide show
  1. package/dist/cjs/core/i18n.js +3 -3
  2. package/dist/cjs/dance/DanceBridge.js +13 -13
  3. package/dist/cjs/dance/DanceScoreEngine.js +8 -8
  4. package/dist/cjs/dance/PoseDetector.js +20 -20
  5. package/dist/cjs/material/NiceMaterialEditor.js +19 -19
  6. package/dist/cjs/model/ModelEditorLeftPanel.js +3 -3
  7. package/dist/cjs/model/ModelEditorMenuBar.js +2 -2
  8. package/dist/cjs/model/ModelEditorRightPanel.js +2 -2
  9. package/dist/cjs/model/ModelEditorSubComponents.js +3 -3
  10. package/dist/cjs/model/ModelEditorTimeline.js +3 -3
  11. package/dist/cjs/model/ModelEditorToolbar.js +2 -2
  12. package/dist/cjs/model/ModelEditorViewport.js +2 -2
  13. package/dist/cjs/model/ModelViewer.js +8 -8
  14. package/dist/cjs/model/NiceArmatureEditor.js +18 -18
  15. package/dist/cjs/model/NiceMorphTargetEditor.js +18 -18
  16. package/dist/cjs/model/NiceOctree.js +16 -16
  17. package/dist/cjs/model/NicePhysicsSimulation.js +24 -24
  18. package/dist/cjs/model/NiceProceduralGeometry.js +8 -8
  19. package/dist/cjs/model/NiceTerrainEditor.js +19 -19
  20. package/dist/cjs/model/NiceWeightPainter.js +14 -14
  21. package/dist/cjs/model/NiceXRPreview.js +18 -18
  22. package/dist/cjs/model/useModelEditor.js +127 -127
  23. package/dist/cjs/model/useModelViewer.js +61 -61
  24. package/dist/cjs/particle/NiceParticleEditor.js +11 -11
  25. package/dist/cjs/rendering/NiceCascadedShadows.js +12 -12
  26. package/dist/cjs/rendering/NiceRenderExport.js +5 -5
  27. package/dist/cjs/rendering/NiceSSAO.js +18 -18
  28. package/dist/cjs/rendering/NiceSSR.js +14 -14
  29. package/dist/cjs/rendering/NiceWebGPURenderer.js +21 -21
  30. package/dist/cjs/ui/dist/index.js +32608 -24033
  31. package/dist/cjs/ui/dist/index.js.map +1 -1
  32. package/dist/cjs/uv/NiceUVEditor.js +24 -24
  33. package/dist/esm/model/ModelEditorLeftPanel.js +5 -5
  34. package/dist/esm/model/ModelEditorMenuBar.js +5 -5
  35. package/dist/esm/model/ModelEditorRightPanel.js +17 -17
  36. package/dist/esm/model/ModelEditorSubComponents.js +6 -6
  37. package/dist/esm/model/ModelEditorTimeline.js +5 -5
  38. package/dist/esm/model/ModelEditorToolbar.js +4 -4
  39. package/dist/esm/model/ModelEditorViewport.js +2 -2
  40. package/dist/esm/model/ModelViewer.js +5 -5
  41. package/dist/esm/ui/dist/index.js +31739 -23166
  42. package/dist/esm/ui/dist/index.js.map +1 -1
  43. package/package.json +1 -1
@@ -1,13 +1,13 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var Ve = require('react');
4
+ var Ue = require('react');
5
5
 
6
6
  const fallback = (_key, defaultValue) => defaultValue;
7
- const NiceI18nContext = Ve.createContext(fallback);
7
+ const NiceI18nContext = Ue.createContext(fallback);
8
8
  const NiceI18nProvider = ({ t, children }) => (jsxRuntime.jsx(NiceI18nContext.Provider, { value: t, children: children }));
9
9
  function useNiceTranslation() {
10
- const t = Ve.useContext(NiceI18nContext);
10
+ const t = Ue.useContext(NiceI18nContext);
11
11
  return { t };
12
12
  }
13
13
 
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var Ve = require('react');
3
+ var Ue = require('react');
4
4
  var DanceScoreEngine = require('./DanceScoreEngine.js');
5
5
 
6
6
  /**
@@ -113,13 +113,13 @@ class DanceBridge {
113
113
  }
114
114
  // ── React hook: useDanceBridge ──────────────────────────────────
115
115
  function useDanceBridge(config, callbacks) {
116
- const bridgeRef = Ve.useRef(null);
117
- const [state, setState] = Ve.useState('idle');
118
- const [lastScore, setLastScore] = Ve.useState(null);
119
- const [result, setResult] = Ve.useState(null);
120
- const [combo, setCombo] = Ve.useState(0);
121
- const [progress, setProgress] = Ve.useState(0);
122
- Ve.useEffect(() => {
116
+ const bridgeRef = Ue.useRef(null);
117
+ const [state, setState] = Ue.useState('idle');
118
+ const [lastScore, setLastScore] = Ue.useState(null);
119
+ const [result, setResult] = Ue.useState(null);
120
+ const [combo, setCombo] = Ue.useState(0);
121
+ const [progress, setProgress] = Ue.useState(0);
122
+ Ue.useEffect(() => {
123
123
  if (!config) {
124
124
  bridgeRef.current = null;
125
125
  return;
@@ -134,11 +134,11 @@ function useDanceBridge(config, callbacks) {
134
134
  return () => { bridgeRef.current = null; };
135
135
  // eslint-disable-next-line react-hooks/exhaustive-deps
136
136
  }, [config]);
137
- const start = Ve.useCallback(() => { var _a; (_a = bridgeRef.current) === null || _a === void 0 ? void 0 : _a.start(); }, []);
138
- const pause = Ve.useCallback(() => { var _a; (_a = bridgeRef.current) === null || _a === void 0 ? void 0 : _a.pause(); }, []);
139
- const resume = Ve.useCallback(() => { var _a; (_a = bridgeRef.current) === null || _a === void 0 ? void 0 : _a.resume(); }, []);
140
- const stop = Ve.useCallback(() => { var _a, _b; return (_b = (_a = bridgeRef.current) === null || _a === void 0 ? void 0 : _a.stop()) !== null && _b !== void 0 ? _b : null; }, []);
141
- const feedFrame = Ve.useCallback((frame) => {
137
+ const start = Ue.useCallback(() => { var _a; (_a = bridgeRef.current) === null || _a === void 0 ? void 0 : _a.start(); }, []);
138
+ const pause = Ue.useCallback(() => { var _a; (_a = bridgeRef.current) === null || _a === void 0 ? void 0 : _a.pause(); }, []);
139
+ const resume = Ue.useCallback(() => { var _a; (_a = bridgeRef.current) === null || _a === void 0 ? void 0 : _a.resume(); }, []);
140
+ const stop = Ue.useCallback(() => { var _a, _b; return (_b = (_a = bridgeRef.current) === null || _a === void 0 ? void 0 : _a.stop()) !== null && _b !== void 0 ? _b : null; }, []);
141
+ const feedFrame = Ue.useCallback((frame) => {
142
142
  var _a, _b;
143
143
  const score = (_b = (_a = bridgeRef.current) === null || _a === void 0 ? void 0 : _a.feedFrame(frame)) !== null && _b !== void 0 ? _b : null;
144
144
  if (bridgeRef.current)
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var Ve = require('react');
3
+ var Ue = require('react');
4
4
 
5
5
  // ── Default config ──────────────────────────────────────────────
6
6
  const DEFAULT_CONFIG = {
@@ -179,25 +179,25 @@ class DanceScoreEngine {
179
179
  }
180
180
  }
181
181
  function useDanceScore(config) {
182
- const engineRef = Ve.useRef(new DanceScoreEngine(config));
183
- const [lastScore, setLastScore] = Ve.useState(null);
184
- const [result, setResult] = Ve.useState(null);
185
- const loadReference = Ve.useCallback((seq) => {
182
+ const engineRef = Ue.useRef(new DanceScoreEngine(config));
183
+ const [lastScore, setLastScore] = Ue.useState(null);
184
+ const [result, setResult] = Ue.useState(null);
185
+ const loadReference = Ue.useCallback((seq) => {
186
186
  engineRef.current.loadReference(seq);
187
187
  setLastScore(null);
188
188
  setResult(null);
189
189
  }, []);
190
- const scoreFrame = Ve.useCallback((frame) => {
190
+ const scoreFrame = Ue.useCallback((frame) => {
191
191
  const score = engineRef.current.scoreFrame(frame);
192
192
  setLastScore(score);
193
193
  return score;
194
194
  }, []);
195
- const finish = Ve.useCallback(() => {
195
+ const finish = Ue.useCallback(() => {
196
196
  const r = engineRef.current.getResult();
197
197
  setResult(r);
198
198
  return r;
199
199
  }, []);
200
- const reset = Ve.useCallback(() => {
200
+ const reset = Ue.useCallback(() => {
201
201
  engineRef.current.reset();
202
202
  setLastScore(null);
203
203
  setResult(null);
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var Ve = require('react');
4
+ var Ue = require('react');
5
5
 
6
6
  // ── Standard keypoint definitions (COCO 17-keypoint model) ──────
7
7
  const COCO_KEYPOINTS = [
@@ -31,14 +31,14 @@ function createSimulatedKeypoints() {
31
31
  // ── Hook: usePoseDetection ──────────────────────────────────────
32
32
  function usePoseDetection(config = {}) {
33
33
  const { maxPersons = 1, minConfidence = 0.5, targetFps = 30, } = config;
34
- const [isDetecting, setIsDetecting] = Ve.useState(false);
35
- const latestFrameRef = Ve.useRef(null);
36
- const frameIndexRef = Ve.useRef(0);
37
- const rafRef = Ve.useRef(0);
38
- const streamRef = Ve.useRef(null);
39
- const videoRef = Ve.useRef(null);
40
- const callbackRef = Ve.useRef(null);
41
- const processFrame = Ve.useCallback(() => {
34
+ const [isDetecting, setIsDetecting] = Ue.useState(false);
35
+ const latestFrameRef = Ue.useRef(null);
36
+ const frameIndexRef = Ue.useRef(0);
37
+ const rafRef = Ue.useRef(0);
38
+ const streamRef = Ue.useRef(null);
39
+ const videoRef = Ue.useRef(null);
40
+ const callbackRef = Ue.useRef(null);
41
+ const processFrame = Ue.useCallback(() => {
42
42
  var _a;
43
43
  if (!videoRef.current || videoRef.current.readyState < 2) {
44
44
  rafRef.current = requestAnimationFrame(processFrame);
@@ -64,7 +64,7 @@ function usePoseDetection(config = {}) {
64
64
  (_a = callbackRef.current) === null || _a === void 0 ? void 0 : _a.call(callbackRef, frame);
65
65
  rafRef.current = requestAnimationFrame(processFrame);
66
66
  }, [maxPersons, minConfidence, targetFps]);
67
- const start = Ve.useCallback(async (video, onFrame) => {
67
+ const start = Ue.useCallback(async (video, onFrame) => {
68
68
  try {
69
69
  const stream = await navigator.mediaDevices.getUserMedia({
70
70
  video: { facingMode: 'user', width: { ideal: 640 }, height: { ideal: 480 } },
@@ -82,7 +82,7 @@ function usePoseDetection(config = {}) {
82
82
  throw new Error(`Camera access failed: ${err instanceof Error ? err.message : String(err)}`);
83
83
  }
84
84
  }, [processFrame]);
85
- const stop = Ve.useCallback(() => {
85
+ const stop = Ue.useCallback(() => {
86
86
  var _a;
87
87
  cancelAnimationFrame(rafRef.current);
88
88
  (_a = streamRef.current) === null || _a === void 0 ? void 0 : _a.getTracks().forEach(t => t.stop());
@@ -91,22 +91,22 @@ function usePoseDetection(config = {}) {
91
91
  videoRef.current.srcObject = null;
92
92
  setIsDetecting(false);
93
93
  }, []);
94
- Ve.useEffect(() => () => { stop(); }, [stop]);
94
+ Ue.useEffect(() => () => { stop(); }, [stop]);
95
95
  return { start, stop, isDetecting, getLatestFrame: () => latestFrameRef.current };
96
96
  }
97
97
  // ── Component: PoseDetector ─────────────────────────────────────
98
- const NicePoseDetector = Ve.forwardRef(function NicePoseDetector(props, ref) {
98
+ const NicePoseDetector = Ue.forwardRef(function NicePoseDetector(props, ref) {
99
99
  const { onFrame, onStart, onStop, onError, className, style, width = 640, height = 480, mirror = true, showSkeleton = true, showConfidence = false, ...config } = props;
100
- const videoRef = Ve.useRef(null);
101
- const canvasRef = Ve.useRef(null);
100
+ const videoRef = Ue.useRef(null);
101
+ const canvasRef = Ue.useRef(null);
102
102
  const detection = usePoseDetection(config);
103
- Ve.useImperativeHandle(ref, () => ({
103
+ Ue.useImperativeHandle(ref, () => ({
104
104
  start: handleStart,
105
105
  stop: handleStop,
106
106
  getLatestFrame: detection.getLatestFrame,
107
107
  get isDetecting() { return detection.isDetecting; },
108
108
  }));
109
- const drawSkeleton = Ve.useCallback((frame) => {
109
+ const drawSkeleton = Ue.useCallback((frame) => {
110
110
  var _a, _b, _c, _d, _e, _f;
111
111
  const ctx = (_a = canvasRef.current) === null || _a === void 0 ? void 0 : _a.getContext('2d');
112
112
  if (!ctx || !canvasRef.current)
@@ -144,11 +144,11 @@ const NicePoseDetector = Ve.forwardRef(function NicePoseDetector(props, ref) {
144
144
  }
145
145
  }
146
146
  }, [showSkeleton, showConfidence]);
147
- const handleFrame = Ve.useCallback((frame) => {
147
+ const handleFrame = Ue.useCallback((frame) => {
148
148
  drawSkeleton(frame);
149
149
  onFrame === null || onFrame === void 0 ? void 0 : onFrame(frame);
150
150
  }, [drawSkeleton, onFrame]);
151
- const handleStart = Ve.useCallback(async () => {
151
+ const handleStart = Ue.useCallback(async () => {
152
152
  try {
153
153
  if (videoRef.current) {
154
154
  await detection.start(videoRef.current, handleFrame);
@@ -159,7 +159,7 @@ const NicePoseDetector = Ve.forwardRef(function NicePoseDetector(props, ref) {
159
159
  onError === null || onError === void 0 ? void 0 : onError(err instanceof Error ? err : new Error(String(err)));
160
160
  }
161
161
  }, [detection, handleFrame, onStart, onError]);
162
- const handleStop = Ve.useCallback(() => {
162
+ const handleStop = Ue.useCallback(() => {
163
163
  detection.stop();
164
164
  onStop === null || onStop === void 0 ? void 0 : onStop();
165
165
  }, [detection, onStop]);
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var Ve = require('react');
4
+ var Ue = require('react');
5
5
  var materialEditorTypes = require('./materialEditorTypes.js');
6
6
  var materialNodeDefinitions = require('./materialNodeDefinitions.js');
7
7
  var materialEditorUtils = require('./materialEditorUtils.js');
@@ -338,9 +338,9 @@ function materialEditorReducer(state, action) {
338
338
  Hook: useMaterialEditor
339
339
  ═══════════════════════════════════════════════════════════════════════════ */
340
340
  function useMaterialEditor(initialGraph) {
341
- const [state, dispatch] = Ve.useReducer(materialEditorReducer, initialGraph, createInitialState);
341
+ const [state, dispatch] = Ue.useReducer(materialEditorReducer, initialGraph, createInitialState);
342
342
  // Auto-compile when graph changes
343
- Ve.useEffect(() => {
343
+ Ue.useEffect(() => {
344
344
  if (state.autoCompile && !state.compiling) {
345
345
  const timeout = setTimeout(() => {
346
346
  dispatch({ type: 'COMPILE' });
@@ -356,7 +356,7 @@ function NodePalette({ searchQuery, expandedCategories, onSearch, onToggleCatego
356
356
  const filteredNodes = searchQuery
357
357
  ? materialNodeDefinitions.searchNodes(searchQuery)
358
358
  : materialNodeDefinitions.MATERIAL_NODE_DEFINITIONS;
359
- const categories = Ve.useMemo(() => {
359
+ const categories = Ue.useMemo(() => {
360
360
  const cats = new Map();
361
361
  for (const node of filteredNodes) {
362
362
  if (!cats.has(node.category)) {
@@ -369,9 +369,9 @@ function NodePalette({ searchQuery, expandedCategories, onSearch, onToggleCatego
369
369
  return (jsxRuntime.jsxs("div", { className: MaterialEditor_module.palette, children: [jsxRuntime.jsx("div", { className: MaterialEditor_module.paletteSearch, children: jsxRuntime.jsx("input", { type: "text", placeholder: "Search nodes...", value: searchQuery, onChange: e => onSearch(e.target.value), className: MaterialEditor_module.searchInput }) }), jsxRuntime.jsx("div", { className: MaterialEditor_module.paletteCategories, children: Array.from(categories.entries()).map(([category, nodes]) => (jsxRuntime.jsxs("div", { className: MaterialEditor_module.paletteCategory, children: [jsxRuntime.jsxs("button", { className: MaterialEditor_module.categoryHeader, onClick: () => onToggleCategory(category), style: { borderLeftColor: materialEditorTypes.NODE_CATEGORY_COLORS[category] }, children: [jsxRuntime.jsx("span", { className: MaterialEditor_module.categoryIcon, children: expandedCategories.includes(category) ? '▼' : '►' }), jsxRuntime.jsx("span", { children: materialEditorTypes.NODE_CATEGORY_NAMES[category] }), jsxRuntime.jsx("span", { className: MaterialEditor_module.categoryCount, children: nodes.length })] }), expandedCategories.includes(category) && (jsxRuntime.jsx("div", { className: MaterialEditor_module.categoryNodes, children: nodes.map(nodeDef => (jsxRuntime.jsxs("div", { className: MaterialEditor_module.paletteNode, draggable: true, onDragStart: e => onDragStart(nodeDef.type, e), onDoubleClick: () => onAddNode(nodeDef.type), title: nodeDef.description, children: [jsxRuntime.jsx("span", { className: MaterialEditor_module.nodeColor, style: { backgroundColor: nodeDef.color || materialEditorTypes.NODE_CATEGORY_COLORS[nodeDef.category] } }), jsxRuntime.jsx("span", { className: MaterialEditor_module.nodeName, children: nodeDef.name })] }, nodeDef.type))) }))] }, category))) })] }));
370
370
  }
371
371
  function GraphNode({ node, definition, selected, viewTransform, connections, onSelect, onMove, onStartConnection, }) {
372
- const nodeRef = Ve.useRef(null);
373
- const [isDragging, setIsDragging] = Ve.useState(false);
374
- const dragStart = Ve.useRef(null);
372
+ const nodeRef = Ue.useRef(null);
373
+ const [isDragging, setIsDragging] = Ue.useState(false);
374
+ const dragStart = Ue.useRef(null);
375
375
  const handleMouseDown = (e) => {
376
376
  if (e.button !== 0)
377
377
  return;
@@ -384,7 +384,7 @@ function GraphNode({ node, definition, selected, viewTransform, connections, onS
384
384
  dragStart.current = { x: e.clientX, y: e.clientY };
385
385
  }
386
386
  };
387
- Ve.useEffect(() => {
387
+ Ue.useEffect(() => {
388
388
  if (!isDragging)
389
389
  return;
390
390
  const handleMouseMove = (e) => {
@@ -441,10 +441,10 @@ function Toolbar({ canUndo, canRedo, canPaste, hasSelection, autoCompile, compil
441
441
  return (jsxRuntime.jsxs("div", { className: MaterialEditor_module.toolbar, children: [jsxRuntime.jsxs("div", { className: MaterialEditor_module.toolbarGroup, children: [jsxRuntime.jsx("button", { onClick: onNew, title: "New Material (Ctrl+N)", children: "\uD83D\uDCC4" }), jsxRuntime.jsx("button", { onClick: onImport, title: "Import (Ctrl+O)", children: "\uD83D\uDCC2" }), jsxRuntime.jsx("button", { onClick: onExport, title: "Export (Ctrl+S)", children: "\uD83D\uDCBE" })] }), jsxRuntime.jsx("div", { className: MaterialEditor_module.toolbarSeparator }), jsxRuntime.jsxs("div", { className: MaterialEditor_module.toolbarGroup, children: [jsxRuntime.jsx("button", { onClick: onUndo, disabled: !canUndo, title: "Undo (Ctrl+Z)", children: "\u21A9\uFE0F" }), jsxRuntime.jsx("button", { onClick: onRedo, disabled: !canRedo, title: "Redo (Ctrl+Y)", children: "\u21AA\uFE0F" })] }), jsxRuntime.jsx("div", { className: MaterialEditor_module.toolbarSeparator }), jsxRuntime.jsxs("div", { className: MaterialEditor_module.toolbarGroup, children: [jsxRuntime.jsx("button", { onClick: onCut, disabled: !hasSelection, title: "Cut (Ctrl+X)", children: "\u2702\uFE0F" }), jsxRuntime.jsx("button", { onClick: onCopy, disabled: !hasSelection, title: "Copy (Ctrl+C)", children: "\uD83D\uDCCB" }), jsxRuntime.jsx("button", { onClick: onPaste, disabled: !canPaste, title: "Paste (Ctrl+V)", children: "\uD83D\uDCE5" }), jsxRuntime.jsx("button", { onClick: onDuplicate, disabled: !hasSelection, title: "Duplicate (Ctrl+D)", children: "\uD83D\uDD04" }), jsxRuntime.jsx("button", { onClick: onDelete, disabled: !hasSelection, title: "Delete (Del)", children: "\uD83D\uDDD1\uFE0F" })] }), jsxRuntime.jsx("div", { className: MaterialEditor_module.toolbarSeparator }), jsxRuntime.jsxs("div", { className: MaterialEditor_module.toolbarGroup, children: [jsxRuntime.jsx("button", { onClick: onSelectAll, title: "Select All (Ctrl+A)", children: "\u2B1C" }), jsxRuntime.jsx("button", { onClick: onZoomToFit, title: "Zoom to Fit (F)", children: "\uD83D\uDD0D" }), jsxRuntime.jsx("button", { onClick: onToggleGrid, className: showGrid ? MaterialEditor_module.active : '', title: "Toggle Grid (G)", children: "#" }), jsxRuntime.jsx("button", { onClick: onToggleSnap, className: snapToGrid ? MaterialEditor_module.active : '', title: "Toggle Snap (S)", children: "\uD83E\uDDF2" })] }), jsxRuntime.jsx("div", { className: MaterialEditor_module.toolbarSeparator }), jsxRuntime.jsxs("div", { className: MaterialEditor_module.toolbarGroup, children: [jsxRuntime.jsx("button", { onClick: onToggleAutoCompile, className: autoCompile ? MaterialEditor_module.active : '', title: "Auto Compile", children: "\u26A1" }), jsxRuntime.jsx("button", { onClick: onCompile, disabled: compiling, title: "Compile (F5)", children: compiling ? '⏳' : '▶️' })] })] }));
442
442
  }
443
443
  function PreviewPanel({ shader, mode, compiling, onModeChange }) {
444
- const canvasRef = Ve.useRef(null);
444
+ const canvasRef = Ue.useRef(null);
445
445
  const previewModes = ['sphere', 'cube', 'plane', 'cylinder', 'torus'];
446
446
  // Simple preview rendering (in real implementation would use Three.js)
447
- Ve.useEffect(() => {
447
+ Ue.useEffect(() => {
448
448
  const canvas = canvasRef.current;
449
449
  if (!canvas)
450
450
  return;
@@ -475,25 +475,25 @@ function PreviewPanel({ shader, mode, compiling, onModeChange }) {
475
475
  ═══════════════════════════════════════════════════════════════════════════ */
476
476
  function NiceMaterialEditor({ graph: initialGraph, onGraphChange, onCompile, customNodes, textures, width = '100%', height = '600px', readOnly = false, showToolbar = true, showPalette = true, showProperties = true, showPreview = true, previewMode: initialPreviewMode = 'sphere', theme = 'dark', className, }) {
477
477
  const { state, dispatch } = useMaterialEditor(initialGraph);
478
- const canvasRef = Ve.useRef(null);
479
- const [pendingConnection, setPendingConnection] = Ve.useState(null);
478
+ const canvasRef = Ue.useRef(null);
479
+ const [pendingConnection, setPendingConnection] = Ue.useState(null);
480
480
  // Merge custom node definitions
481
- const definitions = Ve.useMemo(() => {
481
+ const definitions = Ue.useMemo(() => {
482
482
  const map = new Map(materialNodeDefinitions.MATERIAL_NODE_MAP);
483
483
  customNodes === null || customNodes === void 0 ? void 0 : customNodes.forEach(def => map.set(def.type, def));
484
484
  return map;
485
485
  }, [customNodes]);
486
486
  // Notify parent of changes
487
- Ve.useEffect(() => {
487
+ Ue.useEffect(() => {
488
488
  onGraphChange === null || onGraphChange === void 0 ? void 0 : onGraphChange(state.graph);
489
489
  }, [state.graph, onGraphChange]);
490
- Ve.useEffect(() => {
490
+ Ue.useEffect(() => {
491
491
  if (state.compiledShader) {
492
492
  onCompile === null || onCompile === void 0 ? void 0 : onCompile(state.compiledShader);
493
493
  }
494
494
  }, [state.compiledShader, onCompile]);
495
495
  // Keyboard shortcuts
496
- Ve.useEffect(() => {
496
+ Ue.useEffect(() => {
497
497
  const handleKeyDown = (e) => {
498
498
  if (readOnly)
499
499
  return;
@@ -553,7 +553,7 @@ function NiceMaterialEditor({ graph: initialGraph, onGraphChange, onCompile, cus
553
553
  return () => window.removeEventListener('keydown', handleKeyDown);
554
554
  }, [readOnly, state.selectedNodes, dispatch]);
555
555
  // Handle wheel zoom
556
- const handleWheel = Ve.useCallback((e) => {
556
+ const handleWheel = Ue.useCallback((e) => {
557
557
  var _a;
558
558
  e.preventDefault();
559
559
  const delta = e.deltaY > 0 ? 0.9 : 1.1;
@@ -571,8 +571,8 @@ function NiceMaterialEditor({ graph: initialGraph, onGraphChange, onCompile, cus
571
571
  });
572
572
  }, [state.viewTransform, dispatch]);
573
573
  // Handle canvas pan
574
- const [isPanning, setIsPanning] = Ve.useState(false);
575
- const panStart = Ve.useRef(null);
574
+ const [isPanning, setIsPanning] = Ue.useState(false);
575
+ const panStart = Ue.useRef(null);
576
576
  const handleCanvasMouseDown = (e) => {
577
577
  if (e.button === 1 || (e.button === 0 && e.altKey)) {
578
578
  setIsPanning(true);
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var Ve = require('react');
4
+ var Ue = require('react');
5
5
  var ModelEditor_module = require('./ModelEditor.module.css.js');
6
6
  var index = require('../ui/dist/index.js');
7
7
 
8
- const ModelEditorLeftPanel = Ve.memo(({ api }) => {
8
+ const ModelEditorLeftPanel = Ue.memo(({ api }) => {
9
9
  const { sceneTree, selectedId, outlinerSearch, setOutlinerSearch, selectObject, rebuildTree, toggleNodeExpanded, toggleNodeVisibility, } = api;
10
10
  const renderTreeNode = (node, depth) => {
11
11
  // Outliner search filter
@@ -24,7 +24,7 @@ const ModelEditorLeftPanel = Ve.memo(({ api }) => {
24
24
  node.type === "light" ? "💡" :
25
25
  node.type === "camera" ? "📷" :
26
26
  node.type === "helper" ? "◇" : "📁";
27
- return (jsxRuntime.jsxs(Ve.Fragment, { children: [jsxRuntime.jsxs("div", { className: `${ModelEditor_module.treeItem} ${selectedId === node.id ? ModelEditor_module.treeItemActive : ""}`, style: { paddingLeft: depth * 16 + 4 }, onClick: () => selectObject(node), children: [hasChildren ? (jsxRuntime.jsx("span", { className: ModelEditor_module.treeToggle, onClick: (e) => {
27
+ return (jsxRuntime.jsxs(Ue.Fragment, { children: [jsxRuntime.jsxs("div", { className: `${ModelEditor_module.treeItem} ${selectedId === node.id ? ModelEditor_module.treeItemActive : ""}`, style: { paddingLeft: depth * 16 + 4 }, onClick: () => selectObject(node), children: [hasChildren ? (jsxRuntime.jsx("span", { className: ModelEditor_module.treeToggle, onClick: (e) => {
28
28
  e.stopPropagation();
29
29
  toggleNodeExpanded(node);
30
30
  }, children: node.expanded ? "▼" : "▶" })) : (jsxRuntime.jsx("span", { className: ModelEditor_module.treeToggle })), jsxRuntime.jsx("span", { className: ModelEditor_module.treeIcon, children: icon }), jsxRuntime.jsx("span", { style: { flex: 1, overflow: "hidden", textOverflow: "ellipsis" }, children: node.name }), jsxRuntime.jsx("span", { className: ModelEditor_module.treeVisibility, onClick: (e) => {
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var Ve = require('react');
4
+ var Ue = require('react');
5
5
  var ModelEditor_module = require('./ModelEditor.module.css.js');
6
6
  var index = require('../ui/dist/index.js');
7
7
 
8
- const ModelEditorMenuBar = Ve.memo(({ api, hasOnSaveToLibrary }) => {
8
+ const ModelEditorMenuBar = Ue.memo(({ api, hasOnSaveToLibrary }) => {
9
9
  const { editorMode, setEditorMode, fileInputRef, mergeInputRef, addMenuOpen, setAddMenuOpen, addPrimitive, addSceneLight, addCameraObject, addEmpty, selectedNode, duplicateSelected, deleteSelected, exportGLTF, exportOBJ, exportSTL, exportPLY, exportUSDZ, saveToLibrary, clearScene, showGrid, setShowGrid, showAxes, setShowAxes, wireframe, setWireframe, showSkeleton, setShowSkeleton, showLightHelpers, setShowLightHelpers, bgColor, setBgColor, } = api;
10
10
  return (jsxRuntime.jsxs("div", { className: ModelEditor_module.menuBar, children: [jsxRuntime.jsx(index.NiceSelect, { className: ModelEditor_module.modeSelect, value: editorMode, onChange: (val) => setEditorMode(val), options: [
11
11
  { value: "object", label: "Object Mode" },
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var Ve = require('react');
4
+ var Ue = require('react');
5
5
  var THREE = require('three');
6
6
  var ModelEditor_module = require('./ModelEditor.module.css.js');
7
7
  var modelEditorTypes = require('./modelEditorTypes.js');
@@ -27,7 +27,7 @@ function _interopNamespaceDefault(e) {
27
27
 
28
28
  var THREE__namespace = /*#__PURE__*/_interopNamespaceDefault(THREE);
29
29
 
30
- const ModelEditorRightPanel = Ve.memo(({ api }) => {
30
+ const ModelEditorRightPanel = Ue.memo(({ api }) => {
31
31
  const { propTab, setPropTab, selectedNode, selectedMaterials, selMaterialIdx, setSelMaterialIdx, setMatRefresh, rebuildTree, aiBusy, aiStatus, rootObjectRef, videoInputRef, bgColor, setBgColor, fogEnabled, setFogEnabled, fogColor, setFogColor, fogNear, setFogNear, fogFar, setFogFar, showLightHelpers, setShowLightHelpers, showGrid, setShowGrid, showAxes, setShowAxes, showSkeleton, setShowSkeleton, snapEnabled, setSnapEnabled, snapGrid, setSnapGrid, setStatusText, } = api;
32
32
  return (jsxRuntime.jsxs("div", { className: ModelEditor_module.rightPanel, children: [jsxRuntime.jsx("div", { className: ModelEditor_module.propTabs, children: ["object", "material", "world", "modifiers", "physics"].map((t) => (jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.propTabBtn, variant: propTab === t ? "primary" : "ghost", size: "sm", onClick: () => setPropTab(t), title: t.charAt(0).toUpperCase() + t.slice(1), children: t === "object" ? "🔧" : t === "material" ? "🎨" : t === "world" ? "🌍" : t === "modifiers" ? "🔩" : "⚡" }, t))) }), propTab === "object" && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsx("div", { className: ModelEditor_module.panelTitle, children: "\uD83D\uDD27 Transform" }), jsxRuntime.jsx("div", { className: ModelEditor_module.panelContent, children: selectedNode ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: "Name" }), jsxRuntime.jsx(index.NiceTextInput, { className: ModelEditor_module.propInput, value: selectedNode.name, onChange: (val) => {
33
33
  selectedNode.object.name = val;
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var Ve = require('react');
4
+ var Ue = require('react');
5
5
  var THREE = require('three');
6
6
  var ModelEditor_module = require('./ModelEditor.module.css.js');
7
7
  var modelEditorTypes = require('./modelEditorTypes.js');
@@ -31,7 +31,7 @@ var THREE__namespace = /*#__PURE__*/_interopNamespaceDefault(THREE);
31
31
  ═══════════════════════════════════════════ */
32
32
  /** Vec3 input row for position/scale */
33
33
  const Vec3Row = ({ label, value, onChange }) => {
34
- const [, forceUpdate] = Ve.useState(0);
34
+ const [, forceUpdate] = Ue.useState(0);
35
35
  const set = (axis, v) => {
36
36
  const n = parseFloat(v);
37
37
  if (!isNaN(n)) {
@@ -44,7 +44,7 @@ const Vec3Row = ({ label, value, onChange }) => {
44
44
  };
45
45
  /** Vec3 input row for rotation (shows degrees) */
46
46
  const Vec3RowDeg = ({ label, value, onChange }) => {
47
- const [, forceUpdate] = Ve.useState(0);
47
+ const [, forceUpdate] = Ue.useState(0);
48
48
  const set = (axis, v) => {
49
49
  const n = parseFloat(v);
50
50
  if (!isNaN(n)) {
@@ -1,17 +1,17 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var Ve = require('react');
4
+ var Ue = require('react');
5
5
  var ModelEditor_module = require('./ModelEditor.module.css.js');
6
6
  var modelEditorTypes = require('./modelEditorTypes.js');
7
7
  var index = require('../ui/dist/index.js');
8
8
 
9
- const ModelEditorTimeline = Ve.memo(({ api }) => {
9
+ const ModelEditorTimeline = Ue.memo(({ api }) => {
10
10
  const { bottomCollapsed, setBottomCollapsed, animations, activeAnimIdx, isPlaying, animTime, animDuration, animSpeed, setAnimSpeed, loopAnim, setLoopAnim, seekAnim, togglePlay, stopAnim, playClip, mergeInputRef, } = api;
11
11
  return (jsxRuntime.jsxs("div", { className: `${ModelEditor_module.bottomPanel} ${bottomCollapsed ? ModelEditor_module.bottomPanelCollapsed : ""}`, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.bottomPanelHeader, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.bottomToggle, onClick: () => setBottomCollapsed((c) => !c), children: bottomCollapsed ? "▶" : "▼" }), jsxRuntime.jsxs("span", { className: ModelEditor_module.bottomPanelTitle, onClick: () => setBottomCollapsed((c) => !c), children: ["Animation (", animations.length, " clip", animations.length !== 1 ? "s" : "", ")"] }), jsxRuntime.jsx("div", { className: ModelEditor_module.menuSep }), jsxRuntime.jsxs("div", { className: ModelEditor_module.transportBar, children: [jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.transportBtn, variant: "ghost", size: "sm", onClick: () => seekAnim(0), title: "Go to start", children: "\u23EE" }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.transportBtn, variant: isPlaying ? "primary" : "ghost", size: "sm", onClick: togglePlay, title: "Play/Pause (Space)", children: isPlaying ? "⏸" : "▶" }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.transportBtn, variant: "ghost", size: "sm", onClick: stopAnim, title: "Stop", children: "\u23F9" }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.transportBtn, variant: loopAnim ? "primary" : "ghost", size: "sm", onClick: () => setLoopAnim((v) => !v), title: "Loop", children: "\uD83D\uDD01" })] }), jsxRuntime.jsxs("span", { className: ModelEditor_module.transportTime, children: [modelEditorTypes.fmtTime(animTime), " / ", modelEditorTypes.fmtTime(animDuration)] }), jsxRuntime.jsx("div", { className: ModelEditor_module.menuSep }), jsxRuntime.jsx("label", { className: ModelEditor_module.menuLabel, children: "Speed" }), jsxRuntime.jsx(index.NiceSlider, { min: 0.1, max: 3, step: 0.1, value: animSpeed, onChange: (val) => setAnimSpeed(val), style: { width: 60 } }), jsxRuntime.jsxs("span", { className: ModelEditor_module.menuLabel, children: [animSpeed.toFixed(1), "\u00D7"] })] }), !bottomCollapsed && (jsxRuntime.jsxs("div", { className: ModelEditor_module.animListArea, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.animList, children: [animations.length === 0 && (jsxRuntime.jsx("div", { style: { color: "#666", fontSize: 10, padding: 8 }, children: "No animations loaded" })), animations.map((anim, i) => (jsxRuntime.jsxs("div", { className: `${ModelEditor_module.animItem} ${i === activeAnimIdx ? ModelEditor_module.animItemActive : ""}`, onClick: () => playClip(i), children: [jsxRuntime.jsx("span", { children: anim.name }), jsxRuntime.jsxs("span", { className: ModelEditor_module.animDuration, children: [anim.duration.toFixed(1), "s"] })] }, `${anim.name}-${i}`))), jsxRuntime.jsx("div", { style: { padding: "4px 8px" }, children: jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.btnSecondary, variant: "ghost", size: "sm", style: { width: "100%", fontSize: 10 }, onClick: () => { var _a; return (_a = mergeInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, children: "+ Add Animation File" }) })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.timelineArea, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.timelineRuler, children: [animDuration > 0 &&
12
12
  Array.from({ length: Math.ceil(animDuration) + 1 }, (_, i) => {
13
13
  const pct = (i / animDuration) * 100;
14
- return (jsxRuntime.jsxs(Ve.Fragment, { children: [jsxRuntime.jsx("div", { className: ModelEditor_module.rulerTick, style: { left: `${pct}%` } }), jsxRuntime.jsxs("span", { className: ModelEditor_module.rulerLabel, style: { left: `${pct}%` }, children: [i, "s"] })] }, i));
14
+ return (jsxRuntime.jsxs(Ue.Fragment, { children: [jsxRuntime.jsx("div", { className: ModelEditor_module.rulerTick, style: { left: `${pct}%` } }), jsxRuntime.jsxs("span", { className: ModelEditor_module.rulerLabel, style: { left: `${pct}%` }, children: [i, "s"] })] }, i));
15
15
  }), animDuration > 0 && (jsxRuntime.jsx("div", { className: ModelEditor_module.playhead, style: {
16
16
  left: `${(animTime / animDuration) * 100}%`,
17
17
  height: "100%",
@@ -1,11 +1,11 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var Ve = require('react');
4
+ var Ue = require('react');
5
5
  var ModelEditor_module = require('./ModelEditor.module.css.js');
6
6
  var index = require('../ui/dist/index.js');
7
7
 
8
- const ModelEditorToolbar = Ve.memo(({ api }) => {
8
+ const ModelEditorToolbar = Ue.memo(({ api }) => {
9
9
  const { transformMode, setTransformMode, snapEnabled, setSnapEnabled, gizmoSpace, setGizmoSpace, rootObjectRef, focusOnObject, setCameraPreset, deleteSelected, duplicateSelected, selectedNode, } = api;
10
10
  return (jsxRuntime.jsxs("div", { className: ModelEditor_module.toolbar, children: [jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.toolBtn, variant: transformMode === "translate" ? "primary" : "ghost", size: "sm", onClick: () => setTransformMode("translate"), title: "Translate (G)", children: "\u2725" }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.toolBtn, variant: transformMode === "rotate" ? "primary" : "ghost", size: "sm", onClick: () => setTransformMode("rotate"), title: "Rotate (R)", children: "\u21BB" }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.toolBtn, variant: transformMode === "scale" ? "primary" : "ghost", size: "sm", onClick: () => setTransformMode("scale"), title: "Scale (S)", children: "\u2B21" }), jsxRuntime.jsx("div", { className: ModelEditor_module.toolSep }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.toolBtn, variant: snapEnabled ? "primary" : "ghost", size: "sm", onClick: () => setSnapEnabled((v) => !v), title: `Snap to Grid (${snapEnabled ? "ON" : "OFF"})`, children: "\uD83E\uDDF2" }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: () => setGizmoSpace((s) => (s === "local" ? "world" : "local")), title: `Orientation: ${gizmoSpace}`, children: gizmoSpace === "local" ? "🔶" : "🌐" }), jsxRuntime.jsx("div", { className: ModelEditor_module.toolSep }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: () => rootObjectRef.current && focusOnObject(rootObjectRef.current), title: "Focus (F)", children: "\u25CE" }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: () => setCameraPreset("front"), title: "Front view (Numpad 1)", children: "1" }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: () => setCameraPreset("right"), title: "Right view (Numpad 3)", children: "3" }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: () => setCameraPreset("top"), title: "Top view (Numpad 7)", children: "7" }), jsxRuntime.jsx("div", { className: ModelEditor_module.toolSep }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: deleteSelected, title: "Delete selected (Del)", children: "\uD83D\uDDD1" }), jsxRuntime.jsx(index.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: duplicateSelected, title: "Duplicate (Shift+D)", disabled: !selectedNode, children: "\uD83D\uDCCB" })] }));
11
11
  });
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var Ve = require('react');
4
+ var Ue = require('react');
5
5
  var ModelEditor_module = require('./ModelEditor.module.css.js');
6
6
 
7
- const ModelEditorViewport = Ve.memo(({ api }) => {
7
+ const ModelEditorViewport = Ue.memo(({ api }) => {
8
8
  const { mountRef, dragOver, handleDragOver, handleDragLeave, handleDrop, handleViewportClick, handleContextMenu, editorMode, polyCount, meshCount, boneCount, shadingMode, setShadingMode, gizmoSpace, setGizmoSpace, contextMenu, closeContextMenu, addPrimitive, addSceneLight, duplicateSelected, deleteSelected, selectedNode, rootObjectRef, focusOnObject, snapEnabled, setSnapEnabled, } = api;
9
9
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { ref: mountRef, className: `${ModelEditor_module.viewportContainer} ${dragOver ? ModelEditor_module.dragOver : ""}`, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: handleViewportClick, onContextMenu: handleContextMenu, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.viewportOverlay, children: [jsxRuntime.jsxs("span", { className: ModelEditor_module.viewportBadge, children: [editorMode.toUpperCase(), " MODE"] }), jsxRuntime.jsxs("span", { className: ModelEditor_module.viewportBadge, children: [polyCount.toLocaleString(), " tris \u00B7 ", meshCount, " meshes \u00B7 ", boneCount, " bones"] })] }), jsxRuntime.jsx("div", { className: ModelEditor_module.viewportShadingBar, children: ["wireframe", "solid", "material", "rendered"].map((m) => (jsxRuntime.jsx("button", { className: `${ModelEditor_module.shadingBtn} ${shadingMode === m ? ModelEditor_module.shadingBtnActive : ""}`, onClick: (e) => { e.stopPropagation(); setShadingMode(m); }, title: m.charAt(0).toUpperCase() + m.slice(1), children: m === "wireframe" ? "◇" : m === "solid" ? "◆" : m === "material" ? "🎨" : "☀" }, m))) }), jsxRuntime.jsx("div", { className: ModelEditor_module.viewportGizmoInfo, children: jsxRuntime.jsx("button", { className: ModelEditor_module.shadingBtn, onClick: (e) => {
10
10
  e.stopPropagation();
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var Ve = require('react');
4
+ var Ue = require('react');
5
5
  var ModelViewer_module = require('./ModelViewer.module.css.js');
6
6
  var useModelViewer = require('./useModelViewer.js');
7
7
  var index = require('../ui/dist/index.js');
@@ -14,19 +14,19 @@ const NAV_LABELS = {
14
14
  };
15
15
  const NiceModelViewer = ({ className, showToolbar = true, showStatusBar = true, showInfoPanel = true, toolbarExtra, onFileDrop, children, ...viewerProps }) => {
16
16
  const api = useModelViewer.useModelViewer(viewerProps);
17
- const [panelOpen, setPanelOpen] = Ve.useState(false);
18
- const [dragOver, setDragOver] = Ve.useState(false);
19
- const fileInputRef = Ve.useRef(null);
17
+ const [panelOpen, setPanelOpen] = Ue.useState(false);
18
+ const [dragOver, setDragOver] = Ue.useState(false);
19
+ const fileInputRef = Ue.useRef(null);
20
20
  /* ── drag & drop ── */
21
- const handleDragOver = Ve.useCallback((e) => {
21
+ const handleDragOver = Ue.useCallback((e) => {
22
22
  e.preventDefault();
23
23
  setDragOver(true);
24
24
  }, []);
25
- const handleDragLeave = Ve.useCallback((e) => {
25
+ const handleDragLeave = Ue.useCallback((e) => {
26
26
  e.preventDefault();
27
27
  setDragOver(false);
28
28
  }, []);
29
- const handleDrop = Ve.useCallback((e) => {
29
+ const handleDrop = Ue.useCallback((e) => {
30
30
  var _a;
31
31
  e.preventDefault();
32
32
  setDragOver(false);
@@ -38,7 +38,7 @@ const NiceModelViewer = ({ className, showToolbar = true, showStatusBar = true,
38
38
  }, [api, onFileDrop]);
39
39
  /* ── nav cycle ── */
40
40
  const navModes = ['orbit', 'fps', 'fly', 'walkthrough'];
41
- const cycleNav = Ve.useCallback(() => {
41
+ const cycleNav = Ue.useCallback(() => {
42
42
  const idx = navModes.indexOf(api.navigationMode);
43
43
  api.setNavigationMode(navModes[(idx + 1) % navModes.length]);
44
44
  }, [api]);