@nice2dev/ui-3d 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/dist/cjs/collaborative/collaborativeScene.js +16 -8
  2. package/dist/cjs/collaborative/collaborativeScene.js.map +1 -1
  3. package/dist/cjs/core/i18n.js +3 -3
  4. package/dist/cjs/dance/DanceBridge.js +65 -30
  5. package/dist/cjs/dance/DanceBridge.js.map +1 -1
  6. package/dist/cjs/dance/DanceScoreEngine.js +37 -23
  7. package/dist/cjs/dance/DanceScoreEngine.js.map +1 -1
  8. package/dist/cjs/dance/PoseDetector.js +92 -49
  9. package/dist/cjs/dance/PoseDetector.js.map +1 -1
  10. package/dist/cjs/material/NiceMaterialEditor.js +134 -91
  11. package/dist/cjs/material/NiceMaterialEditor.js.map +1 -1
  12. package/dist/cjs/material/materialEditorUtils.js +86 -55
  13. package/dist/cjs/material/materialEditorUtils.js.map +1 -1
  14. package/dist/cjs/model/ModelEditor.js +16 -14
  15. package/dist/cjs/model/ModelEditor.js.map +1 -1
  16. package/dist/cjs/model/ModelEditorLeftPanel.js +21 -15
  17. package/dist/cjs/model/ModelEditorLeftPanel.js.map +1 -1
  18. package/dist/cjs/model/ModelEditorMenuBar.js +23 -10
  19. package/dist/cjs/model/ModelEditorMenuBar.js.map +1 -1
  20. package/dist/cjs/model/ModelEditorRightPanel.js +32 -27
  21. package/dist/cjs/model/ModelEditorRightPanel.js.map +1 -1
  22. package/dist/cjs/model/ModelEditorSubComponents.js +20 -20
  23. package/dist/cjs/model/ModelEditorSubComponents.js.map +1 -1
  24. package/dist/cjs/model/ModelEditorTimeline.js +12 -11
  25. package/dist/cjs/model/ModelEditorTimeline.js.map +1 -1
  26. package/dist/cjs/model/ModelEditorToolbar.js +5 -5
  27. package/dist/cjs/model/ModelEditorToolbar.js.map +1 -1
  28. package/dist/cjs/model/ModelEditorViewport.js +12 -8
  29. package/dist/cjs/model/ModelEditorViewport.js.map +1 -1
  30. package/dist/cjs/model/ModelViewer.js +16 -15
  31. package/dist/cjs/model/ModelViewer.js.map +1 -1
  32. package/dist/cjs/model/NiceArmatureEditor.js +53 -30
  33. package/dist/cjs/model/NiceArmatureEditor.js.map +1 -1
  34. package/dist/cjs/model/NiceMorphTargetEditor.js +51 -30
  35. package/dist/cjs/model/NiceMorphTargetEditor.js.map +1 -1
  36. package/dist/cjs/model/NiceOctree.js +62 -37
  37. package/dist/cjs/model/NiceOctree.js.map +1 -1
  38. package/dist/cjs/model/NicePhysicsSimulation.js +74 -36
  39. package/dist/cjs/model/NicePhysicsSimulation.js.map +1 -1
  40. package/dist/cjs/model/NiceProceduralGeometry.js +101 -31
  41. package/dist/cjs/model/NiceProceduralGeometry.js.map +1 -1
  42. package/dist/cjs/model/NiceTerrainEditor.js +88 -38
  43. package/dist/cjs/model/NiceTerrainEditor.js.map +1 -1
  44. package/dist/cjs/model/NiceWeightPainter.js +46 -24
  45. package/dist/cjs/model/NiceWeightPainter.js.map +1 -1
  46. package/dist/cjs/model/NiceXRPreview.js +89 -43
  47. package/dist/cjs/model/NiceXRPreview.js.map +1 -1
  48. package/dist/cjs/model/cadModeUtils.js +2 -2
  49. package/dist/cjs/model/cadModeUtils.js.map +1 -1
  50. package/dist/cjs/model/editorShortcuts.js +69 -35
  51. package/dist/cjs/model/editorShortcuts.js.map +1 -1
  52. package/dist/cjs/model/modelEditorTypes.js +56 -52
  53. package/dist/cjs/model/modelEditorTypes.js.map +1 -1
  54. package/dist/cjs/model/modelEditorUtils.js +356 -131
  55. package/dist/cjs/model/modelEditorUtils.js.map +1 -1
  56. package/dist/cjs/model/simsModeUtils.js +819 -74
  57. package/dist/cjs/model/simsModeUtils.js.map +1 -1
  58. package/dist/cjs/model/useModelEditor.js +501 -394
  59. package/dist/cjs/model/useModelEditor.js.map +1 -1
  60. package/dist/cjs/model/useModelViewer.js +117 -86
  61. package/dist/cjs/model/useModelViewer.js.map +1 -1
  62. package/dist/cjs/particle/NiceParticleEditor.js +126 -69
  63. package/dist/cjs/particle/NiceParticleEditor.js.map +1 -1
  64. package/dist/cjs/particle/particleEditorUtils.js +64 -27
  65. package/dist/cjs/particle/particleEditorUtils.js.map +1 -1
  66. package/dist/cjs/rendering/NiceCascadedShadows.js +35 -23
  67. package/dist/cjs/rendering/NiceCascadedShadows.js.map +1 -1
  68. package/dist/cjs/rendering/NiceRenderExport.js +26 -12
  69. package/dist/cjs/rendering/NiceRenderExport.js.map +1 -1
  70. package/dist/cjs/rendering/NiceSSAO.js +28 -23
  71. package/dist/cjs/rendering/NiceSSAO.js.map +1 -1
  72. package/dist/cjs/rendering/NiceSSR.js +22 -18
  73. package/dist/cjs/rendering/NiceSSR.js.map +1 -1
  74. package/dist/cjs/rendering/NiceWebGPURenderer.js +60 -37
  75. package/dist/cjs/rendering/NiceWebGPURenderer.js.map +1 -1
  76. package/dist/cjs/ui/dist/NiceErrorBoundary-D75yr_WE.js +572 -0
  77. package/dist/cjs/ui/dist/NiceErrorBoundary-D75yr_WE.js.map +1 -0
  78. package/dist/cjs/ui/dist/NiceForm-CKoJA6NG.js +4979 -0
  79. package/dist/cjs/ui/dist/NiceForm-CKoJA6NG.js.map +1 -0
  80. package/dist/cjs/ui/dist/NiceModal-1QX7NhyH.js +98 -0
  81. package/dist/cjs/ui/dist/NiceModal-1QX7NhyH.js.map +1 -0
  82. package/dist/cjs/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js +5244 -0
  83. package/dist/cjs/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js.map +1 -0
  84. package/dist/cjs/ui/dist/NicePagination-DbE-uOkl.js +174 -0
  85. package/dist/cjs/ui/dist/NicePagination-DbE-uOkl.js.map +1 -0
  86. package/dist/cjs/ui/dist/NicePinCodeInput-B8cI8zu8.js +10459 -0
  87. package/dist/cjs/ui/dist/NicePinCodeInput-B8cI8zu8.js.map +1 -0
  88. package/dist/cjs/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js +6313 -0
  89. package/dist/cjs/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js.map +1 -0
  90. package/dist/cjs/ui/dist/NiceTabs-DzLHzwuA.js +1639 -0
  91. package/dist/cjs/ui/dist/NiceTabs-DzLHzwuA.js.map +1 -0
  92. package/dist/cjs/ui/dist/NiceWindow-DeC83yfE.js +807 -0
  93. package/dist/cjs/ui/dist/NiceWindow-DeC83yfE.js.map +1 -0
  94. package/dist/cjs/ui/dist/charts-BAS21jkC.js +3833 -0
  95. package/dist/cjs/ui/dist/charts-BAS21jkC.js.map +1 -0
  96. package/dist/cjs/ui/dist/core-Da43q-pO.js +11683 -0
  97. package/dist/cjs/ui/dist/core-Da43q-pO.js.map +1 -0
  98. package/dist/cjs/ui/dist/index-pAuGTbuB.js +28876 -0
  99. package/dist/cjs/ui/dist/index-pAuGTbuB.js.map +1 -0
  100. package/dist/cjs/uv/NiceUVEditor.js +115 -86
  101. package/dist/cjs/uv/NiceUVEditor.js.map +1 -1
  102. package/dist/cjs/uv/uvEditorUtils.js +41 -23
  103. package/dist/cjs/uv/uvEditorUtils.js.map +1 -1
  104. package/dist/esm/collaborative/collaborativeScene.js +16 -8
  105. package/dist/esm/collaborative/collaborativeScene.js.map +1 -1
  106. package/dist/esm/dance/DanceBridge.js +55 -20
  107. package/dist/esm/dance/DanceBridge.js.map +1 -1
  108. package/dist/esm/dance/DanceScoreEngine.js +29 -15
  109. package/dist/esm/dance/DanceScoreEngine.js.map +1 -1
  110. package/dist/esm/dance/PoseDetector.js +73 -30
  111. package/dist/esm/dance/PoseDetector.js.map +1 -1
  112. package/dist/esm/material/NiceMaterialEditor.js +115 -72
  113. package/dist/esm/material/NiceMaterialEditor.js.map +1 -1
  114. package/dist/esm/material/materialEditorUtils.js +86 -55
  115. package/dist/esm/material/materialEditorUtils.js.map +1 -1
  116. package/dist/esm/model/ModelEditor.js +16 -14
  117. package/dist/esm/model/ModelEditor.js.map +1 -1
  118. package/dist/esm/model/ModelEditorLeftPanel.js +21 -15
  119. package/dist/esm/model/ModelEditorLeftPanel.js.map +1 -1
  120. package/dist/esm/model/ModelEditorMenuBar.js +23 -10
  121. package/dist/esm/model/ModelEditorMenuBar.js.map +1 -1
  122. package/dist/esm/model/ModelEditorRightPanel.js +32 -27
  123. package/dist/esm/model/ModelEditorRightPanel.js.map +1 -1
  124. package/dist/esm/model/ModelEditorSubComponents.js +17 -17
  125. package/dist/esm/model/ModelEditorSubComponents.js.map +1 -1
  126. package/dist/esm/model/ModelEditorTimeline.js +12 -11
  127. package/dist/esm/model/ModelEditorTimeline.js.map +1 -1
  128. package/dist/esm/model/ModelEditorToolbar.js +5 -5
  129. package/dist/esm/model/ModelEditorToolbar.js.map +1 -1
  130. package/dist/esm/model/ModelEditorViewport.js +12 -8
  131. package/dist/esm/model/ModelEditorViewport.js.map +1 -1
  132. package/dist/esm/model/ModelViewer.js +8 -7
  133. package/dist/esm/model/ModelViewer.js.map +1 -1
  134. package/dist/esm/model/NiceArmatureEditor.js +36 -13
  135. package/dist/esm/model/NiceArmatureEditor.js.map +1 -1
  136. package/dist/esm/model/NiceMorphTargetEditor.js +34 -13
  137. package/dist/esm/model/NiceMorphTargetEditor.js.map +1 -1
  138. package/dist/esm/model/NiceOctree.js +47 -22
  139. package/dist/esm/model/NiceOctree.js.map +1 -1
  140. package/dist/esm/model/NicePhysicsSimulation.js +51 -13
  141. package/dist/esm/model/NicePhysicsSimulation.js.map +1 -1
  142. package/dist/esm/model/NiceProceduralGeometry.js +94 -24
  143. package/dist/esm/model/NiceProceduralGeometry.js.map +1 -1
  144. package/dist/esm/model/NiceTerrainEditor.js +70 -20
  145. package/dist/esm/model/NiceTerrainEditor.js.map +1 -1
  146. package/dist/esm/model/NiceWeightPainter.js +33 -11
  147. package/dist/esm/model/NiceWeightPainter.js.map +1 -1
  148. package/dist/esm/model/NiceXRPreview.js +72 -26
  149. package/dist/esm/model/NiceXRPreview.js.map +1 -1
  150. package/dist/esm/model/cadModeUtils.js +2 -2
  151. package/dist/esm/model/cadModeUtils.js.map +1 -1
  152. package/dist/esm/model/editorShortcuts.js +69 -35
  153. package/dist/esm/model/editorShortcuts.js.map +1 -1
  154. package/dist/esm/model/modelEditorTypes.js +56 -52
  155. package/dist/esm/model/modelEditorTypes.js.map +1 -1
  156. package/dist/esm/model/modelEditorUtils.js +356 -131
  157. package/dist/esm/model/modelEditorUtils.js.map +1 -1
  158. package/dist/esm/model/simsModeUtils.js +819 -74
  159. package/dist/esm/model/simsModeUtils.js.map +1 -1
  160. package/dist/esm/model/useModelEditor.js +384 -277
  161. package/dist/esm/model/useModelEditor.js.map +1 -1
  162. package/dist/esm/model/useModelViewer.js +56 -25
  163. package/dist/esm/model/useModelViewer.js.map +1 -1
  164. package/dist/esm/particle/NiceParticleEditor.js +116 -59
  165. package/dist/esm/particle/NiceParticleEditor.js.map +1 -1
  166. package/dist/esm/particle/particleEditorUtils.js +64 -27
  167. package/dist/esm/particle/particleEditorUtils.js.map +1 -1
  168. package/dist/esm/rendering/NiceCascadedShadows.js +24 -12
  169. package/dist/esm/rendering/NiceCascadedShadows.js.map +1 -1
  170. package/dist/esm/rendering/NiceRenderExport.js +22 -8
  171. package/dist/esm/rendering/NiceRenderExport.js.map +1 -1
  172. package/dist/esm/rendering/NiceSSAO.js +11 -6
  173. package/dist/esm/rendering/NiceSSAO.js.map +1 -1
  174. package/dist/esm/rendering/NiceSSR.js +9 -5
  175. package/dist/esm/rendering/NiceSSR.js.map +1 -1
  176. package/dist/esm/rendering/NiceWebGPURenderer.js +40 -17
  177. package/dist/esm/rendering/NiceWebGPURenderer.js.map +1 -1
  178. package/dist/esm/ui/dist/NiceErrorBoundary-D75yr_WE.js +563 -0
  179. package/dist/esm/ui/dist/NiceErrorBoundary-D75yr_WE.js.map +1 -0
  180. package/dist/esm/ui/dist/NiceForm-CKoJA6NG.js +4960 -0
  181. package/dist/esm/ui/dist/NiceForm-CKoJA6NG.js.map +1 -0
  182. package/dist/esm/ui/dist/NiceModal-1QX7NhyH.js +96 -0
  183. package/dist/esm/ui/dist/NiceModal-1QX7NhyH.js.map +1 -0
  184. package/dist/esm/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js +5201 -0
  185. package/dist/esm/ui/dist/NiceModuleLifecyclePanel-CMrPbSw9.js.map +1 -0
  186. package/dist/esm/ui/dist/NicePagination-DbE-uOkl.js +172 -0
  187. package/dist/esm/ui/dist/NicePagination-DbE-uOkl.js.map +1 -0
  188. package/dist/esm/ui/dist/NicePinCodeInput-B8cI8zu8.js +10408 -0
  189. package/dist/esm/ui/dist/NicePinCodeInput-B8cI8zu8.js.map +1 -0
  190. package/dist/esm/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js +6296 -0
  191. package/dist/esm/ui/dist/NiceSavedQueryPanel-CZ5bYOe_.js.map +1 -0
  192. package/dist/esm/ui/dist/NiceTabs-DzLHzwuA.js +1630 -0
  193. package/dist/esm/ui/dist/NiceTabs-DzLHzwuA.js.map +1 -0
  194. package/dist/esm/ui/dist/NiceWindow-DeC83yfE.js +796 -0
  195. package/dist/esm/ui/dist/NiceWindow-DeC83yfE.js.map +1 -0
  196. package/dist/esm/ui/dist/charts-BAS21jkC.js +3809 -0
  197. package/dist/esm/ui/dist/charts-BAS21jkC.js.map +1 -0
  198. package/dist/esm/ui/dist/core-Da43q-pO.js +11502 -0
  199. package/dist/esm/ui/dist/core-Da43q-pO.js.map +1 -0
  200. package/dist/esm/ui/dist/index-pAuGTbuB.js +28792 -0
  201. package/dist/esm/ui/dist/index-pAuGTbuB.js.map +1 -0
  202. package/dist/esm/uv/NiceUVEditor.js +91 -62
  203. package/dist/esm/uv/NiceUVEditor.js.map +1 -1
  204. package/dist/esm/uv/uvEditorUtils.js +41 -23
  205. package/dist/esm/uv/uvEditorUtils.js.map +1 -1
  206. package/package.json +2 -2
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var ke = require('react');
4
+ var _e = require('react');
5
+ var ParticleEditor_module = require('./ParticleEditor.module.css.js');
5
6
  var particleEditorTypes = require('./particleEditorTypes.js');
6
7
  var particleEditorUtils = require('./particleEditorUtils.js');
7
- var ParticleEditor_module = require('./ParticleEditor.module.css.js');
8
8
 
9
9
  /* ═══════════════════════════════════════════════════════════════════════════
10
10
  State Reducer
@@ -52,10 +52,11 @@ function particleEditorReducer(state, action) {
52
52
  };
53
53
  }
54
54
  case 'REMOVE_SYSTEM': {
55
- if (state.systems.length <= 1)
55
+ if (state.systems.length <= 1) {
56
56
  return state;
57
+ }
57
58
  const newState = pushToUndoStack(state);
58
- const newSystems = newState.systems.filter(s => s.id !== action.systemId);
59
+ const newSystems = newState.systems.filter((s) => s.id !== action.systemId);
59
60
  return {
60
61
  ...newState,
61
62
  systems: newSystems,
@@ -68,13 +69,14 @@ function particleEditorReducer(state, action) {
68
69
  const newState = pushToUndoStack(state);
69
70
  return {
70
71
  ...newState,
71
- systems: newState.systems.map(s => s.id === action.systemId ? { ...s, ...action.updates } : s),
72
+ systems: newState.systems.map((s) => s.id === action.systemId ? { ...s, ...action.updates } : s),
72
73
  };
73
74
  }
74
75
  case 'DUPLICATE_SYSTEM': {
75
- const system = state.systems.find(s => s.id === action.systemId);
76
- if (!system)
76
+ const system = state.systems.find((s) => s.id === action.systemId);
77
+ if (!system) {
77
78
  return state;
79
+ }
78
80
  const cloned = particleEditorUtils.cloneSystem(system);
79
81
  const newState = pushToUndoStack(state);
80
82
  return {
@@ -91,7 +93,7 @@ function particleEditorReducer(state, action) {
91
93
  return {
92
94
  ...state,
93
95
  expandedModules: state.expandedModules.includes(action.module)
94
- ? state.expandedModules.filter(m => m !== action.module)
96
+ ? state.expandedModules.filter((m) => m !== action.module)
95
97
  : [...state.expandedModules, action.module],
96
98
  };
97
99
  case 'SET_TOOL':
@@ -123,8 +125,9 @@ function particleEditorReducer(state, action) {
123
125
  case 'SET_PREVIEW_MODE':
124
126
  return { ...state, previewMode: action.mode };
125
127
  case 'UNDO': {
126
- if (state.undoStack.length === 0)
128
+ if (state.undoStack.length === 0) {
127
129
  return state;
130
+ }
128
131
  const previous = state.undoStack[state.undoStack.length - 1];
129
132
  return {
130
133
  ...state,
@@ -134,8 +137,9 @@ function particleEditorReducer(state, action) {
134
137
  };
135
138
  }
136
139
  case 'REDO': {
137
- if (state.redoStack.length === 0)
140
+ if (state.redoStack.length === 0) {
138
141
  return state;
142
+ }
139
143
  const next = state.redoStack[state.redoStack.length - 1];
140
144
  return {
141
145
  ...state,
@@ -145,23 +149,27 @@ function particleEditorReducer(state, action) {
145
149
  };
146
150
  }
147
151
  case 'COPY_SYSTEM': {
148
- const system = state.systems.find(s => s.id === action.systemId);
149
- if (!system)
152
+ const system = state.systems.find((s) => s.id === action.systemId);
153
+ if (!system) {
150
154
  return state;
155
+ }
151
156
  return { ...state, clipboard: { ...system } };
152
157
  }
153
158
  case 'COPY_MODULE': {
154
- const system = state.systems.find(s => s.id === action.systemId);
155
- if (!system)
159
+ const system = state.systems.find((s) => s.id === action.systemId);
160
+ if (!system) {
156
161
  return state;
162
+ }
157
163
  const moduleData = system[action.moduleKey];
158
- if (!moduleData)
164
+ if (!moduleData) {
159
165
  return state;
166
+ }
160
167
  return { ...state, clipboard: { [action.moduleKey]: moduleData } };
161
168
  }
162
169
  case 'PASTE_SYSTEM': {
163
- if (!state.clipboard || !state.clipboard.id)
170
+ if (!state.clipboard || !state.clipboard.id) {
164
171
  return state;
172
+ }
165
173
  const pasted = particleEditorUtils.cloneSystem(state.clipboard);
166
174
  const newState = pushToUndoStack(state);
167
175
  return {
@@ -171,19 +179,20 @@ function particleEditorReducer(state, action) {
171
179
  };
172
180
  }
173
181
  case 'PASTE_MODULE': {
174
- if (!state.clipboard || state.clipboard.id)
182
+ if (!state.clipboard || state.clipboard.id) {
175
183
  return state;
184
+ }
176
185
  const newState = pushToUndoStack(state);
177
186
  return {
178
187
  ...newState,
179
- systems: newState.systems.map(s => s.id === action.systemId ? { ...s, ...state.clipboard } : s),
188
+ systems: newState.systems.map((s) => s.id === action.systemId ? { ...s, ...state.clipboard } : s),
180
189
  };
181
190
  }
182
191
  case 'ADD_FORCE': {
183
192
  const newState = pushToUndoStack(state);
184
193
  return {
185
194
  ...newState,
186
- systems: newState.systems.map(s => s.id === action.systemId
195
+ systems: newState.systems.map((s) => s.id === action.systemId
187
196
  ? { ...s, externalForces: [...s.externalForces, action.force] }
188
197
  : s),
189
198
  };
@@ -192,8 +201,8 @@ function particleEditorReducer(state, action) {
192
201
  const newState = pushToUndoStack(state);
193
202
  return {
194
203
  ...newState,
195
- systems: newState.systems.map(s => s.id === action.systemId
196
- ? { ...s, externalForces: s.externalForces.filter(f => f.id !== action.forceId) }
204
+ systems: newState.systems.map((s) => s.id === action.systemId
205
+ ? { ...s, externalForces: s.externalForces.filter((f) => f.id !== action.forceId) }
197
206
  : s),
198
207
  };
199
208
  }
@@ -201,10 +210,10 @@ function particleEditorReducer(state, action) {
201
210
  const newState = pushToUndoStack(state);
202
211
  return {
203
212
  ...newState,
204
- systems: newState.systems.map(s => s.id === action.systemId
213
+ systems: newState.systems.map((s) => s.id === action.systemId
205
214
  ? {
206
215
  ...s,
207
- externalForces: s.externalForces.map(f => f.id === action.forceId ? { ...f, ...action.updates } : f),
216
+ externalForces: s.externalForces.map((f) => f.id === action.forceId ? { ...f, ...action.updates } : f),
208
217
  }
209
218
  : s),
210
219
  };
@@ -213,7 +222,7 @@ function particleEditorReducer(state, action) {
213
222
  const newState = pushToUndoStack(state);
214
223
  return {
215
224
  ...newState,
216
- systems: newState.systems.map(s => s.id === action.systemId
225
+ systems: newState.systems.map((s) => s.id === action.systemId
217
226
  ? { ...s, subEmitters: [...s.subEmitters, action.subEmitter] }
218
227
  : s),
219
228
  };
@@ -222,8 +231,8 @@ function particleEditorReducer(state, action) {
222
231
  const newState = pushToUndoStack(state);
223
232
  return {
224
233
  ...newState,
225
- systems: newState.systems.map(s => s.id === action.systemId
226
- ? { ...s, subEmitters: s.subEmitters.filter(se => se.id !== action.subEmitterId) }
234
+ systems: newState.systems.map((s) => s.id === action.systemId
235
+ ? { ...s, subEmitters: s.subEmitters.filter((se) => se.id !== action.subEmitterId) }
227
236
  : s),
228
237
  };
229
238
  }
@@ -231,7 +240,7 @@ function particleEditorReducer(state, action) {
231
240
  const newState = pushToUndoStack(state);
232
241
  return {
233
242
  ...newState,
234
- systems: newState.systems.map(s => s.id === action.systemId
243
+ systems: newState.systems.map((s) => s.id === action.systemId
235
244
  ? { ...s, emission: { ...s.emission, bursts: [...s.emission.bursts, action.burst] } }
236
245
  : s),
237
246
  };
@@ -240,7 +249,7 @@ function particleEditorReducer(state, action) {
240
249
  const newState = pushToUndoStack(state);
241
250
  return {
242
251
  ...newState,
243
- systems: newState.systems.map(s => s.id === action.systemId
252
+ systems: newState.systems.map((s) => s.id === action.systemId
244
253
  ? {
245
254
  ...s,
246
255
  emission: {
@@ -268,13 +277,13 @@ function particleEditorReducer(state, action) {
268
277
  Hook: useParticleEditor
269
278
  ═══════════════════════════════════════════════════════════════════════════ */
270
279
  function useParticleEditor(initialSystems) {
271
- const [state, dispatch] = ke.useReducer(particleEditorReducer, initialSystems, createInitialState);
280
+ const [state, dispatch] = _e.useReducer(particleEditorReducer, initialSystems, createInitialState);
272
281
  return { state, dispatch };
273
282
  }
274
283
  function SystemListPanel({ systems, selectedId, onSelect, onAdd, onRemove, onDuplicate, onRename, onAddPreset, }) {
275
- const [editingId, setEditingId] = ke.useState(null);
276
- const [editName, setEditName] = ke.useState('');
277
- const [showPresets, setShowPresets] = ke.useState(false);
284
+ const [editingId, setEditingId] = _e.useState(null);
285
+ const [editName, setEditName] = _e.useState('');
286
+ const [showPresets, setShowPresets] = _e.useState(false);
278
287
  const handleStartRename = (system) => {
279
288
  setEditingId(system.id);
280
289
  setEditName(system.name);
@@ -285,10 +294,16 @@ function SystemListPanel({ systems, selectedId, onSelect, onAdd, onRemove, onDup
285
294
  }
286
295
  setEditingId(null);
287
296
  };
288
- return (jsxRuntime.jsxs("div", { className: ParticleEditor_module.systemList, children: [jsxRuntime.jsxs("div", { className: ParticleEditor_module.systemListHeader, children: [jsxRuntime.jsxs("span", { children: ["Systems (", systems.length, ")"] }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.systemListActions, children: [jsxRuntime.jsx("button", { onClick: onAdd, title: "New System", children: "+" }), jsxRuntime.jsx("button", { onClick: () => setShowPresets(!showPresets), title: "Add Preset", children: "\uD83D\uDCCB" })] })] }), showPresets && (jsxRuntime.jsx("div", { className: ParticleEditor_module.presetMenu, children: Object.keys(particleEditorUtils.PARTICLE_PRESETS).map(preset => (jsxRuntime.jsx("button", { className: ParticleEditor_module.presetItem, onClick: () => {
297
+ return (jsxRuntime.jsxs("div", { className: ParticleEditor_module.systemList, children: [jsxRuntime.jsxs("div", { className: ParticleEditor_module.systemListHeader, children: [jsxRuntime.jsxs("span", { children: ["Systems (", systems.length, ")"] }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.systemListActions, children: [jsxRuntime.jsx("button", { onClick: onAdd, title: "New System", children: "+" }), jsxRuntime.jsx("button", { onClick: () => setShowPresets(!showPresets), title: "Add Preset", children: "\uD83D\uDCCB" })] })] }), showPresets && (jsxRuntime.jsx("div", { className: ParticleEditor_module.presetMenu, children: Object.keys(particleEditorUtils.PARTICLE_PRESETS).map((preset) => (jsxRuntime.jsx("button", { className: ParticleEditor_module.presetItem, onClick: () => {
289
298
  onAddPreset(preset);
290
299
  setShowPresets(false);
291
- }, children: preset.charAt(0).toUpperCase() + preset.slice(1) }, preset))) })), jsxRuntime.jsx("div", { className: ParticleEditor_module.systemItems, children: systems.map(system => (jsxRuntime.jsx("div", { className: `${ParticleEditor_module.systemItem} ${selectedId === system.id ? ParticleEditor_module.selected : ''}`, onClick: () => onSelect(system.id), children: editingId === system.id ? (jsxRuntime.jsx("input", { type: "text", value: editName, onChange: e => setEditName(e.target.value), onBlur: handleFinishRename, onKeyDown: e => e.key === 'Enter' && handleFinishRename(), autoFocus: true, className: ParticleEditor_module.renameInput })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: ParticleEditor_module.systemName, onDoubleClick: () => handleStartRename(system), children: system.name }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.systemItemActions, children: [jsxRuntime.jsx("button", { onClick: e => { e.stopPropagation(); onDuplicate(system.id); }, title: "Duplicate", children: "\uD83D\uDCCB" }), jsxRuntime.jsx("button", { onClick: e => { e.stopPropagation(); onRemove(system.id); }, title: "Remove", disabled: systems.length <= 1, children: "\uD83D\uDDD1\uFE0F" })] })] })) }, system.id))) })] }));
300
+ }, children: preset.charAt(0).toUpperCase() + preset.slice(1) }, preset))) })), jsxRuntime.jsx("div", { className: ParticleEditor_module.systemItems, children: systems.map((system) => (jsxRuntime.jsx("div", { className: `${ParticleEditor_module.systemItem} ${selectedId === system.id ? ParticleEditor_module.selected : ''}`, onClick: () => onSelect(system.id), children: editingId === system.id ? (jsxRuntime.jsx("input", { type: "text", value: editName, onChange: (e) => setEditName(e.target.value), onBlur: handleFinishRename, onKeyDown: (e) => e.key === 'Enter' && handleFinishRename(), autoFocus: true, className: ParticleEditor_module.renameInput })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: ParticleEditor_module.systemName, onDoubleClick: () => handleStartRename(system), children: system.name }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.systemItemActions, children: [jsxRuntime.jsx("button", { onClick: (e) => {
301
+ e.stopPropagation();
302
+ onDuplicate(system.id);
303
+ }, title: "Duplicate", children: "\uD83D\uDCCB" }), jsxRuntime.jsx("button", { onClick: (e) => {
304
+ e.stopPropagation();
305
+ onRemove(system.id);
306
+ }, title: "Remove", disabled: systems.length <= 1, children: "\uD83D\uDDD1\uFE0F" })] })] })) }, system.id))) })] }));
292
307
  }
293
308
  function InspectorPanel({ system, expandedModules, selectedModule, onToggleModule, onSelectModule, onUpdateSystem, }) {
294
309
  if (!system) {
@@ -299,7 +314,11 @@ function InspectorPanel({ system, expandedModules, selectedModule, onToggleModul
299
314
  { key: 'emission', hasEnabled: true, enabled: system.emission.enabled },
300
315
  { key: 'shape', hasEnabled: false },
301
316
  { key: 'velocityOverLifetime', hasEnabled: true, enabled: system.velocityOverLifetime.enabled },
302
- { key: 'limitVelocityOverLifetime', hasEnabled: true, enabled: system.limitVelocityOverLifetime.enabled },
317
+ {
318
+ key: 'limitVelocityOverLifetime',
319
+ hasEnabled: true,
320
+ enabled: system.limitVelocityOverLifetime.enabled,
321
+ },
303
322
  { key: 'inheritVelocity', hasEnabled: true, enabled: system.inheritVelocity.enabled },
304
323
  { key: 'forceOverLifetime', hasEnabled: true, enabled: system.forceOverLifetime.enabled },
305
324
  { key: 'colorOverLifetime', hasEnabled: true, enabled: system.colorOverLifetime.enabled },
@@ -313,22 +332,27 @@ function InspectorPanel({ system, expandedModules, selectedModule, onToggleModul
313
332
  { key: 'collision', hasEnabled: true, enabled: system.collision.enabled },
314
333
  { key: 'triggers', hasEnabled: true, enabled: system.triggers.enabled },
315
334
  { key: 'subEmitters', hasEnabled: false },
316
- { key: 'textureSheetAnimation', hasEnabled: true, enabled: system.textureSheetAnimation.enabled },
335
+ {
336
+ key: 'textureSheetAnimation',
337
+ hasEnabled: true,
338
+ enabled: system.textureSheetAnimation.enabled,
339
+ },
317
340
  { key: 'lights', hasEnabled: true, enabled: system.lights.enabled },
318
341
  { key: 'trails', hasEnabled: false },
319
342
  { key: 'renderer', hasEnabled: false },
320
343
  { key: 'material', hasEnabled: false },
321
344
  ];
322
345
  const handleModuleToggle = (key, enabled) => {
323
- onUpdateSystem({ [key]: { ...system[key], enabled } });
346
+ const current = system[key];
347
+ onUpdateSystem({ [key]: { ...current, enabled } });
324
348
  };
325
- return (jsxRuntime.jsxs("div", { className: ParticleEditor_module.inspector, children: [jsxRuntime.jsx("div", { className: ParticleEditor_module.inspectorHeader, children: jsxRuntime.jsx("span", { children: system.name }) }), jsxRuntime.jsx("div", { className: ParticleEditor_module.inspectorModules, children: modules.map(mod => (jsxRuntime.jsxs("div", { className: ParticleEditor_module.moduleSection, children: [jsxRuntime.jsxs("div", { className: `${ParticleEditor_module.moduleHeader} ${selectedModule === mod.key ? ParticleEditor_module.selected : ''}`, onClick: () => onToggleModule(mod.key), children: [jsxRuntime.jsx("span", { className: ParticleEditor_module.moduleIcon, children: expandedModules.includes(mod.key) ? '▼' : '►' }), mod.hasEnabled && (jsxRuntime.jsx("input", { type: "checkbox", checked: mod.enabled, onChange: e => {
349
+ return (jsxRuntime.jsxs("div", { className: ParticleEditor_module.inspector, children: [jsxRuntime.jsx("div", { className: ParticleEditor_module.inspectorHeader, children: jsxRuntime.jsx("span", { children: system.name }) }), jsxRuntime.jsx("div", { className: ParticleEditor_module.inspectorModules, children: modules.map((mod) => (jsxRuntime.jsxs("div", { className: ParticleEditor_module.moduleSection, children: [jsxRuntime.jsxs("div", { className: `${ParticleEditor_module.moduleHeader} ${selectedModule === mod.key ? ParticleEditor_module.selected : ''}`, onClick: () => onToggleModule(mod.key), children: [jsxRuntime.jsx("span", { className: ParticleEditor_module.moduleIcon, children: expandedModules.includes(mod.key) ? '▼' : '►' }), mod.hasEnabled && (jsxRuntime.jsx("input", { type: "checkbox", checked: mod.enabled, onChange: (e) => {
326
350
  e.stopPropagation();
327
351
  handleModuleToggle(mod.key, e.target.checked);
328
352
  }, className: ParticleEditor_module.moduleCheckbox })), jsxRuntime.jsx("span", { className: ParticleEditor_module.moduleName, children: particleEditorTypes.MODULE_NAMES[mod.key] || mod.key })] }), expandedModules.includes(mod.key) && (jsxRuntime.jsx("div", { className: ParticleEditor_module.moduleContent, children: jsxRuntime.jsx(ModuleEditor, { system: system, moduleKey: mod.key, onUpdate: onUpdateSystem }) }))] }, mod.key))) })] }));
329
353
  }
330
354
  function ModuleEditor({ system, moduleKey, onUpdate }) {
331
- const renderDistributionInput = (label, value, onChange) => (jsxRuntime.jsxs("div", { className: ParticleEditor_module.propertyRow, children: [jsxRuntime.jsx("label", { children: label }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.distributionInput, children: [jsxRuntime.jsxs("select", { value: value.type, onChange: e => {
355
+ const renderDistributionInput = (label, value, onChange) => (jsxRuntime.jsxs("div", { className: ParticleEditor_module.propertyRow, children: [jsxRuntime.jsx("label", { children: label }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.distributionInput, children: [jsxRuntime.jsxs("select", { value: value.type, onChange: (e) => {
332
356
  const newType = e.target.value;
333
357
  if (newType === 'constant') {
334
358
  onChange({ type: 'constant', value: value.type === 'constant' ? value.value : 1 });
@@ -337,57 +361,85 @@ function ModuleEditor({ system, moduleKey, onUpdate }) {
337
361
  onChange({ type: 'random', min: 0, max: 1 });
338
362
  }
339
363
  else if (newType === 'curve') {
340
- onChange({ type: 'curve', curve: [{ time: 0, value: 1 }, { time: 1, value: 1 }] });
364
+ onChange({
365
+ type: 'curve',
366
+ curve: [
367
+ { time: 0, value: 1 },
368
+ { time: 1, value: 1 },
369
+ ],
370
+ });
341
371
  }
342
- }, className: ParticleEditor_module.distributionType, children: [jsxRuntime.jsx("option", { value: "constant", children: "Constant" }), jsxRuntime.jsx("option", { value: "random", children: "Random" }), jsxRuntime.jsx("option", { value: "curve", children: "Curve" })] }), value.type === 'constant' && (jsxRuntime.jsx("input", { type: "number", value: value.value, onChange: e => onChange({ ...value, value: parseFloat(e.target.value) || 0 }), className: ParticleEditor_module.numberInput })), value.type === 'random' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("input", { type: "number", value: value.min, onChange: e => onChange({ ...value, min: parseFloat(e.target.value) || 0 }), className: ParticleEditor_module.numberInput, placeholder: "Min" }), jsxRuntime.jsx("input", { type: "number", value: value.max, onChange: e => onChange({ ...value, max: parseFloat(e.target.value) || 0 }), className: ParticleEditor_module.numberInput, placeholder: "Max" })] }))] })] }));
343
- const renderNumberInput = (label, value, onChange, props) => (jsxRuntime.jsxs("div", { className: ParticleEditor_module.propertyRow, children: [jsxRuntime.jsx("label", { children: label }), jsxRuntime.jsx("input", { type: "number", value: value, onChange: e => onChange(parseFloat(e.target.value) || 0), className: ParticleEditor_module.numberInput, ...props })] }));
344
- const renderToggle = (label, value, onChange) => (jsxRuntime.jsxs("div", { className: ParticleEditor_module.propertyRow, children: [jsxRuntime.jsx("label", { children: label }), jsxRuntime.jsx("input", { type: "checkbox", checked: value, onChange: e => onChange(e.target.checked), className: ParticleEditor_module.toggleInput })] }));
345
- const renderSelect = (label, value, options, onChange) => (jsxRuntime.jsxs("div", { className: ParticleEditor_module.propertyRow, children: [jsxRuntime.jsx("label", { children: label }), jsxRuntime.jsx("select", { value: value, onChange: e => onChange(e.target.value), className: ParticleEditor_module.selectInput, children: Object.entries(options).map(([key, name]) => (jsxRuntime.jsx("option", { value: key, children: name }, key))) })] }));
372
+ }, className: ParticleEditor_module.distributionType, children: [jsxRuntime.jsx("option", { value: "constant", children: "Constant" }), jsxRuntime.jsx("option", { value: "random", children: "Random" }), jsxRuntime.jsx("option", { value: "curve", children: "Curve" })] }), value.type === 'constant' && (jsxRuntime.jsx("input", { type: "number", value: value.value, onChange: (e) => onChange({ ...value, value: parseFloat(e.target.value) || 0 }), className: ParticleEditor_module.numberInput })), value.type === 'random' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("input", { type: "number", value: value.min, onChange: (e) => onChange({ ...value, min: parseFloat(e.target.value) || 0 }), className: ParticleEditor_module.numberInput, placeholder: "Min" }), jsxRuntime.jsx("input", { type: "number", value: value.max, onChange: (e) => onChange({ ...value, max: parseFloat(e.target.value) || 0 }), className: ParticleEditor_module.numberInput, placeholder: "Max" })] }))] })] }));
373
+ const renderNumberInput = (label, value, onChange, props) => (jsxRuntime.jsxs("div", { className: ParticleEditor_module.propertyRow, children: [jsxRuntime.jsx("label", { children: label }), jsxRuntime.jsx("input", { type: "number", value: value, onChange: (e) => onChange(parseFloat(e.target.value) || 0), className: ParticleEditor_module.numberInput, ...props })] }));
374
+ const renderToggle = (label, value, onChange) => (jsxRuntime.jsxs("div", { className: ParticleEditor_module.propertyRow, children: [jsxRuntime.jsx("label", { children: label }), jsxRuntime.jsx("input", { type: "checkbox", checked: value, onChange: (e) => onChange(e.target.checked), className: ParticleEditor_module.toggleInput })] }));
375
+ const renderSelect = (label, value, options, onChange) => (jsxRuntime.jsxs("div", { className: ParticleEditor_module.propertyRow, children: [jsxRuntime.jsx("label", { children: label }), jsxRuntime.jsx("select", { value: value, onChange: (e) => onChange(e.target.value), className: ParticleEditor_module.selectInput, children: Object.entries(options).map(([key, name]) => (jsxRuntime.jsx("option", { value: key, children: name }, key))) })] }));
346
376
  switch (moduleKey) {
347
377
  case 'main':
348
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderNumberInput('Duration', system.duration, v => onUpdate({ duration: v }), { min: 0, step: 0.1 }), renderToggle('Looping', system.looping, v => onUpdate({ looping: v })), renderToggle('Prewarm', system.prewarm, v => onUpdate({ prewarm: v })), renderDistributionInput('Start Delay', system.startDelay, v => onUpdate({ startDelay: v })), renderDistributionInput('Start Lifetime', system.startLifetime, v => onUpdate({ startLifetime: v })), renderDistributionInput('Start Speed', system.startSpeed, v => onUpdate({ startSpeed: v })), renderDistributionInput('Start Size', system.startSize, v => onUpdate({ startSize: v })), renderDistributionInput('Start Rotation', system.startRotation, v => onUpdate({ startRotation: v })), renderDistributionInput('Gravity Modifier', system.gravityModifier, v => onUpdate({ gravityModifier: v })), renderSelect('Simulation Space', system.simulationSpace, { local: 'Local', world: 'World', custom: 'Custom' }, v => onUpdate({ simulationSpace: v })), renderNumberInput('Simulation Speed', system.simulationSpeed, v => onUpdate({ simulationSpeed: v }), { min: 0, step: 0.1 }), renderNumberInput('Max Particles', system.maxParticles, v => onUpdate({ maxParticles: v }), { min: 1, step: 1 })] }));
378
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderNumberInput('Duration', system.duration, (v) => onUpdate({ duration: v }), {
379
+ min: 0,
380
+ step: 0.1,
381
+ }), renderToggle('Looping', system.looping, (v) => onUpdate({ looping: v })), renderToggle('Prewarm', system.prewarm, (v) => onUpdate({ prewarm: v })), renderDistributionInput('Start Delay', system.startDelay, (v) => onUpdate({ startDelay: v })), renderDistributionInput('Start Lifetime', system.startLifetime, (v) => onUpdate({ startLifetime: v })), renderDistributionInput('Start Speed', system.startSpeed, (v) => onUpdate({ startSpeed: v })), renderDistributionInput('Start Size', system.startSize, (v) => onUpdate({ startSize: v })), renderDistributionInput('Start Rotation', system.startRotation, (v) => onUpdate({ startRotation: v })), renderDistributionInput('Gravity Modifier', system.gravityModifier, (v) => onUpdate({ gravityModifier: v })), renderSelect('Simulation Space', system.simulationSpace, { local: 'Local', world: 'World', custom: 'Custom' }, (v) => onUpdate({ simulationSpace: v })), renderNumberInput('Simulation Speed', system.simulationSpeed, (v) => onUpdate({ simulationSpeed: v }), { min: 0, step: 0.1 }), renderNumberInput('Max Particles', system.maxParticles, (v) => onUpdate({ maxParticles: v }), { min: 1, step: 1 })] }));
349
382
  case 'emission':
350
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderDistributionInput('Rate over Time', system.emission.rateOverTime, v => onUpdate({ emission: { ...system.emission, rateOverTime: v } })), renderDistributionInput('Rate over Distance', system.emission.rateOverDistance, v => onUpdate({ emission: { ...system.emission, rateOverDistance: v } })), jsxRuntime.jsxs("div", { className: ParticleEditor_module.propertyRow, children: [jsxRuntime.jsxs("label", { children: ["Bursts (", system.emission.bursts.length, ")"] }), jsxRuntime.jsx("button", { className: ParticleEditor_module.addButton, onClick: () => onUpdate({
383
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderDistributionInput('Rate over Time', system.emission.rateOverTime, (v) => onUpdate({ emission: { ...system.emission, rateOverTime: v } })), renderDistributionInput('Rate over Distance', system.emission.rateOverDistance, (v) => onUpdate({ emission: { ...system.emission, rateOverDistance: v } })), jsxRuntime.jsxs("div", { className: ParticleEditor_module.propertyRow, children: [jsxRuntime.jsxs("label", { children: ["Bursts (", system.emission.bursts.length, ")"] }), jsxRuntime.jsx("button", { className: ParticleEditor_module.addButton, onClick: () => onUpdate({
351
384
  emission: {
352
385
  ...system.emission,
353
- bursts: [...system.emission.bursts, {
386
+ bursts: [
387
+ ...system.emission.bursts,
388
+ {
354
389
  time: 0,
355
390
  count: { type: 'constant', value: 30 },
356
391
  cycles: 1,
357
392
  interval: 0.01,
358
393
  probability: 1,
359
- }],
394
+ },
395
+ ],
360
396
  },
361
397
  }), children: "Add Burst" })] })] }));
362
398
  case 'shape':
363
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderSelect('Shape', system.shape.type, particleEditorTypes.EMITTER_SHAPE_NAMES, v => onUpdate({ shape: { ...system.shape, type: v } })), renderToggle('Emit from Shell', system.shape.emitFromShell, v => onUpdate({ shape: { ...system.shape, emitFromShell: v } })), renderToggle('Random Direction', system.shape.randomDirection, v => onUpdate({ shape: { ...system.shape, randomDirection: v } })), (system.shape.type === 'sphere' || system.shape.type === 'hemisphere' ||
364
- system.shape.type === 'cone' || system.shape.type === 'circle') && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderDistributionInput('Radius', system.shape.radius, v => onUpdate({ shape: { ...system.shape, radius: v } })) })), system.shape.type === 'cone' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderNumberInput('Angle', system.shape.angle, v => onUpdate({ shape: { ...system.shape, angle: v } }), { min: 0, max: 90 }), renderNumberInput('Length', system.shape.length, v => onUpdate({ shape: { ...system.shape, length: v } }), { min: 0 })] }))] }));
399
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderSelect('Shape', system.shape.type, particleEditorTypes.EMITTER_SHAPE_NAMES, (v) =>
400
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- writing into discriminated-union variant; runtime narrowed by `type`
401
+ onUpdate({ shape: { ...system.shape, type: v } })), renderToggle('Emit from Shell', system.shape.emitFromShell, (v) => onUpdate({ shape: { ...system.shape, emitFromShell: v } })), renderToggle('Random Direction', system.shape.randomDirection, (v) => onUpdate({ shape: { ...system.shape, randomDirection: v } })), (system.shape.type === 'sphere' ||
402
+ system.shape.type === 'hemisphere' ||
403
+ system.shape.type === 'cone' ||
404
+ system.shape.type === 'circle') && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderDistributionInput('Radius', system.shape.radius, (v) =>
405
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- writing into discriminated-union variant; runtime narrowed by `type`
406
+ onUpdate({ shape: { ...system.shape, radius: v } })) })), system.shape.type === 'cone' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderNumberInput('Angle', system.shape.angle,
407
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- writing into discriminated-union variant; runtime narrowed by `type`
408
+ (v) => onUpdate({ shape: { ...system.shape, angle: v } }), { min: 0, max: 90 }), renderNumberInput('Length', system.shape.length,
409
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- writing into discriminated-union variant; runtime narrowed by `type`
410
+ (v) => onUpdate({ shape: { ...system.shape, length: v } }), { min: 0 })] }))] }));
365
411
  case 'renderer':
366
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderSelect('Render Mode', system.renderer.type, particleEditorTypes.RENDER_MODE_NAMES, v => onUpdate({ renderer: { ...system.renderer, type: v } })), renderSelect('Sort Mode', system.renderer.sortMode, {
412
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderSelect('Render Mode', system.renderer.type, particleEditorTypes.RENDER_MODE_NAMES, (v) =>
413
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- writing into discriminated-union variant; runtime narrowed by `type`
414
+ onUpdate({ renderer: { ...system.renderer, type: v } })), renderSelect('Sort Mode', system.renderer.sortMode, {
367
415
  none: 'None',
368
416
  by_distance: 'By Distance',
369
417
  oldest_in_front: 'Oldest in Front',
370
418
  youngest_in_front: 'Youngest in Front',
371
- }, v => onUpdate({ renderer: { ...system.renderer, sortMode: v } }))] }));
419
+ }, (v) => onUpdate({ renderer: { ...system.renderer, sortMode: v } }))] }));
372
420
  case 'material':
373
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderSelect('Shading', system.material.shading, { unlit: 'Unlit', lit: 'Lit' }, v => onUpdate({ material: { ...system.material, shading: v } })), renderSelect('Blend Mode', system.material.blendMode, particleEditorTypes.BLEND_MODE_NAMES, v => onUpdate({ material: { ...system.material, blendMode: v } }))] }));
421
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [renderSelect('Shading', system.material.shading, { unlit: 'Unlit', lit: 'Lit' }, (v) => onUpdate({ material: { ...system.material, shading: v } })), renderSelect('Blend Mode', system.material.blendMode,
422
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- BLEND_MODE_NAMES is keyed by ParticleBlendMode but renderSelect is generic
423
+ particleEditorTypes.BLEND_MODE_NAMES, (v) => onUpdate({ material: { ...system.material, blendMode: v } }))] }));
374
424
  default:
375
- return (jsxRuntime.jsx("div", { className: ParticleEditor_module.moduleNotImplemented, children: "Module editor not yet implemented" }));
425
+ return jsxRuntime.jsx("div", { className: ParticleEditor_module.moduleNotImplemented, children: "Module editor not yet implemented" });
376
426
  }
377
427
  }
378
428
  function Toolbar({ isPlaying, isPaused, playbackSpeed, currentTime, canUndo, canRedo, showGrid, showBounds, showEmitterShape, viewMode, onPlay, onPause, onStop, onRestart, onSpeedChange, onUndo, onRedo, onToggleGrid, onToggleBounds, onToggleEmitterShape, onViewModeChange, onNew, onExport, onImport, }) {
379
- return (jsxRuntime.jsxs("div", { className: ParticleEditor_module.toolbar, children: [jsxRuntime.jsxs("div", { className: ParticleEditor_module.toolbarGroup, children: [jsxRuntime.jsx("button", { onClick: onNew, title: "New Project", children: "\uD83D\uDCC4" }), jsxRuntime.jsx("button", { onClick: onImport, title: "Import", children: "\uD83D\uDCC2" }), jsxRuntime.jsx("button", { onClick: onExport, title: "Export", children: "\uD83D\uDCBE" })] }), jsxRuntime.jsx("div", { className: ParticleEditor_module.toolbarSeparator }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.toolbarGroup, children: [jsxRuntime.jsx("button", { onClick: onUndo, disabled: !canUndo, title: "Undo", children: "\u21A9\uFE0F" }), jsxRuntime.jsx("button", { onClick: onRedo, disabled: !canRedo, title: "Redo", children: "\u21AA\uFE0F" })] }), jsxRuntime.jsx("div", { className: ParticleEditor_module.toolbarSeparator }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.toolbarGroup, children: [isPlaying && !isPaused ? (jsxRuntime.jsx("button", { onClick: onPause, title: "Pause", children: "\u23F8\uFE0F" })) : (jsxRuntime.jsx("button", { onClick: onPlay, title: "Play", children: "\u25B6\uFE0F" })), jsxRuntime.jsx("button", { onClick: onStop, title: "Stop", children: "\u23F9\uFE0F" }), jsxRuntime.jsx("button", { onClick: onRestart, title: "Restart", children: "\uD83D\uDD04" }), jsxRuntime.jsxs("select", { value: playbackSpeed, onChange: e => onSpeedChange(parseFloat(e.target.value)), className: ParticleEditor_module.speedSelect, title: "Playback Speed", children: [jsxRuntime.jsx("option", { value: 0.25, children: "0.25x" }), jsxRuntime.jsx("option", { value: 0.5, children: "0.5x" }), jsxRuntime.jsx("option", { value: 1, children: "1x" }), jsxRuntime.jsx("option", { value: 2, children: "2x" }), jsxRuntime.jsx("option", { value: 4, children: "4x" })] }), jsxRuntime.jsxs("span", { className: ParticleEditor_module.timeDisplay, children: [currentTime.toFixed(2), "s"] })] }), jsxRuntime.jsx("div", { className: ParticleEditor_module.toolbarSeparator }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.toolbarGroup, children: [jsxRuntime.jsx("button", { onClick: onToggleGrid, className: showGrid ? ParticleEditor_module.active : '', title: "Toggle Grid", children: "#" }), jsxRuntime.jsx("button", { onClick: onToggleBounds, className: showBounds ? ParticleEditor_module.active : '', title: "Toggle Bounds", children: "\u2B1C" }), jsxRuntime.jsx("button", { onClick: onToggleEmitterShape, className: showEmitterShape ? ParticleEditor_module.active : '', title: "Toggle Emitter Shape", children: "\uD83D\uDD36" })] }), jsxRuntime.jsx("div", { className: ParticleEditor_module.toolbarSeparator }), jsxRuntime.jsx("div", { className: ParticleEditor_module.toolbarGroup, children: ['3d', 'top', 'side', 'front'].map(mode => (jsxRuntime.jsx("button", { onClick: () => onViewModeChange(mode), className: viewMode === mode ? ParticleEditor_module.active : '', title: mode.toUpperCase(), children: mode === '3d' ? '🎥' : mode.charAt(0).toUpperCase() }, mode))) })] }));
429
+ return (jsxRuntime.jsxs("div", { className: ParticleEditor_module.toolbar, children: [jsxRuntime.jsxs("div", { className: ParticleEditor_module.toolbarGroup, children: [jsxRuntime.jsx("button", { onClick: onNew, title: "New Project", children: "\uD83D\uDCC4" }), jsxRuntime.jsx("button", { onClick: onImport, title: "Import", children: "\uD83D\uDCC2" }), jsxRuntime.jsx("button", { onClick: onExport, title: "Export", children: "\uD83D\uDCBE" })] }), jsxRuntime.jsx("div", { className: ParticleEditor_module.toolbarSeparator }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.toolbarGroup, children: [jsxRuntime.jsx("button", { onClick: onUndo, disabled: !canUndo, title: "Undo", children: "\u21A9\uFE0F" }), jsxRuntime.jsx("button", { onClick: onRedo, disabled: !canRedo, title: "Redo", children: "\u21AA\uFE0F" })] }), jsxRuntime.jsx("div", { className: ParticleEditor_module.toolbarSeparator }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.toolbarGroup, children: [isPlaying && !isPaused ? (jsxRuntime.jsx("button", { onClick: onPause, title: "Pause", children: "\u23F8\uFE0F" })) : (jsxRuntime.jsx("button", { onClick: onPlay, title: "Play", children: "\u25B6\uFE0F" })), jsxRuntime.jsx("button", { onClick: onStop, title: "Stop", children: "\u23F9\uFE0F" }), jsxRuntime.jsx("button", { onClick: onRestart, title: "Restart", children: "\uD83D\uDD04" }), jsxRuntime.jsxs("select", { value: playbackSpeed, onChange: (e) => onSpeedChange(parseFloat(e.target.value)), className: ParticleEditor_module.speedSelect, title: "Playback Speed", children: [jsxRuntime.jsx("option", { value: 0.25, children: "0.25x" }), jsxRuntime.jsx("option", { value: 0.5, children: "0.5x" }), jsxRuntime.jsx("option", { value: 1, children: "1x" }), jsxRuntime.jsx("option", { value: 2, children: "2x" }), jsxRuntime.jsx("option", { value: 4, children: "4x" })] }), jsxRuntime.jsxs("span", { className: ParticleEditor_module.timeDisplay, children: [currentTime.toFixed(2), "s"] })] }), jsxRuntime.jsx("div", { className: ParticleEditor_module.toolbarSeparator }), jsxRuntime.jsxs("div", { className: ParticleEditor_module.toolbarGroup, children: [jsxRuntime.jsx("button", { onClick: onToggleGrid, className: showGrid ? ParticleEditor_module.active : '', title: "Toggle Grid", children: "#" }), jsxRuntime.jsx("button", { onClick: onToggleBounds, className: showBounds ? ParticleEditor_module.active : '', title: "Toggle Bounds", children: "\u2B1C" }), jsxRuntime.jsx("button", { onClick: onToggleEmitterShape, className: showEmitterShape ? ParticleEditor_module.active : '', title: "Toggle Emitter Shape", children: "\uD83D\uDD36" })] }), jsxRuntime.jsx("div", { className: ParticleEditor_module.toolbarSeparator }), jsxRuntime.jsx("div", { className: ParticleEditor_module.toolbarGroup, children: ['3d', 'top', 'side', 'front'].map((mode) => (jsxRuntime.jsx("button", { onClick: () => onViewModeChange(mode), className: viewMode === mode ? ParticleEditor_module.active : '', title: mode.toUpperCase(), children: mode === '3d' ? '🎥' : mode.charAt(0).toUpperCase() }, mode))) })] }));
380
430
  }
381
431
  function PreviewPanel({ systems, isPlaying, isPaused, currentTime, showGrid, showEmitterShape, }) {
382
- const canvasRef = ke.useRef(null);
432
+ const canvasRef = _e.useRef(null);
383
433
  // Simple preview rendering (placeholder - real implementation would use Three.js)
384
- ke.useEffect(() => {
434
+ _e.useEffect(() => {
385
435
  const canvas = canvasRef.current;
386
- if (!canvas)
436
+ if (!canvas) {
387
437
  return;
438
+ }
388
439
  const ctx = canvas.getContext('2d');
389
- if (!ctx)
440
+ if (!ctx) {
390
441
  return;
442
+ }
391
443
  const width = canvas.width;
392
444
  const height = canvas.height;
393
445
  const centerX = width / 2;
@@ -431,8 +483,8 @@ function PreviewPanel({ systems, isPlaying, isPaused, currentTime, showGrid, sho
431
483
  const angle = seed * Math.PI * 2 + currentTime;
432
484
  const distance = 30 + ((currentTime * 50 + i * 10) % 150);
433
485
  const x = centerX + Math.cos(angle) * distance;
434
- const y = centerY - Math.sin(angle) * distance * 0.5 - (currentTime * 30 + i * 3) % 150;
435
- const alpha = 1 - (distance / 180);
486
+ const y = centerY - Math.sin(angle) * distance * 0.5 - ((currentTime * 30 + i * 3) % 150);
487
+ const alpha = 1 - distance / 180;
436
488
  const size = 3 + Math.sin(seed * 10 + currentTime) * 2;
437
489
  ctx.beginPath();
438
490
  ctx.arc(x, y, size, 0, Math.PI * 2);
@@ -448,19 +500,20 @@ function PreviewPanel({ systems, isPlaying, isPaused, currentTime, showGrid, sho
448
500
  ═══════════════════════════════════════════════════════════════════════════ */
449
501
  function NiceParticleEditor({ systems: initialSystems, onSystemsChange, onPlay, onPause, onStop, customTextures, customMeshes, width = '100%', height = '600px', readOnly = false, showToolbar = true, showSystemList = true, showInspector = true, showPreview = true, showTimeline = true, theme = 'dark', className, }) {
450
502
  const { state, dispatch } = useParticleEditor(initialSystems);
451
- const animationFrameRef = ke.useRef();
452
- const selectedSystem = ke.useMemo(() => state.systems.find(s => s.id === state.selectedSystemId) || null, [state.systems, state.selectedSystemId]);
503
+ const animationFrameRef = _e.useRef();
504
+ const selectedSystem = _e.useMemo(() => state.systems.find((s) => s.id === state.selectedSystemId) || null, [state.systems, state.selectedSystemId]);
453
505
  // Notify parent of changes
454
- ke.useEffect(() => {
506
+ _e.useEffect(() => {
455
507
  onSystemsChange === null || onSystemsChange === void 0 ? void 0 : onSystemsChange(state.systems);
456
508
  }, [state.systems, onSystemsChange]);
457
509
  // Animation loop
458
- ke.useEffect(() => {
459
- if (!state.isPlaying || state.isPaused)
510
+ _e.useEffect(() => {
511
+ if (!state.isPlaying || state.isPaused) {
460
512
  return;
513
+ }
461
514
  let lastTime = performance.now();
462
515
  const animate = (time) => {
463
- const dt = (time - lastTime) / 1000 * state.playbackSpeed;
516
+ const dt = ((time - lastTime) / 1000) * state.playbackSpeed;
464
517
  lastTime = time;
465
518
  dispatch({ type: 'SET_CURRENT_TIME', time: state.currentTime + dt });
466
519
  // Check if we need to loop
@@ -495,8 +548,9 @@ function NiceParticleEditor({ systems: initialSystems, onSystemsChange, onPlay,
495
548
  input.onchange = async (e) => {
496
549
  var _a;
497
550
  const file = (_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0];
498
- if (!file)
551
+ if (!file) {
499
552
  return;
553
+ }
500
554
  const text = await file.text();
501
555
  const systems = particleEditorUtils.importSystemsFromJSON(text);
502
556
  if (systems) {
@@ -514,7 +568,10 @@ function NiceParticleEditor({ systems: initialSystems, onSystemsChange, onPlay,
514
568
  }, onStop: () => {
515
569
  dispatch({ type: 'STOP' });
516
570
  onStop === null || onStop === void 0 ? void 0 : onStop();
517
- }, onRestart: () => dispatch({ type: 'RESTART' }), onSpeedChange: speed => dispatch({ type: 'SET_PLAYBACK_SPEED', speed }), onUndo: () => dispatch({ type: 'UNDO' }), onRedo: () => dispatch({ type: 'REDO' }), onToggleGrid: () => dispatch({ type: 'TOGGLE_GRID' }), onToggleBounds: () => dispatch({ type: 'TOGGLE_BOUNDS' }), onToggleEmitterShape: () => dispatch({ type: 'TOGGLE_EMITTER_SHAPE' }), onViewModeChange: mode => dispatch({ type: 'SET_VIEW_MODE', mode }), onNew: () => dispatch({ type: 'NEW_PROJECT' }), onExport: handleExport, onImport: handleImport })), jsxRuntime.jsxs("div", { className: ParticleEditor_module.editorBody, children: [showSystemList && (jsxRuntime.jsx(SystemListPanel, { systems: state.systems, selectedId: state.selectedSystemId, onSelect: id => dispatch({ type: 'SELECT_SYSTEM', systemId: id }), onAdd: () => dispatch({ type: 'ADD_SYSTEM', system: particleEditorUtils.createDefaultSystem() }), onRemove: id => dispatch({ type: 'REMOVE_SYSTEM', systemId: id }), onDuplicate: id => dispatch({ type: 'DUPLICATE_SYSTEM', systemId: id }), onRename: (id, name) => dispatch({ type: 'UPDATE_SYSTEM', systemId: id, updates: { name } }), onAddPreset: preset => dispatch({ type: 'ADD_SYSTEM', system: particleEditorUtils.applyPreset(preset) }) })), showPreview && (jsxRuntime.jsx(PreviewPanel, { systems: state.systems, isPlaying: state.isPlaying, isPaused: state.isPaused, currentTime: state.currentTime, showGrid: state.showGrid, showEmitterShape: state.showEmitterShape })), showInspector && (jsxRuntime.jsx(InspectorPanel, { system: selectedSystem, expandedModules: state.expandedModules, selectedModule: state.selectedModule, onToggleModule: module => dispatch({ type: 'TOGGLE_MODULE', module }), onSelectModule: module => dispatch({ type: 'SELECT_MODULE', module }), onUpdateSystem: updates => {
571
+ }, onRestart: () => dispatch({ type: 'RESTART' }), onSpeedChange: (speed) => dispatch({ type: 'SET_PLAYBACK_SPEED', speed }), onUndo: () => dispatch({ type: 'UNDO' }), onRedo: () => dispatch({ type: 'REDO' }), onToggleGrid: () => dispatch({ type: 'TOGGLE_GRID' }), onToggleBounds: () => dispatch({ type: 'TOGGLE_BOUNDS' }), onToggleEmitterShape: () => dispatch({ type: 'TOGGLE_EMITTER_SHAPE' }), onViewModeChange: (mode) => dispatch({ type: 'SET_VIEW_MODE', mode }), onNew: () => dispatch({ type: 'NEW_PROJECT' }), onExport: handleExport, onImport: handleImport })), jsxRuntime.jsxs("div", { className: ParticleEditor_module.editorBody, children: [showSystemList && (jsxRuntime.jsx(SystemListPanel, { systems: state.systems, selectedId: state.selectedSystemId, onSelect: (id) => dispatch({ type: 'SELECT_SYSTEM', systemId: id }), onAdd: () => dispatch({ type: 'ADD_SYSTEM', system: particleEditorUtils.createDefaultSystem() }), onRemove: (id) => dispatch({ type: 'REMOVE_SYSTEM', systemId: id }), onDuplicate: (id) => dispatch({ type: 'DUPLICATE_SYSTEM', systemId: id }), onRename: (id, name) => dispatch({ type: 'UPDATE_SYSTEM', systemId: id, updates: { name } }), onAddPreset: (preset) => dispatch({
572
+ type: 'ADD_SYSTEM',
573
+ system: particleEditorUtils.applyPreset(preset),
574
+ }) })), showPreview && (jsxRuntime.jsx(PreviewPanel, { systems: state.systems, isPlaying: state.isPlaying, isPaused: state.isPaused, currentTime: state.currentTime, showGrid: state.showGrid, showEmitterShape: state.showEmitterShape })), showInspector && (jsxRuntime.jsx(InspectorPanel, { system: selectedSystem, expandedModules: state.expandedModules, selectedModule: state.selectedModule, onToggleModule: (module) => dispatch({ type: 'TOGGLE_MODULE', module }), onSelectModule: (module) => dispatch({ type: 'SELECT_MODULE', module }), onUpdateSystem: (updates) => {
518
575
  if (state.selectedSystemId) {
519
576
  dispatch({ type: 'UPDATE_SYSTEM', systemId: state.selectedSystemId, updates });
520
577
  }