@almadar/ui 2.17.0 → 2.19.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.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var React8 = require('react');
3
+ var React7 = require('react');
4
4
  var fiber = require('@react-three/fiber');
5
5
  var THREE6 = require('three');
6
6
  var jsxRuntime = require('react/jsx-runtime');
@@ -9,6 +9,7 @@ var GLTFLoader = require('three/examples/jsm/loaders/GLTFLoader');
9
9
  var OrbitControls_js = require('three/examples/jsm/controls/OrbitControls.js');
10
10
  var GLTFLoader_js = require('three/examples/jsm/loaders/GLTFLoader.js');
11
11
  var OBJLoader_js = require('three/examples/jsm/loaders/OBJLoader.js');
12
+ var providers = require('@almadar/ui/providers');
12
13
  var clsx = require('clsx');
13
14
  var tailwindMerge = require('tailwind-merge');
14
15
 
@@ -32,7 +33,7 @@ function _interopNamespace(e) {
32
33
  return Object.freeze(n);
33
34
  }
34
35
 
35
- var React8__default = /*#__PURE__*/_interopDefault(React8);
36
+ var React7__default = /*#__PURE__*/_interopDefault(React7);
36
37
  var THREE6__namespace = /*#__PURE__*/_interopNamespace(THREE6);
37
38
 
38
39
  var __defProp = Object.defineProperty;
@@ -40,8 +41,8 @@ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { en
40
41
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
41
42
  function Scene3D({ background = "#1a1a2e", fog, children }) {
42
43
  const { scene } = fiber.useThree();
43
- const initializedRef = React8.useRef(false);
44
- React8.useEffect(() => {
44
+ const initializedRef = React7.useRef(false);
45
+ React7.useEffect(() => {
45
46
  if (initializedRef.current) return;
46
47
  initializedRef.current = true;
47
48
  if (background.startsWith("#") || background.startsWith("rgb")) {
@@ -62,7 +63,7 @@ function Scene3D({ background = "#1a1a2e", fog, children }) {
62
63
  }, [scene, background, fog]);
63
64
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
64
65
  }
65
- var Camera3D = React8.forwardRef(
66
+ var Camera3D = React7.forwardRef(
66
67
  ({
67
68
  mode = "isometric",
68
69
  position = [10, 10, 10],
@@ -75,10 +76,10 @@ var Camera3D = React8.forwardRef(
75
76
  onChange
76
77
  }, ref) => {
77
78
  const { camera, set, viewport } = fiber.useThree();
78
- const controlsRef = React8.useRef(null);
79
- const initialPosition = React8.useRef(new THREE6__namespace.Vector3(...position));
80
- const initialTarget = React8.useRef(new THREE6__namespace.Vector3(...target));
81
- React8.useEffect(() => {
79
+ const controlsRef = React7.useRef(null);
80
+ const initialPosition = React7.useRef(new THREE6__namespace.Vector3(...position));
81
+ const initialTarget = React7.useRef(new THREE6__namespace.Vector3(...target));
82
+ React7.useEffect(() => {
82
83
  let newCamera;
83
84
  if (mode === "isometric") {
84
85
  const aspect = viewport.aspect;
@@ -109,7 +110,7 @@ var Camera3D = React8.forwardRef(
109
110
  onChange(camera);
110
111
  }
111
112
  });
112
- React8.useImperativeHandle(ref, () => ({
113
+ React7.useImperativeHandle(ref, () => ({
113
114
  getCamera: () => camera,
114
115
  setPosition: (x, y, z) => {
115
116
  camera.position.set(x, y, z);
@@ -250,7 +251,7 @@ function Canvas3DLoadingState({
250
251
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "canvas-3d-loading__background", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg__grid" }) })
251
252
  ] });
252
253
  }
253
- var Canvas3DErrorBoundary = class extends React8.Component {
254
+ var Canvas3DErrorBoundary = class extends React7.Component {
254
255
  constructor(props) {
255
256
  super(props);
256
257
  __publicField(this, "handleReset", () => {
@@ -329,12 +330,12 @@ function detectAssetRoot(modelUrl) {
329
330
  return modelUrl.substring(0, modelUrl.lastIndexOf("/") + 1);
330
331
  }
331
332
  function useGLTFModel(url, resourceBasePath) {
332
- const [state, setState] = React8.useState({
333
+ const [state, setState] = React7.useState({
333
334
  model: null,
334
335
  isLoading: false,
335
336
  error: null
336
337
  });
337
- React8.useEffect(() => {
338
+ React7.useEffect(() => {
338
339
  if (!url) {
339
340
  setState({ model: null, isLoading: false, error: null });
340
341
  return;
@@ -383,7 +384,7 @@ function ModelLoader({
383
384
  resourceBasePath
384
385
  }) {
385
386
  const { model: loadedModel, isLoading, error } = useGLTFModel(url, resourceBasePath);
386
- const model = React8.useMemo(() => {
387
+ const model = React7.useMemo(() => {
387
388
  if (!loadedModel) return null;
388
389
  const cloned = loadedModel.clone();
389
390
  cloned.traverse((child) => {
@@ -394,13 +395,13 @@ function ModelLoader({
394
395
  });
395
396
  return cloned;
396
397
  }, [loadedModel, castShadow, receiveShadow]);
397
- const scaleArray = React8.useMemo(() => {
398
+ const scaleArray = React7.useMemo(() => {
398
399
  if (typeof scale === "number") {
399
400
  return [scale, scale, scale];
400
401
  }
401
402
  return scale;
402
403
  }, [scale]);
403
- const rotationRad = React8.useMemo(() => {
404
+ const rotationRad = React7.useMemo(() => {
404
405
  return [
405
406
  rotation[0] * Math.PI / 180,
406
407
  rotation[1] * Math.PI / 180,
@@ -486,8 +487,8 @@ function PhysicsObject3D({
486
487
  onGroundHit,
487
488
  onCollision
488
489
  }) {
489
- const groupRef = React8.useRef(null);
490
- const physicsStateRef = React8.useRef({
490
+ const groupRef = React7.useRef(null);
491
+ const physicsStateRef = React7.useRef({
491
492
  id: entityId,
492
493
  x: initialPosition[0],
493
494
  y: initialPosition[1],
@@ -504,8 +505,8 @@ function PhysicsObject3D({
504
505
  mass,
505
506
  state: "Active"
506
507
  });
507
- const groundHitRef = React8.useRef(false);
508
- React8.useEffect(() => {
508
+ const groundHitRef = React7.useRef(false);
509
+ React7.useEffect(() => {
509
510
  if (groupRef.current) {
510
511
  groupRef.current.position.set(
511
512
  initialPosition[0],
@@ -786,21 +787,21 @@ var DEFAULT_OPTIONS = {
786
787
  };
787
788
  function useThree3(options = {}) {
788
789
  const opts = { ...DEFAULT_OPTIONS, ...options };
789
- const containerRef = React8.useRef(null);
790
- const canvasRef = React8.useRef(null);
791
- const rendererRef = React8.useRef(null);
792
- const sceneRef = React8.useRef(null);
793
- const cameraRef = React8.useRef(null);
794
- const controlsRef = React8.useRef(null);
795
- const gridHelperRef = React8.useRef(null);
796
- const rafRef = React8.useRef(0);
797
- const [isReady, setIsReady] = React8.useState(false);
798
- const [dimensions, setDimensions] = React8.useState({ width: 0, height: 0 });
799
- const initialCameraPosition = React8.useMemo(
790
+ const containerRef = React7.useRef(null);
791
+ const canvasRef = React7.useRef(null);
792
+ const rendererRef = React7.useRef(null);
793
+ const sceneRef = React7.useRef(null);
794
+ const cameraRef = React7.useRef(null);
795
+ const controlsRef = React7.useRef(null);
796
+ const gridHelperRef = React7.useRef(null);
797
+ const rafRef = React7.useRef(0);
798
+ const [isReady, setIsReady] = React7.useState(false);
799
+ const [dimensions, setDimensions] = React7.useState({ width: 0, height: 0 });
800
+ const initialCameraPosition = React7.useMemo(
800
801
  () => new THREE6__namespace.Vector3(...opts.cameraPosition),
801
802
  []
802
803
  );
803
- React8.useEffect(() => {
804
+ React7.useEffect(() => {
804
805
  if (!containerRef.current) return;
805
806
  const container = containerRef.current;
806
807
  const { clientWidth, clientHeight } = container;
@@ -893,7 +894,7 @@ function useThree3(options = {}) {
893
894
  scene.clear();
894
895
  };
895
896
  }, []);
896
- React8.useEffect(() => {
897
+ React7.useEffect(() => {
897
898
  if (!cameraRef.current || !containerRef.current) return;
898
899
  const container = containerRef.current;
899
900
  const { clientWidth, clientHeight } = container;
@@ -928,20 +929,20 @@ function useThree3(options = {}) {
928
929
  animate();
929
930
  }
930
931
  }, [opts.cameraMode]);
931
- const setCameraPosition = React8.useCallback((x, y, z) => {
932
+ const setCameraPosition = React7.useCallback((x, y, z) => {
932
933
  if (cameraRef.current) {
933
934
  cameraRef.current.position.set(x, y, z);
934
935
  controlsRef.current?.update();
935
936
  }
936
937
  }, []);
937
- const lookAt = React8.useCallback((x, y, z) => {
938
+ const lookAt = React7.useCallback((x, y, z) => {
938
939
  if (cameraRef.current) {
939
940
  cameraRef.current.lookAt(x, y, z);
940
941
  controlsRef.current?.target.set(x, y, z);
941
942
  controlsRef.current?.update();
942
943
  }
943
944
  }, []);
944
- const resetCamera = React8.useCallback(() => {
945
+ const resetCamera = React7.useCallback(() => {
945
946
  if (cameraRef.current) {
946
947
  cameraRef.current.position.copy(initialCameraPosition);
947
948
  cameraRef.current.lookAt(0, 0, 0);
@@ -951,7 +952,7 @@ function useThree3(options = {}) {
951
952
  }
952
953
  }
953
954
  }, [initialCameraPosition]);
954
- const fitView = React8.useCallback(
955
+ const fitView = React7.useCallback(
955
956
  (bounds) => {
956
957
  if (!cameraRef.current) return;
957
958
  const centerX = (bounds.minX + bounds.maxX) / 2;
@@ -982,20 +983,20 @@ function useThree3(options = {}) {
982
983
  }
983
984
  function useAssetLoader(options = {}) {
984
985
  const { preloadUrls = [], loader: customLoader } = options;
985
- const loaderRef = React8.useRef(customLoader || new AssetLoader());
986
- const [state, setState] = React8.useState({
986
+ const loaderRef = React7.useRef(customLoader || new AssetLoader());
987
+ const [state, setState] = React7.useState({
987
988
  isLoading: false,
988
989
  progress: 0,
989
990
  loaded: 0,
990
991
  total: 0,
991
992
  errors: []
992
993
  });
993
- React8.useEffect(() => {
994
+ React7.useEffect(() => {
994
995
  if (preloadUrls.length > 0) {
995
996
  preload(preloadUrls);
996
997
  }
997
998
  }, []);
998
- const updateProgress = React8.useCallback((loaded, total) => {
999
+ const updateProgress = React7.useCallback((loaded, total) => {
999
1000
  setState((prev) => ({
1000
1001
  ...prev,
1001
1002
  loaded,
@@ -1003,7 +1004,7 @@ function useAssetLoader(options = {}) {
1003
1004
  progress: total > 0 ? Math.round(loaded / total * 100) : 0
1004
1005
  }));
1005
1006
  }, []);
1006
- const loadModel = React8.useCallback(
1007
+ const loadModel = React7.useCallback(
1007
1008
  async (url) => {
1008
1009
  setState((prev) => ({ ...prev, isLoading: true }));
1009
1010
  try {
@@ -1026,7 +1027,7 @@ function useAssetLoader(options = {}) {
1026
1027
  },
1027
1028
  []
1028
1029
  );
1029
- const loadOBJ = React8.useCallback(
1030
+ const loadOBJ = React7.useCallback(
1030
1031
  async (url) => {
1031
1032
  setState((prev) => ({ ...prev, isLoading: true }));
1032
1033
  try {
@@ -1049,7 +1050,7 @@ function useAssetLoader(options = {}) {
1049
1050
  },
1050
1051
  []
1051
1052
  );
1052
- const loadTexture = React8.useCallback(
1053
+ const loadTexture = React7.useCallback(
1053
1054
  async (url) => {
1054
1055
  setState((prev) => ({ ...prev, isLoading: true }));
1055
1056
  try {
@@ -1072,7 +1073,7 @@ function useAssetLoader(options = {}) {
1072
1073
  },
1073
1074
  []
1074
1075
  );
1075
- const preload = React8.useCallback(
1076
+ const preload = React7.useCallback(
1076
1077
  async (urls) => {
1077
1078
  setState((prev) => ({
1078
1079
  ...prev,
@@ -1111,27 +1112,27 @@ function useAssetLoader(options = {}) {
1111
1112
  },
1112
1113
  [updateProgress]
1113
1114
  );
1114
- const hasModel = React8.useCallback((url) => {
1115
+ const hasModel = React7.useCallback((url) => {
1115
1116
  return loaderRef.current.hasModel(url);
1116
1117
  }, []);
1117
- const hasTexture = React8.useCallback((url) => {
1118
+ const hasTexture = React7.useCallback((url) => {
1118
1119
  return loaderRef.current.hasTexture(url);
1119
1120
  }, []);
1120
- const getModel = React8.useCallback((url) => {
1121
+ const getModel = React7.useCallback((url) => {
1121
1122
  try {
1122
1123
  return loaderRef.current.getModel(url);
1123
1124
  } catch {
1124
1125
  return void 0;
1125
1126
  }
1126
1127
  }, []);
1127
- const getTexture = React8.useCallback((url) => {
1128
+ const getTexture = React7.useCallback((url) => {
1128
1129
  try {
1129
1130
  return loaderRef.current.getTexture(url);
1130
1131
  } catch {
1131
1132
  return void 0;
1132
1133
  }
1133
1134
  }, []);
1134
- const clearCache = React8.useCallback(() => {
1135
+ const clearCache = React7.useCallback(() => {
1135
1136
  loaderRef.current.clearCache();
1136
1137
  setState({
1137
1138
  isLoading: false,
@@ -1155,25 +1156,25 @@ function useAssetLoader(options = {}) {
1155
1156
  };
1156
1157
  }
1157
1158
  function useSceneGraph() {
1158
- const nodesRef = React8.useRef(/* @__PURE__ */ new Map());
1159
- const addNode = React8.useCallback((node) => {
1159
+ const nodesRef = React7.useRef(/* @__PURE__ */ new Map());
1160
+ const addNode = React7.useCallback((node) => {
1160
1161
  const existing = nodesRef.current.get(node.id);
1161
1162
  if (existing) {
1162
1163
  existing.mesh.removeFromParent();
1163
1164
  }
1164
1165
  nodesRef.current.set(node.id, node);
1165
1166
  }, []);
1166
- const removeNode = React8.useCallback((id) => {
1167
+ const removeNode = React7.useCallback((id) => {
1167
1168
  const node = nodesRef.current.get(id);
1168
1169
  if (node) {
1169
1170
  node.mesh.removeFromParent();
1170
1171
  nodesRef.current.delete(id);
1171
1172
  }
1172
1173
  }, []);
1173
- const getNode = React8.useCallback((id) => {
1174
+ const getNode = React7.useCallback((id) => {
1174
1175
  return nodesRef.current.get(id);
1175
1176
  }, []);
1176
- const updateNodePosition = React8.useCallback(
1177
+ const updateNodePosition = React7.useCallback(
1177
1178
  (id, x, y, z) => {
1178
1179
  const node = nodesRef.current.get(id);
1179
1180
  if (node) {
@@ -1183,7 +1184,7 @@ function useSceneGraph() {
1183
1184
  },
1184
1185
  []
1185
1186
  );
1186
- const updateNodeGridPosition = React8.useCallback(
1187
+ const updateNodeGridPosition = React7.useCallback(
1187
1188
  (id, gridX, gridZ) => {
1188
1189
  const node = nodesRef.current.get(id);
1189
1190
  if (node) {
@@ -1192,7 +1193,7 @@ function useSceneGraph() {
1192
1193
  },
1193
1194
  []
1194
1195
  );
1195
- const getNodeAtGrid = React8.useCallback(
1196
+ const getNodeAtGrid = React7.useCallback(
1196
1197
  (x, z, type) => {
1197
1198
  return Array.from(nodesRef.current.values()).find((node) => {
1198
1199
  const matchesGrid = node.gridPosition.x === x && node.gridPosition.z === z;
@@ -1201,10 +1202,10 @@ function useSceneGraph() {
1201
1202
  },
1202
1203
  []
1203
1204
  );
1204
- const getNodesByType = React8.useCallback((type) => {
1205
+ const getNodesByType = React7.useCallback((type) => {
1205
1206
  return Array.from(nodesRef.current.values()).filter((node) => node.type === type);
1206
1207
  }, []);
1207
- const getNodesInBounds = React8.useCallback(
1208
+ const getNodesInBounds = React7.useCallback(
1208
1209
  (minX, maxX, minZ, maxZ) => {
1209
1210
  return Array.from(nodesRef.current.values()).filter((node) => {
1210
1211
  const { x, z } = node.gridPosition;
@@ -1213,13 +1214,13 @@ function useSceneGraph() {
1213
1214
  },
1214
1215
  []
1215
1216
  );
1216
- const clearNodes = React8.useCallback(() => {
1217
+ const clearNodes = React7.useCallback(() => {
1217
1218
  nodesRef.current.forEach((node) => {
1218
1219
  node.mesh.removeFromParent();
1219
1220
  });
1220
1221
  nodesRef.current.clear();
1221
1222
  }, []);
1222
- const countNodes = React8.useCallback((type) => {
1223
+ const countNodes = React7.useCallback((type) => {
1223
1224
  if (!type) {
1224
1225
  return nodesRef.current.size;
1225
1226
  }
@@ -1241,9 +1242,9 @@ function useSceneGraph() {
1241
1242
  }
1242
1243
  function useRaycaster(options) {
1243
1244
  const { camera, canvas, cellSize = 1, offsetX = 0, offsetZ = 0 } = options;
1244
- const raycaster = React8.useRef(new THREE6__namespace.Raycaster());
1245
- const mouse = React8.useRef(new THREE6__namespace.Vector2());
1246
- const clientToNDC = React8.useCallback(
1245
+ const raycaster = React7.useRef(new THREE6__namespace.Raycaster());
1246
+ const mouse = React7.useRef(new THREE6__namespace.Vector2());
1247
+ const clientToNDC = React7.useCallback(
1247
1248
  (clientX, clientY) => {
1248
1249
  if (!canvas) {
1249
1250
  return { x: 0, y: 0 };
@@ -1256,7 +1257,7 @@ function useRaycaster(options) {
1256
1257
  },
1257
1258
  [canvas]
1258
1259
  );
1259
- const isWithinCanvas = React8.useCallback(
1260
+ const isWithinCanvas = React7.useCallback(
1260
1261
  (clientX, clientY) => {
1261
1262
  if (!canvas) return false;
1262
1263
  const rect = canvas.getBoundingClientRect();
@@ -1264,7 +1265,7 @@ function useRaycaster(options) {
1264
1265
  },
1265
1266
  [canvas]
1266
1267
  );
1267
- const getIntersection = React8.useCallback(
1268
+ const getIntersection = React7.useCallback(
1268
1269
  (clientX, clientY, objects) => {
1269
1270
  if (!camera || !canvas) return null;
1270
1271
  const ndc = clientToNDC(clientX, clientY);
@@ -1287,7 +1288,7 @@ function useRaycaster(options) {
1287
1288
  },
1288
1289
  [camera, canvas, clientToNDC]
1289
1290
  );
1290
- const getAllIntersections = React8.useCallback(
1291
+ const getAllIntersections = React7.useCallback(
1291
1292
  (clientX, clientY, objects) => {
1292
1293
  if (!camera || !canvas) return [];
1293
1294
  const ndc = clientToNDC(clientX, clientY);
@@ -1306,7 +1307,7 @@ function useRaycaster(options) {
1306
1307
  },
1307
1308
  [camera, canvas, clientToNDC]
1308
1309
  );
1309
- const getGridCoordinates = React8.useCallback(
1310
+ const getGridCoordinates = React7.useCallback(
1310
1311
  (clientX, clientY) => {
1311
1312
  if (!camera || !canvas) return null;
1312
1313
  const ndc = clientToNDC(clientX, clientY);
@@ -1324,7 +1325,7 @@ function useRaycaster(options) {
1324
1325
  },
1325
1326
  [camera, canvas, cellSize, offsetX, offsetZ, clientToNDC]
1326
1327
  );
1327
- const getTileAtPosition = React8.useCallback(
1328
+ const getTileAtPosition = React7.useCallback(
1328
1329
  (clientX, clientY, scene) => {
1329
1330
  if (!camera || !canvas) return null;
1330
1331
  const tileMeshes = [];
@@ -1373,9 +1374,6 @@ function useRaycaster(options) {
1373
1374
  isWithinCanvas
1374
1375
  };
1375
1376
  }
1376
- var EventBusContext = React8.createContext(null);
1377
-
1378
- // hooks/useEventBus.ts
1379
1377
  function getGlobalEventBus() {
1380
1378
  if (typeof window !== "undefined") {
1381
1379
  return window.__kflowEventBus ?? null;
@@ -1443,12 +1441,12 @@ var fallbackEventBus = {
1443
1441
  }
1444
1442
  };
1445
1443
  function useEventBus() {
1446
- const context = React8.useContext(EventBusContext);
1444
+ const context = React7.useContext(providers.EventBusContext);
1447
1445
  return context ?? getGlobalEventBus() ?? fallbackEventBus;
1448
1446
  }
1449
1447
  function useEmitEvent() {
1450
1448
  const eventBus = useEventBus();
1451
- return React8.useCallback(
1449
+ return React7.useCallback(
1452
1450
  (type, payload) => {
1453
1451
  eventBus.emit(type, payload);
1454
1452
  },
@@ -1475,9 +1473,9 @@ function useGameCanvas3DEvents(options) {
1475
1473
  onUnitAnimation
1476
1474
  } = options;
1477
1475
  const emit = useEmitEvent();
1478
- const optionsRef = React8.useRef(options);
1476
+ const optionsRef = React7.useRef(options);
1479
1477
  optionsRef.current = options;
1480
- const handleTileClick = React8.useCallback(
1478
+ const handleTileClick = React7.useCallback(
1481
1479
  (tile, event) => {
1482
1480
  if (tileClickEvent) {
1483
1481
  emit(tileClickEvent, {
@@ -1493,7 +1491,7 @@ function useGameCanvas3DEvents(options) {
1493
1491
  },
1494
1492
  [tileClickEvent, emit]
1495
1493
  );
1496
- const handleUnitClick = React8.useCallback(
1494
+ const handleUnitClick = React7.useCallback(
1497
1495
  (unit, event) => {
1498
1496
  if (unitClickEvent) {
1499
1497
  emit(unitClickEvent, {
@@ -1512,7 +1510,7 @@ function useGameCanvas3DEvents(options) {
1512
1510
  },
1513
1511
  [unitClickEvent, emit]
1514
1512
  );
1515
- const handleFeatureClick = React8.useCallback(
1513
+ const handleFeatureClick = React7.useCallback(
1516
1514
  (feature, event) => {
1517
1515
  if (featureClickEvent) {
1518
1516
  emit(featureClickEvent, {
@@ -1527,7 +1525,7 @@ function useGameCanvas3DEvents(options) {
1527
1525
  },
1528
1526
  [featureClickEvent, emit]
1529
1527
  );
1530
- const handleCanvasClick = React8.useCallback(
1528
+ const handleCanvasClick = React7.useCallback(
1531
1529
  (event) => {
1532
1530
  if (canvasClickEvent) {
1533
1531
  emit(canvasClickEvent, {
@@ -1540,7 +1538,7 @@ function useGameCanvas3DEvents(options) {
1540
1538
  },
1541
1539
  [canvasClickEvent, emit]
1542
1540
  );
1543
- const handleTileHover = React8.useCallback(
1541
+ const handleTileHover = React7.useCallback(
1544
1542
  (tile, event) => {
1545
1543
  if (tile) {
1546
1544
  if (tileHoverEvent) {
@@ -1560,7 +1558,7 @@ function useGameCanvas3DEvents(options) {
1560
1558
  },
1561
1559
  [tileHoverEvent, tileLeaveEvent, emit]
1562
1560
  );
1563
- const handleUnitAnimation = React8.useCallback(
1561
+ const handleUnitAnimation = React7.useCallback(
1564
1562
  (unitId, state) => {
1565
1563
  if (unitAnimationEvent) {
1566
1564
  emit(unitAnimationEvent, {
@@ -1573,7 +1571,7 @@ function useGameCanvas3DEvents(options) {
1573
1571
  },
1574
1572
  [unitAnimationEvent, emit]
1575
1573
  );
1576
- const handleCameraChange = React8.useCallback(
1574
+ const handleCameraChange = React7.useCallback(
1577
1575
  (position) => {
1578
1576
  if (cameraChangeEvent) {
1579
1577
  emit(cameraChangeEvent, {
@@ -1619,17 +1617,17 @@ function TileRenderer({
1619
1617
  validMoves = [],
1620
1618
  attackTargets = []
1621
1619
  }) {
1622
- const meshRef = React8.useRef(null);
1623
- const geometry = React8.useMemo(() => {
1620
+ const meshRef = React7.useRef(null);
1621
+ const geometry = React7.useMemo(() => {
1624
1622
  return new THREE6__namespace.BoxGeometry(cellSize * 0.95, 0.2, cellSize * 0.95);
1625
1623
  }, [cellSize]);
1626
- const material = React8.useMemo(() => {
1624
+ const material = React7.useMemo(() => {
1627
1625
  return new THREE6__namespace.MeshStandardMaterial({
1628
1626
  roughness: 0.8,
1629
1627
  metalness: 0.1
1630
1628
  });
1631
1629
  }, []);
1632
- const { positions, colors, tileMap } = React8.useMemo(() => {
1630
+ const { positions, colors, tileMap } = React7.useMemo(() => {
1633
1631
  const pos = [];
1634
1632
  const cols = [];
1635
1633
  const map = /* @__PURE__ */ new Map();
@@ -1659,7 +1657,7 @@ function TileRenderer({
1659
1657
  });
1660
1658
  return { positions: pos, colors: cols, tileMap: map };
1661
1659
  }, [tiles, cellSize, offsetX, offsetZ, terrainColors, selectedTileIds, validMoves, attackTargets]);
1662
- React8.useEffect(() => {
1660
+ React7.useEffect(() => {
1663
1661
  if (!meshRef.current || !useInstancing) return;
1664
1662
  const mesh = meshRef.current;
1665
1663
  mesh.count = positions.length;
@@ -1763,10 +1761,10 @@ function TileRenderer({
1763
1761
  return /* @__PURE__ */ jsxRuntime.jsx("group", { children: renderIndividualTiles() });
1764
1762
  }
1765
1763
  function UnitVisual({ unit, position, isSelected, onClick }) {
1766
- const groupRef = React8.useRef(null);
1767
- const [animationState, setAnimationState] = React8.useState("idle");
1768
- const [isHovered, setIsHovered] = React8.useState(false);
1769
- const teamColor = React8.useMemo(() => {
1764
+ const groupRef = React7.useRef(null);
1765
+ const [animationState, setAnimationState] = React7.useState("idle");
1766
+ const [isHovered, setIsHovered] = React7.useState(false);
1767
+ const teamColor = React7.useMemo(() => {
1770
1768
  if (unit.faction === "player" || unit.team === "player") return 4491519;
1771
1769
  if (unit.faction === "enemy" || unit.team === "enemy") return 16729156;
1772
1770
  if (unit.faction === "neutral" || unit.team === "neutral") return 16777028;
@@ -1778,11 +1776,11 @@ function UnitVisual({ unit, position, isSelected, onClick }) {
1778
1776
  groupRef.current.position.y = y;
1779
1777
  }
1780
1778
  });
1781
- const healthPercent = React8.useMemo(() => {
1779
+ const healthPercent = React7.useMemo(() => {
1782
1780
  if (unit.health === void 0 || unit.maxHealth === void 0) return 1;
1783
1781
  return Math.max(0, Math.min(1, unit.health / unit.maxHealth));
1784
1782
  }, [unit.health, unit.maxHealth]);
1785
- const healthColor = React8.useMemo(() => {
1783
+ const healthColor = React7.useMemo(() => {
1786
1784
  if (healthPercent > 0.5) return "#44aa44";
1787
1785
  if (healthPercent > 0.25) return "#aaaa44";
1788
1786
  return "#ff4444";
@@ -1843,7 +1841,7 @@ function UnitRenderer({
1843
1841
  onAnimationStateChange,
1844
1842
  animationSpeed = 1
1845
1843
  }) {
1846
- const handleUnitClick = React8__default.default.useCallback(
1844
+ const handleUnitClick = React7__default.default.useCallback(
1847
1845
  (unit) => {
1848
1846
  onUnitClick?.(unit);
1849
1847
  },
@@ -2056,10 +2054,10 @@ function detectAssetRoot3(modelUrl) {
2056
2054
  return modelUrl.substring(0, modelUrl.lastIndexOf("/") + 1);
2057
2055
  }
2058
2056
  function useGLTFModel2(url) {
2059
- const [model, setModel] = React8.useState(null);
2060
- const [isLoading, setIsLoading] = React8.useState(false);
2061
- const [error, setError] = React8.useState(null);
2062
- React8.useEffect(() => {
2057
+ const [model, setModel] = React7.useState(null);
2058
+ const [isLoading, setIsLoading] = React7.useState(false);
2059
+ const [error, setError] = React7.useState(null);
2060
+ React7.useEffect(() => {
2063
2061
  if (!url) {
2064
2062
  setModel(null);
2065
2063
  return;
@@ -2091,9 +2089,9 @@ function FeatureModel({
2091
2089
  onClick,
2092
2090
  onHover
2093
2091
  }) {
2094
- const groupRef = React8.useRef(null);
2092
+ const groupRef = React7.useRef(null);
2095
2093
  const { model: loadedModel, isLoading } = useGLTFModel2(feature.assetUrl);
2096
- const model = React8.useMemo(() => {
2094
+ const model = React7.useMemo(() => {
2097
2095
  if (!loadedModel) return null;
2098
2096
  const cloned = loadedModel.clone();
2099
2097
  cloned.scale.setScalar(0.3);
@@ -2211,7 +2209,7 @@ function CameraController({
2211
2209
  onCameraChange
2212
2210
  }) {
2213
2211
  const { camera } = fiber.useThree();
2214
- React8.useEffect(() => {
2212
+ React7.useEffect(() => {
2215
2213
  if (onCameraChange) {
2216
2214
  onCameraChange({
2217
2215
  x: camera.position.x,
@@ -2222,7 +2220,7 @@ function CameraController({
2222
2220
  }, [camera.position, onCameraChange]);
2223
2221
  return null;
2224
2222
  }
2225
- var GameCanvas3D = React8.forwardRef(
2223
+ var GameCanvas3D = React7.forwardRef(
2226
2224
  ({
2227
2225
  tiles = [],
2228
2226
  units = [],
@@ -2267,10 +2265,10 @@ var GameCanvas3D = React8.forwardRef(
2267
2265
  selectedUnitId = null,
2268
2266
  children
2269
2267
  }, ref) => {
2270
- const containerRef = React8.useRef(null);
2271
- const controlsRef = React8.useRef(null);
2272
- const [hoveredTile, setHoveredTile] = React8.useState(null);
2273
- const [internalError, setInternalError] = React8.useState(null);
2268
+ const containerRef = React7.useRef(null);
2269
+ const controlsRef = React7.useRef(null);
2270
+ const [hoveredTile, setHoveredTile] = React7.useState(null);
2271
+ const [internalError, setInternalError] = React7.useState(null);
2274
2272
  const { isLoading: assetsLoading, progress, loaded, total } = useAssetLoader({
2275
2273
  preloadUrls: preloadAssets,
2276
2274
  loader: customAssetLoader
@@ -2291,7 +2289,7 @@ var GameCanvas3D = React8.forwardRef(
2291
2289
  onTileHover,
2292
2290
  onUnitAnimation
2293
2291
  });
2294
- const gridBounds = React8.useMemo(() => {
2292
+ const gridBounds = React7.useMemo(() => {
2295
2293
  if (tiles.length === 0) {
2296
2294
  return { minX: 0, maxX: 10, minZ: 0, maxZ: 10 };
2297
2295
  }
@@ -2304,14 +2302,14 @@ var GameCanvas3D = React8.forwardRef(
2304
2302
  maxZ: Math.max(...zs)
2305
2303
  };
2306
2304
  }, [tiles]);
2307
- const cameraTarget = React8.useMemo(() => {
2305
+ const cameraTarget = React7.useMemo(() => {
2308
2306
  return [
2309
2307
  (gridBounds.minX + gridBounds.maxX) / 2,
2310
2308
  0,
2311
2309
  (gridBounds.minZ + gridBounds.maxZ) / 2
2312
2310
  ];
2313
2311
  }, [gridBounds]);
2314
- const gridConfig = React8.useMemo(
2312
+ const gridConfig = React7.useMemo(
2315
2313
  () => ({
2316
2314
  ...DEFAULT_GRID_CONFIG,
2317
2315
  offsetX: -(gridBounds.maxX - gridBounds.minX) / 2,
@@ -2319,7 +2317,7 @@ var GameCanvas3D = React8.forwardRef(
2319
2317
  }),
2320
2318
  [gridBounds]
2321
2319
  );
2322
- const gridToWorld2 = React8.useCallback(
2320
+ const gridToWorld2 = React7.useCallback(
2323
2321
  (x, z, y = 0) => {
2324
2322
  const worldX = (x - gridBounds.minX) * gridConfig.cellSize;
2325
2323
  const worldZ = (z - gridBounds.minZ) * gridConfig.cellSize;
@@ -2327,7 +2325,7 @@ var GameCanvas3D = React8.forwardRef(
2327
2325
  },
2328
2326
  [gridBounds, gridConfig]
2329
2327
  );
2330
- React8.useImperativeHandle(ref, () => ({
2328
+ React7.useImperativeHandle(ref, () => ({
2331
2329
  getCameraPosition: () => {
2332
2330
  if (controlsRef.current) {
2333
2331
  const pos = controlsRef.current.object.position;
@@ -2365,19 +2363,19 @@ var GameCanvas3D = React8.forwardRef(
2365
2363
  features
2366
2364
  })
2367
2365
  }));
2368
- const handleTileClick = React8.useCallback(
2366
+ const handleTileClick = React7.useCallback(
2369
2367
  (tile, event) => {
2370
2368
  eventHandlers.handleTileClick(tile, event);
2371
2369
  },
2372
2370
  [eventHandlers]
2373
2371
  );
2374
- const handleUnitClick = React8.useCallback(
2372
+ const handleUnitClick = React7.useCallback(
2375
2373
  (unit, event) => {
2376
2374
  eventHandlers.handleUnitClick(unit, event);
2377
2375
  },
2378
2376
  [eventHandlers]
2379
2377
  );
2380
- const handleFeatureClick = React8.useCallback(
2378
+ const handleFeatureClick = React7.useCallback(
2381
2379
  (feature, event) => {
2382
2380
  if (event) {
2383
2381
  eventHandlers.handleFeatureClick(feature, event);
@@ -2385,7 +2383,7 @@ var GameCanvas3D = React8.forwardRef(
2385
2383
  },
2386
2384
  [eventHandlers]
2387
2385
  );
2388
- const handleTileHover = React8.useCallback(
2386
+ const handleTileHover = React7.useCallback(
2389
2387
  (tile, event) => {
2390
2388
  setHoveredTile(tile);
2391
2389
  if (event) {
@@ -2394,7 +2392,7 @@ var GameCanvas3D = React8.forwardRef(
2394
2392
  },
2395
2393
  [eventHandlers]
2396
2394
  );
2397
- const cameraConfig = React8.useMemo(() => {
2395
+ const cameraConfig = React7.useMemo(() => {
2398
2396
  const size = Math.max(
2399
2397
  gridBounds.maxX - gridBounds.minX,
2400
2398
  gridBounds.maxZ - gridBounds.minZ
@@ -2419,7 +2417,7 @@ var GameCanvas3D = React8.forwardRef(
2419
2417
  };
2420
2418
  }
2421
2419
  }, [cameraMode, gridBounds]);
2422
- const DefaultTileRenderer = React8.useCallback(
2420
+ const DefaultTileRenderer = React7.useCallback(
2423
2421
  ({ tile, position }) => {
2424
2422
  const isSelected = tile.id ? selectedTileIds.includes(tile.id) : false;
2425
2423
  const isHovered = hoveredTile?.id === tile.id;
@@ -2457,7 +2455,7 @@ var GameCanvas3D = React8.forwardRef(
2457
2455
  },
2458
2456
  [selectedTileIds, hoveredTile, validMoves, attackTargets, handleTileClick, handleTileHover]
2459
2457
  );
2460
- const DefaultUnitRenderer = React8.useCallback(
2458
+ const DefaultUnitRenderer = React7.useCallback(
2461
2459
  ({ unit, position }) => {
2462
2460
  const isSelected = selectedUnitId === unit.id;
2463
2461
  const color = unit.faction === "player" ? 4491519 : unit.faction === "enemy" ? 16729156 : 16777028;
@@ -2515,7 +2513,7 @@ var GameCanvas3D = React8.forwardRef(
2515
2513
  },
2516
2514
  [selectedUnitId, handleUnitClick]
2517
2515
  );
2518
- const DefaultFeatureRenderer = React8.useCallback(
2516
+ const DefaultFeatureRenderer = React7.useCallback(
2519
2517
  ({
2520
2518
  feature,
2521
2519
  position
@@ -2822,7 +2820,7 @@ var positionStyles = {
2822
2820
  fixed: "fixed",
2823
2821
  sticky: "sticky"
2824
2822
  };
2825
- var Box = React8__default.default.forwardRef(
2823
+ var Box = React7__default.default.forwardRef(
2826
2824
  ({
2827
2825
  padding,
2828
2826
  paddingX,
@@ -2851,20 +2849,20 @@ var Box = React8__default.default.forwardRef(
2851
2849
  ...rest
2852
2850
  }, ref) => {
2853
2851
  const eventBus = useEventBus();
2854
- const handleClick = React8.useCallback((e) => {
2852
+ const handleClick = React7.useCallback((e) => {
2855
2853
  if (action) {
2856
2854
  e.stopPropagation();
2857
2855
  eventBus.emit(`UI:${action}`, actionPayload ?? {});
2858
2856
  }
2859
2857
  onClick?.(e);
2860
2858
  }, [action, actionPayload, eventBus, onClick]);
2861
- const handleMouseEnter = React8.useCallback((e) => {
2859
+ const handleMouseEnter = React7.useCallback((e) => {
2862
2860
  if (hoverEvent) {
2863
2861
  eventBus.emit(`UI:${hoverEvent}`, { hovered: true });
2864
2862
  }
2865
2863
  onMouseEnter?.(e);
2866
2864
  }, [hoverEvent, eventBus, onMouseEnter]);
2867
- const handleMouseLeave = React8.useCallback((e) => {
2865
+ const handleMouseLeave = React7.useCallback((e) => {
2868
2866
  if (hoverEvent) {
2869
2867
  eventBus.emit(`UI:${hoverEvent}`, { hovered: false });
2870
2868
  }