vehicle-path2 1.0.14 → 2.0.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.
- package/README.md +168 -168
- package/dist/core/algorithms/pathFinding.d.ts +2 -2
- package/dist/core/algorithms/vehicleMovement.d.ts +29 -20
- package/dist/core/engine.d.ts +160 -0
- package/dist/core/index.d.ts +3 -2
- package/dist/core/types/api.d.ts +9 -0
- package/dist/core/types/movement.d.ts +2 -3
- package/dist/core/types/vehicle.d.ts +4 -2
- package/dist/core.cjs +1 -1
- package/dist/core.js +33 -541
- package/dist/index.d.ts +4 -34
- package/dist/utils/event-emitter.d.ts +4 -6
- package/dist/vehicle-path.cjs +1 -1
- package/dist/vehicle-path.js +729 -59
- package/package.json +83 -103
- package/dist/animation-loop-bZEm2pMN.js +0 -37
- package/dist/animation-loop-fC2LjxCd.cjs +0 -1
- package/dist/react/dsl-hooks/useInitialMovement.d.ts +0 -24
- package/dist/react/dsl-hooks/useMovementSequence.d.ts +0 -27
- package/dist/react/dsl-hooks/useSceneDefinition.d.ts +0 -22
- package/dist/react/hooks/useAnimation.d.ts +0 -47
- package/dist/react/hooks/useMovementQueue.d.ts +0 -53
- package/dist/react/hooks/useScene.d.ts +0 -78
- package/dist/react/hooks/useVehicleSimulation.d.ts +0 -128
- package/dist/react/hooks/useVehicles.d.ts +0 -55
- package/dist/react/index.d.ts +0 -48
- package/dist/react/providers/useVehicleEvents.d.ts +0 -78
- package/dist/react.cjs +0 -1
- package/dist/react.js +0 -18
- package/dist/useVehicleEvents-BZVmIugl.cjs +0 -3
- package/dist/useVehicleEvents-CabztfQ4.js +0 -940
- package/dist/utils/animation-loop.d.ts +0 -105
- package/dist/utils/dsl-parser.d.ts +0 -151
- package/dist/utils/index.d.ts +0 -15
- package/dist/utils/type-converters.d.ts +0 -40
- package/dist/utils/vehicle-helpers.d.ts +0 -8
- package/dist/utils.cjs +0 -1
- package/dist/utils.js +0 -17
- package/dist/vehicle-helpers-BgD4BTAJ.js +0 -275
- package/dist/vehicle-helpers-DrnYWjm3.cjs +0 -7
package/dist/react/index.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* React Layer - React hooks and providers
|
|
3
|
-
*
|
|
4
|
-
* This layer provides React-specific integrations for the vehicle-path library.
|
|
5
|
-
* Use this if you want the complete React experience.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* import {
|
|
10
|
-
* useVehicleSimulation,
|
|
11
|
-
* useScene,
|
|
12
|
-
* useVehicles,
|
|
13
|
-
* VehicleEventProvider
|
|
14
|
-
* } from 'vehicle-path/react'
|
|
15
|
-
* ```
|
|
16
|
-
*/
|
|
17
|
-
export { useVehicleSimulation, type UseVehicleSimulationProps, type UseVehicleSimulationResult, type SimulationWarning, type SimulationResult } from './hooks/useVehicleSimulation';
|
|
18
|
-
/** Hook for managing scene (lines & curves) */
|
|
19
|
-
export { useScene, type UseSceneResult } from './hooks/useScene';
|
|
20
|
-
/** Hook for managing vehicles */
|
|
21
|
-
export { useVehicles, type UseVehiclesResult, type UseVehiclesProps } from './hooks/useVehicles';
|
|
22
|
-
/** Hook for managing the queue of movement commands */
|
|
23
|
-
export { useMovementQueue, type UseMovementQueueResult, type UseMovementQueueProps } from './hooks/useMovementQueue';
|
|
24
|
-
/** Hook for running animation (prepare, tick, reset) */
|
|
25
|
-
export { useAnimation, type UseAnimationProps } from './hooks/useAnimation';
|
|
26
|
-
/**
|
|
27
|
-
* @deprecated Use `useMovementQueue` instead. This alias will be removed in a future version.
|
|
28
|
-
*/
|
|
29
|
-
export { useMovementQueue as useMovement } from './hooks/useMovementQueue';
|
|
30
|
-
export type { UseMovementQueueResult as UseMovementResult } from './hooks/useMovementQueue';
|
|
31
|
-
export type { UseMovementQueueProps as UseMovementProps } from './hooks/useMovementQueue';
|
|
32
|
-
/**
|
|
33
|
-
* @deprecated Use `useAnimation` instead. This alias will be removed in a future version.
|
|
34
|
-
*/
|
|
35
|
-
export { useAnimation as useVehicleMovement } from './hooks/useAnimation';
|
|
36
|
-
/**
|
|
37
|
-
* @deprecated Use `useVehicleSimulation.loadFromDSL()` instead. This hook will be removed in a future version.
|
|
38
|
-
*/
|
|
39
|
-
export { useSceneDefinition } from './dsl-hooks/useSceneDefinition';
|
|
40
|
-
/**
|
|
41
|
-
* @deprecated Use `useVehicleSimulation.loadFromDSL()` instead. This hook will be removed in a future version.
|
|
42
|
-
*/
|
|
43
|
-
export { useInitialMovement } from './dsl-hooks/useInitialMovement';
|
|
44
|
-
/**
|
|
45
|
-
* @deprecated Use `useVehicleSimulation.loadFromDSL()` instead. This hook will be removed in a future version.
|
|
46
|
-
*/
|
|
47
|
-
export { useMovementSequence } from './dsl-hooks/useMovementSequence';
|
|
48
|
-
export { useVehicleEventEmitter, useCreateVehicleEventEmitter, useVehicleEvent, VehicleEventContext, VehicleEventProvider, type VehicleEventProviderProps } from './providers/useVehicleEvents';
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import React, { type ReactNode } from 'react';
|
|
2
|
-
import { VehicleEventEmitter, type VehicleEventType, type VehicleEventCallback, type VehicleEventMap, type VehiclePositionUpdate } from '../../utils/event-emitter';
|
|
3
|
-
/**
|
|
4
|
-
* React context for VehicleEventEmitter
|
|
5
|
-
*/
|
|
6
|
-
export declare const VehicleEventContext: React.Context<VehicleEventEmitter | null>;
|
|
7
|
-
/**
|
|
8
|
-
* Hook to access the VehicleEventEmitter instance from context
|
|
9
|
-
* @returns VehicleEventEmitter instance
|
|
10
|
-
* @throws Error if used outside of VehicleEventProvider
|
|
11
|
-
*/
|
|
12
|
-
export declare function useVehicleEventEmitter(): VehicleEventEmitter;
|
|
13
|
-
/**
|
|
14
|
-
* Hook to create a new VehicleEventEmitter instance (for provider)
|
|
15
|
-
* @returns VehicleEventEmitter instance (stable reference)
|
|
16
|
-
*/
|
|
17
|
-
export declare function useCreateVehicleEventEmitter(): VehicleEventEmitter;
|
|
18
|
-
/**
|
|
19
|
-
* Hook to subscribe to a vehicle event with automatic cleanup
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```typescript
|
|
23
|
-
* useVehicleEvent('commandComplete', (info) => {
|
|
24
|
-
* console.log(`Vehicle ${info.vehicleId} arrived!`)
|
|
25
|
-
* if (info.payload) {
|
|
26
|
-
* // Handle payload
|
|
27
|
-
* }
|
|
28
|
-
* })
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
|
-
export declare function useVehicleEvent<K extends VehicleEventType>(event: K, callback: VehicleEventCallback<K>, deps?: React.DependencyList): void;
|
|
32
|
-
/**
|
|
33
|
-
* Props for VehicleEventProvider
|
|
34
|
-
*/
|
|
35
|
-
export interface VehicleEventProviderProps {
|
|
36
|
-
children: ReactNode;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Provider component for VehicleEventEmitter
|
|
40
|
-
*
|
|
41
|
-
* This simplifies the setup from:
|
|
42
|
-
* ```typescript
|
|
43
|
-
* const emitter = useCreateVehicleEventEmitter()
|
|
44
|
-
* <VehicleEventContext.Provider value={emitter}>
|
|
45
|
-
* <App />
|
|
46
|
-
* </VehicleEventContext.Provider>
|
|
47
|
-
* ```
|
|
48
|
-
*
|
|
49
|
-
* To just:
|
|
50
|
-
* ```typescript
|
|
51
|
-
* <VehicleEventProvider>
|
|
52
|
-
* <App />
|
|
53
|
-
* </VehicleEventProvider>
|
|
54
|
-
* ```
|
|
55
|
-
*
|
|
56
|
-
* @example
|
|
57
|
-
* ```typescript
|
|
58
|
-
* import { VehicleEventProvider, useVehicleEvent } from 'vehicle-path'
|
|
59
|
-
*
|
|
60
|
-
* function App() {
|
|
61
|
-
* return (
|
|
62
|
-
* <VehicleEventProvider>
|
|
63
|
-
* <MyComponent />
|
|
64
|
-
* </VehicleEventProvider>
|
|
65
|
-
* )
|
|
66
|
-
* }
|
|
67
|
-
*
|
|
68
|
-
* function MyComponent() {
|
|
69
|
-
* useVehicleEvent('commandComplete', (info) => {
|
|
70
|
-
* console.log(`Vehicle ${info.vehicleId} arrived!`)
|
|
71
|
-
* })
|
|
72
|
-
*
|
|
73
|
-
* return <div>...</div>
|
|
74
|
-
* }
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export declare function VehicleEventProvider({ children }: VehicleEventProviderProps): React.ReactElement;
|
|
78
|
-
export type { VehicleEventEmitter, VehicleEventType, VehicleEventCallback, VehicleEventMap, VehiclePositionUpdate };
|
package/dist/react.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./useVehicleEvents-BZVmIugl.cjs");exports.VehicleEventContext=e.VehicleEventContext;exports.VehicleEventProvider=e.VehicleEventProvider;exports.useAnimation=e.useAnimation;exports.useCreateVehicleEventEmitter=e.useCreateVehicleEventEmitter;exports.useInitialMovement=e.useInitialMovement;exports.useMovement=e.useMovementQueue;exports.useMovementQueue=e.useMovementQueue;exports.useMovementSequence=e.useMovementSequence;exports.useScene=e.useScene;exports.useSceneDefinition=e.useSceneDefinition;exports.useVehicleEvent=e.useVehicleEvent;exports.useVehicleEventEmitter=e.useVehicleEventEmitter;exports.useVehicleMovement=e.useAnimation;exports.useVehicleSimulation=e.useVehicleSimulation;exports.useVehicles=e.useVehicles;
|
package/dist/react.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { V as t, a as i, u as a, b as n, c as u, d as c, d as o, e as v, f as l, g as m, h, i as V, u as r, j as E, k as M } from "./useVehicleEvents-CabztfQ4.js";
|
|
2
|
-
export {
|
|
3
|
-
t as VehicleEventContext,
|
|
4
|
-
i as VehicleEventProvider,
|
|
5
|
-
a as useAnimation,
|
|
6
|
-
n as useCreateVehicleEventEmitter,
|
|
7
|
-
u as useInitialMovement,
|
|
8
|
-
c as useMovement,
|
|
9
|
-
o as useMovementQueue,
|
|
10
|
-
v as useMovementSequence,
|
|
11
|
-
l as useScene,
|
|
12
|
-
m as useSceneDefinition,
|
|
13
|
-
h as useVehicleEvent,
|
|
14
|
-
V as useVehicleEventEmitter,
|
|
15
|
-
r as useVehicleMovement,
|
|
16
|
-
E as useVehicleSimulation,
|
|
17
|
-
M as useVehicles
|
|
18
|
-
};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use strict";const r=require("react"),R=require("./core.cjs"),A=require("./vehicle-helpers-DrnYWjm3.cjs"),se=require("react/jsx-runtime");function G(t){return Array.isArray(t)?{x:t[0],y:t[1]}:t}function K(t){return{id:t.id,start:G(t.start),end:G(t.end)}}function U(t){const c=t.fromIsPercentage!==!1,M=t.toIsPercentage!==!1;return{fromLineId:t.from,toLineId:t.to,fromOffset:t.fromPosition,fromIsPercentage:t.fromPosition!==void 0?c:void 0,toOffset:t.toPosition,toIsPercentage:t.toPosition!==void 0?M:void 0}}function H(t){const c=t.position??0,M=t.isPercentage!==!1;return{vehicleId:t.id,lineId:t.lineId,offset:c,isPercentage:M}}function J(t){const c=t.isPercentage!==!1,M=t.targetPosition??1;return{vehicleId:t.vehicleId,targetLineId:t.targetLineId,targetOffset:M,isPercentage:c,payload:t.payload}}function re(t){const c=[],M=new Set;for(const s of t.lines)M.has(s.id)&&c.push(`Duplicate line ID: ${s.id}`),M.add(s.id);if(t.connections)for(const s of t.connections){M.has(s.from)||c.push(`Connection references non-existent line: ${s.from}`),M.has(s.to)||c.push(`Connection references non-existent line: ${s.to}`);const g=s.fromIsPercentage!==!1,e=s.toIsPercentage!==!1;!g&&s.fromPosition===void 0&&c.push("fromPosition is required when fromIsPercentage is false"),!e&&s.toPosition===void 0&&c.push("toPosition is required when toIsPercentage is false"),s.fromPosition!==void 0&&(g&&(s.fromPosition<0||s.fromPosition>1)?c.push(`Invalid fromPosition: ${s.fromPosition} (must be 0-1 for percentage)`):!g&&s.fromPosition<0&&c.push(`Invalid fromPosition: ${s.fromPosition} (must be >= 0 for absolute distance)`)),s.toPosition!==void 0&&(e&&(s.toPosition<0||s.toPosition>1)?c.push(`Invalid toPosition: ${s.toPosition} (must be 0-1 for percentage)`):!e&&s.toPosition<0&&c.push(`Invalid toPosition: ${s.toPosition} (must be >= 0 for absolute distance)`))}return{valid:c.length===0,errors:c}}function B(){const[t,c]=r.useState([]),[M,s]=r.useState([]),[g,e]=r.useState(null),d=r.useCallback((n,p)=>{c(n),s(p),e(null)},[]),x=r.useCallback(n=>{const p=re(n);if(!p.valid)return e(p.errors.join("; ")),{success:!1,errors:p.errors};const u=n.lines.map(K),v=n.connections?.map(U)||[];return d(u,v),{success:!0}},[d]),y=r.useCallback(n=>{if(t.some(u=>u.id===n.id)){const u=`Line with ID '${n.id}' already exists`;return e(u),{success:!1,error:u}}return c(u=>[...u,K(n)]),e(null),{success:!0}},[t]),D=r.useCallback((n,p)=>{if(t.findIndex(v=>v.id===n)===-1){const v=`Line with ID '${n}' not found`;return e(v),{success:!1,error:v}}return c(v=>v.map(V=>V.id!==n?V:{...V,start:p.start?G(p.start):V.start,end:p.end?G(p.end):V.end})),e(null),{success:!0}},[t]),k=r.useCallback(n=>{if(!t.some(u=>u.id===n)){const u=`Line with ID '${n}' not found`;return e(u),{success:!1,error:u}}return c(u=>u.filter(v=>v.id!==n)),s(u=>u.filter(v=>v.fromLineId!==n&&v.toLineId!==n)),e(null),{success:!0}},[t]),b=r.useCallback(n=>{const p=t.some(m=>m.id===n.from),u=t.some(m=>m.id===n.to);if(!p){const m=`Line '${n.from}' not found`;return e(m),{success:!1,error:m}}if(!u){const m=`Line '${n.to}' not found`;return e(m),{success:!1,error:m}}const v=n.fromIsPercentage!==!1,V=n.toIsPercentage!==!1;if(!v&&n.fromPosition===void 0){const m="fromPosition is required when fromIsPercentage is false";return e(m),{success:!1,error:m}}if(!V&&n.toPosition===void 0){const m="toPosition is required when toIsPercentage is false";return e(m),{success:!1,error:m}}if(M.some(m=>m.fromLineId===n.from&&m.toLineId===n.to)){const m=`Connection from '${n.from}' to '${n.to}' already exists`;return e(m),{success:!1,error:m}}return s(m=>[...m,U(n)]),e(null),{success:!0}},[t,M]),P=r.useCallback((n,p,u)=>{const v=M.findIndex(f=>f.fromLineId===n&&f.toLineId===p);if(v===-1){const f=`Connection from '${n}' to '${p}' not found`;return e(f),{success:!1,error:f}}const V=M[v],Q=u.fromIsPercentage??V.fromIsPercentage,m=u.toIsPercentage??V.toIsPercentage;let w;u.fromOffset!==void 0?w=u.fromOffset:V.fromOffset!==void 0&&(w=V.fromOffset);let L;if(u.toOffset!==void 0?L=u.toOffset:V.toOffset!==void 0&&(L=V.toOffset),w!==void 0){if(Q!==!1&&(w<0||w>1)){const f=`Invalid fromOffset: ${w} (must be 0-1 for percentage)`;return e(f),{success:!1,error:f}}if(Q===!1&&w<0){const f=`Invalid fromOffset: ${w} (must be >= 0 for absolute distance)`;return e(f),{success:!1,error:f}}}if(L!==void 0){if(m!==!1&&(L<0||L>1)){const f=`Invalid toOffset: ${L} (must be 0-1 for percentage)`;return e(f),{success:!1,error:f}}if(m===!1&&L<0){const f=`Invalid toOffset: ${L} (must be >= 0 for absolute distance)`;return e(f),{success:!1,error:f}}}if(Q===!1&&w===void 0){const f="fromOffset is required when fromIsPercentage is false";return e(f),{success:!1,error:f}}if(m===!1&&L===void 0){const f="toOffset is required when toIsPercentage is false";return e(f),{success:!1,error:f}}const j={from:n,to:p,fromPosition:w,fromIsPercentage:Q,toPosition:L,toIsPercentage:m};return s(f=>f.map((o,a)=>a===v?U(j):o)),e(null),{success:!0}},[M]),C=r.useCallback((n,p)=>{if(!M.some(v=>v.fromLineId===n&&v.toLineId===p)){const v=`Connection from '${n}' to '${p}' not found`;return e(v),{success:!1,error:v}}return s(v=>v.filter(V=>!(V.fromLineId===n&&V.toLineId===p))),e(null),{success:!0}},[M]),i=r.useCallback(()=>{c([]),s([]),e(null)},[]);return{lines:t,curves:M,setScene:x,addLine:y,updateLine:D,removeLine:k,addConnection:b,updateConnection:P,removeConnection:C,clear:i,error:g,_loadScene:d}}function W({lines:t,wheelbase:c}){const[M,s]=r.useState([]),[g,e]=r.useState(null),d=r.useRef([]),x=r.useCallback(P=>{d.current=P,s(P),e(null)},[]),y=r.useCallback(P=>{const C=Array.isArray(P)?P:[P],i=[];for(const v of C)d.current.some(Q=>Q.id===v.id)&&i.push(`Vehicle with ID '${v.id}' already exists`);if(i.length>0)return e(i.join("; ")),{success:!1,errors:i};const n=C.map(H),{vehicles:p,errors:u}=A.validateAndCreateVehicles(n,t,c);return u.length>0?(e(u.join("; ")),{success:!1,errors:u}):(d.current=[...d.current,...p],s(d.current),e(null),{success:!0})},[t,c]),D=r.useCallback((P,C)=>{const i=d.current.findIndex(L=>L.id===P);if(i===-1){const L=`Vehicle with ID '${P}' not found`;return e(L),{success:!1,error:L}}const n=d.current[i];if(n.state!=="idle"){const L=`Cannot update vehicle '${P}' while it is ${n.state}. Vehicle must be idle.`;return e(L),{success:!1,error:L}}const p=C.lineId??n.lineId;if(!t.find(L=>L.id===p)){const L=`Line '${p}' not found`;return e(L),{success:!1,error:L}}let v,V;C.lineId!==void 0&&C.position===void 0?(v=0,V=!0):C.position!==void 0?(v=C.position,V=C.isPercentage??!0):(v=n.offset,V=n.isPercentage);const Q={vehicleId:P,lineId:p,offset:v,isPercentage:V},{vehicles:m,errors:w}=A.validateAndCreateVehicles([Q],t,c);return w.length>0?(e(w.join("; ")),{success:!1,error:w.join("; ")}):(d.current=d.current.map((L,j)=>j===i?m[0]:L),s(d.current),e(null),{success:!0})},[t,c]),k=r.useCallback(P=>{if(!d.current.some(i=>i.id===P)){const i=`Vehicle with ID '${P}' not found`;return e(i),{success:!1,error:i}}return d.current=d.current.filter(i=>i.id!==P),s(d.current),e(null),{success:!0}},[]),b=r.useCallback(()=>{d.current=[],s([]),e(null)},[]);return{vehicles:M,addVehicles:y,updateVehicle:D,removeVehicle:k,clear:b,error:g,_loadVehicles:x}}function X({vehicles:t,lines:c}){const[M,s]=r.useState(new Map),[g,e]=r.useState(null),d=r.useRef(new Map),x=r.useCallback(()=>d.current,[]),y=r.useCallback(b=>{d.current=b,s(b),e(null)},[]),D=r.useCallback((b,P)=>{if(!t.some(m=>m.id===b)){const m=`Vehicle '${b}' not found`;return e(m),{success:!1,error:m}}const i=c.find(m=>m.id===P.targetLineId);if(!i){const m=`Line '${P.targetLineId}' not found`;return e(m),{success:!1,error:m}}const n=P.isPercentage!==!1,p=R.distance(i.start,i.end);if(!n&&P.targetPosition===void 0){const m="targetPosition is required when isPercentage is false";return e(m),{success:!1,error:m}}const u=P.targetPosition??1;if(n){if(u<0||u>1){const m=`Invalid targetPosition: ${u} (must be 0-1 for percentage)`;return e(m),{success:!1,error:m}}}else{if(u<0){const m=`Invalid targetPosition: ${u} (must be >= 0 for absolute distance)`;return e(m),{success:!1,error:m}}if(u>p){const m=`Position ${u} exceeds line length ${p}`;return e(m),{success:!1,error:m}}}const v=J({vehicleId:b,...P}),V=new Map(d.current),Q=V.get(b)||[];return V.set(b,[...Q,v]),d.current=V,s(V),e(null),{success:!0}},[t,c]),k=r.useCallback(b=>{if(b!==void 0){if(!t.some(i=>i.id===b)){const i=`Vehicle '${b}' not found`;return e(i),{success:!1,error:i}}const C=new Map(d.current);C.delete(b),d.current=C,s(C)}else d.current=new Map,s(new Map);return e(null),{success:!0}},[t]);return{vehicleQueues:M,getVehicleQueues:x,queueMovement:D,clearQueue:k,error:g,_loadQueues:y}}function ee({vehicles:t,lines:c,vehicleQueues:M,getVehicleQueues:s,wheelbase:g,tangentMode:e,curves:d,eventEmitter:x}){const[y,D]=r.useState([]),k=r.useRef([]),b=r.useCallback(f=>{typeof f=="function"?D(o=>{const a=f(o);return k.current=a,a}):(k.current=f,D(f))},[]),P=r.useCallback(()=>k.current,[]),C=r.useMemo(()=>({wheelbase:g,tangentMode:e}),[g,e]),i=r.useMemo(()=>new Map(c.map(f=>[f.id,f])),[c]),n=r.useRef(new Map);r.useEffect(()=>{const{movingVehicles:f,stateMap:o}=R.initializeAllVehicles(t,i);n.current=o;const a=setTimeout(()=>{b(f)},0);return()=>clearTimeout(a)},[t,i]);const p=r.useRef(null);r.useEffect(()=>{c.length>0&&(p.current=R.buildGraph(c,d,C))},[c,d,C]);const u=r.useRef(0),v=r.useRef(!1),V=r.useCallback(f=>{if(!v.current)return!1;let o=!1;for(const[,l]of n.current)if(l.vehicle.state==="moving"){o=!0;break}if(!o)return!1;const a=[];for(const[l,h]of n.current){if(h.vehicle.state!=="moving"||!h.execution)continue;const I=h.execution;let S;if(I.front.currentSegmentIndex<I.path.segments.length){const T=I.path.segments[I.front.currentSegmentIndex];if(T.type==="line"){const E=i.get(T.lineId);E&&(S=Math.sqrt(Math.pow(E.end.x-E.start.x,2)+Math.pow(E.end.y-E.start.y,2)))}}const O=R.updateAxlePosition(h.vehicle.rear,I.rear,I.path,f,i,I.curveDataMap),q=R.updateAxlePosition(h.vehicle.front,I.front,I.path,f,i,I.curveDataMap,S);if(h.vehicle={...h.vehicle,rear:O.axleState,front:q.axleState},h.execution.rear=O.execution,h.execution.front=q.execution,O.completed){const T={linesMap:i,config:C,vehicleQueues:M,curves:d,graphRef:p,prepareCommandPath:R.prepareCommandPath,onCommandComplete:F=>a.push({type:"commandComplete",data:F}),onCommandStart:F=>a.push({type:"commandStart",data:F})},E=R.handleArrival(h,T);h.vehicle=E.vehicle,E.newExecution!==void 0&&(h.execution=E.newExecution),E.vehicle.state!=="moving"&&a.push({type:"stateChange",data:{vehicleId:l,from:"moving",to:E.vehicle.state}});const $=E.vehicle.rear.position,_=E.vehicle.front.position;a.push({type:"positionUpdate",data:{vehicleId:l,rear:$,front:_,center:{x:($.x+_.x)/2,y:($.y+_.y)/2},angle:Math.atan2(_.y-$.y,_.x-$.x)}})}}if(b(l=>l.map(h=>{const I=n.current.get(h.id);return I?I.vehicle:h})),x&&a.length>0){const l=u.current;setTimeout(()=>{u.current===l&&a.forEach(({type:h,data:I})=>{x.emit(h,I)})},0)}for(const[,l]of n.current)if(l.vehicle.state==="moving")return!0;return v.current=!1,!1},[i,d,C,M,x]),Q=r.useCallback(()=>{const f=p.current;if(!f)return!1;const o=s?s():M,a=[];let l=!1;for(const[h,I]of n.current){const S=I.vehicle;if(S.state==="moving")continue;const O=o.get(h);if(!O||O.length===0)continue;const q=O[0],T={graph:f,linesMap:i,curves:d,config:C},E=R.prepareCommandPath(S,q,T);if(!E){console.warn(`No path found for vehicle ${h}`);continue}const $=R.calculateFrontAxlePosition(E.path,0,0,g);n.current.set(h,{...I,execution:{path:E.path,curveDataMap:E.curveDataMap,currentCommandIndex:0,rear:{currentSegmentIndex:0,segmentDistance:0},front:$?{currentSegmentIndex:$.segmentIndex,segmentDistance:$.segmentDistance}:{currentSegmentIndex:0,segmentDistance:0}},vehicle:{...S,state:"moving"}}),l=!0,a.push({id:h,fromState:S.state,command:q,startPosition:{lineId:S.rear.lineId,absoluteOffset:S.rear.absoluteOffset,position:S.rear.position}})}if(!l)return!1;if(v.current=!0,b(h=>h.map(I=>{const S=n.current.get(I.id);return S?S.vehicle:I})),x&&a.length>0){const h=u.current;setTimeout(()=>{u.current===h&&a.forEach(({id:I,fromState:S,command:O,startPosition:q})=>{x.emit("commandStart",{vehicleId:I,command:O,commandIndex:0,startPosition:q}),x.emit("stateChange",{vehicleId:I,from:S,to:"moving"})})},0)}return!0},[i,d,M,s,C,g,x]),m=r.useCallback(()=>{u.current++,v.current=!1;const{movingVehicles:f,stateMap:o}=R.initializeAllVehicles(t,i);n.current=o,b(f)},[t,i]),w=r.useCallback(f=>{const o=t.find(I=>I.id===f);if(!o||!i.get(o.lineId))return;const l=R.initializeMovingVehicle(o),h=R.createInitialMovementState(l);n.current.set(f,h),b(I=>I.map(S=>S.id===f?l:S))},[t,i]),L=r.useCallback(f=>{const o=n.current.get(f);if(!o||o.vehicle.state!=="waiting")return!1;const a=M.get(f),l=o.execution;if(!l)return!1;const h=l.currentCommandIndex+1;if(a&&h<a.length){const I=p.current;if(I){const S=a[h],O={graph:I,linesMap:i,curves:d,config:C},q=R.prepareCommandPath(o.vehicle,S,O);if(q){const T=R.calculateFrontAxlePosition(q.path,0,0,g);if(o.execution={path:q.path,curveDataMap:q.curveDataMap,currentCommandIndex:h,rear:{currentSegmentIndex:0,segmentDistance:0},front:T?{currentSegmentIndex:T.segmentIndex,segmentDistance:T.segmentDistance}:{currentSegmentIndex:0,segmentDistance:0}},o.vehicle={...o.vehicle,state:"moving"},b(E=>E.map($=>$.id===f?o.vehicle:$)),x){const E=u.current;setTimeout(()=>{u.current===E&&x.emit("stateChange",{vehicleId:f,from:"waiting",to:"moving"})},0)}return!0}}}if(o.vehicle={...o.vehicle,state:"idle"},o.execution=null,b(I=>I.map(S=>S.id===f?o.vehicle:S)),x){const I=u.current;setTimeout(()=>{u.current===I&&x.emit("stateChange",{vehicleId:f,from:"waiting",to:"idle"})},0)}return!0},[M,i,d,C,g,x]),j=r.useCallback(()=>{for(const[,f]of n.current)if(f.vehicle.state==="moving")return!0;return!1},[]);return{movingVehicles:y,getMovingVehicles:P,prepare:Q,tick:V,reset:m,resetVehicle:w,continueVehicle:L,isMoving:j,isPrepared:v.current}}function ne({wheelbase:t,tangentMode:c="proportional-40",eventEmitter:M}){const s=B(),g=W({lines:s.lines,wheelbase:t}),e=X({vehicles:g.vehicles,lines:s.lines,curves:s.curves}),d=ee({vehicles:g.vehicles,lines:s.lines,vehicleQueues:e.vehicleQueues,getVehicleQueues:e.getVehicleQueues,wheelbase:t,tangentMode:c,curves:s.curves,eventEmitter:M}),x=r.useCallback(o=>g.vehicles.filter(a=>a.lineId===o||a.rear.lineId===o),[g.vehicles]),y=r.useCallback(o=>x(o).length>0,[x]),D=r.useCallback(o=>{const a=s.addLine(o);return a.success?{success:!0}:{success:!1,error:a.error}},[s]),k=r.useCallback((o,a)=>{const l=s.updateLine(o,a);return l.success?{success:!0}:{success:!1,error:l.error}},[s]),b=r.useCallback(o=>{const a=[],l=x(o);l.length>0&&(a.push({type:"vehicle_on_removed_line",message:`${l.length} vehicle(s) are on line '${o}'`,details:{lineId:o,vehicleIds:l.map(S=>S.id)}}),l.forEach(S=>{g.removeVehicle(S.id),e.clearQueue(S.id)}));const h=s.curves.filter(S=>S.fromLineId===o||S.toLineId===o);h.length>0&&a.push({type:"orphaned_connection",message:`${h.length} connection(s) will be removed`,details:{lineId:o,connectionCount:h.length}});const I=s.removeLine(o);return I.success?{success:!0,warnings:a.length>0?a:void 0}:{success:!1,error:I.error}},[s,x,g,e]),P=r.useCallback(()=>{s.clear(),g.clear(),e.clearQueue()},[s,g,e]),C=r.useCallback((o,a,l)=>{const h=s.addConnection({from:o,to:a,fromPosition:l?.fromOffset,fromIsPercentage:l?.fromIsPercentage,toPosition:l?.toOffset,toIsPercentage:l?.toIsPercentage});return h.success?{success:!0}:{success:!1,error:h.error}},[s]),i=r.useCallback((o,a,l)=>{const h=s.updateConnection(o,a,l);return h.success?{success:!0}:{success:!1,error:h.error}},[s]),n=r.useCallback((o,a)=>{const l=s.removeConnection(o,a);return l.success?{success:!0}:{success:!1,error:l.error}},[s]),p=r.useCallback(o=>{const a=g.addVehicles(o);return a.success?{success:!0}:{success:!1,error:a.errors?.join("; ")}},[g]),u=r.useCallback((o,a)=>{const l=g.updateVehicle(o,a);return l.success?{success:!0}:{success:!1,error:l.error}},[g]),v=r.useCallback(o=>{const a=[],l=e.vehicleQueues.get(o);l&&l.length>0&&(a.push({type:"movement_queue_cleared",message:`${l.length} queued movement(s) will be cleared for vehicle '${o}'`,details:{vehicleId:o}}),e.clearQueue(o));const h=g.removeVehicle(o);return h.success?{success:!0,warnings:a.length>0?a:void 0}:{success:!1,error:h.error}},[g,e]),V=r.useCallback(()=>{g.clear(),e.clearQueue()},[g,e]),Q=r.useCallback(o=>{const a={targetLineId:o.lineId,targetPosition:o.position??1,isPercentage:o.isPercentage,payload:o.payload},l=e.queueMovement(o.id,a);return l.success?{success:!0}:{success:!1,error:l.error}},[e]),m=r.useCallback(o=>{const a=e.clearQueue(o);return a.success?{success:!0}:{success:!1,error:a.error}},[e]),w=r.useCallback(o=>{e.clearQueue(o),d.resetVehicle(o)},[e,d]),L=r.useCallback(o=>{const a=[],l=[],{scene:h,vehicles:I,movements:S}=A.parseAllDSL(o);h.errors.length>0&&l.push(...h.errors),I.errors.length>0&&l.push(...I.errors),S.errors.length>0&&l.push(...S.errors);const O=h.data.lines.map(K),q=(h.data.connections||[]).map(U),T=I.data.map(H),{vehicles:E,errors:$}=A.validateAndCreateVehicles(T,O,t);$.length>0&&l.push(...$);const _=new Map;for(const F of S.data){const Z=_.get(F.vehicleId)||[];Z.push(J(F)),_.set(F.vehicleId,Z)}return s._loadScene(O,q),g._loadVehicles(E),e._loadQueues(_),l.length>0&&a.push({type:"dsl_parse_error",message:`DSL loading had ${l.length} error(s)`,details:{errors:l}}),{success:!0,warnings:a.length>0?a:void 0}},[s,g,e,t]),j=r.useCallback(o=>{const a=[],l=[],h=o.lines.map(K),I=(o.connections||[]).map(U),S=(o.vehicles||[]).map(H),{vehicles:O,errors:q}=A.validateAndCreateVehicles(S,h,t);q.length>0&&l.push(...q);const T=new Map;for(const E of o.movements||[]){const $=T.get(E.vehicleId)||[];$.push(J({vehicleId:E.vehicleId,targetLineId:E.targetLineId,targetPosition:E.targetPosition,isPercentage:E.isPercentage,payload:E.payload})),T.set(E.vehicleId,$)}return s._loadScene(h,I),g._loadVehicles(O),e._loadQueues(T),l.length>0&&a.push({type:"dsl_parse_error",message:`JSON loading had ${l.length} error(s)`,details:{errors:l}}),{success:!0,warnings:a.length>0?a:void 0}},[s,g,e,t]),f=r.useMemo(()=>s.error||g.error||e.error,[s.error,g.error,e.error]);return{lines:s.lines,curves:s.curves,vehicles:g.vehicles,movingVehicles:d.movingVehicles,getMovingVehicles:d.getMovingVehicles,vehicleQueues:e.vehicleQueues,error:f,addLine:D,updateLine:k,removeLine:b,clearScene:P,connect:C,updateConnection:i,disconnect:n,addVehicles:p,updateVehicle:u,removeVehicle:v,clearVehicles:V,goto:Q,clearQueue:m,prepare:d.prepare,tick:d.tick,reset:d.reset,resetVehicle:w,continueVehicle:d.continueVehicle,isMoving:d.isMoving,loadFromDSL:L,loadFromJSON:j,getVehiclesOnLine:x,hasVehiclesOnLine:y}}function z(t){return t.map(c=>({id:c.id,start:c.start,end:c.end}))}function N(t){return t.map(c=>({from:c.fromLineId,to:c.toLineId,fromPosition:c.fromOffset,fromIsPercentage:c.fromIsPercentage,toPosition:c.toOffset,toIsPercentage:c.toIsPercentage}))}function oe(){const[t,c]=r.useState(""),[M,s]=r.useState(null),{lines:g,curves:e,setScene:d}=B(),x=r.useRef(!1),y=r.useRef("");r.useEffect(()=>{y.current=t},[t]),r.useEffect(()=>{if(x.current)return;const P={lines:z(g),connections:e.length>0?N(e):void 0},C=A.generateSceneDSL(P);C!==y.current&&(x.current=!0,c(C),setTimeout(()=>{x.current=!1},50))},[g,e]);const D=r.useCallback(P=>{x.current=!0,c(P);try{const{data:C,errors:i}=A.parseSceneDSL(P);i.length>0&&s(i.join("; "));const n=d(C);!n.success&&n.errors?s(p=>p?`${p}; ${n.errors.join("; ")}`:n.errors.join("; ")):i.length===0&&s(null)}catch(C){s(C instanceof Error?C.message:"Invalid scene definition")}setTimeout(()=>{x.current=!1},50)},[d]),k=r.useCallback(P=>{const C=typeof P=="function"?P(g):P,i=N(e);d({lines:z(C),connections:i.length>0?i:void 0});const n={lines:z(C),connections:i.length>0?i:void 0},p=A.generateSceneDSL(n);x.current=!0,c(p),setTimeout(()=>{x.current=!1},50)},[g,e,d]),b=r.useCallback(P=>{const C=typeof P=="function"?P(e):P,i=N(C);d({lines:z(g),connections:i.length>0?i:void 0});const n={lines:z(g),connections:i.length>0?i:void 0},p=A.generateSceneDSL(n);x.current=!0,c(p),setTimeout(()=>{x.current=!1},50)},[g,e,d]);return{lines:g,curves:e,sceneDefinitionText:t,sceneError:M,isDebouncing:!1,debounceKey:0,setLines:k,setCurves:b,setSceneDefinitionText:D}}function ce({lines:t,wheelbase:c}){const[M,s]=r.useState(""),[g,e]=r.useState(null),{vehicles:d,addVehicles:x,clear:y,error:D}=W({lines:t,wheelbase:c}),k=r.useRef(!1),b=r.useCallback(P=>{k.current=!0,s(P);try{const{data:C,errors:i}=A.parseVehiclesDSL(P),n=[...i];y();for(const p of C){const u=x(p);!u.success&&u.errors&&n.push(...u.errors)}n.length>0?e(n.join(`
|
|
2
|
-
`)):e(null)}catch(C){e(C instanceof Error?C.message:"Invalid initial movement")}setTimeout(()=>{k.current=!1},50)},[x,y]);return{vehicles:d,initialMovementText:M,movementError:g||D,isDebouncing:!1,debounceKey:0,setInitialMovementText:b}}function ie({lines:t,vehicles:c}){const[M,s]=r.useState(""),[g,e]=r.useState([]),[d,x]=r.useState(null),{vehicleQueues:y,queueMovement:D,clearQueue:k,error:b}=X({vehicles:c,lines:t}),P=r.useRef(!1),C=r.useCallback(i=>{P.current=!0,s(i);try{const{data:n,errors:p}=A.parseMovementDSL(i),u=[...p];k();for(const v of n){const V=D(v.vehicleId,{targetLineId:v.targetLineId,targetPosition:v.targetPosition,isPercentage:v.isPercentage,payload:v.payload});!V.success&&V.error&&u.push(V.error)}e(n),u.length>0?x(u.join(`
|
|
3
|
-
`)):x(null)}catch(n){x(n instanceof Error?n.message:"Invalid movement sequence"),e([])}setTimeout(()=>{P.current=!1},50)},[D,k]);return{movementSequenceText:M,gotoCommands:g,vehicleQueues:y,sequenceError:d||b,isDebouncing:!1,debounceKey:0,setMovementSequenceText:C}}const Y=r.createContext(null);function te(){const t=r.useContext(Y);if(!t)throw new Error("useVehicleEventEmitter must be used within a VehicleEventProvider");return t}function ae(){return r.useMemo(()=>new A.VehicleEventEmitter,[])}function ue(t,c,M=[]){const s=te();r.useEffect(()=>s.on(t,c),[s,t,...M])}function le({children:t}){const c=r.useMemo(()=>new A.VehicleEventEmitter,[]);return se.jsx(Y.Provider,{value:c,children:t})}exports.VehicleEventContext=Y;exports.VehicleEventProvider=le;exports.useAnimation=ee;exports.useCreateVehicleEventEmitter=ae;exports.useInitialMovement=ce;exports.useMovementQueue=X;exports.useMovementSequence=ie;exports.useScene=B;exports.useSceneDefinition=oe;exports.useVehicleEvent=ue;exports.useVehicleEventEmitter=te;exports.useVehicleSimulation=ne;exports.useVehicles=W;
|