1import { r as reactExports, j as jsxRuntimeExports } from "./vendor-react-Bay9Y7Lb.js"; 2import { P as PERCUSSION_INSTRUMENTS, g as getInstrumentDef, a as PROGRAM_SPECIFIC_ACTIONS, D as DEFAULT_HOLD_STYLE_ACTIONS, b as DEFAULT_IDLE_ACTIONS, S as SouthparkCharacter, B as BASE_ANIMALS } from "./SouthparkCharacter-BNwA9Wd0.js"; 3import { I as INSTRUMENT_CATEGORIES, k as GM_INSTRUMENTS } from "./utils-BYCVoSTN.js"; 4import { df as SlidersVertical, bg as Music, bL as Clock, cL as RefreshCw, cc as Save, bf as Search, c3 as RotateCcw, bi as Sparkles, ce as Plus, b5 as Trash2, bZ as Pause, bU as Play } from "./vendor-dVNaLJx_.js"; 5import "./IkMath-D6fi1ppd.js"; 6import "./vendor-framer-C8eEgkdL.js"; 7import "./index-D0Bmh-UX.js"; 8import "./vendor-i18n-R-bMoYp_.js"; 9const TARGET_OPTIONS = [ 10 { id: "targetL", label: "Left Arm (Target X/Y)", group: "Limbs" }, 11 { id: "targetR", label: "Right Arm (Target X/Y)", group: "Limbs" }, 12 { id: "wristTiltL", label: "Left Wrist Tilt (Deg)", group: "Limbs" }, 13 { id: "wristTiltR", label: "Right Wrist Tilt (Deg)", group: "Limbs" }, 14 { id: "bodyBounce", label: "Body Vertical Bounce (Y)", group: "Torso" }, 15 { id: "bodySquash", label: "Body Squash/Stretch", group: "Torso" }, 16 { id: "bodySwayX", label: "Body Lateral Sway (X)", group: "Torso" }, 17 { id: "headTilt", label: "Head Rotation Tilt (Deg)", group: "Head & Mouth" }, 18 { id: "headBobY", label: "Head Bob (Y)", group: "Head & Mouth" }, 19 { id: "mouthOpen", label: "Mouth Open / Blow (0-1)", group: "Head & Mouth" }, 20 { id: "instrumentRotation", label: "Instrument Tilt (Deg)", group: "Instrument" } 21]; 22const SouthparkActionsStudio = ({ 23 actionsConfig, 24 onChangeActionsConfig, 25 instrumentsConfig, 26 charactersConfig, 27 costumesConfig, 28 onSave, 29 isSaving 30}) => { 31 const [studioMode, setStudioMode] = reactExports.useState("playing"); 32 const [selectedProgram, setSelectedProgram] = reactExports.useState(0); 33 const [searchQuery, setSearchQuery] = reactExports.useState(""); 34 const [selectedCategory, setSelectedCategory] = reactExports.useState("all"); 35 const [editScope, setEditScope] = reactExports.useState("holdStyle"); 36 const [previewAnimal, setPreviewAnimal] = reactExports.useState("fox"); 37 const [isSimulating, setIsSimulating] = reactExports.useState(true); 38 const [simVelocity, setSimVelocity] = reactExports.useState(100); 39 const [simPitch, setSimPitch] = reactExports.useState(60); 40 const [simBpm, setSimBpm] = reactExports.useState(120); 41 const [notePulsing, setNotePulsing] = reactExports.useState(true); 42 const [isNoteActive, setIsNoteActive] = reactExports.useState(true); 43 const [showSkeleton, setShowSkeleton] = reactExports.useState(false); 44 const [skeletonOnly, setSkeletonOnly] = reactExports.useState(false); 45 const [simTime, setSimTime] = reactExports.useState(0); 46 const [activeTestingIdleId, setActiveTestingIdleId] = reactExports.useState(null); 47 const percKits = reactExports.useMemo(() => { 48 return Object.entries(PERCUSSION_INSTRUMENTS).map(([key, def]) => ({ 49 id: def.program, 50 name: `${def.name} (${key})`, 51 percRole: key, 52 isPercussion: true 53 })); 54 }, []); 55 const allInstruments = reactExports.useMemo(() => { 56 const gm = GM_INSTRUMENTS.map((name, idx) => ({ 57 id: idx, 58 name: `${idx}: ${name}`, 59 percRole: void 0, 60 isPercussion: false 61 })); 62 return [...gm, ...percKits]; 63 }, [percKits]); 64 const filteredInstruments = reactExports.useMemo(() => { 65 return allInstruments.filter((inst) => { 66 const matchesSearch = inst.name.toLowerCase().includes(searchQuery.toLowerCase()) || inst.id.toString().includes(searchQuery); 67 if (!matchesSearch) return false; 68 if (selectedCategory === "all") return true; 69 if (selectedCategory === "percussion") return inst.isPercussion; 70 if (inst.isPercussion) return false; 71 const cat = INSTRUMENT_CATEGORIES.find((c) => inst.id >= c.start && inst.id <= c.end); 72 return cat ? cat.name.toLowerCase().includes(selectedCategory.toLowerCase()) : false; 73 }); 74 }, [allInstruments, searchQuery, selectedCategory]); 75 const selectedInstDef = reactExports.useMemo(() => { 76 return getInstrumentDef(selectedProgram, selectedProgram < 0); 77 }, [selectedProgram]); 78 const holdStyle = selectedInstDef.holdStyle || "standard"; 79 const currentActions = reactExports.useMemo(() => { 80 var _a, _b; 81 if (editScope === "program") { 82 if ((_a = actionsConfig.programActions) == null ? void 0 : _a[selectedProgram]) { 83 return actionsConfig.programActions[selectedProgram]; 84 } 85 if (PROGRAM_SPECIFIC_ACTIONS[selectedProgram]) { 86 return PROGRAM_SPECIFIC_ACTIONS[selectedProgram]; 87 } 88 } 89 return ((_b = actionsConfig.holdStyleActions) == null ? void 0 : _b[holdStyle]) || DEFAULT_HOLD_STYLE_ACTIONS[holdStyle] || DEFAULT_HOLD_STYLE_ACTIONS.standard; 90 }, [editScope, selectedProgram, holdStyle, actionsConfig]); 91 const idleActionsList = reactExports.useMemo(() => { 92 return actionsConfig.idleActions || DEFAULT_IDLE_ACTIONS; 93 }, [actionsConfig.idleActions]); 94 reactExports.useEffect(() => { 95 if (!isSimulating) return; 96 let animationFrameId; 97 let lastTimestamp = performance.now(); 98 const tick = (now) => { 99 const deltaSec = (now - lastTimestamp) / 1e3; 100 lastTimestamp = now; 101 setSimTime((prev) => prev + deltaSec); 102 if (notePulsing) { 103 const bps = simBpm / 60; 104 const beatPhase = (simTime + deltaSec) * bps * Math.PI * 2; 105 const stroke = Math.sin(beatPhase); 106 setIsNoteActive(stroke > -0.2); 107 } 108 animationFrameId = requestAnimationFrame(tick); 109 }; 110 animationFrameId = requestAnimationFrame(tick); 111 return () => cancelAnimationFrame(animationFrameId); 112 }, [isSimulating, simTime, notePulsing, simBpm]);
113 const handleUpdateChannel = (actionIndex, channelIndex, updatedChannel) => { 114 const clonedActions = JSON.parse(JSON.stringify(currentActions)); 115 if (!clonedActions[actionIndex]) return; 116 clonedActions[actionIndex].channels[channelIndex] = updatedChannel; 117 if (editScope === "program") { 118 onChangeActionsConfig({ 119 ...actionsConfig, 120 programActions: { 121 ...actionsConfig.programActions || {}, 122 [selectedProgram]: clonedActions 123 } 124 }); 125 } else { 126 onChangeActionsConfig({ 127 ...actionsConfig, 128 holdStyleActions: { 129 ...actionsConfig.holdStyleActions || {}, 130 [holdStyle]: clonedActions 131 } 132 }); 133 } 134 }; 135 const handleAddChannel = (actionIndex) => { 136 const clonedActions = JSON.parse(JSON.stringify(currentActions)); 137 if (!clonedActions[actionIndex]) return; 138 clonedActions[actionIndex].channels.push({ 139 target: "targetR", 140 driver: "wave", 141 wave: { 142 waveform: "sine", 143 frequency: 2, 144 amplitude: 5, 145 amplitudeBase: 0, 146 phase: 0, 147 axis: "y", 148 activeOnly: true 149 } 150 }); 151 if (editScope === "program") { 152 onChangeActionsConfig({ 153 ...actionsConfig, 154 programActions: { 155 ...actionsConfig.programActions || {}, 156 [selectedProgram]: clonedActions 157 } 158 }); 159 } else { 160 onChangeActionsConfig({ 161 ...actionsConfig, 162 holdStyleActions: { 163 ...actionsConfig.holdStyleActions || {}, 164 [holdStyle]: clonedActions 165 } 166 }); 167 } 168 }; 169 const handleRemoveChannel = (actionIndex, channelIndex) => { 170 const clonedActions = JSON.parse(JSON.stringify(currentActions)); 171 if (!clonedActions[actionIndex]) return; 172 clonedActions[actionIndex].channels.splice(channelIndex, 1); 173 if (editScope === "program") { 174 onChangeActionsConfig({ 175 ...actionsConfig, 176 programActions: { 177 ...actionsConfig.programActions || {}, 178 [selectedProgram]: clonedActions 179 } 180 }); 181 } else { 182 onChangeActionsConfig({ 183 ...actionsConfig, 184 holdStyleActions: { 185 ...actionsConfig.holdStyleActions || {}, 186 [holdStyle]: clonedActions 187 } 188 }); 189 } 190 }; 191 const handleResetActionToDefault = () => { 192 if (editScope === "program") { 193 const next = { ...actionsConfig.programActions || {} }; 194 delete next[selectedProgram]; 195 onChangeActionsConfig({ 196 ...actionsConfig, 197 programActions: next 198 }); 199 } else { 200 const next = { ...actionsConfig.holdStyleActions || {} }; 201 delete next[holdStyle]; 202 onChangeActionsConfig({ 203 ...actionsConfig, 204 holdStyleActions: next 205 }); 206 } 207 }; 208 const handleUpdateIdleSchedule = (idleId, field, val) => { 209 const nextList = idleActionsList.map((item) => { 210 if (item.id === idleId) { 211 return { 212 ...item, 213 idleSchedule: { 214 ...item.idleSchedule || { minIntervalMs: 1e4, maxIntervalMs: 3e4, durationMs: 2e3, blendInMs: 400, blendOutMs: 400 }, 215 [field]: val 216 } 217 }; 218 } 219 return item; 220 }); 221 onChangeActionsConfig({ 222 ...actionsConfig, 223 idleActions: nextList 224 }); 225 }; 226 const handleTestIdleAction = (idleId) => { 227 setActiveTestingIdleId(idleId); 228 setIsNoteActive(false); 229 setNotePulsing(false); 230 setTimeout(() => { 231 setActiveTestingIdleId(null); 232 }, 3500); 233 }; 234 const handleResetAllIdleDefaults = () => { 235 onChangeActionsConfig({ 236 ...actionsConfig, 237 idleActions: DEFAULT_IDLE_ACTIONS 238 }); 239 }; 240 const activeAnimalDef = BASE_ANIMALS[previewAnimal] || BASE_ANIMALS.fox; 241 const charConfig = charactersConfig[previewAnimal]; 242 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [ 243 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5 shadow-xl flex flex-col md:flex-row md:items-center justify-between gap-4", children: [
244 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [ 245 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-2.5 rounded-xl bg-indigo-500/10 text-indigo-400 border border-indigo-500/20", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SlidersVertical, { size: 22 }) }), 246 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 247 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [ 248 /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold text-white tracking-wide", children: "Actions & Kinematics Studio" }), 249 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "px-2.5 py-0.5 rounded-full text-xs font-semibold bg-emerald-500/20 text-emerald-300 border border-emerald-500/30", children: "Data-Driven Engine" }) 250 ] }), 251 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400 mt-1", children: "Customize unique limb movements, note-pitch responsiveness, mouth blowing, and orchestra idle behaviors." }) 252 ] }) 253 ] }) }),
254 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [ 255 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center bg-zinc-950 p-1 rounded-xl border border-zinc-800", children: [ 256 /* @__PURE__ */ jsxRuntimeExports.jsxs( 257 "button", 258 { 259 onClick: () => setStudioMode("playing"), 260 className: `flex items-center gap-2 px-4 py-2 rounded-lg text-xs font-semibold transition-all ${studioMode === "playing" ? "bg-indigo-600 text-white shadow-lg" : "text-zinc-400 hover:text-white"}`, 261 children: [ 262 /* @__PURE__ */ jsxRuntimeExports.jsx(Music, { size: 14 }), 263 "Instrument Playing Actions" 264 ] 265 } 266 ), 267 /* @__PURE__ */ jsxRuntimeExports.jsxs( 268 "button", 269 { 270 onClick: () => setStudioMode("idle"), 271 className: `flex items-center gap-2 px-4 py-2 rounded-lg text-xs font-semibold transition-all ${studioMode === "idle" ? "bg-indigo-600 text-white shadow-lg" : "text-zinc-400 hover:text-white"}`, 272 children: [
273 /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { size: 14 }), 274 "Idle & Spare Actions" 275 ] 276 } 277 ) 278 ] }), 279 onSave && /* @__PURE__ */ jsxRuntimeExports.jsxs( 280 "button", 281 { 282 onClick: onSave, 283 disabled: isSaving, 284 className: "flex items-center gap-2 px-4 py-2 bg-emerald-600 hover:bg-emerald-500 disabled:opacity-50 text-white font-semibold rounded-xl text-xs shadow-lg transition-all", 285 children: [ 286 isSaving ? /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { size: 14, className: "animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Save, { size: 14 }), 287 "Save All Actions" 288 ] 289 } 290 ) 291 ] }) 292 ] }), 293 studioMode === "playing" ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 xl:grid-cols-12 gap-6", children: [ 294 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "xl:col-span-7 space-y-6", children: [
295 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5 shadow-lg space-y-4", children: [ 296 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [ 297 /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "text-sm font-bold text-white uppercase tracking-wider flex items-center gap-2", children: [ 298 /* @__PURE__ */ jsxRuntimeExports.jsx(Music, { size: 16, className: "text-indigo-400" }), 299 "Select Instrument to Configure" 300 ] }), 301 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx( 302 "button", 303 { 304 onClick: () => setEditScope(editScope === "holdStyle" ? "program" : "holdStyle"), 305 className: `text-xs px-3 py-1 rounded-lg border font-medium transition-all ${editScope === "program" ? "bg-amber-500/20 text-amber-300 border-amber-500/40" : "bg-zinc-800 text-zinc-400 border-zinc-700 hover:text-white"}`, 306 children: editScope === "program" ? "â¡ Program Override Active" : "Hold Style Default" 307 } 308 ) }) 309 ] }),
310 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row gap-3", children: [ 311 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex-1", children: [ 312 /* @__PURE__ */ jsxRuntimeExports.jsx(Search, { className: "absolute left-3 top-2.5 text-zinc-500", size: 16 }), 313 /* @__PURE__ */ jsxRuntimeExports.jsx( 314 "input", 315 { 316 type: "text", 317 placeholder: "Search GM instrument name or number...", 318 value: searchQuery, 319 onChange: (e) => setSearchQuery(e.target.value), 320 className: "w-full pl-9 pr-3 py-2 bg-zinc-950 border border-zinc-800 rounded-xl text-xs text-white placeholder-zinc-500 outline-none focus:border-indigo-500" 321 } 322 ) 323 ] }), 324 /* @__PURE__ */ jsxRuntimeExports.jsxs( 325 "select", 326 { 327 value: selectedCategory, 328 onChange: (e) => setSelectedCategory(e.target.value), 329 className: "bg-zinc-950 border border-zinc-800 rounded-xl px-3 py-2 text-xs text-zinc-300 outline-none focus:border-indigo-500", 330 children: [
331 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "all", children: "All Categories" }), 332 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "piano", children: "Piano & Keys" }), 333 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "guitar", children: "Guitars" }), 334 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "bass", children: "Basses" }), 335 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "strings", children: "Strings / Orchestral" }), 336 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "brass", children: "Brass" }), 337 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "reed", children: "Woodwinds / Reeds" }), 338 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "pipe", children: "Flutes / Pipes" }), 339 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "synth", children: "Synths & FX" }), 340 /* @__P
340URE__ */ jsxRuntimeExports.jsx("option", { value: "ethnic", children: "Ethnic & World" }), 341 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "percussion", children: "Percussion Kits" }) 342 ] 343 } 344 ) 345 ] }), 346 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-2 overflow-x-auto pb-2 scrollbar-thin scrollbar-thumb-zinc-800", children: filteredInstruments.slice(0, 30).map((inst) => { 347 var _a; 348 const isSelected = inst.id === selectedProgram; 349 const hasCustomProgram = !!((_a = actionsConfig.programActions) == null ? void 0 : _a[inst.id]); 350 return /* @__PURE__ */ jsxRuntimeExports.jsxs( 351 "button", 352 { 353 onClick: () => setSelectedProgram(inst.id), 354 className: `shrink-0 px-3 py-2 rounded-xl text-left border transition-all ${isSelected ? "bg-indigo-600/30 text-white border-indigo-500 shadow-md" : "bg-zinc-950/70 text-zinc-400 border-zinc-800 hover:border-zinc-700 hover:text-zinc-200"}`, 355 children: [
356 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5", children: [ 357 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[11px] font-mono font-bold text-zinc-400", children: inst.id }), 358 hasCustomProgram && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-amber-400 animate-pulse", title: "Custom Override" }) 359 ] }), 360 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs font-semibold truncate max-w-[140px] mt-0.5", children: inst.name.split(":")[1] || inst.name }) 361 ] 362 }, 363 inst.id 364 ); 365 }) }), 366 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-950 border border-zinc-800/80 rounded-xl p-3 flex items-center justify-between", children: [ 367 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
368 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-10 h-10 rounded-lg bg-zinc-900 border border-zinc-800 flex items-center justify-center text-lg font-bold text-indigo-400", children: selectedProgram < 0 ? "ð¥" : selectedProgram }), 369 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 370 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-sm font-bold text-white flex items-center gap-2", children: [ 371 selectedInstDef.name, 372 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-2 py-0.5 rounded-md text-[10px] font-semibold bg-indigo-500/20 text-indigo-300 border border-indigo-500/30", children: [ 373 "Hold: ", 374 holdStyle 375 ] }) 376 ] }), 377 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-[11px] text-zinc-400", children: [ 378 "Editing Scope: ", 379 /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "text-zinc-200", children: editScope === "program" ? `Specific to Program ${selectedProgram}` : `All '${holdStyle}' Instruments` }) 380 ] }) 381 ] }) 382 ] }),
383 /* @__PURE__ */ jsxRuntimeExports.jsxs( 384 "button", 385 { 386 onClick: handleResetActionToDefault, 387 className: "flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs text-zinc-400 hover:text-white bg-zinc-900 hover:bg-zinc-800 border border-zinc-800 transition-all", 388 title: "Reset this action to factory built-in defaults", 389 children: [ 390 /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 12 }), 391 "Reset to Defaults" 392 ] 393 } 394 ) 395 ] }) 396 ] }), 397 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-4", children: currentActions.map((action, actionIdx) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5 shadow-lg space-y-4", children: [ 398 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-zinc-800 pb-3", children: [
399 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 400 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [ 401 /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { size: 16, className: "text-amber-400" }), 402 /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-bold text-white tracking-wide", children: action.name }), 403 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-[10px] font-mono px-2 py-0.5 rounded bg-zinc-800 text-zinc-400", children: [ 404 action.channels.length, 405 " channels" 406 ] }) 407 ] }), 408 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400 mt-0.5", children: "Active when instrument plays notes (velocity > 0)" }) 409 ] }), 410 /* @__PURE__ */ jsxRuntimeExports.jsxs( 411 "button", 412 { 413 onClick: () => handleAddChannel(actionIdx), 414 className: "flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-indigo-500/20 text-indigo-300 hover:bg-indigo-500/30 border border-indigo-500/40 text-xs font-semibold transition-all", 415 children: [
416 /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { size: 14 }), 417 "Add Movement Channel" 418 ] 419 } 420 ) 421 ] }), 422 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-3", children: action.channels.map((channel, chIdx) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-950 border border-zinc-800 rounded-xl p-4 space-y-3", children: [ 423 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 border-b border-zinc-900 pb-2.5", children: [ 424 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [ 425 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "w-5 h-5 rounded-full bg-zinc-800 text-zinc-400 text-[11px] font-bold flex items-center justify-center", children: chIdx + 1 }), 426 /* @__PURE__ */ jsxRuntimeExports.jsx( 427 "select", 428 { 429 value: channel.target, 430 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 431 ...channel, 432 target: e.target.value 433 }), 434 className: "bg-zinc-900 border border-zinc-700 text-xs font-bold text-white px-2.5 py-1 rounded-lg outline-none", 435 children: TARGET_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntimeExports.jsxs("option", { value: opt.id, className: "bg-zinc-900 text-white", children: [ 436 opt.group, 437 ": ", 438 opt.label 439 ] }, opt.id)) 440 } 441 ),
442 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-600 text-xs", children: "â" }), 443 /* @__PURE__ */ jsxRuntimeExports.jsxs( 444 "select", 445 { 446 value: channel.driver, 447 onChange: (e) => { 448 const newDriver = e.target.value; 449 let updated = { ...channel, driver: newDriver }; 450 if (newDriver === "wave" && !updated.wave) { 451 updated.wave = { waveform: "sine", frequency: 2, amplitude: 5, axis: "y", activeOnly: true }; 452 } else if (newDriver === "density_pulse" && !updated.densityPulse) { 453 updated.densityPulse = { waveform: "sine", baseFrequency: 2, densityFactor: 0.15, amplitude: 6, axis: "y" }; 454 } else if (newDriver === "velocity_envelope" && !updated.velocityEnvelope) { 455 updated.velocityEnvelope = { factor: 3, axis: "y" }; 456 } else if (newDriver === "articulation_switch" && !updated.articulationSwitch) { 457 updated.articulationSwitch = { staccatoValue: -4, legatoValue: 3, sustainedValue: 0, axis: "y" }; 458 } else if (newDriver === "phrase_accent" && !updated.phraseAccent) { 459 updated.phraseAccent = { impulse: 5, axis: "y" }; 460 } else if (newDriver === "polyphony_spread" && !updated.polyphonySpread) { 461 updated.polyphonySpread = { spreadPerNote: 2, maxSpread: 8, axis: "x" }; 462 } else if (newDriver === "climax_boost" && !updated.climaxBoost) { 463 updated.climaxBoost = { multiplier: 1.5, axis: "y" }; 464 } else if (newDriver === "pitch_map" && !updated.pitchMap) { 465 updated.pitchMap = { midiLow: 36, midiHigh: 84, outputLow: -6, outputHigh: 6, axis: "y" }; 466 } else if (newDriver === "velocity_scale" && !updated.velocityScale) { 467 updated.velocityScale = { factor: 3, axis: "y", activeOnly: true }; 468 } 469 handleUpdateChannel(actionIdx, chIdx, updated); 470 }, 471 className: "bg-zinc-900 border border-zinc-700 text-xs font-bold text-amber-300 px-2.5 py-1 rounded-lg outline-none", 472 children: [
473 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "wave", children: "Wave (Oscillation / Stroke)" }), 474 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "density_pulse", children: "Density Pulse (Music Speed)" }), 475 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "velocity_envelope", children: "Velocity Envelope (Smooth Dynamics)" }), 476 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "articulation_switch", children: "Articulation Switch (Legato/Staccato)" }), 477 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "phrase_accent", children: "Phrase Accent (Attack Impulse)" }), 478 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "polyphony_spread", children: "Polyphony Spread (Chord Width)" }), 479 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "climax_boost", children: "Climax Boost (Tutti Surge)" }), 480 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "pitch_map", children: "Pitch Map (Fret / Slide / Keys)" }),
481 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "velocity_scale", children: "Velocity Scale (Impact)" }), 482 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "constant", children: "Constant Offset" }) 483 ] 484 } 485 ) 486 ] }), 487 /* @__PURE__ */ jsxRuntimeExports.jsx( 488 "button", 489 { 490 onClick: () => handleRemoveChannel(actionIdx, chIdx), 491 className: "text-zinc-500 hover:text-red-400 p-1 transition-colors", 492 title: "Delete Channel", 493 children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { size: 14 }) 494 } 495 ) 496 ] }), 497 channel.driver === "wave" && channel.wave && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-3 text-xs", children: [ 498 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
499 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Waveform:" }), 500 /* @__PURE__ */ jsxRuntimeExports.jsxs( 501 "select", 502 { 503 value: channel.wave.waveform, 504 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 505 ...channel, 506 wave: { ...channel.wave, waveform: e.target.value } 507 }), 508 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none", 509 children: [ 510 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "sine", children: "Sine (Smooth)" }), 511 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "abs_sine", children: "Abs Sine (Bounce)" }), 512 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "triangle", children: "Triangle (Linear)" }), 513 /* @__P
513URE__ */ jsxRuntimeExports.jsx("option", { value: "sawtooth", children: "Sawtooth (Ramp)" }) 514 ] 515 } 516 ) 517 ] }), 518 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 519 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-500 mb-1", children: [ 520 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Beat Rate:" }), 521 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono", children: [ 522 channel.wave.frequency, 523 "x" 524 ] }) 525 ] }), 526 /* @__PURE__ */ jsxRuntimeExports.jsx( 527 "input", 528 { 529 type: "range", 530 min: "0.5", 531 max: "8.0", 532 step: "0.5", 533 value: channel.wave.frequency, 534 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 535 ...channel, 536 wave: { ...channel.wave, frequency: parseFloat(e.target.value) } 537 }), 538 className: "w-full accent-indigo-500 cursor-pointer" 539 } 540 ) 541 ] }),
542 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 543 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-500 mb-1", children: [ 544 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Amplitude:" }), 545 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono", children: [ 546 channel.wave.amplitude, 547 "px" 548 ] }) 549 ] }), 550 /* @__PURE__ */ jsxRuntimeExports.jsx( 551 "input", 552 { 553 type: "range", 554 min: "0", 555 max: "30", 556 step: "1", 557 value: channel.wave.amplitude, 558 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 559 ...channel, 560 wave: { ...channel.wave, amplitude: parseFloat(e.target.value) } 561 }), 562 className: "w-full accent-indigo-500 cursor-pointer" 563 } 564 ) 565 ] }),
566 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 567 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }), 568 /* @__PURE__ */ jsxRuntimeExports.jsxs( 569 "select", 570 { 571 value: channel.wave.axis || "y", 572 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 573 ...channel, 574 wave: { ...channel.wave, axis: e.target.value } 575 }), 576 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none", 577 children: [ 578 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }), 579 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" }), 580 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "both", children: "Elliptical (Both X & Y)" }) 581 ] 582 } 583 ) 584 ] }) 585 ] }), 586 channel.driver === "pitch_map" && channel.pitchMap && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-3 text-xs", children: [
587 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 588 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "MIDI Low (Pitch):" }), 589 /* @__PURE__ */ jsxRuntimeExports.jsx( 590 "input", 591 { 592 type: "number", 593 value: channel.pitchMap.midiLow, 594 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 595 ...channel, 596 pitchMap: { ...channel.pitchMap, midiLow: parseInt(e.target.value) } 597 }), 598 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono" 599 } 600 ) 601 ] }), 602 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 603 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "MIDI High (Pitch):" }), 604 /* @__P
604URE__ */ jsxRuntimeExports.jsx( 605 "input", 606 { 607 type: "number", 608 value: channel.pitchMap.midiHigh, 609 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 610 ...channel, 611 pitchMap: { ...channel.pitchMap, midiHigh: parseInt(e.target.value) } 612 }), 613 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono" 614 } 615 ) 616 ] }), 617 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 618 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Output Low (px/deg):" }), 619 /* @__PURE__ */ jsxRuntimeExports.jsx( 620 "input", 621 { 622 type: "number", 623 value: channel.pitchMap.outputLow, 624 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 625 ...channel, 626 pitchMap: { ...channel.pitchMap, outputLow: parseFloat(e.target.value) } 627 }), 628 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono" 629 } 630 ) 631 ] }),
632 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 633 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Output High (px/deg):" }), 634 /* @__PURE__ */ jsxRuntimeExports.jsx( 635 "input", 636 { 637 type: "number", 638 value: channel.pitchMap.outputHigh, 639 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 640 ...channel, 641 pitchMap: { ...channel.pitchMap, outputHigh: parseFloat(e.target.value) } 642 }), 643 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono" 644 } 645 ) 646 ] }) 647 ] }), 648 channel.driver === "velocity_scale" && channel.velocityScale && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-4 text-xs", children: [ 649 /* @__P
649URE__ */ jsxRuntimeExports.jsxs("div", { children: [ 650 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-500 mb-1", children: [ 651 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Velocity Impact Factor:" }), 652 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-white font-mono", children: channel.velocityScale.factor }) 653 ] }), 654 /* @__PURE__ */ jsxRuntimeExports.jsx( 655 "input", 656 { 657 type: "range", 658 min: "-15", 659 max: "15", 660 step: "0.5", 661 value: channel.velocityScale.factor, 662 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 663 ...channel, 664 velocityScale: { ...channel.velocityScale, factor: parseFloat(e.target.value) } 665 }), 666 className: "w-full accent-indigo-500 cursor-pointer" 667 } 668 ) 669 ] }),
670 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 671 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }), 672 /* @__PURE__ */ jsxRuntimeExports.jsxs( 673 "select", 674 { 675 value: channel.velocityScale.axis || "y", 676 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 677 ...channel, 678 velocityScale: { ...channel.velocityScale, axis: e.target.value } 679 }), 680 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none", 681 children: [ 682 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }), 683 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" }) 684 ] 685 } 686 ) 687 ] }) 688 ] }), 689 channel.driver === "constant" && channel.constant && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-2 gap-4 text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
690 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Offset Value:" }), 691 /* @__PURE__ */ jsxRuntimeExports.jsx( 692 "input", 693 { 694 type: "number", 695 value: channel.constant.value, 696 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 697 ...channel, 698 constant: { ...channel.constant, value: parseFloat(e.target.value) } 699 }), 700 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono" 701 } 702 ) 703 ] }) }), 704 channel.driver === "density_pulse" && channel.densityPulse && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-3 text-xs", children: [ 705 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 706 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Base Rate:" }),
707 /* @__PURE__ */ jsxRuntimeExports.jsx( 708 "input", 709 { 710 type: "number", 711 step: "0.5", 712 value: channel.densityPulse.baseFrequency ?? 1, 713 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 714 ...channel, 715 densityPulse: { ...channel.densityPulse, baseFrequency: parseFloat(e.target.value) } 716 }), 717 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono" 718 } 719 ) 720 ] }), 721 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 722 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Density Scaling Factor:" }), 723 /* @__PURE__ */ jsxRuntimeExports.jsx( 724 "input", 725 { 726 type: "number", 727 step: "0.05", 728 value: channel.densityPulse.densityFactor ?? 0.15, 729 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 730 ...channel, 731 densityPulse: { ...channel.densityPulse, densityFactor: parseFloat(e.target.value) } 732 }), 733 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono" 734 } 735 ) 736 ] }),
737 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 738 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Amplitude:" }), 739 /* @__PURE__ */ jsxRuntimeExports.jsx( 740 "input", 741 { 742 type: "number", 743 value: channel.densityPulse.amplitude, 744 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 745 ...channel, 746 densityPulse: { ...channel.densityPulse, amplitude: parseFloat(e.target.value) } 747 }), 748 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono" 749 } 750 ) 751 ] }), 752 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 753 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }), 754 /* @__P
754URE__ */ jsxRuntimeExports.jsxs( 755 "select", 756 { 757 value: channel.densityPulse.axis || "y", 758 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 759 ...channel, 760 densityPulse: { ...channel.densityPulse, axis: e.target.value } 761 }), 762 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none", 763 children: [ 764 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }), 765 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" }), 766 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "both", children: "Both (X & Y)" }) 767 ] 768 } 769 ) 770 ] }) 771 ] }), 772 channel.driver === "velocity_envelope" && channel.velocityEnvelope && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-4 text-xs", children: [
773 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 774 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Envelope Scale Factor:" }), 775 /* @__PURE__ */ jsxRuntimeExports.jsx( 776 "input", 777 { 778 type: "number", 779 step: "0.5", 780 value: channel.velocityEnvelope.factor, 781 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 782 ...channel, 783 velocityEnvelope: { ...channel.velocityEnvelope, factor: parseFloat(e.target.value) } 784 }), 785 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono" 786 } 787 ) 788 ] }), 789 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 790 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }),
791 /* @__PURE__ */ jsxRuntimeExports.jsxs( 792 "select", 793 { 794 value: channel.velocityEnvelope.axis || "y", 795 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 796 ...channel, 797 velocityEnvelope: { ...channel.velocityEnvelope, axis: e.target.value } 798 }), 799 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none", 800 children: [ 801 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }), 802 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" }) 803 ] 804 } 805 ) 806 ] }) 807 ] }), 808 channel.driver === "articulation_switch" && channel.articulationSwitch && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-3 text-xs", children: [
809 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 810 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Legato Value:" }), 811 /* @__PURE__ */ jsxRuntimeExports.jsx( 812 "input", 813 { 814 type: "number", 815 value: channel.articulationSwitch.legatoValue ?? 0, 816 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 817 ...channel, 818 articulationSwitch: { ...channel.articulationSwitch, legatoValue: parseFloat(e.target.value) } 819 }), 820 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono" 821 } 822 ) 823 ] }), 824 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 825 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Staccato Value:" }),
826 /* @__PURE__ */ jsxRuntimeExports.jsx( 827 "input", 828 { 829 type: "number", 830 value: channel.articulationSwitch.staccatoValue ?? 0, 831 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 832 ...channel, 833 articulationSwitch: { ...channel.articulationSwitch, staccatoValue: parseFloat(e.target.value) } 834 }), 835 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono" 836 } 837 ) 838 ] }), 839 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 840 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Tremolo Value:" }), 841 /* @__PURE__ */ jsxRuntimeExports.jsx( 842 "input", 843 { 844 type: "number", 845 value: channel.articulationSwitch.tremoloValue ?? 0, 846 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 847 ...channel, 848 articulationSwitch: { ...channel.articulationSwitch, tremoloValue: parseFloat(e.target.value) } 849 }), 850 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono" 851 } 852 ) 853 ] }),
854 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 855 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }), 856 /* @__PURE__ */ jsxRuntimeExports.jsxs( 857 "select", 858 { 859 value: channel.articulationSwitch.axis || "y", 860 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 861 ...channel, 862 articulationSwitch: { ...channel.articulationSwitch, axis: e.target.value } 863 }), 864 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none", 865 children: [ 866 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }), 867 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" }) 868 ] 869 } 870 ) 871 ] }) 872 ] }), 873 channel.driver === "phrase_accent" && channel.phraseAccent && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-4 text-xs", children: [
874 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 875 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Attack Impulse:" }), 876 /* @__PURE__ */ jsxRuntimeExports.jsx( 877 "input", 878 { 879 type: "number", 880 value: channel.phraseAccent.impulse, 881 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 882 ...channel, 883 phraseAccent: { ...channel.phraseAccent, impulse: parseFloat(e.target.value) } 884 }), 885 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono" 886 } 887 ) 888 ] }), 889 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 890 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }), 891 /* @__P
891URE__ */ jsxRuntimeExports.jsxs( 892 "select", 893 { 894 value: channel.phraseAccent.axis || "y", 895 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 896 ...channel, 897 phraseAccent: { ...channel.phraseAccent, axis: e.target.value } 898 }), 899 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none", 900 children: [ 901 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }), 902 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" }) 903 ] 904 } 905 ) 906 ] }) 907 ] }), 908 channel.driver === "polyphony_spread" && channel.polyphonySpread && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 sm:grid-cols-3 gap-3 text-xs", children: [
909 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 910 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Spread Per Note:" }), 911 /* @__PURE__ */ jsxRuntimeExports.jsx( 912 "input", 913 { 914 type: "number", 915 step: "0.5", 916 value: channel.polyphonySpread.spreadPerNote, 917 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 918 ...channel, 919 polyphonySpread: { ...channel.polyphonySpread, spreadPerNote: parseFloat(e.target.value) } 920 }), 921 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono" 922 } 923 ) 924 ] }), 925 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 926 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Max Spread:" }),
927 /* @__PURE__ */ jsxRuntimeExports.jsx( 928 "input", 929 { 930 type: "number", 931 value: channel.polyphonySpread.maxSpread ?? 10, 932 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 933 ...channel, 934 polyphonySpread: { ...channel.polyphonySpread, maxSpread: parseFloat(e.target.value) } 935 }), 936 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 font-mono" 937 } 938 ) 939 ] }), 940 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 941 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Axis:" }), 942 /* @__PURE__ */ jsxRuntimeExports.jsxs( 943 "select", 944 { 945 value: channel.polyphonySpread.axis || "x", 946 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 947 ...channel, 948 polyphonySpread: { ...channel.polyphonySpread, axis: e.target.value } 949 }), 950 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2 py-1 text-zinc-200 outline-none", 951 children: [
952 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "x", children: "Horizontal (X)" }), 953 /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: "y", children: "Vertical (Y)" }) 954 ] 955 } 956 ) 957 ] }) 958 ] }), 959 channel.driver === "climax_boost" && channel.climaxBoost && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-2 gap-4 text-xs", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 960 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-1", children: "Climax Multiplier:" }), 961 /* @__PURE__ */ jsxRuntimeExports.jsx( 962 "input", 963 { 964 type: "number", 965 step: "0.1", 966 value: channel.climaxBoost.multiplier, 967 onChange: (e) => handleUpdateChannel(actionIdx, chIdx, { 968 ...channel, 969 climaxBoost: { ...channel.climaxBoost, multiplier: parseFloat(e.target.value) } 970 }), 971 className: "w-full bg-zinc-900 border border-zinc-800 rounded-lg px-2.5 py-1 text-zinc-200 font-mono" 972 } 973 ) 974 ] }) }) 975 ] }, chIdx)) }) 976 ] }, action.id || actionIdx)) }) 977 ] }),
978 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "xl:col-span-5 space-y-6", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5 shadow-xl sticky top-6 space-y-5", children: [ 979 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-zinc-800 pb-3", children: [ 980 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [ 981 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-2.5 h-2.5 rounded-full bg-emerald-400 animate-ping" }), 982 /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-bold text-white uppercase tracking-wider", children: "Live Action Simulator" }) 983 ] }), 984 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs( 985 "button", 986 { 987 onClick: () => setIsSimulating(!isSimulating), 988 className: `px-3 py-1 rounded-lg text-xs font-semibold flex items-center gap-1.5 transition-all ${isSimulating ? "bg-emerald-500/20 text-emerald-300 border border-emerald-500/30" : "bg-zinc-800 text-zinc-400 border border-zinc-700"}`, 989 children: [
990 isSimulating ? /* @__PURE__ */ jsxRuntimeExports.jsx(Pause, { size: 12 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Play, { size: 12 }), 991 isSimulating ? "Playing" : "Paused" 992 ] 993 } 994 ) }) 995 ] }), 996 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full h-80 bg-zinc-950 border border-zinc-800 rounded-2xl relative overflow-hidden flex items-center justify-center", children: [ 997 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-x-0 bottom-0 h-28 bg-gradient-to-t from-black/80 to-transparent pointer-events-none" }), 998 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute w-40 h-8 rounded-full bg-black/60 blur-md bottom-12" }), 999 /* @__PURE__ */ jsxRuntimeExports.jsx( 1000 "svg", 1001 { 1002 viewBox: "-100 -120 200 240", 1003 className: "w-full h-full relative z-10", 1004 preserveAspectRatio: "xMidYMid meet", 1005 children: /* @__PURE__ */ jsxRuntimeExports.jsx( 1006 SouthparkCharacter, 1007 { 1008 animal: activeAnimalDef, 1009 instrument: selectedInstDef, 1010 isActive: isNoteActive, 1011 velocity: isNoteActive ? simVelocity : 0, 1012 activePitch: simPitch, 1013 currentTime: simTime, 1014 bpm: simBpm, 1015 isPlaying: isSimulating, 1016 physicsMode: "snappy", 1017 showInstrument: true, 1018 showSkeleton, 1019 skeletonOnly, 1020 customConfig: charConfig, 1021 actionsConfig 1022 } 1023 ) 1024 } 1025 ),
1026 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "absolute top-3 left-3 px-2.5 py-1 rounded-lg text-[10px] font-bold border flex items-center gap-1.5 bg-zinc-900/90 backdrop-blur-sm", children: [ 1027 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: `w-2 h-2 rounded-full ${isNoteActive ? "bg-emerald-400" : "bg-zinc-600"}` }), 1028 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: isNoteActive ? "text-emerald-300" : "text-zinc-500", children: isNoteActive ? `NOTE ON (Vel ${simVelocity})` : "IDLE GAP" }) 1029 ] }), 1030 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-3 right-3", children: /* @__PURE__ */ jsxRuntimeExports.jsx( 1031 "select", 1032 { 1033 value: previewAnimal, 1034 onChange: (e) => setPreviewAnimal(e.target.value), 1035 className: "bg-zinc-900/90 border border-zinc-700 text-[11px] font-bold text-white px-2.5 py-1 rounded-lg outline-none backdrop-blur-sm", 1036 children: Object.keys(BASE_ANIMALS).map((aId) => /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: aId, className: "bg-zinc-900 text-white", children: BASE_ANIMALS[aId].name }, aId)) 1037 } 1038 ) }) 1039 ] }),
1040 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4 bg-zinc-950 p-4 rounded-xl border border-zinc-800 text-xs", children: [ 1041 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between", children: [ 1042 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-semibold text-zinc-300", children: "Rhythmic Downbeat Pulse:" }), 1043 /* @__PURE__ */ jsxRuntimeExports.jsx( 1044 "button", 1045 { 1046 onClick: () => setNotePulsing(!notePulsing), 1047 className: `px-2.5 py-0.5 rounded text-[11px] font-bold border transition-all ${notePulsing ? "bg-emerald-500/20 text-emerald-300 border-emerald-500/40" : "bg-zinc-800 text-zinc-400 border-zinc-700"}`, 1048 children: notePulsing ? "Auto Tempo Pulsing" : "Manual Trigger" 1049 } 1050 ) 1051 ] }), 1052 !notePulsing && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx( 1053 "button", 1054 { 1055 onMouseDown: () => setIsNoteActive(true), 1056 onMouseUp: () => setIsNoteActive(false), 1057 onTouchStart: () => setIsNoteActive(true), 1058 onTouchEnd: () => setIsNoteActive(false), 1059 className: "flex-1 py-2 rounded-xl bg-indigo-600 hover:bg-indigo-500 active:scale-95 text-white font-bold text-xs shadow-md transition-all text-center", 1060 children: "Hold to Strike Note ðµ" 1061 } 1062 ) }),
1063 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 1064 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-400 mb-1", children: [ 1065 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "MIDI Pitch (Slides / Fret / Keys):" }), 1066 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono font-bold", children: [ 1067 simPitch, 1068 " (C", 1069 Math.floor(simPitch / 12) - 1, 1070 ")" 1071 ] }) 1072 ] }), 1073 /* @__PURE__ */ jsxRuntimeExports.jsx( 1074 "input", 1075 { 1076 type: "range", 1077 min: "21", 1078 max: "108", 1079 value: simPitch, 1080 onChange: (e) => setSimPitch(parseInt(e.target.value)), 1081 className: "w-full accent-amber-500 cursor-pointer" 1082 } 1083 ) 1084 ] }), 1085 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
1086 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-400 mb-1", children: [ 1087 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Velocity (Impact Energy):" }), 1088 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono font-bold", children: [ 1089 simVelocity, 1090 " / 127" 1091 ] }) 1092 ] }), 1093 /* @__PURE__ */ jsxRuntimeExports.jsx( 1094 "input", 1095 { 1096 type: "range", 1097 min: "20", 1098 max: "127", 1099 value: simVelocity, 1100 onChange: (e) => setSimVelocity(parseInt(e.target.value)), 1101 className: "w-full accent-emerald-500 cursor-pointer" 1102 } 1103 ) 1104 ] }), 1105 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 1106 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-400 mb-1", children: [
1107 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "BPM (Tempo Speed):" }), 1108 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono font-bold", children: [ 1109 simBpm, 1110 " BPM" 1111 ] }) 1112 ] }), 1113 /* @__PURE__ */ jsxRuntimeExports.jsx( 1114 "input", 1115 { 1116 type: "range", 1117 min: "60", 1118 max: "200", 1119 value: simBpm, 1120 onChange: (e) => setSimBpm(parseInt(e.target.value)), 1121 className: "w-full accent-indigo-500 cursor-pointer" 1122 } 1123 ) 1124 ] }), 1125 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between pt-2 border-t border-zinc-900", children: [ 1126 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-400 font-medium", children: "Kinematic Wireframe:" }), 1127 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
1128 /* @__PURE__ */ jsxRuntimeExports.jsx( 1129 "button", 1130 { 1131 onClick: () => setShowSkeleton(!showSkeleton), 1132 className: `px-2 py-1 rounded text-[11px] font-semibold border ${showSkeleton ? "bg-indigo-500/20 text-indigo-300 border-indigo-500/40" : "bg-zinc-900 text-zinc-500 border-zinc-800"}`, 1133 children: "Joint Overlay" 1134 } 1135 ), 1136 /* @__PURE__ */ jsxRuntimeExports.jsx( 1137 "button", 1138 { 1139 onClick: () => setSkeletonOnly(!skeletonOnly), 1140 className: `px-2 py-1 rounded text-[11px] font-semibold border ${skeletonOnly ? "bg-amber-500/20 text-amber-300 border-amber-500/40" : "bg-zinc-900 text-zinc-500 border-zinc-800"}`, 1141 children: "Skeleton Only" 1142 } 1143 ) 1144 ] }) 1145 ] }) 1146 ] }) 1147 ] }) }) 1148 ] }) : ( 1149 /* IDLE & SPARE ACTIONS STUDIO */ 1150 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [
1151 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-900 border border-zinc-800 rounded-2xl p-5 shadow-lg flex flex-col md:flex-row md:items-center justify-between gap-4", children: [ 1152 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 1153 /* @__PURE__ */ jsxRuntimeExports.jsxs("h3", { className: "text-base font-bold text-white flex items-center gap-2", children: [ 1154 /* @__PURE__ */ jsxRuntimeExports.jsx(Clock, { size: 18, className: "text-amber-400" }), 1155 "Orchestra Idle & Spare Actions Library" 1156 ] }), 1157 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-400 mt-1", children: "Characters randomly execute these natural micro-behaviors during rests and silent passages, bringing the stage to life." }) 1158 ] }), 1159 /* @__PURE__ */ jsxRuntimeExports.jsxs( 1160 "button", 1161 { 1162 onClick: handleResetAllIdleDefaults, 1163 className: "flex items-center gap-1.5 px-3 py-1.5 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 text-xs font-semibold rounded-lg border border-zinc-700 transition-all", 1164 children: [
1165 /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 14 }), 1166 "Reset All Idle Defaults" 1167 ] 1168 } 1169 ) 1170 ] }), 1171 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6", children: idleActionsList.map((idle) => { 1172 const isTesting = activeTestingIdleId === idle.id; 1173 const sched = idle.idleSchedule || { 1174 minIntervalMs: 1e4, 1175 maxIntervalMs: 3e4, 1176 durationMs: 2e3, 1177 blendInMs: 400, 1178 blendOutMs: 400 1179 }; 1180 return /* @__PURE__ */ jsxRuntimeExports.jsxs( 1181 "div", 1182 { 1183 className: `bg-zinc-900 border rounded-2xl p-5 shadow-lg space-y-4 transition-all ${isTesting ? "border-amber-500/60 shadow-amber-500/10" : "border-zinc-800"}`, 1184 children: [ 1185 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between border-b border-zinc-800 pb-3", children: [
1186 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 1187 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [ 1188 /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-bold text-white", children: idle.name }), 1189 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] font-mono px-2 py-0.5 rounded bg-zinc-800 text-zinc-400", children: idle.id }) 1190 ] }), 1191 /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-[11px] text-zinc-500 mt-0.5", children: [ 1192 "Targets: ", 1193 idle.channels.map((c) => c.target).join(", ") 1194 ] }) 1195 ] }), 1196 /* @__PURE__ */ jsxRuntimeExports.jsxs( 1197 "button", 1198 { 1199 onClick: () => handleTestIdleAction(idle.id), 1200 className: `px-3 py-1.5 rounded-xl text-xs font-bold flex items-center gap-1.5 transition-all ${isTesting ? "bg-amber-500 text-black shadow-lg animate-pulse" : "bg-indigo-600/30 text-indigo-300 hover:bg-indigo-600/50 border border-indigo-500/30"}`, 1201 children: [
1202 /* @__PURE__ */ jsxRuntimeExports.jsx(Play, { size: 12 }), 1203 isTesting ? "Testing Now..." : "Test Action" 1204 ] 1205 } 1206 ) 1207 ] }), 1208 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3 text-xs bg-zinc-950 p-3.5 rounded-xl border border-zinc-800/80", children: [ 1209 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 1210 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-400 mb-1", children: [ 1211 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Duration:" }), 1212 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono font-bold", children: [ 1213 (sched.durationMs / 1e3).toFixed(1), 1214 "s" 1215 ] }) 1216 ] }), 1217 /* @__PURE__ */ jsxRuntimeExports.jsx( 1218 "input", 1219 { 1220 type: "range", 1221 min: "500", 1222 max: "6000", 1223 step: "100", 1224 value: sched.durationMs, 1225 onChange: (e) => handleUpdateIdleSchedule(idle.id, "durationMs", parseInt(e.target.value)), 1226 className: "w-full accent-indigo-500 cursor-pointer" 1227 } 1228 ) 1229 ] }),
1230 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-3", children: [ 1231 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 1232 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-500 mb-1", children: [ 1233 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Min Interval:" }), 1234 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono", children: [ 1235 Math.round(sched.minIntervalMs / 1e3), 1236 "s" 1237 ] }) 1238 ] }), 1239 /* @__PURE__ */ jsxRuntimeExports.jsx( 1240 "input", 1241 { 1242 type: "range", 1243 min: "4000", 1244 max: "40000", 1245 step: "1000", 1246 value: sched.minIntervalMs, 1247 onChange: (e) => handleUpdateIdleSchedule(idle.id, "minIntervalMs", parseInt(e.target.value)), 1248 className: "w-full accent-indigo-500 cursor-pointer" 1249 } 1250 ) 1251 ] }),
1252 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 1253 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between text-zinc-500 mb-1", children: [ 1254 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Max Interval:" }), 1255 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-white font-mono", children: [ 1256 Math.round(sched.maxIntervalMs / 1e3), 1257 "s" 1258 ] }) 1259 ] }), 1260 /* @__PURE__ */ jsxRuntimeExports.jsx( 1261 "input", 1262 { 1263 type: "range", 1264 min: "8000", 1265 max: "90000", 1266 step: "1000", 1267 value: sched.maxIntervalMs, 1268 onChange: (e) => handleUpdateIdleSchedule(idle.id, "maxIntervalMs", parseInt(e.target.value)), 1269 className: "w-full accent-indigo-500 cursor-pointer" 1270 } 1271 ) 1272 ] }) 1273 ] }),
1274 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-3 pt-1 border-t border-zinc-900", children: [ 1275 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 1276 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-0.5", children: "Blend In:" }), 1277 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-zinc-300 font-mono text-[11px]", children: [ 1278 sched.blendInMs, 1279 "ms" 1280 ] }) 1281 ] }), 1282 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 1283 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-zinc-500 block mb-0.5", children: "Blend Out:" }), 1284 /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-zinc-300 font-mono text-[11px]", children: [ 1285 sched.blendOutMs, 1286 "ms" 1287 ] }) 1288 ] }) 1289 ] }) 1290 ] }) 1291 ] 1292 }, 1293 idle.id 1294 ); 1295 }) }) 1296 ] }) 1297 ) 1298 ] }); 1299}; 1300export { 1301 SouthparkActionsStudio, 1302 SouthparkActionsStudio as default 1303};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.